Location: PHPKode > projects > Myphpim > MyPhPim-01.05/includes/imap_cl.inc
<?php

//****************************************************************************************
//                Copyright (C) 2000 Koen de Boeve
//
//        This program is free software; you can redistribute it and/or
//        modify it under the terms of the GNU General Public License
//        as published by the Free Software Foundation; either version 2
//        of the License, or (at your option) any later version.
//
//        This program is distributed in the hope that it will be useful,
//        but WITHOUT ANY WARRANTY; without even the implied warranty of
//        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//        GNU General Public License for more details.
//
//        You should have received a copy of the GNU General Public License
//        along with this program; if not, write to the Free Software
//        Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
//        Version : MyPhPim-01.05
//        Author : Koen de Boeve
//        Contact: hide@address.com
//**************************************************************************************** 
if ( file_exists ( "conf" ) ) { $conf = "conf"; }
if ( file_exists ( "../conf" ) ) { $conf = "../conf"; }
include $conf . "/config.inc";

//######################################################################################################################################################

class ImapCl {


	//#######################################################################################

	// Open a connection to the mailbox

	Function Init ( $host, $port, $type, $user, $pass ) {
   		global $config;
   		if ( $type == "POP3" ) {  
      			$hoststr = "\{$host/pop3:$port}INBOX";
   		} else if ( $type == "IMAP" ) {
      			$hoststr = "\{$host:$port}INBOX";
   		}
   		$mbox = imap_open ( "$hoststr", "$user", "$pass" );
   		return $mbox;
	}

	//#######################################################################################
	
	// Open a connection to a specific folder in the mailbox ( only for imap servers )
	// This wont work for pop3 accounts

	Function InitFolder ( $host, $port, $type, $user, $pass, $folder ) {
        	global $config;
        	if ( $type == "POP3" ) {
                	$hoststr = "\{$host/pop3:$port}INBOX";
        	} else if ( $type == "IMAP" ) {
                	$hoststr = "\{$host:$port}INBOX.$folder";
        	}
        	$mbox = imap_open ( "$hoststr", "$user", "$pass" );
        	return $mbox;
	}
	
	//#######################################################################################

	// Close the connection to the mailserver
	
	Function close ( $mbox ) {
		imap_close ( $mbox );
	}

	//#######################################################################################

	// Fetch number of messages

	Function NumMesg ( $mbox ) {
		return imap_num_msg ( $mbox );
	} 

	//#######################################################################################

	// Fetch number of recent messages

	Function Numrecent ( $mbox ) {
		return imap_num_recent ( $mbox );
	}

	//#######################################################################################

	// Fetch the headers object of a message

	Function FetchHeader ( $mbox, $msgno ) {
		return imap_header( $mbox, $msgno );
	}

	//#######################################################################################

	// Get particular data from the header object

	Function FetchHeaderData ( $header, $key ) {
		$key = strtoupper ( $key );
		switch ( $key ) {
			case "DATE" :		$value = $header->Date;
						break;;
			case "SUBJECT" :	$value = $header->subject;
						break;;
			case "INREPLYTO" :	$value = $header->in_reply_to;
						break;;
			case "MSGID" :		$value = $header->message_id;
						break;;
			case "NEWSGRP" :	$value = $header->newsgroups;
						break;;
			case "FLWUP" :		$value = $header->followup_to;
						break;;
			case "REF" :		$value = $header->references;
						break;;
			case "FLAGS" :		$recent = $header->Recent;
						$unseen = $header->Unseen;
						$answered = $header->Answered;
						$deleted = $header->Deleted;
						$draft = $header->Draft;
						$flagged = $header->Flagged;
						if ( $recent == "N" || $recent == "R" ) {
							$value = $recent;
						} else if ( $unseen == "U" ) {
							$value = $unseen;
						} else if ( $answered == "A" ) {
							$value = $answered;
						} else if ( $deleted == "D" ) {
							$value = $deleted;
						} else if ( $draft == "X" ) {
							$value = $draft;
						} else {
							$value = $flagged;
						}
						break;;
			case "TO" :		$numto = count ( $header->to );
						for ( $i = 0; $i < $numto; $i++ ) { // we might have more then one recipient
							$tmp[$i] = $header->to[$i];
							$to = $header->to[$i];  
							while ( list ( $key, $val ) = each ( $to ) ) {
								$personal = $to->personal;
								$mailbox = $to->mailbox;
								$host = $to->host;
								$tmp = quoted_printable_decode(str_replace("=\r\n","", $personal ) );
								if ( strpos ( $tmp, "?Q?" ) ) {  // lets convert special characters
									$tmp_array = explode ( "?", $tmp ); 
									$pers_array = explode ( "_", $tmp_array[3] );
									$value[$i]->name = $pers_array[0] . " " . $pers_array[1];
								} else {
									$value[$i]->name = $tmp;
								}
								$value[$i]->address =  $mailbox . "@" . $host;
							}
						}
						break;;
			case "FROM" :		$numfrom = count ( $header->from );
						for ( $i = 0; $i < $numfrom; $i++ ) {
							$tmp[$i] = $header->from[$i];
							$from = $tmp[$i];
							while ( list ( $key, $val ) = each ( $from ) ) {
								$personal = $from->personal;
								$mailbox = $from->mailbox;
								$host = $from->host;
								$tmp = quoted_printable_decode(str_replace("=\r\n","", $personal ) );
								if ( strpos ( $tmp, "?Q?" ) ) {
									$tmp_array = explode ( "?", $tmp ); 
									$pers_array = explode ( "_", $tmp_array[3] );
									$value[$i]->name = $pers_array[0] . " " . $pers_array[1];
								} else {
									$value[$i]->name = $tmp;
								}
								$value[$i]->address =  $mailbox . "@" . $host;
							}
						}
						break;;
			case "CC" :		$numcc = count ( $header->cc );
						for ( $i = 0; $i < $numcc; $i++ ) {
							$tmp[$i] = $header->cc[$i];
							$cc = $tmp[$i];
							if ( is_array ( $cc ) || is_object ( $cc ) ) {
								while ( list ( $key, $val ) = each ( $cc ) ) {
									$personal = $cc->personal;
									$mailbox = $cc->mailbox;
									$host = $cc->host;
									$tmp = quoted_printable_decode(str_replace("=\r\n","", $personal ) );
									if ( strpos ( $tmp, "?Q?" ) ) {
										$tmp_array = explode ( "?", $tmp ); 
										$pers_array = explode ( "_", $tmp_array[3] );
										$value[$i]->name = $pers_array[0] . " " . $pers_array[1];
									} else {
										$value[$i]->name = $tmp;
									}
									$value[$i]->address =  $mailbox . "@" . $host;
								}
							} 
						}
						break;;
			case "BCC" :		$numbcc = count ( $header->bcc );
						for ( $i = 0; $i < $numbcc; $i++ ) {
							$tmp[$i] = $header->bcc[$i];
							$bcc = $tmp[$i];
							while ( list ( $key, $val ) = each ( $bcc ) ) {
								$personal = $bcc->personal;
								$mailbox = $bcc->mailbox;
								$host = $bcc->host;
								$tmp = quoted_printable_decode(str_replace("=\r\n","", $personal ) );
								if ( strpos ( $tmp, "?Q?" ) ) {
									$tmp_array = explode ( "?", $tmp ); 
									$pers_array = explode ( "_", $tmp_array[3] );
									$value[$i]->name = $pers_array[0] . " " . $pers_array[1];
								} else {
									$value[$i]->name = $tmp;
								}
								$value[$i]->address =  $mailbox . "@" . $host;
							}
						}
						break;;
			case "REPLYTO" :	$numreplyto = count ( $header->reply_to );
						for ( $i = 0; $i < $numreplyto; $i++ ) {
							$tmp[$i] = $header->reply_to[$i];
							$replyto = $tmp[$i];
							while ( list ( $key, $val ) = each ( $replyto ) ) {
								$personal = $replyto->personal;
								$mailbox = $replyto->mailbox;
								$host = $replyto->host;
								$tmp = quoted_printable_decode(str_replace("=\r\n","", $personal ) );
								if ( strpos ( $tmp, "?Q?" ) ) {
									$tmp_array = explode ( "?", $tmp ); 
									$pers_array = explode ( "_", $tmp_array[3] );
									$value[$i]->name = $pers_array[0] . " " . $pers_array[1];
								} else {
									$value[$i]->name = $tmp;
								}
								$value[$i]->address =  $mailbox . "@" . $host;
							}
						}
						break;;
			case "SENDER" :		$numsender = count ( $header->sender );
						for ( $i = 0; $i < $numsender; $i++ ) {
							$tmp[$i] = $header->sender[$i];
							$sender = $tmp[$i];
							while ( list ( $key, $val ) = each ( $sender ) ) {
								$personal = $sender->personal;
								$mailbox = $sender->mailbox;
								$host = $sender->host;
								$tmp = quoted_printable_decode(str_replace("=\r\n","", $personal ) );
								if ( strpos ( $tmp, "?Q?" ) ) {
									$tmp_array = explode ( "?", $tmp ); 
									$pers_array = explode ( "_", $tmp_array[3] );
									$value[$i]->name = $pers_array[0] . " " . $pers_array[1];
								} else {
									$value[$i]->name = $tmp;
								}
								$value[$i]->address =  $mailbox . "@" . $host;
							}
						}
						break;;
			case "RETURNPATH" :	$numpath = count ( $header->return_path );
						for ( $i = 0; $i < $numpath; $i++ ) {
							$tmp[$i] = $header->return_path[$i];
							$path = $tmp[$i];
							while ( list ( $key, $val ) = each ( $path ) ) {
								$personal = $path->personal;
								$mailbox = $path->mailbox;
								$host = $path->host;
								$tmp = quoted_printable_decode(str_replace("=\r\n","", $personal ) );
								if ( strpos ( $tmp, "?Q?" ) ) {
									$tmp_array = explode ( "?", $tmp ); 
									$pers_array = explode ( "_", $tmp_array[3] );
									$value[$i]->name = $pers_array[0] . " " . $pers_array[1];
								} else {
									$value[$i]->name = $tmp;
								}
								$value[$i]->address =  $mailbox . "@" . $host;
							}
						}
						break;;
			
		}
		return $value;
	}	

	//#######################################################################################

	Function FetchBodyType ( $type ) {
		switch ( $type ) {
			case 0: $value = "TEXT"; break;;
			case 1: $value = "MULTIPART"; break;;
			case 2: $value = "MESSAGE"; break;;
			case 3: $value = "APPLICATION"; break;;
			case 4: $value = "AUDIO"; break;;
			case 5: $value = "IMAGE"; break;;
			case 6: $value = "VIDEO"; break;;
			case 7: $value = "OTHER"; break;;
			case 9: $value = "MULTIPART"; break;;
		}
		return $value;
	}

	//#######################################################################################
	// This function converts strings with fi =?big5?B?uXG4o7ZXpEg3MTEw?= or =?iso-8859-1?Q?A7=EB=B2=BC=B6=7D=A9l=21?= 	
	// To a normal string

	Function ConvertEnc ( $string ) {
		
		if( ereg ( "=\?.{0,}\?[Bb]\?", $string ) ) { //big5
			$arr = split ( "=\?.{0,}\?[Bb]\?", $string );
			while ( list ( $key, $value ) = each ( $arr ) ) {
				if ( ereg ( "\?=", $value ) ) {
					$arrTemp = split ( "\?=", $value );
					$arrTemp[0] = base64_decode ( $arrTemp[0] );
					$arrHead[$key] = join ( "", $arrTemp );
				}
			} 
                        $string = join ( "", $arrHead ); 
		}
		if( ereg ( "=\?.{0,}\?[Qq]\?", $string ) ) { // iso-8859-1 
			$strHead = quoted_printable_decode ( $string );
			$string = ereg_replace ( "=\?.{0,}\?[Qq]\?", "", $string );
			$string = ereg_replace ( "\?=", "", $string );
		}
		return $string;
	}

	//#######################################################################################

	Function FetchEncoding ( $encoding ) {
		if ( $encoding ) {
			switch ( $encoding ) {
				case 0: $value = "7BIT"; break;;
				case 1: $value = "8BIT"; break;;
				case 2: $value = "BINARY"; break;;
				case 3: $value = "BASE64"; break;;
				case 4: $value = "QUOTED-PRINTABLE"; break;;
				case 5: $value = "OTHER"; break;;
			}
		} else {
			$value = "";
		}
		return $value;
	}

	
	//#######################################################################################
	
	// Lets build a nice looking message 

	Function ParseTxtToHtml ( $data ) {
		global $user;
		$db = new DB;
		$query = "SELECT user_id FROM users WHERE user='$user'";
		$result = $db->query ( $query );
		$user_id = $db->result ( $result, 0, "user_id" );
        	//echo "<table border=0 cellpadding=2 cellspacing=2><tr><td>&nbsp</td><td>
		echo "<font size=-1>\n";
		// first convert special chars, to be printed correctly 
        	$text = htmlspecialchars ( $data );
		$text = quoted_printable_decode ( $text ); 
                $lines = split("[\n]", $text);
		$numlines = count ( $lines );
		for ($j = 0; $j < $numlines; $j++) {
                	if ( ereg ( "^&gt" , $lines[$j] ) && ! ereg ( "&lt;" , $lines[$j] ) ) {
     	               		echo "<i>$lines[$j]</i><br>\n";
			} else {
                		$tok = split("[ \t]", $lines[$j]);
                    		$numtok = count($tok);
				for ($i = 0; $i < $numtok; $i++) {
					$elem = $tok[$i];
					if ( ereg ( "&lt;html&gt;" , $elem ) ) {
						$j = $numlines;
						break; 	
					}
					if (eregi ("@",$elem)) {  
						if ( ereg ( "&lt;", $elem ) ) {
							$email = str_replace ( "&lt;", "", $elem );
							$email = str_replace ( "&gt;", "", $email );
						} else { $email = $elem; }
						$query = "SELECT email FROM addresses WHERE email='$email' AND owner=$user_id";
						$result = $db->query ( $query );
						$numrows = $db->numrows ( $result );
						if ( $numrows != 0 ) {
                                        		echo "<a href=main.php3?menu=compose&to=$email>$elem</a> ";
						} else {
							echo "<a href='javascript: DoWhatWithemail ( $email )'>$elem</a>";
						}
                                     	} else if ( eregi ("http://", $elem ) ) { 
                                            	echo "<a href=$elem>$elem</a> ";
                                     	} else if ( eregi ("ftp://" , $elem ) ) {
                                             	echo "<a href=$elem>$elem</a> ";
                                     	} else if ( eregi ( "www.", $elem ) ) {
                                             	echo "<a href=http://$elem>$elem</a> ";
                                     	} else { // if the string doesnt contain any important stuff, just print it as it is...
                                              	echo "<b> $elem </b>";
                                     	}
				}
				echo "<br>\n";
			}
		}
        	echo "</font>\n";
        	//echo "</td></tr></table>\n";
	}

	//#######################################################################################

	// Fetch compplete source of message
	Function FetchSource ( $mbox, $msgno ) {
		return imap_fetchheader ( $mbox, $msgno ) . imap_body ( $mbox, $msgno );
	}

	//#######################################################################################

	// lets see which kind of encoding is used for a message part before we parse the text.

	Function PrintPlainText ( $mbox, $msgno, $part_no, $encoding, $return ) {
		if ( $part_no == 1 ) {
			$part = $part_no;
		} else {
			if ( strpos ( $part_no, "." ) ) {
                        	$tmp = explode ( ".", $part_no );
				$counttmp = count ( $tmp );
				for ( $i = 1; $i < $counttmp; $i++ ) {
					if ( $i == 1 ) {
                        			$part = $tmp[$i];
					} else {
						$part = $part . "." . $tmp[$i];
					}
				}
			}
		}
		$text = imap_fetchbody ( $mbox, $msgno, $part );
		$flag =0;
		switch ( $encoding ) {
			case "BASE64":
				$tmp = imap_base64 ( $text );
				$text = str_replace("=\r\n", "",$tmp );
				break;;
			case "QUOTED-PRINTABLE" :
				$tmp = imap_qprint(str_replace("=\r\n","", $text ) );
				$text = $tmp;
				if ( eregi ( "<html>" , $text ) && eregi ( "</html>", $text ) ) {
					$flag = 1;  	// Lets strip html code if it is found
					    		// inside the text part of the message
					    		// html code doesn't belong there !
					$tmp =  str_replace ( "=\r\n", "", $text  );
					$text_arr = explode ( "html>", $tmp );
				} 
				break;;
		 	case "8BIT" : 
				if ( eregi ( "<html>" , $text ) && eregi ( "</html>", $text ) ) {
					$flag = 1;  	// Lets strip html code if it is found
					    		// inside the text part of the message
					    		// html code doesn't belong there !
					$tmp =  str_replace ( "=\r\n", "", $text  );
					$text_arr = explode ( "html>", $tmp );
				} 
				break;;
			case "BINARY" : 
				if ( eregi ( "<html>" , $text ) && eregi ( "</html>", $text ) ) {
					$flag = 1;  	// Lets strip html code if it is found
					    		// inside the text part of the message
					    		// html code doesn't belong there !
					$tmp =  str_replace ( "=\r\n", "", $text  );
					$text_arr = explode ( "html>", $tmp );
				}
				break;; 
			default : 
				if ( eregi ( "<html>" , $text ) && eregi ( "</html>", $text ) ) {
                                        $flag = 1;      // Lets strip html code if it is found
                                                        // inside the text part of the message
                                                        // html code doesn't belong there !
                                        $tmp =  str_replace ( "=\r\n", "", $text  );
                                        $text_arr = explode ( "html>", $tmp );
				}
				break;;
		}				
		if ( $return == 0 ) { 	// if return = 0 we print from this function, otherwise 
					// we just return the value of $text
			if ( $flag == 0 ) { // hopefully we stripped the message part 
					    // from all bad things and we can proceed
					    // making a nice layout for the message to 
					    // be displayed.
				$this->ParseTxtToHtml ( $text );
			} else if ( $flag == 1) {
				echo "$text_arr[1]";
			} 
		} else {
			return $text;
		}	
	}

	//#######################################################################################

	// if there's a TEXT/HTML part in the message, we only need the html code.

	Function PrintHtml ( $mbox, $msgno, $part_no, $encoding ) {
		if ( $part_no == "1" ) {
			$part = $part_no;
		} else {
			if ( strpos ( $part_no, "." ) ) {
                        	$tmp = explode ( ".", $part_no );
				$counttmp = count ( $tmp );
				for ( $i = 1; $i < $counttmp; $i++ ) {
					if ( $i == 1 ) {
                        			$part = $tmp[$i];
					} else {
						$part = $part . "." . $tmp[$i];
					}
				}
			}
		}
		$text = imap_fetchbody ( $mbox, $msgno, $part );
		switch ( $encoding ) {
			case "BASE64" :
				$tmp = imap_base64 ( $text );
				$text = $tmp;
				break;;
			case "QUOTED-PRINTABLE" :
				$tmp = imap_qprint ( $text );
				$text = $tmp;
				break;;
		}
		$stripped = explode ( "</html>", $text ); // make shure no extra data is included
							  // after the html closing tag so our message
							  // will be displayed in the original way
							  // as intended by the creator..
		if ( $stripped[1] != "\r\n" ) {
			if ( $stripped[1] != "" ) {
				$this->ParseTxtToHtml ( $stripped[1] );
			} else {
				echo "$stripped[0]";
			}
		} else {
			echo "$text";
			//$this->ParseTxtToHtml ( $text );
		}
			
	}

	//#######################################################################################

	// Prepare parts of the message you want to be available as downloadable items.
	// eg zip or exe files, word documents, images, sound, etc...

	Function DownloadPart( $mbox,$msgno, $part_no ,$filename, $encoding, $folder) {
		if ( $part_no == 1 ) {
			$part = $part_no;
		} else {
			if ( strpos ( $part_no, "." ) ) {
                        	$tmp = explode ( ".", $part_no );
				$counttmp = count ( $tmp );
				for ( $i = 0; $i < $counttmp; $i++ ) {
					if ( $i == 1 ) {
                        			$part = $tmp[$i];
					} else {
						$part = $part . "." . $tmp[$i];
					}
				}
			}
		}
		//Replace spaces with %20 in links
		$filenme = str_replace ( " ", "%20", $filename );
		// create the link to retrieve the file
		echo "<tr bgcolor=lightgrey><td>";
		echo "<p><a href=download.php3?folder=$folder&msgno=$msgno&part=$part&encoding=$encoding&filename=$filenme><font size=-1>$filename</font></a><p>\n";
		echo "</td></tr>";
	}
	
	// ######################################################################################

	Function FetchStruct ( $mbox, $folder, $msgno, $this_part, $part_no, $count , $subpart) {
		// first let see what parameters are set in the message parts
		$type = $this->FetchBodyType ( $this_part->type ); // type of part eg: TEXT, IMAGE, MULTIPART...
		$encoding = $this->FetchEncoding ( $this_part->encoding ); // lets see which type of decoding needs to be done, if any...
		$subtype = $this_part->subtype; //what kind of part is this? PLAIN, HTML, GIF, ....
		if ( $this_part->ifdescription ) {
			$description = $this_part->description;
		}
		if ( $this_part->ifid ) {
			$id = $this_part->id;
		
		}
		if ( $this_part->ifdisposition ) {
			$disposition = $this_part->disposition; // mostly this will be "ATTACHMENT" or"INLINE"
								// just to tell if we need to treat the part as
								// an attachment or if we can print the part inside the message.
		}
		if ( $this_part->ifdparameters ) {		
			$dparameters = $this_part->dparameters;
			$numdparam = count ( $dparameters );
			for ( $i = 0; $i < $numdparam; $i++ ) {
				$dparam = $dparameters[$i];
			}
		}
		if ( $this_part->ifparameters ) {
			$parameters = $this_part->parameters;
			$numparam = count ( $parameters );
			for ( $i = 0; $i < $numparam; $i++ ) {
				$param = $parameters[$i];
			}
		}
		switch ( $type ) {   
			case "MULTIPART" :
                                break;;
			case "TEXT" :
				break;;
			case "APPLICATION" : 
				$attribute = strtoupper ( $param->attribute );
				$dattribute = strtoupper ( $dparam->attribute );
				if ( $attribute == "NAME" ) {
					$filename = $param->value;
				} else if ( $dattribute == "FILENAME" ) {
					$filename = $dparam->value;
				} else {
					$filename = "unknown";
				}
				if ( ! $folder ) { $folder = "INBOX"; }
				break;;
			case "VIDEO" : 
				$attribute = strtoupper ( $param->attribute );
				$dattribute = strtoupper ( $dparam->attribute );
				if ( $attribute == "NAME" ) {
					$filename = $param->value;
				} else if ( $dattribute == "FILENAME" ) {
					$filename = $dparam->value;
				} else {
					$filename = "unknown";
				}
				if ( ! $folder ) { $folder = "INBOX"; }
				break;;
			case "AUDIO" : 
				$attribute = strtoupper ( $param->attribute );
				$dattribute = strtoupper ( $dparam->attribute );
				if ( $attribute == "NAME" ) {
					$filename = $param->value;
				} else if ( $dattribute == "FILENAME" ) {
					$filename = $dparam->value;
				} else {
					$filename = "unknown";
				}
				if ( ! $folder ) { $folder = "INBOX"; }
				break;;
			case "IMAGE" : 
				$attribute = strtoupper ( $param->attribute );
				$dattribute = strtoupper ( $dparam->attribute );
				if ( $attribute == "NAME" ) {
					$filename = $param->value;
				} else if ( $dattribute == "FILENAME" ) {
					$filename = $dparam->value;
				} else {
					$filename = "unknown";
				}
				if ( ! $folder ) { $folder = "INBOX"; }
				break;;
			case "MESSAGE" : 
				$attribute = strtoupper ( $param->attribute );
				$dattribute = strtoupper ( $dparam->attribute );
				if ( $attribute == "NAME" ) {
					$filename = $param->value;
				} else if ( $dattribute == "FILENAME" ) {
					$filename = $dparam->value;
				} else {
					$filename = "unknown";
				}
				if ( ! $folder ) { $folder = "INBOX"; }
				break;;
		}
		if ( $part_no && $filename) {
			$subpart = $subpart . ", " . $part_no; 
			$subpart = $subpart . ", " . $encoding;
			$subpart = $subpart . ", " . $filename;
			$count++;
		}	
			
		$parts = $this_part->parts;
		$numparts = count ( $parts );
		for ( $i = 0; $i <$numparts; $i++ ) { // now rerun this function for each individual part of the message
						      // so we don't miss any sub or sub sub parts.
			$subpart = $this->FetchStruct ( $mbox, $folder, $msgno, $this_part->parts[$i], $part_no . "." .($i +1 ),  $count, $subpart);
		}
	return $subpart;
	}

	function get_mime_type(&$structure) {
		$primary_mime_type = array("TEXT", "MULTIPART", "MESSAGE",
                                            "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER");
		if($structure->subtype) {
			return $primary_mime_type[(int) $structure->type] . '/' . $structure->subtype;
		}
			return "TEXT/PLAIN";
	} 

	function get_part($stream, $msg_number, $mime_type , $structure = false,
                                            $part_number = false ) {
		if(!$structure) {
			$structure = imap_fetchstructure($stream, $msg_number);
		} 
		if($mime_type == $this->get_mime_type($structure)) {
			if(!$part_number) {
				$part_number = "1"; 
			}
			$text = imap_fetchbody($stream, $msg_number, $part_number);
			if($structure->encoding == 3) {
				return imap_base64($text);
			} else if($structure->encoding == 4) {
				return imap_qprint($text);
			} else {
				return $text;
			}
		}
		if($structure->type == 1) /* multipart */ {
			while(list($index, $sub_structure) = each($structure->parts)) {
				if($part_number) {
					$prefix = $part_number . '.';
				}
				$data = $this->get_part($stream, $msg_number, $mime_type, $sub_structure, $prefix . ($index + 1), $get); 
                                if($data) {
					return $data;
				}
			}
		}
		return false;
	}


	//#######################################################################################

	// Lets look at the structure of the message, which can contain several parts and sub parts
        // part 0 is the complete message, including the message headers
	// part 1 is mostly TEXT or MULTIPART and contains, besides the main message, information
	// on the sub parts within this part 1 ( subparts are numbered as "mainpart.subpart"
	// for example 1.1 is the first subpart of part 1 of a message subparts can also contain 
	// other subparts so 1.1.2 is the second sub part of the first subpart of the first part
	// of a message and so on. 

	Function FetchParts ( $mbox, $folder, $msgno, $this_part, $part_no ) {

		// first let see what parameters are set in the message parts
		$type = $this->FetchBodyType ( $this_part->type ); // type of part eg: TEXT, IMAGE, MULTIPART...
		$encoding = $this->FetchEncoding ( $this_part->encoding ); // lets see which type of decoding needs to be done, if any...
		$subtype = $this_part->subtype; //what kind of part is this? PLAIN, HTML, GIF, ....
		if ( $this_part->ifdescription ) {
			$description = $this_part->description;
		}
		if ( $this_part->ifid ) {
			$id = $this_part->id;
		
		}
		if ( $this_part->ifdisposition ) {
			$disposition = $this_part->disposition; // mostly this will be "ATTACHMENT" or"INLINE"
								// just to tell if we need to treat the part as
								// an attachment or if we can print the part inside the message.
		}
		if ( $this_part->ifdparameters ) {		
			$dparameters = $this_part->dparameters;
			$numdparam = count ( $dparameters );
			for ( $i = 0; $i < $numdparam; $i++ ) {
				$dparam = $dparameters[$i];
			}
		}
		if ( $this_part->ifparameters ) {
			$parameters = $this_part->parameters;
			$numparam = count ( $parameters );
			for ( $i = 0; $i < $numparam; $i++ ) {
				$param = $parameters[$i];
			}
		}
		switch ( $type ) {  // OK , Lets decide what to do with a part , based on the type 
			case "MESSAGE" :
				$this->PrintPlainText ( $mbox, $msgno, $part_no, $encoding, 0);
				break;;
			case "TEXT" :
				if ( $subtype == "PLAIN" ) { 	// if it is plain text we can echo away
							     	// watch out, sometimes html code is also 
							     	// send as plain text , so we need to verify
								// first before parsing it.
								// also it might be that this plain text is
								// encoded.
					$this->PrintPlainText ( $mbox, $msgno, $part_no, $encoding, 0);
				} else if ( $subtype == "HTML" ) { // OK its a html message, but probbably
								   // there's also a plain text part of the message
								   // so we decide to show the plain text immediatly
								   // and offer this html part as a link which
								   // opens a new browser window with the html part
								   // parsed to it.
		
					if ( ! $folder ) { $folder = "INBOX"; }
					$this->PrintHtml ( $mbox, $msgno, $part_no, $encoding);			
					echo "<SCRIPT LANGUAGE=\"JavaScript\">\n";
    					echo "<!--//hide script from old browsers\n";
    					echo "function launch() {\n";
    					echo "window.open('viewfile.php3?folder=$folder&msgno=$msgno&part_no=$part_no&encoding=$encoding', 'viewfile', 'resizable=yes,toolbar=no,location=no,directories=no, status=no,menubar=no,scrollbars=yes,width=600,height=300') }\n";
    					echo "//end hiding contents -->\n";
    					echo "</SCRIPT>\n";
    					echo "<A HREF=\"javascript: launch()\"><font size=-1>Html View</font></A>\n";
				} else if ( $subtype == "X-VCARD" ) {
					$attribute = strtoupper ( $param->attribute );
                                	$dattribute = strtoupper ( $dparam->attribute );
                                	if ( $attribute == "NAME" ) {
                                        	$filename = $param->value;
                                	} else if ( $dattribute == "FILENAME" ) {
                                        	$filename = $dparam->value;
                                	} else {
                                        	$filename = "unknown";
                                	}
                                	if ( ! $folder ) { $folder = "INBOX"; }
                                		$this->DownloadPart( $mbox, $msgno, $part_no ,$filename, $encoding, $folder);
				} else {

					// maybe there's another possible TEXT/subtype combination possible that I don't know of...

					echo "Dunno what this should be yet<p>\n";
				}
				break;;
			case "APPLICATION" : // if the part is an application or a specific filetype webbrowsers cannot
					     // display properly, offer the user to download it by providing a link

				$attribute = strtoupper ( $param->attribute );
				$dattribute = strtoupper ( $dparam->attribute );
				if ( $attribute == "NAME" ) {
					$filename = $param->value;
				} else if ( $dattribute == "FILENAME" ) {
					$filename = $dparam->value;
				} else {
					$filename = "unknown";
				}
				if ( ! $folder ) { $folder = "INBOX"; }
				$this->DownloadPart( $mbox, $msgno, $part_no ,$filename, $encoding, $folder);
				break;;
			case "VIDEO" : // if the part is an application or a specific filetype webbrowsers cannot
					     // display properly, offer the user to download it by providing a link

				$attribute = strtoupper ( $param->attribute );
				$dattribute = strtoupper ( $dparam->attribute );
				if ( $attribute == "NAME" ) {
					$filename = $param->value;
				} else if ( $dattribute == "FILENAME" ) {
					$filename = $dparam->value;
				} else {
					$filename = "unknown";
				}
				if ( ! $folder ) { $folder = "INBOX"; }
				$this->DownloadPart( $mbox, $msgno, $part_no ,$filename, $encoding, $folder);
				break;;
			case "AUDIO" : // if the part is an application or a specific filetype webbrowsers cannot
					     // display properly, offer the user to download it by providing a link

				$attribute = strtoupper ( $param->attribute );
				$dattribute = strtoupper ( $dparam->attribute );
				if ( $attribute == "NAME" ) {
					$filename = $param->value;
				} else if ( $dattribute == "FILENAME" ) {
					$filename = $dparam->value;
				} else {
					$filename = "unknown";
				}
				if ( ! $folder ) { $folder = "INBOX"; }
				$this->DownloadPart( $mbox, $msgno, $part_no ,$filename, $encoding, $folder);
				break;;
			case "IMAGE" : // create a download link and show the part IN the message if it is a GIF or JPEG image.
				$attribute = strtoupper ( $param->attribute );
				$dattribute = strtoupper ( $dparam->attribute );
				if ( $attribute == "NAME" ) {
					$filename = $param->value;
				} else if ( $dattribute == "FILENAME" ) {
					$filename = $dparam->value;
				} else {
					$filename = "unknown";
				}
				if ( ! $folder ) { $folder = "INBOX"; }
				if ( $subtype == "JPEG" || $subtype == "GIF" ) {
					echo "<tr bgcolor=lightgrey><td>";
					echo "<img src=makeimage.php3?msgno=$msgno&part_no=$part_no&encoding=$encoding&folder=$folder&subtype=$subtype><p>\n";
					echo "</td></tr>";
				}
				$this->DownloadPart( $mbox, $msgno, $part_no ,$filename, $encoding, $folder);
				break;;
			//default: $this->PrintPlainText ( $mbox, $msgno, $part_no, $encoding ); 
			//	break;;
		}
		$parts = $this_part->parts;
		$numparts = count ( $parts );
		for ( $i = 0; $i <$numparts; $i++ ) { // now rerun this function for each individual part of the message
						      // so we don't miss any sub or sub sub parts.
	//		echo "part= $part_no\n";
			$this->FetchParts ( $mbox, $folder, $msgno, $this_part->parts[$i], $part_no . "." .($i +1 ) );
		}
	}

	//#######################################################################################

	// Create a new folder, this only works with imap servers, since the pop protocol doesn't support this feature.
	// no worries, if you can connect to your mailserver, by using both protocols, and you created folders via the 
	// imap server, you still will see ALL messages if you connect via the pop server afterwards
			
	Function CreateNewFolder ( $host, $mbox, $newbox ) {
   		global $config;
   		$boxname = imap_utf7_encode ( "{ $host }INBOX.$newbox" );
   		if ( ! imap_createmailbox ( $mbox, $boxname ) ) {
      			return 0;
   		} else {
      			imap_subscribe ( $mbox, $boxname );
      			return 1;
   		}
	}

	//#######################################################################################

	// delete a folder
	// same remark stands here as for the CreateNewFlder function
			
	Function DeleteFolder ( $host, $mbox, $selmbox ) {
   		global $config;
   		$boxname = imap_utf7_encode ( "{ $host }INBOX.$selmbox" );
   		if ( @imap_deletemailbox ( $mbox, $boxname ) ) {
      			return 1;
   		} else {
			print  "imap_deletemailbox on new mailbox failed: ".implode("<br>\n",imap_errors())."<br>\n";
      			return 0;
   		}
	}


	//#######################################################################################

	// Get a List of all folders in your maildirectory
			
	Function FetchFolders ( $host, $mbox ) {
   		global $config;
   		$list = imap_getmailboxes($mbox,"{ $host }","*");
   		sort ( $list );
   		if(is_array($list)) {
         		reset($list);
      			$i = 0;
         		while (list($key, $val) = each($list)) {
                        	$tmp = imap_utf7_decode($val->name);
         			$tmp = str_replace ( "{ $host }", "", $tmp );
         			$folder = str_replace ( "INBOX.", "", $tmp );
         			//if ( ! eregi ( "INBOX", $folder ) ) {
            				$value[$i] = $folder;
            				$i++;
         			//}
                	}
        	} else {
         		print "imap_getmailboxes failed: ".imap_last_error()."\n";
        	}
   		return $value;
	}
	
	//#######################################################################################

	// lets get the headers of al messages in the mailbox.
			
	Function FetchHeaders ( $mbox ) {
		$headers = imap_headers ( $mbox );
		return $headers;
	}

	//#######################################################################################

	// lets sort all messages in the mailbox.

	Function sort ( $mbox, $sorttype, $reverse ) {
		switch ( $sorttype ) {
			case "date" :
					$sorted = imap_sort( $mbox, SORTDATE, $reverse, SE_NOPREFETCH );
					break;;
			case "from" : 
					$sorted = imap_sort( $mbox, SORTFROM, $reverse, SE_NOPREFETCH );
					break;;
			case "subject" : 
					$sorted = imap_sort( $mbox, SORTSUBJECT, $reverse, SE_NOPREFETCH );
					break;;
		}
		return $sorted;
	}

	//#######################################################################################

	Function TransferMsg ( $host, $mbox, $msgs, $flag, $destination ) {
		$flag = strtoupper ( $flag );
		switch ( $flag ) {
			case "DELETE" :
				imap_delete ( $mbox, $msgs, "INBOX." . $destination );
				imap_expunge ( $mbox );
				break;;
			case "COPY" :
				imap_mail_copy ( $mbox, $msgs, "INBOX." . $destination );
				imap_expunge ( $mbox );
				break;;
			case "MOVE" :
				imap_mail_move ( $mbox, $msgs, "INBOX." . $destination );
				imap_expunge ( $mbox );
				break;;
		}

	}


}	

// END of the IMAP Class.

//###################################################################################################################################

?>
Return current item: Myphpim