<?php

/**
 * @package Horde_Kolab
 *
 * $Horde: framework/Kolab/Kolab/IMAP.php,v 1.1 2007/03/09 13:16:14 jan Exp $
 */

/**
 * The Horde_Kolab library requires version >= 1.0.3 of
 * Net_IMAP (i.e. a version that includes support for the
 * ANNOTATEMORE IMAP extension). The latest version of
 * Net_IMAP can be obtained from
 * http://pear.php.net/get/Net_IMAP
 */
require_once 'Net/IMAP.php';

/**
 * The Kolab_IMAP_Connection_pear class connects to an IMAP server
 * using the Net_IMAP PEAR package.
 *
 * $Horde: framework/Kolab/Kolab/IMAP.php,v 1.1 2007/03/09 13:16:14 jan Exp $
 *
 * Copyright 2007 The Horde Project (http://www.horde.org/)
 *
 * See the enclosed file COPYING for license information (LGPL). If you
 * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
 *
 * @author  Gunnar Wrobel <wrobel@pardus.de>
 * @author  Thomas Jarosch <thomas.jarosch@intra2net.com>
 * @package Horde_Kolab
 */
class Kolab_IMAP_Connection_pear extends Kolab_IMAP_Connection {

    /**
     * Connect to the IMAP server.
     *
     * @param string  $login     The user account name.
     * @param string  $password  The user password.
     * @param boolean $tls       Should TLS be used for the connection?
     *
     * @return mixed True in case the connection was opened
     * successfully, a PEAR error otherwise.
     */
    function connect($login, $password, $tls = false)
    {
        $this->_imap = &new Net_IMAP($this->_server, $this->_port);
        return $this->_imap->login($login, $password, true, false);
    }

    /**
     * Disconnect from the IMAP server.
     *
     * @return mixed True in case the connection was closed
     * successfully, a PEAR error otherwise.
     */
    function disconnect()
    {
        return $this->_imap->disconnect();
    }

    /**
     * Open the given folder.
     *
     * @param string $folder The folder to open
     *
     * @return mixed True in case the folder was opened successfully,
     * a PEAR error otherwise.
     */
    function select($folder)
    {
        return $this->_imap->selectMailbox($folder);
    }

    /**
     * Return the status of the current folder.
     *
     * @return array An array that contains 'uidvalidity' and
     * 'uidnext'
     */
    function status()
    {
        $result = array();

        $mailbox = $this->_imap->getCurrentMailbox();

        // Net_IMAP is not very efficent here
        $ret = $this->_imap->cmdStatus( $mailbox , "UIDVALIDITY" );
        $result["uidvalidity"] = $ret["PARSED"]["STATUS"]["ATTRIBUTES"]["UIDVALIDITY"];

        $ret = $this->_imap->cmdStatus( $mailbox , "UIDNEXT" );
        $result["uidnext"] = $ret["PARSED"]["STATUS"]["ATTRIBUTES"]["UIDNEXT"];

        return $result;
    }

    /**
     * Get the message ids of the messages in this folder.
     *
     * @return array The message ids
     */
    function getUids()
    {
        $uids = $this->_imap->search("UNDELETED");

        if (!is_array($uids)) {
            $uids = array();
        }
        return $uids;
    }

    /**
     * Search the current folder using the given list of search
     * criteria.
     *
     * @param string $search_list A list of search criteria
     *
     * @return mixed The list of matching message ids or a PEAR error
     * in case of an error.
     */
    function search($search_list, $uidSearch = true) 
    {
        return $this->_imap->search($search_list, $uidSearch);
    }
    
    /**
     * Search the headers of the messages. 
     *
     * @param string $field  The name of the header field
     * @param string $value  The value that field should match
     *
     * @return mixed The list of matching message ids or a PEAR error
     * in case of an error.
     */
    function searchHeaders($field, $value) 
    {
        return $this->_imap->search('HEADER "' . $field . '" "' . $value . '"', true);
    }
    
    /**
     * Retrieve the message headers for a given message id.
     *
     * @param int     $uid            The message id
     * @param boolean $peek_for_body  Prefetch the body
     *
     * @return mixed The message header or a PEAR error in case of an
     * error.
     */
    function getMessageHeader($uid, $peek_for_body = true)
    {
        $ret = $this->_imap->cmdUidFetch($uid, "BODY[HEADER]");
	if(strtoupper($ret["RESPONSE"]["CODE"]) != "OK"){
            return PEAR::raiseError(sprintf(_("Horde/Kolab/IMAP: Failed fetching headers of message %s. Error was %s"), $uid, 
                                            $ret["RESPONSE"]["CODE"] . ", " . $ret["RESPONSE"]["STR_CODE"]));
        }
	if(isset($ret["PARSED"])){
	    foreach($ret["PARSED"] as $msg){
                if(isset($msg["EXT"]["BODY[HEADER]"]["CONTENT"])){
                    return $msg["EXT"]["BODY[HEADER]"]["CONTENT"];
                }
            }
       }
       return '';
    }
    
    /**
     * Retrieve the message body for a given message id.
     *
     * @param int     $uid            The message id
     *
     * @return mixed The message body or a PEAR error in case of an
     * error.
     */
    function getMessageBody($uid)
    {
        $ret = $this->_imap->cmdUidFetch($uid, "BODY[TEXT]");
	if(strtoupper($ret["RESPONSE"]["CODE"]) != "OK"){
            return PEAR::raiseError(sprintf(_("Horde/Kolab/IMAP: Failed fetching body of message %s. Error was %s"), $uid, 
                                            $ret["RESPONSE"]["CODE"] . ", " . $ret["RESPONSE"]["STR_CODE"]));
        }
	if(isset($ret["PARSED"])){
	    foreach($ret["PARSED"] as $msg){
                if(isset($msg["EXT"]["BODY[TEXT]"]["CONTENT"])){
                    return $msg["EXT"]["BODY[TEXT]"]["CONTENT"];
                }
            }
       }
       return '';
    }

    /**
     * Retrieve the full message text for a given message id.
     *
     * @param int     $uid            The message id
     *
     * @return mixed The message text or a PEAR error in case of an
     * error.
     */
    function getMessage($uid)
    {
        $ret = $this->_imap->cmdUidFetch($uid, "RFC822");
        if(strtoupper($ret["RESPONSE"]["CODE"]) != "OK"){
            return PEAR::raiseError(sprintf(_("Horde/Kolab/IMAP: Failed	fetching message %s. Error was %s"), $uid,
                                            $ret["RESPONSE"]["CODE"] . ", " . $ret["RESPONSE"]["STR_CODE"]));
        }
        if(isset($ret["PARSED"])){
            foreach($ret["PARSED"] as $msg){
                if(isset($msg["EXT"]["RFC822"]["CONTENT"])){
                    return $msg["EXT"]["RFC822"]["CONTENT"];
                }
            }
        }
        return '';
    }
    
    /**
     * Retrieve a list of mailboxes on the server.
     *
     * @return mixed The list of mailboxes or a PEAR error in case of an
     * error.
     */
    function getMailboxes()
    {
        return $this->_imap->getMailboxes();
    }
    
    /**
     * Fetch the annotation on a folder.
     *
     * @param string  $entries        The entry to fetch.
     * @param string  $values         The specific value to fetch.
     * @param string  $mailbox_name   The name of the folder.
     *
     * @return mixed The annotation value or a PEAR error in case of
     * an error.
     */
    function getAnnotation($entries, $values, $mailbox_name)
    {
        return $this->_imap->getAnnotation($entries, $values, $mailbox_name);
    }

    /**
     * Append a message to the current folder.
     *
     * @param string  $msg       The message to append
     *
     * @return mixed True or a PEAR error in case of an error.
     */
    function appendMessage($msg)
    {
        return $this->_imap->appendMessage($msg);
    }
    
    /**
     * Copy a message to a new folder.
     *
     * @param int    $uid       IMAP message id
     * @param string $new_folder  Target folder
     *
     * @return mixed True or a PEAR error in case of an error.
     */
    function copyMessage($uid, $new_folder)
    {
        return $this->_imap->cmdUidCopy($new_folder, $uid);
    }

    /**
     * Move a message to a new folder.
     *
     * @param int    $uid       IMAP message id
     * @param string $new_folder  Target folder
     *
     * @return mixed True or a PEAR error in case of an error.
     */
    function moveMessage($uid, $new_folder)
    {

        $result = $this->copyMessage($uid, $new_folder);
        if (is_a($result, 'PEAR_Error')) {
            return $result;
        }

        $result = $this->deleteMessage($uid);
        if (is_a($result, 'PEAR_Error')) {
            return $result;
        }

        $result = $this->expunge();
        if (is_a($result, 'PEAR_Error')) {
            return $result;
        }
        return true;
    }

    /**
     * Delete messages from the current folder.
     *
     * @param int    $uids         IMAP message ids
     *
     * @return mixed True or a PEAR error in case of an error.
     */
    function deleteMessages($uids)
    {
        if (!is_array($uids)) {
            $uids = array($uids);
        }

        foreach($uids as $uid) {
            $result = $this->_imap->cmdUidStore($uid, '+FLAGS.SILENT', '\Deleted');
            if (is_a($result, 'PEAR_Error')) {
                return $result;
            }
        }
        return true;
    }

    /**
     * Undelete a message in the current folder.
     *
     * @param int    $uid         IMAP message id
     *
     * @return mixed True or a PEAR error in case of an error.
     */
    function undeleteMessages($uid)
    {
        return $this->_imap->cmdUidStore($uid, '-FLAGS.SILENT', '\Deleted');
    }

    /**
     * Expunge messages in the current folder.
     *
     * @return mixed True or a PEAR error in case of an error.
     */
    function expunge()
    {
        return $this->_imap->expunge();
    }

}