* @copyright © 1999-2006 The SquirrelMail Project Team
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
* @version $Id$
* @package squirrelmail
* @subpackage search
* @link http://www.ietf.org/rfc/rfc3501.txt
*/
/**
* Include the SquirrelMail initialization file.
*/
require('../include/init.php');
/** SquirrelMail required files.
*/
require_once(SM_PATH . 'functions/imap_asearch.php');
require_once(SM_PATH . 'functions/imap_messages.php');
require_once(SM_PATH . 'functions/imap_general.php');
require_once(SM_PATH . 'functions/mime.php');
require_once(SM_PATH . 'functions/mailbox_display.php'); //getButton()
require_once(SM_PATH . 'functions/forms.php');
require_once(SM_PATH . 'functions/date.php');
/** Prefs array ordinals. Must match $recent_prefkeys and $saved_prefkeys
*/
define('ASEARCH_WHERE', 0);
define('ASEARCH_MAILBOX', 1);
define('ASEARCH_WHAT', 2);
define('ASEARCH_UNOP', 3);
define('ASEARCH_BIOP', 4);
define('ASEARCH_EXCLUDE', 5);
define('ASEARCH_SUB', 6);
define('ASEARCH_MAX', 7);
/** Name of session var
*/
define('ASEARCH_CRITERIA', 'criteria');
/** Builds a href with params
* @param string $params optional parameters to GET
*/
function asearch_get_href($params = '')
{
$href = 'search.php';
if ($params != '')
$href .= '?' . $params;
return $href;
}
/** Builds a [link]
* @param string $href (reference)
* @param string $text
* @param string $title
*/
function asearch_get_link(&$href, $text, $title = '')
{
if ($title != '')
$title = ' title="' . $title . '"';
return '' . $text . '';
}
/** Builds a toggle [link]
* @param integer $value
* @param string $action
* @param array $text_array
* @param array $title_array
*/
function asearch_get_toggle_link($value, $action, $text_array, $title_array = array())
{
$asearch_nz=asearch_nz($title_array[$value]);
$asearch_get_href=asearch_get_href($action . '=' . (int)$value);
return asearch_get_link($asearch_get_href, $text_array[$value], $asearch_nz);
}
/**
* @param string $a
* @param string $b
* @return bool strcoll()-like result
*/
function asearch_unhtml_strcoll($a, $b)
{
return strcoll(asearch_unhtmlentities($a), asearch_unhtmlentities($b));
}
/**
* @param string $mailbox mailbox name utf7 encoded inc. special case INBOX
* @return string mailbox name ready to display (utf7 decoded or localized INBOX)
*/
function imap_get_mailbox_display($mailbox)
{
if (strtoupper($mailbox) == 'INBOX')
return _("INBOX");
return imap_utf7_decode_local($mailbox);
}
/**
* @param string $mailbox mailbox name or special case 'All Folders'
* @return string mailbox name ready to display (utf7 decoded or localized 'All Folders')
*/
function asearch_get_mailbox_display($mailbox)
{
if ($mailbox == 'All Folders')
return _("All Folders");
return imap_get_mailbox_display($mailbox);
}
/**
* @param array $color color array
* @param string $txt text to display
* @return string title ready to display
*/
function asearch_get_title_display(&$color, $txt)
{
return '' . $txt . '';
}
/**
* @param array $color color array
* @param string $txt text to display
* @return string error text ready to display
*/
function asearch_get_error_display(&$color, $txt)
{
return '' . '' . $txt . '';
}
/**
* @param array $input_array array to serialize
* @return string a string containing a byte-stream representation of value that can be stored anywhere
*/
function asearch_serialize(&$input_array)
{
global $search_advanced;
if ($search_advanced)
return serialize($input_array);
return $input_array[0];
}
/**
* @param string $input_string string to unserialize
* @return array
*/
function asearch_unserialize($input_string)
{
global $search_advanced;
if ($search_advanced)
return unserialize($input_string);
return array($input_string);
}
/**
* @param string $key the pref key
* @param integer $index the pref key index
* @param string $default default value
* @return string pref value
*/
function asearch_getPref(&$key, $index, $default = '')
{
global $data_dir, $username, $search_advanced;
return getPref($data_dir, $username, $key . ($index + !$search_advanced), $default);
}
/**
* @param string $key the pref key
* @param integer $index the pref key index
* @param string $value pref value to set
* @return bool status
*/
function asearch_setPref(&$key, $index, $value)
{
global $data_dir, $username, $search_advanced;
return setPref($data_dir, $username, $key . ($index + !$search_advanced), $value);
}
/**
* @param string $key the pref key
* @param integer $index the pref key index
* @return bool status
*/
function asearch_removePref(&$key, $index)
{
global $data_dir, $username, $search_advanced;
return removePref($data_dir, $username, $key . ($index + !$search_advanced));
}
/** Sanity checks, done before running the imap command and before calling push_recent
*/
function asearch_check_query(&$where_array, &$what_array, &$exclude_array)
{
global $imap_asearch_opcodes;
if (empty($where_array))
return _("Please enter something to search for");
if (count($exclude_array) == count($where_array))
return _("There must be at least one criteria to search for");
for ($crit_num = 0; $crit_num < count($where_array); $crit_num++) {
$where = $where_array[$crit_num];
$what = $what_array[$crit_num];
if (!(($what == '') ^ ($imap_asearch_opcodes[$where] != '')))
return _("Error in criteria argument");
}
return '';
}
/** Read the recent searches from the prefs
*/
function asearch_read_recent()
{
global $recent_prefkeys, $search_memory;
$recent_array = array();
$recent_num = 0;
for ($pref_num = 0; $pref_num < $search_memory; $pref_num++) {
foreach ($recent_prefkeys as $prefkey) {
$pref = asearch_getPref($prefkey, $pref_num);
/* if (!empty($pref))*/
$recent_array[$prefkey][$recent_num] = $pref;
}
if (empty($recent_array[$recent_prefkeys[0]][$recent_num])) {
foreach ($recent_prefkeys as $key) {
array_pop($recent_array[$key]);
}
// break; //Disabled to support old search code broken prefs
}
else
$recent_num++;
}
return $recent_array;
}
/** Read the saved searches from the prefs
*/
function asearch_read_saved()
{
global $saved_prefkeys;
$saved_array = array();
$saved_key = $saved_prefkeys[0];
for ($saved_count = 0; ; $saved_count++) {
$pref = asearch_getPref($saved_key, $saved_count);
if (empty($pref))
break;
}
for ($saved_num = 0; $saved_num < $saved_count; $saved_num++) {
foreach ($saved_prefkeys as $key) {
$saved_array[$key][$saved_num] = asearch_getPref($key, $saved_num);
}
}
return $saved_array;
}
/** Save a recent search to the prefs
*/
function asearch_save_recent($recent_index)
{
global $recent_prefkeys, $saved_prefkeys;
$saved_array = asearch_read_saved();
$saved_index = count($saved_array[$saved_prefkeys[0]]);
$recent_array = asearch_read_recent();
$n = 0;
foreach ($recent_prefkeys as $key) {
$recent_slice = array_slice($recent_array[$key], $recent_index, 1);
if (!empty($recent_slice[0]))
asearch_setPref($saved_prefkeys[$n], $saved_index, $recent_slice[0]);
else
asearch_removePref($saved_prefkeys[$n], $saved_index);
$n++;
}
}
/** Write a recent search to prefs
*/
function asearch_write_recent(&$recent_array)
{
global $recent_prefkeys, $search_memory;
$recent_count = min($search_memory, count($recent_array[$recent_prefkeys[0]]));
for ($recent_num = 0; $recent_num < $recent_count; $recent_num++) {
foreach ($recent_prefkeys as $key) {
asearch_setPref($key, $recent_num, $recent_array[$key][$recent_num]);
}
}
for (; $recent_num < $search_memory; $recent_num++) {
foreach ($recent_prefkeys as $key) {
asearch_removePref($key, $recent_num);
}
}
}
/** Remove a recent search from prefs
*/
function asearch_forget_recent($forget_index)
{
global $recent_prefkeys;
$recent_array = asearch_read_recent();
foreach ($recent_prefkeys as $key) {
array_splice($recent_array[$key], $forget_index, 1);
}
asearch_write_recent($recent_array);
}
/** Find a recent search in the prefs (used to avoid saving duplicates)
*/
function asearch_find_recent(&$recent_array, &$mailbox_array, &$biop_array, &$unop_array, &$where_array, &$what_array, &$exclude_array, &$sub_array)
{
global $recent_prefkeys, $search_advanced;
$where_string = asearch_serialize($where_array);
$mailbox_string = asearch_serialize($mailbox_array);
$what_string = asearch_serialize($what_array);
$unop_string = asearch_serialize($unop_array);
if ($search_advanced) {
$biop_string = asearch_serialize($biop_array);
$exclude_string = asearch_serialize($exclude_array);
$sub_string = asearch_serialize($sub_array);
}
$recent_count = count($recent_array[$recent_prefkeys[ASEARCH_WHERE]]);
for ($recent_num = 0; $recent_num < $recent_count; $recent_num++) {
if (isset($recent_array[$recent_prefkeys[ASEARCH_WHERE]][$recent_num])) {
if (
$where_string == $recent_array[$recent_prefkeys[ASEARCH_WHERE]][$recent_num] &&
$mailbox_string == $recent_array[$recent_prefkeys[ASEARCH_MAILBOX]][$recent_num] &&
$what_string == $recent_array[$recent_prefkeys[ASEARCH_WHAT]][$recent_num] &&
$unop_string == $recent_array[$recent_prefkeys[ASEARCH_UNOP]][$recent_num] &&
((!$search_advanced) ||
($biop_string == $recent_array[$recent_prefkeys[ASEARCH_BIOP]][$recent_num] &&
$exclude_string == $recent_array[$recent_prefkeys[ASEARCH_EXCLUDE]][$recent_num] &&
$sub_string == $recent_array[$recent_prefkeys[ASEARCH_SUB]][$recent_num]))
)
return $recent_num;
}
}
return -1;
}
/** Push a recent search into the prefs
*/
function asearch_push_recent(&$mailbox_array, &$biop_array, &$unop_array, &$where_array, &$what_array, &$exclude_array, &$sub_array)
{
global $recent_prefkeys, $search_memory;
//global $what; // Hack to access issued search from read_body.php
$what = 1;
/**
* Update search history and store it in the session so we can retrieve the
* issued search when returning from an external page like read_body.php
*/
$criteria[$what] = array($mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array);
sqsession_register($criteria, ASEARCH_CRITERIA);
if ($search_memory > 0) {
$recent_array = asearch_read_recent();
$recent_found = asearch_find_recent($recent_array, $mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array);
if ($recent_found >= 0) { // Remove identical recent
foreach ($recent_prefkeys as $key) {
array_splice($recent_array[$key], $recent_found, 1);
}
}
$input = array($where_array, $mailbox_array, $what_array, $unop_array, $biop_array, $exclude_array, $sub_array);
$i = 0;
foreach ($recent_prefkeys as $key) {
array_unshift($recent_array[$key], asearch_serialize($input[$i]));
$i++;
}
asearch_write_recent($recent_array);
}
}
/** Edit a recent search
* @global array mailbox_array searched mailboxes
*/
function asearch_edit_recent($index)
{
global $recent_prefkeys, $search_advanced;
global $where_array, $mailbox_array, $what_array, $unop_array;
global $biop_array, $exclude_array, $sub_array;
$where_array = asearch_unserialize(asearch_getPref($recent_prefkeys[ASEARCH_WHERE], $index));
$mailbox_array = asearch_unserialize(asearch_getPref($recent_prefkeys[ASEARCH_MAILBOX], $index));
$what_array = asearch_unserialize(asearch_getPref($recent_prefkeys[ASEARCH_WHAT], $index));
$unop_array = asearch_unserialize(asearch_getPref($recent_prefkeys[ASEARCH_UNOP], $index));
if ($search_advanced) {
$biop_array = asearch_unserialize(asearch_getPref($recent_prefkeys[ASEARCH_BIOP], $index));
$exclude_array = asearch_unserialize(asearch_getPref($recent_prefkeys[ASEARCH_EXCLUDE], $index));
$sub_array = asearch_unserialize(asearch_getPref($recent_prefkeys[ASEARCH_SUB], $index));
}
}
/** Get last search criteria from session or prefs
* FIX ME, try to avoid globals
*/
function asearch_edit_last($index) {
if (sqGetGlobalVar(ASEARCH_CRITERIA, $criteria, SQ_SESSION)) {
global $where_array, $mailbox_array, $what_array, $unop_array;
global $biop_array, $exclude_array, $sub_array;
$mailbox_array = $criteria[$index][0];
$biop_array = $criteria[$index][1];
$unop_array = $criteria[$index][2];
$where_array = $criteria[$index][3];
$what_array = $criteria[$index][4];
$exclude_array = $criteria[$index][5];
$sub_array = $criteria[$index][6];
unset($criteria[$index]);
//sqsession_unregister(ASEARCH_CRITERIA);
} else {
global $search_memory;
if ($search_memory > 0) {
asearch_edit_recent(0);
}
}
}
/** Edit a saved search
*/
function asearch_edit_saved($index)
{
global $saved_prefkeys, $search_advanced;
global $where_array, $mailbox_array, $what_array, $unop_array;
global $biop_array, $exclude_array, $sub_array;
$where_array = asearch_unserialize(asearch_getPref($saved_prefkeys[ASEARCH_WHERE], $index));
$mailbox_array = asearch_unserialize(asearch_getPref($saved_prefkeys[ASEARCH_MAILBOX], $index));
$what_array = asearch_unserialize(asearch_getPref($saved_prefkeys[ASEARCH_WHAT], $index));
$unop_array = asearch_unserialize(asearch_getPref($saved_prefkeys[ASEARCH_UNOP], $index));
if ($search_advanced) {
$biop_array = asearch_unserialize(asearch_getPref($saved_prefkeys[ASEARCH_BIOP], $index));
$exclude_array = asearch_unserialize(asearch_getPref($saved_prefkeys[ASEARCH_EXCLUDE], $index));
$sub_array = asearch_unserialize(asearch_getPref($saved_prefkeys[ASEARCH_SUB], $index));
}
}
/** Write a saved search to the prefs
*/
function asearch_write_saved(&$saved_array)
{
global $saved_prefkeys;
$saved_count = count($saved_array[$saved_prefkeys[0]]);
for ($saved_num=0; $saved_num < $saved_count; $saved_num++) {
foreach ($saved_prefkeys as $key) {
asearch_setPref($key, $saved_num, $saved_array[$key][$saved_num]);
}
}
foreach ($saved_prefkeys as $key) {
asearch_removePref($key, $saved_count);
}
}
/** Delete a saved search from the prefs
*/
function asearch_delete_saved($saved_index)
{
global $saved_prefkeys;
$saved_array = asearch_read_saved();
$asearch_keys = $saved_prefkeys;
foreach ($asearch_keys as $key) {
array_splice($saved_array[$key], $saved_index, 1);
}
asearch_write_saved($saved_array);
}
/** Translate the input date to imap date to local date display,
* so the user can know if the date is wrong or illegal
* @return string locally formatted date or error text
*/
function asearch_get_date_display(&$what)
{
$what_parts = sqimap_asearch_parse_date($what);
if (count($what_parts) == 4) {
if (checkdate($what_parts[2], $what_parts[1], $what_parts[3]))
return date_intl(_("M j, Y"), mktime(0,0,0,$what_parts[2],$what_parts[1],$what_parts[3]));
//return $what_parts[1] . ' ' . getMonthName($what_parts[2]) . ' ' . $what_parts[3];
return _("(Illegal date)");
}
return _("(Wrong date)");
}
/** Translate the query to rough natural display
* @return string rough natural query ready to display
*/
function asearch_get_query_display(&$color, &$mailbox_array, &$biop_array, &$unop_array, &$where_array, &$what_array, &$exclude_array, &$sub_array)
{
global $imap_asearch_biops_in, $imap_asearch_biops, $imap_asearch_unops, $imap_asearch_options;
global $imap_asearch_opcodes;
$last_mailbox = $mailbox_array[0];
if (empty($last_mailbox))
$last_mailbox = 'INBOX';
$query_display = '';
for ($crit_num=0; $crit_num < count($where_array); $crit_num++) {
if ((!isset($exclude_array[$crit_num])) || (!$exclude_array[$crit_num])) {
$cur_mailbox = $mailbox_array[$crit_num];
if (empty($cur_mailbox))
$cur_mailbox = 'INBOX';
$biop = asearch_nz($biop_array[$crit_num]);
if (($query_display == '') || ($cur_mailbox != $last_mailbox)) {
$mailbox_display = ' ' . htmlspecialchars(asearch_get_mailbox_display($cur_mailbox)) . '';
if ($query_display == '')
$biop_display = _("In");
else
$biop_display = $imap_asearch_biops_in[$biop];
$last_mailbox = $cur_mailbox;
}
else {
$mailbox_display = '';
$biop_display = $imap_asearch_biops[$biop];
}
$unop = $unop_array[$crit_num];
$unop_display = $imap_asearch_unops[$unop];
if ($unop_display != '')
$unop_display .= ' ';
$where = $where_array[$crit_num];
$where_display = $unop_display . asearch_nz($imap_asearch_options[$where], $where);
$what_type = $imap_asearch_opcodes[$where];
$what = $what_array[$crit_num];
if ($what_type) { /* Check opcode parameter */
if ($what == '')
$what_display = ' ' . asearch_get_error_display($color, _("(Missing argument)"));
else {
if ($what_type == 'adate')
$what_display = asearch_get_date_display($what);
else
$what_display = htmlspecialchars($what);
$what_display = ' ' . $what_display . '';
}
}
else {
if ($what)
$what_display = ' ' . asearch_get_error_display($color, _("(Spurious argument)"));
else
$what_display = '';
}
if ($mailbox_display != '')
$query_display .= ' ' . $biop_display . '' . $mailbox_display . ' ' . $where_display . '' . $what_display;
else
$query_display .= ' ' . $biop_display . ' ' . $where_display . '' . $what_display;
}
}
return $query_display;
}
/**
* Creates button
*
* @deprecated see form functions available in 1.5.1 and 1.4.3.
* @param string $type
* @param string $name
* @param string $value
* @param string $js
* @param bool $enabled
*/
function getButton($type, $name, $value, $js = '', $enabled = TRUE) {
$disabled = ( $enabled ? '' : 'disabled ' );
$js = ( $js ? $js.' ' : '' );
return '';
}
/** Handle the alternate row colors
* @return string color value
*/
function asearch_get_row_color(&$color, $row_num)
{
/*$color_string = ($row_num%2 ? $color[0] : $color[4]);*/
$color_string = $color[4];
if ($GLOBALS['alt_index_colors']) {
if (($row_num % 2) == 0) {
if (!isset($color[12]))
$color[12] = '#EAEAEA';
$color_string = $color[12];
}
}
return $color_string;
}
/** Print a whole query array, recent or saved
*/
function asearch_print_query_array(&$boxes, &$query_array, &$query_keys, &$action_array, $title, $show_pref)
{
global $color;
global $data_dir, $username;
global $use_icons, $icon_theme;
$show_flag = getPref($data_dir, $username, $show_pref, 0) & 1;
$use_icons_flag = ($use_icons) && ($icon_theme != 'none');
if ($use_icons_flag)
$text_array = array('',
'');
else
$text_array = array('-', '+');
$toggle_link = asearch_get_toggle_link(!$show_flag, $show_pref, $text_array, array(_("Fold"), _("Unfold")));
if (!$use_icons_flag)
$toggle_link = '[' . $toggle_link . ']';
echo "
\n";
echo html_tag('table', '', 'center', $color[9], 'width="95%" cellpadding="1" cellspacing="1" border="0"');
echo html_tag('tr',
html_tag('td', $toggle_link, 'center', $color[5], 'width="5%"')
. html_tag('td', asearch_get_title_display($color, $title), 'center', $color[5], 'colspan=4'));
if ($show_flag) {
$main_key = $query_keys[ASEARCH_WHERE];
$query_count = count($query_array[$main_key]);
for ($query_num = 0, $row_num = 0; $query_num < $query_count; $query_num++) {
if (!empty($query_array[$main_key][$query_num])) {
echo html_tag('tr', '', '', asearch_get_row_color($color, $row_num));
unset($search_array);
foreach ($query_keys as $query_key) {
$search_array[] = asearch_unserialize($query_array[$query_key][$query_num]);
}
$where_array = $search_array[ASEARCH_WHERE];
$mailbox_array = $search_array[ASEARCH_MAILBOX];
$what_array = $search_array[ASEARCH_WHAT];
$unop_array = $search_array[ASEARCH_UNOP];
$biop_array = asearch_nz($search_array[ASEARCH_BIOP], array());
$exclude_array = asearch_nz($search_array[ASEARCH_EXCLUDE], array());
$sub_array = asearch_nz($search_array[ASEARCH_SUB], array());
$query_display = asearch_get_query_display($color, $mailbox_array, $biop_array, $unop_array, $where_array, $what_array, $exclude_array, $sub_array);
echo html_tag('td', $query_num + 1, 'right');
echo html_tag('td', $query_display, 'center', '', 'width="80%"');
foreach ($action_array as $action => $action_display) {
echo html_tag('td', '' . $action_display . '', 'center');
}
echo '' . "\n";
$row_num++;
}
}
}
echo '' . "\n";
}
/** Print the saved array
*/
function asearch_print_saved(&$boxes)
{
global $saved_prefkeys;
$saved_array = asearch_read_saved();
if (isset($saved_array[$saved_prefkeys[0]])) {
$saved_count = count($saved_array[$saved_prefkeys[0]]);
if ($saved_count > 0) {
$saved_actions = array('edit_saved' => _("Edit"), 'search_saved' => _("Search"), 'delete_saved' => _("Delete"));
asearch_print_query_array($boxes, $saved_array, $saved_prefkeys, $saved_actions, _("Saved Searches"), 'search_show_saved');
}
}
}
/**
* Print the recent array
*/
function asearch_print_recent(&$boxes)
{
global $recent_prefkeys, $search_memory;
$recent_array = asearch_read_recent();
if (isset($recent_array[$recent_prefkeys[0]])) {
$recent_count = count($recent_array[$recent_prefkeys[0]]);
if (min($recent_count, $search_memory) > 0) {
$recent_actions = array('save_recent' => _("save"), 'search_recent' => _("search"), 'forget_recent' => _("forget"));
asearch_print_query_array($boxes, $recent_array, $recent_prefkeys, $recent_actions, _("Recent Searches"), 'search_show_recent');
}
}
}
/** Build an ' . "\n";
}
/** Build a