<?php
/**
 * $Horde: imp/search.php,v 2.128.2.6 2005/09/02 04:49:04 slusarz Exp $
 *
 * Copyright 1999-2005 Charles J. Hagenbuch <chuck@horde.org>
 * Copyright 1999-2005 Jon Parise <jon@horde.org>
 * Copyright 2002-2005 Michael Slusarz <slusarz@bigworm.colorado.edu>
 *
 * See the enclosed file COPYING for license information (GPL).  If you
 * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
 *
 * URL Parameters:
 * ---------------
 * 'mailbox'  --  If exists, don't show the folder selection list; use the
 *                passed in mailbox value instead.
 */

/* Utility functions. */
/**
 * Generates the HTML for a day selection widget.
 *
 * @param string $name      The name of the widget.
 * @param integer $default  The value to select by default. Range: 1-31
 * @param string $params    Any additional parameters to include in the <a>
 *                          tag.
 *
 * @return string  The HTML <select> widget.
 */
function buildDayWidget($name, $default = null, $params = null)
{
    $html = '<select id="' . $name . '" name="' . $name. '"';
    if (!is_null($params)) {
        $html .= ' ' . $params;
    }
    $html .= '>';

    for ($day = 1; $day <= 31; $day++) {
        $html .= '<option value="' . $day . '"';
        $html .= ($day == $default) ? ' selected="selected">' : '>';
        $html .= $day . '</option>';
    }

    return $html . "</select>\n";
}

/**
 * Generates the HTML for a month selection widget.
 *
 * @param string $name      The name of the widget.
 * @param integer $default  The value to select by default.
 * @param string $params    Any additional parameters to include in the <a>
 *                          tag.
 *
 * @return string  The HTML <select> widget.
 */
function buildMonthWidget($name, $default = null, $params = null)
{
    $html = '<select id="' . $name . '" name="' . $name. '"';
    if (!is_null($params)) {
        $html .= ' ' . $params;
    }
    $html .= '>';

    for ($month = 1; $month <= 12; $month++) {
        $html .= '<option value="' . $month . '"';
        $html .= ($month == $default) ? ' selected="selected">' : '>';
        $html .= strftime('%B', mktime(0, 0, 0, $month, 1)) . '</option>';
    }

    return $html . "</select>\n";
}

/**
 * Generates the HTML for a year selection widget.
 *
 * @param integer $name    The name of the widget.
 * @param integer $years   The number of years to include.
 *                         If (+): future years
 *                         If (-): past years
 * @param string $default  The timestamp to select by default.
 * @param string $params   Any additional parameters to include in the <a>
 *                         tag.
 *
 * @return string  The HTML <select> widget.
 */
function buildYearWidget($name, $years, $default = null, $params = null)
{
    $curr_year = date('Y');
    $yearlist = array();

    $startyear = (!is_null($default) && ($default < $curr_year) && ($years > 0)) ? $default : $curr_year;
    $startyear = min($startyear, $startyear + $years);
    for ($i = 0; $i <= abs($years); $i++) {
        $yearlist[] = $startyear++;
    }
    if ($years < 0) {
        $yearlist = array_reverse($yearlist);
    }

    $html = '<select id="' . $name . '" name="' . $name. '"';
    if (!is_null($params)) {
        $html .= ' ' . $params;
    }
    $html .= '>';

    foreach ($yearlist as $year) {
        $html .= '<option value="' . $year . '"';
        $html .= ($year == $default) ? ' selected="selected">' : '>';
        $html .= $year . '</option>';
    }

    return $html . "</select>\n";
}

/* Defines used to determine what kind of field query we are dealing
 * with. */
define('IMP_SEARCH_HEADER', 1);
define('IMP_SEARCH_BODY', 2);
define('IMP_SEARCH_DATE', 3);
define('IMP_SEARCH_TEXT', 4);

/* Defines used to identify the flag input. */
define('IMP_SEARCH_FLAG_SEEN', 1);
define('IMP_SEARCH_FLAG_ANSWERED', 2);
define('IMP_SEARCH_FLAG_FLAGGED', 3);
define('IMP_SEARCH_FLAG_DELETED', 4);

/* Defines used to identify whether to show unsubscribed folders. */
define('IMP_SEARCH_SHOW_UNSUBSCRIBED', 0);
define('IMP_SEARCH_SHOW_SUBSCRIBED_ONLY', 1);

/* The base search fields. */
$fields = array(
    'from' => array(
        'label' => _("From"),
        'type' => IMP_SEARCH_HEADER
    ),
    'to' => array(
        'label' => _("To"),
        'type' => IMP_SEARCH_HEADER
    ),
    'cc' => array(
        'label' => _("Cc"),
        'type' => IMP_SEARCH_HEADER
    ),
    'bcc' => array(
        'label' => _("Bcc"),
        'type' => IMP_SEARCH_HEADER
    ),
    'subject' => array(
        'label' => _("Subject"),
        'type' => IMP_SEARCH_HEADER
    ),
    'body' => array(
       'label' => _("Body"),
       'type' => IMP_SEARCH_BODY
    ),
    'text' => array(
       'label' => _("Entire Message"),
       'type' => IMP_SEARCH_TEXT
    ),
    'received_on' => array(
        'label' => _("Received On"),
        'type' => IMP_SEARCH_DATE
    ),
    'received_until' => array(
        'label' => _("Received Until"),
        'type' => IMP_SEARCH_DATE
    ),
    'received_since' => array(
        'label' => _("Received Since"),
        'type' => IMP_SEARCH_DATE
    )
);

define('IMP_BASE', dirname(__FILE__));
$authentication = OP_HALFOPEN;
require_once IMP_BASE . '/lib/base.php';
require_once IMP_BASE . '/lib/Folder.php';

/* Determine if we are running in the non-standard search mode. */
$create_vfolder = Util::getFormData('create_vfolder');
$edit_vfolder = Util::getFormData('edit_vfolder');
$edit_vfolder_id = Util::getFormData('vfolder');

/* Get URL parameter data. */
$search = array();
if (Util::getFormData('no_match')) {
    require_once IMP_BASE . '/lib/Search.php';
    $search = IMP_Search::retrieveUIQuery();
} elseif ($edit_vfolder_id) {
    $search = IMP_VFolder::retrieveUIQuery($edit_vfolder_id);
} else {
    $search['field'] = Util::getFormData('field', array());
    if (!empty($search['field']) && !end($search['field'])) {
        array_pop($search['field']);
    }
    $search['field_end'] = count($search['field']);
    $search['mbox'] = Util::getFormData('mailbox');
    $search['match'] = Util::getFormData('search_match');
    $search['text'] = Util::getFormData('search_text');
    $search['text_not'] = Util::getFormData('search_text_not');
    $search['date'] = Util::getFormData('search_date');
    $search['flag'] = Util::getFormData('search_flag');
    $search['folders'] = Util::getFormData('search_folders', array());
    $search['save_vfolder'] = Util::getFormData('save_vfolder');
    $search['vfolder_label'] = Util::getFormData('vfolder_label');
    if ($edit_vfolder) {
        $edit_vfolder_id = Util::getFormData('edit_vfolder_id');
    }
}

$curr_date = getdate();

/* Run through the action handlers. */
$actionID = Util::getFormData('actionID');
switch ($actionID) {
case 'do_search':
    /* Create the search query. */
    require_once 'Horde/IMAP/Search.php';
    $query = &new IMAP_Search_Query();

    /* Flag searches. */
    $flag_names = array(
        IMP_SEARCH_FLAG_SEEN => 'seen',
        IMP_SEARCH_FLAG_ANSWERED => 'answered',
        IMP_SEARCH_FLAG_FLAGGED => 'flagged',
        IMP_SEARCH_FLAG_DELETED => 'deleted'
    );
    foreach ($search['flag'] as $key => $val) {
        $flag = $flag_names[$key];
        switch ($val) {
        case 0:
            $query->$flag(true);
            break;
        case 1:
            $query->$flag(false);
            break;
        }
    }

    /* Field searches. */
    $search_array = array();
    foreach ($search['field'] as $key => $val) {
        $ob = &new IMAP_Search_Query();
        switch ($fields[$val]['type']) {
        case IMP_SEARCH_HEADER:
            if (!empty($search['text'][$key])) {
                $ob->header($val, $search['text'][$key], $search['text_not'][$key]);
                $search_array[] = &$ob;
            }
            break;

        case IMP_SEARCH_BODY:
            if (!empty($search['text'][$key])) {
                $ob->body($search['text'][$key], $search['text_not'][$key]);
                $search_array[] = &$ob;
            }
            break;

        case IMP_SEARCH_TEXT:
            if (!empty($search['text'][$key])) {
                $ob->text($search['text'][$key], $search['text_not'][$key]);
                $search_array[] = &$ob;
            }
            break;

        case IMP_SEARCH_DATE:
            if (!empty($search['date'][$key]['day']) &&
                !empty($search['date'][$key]['month']) &&
                !empty($search['date'][$key]['year'])) {
                if ($val == 'received_on') {
                    $ob->on($search['date'][$key]['day'], $search['date'][$key]['month'], $search['date'][$key]['year']);
                } elseif ($val == 'received_until') {
                    $ob->before($search['date'][$key]['day'], $search['date'][$key]['month'], $search['date'][$key]['year']);
                } elseif ($val == 'received_since') {
                    $ob->since($search['date'][$key]['day'], $search['date'][$key]['month'], $search['date'][$key]['year']);
                }
                $search_array[] = &$ob;
            }
            break;
        }
    }

    /* Search match. */
    if ($search['match'] == 'and') {
        $query->imapAnd($search_array);
    } elseif ($search['match'] == 'or') {
        $query->imapOr($search_array);
    }

    /* Save the search as a virtual folder if requested. */
    if (!empty($search['save_vfolder'])) {
        $label = $search['vfolder_label'];
        if (empty($label)) {
            $notification->push(_("Virtual Folders require a label."), 'horde.error');
            break;
        }

        require_once IMP_BASE . '/lib/IMAP/Tree.php';
        require_once IMP_BASE . '/lib/VFolder.php';
        $imptree = &IMP_Tree::singleton();
        if ($edit_vfolder && $edit_vfolder_id) {
            IMP_VFolder::deleteVFolder($edit_vfolder_id);
            if ($imptree) {
                $imptree->delete($edit_vfolder_id);
            }
        }
        $vfolder_id = IMP_VFolder::addVFolder($query, $search);
        if ($imptree) {
            $imptree->insertVFolders(array($vfolder_id => $label));
        }

        $notification->push(sprintf(_("Virtual Folder \"%s\" created succesfully."), $label), 'horde.success');
    } else {
        $label = _("Search Results");
        $vfolder_id = null;
    }

    /* Set the search in the IMP session. */
    require_once IMP_BASE . '/lib/Search.php';
    IMP_Search::createSearchQuery($query, $search['folders'], $search, $label, $vfolder_id);

    /* Redirect to the Mailbox Screen. */
    header('Location: ' . Util::addParameter(Horde::applicationUrl('mailbox.php', true), 'mailbox', IMP_SEARCH_MBOX, false));
    exit;

case 'reset_search':
    $search['field'] = array();
    $search['field_end'] = 0;
    $search['match'] = null;
    $search['date'] = $search['text'] = $search['text_not'] = $search['flag'] = array();
    $search['folders'] = array();
    break;

case 'delete_field':
    $key = Util::getFormData('delete_field_id');

    /* Unset all entries in array input and readjust ids. */
    $vars = array('field', 'text', 'text_not', 'date');
    foreach ($vars as $val) {
        unset($search[$val][$key]);
        if (!empty($search[$val])) {
            $search[$val] = array_values($search[$val]);
        }
    }
    $search['field_end'] = count($search['field']);
    break;
}

$subscribe = 0;
if (!$conf['user']['allow_folders']) {
    $search['mbox'] = 'INBOX';
    $search['folders'][] = 'INBOX';
} elseif ($subscribe = $prefs->getValue('subscribe')) {
    $shown = Util::getFormData('show_subscribed_only', $subscribe);
}

$title = _("Message Search");
if ($create_vfolder) {
    $submit_label = _("Create");
} elseif ($edit_vfolder) {
    $submit_label = _("Save");
} else {
    $submit_label = _("Submit");
}
require IMP_TEMPLATES . '/common-header.inc';
require IMP_TEMPLATES . '/menu.inc';
IMP::status();
require IMP_TEMPLATES . '/search/javascript.inc';
require IMP_TEMPLATES . '/search/header.inc';

/* Process the list of fields. */
for ($i = 0; $i <= $search['field_end']; $i++) {
    $last_field = ($i == $search['field_end']);
    $curr_field = (isset($search['field'][$i])) ? $search['field'][$i] : null;
    require IMP_TEMPLATES . '/search/fields.inc';
}

$newcol = 1;
$numcolumns = 1;
$folderlist = '';
$imp_folder = &IMP_Folder::singleton();

if (!$search['mbox']) {
    $mailboxes = $imp_folder->flist_IMP(array(), (isset($shown)) ? (bool) $shown : null);
    $total = ceil(count($mailboxes) / 3);

    if (empty($search['folders'])) {
        /* Try to guess what folder the user wants to search */
        if (!empty($imp['mailbox']) && $imp['mailbox'] != IMP_SEARCH_MBOX) {
            $search['folders'][] = $imp['mailbox'];
        } elseif (!empty($imp['thismailbox']) && $imp['mailbox'] != IMP_SEARCH_MBOX) {
            $search['folders'][] = $imp['thismailbox'];
        } elseif (($initial_page = $prefs->getValue('initial_page')) &&
                  ($initial_page != 'folders.php')) {
            $search['folders'][] = IMP::addPreambleString($initial_page);
        } else {
            $search['folders'][] = 'INBOX';
        }
    }

    $count = 0;
    foreach ($mailboxes as $mbox) {
        $newcol++;
        if (!empty($mbox['val'])) {
            $folderlist .= '<input id="folder' . $count . '" type="checkbox" name="search_folders[]" value="' . htmlspecialchars($mbox['val']) . '"';
            if (in_array($mbox['val'], $search['folders'])) {
                $folderlist .= ' checked="checked"';
            }
        } else {
            $folderlist .= '<input id="folder' . $count . '" type="checkbox" disabled="disabled"'; 
        }

        $folderlist .= " />\n" . Horde::label('folder' . $count++, str_replace(' ', '&nbsp;', $mbox['label']), '') . "<br />\n";

        if (($newcol > $total) && ($numcolumns != 3)) {
            $newcol = 1;
            $numcolumns++;
            $folderlist .= "</td>\n" . '<td class="item" valign="top" align="left">';
        }
    }
}

require IMP_TEMPLATES . '/search/main.inc';
require $registry->get('templates', 'horde') . '/common-footer.inc';
