<?php
//include('includes/classes/class.textitems.php');
class DBmail {
	var $id;
	var $subject;
	var $subject_words = array();
	var $mailto;
	var $from_name;
	var $from_email;
	var $messageid;
	var $body;
	var $body_words = array();
	var $date;
	var $reply_id;
	var $ebay_id;
	var $customers_id;
	var $orders_id;
	var $read_status;
	var $reply_status;
	var $ownmail;
	var $allocation_status;
	var $saved;
	var $editor;
	var $ebay_user;
	
	var $_filter = array();
    
	function DBmail( $id,$body = true ){
		if($body){
			$query = xtc_db_query("SELECT em.*,emb.email_body FROM ebay_emails em LEFT JOIN ebay_email_bodys emb on em.id=emb.email_id WHERE em.id='".$id."'");
		}else{
			$query = xtc_db_query("SELECT id,subject,mailto,from_name,from_email,date,ebay_id,customers_id,messageid,orders_id,read_status,reply_status,reply_id,ownmail,saved,allocation_status,editor FROM ebay_emails WHERE id='".$id."'");
		}
		$res = xtc_db_fetch_array($query);
		$this->id = $res['id'];
		$this->subject = $res['subject'];
		$this->mailto = $res['mailto'];
		$this->from_name = $res['from_name'];
		$this->from_email = $res['from_email'];
		$this->messageid = $res['message_id'];
		if($body){
			$this->body = $res['email_body'];
		}else{
			$this->body = '';
		}
		$this->date = $res['date'];
		$this->ebay_id = $res['ebay_id'];
		$this->customers_id = $res['customers_id'];
		$this->orders_id = $res['orders_id'];
		$this->read_status = $res['read_status'];
		$this->reply_status = $res['reply_status'];
		$this->reply_id = $res['reply_id'];
		$this->ownmail = $res['ownmail'];
		$this->saved = $res['saved'];
		$this->setEbayUser($res['ebay_user']);
		$this->allocation_status = $res['allocation_status'];
		if($res['editor'] > 0)
			$this->editor = xtc_get_editor_name($res['editor']);
		else
			$this->editor = '';
	}

	function get_email_data() {
		if(EMAIL_FILTER_FROM_DB == 1){
			// CODE AUS MAILFILTER_CRON
			$list = array();
			$orders_query_raw = "select LOWER(customers_email_address) as email from customers";
			$orders_query = xtDBquery($orders_query_raw);
			while ($orders = xtc_db_fetch_array($orders_query,true)) {
				$list[ $orders['email'] ] = true;
			}
			return $list;
		}else{
			// @@@ Fully new code 
			while (is_file(DIR_FS_ADMIN.'cron/'."LOCK"))
			{
				sleep(5);
			}
			
			return unserialize(file_get_contents(DIR_FS_ADMIN.'cron/'."email.txt"));
		}
	}
	
	function get_ebayid_data() {
		if(EMAIL_FILTER_FROM_DB == 1){
			// CODE AUS MAILFILTER_CRON
			$list = array();
			$auction_query_raw = "select ebay_id from ebay_auctions";
			$auction_query = xtDBquery($auction_query_raw);
			while ($auction = xtc_db_fetch_array($auction_query,true)) {
				if($auction['ebay_id'] != '')
					$list[$auction['ebay_id']] = true;
			}
			return $list;
		}else{
			// @@@ Fully new code 
			
			while (is_file(DIR_FS_ADMIN.'cron/'."LOCK"))
			{
				sleep(5);
			}
			
			return unserialize(file_get_contents(DIR_FS_ADMIN.'cron/'."ebayid.txt"));
		}
	}
	
	function get_ebayuser_data() {
		if(EMAIL_FILTER_FROM_DB == 1){
			// CODE AUS MAILFILTER_CRON
			$list = array();
			$query = xtDBquery("select distinct LOWER(userid) as username from ebay_transactions");
			while($res = xtc_db_fetch_array($query,true)) {
				if(trim($res['username']) != '')
					$list[ trim( $res['username'] ) ] = true;
			}
			return $list;
		}else{
			// @@@ Fully new code 
			
			while (is_file(DIR_FS_ADMIN.'cron/'."LOCK"))
			{
				sleep(5);
			}
			
			return unserialize(file_get_contents(DIR_FS_ADMIN.'cron/'."ebayuser.txt"));
		}
	}


	function _searchEmailInArray( $string ) {
		return isset($this->orders[$string]);
	}

	function _searchEbayIdInArray( $string ) {
		return isset($this->auctions[$string]);
	}

	function _searchEbayUserInArray( $string ) {
		return isset($this->ebayuserlist[$string]);
	}

	
	function autofilter( $orders,$emails ) {
		$this->orders = $orders;
		if(sizeOf($emails)>0){
			foreach($emails as $eId=>$email){
				
				// ----- nach email im from feld suchen
				if( $this->_searchEmailInArray($email) == true)
					$matched_orders[$eId] = $email;
			}	
		}
		if(is_array($matched_orders)){
			foreach($matched_orders as $eID=>$match){
				$view[$eID] = $match;
			}
		}
		return $view;
	}

	function filter() {
		$view = array();
		
		$this->ebayuser = $this->get_ebayuser_data();
		$this->orders = $this->get_email_data();
		$this->auctions = $this->get_ebayid_data();
		
		$this->body_words = $this->split_string($this->body); // emailbody als array = $this->body_words
		$this->subject_words = $this->split_string($this->subject); // emailbody als array = $this->body_words
		
		// ----- nach email im from feld suchen
		$_mail = strtolower(trim( $this->getFrom_email(-1,false) ));
		if(strlen($_mail) > 5){
			if( $this->_searchEmailInArray($_mail) == true)
				$matched_orders['email'][$_mail] = true;
		}
		
		if(sizeOf($this->subject_words)>0){
			foreach($this->subject_words as $k=>$v){
				if(strlen($k)==12 && is_numeric($k))
					if( $this->_searchEbayIdInArray($k) == true )
						$matched_orders['ebay_id'][$k] = true;
				
				if(strlen($k)>2)
					if( $this->_searchEbayUserInArray( $k ) == true )
						$matched_orders['ebay_user'][$k] = true;
				
				if(xtc_validate_email($k)==true)
					if( $this->_searchEmailInArray($k) == true)
						$matched_orders['email'][$k] = true;
				
			}
		}
		
		if(sizeOf($this->body_words)>0){
			foreach($this->body_words as $k=>$v){
				// ----- nach ebay_id im body suchen
				if(strlen($k)==12 && is_numeric($k))
					if( $this->_searchEbayIdInArray($k) == true )
						$matched_orders['ebay_id'][$k] = true;
				
				if(strlen($k)>2)
					if( $this->_searchEbayUserInArray( $k ) == true )
						$matched_orders['ebay_user'][$k] = true;
				
				if(xtc_validate_email($k)==true)
					if( $this->_searchEmailInArray($k) == true)
						$matched_orders['email'][$k] = true;
			}
		}
		
		if(is_array($matched_orders)){
			foreach($matched_orders as $class=>$matches){
				if(is_array($matches)){
					foreach( $matches as $value=>$muell ) {
						switch($class){
							case 'ebay_id':
								$view[$class][$value] = true;
								break;
							case 'email':
								$view[$class][$value] = true;
								break;
							case 'ebay_user':
								$view[$class][$value] = true;
								break;
							case 'shop_user':
								$view[$class][$value] = true;
								break;
						}
					}
				}
			}
		}
		return $view;
	}
	
	function split_string($string) {
		$array = array();
		if(trim($string)!=''){
			$words = str_replace("\r\n"," ",strtolower($string));
			$words = str_replace(","," ",$words);
			$words = str_replace(";"," ",$words);
			$words = str_replace(":"," ",$words);
			$words = split(' ',strip_tags(nl2br($words)));
			if(sizeOf($words)>0){
				foreach($words as $k=>$v){
					if(trim($v)!='')
						$array[trim($v)] = true;
				}
			}
		}
		return $array;
	}
	
	function getSubject($strlen=-1){
		if($strlen <= 0) $strlen=strlen($this->subject);
		if($this->isRead())
			return substr($this->subject,0,$strlen);
		else
			if($strlen > 0)
				return "<b>".substr($this->subject,0,$strlen)."</b>";
	}

	function getBody( $MODE = 'HTML' ){
		switch($MODE){
			case 'PLAIN':
				return $this->body;
				break;
			default:
				return nl2br($this->body);
				break;
		}
	}

	function getFrom_name($strlen=-1){
		if($strlen <= 0) $strlen=strlen($this->from_name);
		if($this->isRead())
			return substr($this->from_name,0,$strlen);
		else
			return "<b>".substr($this->from_name,0,$strlen)."</b>";
	}

	function getFrom_email($strlen=-1,$formatted = true ){
		if($strlen <= 0) $strlen=strlen($this->from_email);
		$string = ereg_replace('>','',$this->from_email);
		$string = ereg_replace('<','',$string);
		if($this->isRead()){
			return substr($string,0,$strlen);
		}else{
			if($formatted = true)
				return "<b>".substr($string,0,$strlen)."</b>";
			else
				return substr($string,0,$strlen);
		}
	}

	function get_cleanemail($email_string){
		$string = ereg_replace('>','',$email_string);
		$string = ereg_replace('<','',$string);
		return strtolower($string);
	}

	function getFormatedDate() {
		return strftime('%d.%m.%y<br>%H:%M:%S',strtotime($this->date));
	}

	function getRawDate() {
		return strftime('%d.%m.%y %H:%M:%S',strtotime($this->date));
	}

	function getEbayUser(){
		return $this->ebay_user;
	}

	function setEbayUser($value){
		$this->ebay_user = $value;
	}
	
	function isRead() {
		if($this->read_status > 0)
			return true;
		else
			return false;
	}
	
	function save_mail($subject,$mailto,$from_name,$from_email,$body, $date, $ebay_id='',$customers_id='',$oID='') {
          $query = xtc_db_query("INSERT INTO ebay_emails SET subject='".xtc_db_input($subject)."',mailto='".xtc_db_input($mailto)."', from_name='".xtc_db_input($from_name)."',from_email='".xtc_db_input($from_email)."',date='".xtc_db_input($date)."', ebay_id='".xtc_db_input($ebay_id)."', customers_id='".$customers_id."',orders_id='".$oID."',read_status='1',reply_status='1',allocation_status='1',ownmail='1'");
	  $insert_id = xtc_db_insert_id($query);
	  xtc_db_query("INSERT INTO ebay_email_bodys SET email_id='".$insert_id."',email_body='".xtc_db_input($body)."'");
	}

	function allocateEbayId() {
		xtc_db_query("UPDATE ebay_emails SET ebay_id='".$this->_filter['ebay_id']."', allocation_status='1' WHERE id='".$this->id."'");
	}

	function allocateEbayUserId() {
		$query = xtc_db_query("SELECT c.customers_id FROM ebay_transactions t, customers c WHERE t.userid='".$this->_filter['ebayuser']."' && t.email = c.customers_email_address");
		if(xtc_db_num_rows($query)>0)	{
			$res = xtc_db_fetch_array($query);
			xtc_db_query("UPDATE ebay_emails SET customers_id='".$res['customers_id']."', allocation_status='1' WHERE id='".$this->id."'");
		}
	}

	function allocateEmail() {
		// in customers vorhanden?
		$query = xtc_db_query("SELECT customers_id FROM ".TABLE_CUSTOMERS." WHERE customers_email_address='".$this->_filter['email']."'");
		if(xtc_db_num_rows($query)>0){
			$res = xtc_db_fetch_array($query);
			xtc_db_query("UPDATE ebay_emails SET customers_id='".$res['customers_id']."', allocation_status='1' WHERE id='".$this->id."'");
		}
		// in orders vorhanden?
		$query = xtc_db_query("SELECT customers_id,orders_id FROM ".TABLE_ORDERS." WHERE customers_email_address='".$this->_filter['email']."'");
		if(xtc_db_num_rows($query)>0){
			$res = xtc_db_fetch_array($query);
			xtc_db_query("UPDATE ebay_emails SET customers_id='".$res['customers_id']."',orders_id='".$res['orders_id']."', allocation_status='1' WHERE id='".$this->id."'");
		}
	}

}

/**
* +---------------------------------------------------------------------------+
* | Project:  getmail                                                 |
* | File:     email.class.php                                                 |
* +---------------------------------------------------------------------------+
* | Authors: Manuel Seeger <mail@manuelseeger.de>                             |
* |          ...                                                              |
* +---------------------------------------------------------------------------+
* | GetMail 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.                                       |
* +---------------------------------------------------------------------------+
* | GetMail 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 GetMail; if not, write to the Free Software                    |
* | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA |
* +---------------------------------------------------------------------------+
*
*
* @link http://manuelseeger.de/software/
* @copyright 2003/2004 Manuel Seeger
* @author Manuel Seeger <mail@manuelseeger.de>
* @package getmail
* @version 0.5.3
*
*/

class myEmail {


    /**
     * a list of Email obejcts if isMulitpart is true otherwise the whole email
     * @access public
     * @var array
     */
    var $parts;


    /**
     * list of Headers containing header keys, values and params
     * @access public
     * @var array
     */
    var $headers;

    /**
     * the email's body [may also be a set of subbodies]
     * @access public
     * @var string
     */
    var $body;

    /**
     * occuring errors are stored here
     * @access public
     * @var array
     */
    var $error;

    /**
     * the iterator used by the walk() method
     * @access private
     * @var int
     */
    var $_iterator = 0;
    /**
     * get a possilby given filesname
     * or part name out of the
     * content-disposition paramter list
     * also check the content-type list
     *
     * @access public
     * @return string
     */
    function getFileName()
    {
        if (false !== ($name = $this->getHeader('content-type', 'name'))) {
            return $name;
        }
        else {
            return $this->getHeader('content-disposition', 'filename');
        }
    }
    
    /**
     * Extracts the Email address from a String, eg "my name <myname@mail.tld>"
     * @param string $string
     * @return array('email'=>email,'name'=>name)
     */
    function extract_email($string){
    	$array = array();
    	$string = trim($string);
		// wir filtern den Namen weg, wenn vorhanden
		if(strlen($string)>0){
				$first_pos = strpos($string,'<');
				$last_pos = strpos($string,'>');
				if($first_pos === false and $last_pos === false){
					// ist ok, hat keine klammern
					$array = array('email'=>$string,'name'=>'');
				}else{
					$from = substr($string,($first_pos+1),$last_pos-$first_pos-1);
					$from_name = substr($string,0,($first_pos-1));
					$array = array('email'=>$from,'name'=>$from_name);
				}
		}
		return $array;
    }

    /**
     * get the email's subject
     *
     * @access public
     * @return string or false
     */
    function getSubject()
    {
        return $this->getHeader('subject');
    }

    /**
     * get the email's sender
     *
     * @access public
     * @return string or false
     */
    function getSender()
    {
        return $this->getHeader('from');
    }

  function SplitSender($sender) {
    $senderParts["name"] = $sender;

    if (($pos = strrpos($sender, "<")) && substr($sender, -1) == ">") {
      $senderParts["name"] = substr($sender, 0, $pos - 1);
      $senderParts["email"] = substr($sender, $pos);
    }

    $senderParts["name"] = eregi_replace("\<|\>", "", $senderParts["name"]);

    $firstChar = substr($senderParts["name"], 0, 1);
    $lastChar = substr($senderParts["name"], -1);
    if ($firstChar == "\"" || $firstChar == "'") $senderParts["name"] = substr($senderParts["name"], 1);
    if ($lastChar == "\"" || $lastChar == "'") $senderParts["name"] = substr($senderParts["name"], 0, -1);
    return $senderParts;
  }
  function FormatSender($sender) {
    $sender = eregi_replace("\"", "", $sender);
    $sender = eregi_replace("\<", "", $sender);
    $sender = eregi_replace("\>", "", $sender);
    return $sender;
  }
    /**
     * get the email's recipient
     *
     * @access public
     * @return string or false
     */

    function getRecipient()
    {
        return $this->getHeader('to');
    }

    function getMessageId()
    {
        return $this->getHeader('message-id');
    }

    /**
     * get the email's sent date
     *
     * @access public
     * @return int A Unix timestamp
     */
    function getDate()
    {
        $check = $this->getHeader('date');
        if ($check !== false) {
            //
            // parse the given date an return a
            // unix timestamp
            //
            return strtotime($check);
        }
        else {
            return $check;
        }
    }

    /**
     * get the whole email as a string
     *
     * @access public
     * @return string
     */
    function getMessage()
    {
        return $this->body;
    }

    /**
     * check if it this a multipart message
     *
     * @access public
     * @return boolean
     */
    function isMultipart()
    {
        //
        // part[0] is always the whole email in
        // a flat string
        //
        if (count($this->parts) > 1) {
            return true;
        }
        else {
            return false;
        }
    }

    /**
     * get one of the emails parts
     * return a reference to the
     * part no $i
     *
     * @param $i return the $ith part
     * @access public
     * @return mixed string / object / false
     */
    function &getPart($i=0)
    {
        if (isset($this->parts[$i])) {
            $part =& $this->parts[$i];
            return $part;
        }
        else {
            return false;
        }
    }

    /**
     * get the email's content type
     * either in oen string or
     * sub- and mainpart seperated
     *
     * @param $split boolean wether to split the content type by its / char
     * @access public
     * @return mixed string or array if $split is true
     */
    function getContentType($split=false)
    {
        //
        // check if we want sub and main ctype seperated
        //
        $check = $this->getHeader('content-type');
        if ($split === true and $check !== false) {
            if (false !== ($pos = strpos($check, '/'))) {
                return explode('/', $check);
            }
            else {
                // don't really know what this was all about...
                return array($check, false);
            }
        }
        else {
            return $check;
        }
    }

    /**
     * iterate over all the emails parts
     * this will return all the email's parts
     * (which are also email objects)
     * Returns false if all parts are returned
     * or the emails is ne multipart message
     *
     * can be used in while loops like this:
     * while ($part = $mail->walk()) {
     *     echo $part->getContentType();
     *     echo $part->getFileName();
     * }
     *
     * @access public
     * @return mixed object or false, if there is no part left
     */
    function &walk()
    {

        if ($this->_iterator == (count($this->parts)-1)) {
            //echo 'foo';
            reset($this->parts);
            $this->_iterator = 0;
            return false;
        }
        else {

            // walk() will begin with part[1], since part[0] is always
            // the entire message and can be retrieved by $this->getMessage
            $this->_iterator++;
            return $this->getPart($this->_iterator);
        }
    }


    /**
     * static method which can be used to determine wether
     * a given variable is an email object.
     * It checks for methods and inheritance
     * of the Email class.
     *
     * @access public static
     * @param mixed
     * @return boolean
     */
    function isEmail($var)
    {
        if (!is_object($var)) {
            return false;
        }
        else {
            //
            // most simple: only checks for a list of methods
            //
            if (function_exists('is_a')) {
                if (!is_a($var, 'Email')) {
                    return false;
                }
            }
            $methods = get_class_methods('Email');
            foreach ($methods as $method) {
                if (method_exists($var, $method)) {
                    continue;
                }
                else {
                    return false;
                }
            }
            return true;
        }
    }

    /**
     * some kind of ::factory method
     *
     * @access public
     */
    function &factory()
    {
        $obj =& new myEmail;
        return $obj;
    }

    /**
     * set one of the class's member variables
     * don't use this!
     *
     * @access private
     * @param $var string the name of the variable
     * @param $value mixed the value of the new variable
     */
    function __set($var_value, $value=NULL)   // experimantal...
    {
        if (is_string($var_value) and !empty($value)) {
            $this->{$var_value} = $value;
        }
        //print $var_value.': '.gettype($var_value);

    }

    /**
     * search $this->headers for a header field
     * specified in $get.
     * Return the headerfield's value or
     * one f it's paramters (which must
     * be given in $param and must not be
     * false)
     * If the header(/param) can't be found,
     * return false
     *
     * I recently checked RFC 2231 - can't
     * really say if this is compliant to that rfc
     *
     * @access public
     * @param string the name of the variable
     * @param $value mixed the value of the new variable
     */
    function getHeader($get, $param = false)
    {
        $get = trim(strtolower($get));

        if ($param !== false) {
            $param = trim(strtolower($param));
            if (isset($this->headers[$get]) and
                isset($this->headers[$get]['params'][$param])) {
                //
                // return a parameter, if present
                //
                return $this->headers[$get]['params'][$param];
            }
            else {
                return false;
            }
        }

        if (isset($this->headers[$get])) {
            return $this->headers[$get]['value'];
        }
        else {
            $this->_raiseError("Header $get does not exists!", true);
            return false;
        }
    }

    /**
     * Add the Error in $msg to the
     * list of errors in $this->error
     * todo: distiguish between real
     * errors and simple log entries
     * ie: header c does not exists
     * needs not to be an error..
     *
     * @param string $msg The error message
     * @param bool $log wether it is an error or a log msg
     * @access pricate
     * @return string
     */
    function _raiseError($msg, $log=false)
    {
        if ($log === true) {
            $this->error[] = $msg;
        }
        else {
            $this->error[] = $msg;
        }
    }

    /**
     * return the last errormsg
     * may be called in a while loop;
     * while ($err = $mail->getError()) print $err;
     *
     * @access public
     * @return string
     */
    function getError()
    {
        if (count($this->error) == 0) {
            return false;
        }
        else {
            return array_pop($this->error);
        }
    }
}

/**
* +---------------------------------------------------------------------------+
* | Project:  getmail                                                         |
* | File:     pop3.class.php                                                   |
* +---------------------------------------------------------------------------+
* | Authors: Manuel Seeger <mail@manuelseeger.de>                             |
* |          ...                                                              |
* +---------------------------------------------------------------------------+
* | GetMail 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.                                       |
* +---------------------------------------------------------------------------+
* | GetMail 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 GetMail; if not, write to the Free Software                    |
* | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA |
* +---------------------------------------------------------------------------+
*
* @link http://manuelseeger.de/software/
* @copyright 2003/2004 Manuel Seeger
* @author Manuel Seeger <mail@manuelseeger.de>
* @package GetMail
* @version 0.5.2
*/


class POP3 {

    /**
     * if we get an error, dump it into this array:
     *
     * @var array
     */
    var $error;

    /**
     * The size of the mailbox in bytes
     *
     * @var int
     */
    var $box_size;

    /**
     * the number of emails in the mailbox
     * important for looping through the box
     *
     * @var int
     */
    var $num_msgs;

    /**
     * the connection's state ie 'AUTHORIZATION'
     *
     * @var string
     */
    var $_state;



    /**
     * the socket handle
     *
     * @var resource
     */
    var $_fp;


    /**
     * constructor - define CRLF
     * connect and login if the paramters
     * are passed.
     *
     * @param string $pop3server ip/hostname of the mailserver
     * @param int $port portnumber of the POP server
     * @param string $user pop-box / username
     * @param string $pwd password for the pop-box
     * @access public
     */
    function POP3($server=NULL, $port=110, $user=NULL, $pwd=NULL)
    {
        if (!empty($server)) {
           $this->connect($server, $port);
        }
        if (!empty($user) AND !empty($pwd)) {
           $this->login($user, $pwd);
        }
        //
        // Nur der �bersicht halber (sonst vergisst man das ja eh irgednwo):
        //
        if (!defined('CRLF'))
            define('CRLF', "\r\n");

        $this->error = array();
    }

    /**
     * connects to the POP server, creates socket handle $this->_fp
     *
     * @access public
     * @param string $pop3server ip/hostname of the mailserver
     * @param int $port
     * @return bool
     */
    function connect($pop3server, $port = 110)
    {
        //
        // connect - baut die verbindung auf und erstellt den
        // socket-handler _fp
        //
        if (is_resource($this->_fp = fsockopen( $pop3server,
                                                $port,
                                                $ern,
                                                $err,
                                                10))) {
            $reply = $this->_getLine();
            //
            // Ab jetzt kann eingeloggt werden, es m�sste jetzt die Methode
            // login genutzt werden
            //
            $this->_state = 'AUTHORIZATION';
            return true;
        }
        else {
            $this->error[] = $ern.': '.$err;
            return false;
        }
    }

    /**
     * log in a user - switch from authorization state into transaction state
     *
     * @access public
     * @param string $user
     * @param string $pwd
     * @return bool
     */
    function login($user, $pwd)
    {
        //
        // we are supposed to be in authorization state
        //
        if ($this->_state == 'AUTHORIZATION') {

            $reply = $this->sendCommand('USER '.$user);
            if (($reply = $this->sendCommand('PASS '.$pwd)) !== false) {
                //
                // from now on we are in transaction state
                //
                $this->_state = 'TRANSACTION';
                return true;
            }
            else {
                $this->error[] = 'Falscher Benutzername/Kennwort f�r dieses Postfach';
                return false;
            }
        }
        else {
          $this->error[] = 'Kann nicht einloggen wenn nicht in AUTHORIZATION state';
          return false;
        }
    }

    /**
     * return the size of the mailbox in Bytes
     *
     * @access public
     *
     * @return int
     */
    function getBoxSize()
    {
        if ($this->_state == 'TRANSACTION') {

            if (!isset($this->box_size)) {
                $this->_sendStatCmd();
            }
            return $this->box_size;
        }
        else {
            $this->error[] = 'Kann nicht STAT ausf�hren wenn nicht im TRANSACTION state';
            return false;
        }
    }

    /**
     * return the number of emails in the box
     * carmen lopez: 06227 763077
     *
     * @access public
     *
     * @return int
     */
    function getNumMsgs()
    {
        if ($this->_state == 'TRANSACTION') {

            if (!isset($this->num_msgs)) {
                $this->_sendStatCmd();
            }
            return $this->num_msgs;
        }
        else {
            $this->error .= 'Kann nicht STAT ausf�hren wenn nicht im TRANSACTION state';
            return false;
        }
    }

    /**
     * close the socket and shut down the connection
     *
     * @access public
     */
    function close()
    {
        $line = $this->sendCommand('QUIT');
        fclose($this->_fp);
        return substr($line, 0, 1) == '+' ? true : false;
    }

    /**
     * mark a message as deleted on the server. the message will
     * be deleted in the UPDATE state, means after all transactions
     * are done.
     * So you have to call $this->close() in order to actually
     * delete the messages marked with DELE
     *
     * @access public
     */
    function delMsg($id)
    {
        $line = $this->sendCommand('DELE '.trim($id));
        if (substr($line, 0, 1) != '+') {
            return false;
        }
        else {
            return true;
        }
    }

    /**
     * now it gets interesting: this method retrieves the email with ID $id
     * from the mailserver. in most cases, you don't know the ID, and you call
     * this method out of a loop. see $this->getSizeAndCount() for more
     * information
     *
     * @access public
     * @param $id        // id of a mail in the box
     */
    function getMail($id)
    {
        $reply = $this->sendCommand('RETR '.trim($id));
        $buffer = '';
        while (($line = $this->_getLine()) != '.') {

            if (substr($line, 0, 2) == '..') {
                $line = substr($line, 1);
            }
            $buffer .= $line.CRLF;
        }
        return $buffer;
    }

    /**
     * send a TOP command to the server and retrieve only the
     * headers of a message
     *
     * @param $id        // id of a mail in the box
     * @access public
     */
    function getHeader($id)
    {
        // get the header plus 0 additional body lines
        $reply = $this->sendCommand('TOP '.trim($id).' 0');
        $buffer = '';
        while (($line = $this->_getLine()) != '.') {

            if (substr($line, 0, 2) == '..') {
                $line = substr($line, 1);
            }
            $buffer .= $line.CRLF;
        }
        return $buffer;
    }



    /**
     * send a command to the webserver and return it's reply, or false
     *
     * @access public
     * @param $command        // command to send (see RFC 1939)
     * @return mixed
     */
    function sendCommand($command)
    {
        //
        // Sendet einfach ein Command an den Server.
        // Gibt die Antwort zur�ck
        // Kommt eine fehlermeldung zur�ck, gibt die Funktion false zur�ck
        //
        fwrite($this->_fp, $this->_removeLineBreaks($command).CRLF);
        if (substr($line = $this->_getLine(), 0, 1) != '+') {
            //
            // Wenn kein +OK am anfang steht, hats halt nicht geklappt, siehe RFC 1939
            //
            $this->_raiseError('Server error: '.$line);
            return false;
        }
        else {
            return str_replace('+OK', '', $line);
            //return $line;
        }
    }

    /**
     * Add the Error in $msg to the
     * list of errors in $this->error
     * todo: distiguish between real
     * errors and simple log entries
     *
     * @param string $msg The error message
     * @param bool $log wether it is an error or a log msg
     * @access private
     */
    function _raiseError($msg, $log=false)
    {
        if ($log === true) {
            $this->error[] = $msg;
        }
        else {
            $this->error[] = $msg;
        }
    }

    /**
     * return the last errormsg
     * may be called in a while loop;
     * while ($err = $mail->getError()) print $err;
     *
     * @access public
     * @return mixed String or false, if no error occured
     */
    function getError()
    {
        if (count($this->error) == 0) {
            return false;
        }
        else {
            return array_pop($this->error);
        }
    }


    /**
     * perform STAT command - get the size of the mailbox
     * and the number of emails there
     * Sets  $this->box_size and $this->num_msgs
     *
     * @access private
     * @return bool
     */
    function _sendStatCmd()
    {
        //
        // you need this to get all mails:
        // for ($id=1; $id <= $mailcount; $id++ ) {
        //     $mails[] = $pop->getMail($id);
        // }
        //
        if ($this->_state == 'TRANSACTION') {

            if (empty($this->num_msgs) AND empty($this->box_size)) {
                $reply = $this->sendCommand('STAT');
                list($size, $num) = explode(' ', trim($reply), 2);

                $this->box_size    = $num;
                $this->num_msgs    = $size;
                return true;
            }
            else {
                // stat already sent
                return true;
            }
        }
        else {
            $this->error .= 'Kann nicht STAT ausf�hren wenn nicht im TRANSACTION state';
            return false;
        }
    }

    function _removeLineBreaks($string)
    {
        //
        // Killt vorhandenen \r\n aus dem String (siehe $this->sendCommand())
        //
        return strtr($string, CRLF, '  ');
    }

    function _getLine()
    {
        //
        // lie�t eine zeile aus der Antwort des Servers und
        // killt dabei letzten beiden zeichen (\r\n)
        //
        return substr(fgets($this->_fp, 4096), 0, -2);
    }
}

/**
* +---------------------------------------------------------------------------+
* | Project:  getmail                                                         |
* | File:     mail_parse.class.php                                                   |
* +---------------------------------------------------------------------------+
* | Authors: Manuel Seeger <mail@manuelseeger.de>                             |
* |          ...                                                              |
* +---------------------------------------------------------------------------+
* | GetMail 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.                                       |
* +---------------------------------------------------------------------------+
* | GetMail 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 GetMail; if not, write to the Free Software                    |
* | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA |
* +---------------------------------------------------------------------------+
*
* @dependency email class (email.class.php)
*
* @link http://manuelseeger.de/software/
* @copyright 2003/2004 Manuel Seeger
* @author Manuel Seeger <mail@manuelseeger.de>
* @package GetMail
* @version 0.5.3
*
*/



class Mail_Parser {

    /**
     * the raw header of the email message
     * @access private
     * @var string
     */
    var $_header;

    /**
     * the raw body of the email message
     * @access private
     * @var string
     */
    var $_body;

    /**
     * the raw email message
     * @access private
     * @var string
     */
    var $_data;

    /**
     * Public method whoch will call the other mails
     *
     * @param string $data The email's plain source
     * @return object A reference to the email object
     * @access public
     */

    /**
     *  Possible error msgs here
     * @access public
     * @var array
     */
     var $error = array();

    function &decode($data)
    {
        $this->_data = $data;
        unset($data);
        //
        // fixed the header only bug (see $this->_splitBodyHeader )
        //
        list($header, $body) = $this->_splitBodyHeader($this->_data);

        $this->_header = $header;
        $this->_body   = $body;

        //
        // return a reference to the parsed email object
        //
        return $this->_decode();
    }

    /**
     * split the given data at the first occurance of
     * 2 CRLF (end of header) into header and body
     *
     * @param string data to split
     * @return array header and body
     * @access private
     */
    function _splitBodyHeader($data)
    {
        $data = explode(str_repeat(CRLF,2), $data, 2);
        if (!isset($data[0])) {
            $this->_raiseError('Exploding into body and header failed');
        }
        if (!isset($data[1])) {
            //
            // if you just want to parse headers (ie a TOP result)
            //
            $data[1] = false;
        }
        return $data;
    }

    /**
     * Parse headers given in $data and return
     * as assoc array containg all information about the header
     * public so you can also decode a TOP result
     *
     * @param string Headers to parse
     * @return array Contains parsed header objects
     * @access public
     */
    function parseHeaders($data)
    {
        // unfold the field value (see rfc 822)
        $data = preg_replace("/\r\n(\t| )+/", ' ', $data);

        $headers = explode(CRLF, trim($data));
        $return = array();

        foreach ($headers as $field) {

            if (($pos = strpos($field, ':')) === false) {
                $this->_raiseError('Header parsing failed on field'.$field);
            }
            //echo $field.$pos;
            $field_name  = substr($field, 0, $pos);
            $field_name  = strtolower(trim($field_name));
            //
            // create a new Header object in the list of headers and
            // fill it then with its values
            //

            $field_value = trim(substr($field, $pos+1));
            //
            // decoding and parsing extracts the headers value
            // and additional paramters
            //
            $field_value = $this->_decodeHeader($field_value);
            $field_value = $this->_parseHeaderValue($field_value);
            //
            // $field_value is now an array of the form
            // array('value'=>'thats the value'
            //       'params'=> array('param1name'=>'param1value', etc));
            //
            //foreach ($field_value['params'] as $name => $value) {
            //    $return[$field_name]->paramAppend($name, $value);
            //}
            //
            // eg $return['content-type'] === array(
            //                                'value'=>'text/html',
            //                                'params'=>array(
            //                                          'charset'='iso-9880-1'
            //                                          )
            //                                )
            $return[$field_name] = $field_value;
        }
        //var_dump($return);
        return $return;
    }

    /**
     * Function to parse a header value,
     * extract first part, and any secondary
     * parts (after ;) This function is not as
     * robust as it could be. Eg. header comments        // NOT MY WORK
     * in the wrong place will probably break it.
     *
     * @param string $input Header value to parse
     * @return array Contains parsed result
     * @access private
     */
    function _parseHeaderValue($input)
    {

        $return = array();

        if (($pos = strpos($input, ';')) !== false) {

            $return['value'] = trim(substr($input, 0, $pos));
            // possible paramter go after a ";":
            $input = trim(substr($input, $pos+1));

            if (strlen($input) > 0) {

                $return['params'] = array();
                // This splits on a semi-colon, if there's no preceeding
                // backslash
                // Can't handle if it's in double quotes however.
                // (Of course anyone sending that needs a good slap).
                $parameters = preg_split('/\s*(?<!\\\\);\s*/i', $input);

                for ($i = 0; $i < count($parameters); $i++) {
                    $pos = strpos($parameters[$i], '=');
                    $param_name  = substr($parameters[$i], 0, $pos);
                    $param_value = substr($parameters[$i], $pos + 1);
                    if ($param_value[0] == '"') {
                        $param_value = substr($param_value, 1, -1);
                    }
                    $return['params'][$param_name] = $param_value;
                }
            }
            else {
                $return['params'] = array();
            }
        }
        else {
            $return['value'] = trim($input);
            $return['params'] = array();
        }
        return $return;
    }


    /**
     * Given a header, this function will decode it
     * according to RFC2047. Probably not *exactly*   // NOT (completly) MY WORK
     * conformant, but it does pass all the given
     * examples (in RFC2047).
     *
     * @param string Input header value to decode
     * @return string Decoded header value
     * @access private
     */
    function _decodeHeader($input)
    {
        // Remove white space between encoded-words
        $input = preg_replace('/(=\?[^?]+\?(q|b)\?[^?]*\?=)(\s)+=\?/i',
                              '\1=?',
                              $input);

        // For each encoded-word...
        while (preg_match('/(=\?([^?]+)\?(q|b)\?([^?]*)\?=)/i',
                          $input,
                          $matches)) {

            $encoded  = $matches[1];
            $charset  = $matches[2];
            $encoding = $matches[3];
            $text     = $matches[4];

            switch (strtolower($encoding)) {
                case 'b':
                    $text = base64_decode($text);
                    break;

                case 'q':
                    $text = quoted_printable_decode($text);
                    break;
            }
            $input = str_replace($encoded, $text, $input);
        }
        return $input;
    }


    /**
     * search $headers for a header field
     * specified in $get.
     * Return the headerfield's value or
     * one f it's paramters (which must
     * be given in $param and must not be
     * false)
     *
     * @param array $headers An array as returned by $this->parseHeaders
     * @param string $get The name of the header field
     * @param mixed $param The name of a paramter or false
     * @access private
     * @return string
     */
    function _getHeader($headers, $get, $param=false)
    {
        $get = trim(strtolower($get));

        if ($param !== false) {
            $param = trim(strtolower($param));
            if (isset($headers[$get])) {
                if (isset($headers[$get]['params'][$param])) {
                    return $headers[$get]['params'][$param];
                }
                else {
                    //var_dump($headers[$get]);
                    //var_dump($param);
                    $err= "Param $param does not exists!";
                    $err .= "returning header value instead.";
                    $this->_raiseError($err);
                    return $headers[$get]['value'];
                }
            }
            else {
                $err = "Header $get does not exists!";
                $this->_raiseError($err, true);
                return false;
            }
        }

        if (isset($headers[$get])) {
            return $headers[$get]['value'];
        }
        else {
            $this->_raiseError("Header $get does not exists!", true);
            return false;
        }
    }
    /**
     * Add the Error in $msg to the
     * list of errors in $this->error
     * todo: distiguish between real
     * errors and simple log entries
     * ie: header c does not exists
     * needs not to be an error..
     *
     * @param string $msg The error message
     * @param bool $log wether it is an error or a log msg
     * @access private
     */
    function _raiseError($msg, $log=false)
    {
        if ($log === true) {
            $this->error[] = $msg;
        }
        else {
            $this->error[] = $msg;
        }
    }

    /**
     * return the last errormsg
     * may be called in a while loop;
     * while ($err = $mail->getError()) print $err;
     *
     * @access public
     * @return mixed String or false, if no error occured
     */
    function getError()
    {
        if (count($this->error) == 0) {
            return false;
        }
        else {
            return array_pop($this->error);
        }
    }


    /**
     * This function does the main part of
     * the encoding.
     *
     * Make a new email object
     * (see email.class.php)
     * Then parse the headers in $this->header
     * and evaluate the content type of the email
     * In case it is one of the mulitpart/ types,
     * the body of the email is to be exploded at the
     * boundary-string (the boundary string is a
     * paramter of content-type, it will be retrieved
     * using $this->_getHeader())
     * For each of the email's parts which result from
     * the exploding, build a new email object. Again
     * parse the headers of that object.
     * If a part is decoded  using base64 or quoted printable,
     * decode it. (see $this->_decodeData())
     * Can't decode UU so far
     *
     * The returned email object has a member variable
     * $parts (array), containing:
     * - $parts[0] the unparsed body of the entire email
     * - $parts[1] a new email object representing a
     *   subpart of the email's body in case the email
     *   is one of the multipart types
     * - $parts[2-n] more subpart email objects
     *
     * See the email.class.php for more information on the
     * the usage of email objects
     *
     * @access pricate
     * @return object The email object returned by $this->decode
     */
    function &_decode()
    {
        //
        // we will return this object
        //
        $ret =& myEmail::factory();

        $headers = $this->parseHeaders($this->_header);

        $ret->__set('headers', $headers);
        //*/

        //
        // All the emails body data is stored here:
        //
        $part_info = array();
        $part_info[] = $this->_data;

        switch (strtolower($this->_getHeader($headers, 'content-type'))) {

            case 'text/html':
            case 'text/plain':
            case 'message/rfc822':
                //
                // just decode the body
                //
                $en = $this->_getHeader($headers, 'content-transfer-encoding');
                //
                // in case the whole email body is encoded:
                //
                $this->_body = $this->_decodeData($en, $this->_body);
                $ret->__set('body', $this->_body);
                break;

            case 'multipart/parallel':
            case 'multipart/report': // RFC1892
            case 'multipart/signed': // PGP
            case 'multipart/digest':
            case 'multipart/alternative':
            case 'multipart/related':
            case 'multipart/mixed':
                //
                // get the buondart parameter
                //
                $boundary = $this->_getHeader($headers,
                                             'content-type',
                                             'boundary'
                                             );
                $multiparts = explode('--'.$boundary, $this->_body);
                //echo $this->_body;
                //echo $boundary;
                //var_dump($multiparts);
                //
                // remove the first part ("this is a message in mime format"...)
                // and the last part, which has to constist of two hyphens: --
                //
                $info_msg = array_shift($multiparts);
                if (trim(array_pop($multiparts)) != '--') {
                    $this->_raiseError('parsing failed in method _decode');
                }

                foreach ($multiparts as $key => $part_buffer) {
                    // since $part_info[0] is $this->_body, we must
                    // not override it and therefor increase the current key
                    $i = $key + 1;
                    $part_info[$i] =& myEmail::factory();

                    list($header,$body) = $this->_splitBodyHeader($part_buffer);
                    $part_headers = $this->parseHeaders($header);
                    //
                    // decode the body part according to the header field
                    // content-transfer-encoding
                    //
                    $encoding = $this->_getHeader($part_headers,
                                                  'content-transfer-encoding');
                    $body = $this->_decodeData($encoding, $body);

                    $part_info[$i]->__set('headers', $part_headers);
                    //
                    // parts awaits an array:
                    //
                    $part_info[$i]->__set('parts', array($part_buffer));
                    $part_info[$i]->__set('body', $body);

                    $ctype = $this->_getHeader($part_headers, 'content-type');
                }
                //
                // we are still in a switch:
                //
                break;
        }
        $ret->__set('parts', $part_info);
        //
        // and now we return - finally - the Mail Object
        //
        return $ret;
    }


    /**
     * this method will decode the email objects body variable
     * according to the content-transfer-encoding header field.
     *
     * @param string Encoding type
     * @param string Encoded/plain data
     * @return string Decoded body
     * @access private
     */
    function _decodeData($encoding, $data)
    {
        switch ($encoding) {

            case 'quoted-printable':
                return quoted_printable_decode($data);
                break;

            case 'base64':
                return base64_decode($data);
                break;

            default:
                return $data;
        }
    }
}
?>
