Source for file imap_mailbox.php

Documentation is available at imap_mailbox.php

  1. <?php
  2.  
  3. /**
  4.  * imap_mailbox.php
  5.  *
  6.  * This implements all functions that manipulate mailboxes
  7.  *
  8.  * @copyright 1999-2014 The SquirrelMail Project Team
  9.  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  10.  * @version $Id: imap_mailbox.php 14422 2014-01-01 20:59:43Z pdontthink $
  11.  * @package squirrelmail
  12.  * @subpackage imap
  13.  */
  14.  
  15. /** UTF7 support */
  16. require_once(SM_PATH 'functions/imap_utf7_local.php');
  17.  
  18. global $boxesnew;
  19.  
  20. function sortSpecialMbx($a$b{
  21.     if ($a->is_inbox{
  22.         $acmp '0'$a->mailboxname_full;
  23.     else if ($a->is_special{
  24.         $acmp '1'$a->mailboxname_full;
  25.     else {
  26.         $acmp '2' $a->mailboxname_full;
  27.     }
  28.     if ($b->is_inbox{
  29.         $bcmp '0'$b->mailboxname_full;
  30.     }else if ($b->is_special{
  31.         $bcmp '1' $b->mailboxname_full;
  32.     else {
  33.         $bcmp '2' $b->mailboxname_full;
  34.     }
  35.     if ($acmp == $bcmpreturn 0;
  36.     return ($acmp $bcmp1: -1;
  37. }
  38.  
  39. function find_mailbox_name ($mailbox{
  40.     if (preg_match('/\*.+\"([^\r\n\"]*)\"[\s\r\n]*$/'$mailbox$regs))
  41.         return $regs[1];
  42.     if (preg_match('/ *"([^\r\n"]*)"[ \r\n]*$/'$mailbox$regs))
  43.         return $regs[1];
  44.     preg_match('/ *([^ \r\n"]*)[ \r\n]*$/',$mailbox,$regs);
  45.     return $regs[1];
  46. }
  47.  
  48. /**
  49.  * @return bool whether this is a Noselect mailbox.
  50.  */
  51. function check_is_noselect ($lsub_line{
  52.     return preg_match("/^\* (LSUB|LIST) \([^\)]*\\\\Noselect[^\)]*\)/i"$lsub_line);
  53. }
  54.  
  55. /**
  56.  * If $haystack is a full mailbox name, and $needle is the mailbox
  57.  * separator character, returns the second last part of the full
  58.  * mailbox name (i.e. the mailbox's parent mailbox)
  59.  */
  60. function readMailboxParent($haystack$needle{
  61.     if ($needle == ''{
  62.         $ret '';
  63.     else {
  64.         $parts explode($needle$haystack);
  65.         $elem array_pop($parts);
  66.         while ($elem == '' && count($parts)) {
  67.             $elem array_pop($parts);
  68.         }
  69.         $ret join($needle$parts);
  70.     }
  71.     return$ret );
  72. }
  73.  
  74. /**
  75.  * Check if $subbox is below the specified $parentbox
  76.  */
  77. function isBoxBelow$subbox$parentbox {
  78.     global $delimiter;
  79.     /*
  80.      * Eliminate the obvious mismatch, where the
  81.      * subfolder path is shorter than that of the potential parent
  82.      */
  83.     if strlen($subboxstrlen($parentbox) ) {
  84.       return false;
  85.     }
  86.     /* check for delimiter */
  87.         if (substr($parentbox,-1!= $delimiter{
  88.             $parentbox.=$delimiter;
  89.         }
  90.         if (substr($subbox,0,strlen($parentbox)) == $parentbox{
  91.             return true;
  92.         else {
  93.             return false;
  94.         }
  95. }
  96.  
  97. /**
  98.  * Defines special mailboxes: given a mailbox name, it checks if this is a
  99.  * "special" one: INBOX, Trash, Sent or Draft.
  100.  *
  101.  * Since 1.2.5 function includes special_mailbox hook.
  102.  *
  103.  * Since 1.4.3 hook supports more than one plugin.
  104.  *
  105. //FIXME: make $subfolders_of_inbox_are_special a configuration setting in conf.pl and config.php
  106.  * Since 1.4.22/1.5.2, the administrator can add
  107.  * $subfolders_of_inbox_are_special = TRUE;
  108.  * to config/config_local.php and all subfolders
  109.  * of the INBOX will be treated as special.
  110.  *
  111.  * @param string $box mailbox name
  112.  * @param boolean $include_subs (since 1.5.2 and 1.4.9) if true, subfolders of
  113.  *   system folders are special. if false, subfolders are not special mailboxes
  114.  *   unless they are tagged as special in 'special_mailbox' hook.
  115.  * @return boolean 
  116.  * @since 1.2.3
  117.  */
  118. function isSpecialMailbox($box,$include_subs=true{
  119.     global $subfolders_of_inbox_are_special;
  120.     $ret ( ($subfolders_of_inbox_are_special && isInboxMailbox($box,$include_subs)) ||
  121.              (!$subfolders_of_inbox_are_special && strtolower($box== 'inbox'||
  122.              isTrashMailbox($box,$include_subs|| 
  123.              isSentMailbox($box,$include_subs|| 
  124.              isDraftMailbox($box,$include_subs) );
  125.  
  126.     if !$ret {
  127.         $ret boolean_hook_function('special_mailbox',$box,1);
  128.     }
  129.     return $ret;
  130. }
  131.  
  132. /**
  133.  * Detects if mailbox is the Inbox folder or subfolder of the Inbox
  134.  *
  135.  * @param string $box The mailbox name to test
  136.  * @param boolean $include_subs If true, subfolders of system folders
  137.  *                               are special.  If false, subfolders are
  138.  *                               not special mailboxes.
  139.  *
  140.  * @return boolean Whether this is the Inbox or a child thereof.
  141.  *
  142.  * @since 1.4.22
  143.  */
  144. function isInboxMailbox($box$include_subs=TRUE{
  145.    return ((strtolower($box== 'inbox')
  146.         || ($include_subs && isBoxBelow(strtolower($box)'inbox')));
  147. }
  148.  
  149.  
  150. /**
  151.  * Detects if mailbox is a Trash folder or subfolder of Trash
  152.  * @param string $box mailbox name
  153.  * @param boolean $include_subs (since 1.5.2 and 1.4.9) if true, subfolders of
  154.  *   system folders are special. if false, subfolders are not special mailboxes.
  155.  * @return bool whether this is a Trash folder
  156.  * @since 1.4.0
  157.  */
  158. function isTrashMailbox ($box,$include_subs=true{
  159.     global $trash_folder$move_to_trash;
  160.     return $move_to_trash && $trash_folder &&
  161.            $box == $trash_folder || 
  162.              ($include_subs && isBoxBelow($box$trash_folder)) );
  163. }
  164.  
  165. /**
  166.  * Detects if mailbox is a Sent folder or subfolder of Sent
  167.  * @param string $box mailbox name
  168.  * @param boolean $include_subs (since 1.5.2 and 1.4.9) if true, subfolders of
  169.  *   system folders are special. if false, subfolders are not special mailboxes.
  170.  * @return bool whether this is a Sent folder
  171.  * @since 1.4.0
  172.  */
  173. function isSentMailbox($box,$include_subs=true{
  174.    global $sent_folder$move_to_sent;
  175.    return $move_to_sent && $sent_folder &&
  176.           $box == $sent_folder || 
  177.             ($include_subs && isBoxBelow($box$sent_folder)) );
  178. }
  179.  
  180. /**
  181.  * Detects if mailbox is a Drafts folder or subfolder of Drafts
  182.  * @param string $box mailbox name
  183.  * @param boolean $include_subs (since 1.5.2 and 1.4.9) if true, subfolders of
  184.  *   system folders are special. if false, subfolders are not special mailboxes.
  185.  * @return bool whether this is a Draft folder
  186.  * @since 1.4.0
  187.  */
  188. function isDraftMailbox($box,$include_subs=true{
  189.    global $draft_folder$save_as_draft;
  190.    return $save_as_draft &&
  191.           $box == $draft_folder || 
  192.             ($include_subs && isBoxBelow($box$draft_folder)) );
  193. }
  194.  
  195. /**
  196.  * Expunges a mailbox, ie. delete all contents.
  197.  */
  198. function sqimap_mailbox_expunge ($imap_stream$mailbox$handle_errors true$id=''{
  199.     global $uid_support;
  200.     if ($id{
  201.         if (is_array($id)) {
  202.             $id sqimap_message_list_squisher($id);
  203.         }
  204.         $id ' '.$id;
  205.         $uid $uid_support;
  206.     else {
  207.         $uid false;
  208.     }
  209.     $read sqimap_run_command($imap_stream'EXPUNGE'.$id$handle_errors,
  210.                                $response$message$uid);
  211.     $cnt 0;
  212.  
  213.     if (is_array($read)) {
  214.         foreach ($read as $r{
  215.             if (preg_match('/^\*\s[0-9]+\sEXPUNGE/AUi',$r,$regs)) {
  216.                 $cnt++;
  217.             }
  218.         }
  219.     }
  220.     return $cnt;
  221. }
  222.  
  223. /**
  224.  * Checks whether or not the specified mailbox exists
  225.  */
  226. function sqimap_mailbox_exists ($imap_stream$mailbox{
  227.     if (!isset($mailbox|| empty($mailbox)) {
  228.         return false;
  229.     }
  230.     $mbx sqimap_run_command($imap_stream"LIST \"\" \"$mailbox\"",
  231.                               true$response$message);
  232.     return isset($mbx[0]);
  233. }
  234.  
  235. /**
  236.  * Selects a mailbox
  237.  */
  238. function sqimap_mailbox_select ($imap_stream$mailbox{
  239.     global $auto_expunge;
  240.  
  241.     if (empty($mailbox)) {
  242.         return;
  243.     }
  244.  
  245.     /**
  246.      * Default UW IMAP server configuration allows to access other files
  247.      * on server. $imap_server_type is not checked because interface can
  248.      * be used with 'other' or any other server type setting. $mailbox
  249.      * variable can be modified in any script that uses variable from GET 
  250.      * or POST. This code blocks all standard SquirrelMail IMAP API requests 
  251.      * that use mailbox with full path (/etc/passwd) or with ../ characters 
  252.      * in path (../../etc/passwd)
  253.      */
  254.     if (strstr($mailbox'../'|| substr($mailbox01== '/'{
  255.         global $color;
  256.         include_once(SM_PATH 'functions/display_messages.php');
  257.         error_box(sprintf(_("Invalid mailbox name: %s"),sm_encode_html_special_chars($mailbox)),$color);
  258.         sqimap_logout($imap_stream);
  259.         die('</body></html>');
  260.     }
  261.  
  262.     // cleanup $mailbox in order to prevent IMAP injection attacks
  263.     $mailbox str_replace(array("\r","\n")array("",""),$mailbox);
  264.  
  265.     $read sqimap_run_command($imap_stream"SELECT \"$mailbox\"",
  266.                                true$response$message);
  267.     $result array();
  268.     for ($i 0$cnt count($read)$i $cnt$i++{
  269.         if (preg_match('/^\*\s+OK\s\[(\w+)\s(\w+)\]/',$read[$i]$regs)) {
  270.             $result[strtoupper($regs[1])$regs[2];
  271.         else if (preg_match('/^\*\s([0-9]+)\s(\w+)/',$read[$i]$regs)) {
  272.             $result[strtoupper($regs[2])$regs[1];
  273.         else {
  274.             if (preg_match("/PERMANENTFLAGS(.*)/i",$read[$i]$regs)) {
  275.                 $regs[1]=trim(preg_replace (  array ("/\(/","/\)/","/\]/",''$regs[1])) ;
  276.                 $result['PERMANENTFLAGS'$regs[1];
  277.             else if (preg_match("/FLAGS(.*)/i",$read[$i]$regs)) {
  278.                 $regs[1]=trim(preg_replace (  array ("/\(/","/\)/",''$regs[1])) ;
  279.                 $result['FLAGS'$regs[1];
  280.             }
  281.         }
  282.     }
  283.     if (preg_match('/^\[(.+)\]/',$message$regs)) {
  284.         $result['RIGHTS']=$regs[1];
  285.     }
  286.  
  287.     if ($auto_expunge{
  288.         $tmp sqimap_run_command($imap_stream'EXPUNGE'false$a$b);
  289.     }
  290.     return $result;
  291. }
  292.  
  293. /**
  294.  * Creates a folder.
  295.  */
  296. function sqimap_mailbox_create ($imap_stream$mailbox$type{
  297.     global $delimiter;
  298.     if (strtolower($type== 'noselect'{
  299.         $create_mailbox $mailbox $delimiter;
  300.     else {
  301.         $create_mailbox $mailbox;
  302.     }
  303.  
  304.     $read_ary sqimap_run_command($imap_stream"CREATE \"$create_mailbox\"",
  305.                                    true$response$message);
  306.     sqimap_subscribe ($imap_stream$mailbox);
  307. }
  308.  
  309. /**
  310.  * Subscribes to an existing folder.
  311.  */
  312. function sqimap_subscribe ($imap_stream$mailbox{
  313.     $read_ary sqimap_run_command($imap_stream"SUBSCRIBE \"$mailbox\"",
  314.                                    true$response$message);
  315. }
  316.  
  317. /**
  318.  * Unsubscribes from an existing folder
  319.  */
  320. function sqimap_unsubscribe ($imap_stream$mailbox{
  321.     $read_ary sqimap_run_command($imap_stream"UNSUBSCRIBE \"$mailbox\"",
  322.                                    false$response$message);
  323. }
  324.  
  325. /**
  326.  * Deletes the given folder
  327.  */
  328. function sqimap_mailbox_delete ($imap_stream$mailbox{
  329.     global $data_dir$username;
  330.     sqimap_unsubscribe ($imap_stream$mailbox);
  331.     if (sqimap_mailbox_exists($imap_stream$mailbox)) {
  332.         $read_ary sqimap_run_command($imap_stream"DELETE \"$mailbox\"",
  333.                                        true$response$message);
  334.         if ($response !== 'OK'{
  335.             // subscribe again
  336.             sqimap_subscribe ($imap_stream$mailbox);
  337.         else {
  338.             do_hook_function('rename_or_delete_folder'$args array($mailbox'delete'''));
  339.             removePref($data_dir$username"thread_$mailbox");
  340.             removePref($data_dir$username"collapse_folder_$mailbox");
  341.         }
  342.     }
  343. }
  344.  
  345. /**
  346.  * Determines if the user is subscribed to the folder or not
  347.  */
  348. function sqimap_mailbox_is_subscribed($imap_stream$folder{
  349.     $boxesall sqimap_mailbox_list ($imap_stream);
  350.     foreach ($boxesall as $ref{
  351.         if ($ref['unformatted'== $folder{
  352.             return true;
  353.         }
  354.     }
  355.     return false;
  356. }
  357.  
  358. /**
  359.  * Renames a mailbox.
  360.  */
  361. function sqimap_mailbox_rename$imap_stream$old_name$new_name {
  362.     if $old_name != $new_name {
  363.         global $delimiter$imap_server_type$data_dir$username;
  364.         if substr$old_name-== $delimiter  {
  365.             $old_name substr$old_name0strlen$old_name );
  366.             $new_name substr$new_name0strlen$new_name );
  367.             $postfix $delimiter;
  368.         else {
  369.             $postfix '';
  370.         }
  371.  
  372.         $boxesall sqimap_mailbox_list_all($imap_stream);
  373.         $cmd 'RENAME "' $old_name '" "' $new_name '"';
  374.         $data sqimap_run_command($imap_stream$cmdtrue$response$message);
  375.         sqimap_unsubscribe($imap_stream$old_name.$postfix);
  376.         $oldpref_thread getPref($data_dir$username'thread_'.$old_name.$postfix);
  377.         $oldpref_collapse getPref($data_dir$username'collapse_folder_'.$old_name.$postfix);
  378.         removePref($data_dir$username'thread_'.$old_name.$postfix);
  379.         removePref($data_dir$username'collapse_folder_'.$old_name.$postfix);
  380.         sqimap_subscribe($imap_stream$new_name.$postfix);
  381.         setPref($data_dir$username'thread_'.$new_name.$postfix$oldpref_thread);
  382.         setPref($data_dir$username'collapse_folder_'.$new_name.$postfix$oldpref_collapse);
  383.         do_hook_function('rename_or_delete_folder',$args array($old_name'rename'$new_name));
  384.         $l strlen$old_name 1;
  385.         $p 'unformatted';
  386.  
  387.         foreach ($boxesall as $box{
  388.             if (substr($box[$p]0$l== $old_name $delimiter{
  389.                 $new_sub $new_name $delimiter substr($box[$p]$l);
  390.                 /* With Cyrus IMAPd >= 2.0 rename is recursive, so don't check for errors here */
  391.                 if ($imap_server_type == 'cyrus'{
  392.                     $cmd 'RENAME "' $box[$p'" "' $new_sub '"';
  393.                     $data sqimap_run_command($imap_stream$cmdfalse,
  394.                                                $response$message);
  395.                 }
  396.                 $was_subscribed sqimap_mailbox_is_subscribed($imap_stream$box[$p]);
  397.                 if $was_subscribed {
  398.                     sqimap_unsubscribe($imap_stream$box[$p]);
  399.                 }
  400.                 $oldpref_thread getPref($data_dir$username'thread_'.$box[$p]);
  401.                 $oldpref_collapse getPref($data_dir$username'collapse_folder_'.$box[$p]);
  402.                 removePref($data_dir$username'thread_'.$box[$p]);
  403.                 removePref($data_dir$username'collapse_folder_'.$box[$p]);
  404.                 if $was_subscribed {
  405.                     sqimap_subscribe($imap_stream$new_sub);
  406.                 }
  407.                 setPref($data_dir$username'thread_'.$new_sub$oldpref_thread);
  408.                 setPref($data_dir$username'collapse_folder_'.$new_sub$oldpref_collapse);
  409.                 do_hook_function('rename_or_delete_folder',
  410.                                  $args array($box[$p]'rename'$new_sub));
  411.             }
  412.         }
  413.     }
  414. }
  415.  
  416. /**
  417.  * Formats a mailbox into parts for the $boxesall array
  418.  *
  419.  * The parts are:
  420.  *
  421.  *     raw            - Raw LIST/LSUB response from the IMAP server
  422.  *     formatted      - nicely formatted folder name
  423.  *     unformatted    - unformatted, but with delimiter at end removed
  424.  *     unformatted-dm - folder name as it appears in raw response
  425.  *     unformatted-disp - unformatted without $folder_prefix
  426.  */
  427. function sqimap_mailbox_parse ($line$line_lsub{
  428.     global $folder_prefix$delimiter;
  429.  
  430.     /* Process each folder line */
  431.     for ($g 0$cnt count($line)$g $cnt++$g{
  432.         /* Store the raw IMAP reply */
  433.         if (isset($line[$g])) {
  434.             $boxesall[$g]['raw'$line[$g];
  435.         else {
  436.             $boxesall[$g]['raw''';
  437.         }
  438.  
  439.         /* Count number of delimiters ($delimiter) in folder name */
  440.         $mailbox  $line_lsub[$g];
  441.         $dm_count substr_count($mailbox$delimiter);
  442.         if (substr($mailbox-1== $delimiter{
  443.             /* If name ends in delimiter, decrement count by one */
  444.             $dm_count--;
  445.         }
  446.  
  447.         /* Format folder name, but only if it's a INBOX.* or has a parent. */
  448.         $boxesallbyname[$mailbox$g;
  449.         $parentfolder readMailboxParent($mailbox$delimiter);
  450.         if ( (strtolower(substr($mailbox05)) == "inbox"||
  451.              (substr($mailbox0strlen($folder_prefix)) == $folder_prefix||
  452.              (isset($boxesallbyname[$parentfolder]&&
  453.               (strlen($parentfolder0) ) ) {
  454.             $indent $dm_count (substr_count($folder_prefix$delimiter));
  455.             if ($indent 0{
  456.                 $boxesall[$g]['formatted'str_repeat('&nbsp;&nbsp;'$indent);
  457.             else {
  458.                 $boxesall[$g]['formatted''';
  459.             }
  460.             $boxesall[$g]['formatted'.= imap_utf7_decode_local(readShortMailboxName($mailbox$delimiter));
  461.         else {
  462.             $boxesall[$g]['formatted']  imap_utf7_decode_local($mailbox);
  463.         }
  464.  
  465.         $boxesall[$g]['unformatted-dm'$mailbox;
  466.         if (substr($mailbox-1== $delimiter{
  467.             $mailbox substr($mailbox0strlen($mailbox1);
  468.         }
  469.         $boxesall[$g]['unformatted'$mailbox;
  470.         if (substr($mailbox,0,strlen($folder_prefix))==$folder_prefix{
  471.             $mailbox substr($mailboxstrlen($folder_prefix));
  472.         }
  473.         $boxesall[$g]['unformatted-disp'$mailbox;
  474.         $boxesall[$g]['id'$g;
  475.  
  476.         $boxesall[$g]['flags'array();
  477.         if (isset($line[$g])) {
  478.             if preg_match('/\(([^)]*)\)/',$line[$g],$regs) ) {
  479.                 $flags trim(strtolower(str_replace('\\''',$regs[1])));
  480.                 if ($flags{
  481.                     $boxesall[$g]['flags'explode(' '$flags);
  482.                 }
  483.             }
  484.         }
  485.     }
  486.     return $boxesall;
  487. }
  488.  
  489. /**
  490.  * Sorting function used to sort mailbox names.
  491.  *     + Original patch from dave_michmerhuizen@yahoo.com
  492.  *     + Allows case insensitivity when sorting folders
  493.  *     + Takes care of the delimiter being sorted to the end, causing
  494.  *       subfolders to be listed in below folders that are prefixed
  495.  *       with their parent folders name.
  496.  *
  497.  *       For example: INBOX.foo, INBOX.foobar, and INBOX.foo.bar
  498.  *       Without special sort function: foobar between foo and foo.bar
  499.  *       With special sort function: foobar AFTER foo and foo.bar :)
  500.  */
  501. function user_strcasecmp($a$b{
  502.     return  strnatcasecmp($a$b);
  503. }
  504.  
  505. /**
  506.  * Returns list of options (to be echoed into select statement
  507.  * based on available mailboxes and separators
  508.  * Caller should surround options with <select ...> </select> and
  509.  * any formatting.
  510.  *   $imap_stream - $imapConnection to query for mailboxes
  511.  *   $show_selected - array containing list of mailboxes to pre-select (0 if none)
  512.  *   $folder_skip - array of folders to keep out of option list (compared in lower)
  513.  *   $boxes - list of already fetched boxes (for places like folder panel, where
  514.  *            you know these options will be shown 3 times in a row.. (most often unset).
  515.  *   $flag - flag to check for in mailbox flags, used to filter out mailboxes.
  516.  *           'noselect' by default to remove unselectable mailboxes.
  517.  *           'noinferiors' used to filter out folders that can not contain subfolders.
  518.  *           NULL to avoid flag check entirely.
  519.  *   $use_long_format - override folder display preference and always show full folder name.
  520.  */
  521. function sqimap_mailbox_option_list($imap_stream$show_selected 0$folder_skip 0$boxes 0,
  522.                                     $flag 'noselect'$use_long_format false {
  523.     global $username$data_dir;
  524.     $mbox_options '';
  525.     if $use_long_format {
  526.         $shorten_box_names 0;
  527.     else {
  528.         $shorten_box_names getPref($data_dir$username'mailbox_select_style'1);
  529.     }
  530.  
  531.     if ($boxes == 0{
  532.         $boxes sqimap_mailbox_list($imap_stream);
  533.     }
  534.  
  535.     foreach ($boxes as $boxes_part{
  536.         if ($flag == NULL || !in_array($flag$boxes_part['flags'])) {
  537.             $box $boxes_part['unformatted'];
  538.  
  539.             if ($folder_skip != && in_array($box$folder_skip) ) {
  540.                 continue;
  541.             }
  542.             $lowerbox strtolower($box);
  543.             // mailboxes are casesensitive => inbox.sent != inbox.Sent
  544.             // nevermind, to many dependencies this should be fixed!
  545.  
  546.             if (strtolower($box== 'inbox'// inbox is special and not casesensitive
  547.                 $box2 _("INBOX");
  548.             else {
  549.                 switch ($shorten_box_names)
  550.                 {
  551.                   case 2:   /* delimited, style = 2 */
  552.                     $box2 str_replace('&nbsp;&nbsp;''.&nbsp;'$boxes_part['formatted']);
  553.                     break;
  554.                   case 1:   /* indent, style = 1 */
  555.                     $box2 $boxes_part['formatted'];
  556.                     break;
  557.                   default:  /* default, long names, style = 0 */
  558.                     $box2 str_replace(' ''&nbsp;'sm_encode_html_special_chars(imap_utf7_decode_local($boxes_part['unformatted-disp'])));
  559.                     break;
  560.                 }
  561.             }
  562.             $box2 str_replace(array('<','>')array('&lt;','&gt;'$box2);
  563.  
  564.             if ($show_selected != && in_array($lowerbox$show_selected) ) {
  565.                 $mbox_options .= '<option value="' sm_encode_html_special_chars($box.'" selected="selected">'.$box2.'</option>' "\n";
  566.             else {
  567.                 $mbox_options .= '<option value="' sm_encode_html_special_chars($box.'">'.$box2.'</option>' "\n";
  568.             }
  569.         }
  570.     }
  571.     return $mbox_options;
  572. }
  573.  
  574. /**
  575.  * Mailboxes with some chars (like -) can mess up the order, this fixes it
  576.  */
  577. function mailtree_sort(&$lsub{
  578.     if(!is_array($lsub)) return;
  579.     
  580.     global $delimiter;
  581.     
  582.     foreach($lsub as $index => $mailbox)
  583.         $lsub[$indexstr_replace($delimiter,' -#- ',$lsub[$index]);
  584.  
  585.     usort($lsub'user_strcasecmp');
  586.  
  587.     foreach($lsub as $index => $mailbox)
  588.         $lsub[$indexstr_replace(' -#- ',$delimiter,$lsub[$index]);
  589. }
  590.  
  591. /**
  592.  * Returns sorted mailbox lists in several different ways.
  593.  * See comment on sqimap_mailbox_parse() for info about the returned array.
  594.  */
  595.  
  596.  
  597. function sqimap_mailbox_list($imap_stream$force=false{
  598.  
  599.     if (!sqgetGlobalVar('boxesnew',$boxesnew,SQ_SESSION|| $force{
  600.         global $data_dir$username$list_special_folders_first,
  601.                $folder_prefix$trash_folder$sent_folder$draft_folder,
  602.                $move_to_trash$move_to_sent$save_as_draft,
  603.                $delimiter$noselect_fix_enable;
  604.         $inbox_in_list false;
  605.         $inbox_subscribed false;
  606.  
  607.         require_once(SM_PATH 'include/load_prefs.php');
  608.  
  609.         if ($noselect_fix_enable{
  610.             $lsub_args "LSUB \"$folder_prefix\" \"*%\"";
  611.         else {
  612.             $lsub_args "LSUB \"$folder_prefix\" \"*\"";
  613.         }
  614.         /* LSUB array */
  615.         $lsub_ary sqimap_run_command ($imap_stream$lsub_args,
  616.                                         true$response$message);
  617.  
  618.         $sorted_lsub_ary array();
  619.         for ($i 0$cnt count($lsub_ary);$i $cnt$i++{
  620.             /*
  621.              * Workaround for mailboxes returned as literal
  622.              * Doesn't work if the mailbox name is multiple lines
  623.              * (larger then fgets buffer)
  624.              */
  625.             if (isset($lsub_ary[$i 1]&& substr($lsub_ary[$i],-3== "}\r\n"{
  626.                 if (preg_match('/^(\* [A-Z]+.*)\{[0-9]+\}([ \n\r\t]*)$/',
  627.                      $lsub_ary[$i]$regs)) {
  628.                         $i++;
  629.                         $lsub_ary[$i$regs[1'"' addslashes(trim($lsub_ary[$i])) '"' $regs[2];
  630.                 }
  631.             }
  632.             $temp_mailbox_name find_mailbox_name($lsub_ary[$i]);
  633.             $sorted_lsub_ary[$temp_mailbox_name;
  634.             if (!$inbox_subscribed && strtoupper($temp_mailbox_name== 'INBOX'{
  635.                 $inbox_subscribed true;
  636.             }
  637.         }
  638.         /* remove duplicates */
  639.         $sorted_lsub_ary array_unique($sorted_lsub_ary);
  640.        
  641.         /* natural sort mailboxes */
  642.         if (isset($sorted_lsub_ary)) {
  643.             mailtree_sort($sorted_lsub_ary);
  644.         }
  645.         /*
  646.          * The LSUB response doesn't provide us information about \Noselect
  647.          * mail boxes. The LIST response does, that's why we need to do a LIST
  648.          * call to retrieve the flags for the mailbox
  649.            * Note: according RFC2060 an imap server may provide \NoSelect flags in the LSUB response.
  650.            * in other words, we cannot rely on it.
  651.          */
  652.         if ($noselect_fix_enable{
  653.             $list_args "LIST \"$folder_prefix\" \"*%\"";
  654.         else {
  655.             $list_args "LIST \"$folder_prefix\" \"*\"";
  656.         }
  657.         /* LIST array */
  658.         $list_ary sqimap_run_command ($imap_stream$list_args,
  659.                                         true$response$message);
  660.         $sorted_list_ary array();
  661.         for ($i 0$cnt count($list_ary);$i $cnt$i++{
  662.             /*
  663.              * Workaround for mailboxes returned as literal
  664.              * Doesn't work if the mailbox name is multiple lines
  665.              * (larger then fgets buffer)
  666.              */
  667.             if (isset($list_ary[$i 1]&& substr($list_ary[$i],-3== "}\r\n"{
  668.                 if (preg_match('/^(\* [A-Z]+.*)\{[0-9]+\}([ \n\r\t]*)$/',
  669.                      $list_ary[$i]$regs)) {
  670.                         $i++;
  671.                         $list_ary[$i$regs[1'"' addslashes(trim($list_ary[$i])) '"' $regs[2];
  672.                 }
  673.             }
  674.             $temp_mailbox_name find_mailbox_name($list_ary[$i]);
  675.  
  676.             // is_numeric() because before PHP 4.2.0, bad return
  677.             // value is NULL; whereas in newer versions, it's FALSE
  678.             if (is_numeric($key array_search($temp_mailbox_name$sorted_lsub_ary))) {
  679.                 $sorted_list_ary[$key$list_ary[$i];
  680.             }
  681.         }
  682.  
  683.         /*
  684.          * Just in case they're not subscribed to their inbox,
  685.          * we'll get it for them anyway
  686.          */
  687.         if (!$inbox_subscribed{
  688.             $inbox_ary sqimap_run_command ($imap_stream"LIST \"\" \"INBOX\"",
  689.                                              true$response$message);
  690.             /* Another workaround for literals */
  691.             if (isset($inbox_ary[1]&& substr($inbox_ary[0],-3== "}\r\n"{
  692.                 if (preg_match('/^(\* [A-Z]+.*)\{[0-9]+\}([ \n\r\t]*)$/',
  693.                      $inbox_ary[0]$regs)) {
  694.                     $inbox_ary[0$regs[1'"' addslashes(trim($inbox_ary[1])) .
  695.                                 '"' $regs[2];
  696.                 }
  697.             }
  698.             $sorted_list_ary[$inbox_ary[0];
  699.             $sorted_lsub_ary[find_mailbox_name($inbox_ary[0]);
  700.         }
  701.  
  702.         $boxesall sqimap_mailbox_parse ($sorted_list_ary$sorted_lsub_ary);
  703.  
  704.         /* Now, lets sort for special folders */
  705.         $boxesnew $used array();
  706.  
  707.         /* Find INBOX */
  708.         $cnt count($boxesall);
  709.         $used array_pad($used,$cnt,false);
  710.         for($k 0$k $cnt++$k{
  711.             if (strtolower($boxesall[$k]['unformatted']== 'inbox'{
  712.                 $boxesnew[$boxesall[$k];
  713.                 $used[$ktrue;
  714.                 break;
  715.             }
  716.         }
  717.  
  718.         /* 
  719.          * For systems where folders might be either under the INBOX or
  720.          * at the top-level (Dovecot, hMailServer), INBOX subfolders have
  721.          * to be added before special folders
  722.          */
  723.         if (!$default_sub_of_inbox{
  724.             for($k 0$k $cnt++$k{
  725.                 if (!$used[$k&& isBoxBelow(strtolower($boxesall[$k]['unformatted'])'inbox'&&
  726.                     strtolower($boxesall[$k]['unformatted']!= 'inbox'{
  727.                     $boxesnew[$boxesall[$k];
  728.                     $used[$ktrue;
  729.                 }
  730.             }
  731.         }
  732.  
  733.  
  734.         /* List special folders and their subfolders, if requested. */
  735.         if ($list_special_folders_first{
  736.             for($k 0$k $cnt++$k{
  737.                 if (!$used[$k&& isSpecialMailbox($boxesall[$k]['unformatted'])) {
  738.                     $boxesnew[$boxesall[$k];
  739.                     $used[$k]   true;
  740.                 }
  741.             }
  742.         }
  743.  
  744.  
  745.         /* Find INBOX's children for systems where folders are ONLY under INBOX */
  746.         if ($default_sub_of_inbox{
  747.             for($k 0$k $cnt++$k{
  748.                 if (!$used[$k&& isBoxBelow(strtolower($boxesall[$k]['unformatted'])'inbox'&&
  749.                     strtolower($boxesall[$k]['unformatted']!= 'inbox'{
  750.                     $boxesnew[$boxesall[$k];
  751.                     $used[$ktrue;
  752.                 }
  753.             }
  754.         }
  755.  
  756.  
  757.         /* Rest of the folders */
  758.         for($k 0$k $cnt$k++{
  759.             if (!$used[$k]{
  760.                 $boxesnew[$boxesall[$k];
  761.             }
  762.         }
  763.         sqsession_register($boxesnew,'boxesnew');
  764.     }
  765.     return $boxesnew;
  766. }
  767.  
  768. /**
  769.  *  Returns a list of all folders, subscribed or not
  770.  */
  771. function sqimap_mailbox_list_all($imap_stream{
  772.     global $list_special_folders_first$folder_prefix$delimiter;
  773.  
  774.     $ssid sqimap_session_id();
  775.     $lsid strlen$ssid );
  776.     fputs ($imap_stream$ssid " LIST \"$folder_prefix\" *\r\n");
  777.     $read_ary sqimap_read_data ($imap_stream$ssidtrue$response$message);
  778.     $g 0;
  779.     $phase 'inbox';
  780.     $fld_pre_length strlen($folder_prefix);
  781.  
  782.     for ($i 0$cnt count($read_ary)$i $cnt$i++{
  783.         /* Another workaround for EIMS */
  784.         if (isset($read_ary[$i 1]&&
  785.             preg_match('/^(\* [A-Z]+.*)\{[0-9]+\}([ \n\r\t]*)$/',
  786.                  $read_ary[$i]$regs)) {
  787.             $i ++;
  788.             $read_ary[$i$regs[1'"' addslashes(trim($read_ary[$i])) '"' $regs[2];
  789.         }
  790.         if (substr($read_ary[$i]0$lsid!= $ssid {
  791.             /* Store the raw IMAP reply */
  792.             $boxes[$g]['raw'$read_ary[$i];
  793.  
  794.             /* Count number of delimiters ($delimiter) in folder name */
  795.             $mailbox find_mailbox_name($read_ary[$i]);
  796.             $dm_count =  substr_count($mailbox$delimiter);
  797.             if (substr($mailbox-1== $delimiter{
  798.                 /* If name ends in delimiter - decrement count by one */
  799.                 $dm_count--;
  800.             }
  801.  
  802.             /* Format folder name, but only if it's a INBOX.* or has a parent. */
  803.             $boxesallbyname[$mailbox$g;
  804.             $parentfolder readMailboxParent($mailbox$delimiter);
  805.             /* @FIXME shouldn't use preg_match for simple string matching */
  806.             if((preg_match('|^inbox'.quotemeta($delimiter).'|i'$mailbox)) ||
  807.                (preg_match('|^'.$folder_prefix.'|'$mailbox)) ||
  808.                isset($boxesallbyname[$parentfolder]&& (strlen($parentfolder0) ) ) {
  809.                 if ($dm_count{
  810.                     $boxes[$g]['formatted']  str_repeat('&nbsp;&nbsp;'$dm_count);
  811.                 else {
  812.                     $boxes[$g]['formatted''';
  813.                 }
  814.                 $boxes[$g]['formatted'.= imap_utf7_decode_local(readShortMailboxName($mailbox$delimiter));
  815.             else {
  816.                 $boxes[$g]['formatted']  imap_utf7_decode_local($mailbox);
  817.             }
  818.  
  819.             $boxes[$g]['unformatted-dm'$mailbox;
  820.             if (substr($mailbox-1== $delimiter{
  821.                 $mailbox substr($mailbox0strlen($mailbox1);
  822.             }
  823.             $boxes[$g]['unformatted'$mailbox;
  824.             $boxes[$g]['unformatted-disp'substr($mailbox,$fld_pre_length);
  825.  
  826.             $boxes[$g]['id'$g;
  827.  
  828.             /* Now lets get the flags for this mailbox */
  829.             $read_mlbx $read_ary[$i];
  830.  
  831. //            $read_mlbx = sqimap_run_command ($imap_stream, "LIST \"\" \"$mailbox\"",
  832. //                                             true, $response, $message);
  833.  
  834.             /* Another workaround for EIMS */
  835. //            if (isset($read_mlbx[1]) &&
  836. //                preg_match('/^(\* [A-Z]+.*)\{[0-9]+\}([ \n\r\t]*)$/', $read_mlbx[0], $regs)) {
  837. //                $read_mlbx[0] = $regs[1] . '"' . addslashes(trim($read_mlbx[1])) . '"' . $regs[2];
  838. //            }
  839. //            echo  $read_mlbx[0] .' raw 2 <br>';
  840.  
  841.             $flags substr($read_mlbxstrpos($read_mlbx'(')+1);
  842.             $flags substr($flags0strpos($flags')'));
  843.             $flags str_replace('\\'''$flags);
  844.             $flags trim(strtolower($flags));
  845.             if ($flags{
  846.                 $boxes[$g]['flags'explode(' '$flags);
  847.             else {
  848.                 $boxes[$g]['flags'array();
  849.             }
  850.         }
  851.         $g++;
  852.     }
  853.     if(is_array($boxes)) {
  854.         sort ($boxes);
  855.     }
  856.  
  857.     return $boxes;
  858. }

Documentation generated on Sat, 20 Dec 2014 04:21:04 +0100 by phpDocumentor 1.4.3