<?php

require_once HORDE_BASE . '/lib/Identity.php';

/**
 * This class provides an IMP-specific interface to all identities a
 * user might have. Its methods take care of any site-specific
 * restrictions configured in prefs.php and conf.php.
 *
 * $Horde: imp/lib/Identity/imp.php,v 1.24 2003/08/01 21:41:06 jan Exp $
 *
 * Copyright 2001-2003 Jan Schneider <jan@horde.org>
 * Copyright 2001-2003 Chuck Hagenbuch <chuck@horde.org>
 *
 * See the enclosed file COPYING for license information (GPL). If you
 * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
 *
 * @author  Jan Schneider <jan@horde.org>
 * @author  Chuck Hagenbuch <chuck@horde.org>
 * @version $Revision: 1.24 $
 * @since   IMP 2.3.7
 * @package horde.identity
 */
class Identity_imp extends Identity {

    /**
     * Array containing all of the properties in this identity,
     * excluding the id.
     *
     * @var array $_properties
     */
    var $_properties = array(
        'fullname', 'from_addr', 'replyto_addr', 'alias_addr', 'tieto_addr',
        'signature', 'sig_first', 'sig_dashes', 'save_sent_mail',
        'sent_mail_folder'
    );

    /**
     * Cached alias list.
     *
     * @var array $_aliases
     */
    var $_aliases = array();

    /**
     * Cached from address list.
     *
     * @var array $_fromList
     */
    var $_fromList = array();

    /**
     * Cached names list.
     *
     * @var array $_names
     */
    var $_names = array();

    /**
     * Cached signature list.
     *
     * @var array $_signatures
     */
    var $_signatures = array();

    /**
     * Reads all the user's identities from the prefs object or builds
     * a new identity from the standard values given in prefs.php.
     */
    function Identity_imp()
    {
        parent::Identity();
    }

    /**
     * Returns a complete From: header based on all relevent factors (fullname,
     * from address, input fields, locks etc.)
     *
     * @param optional integer $ident        The identity to retrieve the
     *                                       values from.
     * @param optional string $from_address  A default from address to use if
     *                                       no identity is selected and the
     *                                       from_addr preference is locked.
     *
     * @return string  A full From: header in the format
     *                 'Fullname <user@example.com>'.
     */
    function getFromLine($ident = null, $from_address = '')
    {
        global $imp;

        if (isset($froms[$ident])) {
            return $froms[$ident];
        }

        if (!isset($ident)) {
            $address = $from_address;
        }

        if (empty($address) || $this->_prefs->isLocked('from_addr')) {
            $address = $this->getFromAddress($ident);
            $name = $this->getFullname($ident);
        }

        if (!empty($address)) {
            $ob = imap_rfc822_parse_adrlist($address, $imp['maildomain']);
        }

        if (empty($name)) {
            if (!empty($ob[0]->personal)) {
                $name = $ob[0]->personal;
            } else {
                $name = $this->getFullname($ident);
            }
        }

        $from = MIME::trimEmailAddress(MIME::rfc822WriteAddress($ob[0]->mailbox, $ob[0]->host, $name));

        $froms[$ident] = $from;
        return $from;
    }

    /**
     * Returns an array with From: headers from all identities
     *
     * @return array  The From: headers from all identities
     */
    function getAllFromLines()
    {
        foreach ($this->_identities as $ident => $dummy) {
            $list[$ident] = $this->getFromAddress($ident);
        }
        return $list;
    }

    /**
     * Returns an array with the necessary values for the identity select
     * box in the IMP compose window.
     *
     * @return array  The array with the necessary strings
     */
    function getSelectList()
    {
        $ids = $this->getAll('id');
        foreach ($ids as $key => $id) {
            $list[$key] = $this->getFromAddress($key) . ' (' . $id . ')';
        }
        return $list;
    }

    /**
     * Returns true if the given address belongs to one of the identities.
     * This function will search aliases for an identity automatically.
     *
     * @param string $address  The address to search for in the identities.
     *
     * @return boolean  True if the address was found.
     */
    function hasAddress($address)
    {
        static $list;

        $address = String::lower($address);
        if (!isset($list)) {
            $list = $this->getAllFromAddresses(true);
        }

        if (array_key_exists($address, $list)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Returns the from address based on the chosen identity. If no
     * address can be found it is built from the current user name and
     * the specified maildomain.
     *
     * @param optional integer $ident  The identity to retrieve the address
     *                                 from.
     *
     * @return string  A valid from address.
     */
    function getFromAddress($ident = null)
    {
        global $imp;

        if (!empty($this->_fromList[$ident])) {
            return $this->_fromList[$ident];
        }

        $val = $this->getValue('from_addr', $ident);
        if (empty($val)) {
            $val = $imp['user'];
        }

        if (!strstr($val, '@')) {
            $val .= '@' . $imp['maildomain'];
        }

        $this->_fromList[$ident] = $val;

        return $val;
    }

    /**
     * Returns all aliases based on the chosen identity.
     *
     * @param integer $ident  The identity to retrieve the aliases from.
     *
     * @return array  Aliases for the identity.
     */
    function getAliasAddress($ident)
    {
        if (empty($this->_aliases[$ident])) {
            $this->_aliases[$ident] = $this->getValue('alias_addr', $ident);
        }

        return $this->_aliases[$ident];
    }

    /**
     * Returns an array with all identities' from addresses.
     *
     * @param optional boolean $alias  Include aliases?
     *
     * @return array  The array with
     *                KEY - address
     *                VAL - identity number
     */
    function getAllFromAddresses($alias = false)
    {
        $list = array();

        foreach ($this->_identities as $key => $identity) {
            /* Get From Addresses. */
            $addr = $this->getFromAddress($key);
            if (!isset($list[$addr])) {
                $list[$addr] = $key;
            }

            /* Get Aliases. */
            if ($alias) {
                $addrs = $this->getAliasAddress($key);
                if (!empty($addrs)) {
                    foreach ($addrs as $val) {
                        if (!isset($list[$val])) {
                            $list[$val] = $key;
                        }
                    }
                }
            }
        }

        return $list;
    }

    /**
     * Get all 'tie to' address/identity pairs.
     *
     * @access public
     *
     * @return array  The array with
     *                KEY - address
     *                VAL - identity number
     */
    function getAllTieAddresses()
    {
        $list = array();

        foreach ($this->_identities as $key => $identity) {
            $tieaddr = $this->getValue('tieto_addr', $key);
            if (!empty($tieaddr)) {
                foreach ($tieaddr as $val) {
                    if (!isset($list[$val])) {
                        $list[$val] = $key;
                    }
                }
            }
        }

        return $list;
    }

    /**
     * Returns the identity's id that matches the passed addresses.
     *
     * @param mixed $addresses  Either an array or a single string or a
     *                          comma separated list of email addresses.
     *
     * @return integer  The id of the first identity that from or alias
     *                  addresses match (one of) the passed addresses or
     *                  null if none matches.
     */
    function getMatchingIdentity($addresses)
    {
        // Normalize address list.
        if (!is_array($addresses)) {
            $addresses = array($addresses);
        }
        $addresses = implode(', ', $addresses);
        $addresses = imap_rfc822_parse_adrlist($addresses, '');

        $ident = null;
        $tie_addresses = $this->getAllTieAddresses();
        $own_addresses = $this->getAllFromAddresses(true);

        foreach ($addresses as $address) {
            if (empty($address->mailbox)) {
                continue;
            }
            $find_address = $address->mailbox;
            if (!empty($address->host)) {
                $find_address .= '@' . $address->host;
            }
            $find_address = String::lower($find_address);

            /* Search 'tieto' addresses first. */
            if (array_key_exists($find_address, $tie_addresses)) {
                $ident = $tie_addresses[$find_address];
                break;
            }
         
            /* Next, search all from addresses. */
            if (array_key_exists($find_address, $own_addresses)) {
                $ident = $own_addresses[$find_address];
                break;
            }
       }

       return $ident;
    }

    /**
     * Returns the users full name.
     *
     * @param optional integer $ident  The identity to retrieve the name from.
     *
     * @return string  The user's full name.
     */
    function getFullname($ident = null)
    {
        if (isset($this->_names[$ident])) {
            return $this->_names[$ident];
        }

        $this->_names[$ident] = $this->getValue('fullname', $ident);

        return $this->_names[$ident];
    }

    /**
     * Returns the full signature based on the current settings for the
     * signature itself, the dashes and the position.
     *
     * @param optional integer $ident  The identity to retrieve the signature
     *                                 from.
     *
     * @return string  The full signature.
     */
    function getSignature($ident = null)
    {
        global $conf;

        if (isset($this->_signatures[$ident])) {
            return $this->_signatures[$ident];
        }

        $val = $this->getValue('signature', $ident);
        if (!empty($val)) {
            $sig_first = $this->getValue('sig_first', $ident);
            $sig_dashes = $this->getValue('sig_dashes', $ident);
            $val = str_replace("\r\n", "\n", $val);
            if ($sig_dashes) {
                $val = "-- \n$val";
            }
            if (isset($sig_first) && $sig_first) {
                $val = "\n" . $val . "\n\n\n";
            } else {
                $val = "\n" . $val;
            }
        }

        if (!empty($conf['hooks']['signature'])) {
            include_once HORDE_BASE . '/config/hooks.php';
            if (function_exists('_imp_hook_signature')) {
                $val = call_user_func('_imp_hook_signature', $val);
            }
        }

        $this->_signatures[$ident] = $val;

        return $val;
    }

    /**
     * Returns an array with the signatures from all identities
     *
     * @return array  The array with all the signatures.
     */
    function getAllSignatures()
    {
        static $list;

        if (isset($list)) {
            return $list;
        }

        foreach ($this->_identities as $key => $identity) {
            $list[$key] = $this->getSignature($key);
        }

        return $list;
    }

    /**
     * Returns the sent-mail folder name.
     *
     * @param optional integer $ident            The identity to retrive the
     *                                           folder name from.
     * @param optional string $sent_mail_folder  A default folder that is
     *                                           returned no identity is
     *                                           selected and the
     *                                           sent_mail_folder preference
     *                                           is not locked.
     *
     * @return string  The folder name with the folder prefix.
     */
    function getSentmailFolder($ident = null, $sent_mail_folder = '')
    {
        if (!isset($ident)) {
            $folder = $sent_mail_folder;
        }
        if (empty($folder) || $this->_prefs->isLocked('sent_mail_folder')) {
            $folder = $this->getValue('sent_mail_folder', $ident);
        }

        if (String::substr($folder, 0, String::length(IMP::preambleString())) != IMP::preambleString()) {
            $folder = IMP::addPreambleString($folder);
        }

        return $folder;
    }

    /**
     * Returns an array with the sent-mail folder names from all the
     * identities.
     *
     * @return array  The array with the folder names.
     */
    function getAllSentmailFolders()
    {
        foreach ($this->_identities as $key => $identity) {
            $list[$this->getSentmailFolder($key)] = true;
        }
        return array_keys($list);
    }

    /**
     * Returns true if the mail should be saved and the user is allowed to.
     *
     * @param optional integer $ident  The identity to retrieve the setting
     *                                 from.
     *
     * @return boolean  True if the sent mail should be saved.
     */
    function saveSentmail($ident = null)
    {
        global $conf;

        if (!$conf['user']['allow_folders']) {
            return false;
        }

        return $this->getValue('save_sent_mail', $ident);
    }

}
