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-2017 The SquirrelMail Project Team
  9.  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  10.  * @version $Id: imap_mailbox.php 14728 2017-11-18 21:39:52Z 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.  * @param boolean $handle_errors When TRUE, IMAP errors
  239.  *                                are handled herein, causing
  240.  *                                an error to be displayed on
  241.  *                                screen and execution to stop
  242.  *                                and when FALSE, error status
  243.  *                                is returned to the caller
  244.  *                                (OPTIONAL; default is TRUE)
  245.  * @return mixed Void/unpredictable when handling errors internally
  246.  *                or an array when $handle_errors is false; in that
  247.  *                case, good responses are returned in an array,
  248.  *                bad ones with an empty array.
  249.  */
  250. function sqimap_mailbox_select ($imap_stream$mailbox$handle_errors=true{
  251.     global $auto_expunge;
  252.  
  253.     if (empty($mailbox)) {
  254.         return;
  255.     }
  256.  
  257.     /**
  258.      * Default UW IMAP server configuration allows to access other files
  259.      * on server. $imap_server_type is not checked because interface can
  260.      * be used with 'other' or any other server type setting. $mailbox
  261.      * variable can be modified in any script that uses variable from GET 
  262.      * or POST. This code blocks all standard SquirrelMail IMAP API requests 
  263.      * that use mailbox with full path (/etc/passwd) or with ../ characters 
  264.      * in path (../../etc/passwd)
  265.      */
  266.     if (strstr($mailbox'../'|| substr($mailbox01== '/'{
  267.         global $color;
  268.         include_once(SM_PATH 'functions/display_messages.php');
  269.         error_box(sprintf(_("Invalid mailbox name: %s"),sm_encode_html_special_chars($mailbox)),$color);
  270.         sqimap_logout($imap_stream);
  271.         die('</body></html>');
  272.     }
  273.  
  274.     // cleanup $mailbox in order to prevent IMAP injection attacks
  275.     $mailbox str_replace(array("\r","\n")array("",""),$mailbox);
  276.  
  277.     $read sqimap_run_command($imap_stream"SELECT \"$mailbox\"",
  278.                                $handle_errors$response$message);
  279.     $result array();
  280.     for ($i 0$cnt count($read)$i $cnt$i++{
  281.         if (preg_match('/^\*\s+OK\s\[(\w+)\s(\w+)\]/',$read[$i]$regs)) {
  282.             $result[strtoupper($regs[1])$regs[2];
  283.         else if (preg_match('/^\*\s([0-9]+)\s(\w+)/',$read[$i]$regs)) {
  284.             $result[strtoupper($regs[2])$regs[1];
  285.         else {
  286.             if (preg_match("/PERMANENTFLAGS(.*)/i",$read[$i]$regs)) {
  287.                 $regs[1]=trim(preg_replace (  array ("/\(/","/\)/","/\]/",''$regs[1])) ;
  288.                 $result['PERMANENTFLAGS'$regs[1];
  289.             else if (preg_match("/FLAGS(.*)/i",$read[$i]$regs)) {
  290.                 $regs[1]=trim(preg_replace (  array ("/\(/","/\)/",''$regs[1])) ;
  291.                 $result['FLAGS'$regs[1];
  292.             }
  293.         }
  294.     }
  295.     if (preg_match('/^\[(.+)\]/',$message$regs)) {
  296.         $result['RIGHTS']=$regs[1];
  297.     }
  298.  
  299.     if ($auto_expunge{
  300.         $tmp sqimap_run_command($imap_stream'EXPUNGE'false$a$b);
  301.     }
  302.     return $result;
  303. }
  304.  
  305. /**
  306.  * Creates a folder.
  307.  */
  308. function sqimap_mailbox_create ($imap_stream$mailbox$type{
  309.     global $delimiter;
  310.     if (strtolower($type== 'noselect'{
  311.         $create_mailbox $mailbox $delimiter;
  312.     else {
  313.         $create_mailbox $mailbox;
  314.     }
  315.  
  316.     $read_ary sqimap_run_command($imap_stream"CREATE \"$create_mailbox\"",
  317.                                    true$response$message);
  318.     sqimap_subscribe ($imap_stream$mailbox);
  319. }
  320.  
  321. /**
  322.  * Subscribes to an existing folder.
  323.  */
  324. function sqimap_subscribe ($imap_stream$mailbox{
  325.     $read_ary sqimap_run_command($imap_stream"SUBSCRIBE \"$mailbox\"",
  326.                                    true$response$message);
  327. }
  328.  
  329. /**
  330.  * Unsubscribes from an existing folder
  331.  */
  332. function sqimap_unsubscribe ($imap_stream$mailbox{
  333.     $read_ary sqimap_run_command($imap_stream"UNSUBSCRIBE \"$mailbox\"",
  334.                                    false$response$message);
  335. }
  336.  
  337. /**
  338.  * Deletes the given folder
  339.  */
  340. function sqimap_mailbox_delete ($imap_stream$mailbox{
  341.     global $data_dir$username;
  342.     sqimap_unsubscribe ($imap_stream$mailbox);
  343.     if (sqimap_mailbox_exists($imap_stream$mailbox)) {
  344.         $read_ary sqimap_run_command($imap_stream"DELETE \"$mailbox\"",
  345.                                        true$response$message);
  346.         if ($response !== 'OK'{
  347.             // subscribe again
  348.             sqimap_subscribe ($imap_stream$mailbox);
  349.         else {
  350.             do_hook_function('rename_or_delete_folder'$args array($mailbox'delete'''));
  351.             removePref($data_dir$username"thread_$mailbox");
  352.             removePref($data_dir$username"collapse_folder_$mailbox");
  353.         }
  354.     }
  355. }
  356.  
  357. /**
  358.  * Determines if the user is subscribed to the folder or not
  359.  */
  360. function sqimap_mailbox_is_subscribed($imap_stream$folder{
  361.     $boxesall sqimap_mailbox_list ($imap_stream);
  362.     foreach ($boxesall as $ref{
  363.         if ($ref['unformatted'== $folder{
  364.             return true;
  365.         }
  366.     }
  367.     return false;
  368. }
  369.  
  370. /**
  371.  * Renames a mailbox.
  372.  */
  373. function sqimap_mailbox_rename$imap_stream$old_name$new_name {
  374.     if $old_name != $new_name {
  375.         global $delimiter$imap_server_type$data_dir$username;
  376.         if substr$old_name-== $delimiter  {
  377.             $old_name substr$old_name0strlen$old_name );
  378.             $new_name substr$new_name0strlen$new_name );
  379.             $postfix $delimiter;
  380.         else {
  381.             $postfix '';
  382.         }
  383.  
  384.         $boxesall sqimap_mailbox_list_all($imap_stream);
  385.         $cmd 'RENAME "' $old_name '" "' $new_name '"';
  386.         $data sqimap_run_command($imap_stream$cmdtrue$response$message);
  387.         sqimap_unsubscribe($imap_stream$old_name.$postfix);
  388.         $oldpref_thread getPref($data_dir$username'thread_'.$old_name.$postfix);
  389.         $oldpref_collapse getPref($data_dir$username'collapse_folder_'.$old_name.$postfix);
  390.         removePref($data_dir$username'thread_'.$old_name.$postfix);
  391.         removePref($data_dir$username'collapse_folder_'.$old_name.$postfix);
  392.         sqimap_subscribe($imap_stream$new_name.$postfix);
  393.         setPref($data_dir$username'thread_'.$new_name.$postfix$oldpref_thread);
  394.         setPref($data_dir$username'collapse_folder_'.$new_name.$postfix$oldpref_collapse);
  395.         do_hook_function('rename_or_delete_folder',$args array($old_name'rename'$new_name));
  396.         $l strlen$old_name 1;
  397.         $p 'unformatted';
  398.  
  399.         foreach ($boxesall as $box{
  400.             if (substr($box[$p]0$l== $old_name $delimiter{
  401.                 $new_sub $new_name $delimiter substr($box[$p]$l);
  402.                 /* With Cyrus IMAPd >= 2.0 rename is recursive, so don't check for errors here */
  403.                 if ($imap_server_type == 'cyrus'{
  404.                     $cmd 'RENAME "' $box[$p'" "' $new_sub '"';
  405.                     $data sqimap_run_command($imap_stream$cmdfalse,
  406.                                                $response$message);
  407.                 }
  408.                 $was_subscribed sqimap_mailbox_is_subscribed($imap_stream$box[$p]);
  409.                 if $was_subscribed {
  410.                     sqimap_unsubscribe($imap_stream$box[$p]);
  411.                 }
  412.                 $oldpref_thread getPref($data_dir$username'thread_'.$box[$p]);
  413.                 $oldpref_collapse getPref($data_dir$username'collapse_folder_'.$box[$p]);
  414.                 removePref($data_dir$username'thread_'.$box[$p]);
  415.                 removePref($data_dir$username'collapse_folder_'.$box[$p]);
  416.                 if $was_subscribed {
  417.                     sqimap_subscribe($imap_stream$new_sub);
  418.                 }
  419.                 setPref($data_dir$username'thread_'.$new_sub$oldpref_thread);
  420.                 setPref($data_dir$username'collapse_folder_'.$new_sub$oldpref_collapse);
  421.                 do_hook_function('rename_or_delete_folder',
  422.                                  $args array($box[$p]'rename'$new_sub));
  423.             }
  424.         }
  425.     }
  426. }
  427.  
  428. /**
  429.  * Formats a mailbox into parts for the $boxesall array
  430.  *
  431.  * The parts are:
  432.  *
  433.  *     raw            - Raw LIST/LSUB response from the IMAP server
  434.  *     formatted      - nicely formatted folder name
  435.  *     unformatted    - unformatted, but with delimiter at end removed
  436.  *     unformatted-dm - folder name as it appears in raw response
  437.  *     unformatted-disp - unformatted without $folder_prefix
  438.  */
  439. function sqimap_mailbox_parse ($line$line_lsub{
  440.     global $folder_prefix$delimiter;
  441.  
  442.     /* Process each folder line */
  443.     ksort($line)// get physical ordering same as alphabetical sort we did before now (might be a better place for this)
  444.     foreach ($line as $g => $l)
  445.     // was this but array not guaranteed to be contiguous: for ($g = 0, $cnt = count($line); $g < $cnt; ++$g)
  446.     {
  447.         /* Store the raw IMAP reply */
  448.         if (isset($line[$g])) {
  449.             $boxesall[$g]['raw'$line[$g];
  450.         else {
  451.             $boxesall[$g]['raw''';
  452.         }
  453.  
  454.         /* Count number of delimiters ($delimiter) in folder name */
  455.         $mailbox  $line_lsub[$g];
  456.         $dm_count substr_count($mailbox$delimiter);
  457.         if (substr($mailbox-1== $delimiter{
  458.             /* If name ends in delimiter, decrement count by one */
  459.             $dm_count--;
  460.         }
  461.  
  462.         /* Format folder name, but only if it's a INBOX.* or has a parent. */
  463.         $boxesallbyname[$mailbox$g;
  464.         $parentfolder readMailboxParent($mailbox$delimiter);
  465.         if ( (strtolower(substr($mailbox05)) == "inbox"||
  466.              (substr($mailbox0strlen($folder_prefix)) == $folder_prefix||
  467.              (isset($boxesallbyname[$parentfolder]&&
  468.               (strlen($parentfolder0) ) ) {
  469.             $indent $dm_count (substr_count($folder_prefix$delimiter));
  470.             if ($indent 0{
  471.                 $boxesall[$g]['formatted'str_repeat('&nbsp;&nbsp;'$indent);
  472.             else {
  473.                 $boxesall[$g]['formatted''';
  474.             }
  475.             $boxesall[$g]['formatted'.= imap_utf7_decode_local(readShortMailboxName($mailbox$delimiter));
  476.         else {
  477.             $boxesall[$g]['formatted']  imap_utf7_decode_local($mailbox);
  478.         }
  479.  
  480.         $boxesall[$g]['unformatted-dm'$mailbox;
  481.         if (substr($mailbox-1== $delimiter{
  482.             $mailbox substr($mailbox0strlen($mailbox1);
  483.         }
  484.         $boxesall[$g]['unformatted'$mailbox;
  485.         if (substr($mailbox,0,strlen($folder_prefix))==$folder_prefix{
  486.             $mailbox substr($mailboxstrlen($folder_prefix));
  487.         }
  488.         $boxesall[$g]['unformatted-disp'$mailbox;
  489.         $boxesall[$g]['id'$g;
  490.  
  491.         $boxesall[$g]['flags'array();
  492.         if (isset($line[$g])) {
  493.             if preg_match('/\(([^)]*)\)/',$line[$g],$regs) ) {
  494.                 $flags trim(strtolower(str_replace('\\''',$regs[1])));
  495.                 if ($flags{
  496.                     $boxesall[$g]['flags'explode(' '$flags);
  497.                 }
  498.             }
  499.         }
  500.     }
  501.     return $boxesall;
  502. }
  503.  
  504. /**
  505.  * Sorting function used to sort mailbox names.
  506.  *     + Original patch from dave_michmerhuizen@yahoo.com
  507.  *     + Allows case insensitivity when sorting folders
  508.  *     + Takes care of the delimiter being sorted to the end, causing
  509.  *       subfolders to be listed in below folders that are prefixed
  510.  *       with their parent folders name.
  511.  *
  512.  *       For example: INBOX.foo, INBOX.foobar, and INBOX.foo.bar
  513.  *       Without special sort function: foobar between foo and foo.bar
  514.  *       With special sort function: foobar AFTER foo and foo.bar :)
  515.  */
  516. function user_strcasecmp($a$b{
  517.     return  strnatcasecmp($a$b);
  518. }
  519.  
  520. /**
  521.  * Returns list of options (to be echoed into select statement
  522.  * based on available mailboxes and separators
  523.  * Caller should surround options with <select ...> </select> and
  524.  * any formatting.
  525.  *   $imap_stream - $imapConnection to query for mailboxes
  526.  *   $show_selected - array containing list of mailboxes to pre-select (0 if none)
  527.  *   $folder_skip - array of folders to keep out of option list (compared in lower)
  528.  *   $boxes - list of already fetched boxes (for places like folder panel, where
  529.  *            you know these options will be shown 3 times in a row.. (most often unset).
  530.  *   $flag - flag to check for in mailbox flags, used to filter out mailboxes.
  531.  *           'noselect' by default to remove unselectable mailboxes.
  532.  *           'noinferiors' used to filter out folders that can not contain subfolders.
  533.  *           NULL to avoid flag check entirely.
  534.  *   $use_long_format - override folder display preference and always show full folder name.
  535.  */
  536. function sqimap_mailbox_option_list($imap_stream$show_selected 0$folder_skip 0$boxes 0,
  537.                                     $flag 'noselect'$use_long_format false {
  538.     global $username$data_dir;
  539.     $mbox_options '';
  540.     if $use_long_format {
  541.         $shorten_box_names 0;
  542.     else {
  543.         $shorten_box_names getPref($data_dir$username'mailbox_select_style'1);
  544.     }
  545.  
  546.     if ($boxes == 0{
  547.         $boxes sqimap_mailbox_list($imap_stream);
  548.     }
  549.  
  550.     foreach ($boxes as $boxes_part{
  551.         if ($flag == NULL || !in_array($flag$boxes_part['flags'])) {
  552.             $box $boxes_part['unformatted'];
  553.  
  554.             if ($folder_skip != && in_array($box$folder_skip) ) {
  555.                 continue;
  556.             }
  557.             $lowerbox strtolower($box);
  558.             // mailboxes are casesensitive => inbox.sent != inbox.Sent
  559.             // nevermind, to many dependencies this should be fixed!
  560.  
  561.             if (strtolower($box== 'inbox'// inbox is special and not casesensitive
  562.                 $box2 _("INBOX");
  563.             else {
  564.                 switch ($shorten_box_names)
  565.                 {
  566.                   case 2:   /* delimited, style = 2 */
  567.                     $box2 str_replace('&nbsp;&nbsp;''.&nbsp;'$boxes_part['formatted']);
  568.                     break;
  569.                   case 1:   /* indent, style = 1 */
  570.                     $box2 $boxes_part['formatted'];
  571.                     break;
  572.                   default:  /* default, long names, style = 0 */
  573.                     $box2 str_replace(' ''&nbsp;'sm_encode_html_special_chars(imap_utf7_decode_local($boxes_part['unformatted-disp'])));
  574.                     break;
  575.                 }
  576.             }
  577.             $box2 str_replace(array('<','>')array('&lt;','&gt;'$box2);
  578.  
  579.             if ($show_selected != && in_array($lowerbox$show_selected) ) {
  580.                 $mbox_options .= '<option value="' sm_encode_html_special_chars($box.'" selected="selected">'.$box2.'</option>' "\n";
  581.             else {
  582.                 $mbox_options .= '<option value="' sm_encode_html_special_chars($box.'">'.$box2.'</option>' "\n";
  583.             }
  584.         }
  585.     }
  586.     return $mbox_options;
  587. }
  588.  
  589. /**
  590.  * Mailboxes with some chars (like -) can mess up the order, this fixes it
  591.  */
  592. function mailtree_sort(&$lsub{
  593.     if(!is_array($lsub)) return;
  594.     
  595.     global $delimiter;
  596.     
  597.     foreach($lsub as $index => $mailbox)
  598.         $lsub[$indexstr_replace($delimiter,' -#- ',$lsub[$index]);
  599.  
  600.     usort($lsub'user_strcasecmp');
  601.  
  602.     foreach($lsub as $index => $mailbox)
  603.         $lsub[$indexstr_replace(' -#- ',$delimiter,$lsub[$index]);
  604. }
  605.  
  606. /**
  607.  * Returns sorted mailbox lists in several different ways.
  608.  * See comment on sqimap_mailbox_parse() for info about the returned array.
  609.  */
  610.  
  611.  
  612. function sqimap_mailbox_list($imap_stream$force=false{
  613.  
  614.     if (!sqgetGlobalVar('boxesnew',$boxesnew,SQ_SESSION|| $force{
  615.         global $data_dir$username$list_special_folders_first,
  616.                $folder_prefix$trash_folder$sent_folder$draft_folder,
  617.                $move_to_trash$move_to_sent$save_as_draft,
  618.                $delimiter$noselect_fix_enable;
  619.         $inbox_in_list false;
  620.         $inbox_subscribed false;
  621.  
  622.         require_once(SM_PATH 'include/load_prefs.php');
  623.  
  624.         if ($noselect_fix_enable{
  625.             $lsub_args "LSUB \"$folder_prefix\" \"*%\"";
  626.         else {
  627.             $lsub_args "LSUB \"$folder_prefix\" \"*\"";
  628.         }
  629.         /* LSUB array */
  630.         $lsub_ary sqimap_run_command ($imap_stream$lsub_args,
  631.                                         true$response$message);
  632.  
  633.         $sorted_lsub_ary array();
  634.         for ($i 0$cnt count($lsub_ary);$i $cnt$i++{
  635.             /*
  636.              * Workaround for mailboxes returned as literal
  637.              * Doesn't work if the mailbox name is multiple lines
  638.              * (larger then fgets buffer)
  639.              */
  640.             if (isset($lsub_ary[$i 1]&& substr($lsub_ary[$i],-3== "}\r\n"{
  641.                 if (preg_match('/^(\* [A-Z]+.*)\{[0-9]+\}([ \n\r\t]*)$/',
  642.                      $lsub_ary[$i]$regs)) {
  643.                         $i++;
  644.                         $lsub_ary[$i$regs[1'"' addslashes(trim($lsub_ary[$i])) '"' $regs[2];
  645.                 }
  646.             }
  647.             $temp_mailbox_name find_mailbox_name($lsub_ary[$i]);
  648.             $sorted_lsub_ary[$temp_mailbox_name;
  649.             if (!$inbox_subscribed && strtoupper($temp_mailbox_name== 'INBOX'{
  650.                 $inbox_subscribed true;
  651.             }
  652.         }
  653.         /* remove duplicates */
  654.         $sorted_lsub_ary array_unique($sorted_lsub_ary);
  655.        
  656.         /* natural sort mailboxes */
  657.         if (isset($sorted_lsub_ary)) {
  658.             mailtree_sort($sorted_lsub_ary);
  659.         }
  660.         /*
  661.          * The LSUB response doesn't provide us information about \Noselect
  662.          * mail boxes. The LIST response does, that's why we need to do a LIST
  663.          * call to retrieve the flags for the mailbox
  664.            * Note: according RFC2060 an imap server may provide \NoSelect flags in the LSUB response.
  665.            * in other words, we cannot rely on it.
  666.          */
  667.         if ($noselect_fix_enable{
  668.             $list_args "LIST \"$folder_prefix\" \"*%\"";
  669.         else {
  670.             $list_args "LIST \"$folder_prefix\" \"*\"";
  671.         }
  672.         /* LIST array */
  673.         $list_ary sqimap_run_command ($imap_stream$list_args,
  674.                                         true$response$message);
  675.         $sorted_list_ary array();
  676.         for ($i 0$cnt count($list_ary);$i $cnt$i++{
  677.             /*
  678.              * Workaround for mailboxes returned as literal
  679.              * Doesn't work if the mailbox name is multiple lines
  680.              * (larger then fgets buffer)
  681.              */
  682.             if (isset($list_ary[$i 1]&& substr($list_ary[$i],-3== "}\r\n"{
  683.                 if (preg_match('/^(\* [A-Z]+.*)\{[0-9]+\}([ \n\r\t]*)$/',
  684.                      $list_ary[$i]$regs)) {
  685.                         $i++;
  686.                         $list_ary[$i$regs[1'"' addslashes(trim($list_ary[$i])) '"' $regs[2];
  687.                 }
  688.             }
  689.             $temp_mailbox_name find_mailbox_name($list_ary[$i]);
  690.  
  691.             // is_numeric() because before PHP 4.2.0, bad return
  692.             // value is NULL; whereas in newer versions, it's FALSE
  693.             if (is_numeric($key array_search($temp_mailbox_name$sorted_lsub_ary))) {
  694.                 $sorted_list_ary[$key$list_ary[$i];
  695.             }
  696.         }
  697.  
  698.         /*
  699.          * Just in case they're not subscribed to their inbox,
  700.          * we'll get it for them anyway
  701.          */
  702.         if (!$inbox_subscribed{
  703.             $inbox_ary sqimap_run_command ($imap_stream"LIST \"\" \"INBOX\"",
  704.                                              true$response$message);
  705.             /* Another workaround for literals */
  706.             if (isset($inbox_ary[1]&& substr($inbox_ary[0],-3== "}\r\n"{
  707.                 if (preg_match('/^(\* [A-Z]+.*)\{[0-9]+\}([ \n\r\t]*)$/',
  708.                      $inbox_ary[0]$regs)) {
  709.                     $inbox_ary[0$regs[1'"' addslashes(trim($inbox_ary[1])) .
  710.                                 '"' $regs[2];
  711.                 }
  712.             }
  713.             $sorted_list_ary[$inbox_ary[0];
  714.             $sorted_lsub_ary[find_mailbox_name($inbox_ary[0]);
  715.         }
  716.  
  717.         $boxesall sqimap_mailbox_parse ($sorted_list_ary$sorted_lsub_ary);
  718.  
  719.         /* Now, lets sort for special folders */
  720.         $boxesnew $used array();
  721.  
  722.         /* Find INBOX */
  723.         $cnt count($boxesall);
  724.         $used array_pad($used,$cnt,false);
  725.         foreach ($boxesall as $k => $b)
  726.         // was this but array not guaranteed to be contiguous: for($k = 0; $k < $cnt; ++$k)
  727.         {
  728.             if (strtolower($boxesall[$k]['unformatted']== 'inbox'{
  729.                 $boxesnew[$boxesall[$k];
  730.                 $used[$ktrue;
  731.                 break;
  732.             }
  733.         }
  734.  
  735.         /* 
  736.          * For systems where folders might be either under the INBOX or
  737.          * at the top-level (Dovecot, hMailServer), INBOX subfolders have
  738.          * to be added before special folders
  739.          */
  740.         if (!$default_sub_of_inbox{
  741.             foreach ($boxesall as $k => $b)
  742.             // was this but array not guaranteed to be contiguous: for($k = 0; $k < $cnt; ++$k)
  743.             {
  744.                 if (!$used[$k&& isBoxBelow(strtolower($boxesall[$k]['unformatted'])'inbox'&&
  745.                     strtolower($boxesall[$k]['unformatted']!= 'inbox'{
  746.                     $boxesnew[$boxesall[$k];
  747.                     $used[$ktrue;
  748.                 }
  749.             }
  750.         }
  751.  
  752.  
  753.         /* List special folders and their subfolders, if requested. */
  754.         if ($list_special_folders_first{
  755.             foreach ($boxesall as $k => $b)
  756.             // was this but array not guaranteed to be contiguous: for($k = 0; $k < $cnt; ++$k)
  757.             {
  758.                 if (!$used[$k&& isSpecialMailbox($boxesall[$k]['unformatted'])) {
  759.                     $boxesnew[$boxesall[$k];
  760.                     $used[$k]   true;
  761.                 }
  762.             }
  763.         }
  764.  
  765.  
  766.         /* Find INBOX's children for systems where folders are ONLY under INBOX */
  767.         if ($default_sub_of_inbox{
  768.             foreach ($boxesall as $k => $b)
  769.             // was this but array not guaranteed to be contiguous: for($k = 0; $k < $cnt; ++$k)
  770.             {
  771.                 if (!$used[$k&& isBoxBelow(strtolower($boxesall[$k]['unformatted'])'inbox'&&
  772.                     strtolower($boxesall[$k]['unformatted']!= 'inbox'{
  773.                     $boxesnew[$boxesall[$k];
  774.                     $used[$ktrue;
  775.                 }
  776.             }
  777.         }
  778.  
  779.  
  780.         /* Rest of the folders */
  781.         foreach ($boxesall as $k => $b)
  782.         // was this but array not guaranteed to be contiguous: for($k = 0; $k < $cnt; $k++)
  783.         {
  784.             if (!$used[$k]{
  785.                 $boxesnew[$boxesall[$k];
  786.             }
  787.         }
  788.         sqsession_register($boxesnew,'boxesnew');
  789.     }
  790.     return $boxesnew;
  791. }
  792.  
  793. /**
  794.  *  Returns a list of all folders, subscribed or not
  795.  */
  796. function sqimap_mailbox_list_all($imap_stream{
  797.     global $list_special_folders_first$folder_prefix$delimiter;
  798.  
  799.     $ssid sqimap_session_id();
  800.     $lsid strlen$ssid );
  801.     fputs ($imap_stream$ssid " LIST \"$folder_prefix\" *\r\n");
  802.     $read_ary sqimap_read_data ($imap_stream$ssidtrue$response$message);
  803.     $g 0;
  804.     $phase 'inbox';
  805.     $fld_pre_length strlen($folder_prefix);
  806.  
  807.     for ($i 0$cnt count($read_ary)$i $cnt$i++{
  808.         /* Another workaround for EIMS */
  809.         if (isset($read_ary[$i 1]&&
  810.             preg_match('/^(\* [A-Z]+.*)\{[0-9]+\}([ \n\r\t]*)$/',
  811.                  $read_ary[$i]$regs)) {
  812.             $i ++;
  813.             $read_ary[$i$regs[1'"' addslashes(trim($read_ary[$i])) '"' $regs[2];
  814.         }
  815.         if (substr($read_ary[$i]0$lsid!= $ssid {
  816.             /* Store the raw IMAP reply */
  817.             $boxes[$g]['raw'$read_ary[$i];
  818.  
  819.             /* Count number of delimiters ($delimiter) in folder name */
  820.             $mailbox find_mailbox_name($read_ary[$i]);
  821.             $dm_count =  substr_count($mailbox$delimiter);
  822.             if (substr($mailbox-1== $delimiter{
  823.                 /* If name ends in delimiter - decrement count by one */
  824.                 $dm_count--;
  825.             }
  826.  
  827.             /* Format folder name, but only if it's a INBOX.* or has a parent. */
  828.             $boxesallbyname[$mailbox$g;
  829.             $parentfolder readMailboxParent($mailbox$delimiter);
  830.             /* @FIXME shouldn't use preg_match for simple string matching */
  831.             if((preg_match('|^inbox'.quotemeta($delimiter).'|i'$mailbox)) ||
  832.                (preg_match('|^'.$folder_prefix.'|'$mailbox)) ||
  833.                isset($boxesallbyname[$parentfolder]&& (strlen($parentfolder0) ) ) {
  834.                 if ($dm_count{
  835.                     $boxes[$g]['formatted']  str_repeat('&nbsp;&nbsp;'$dm_count);
  836.                 else {
  837.                     $boxes[$g]['formatted''';
  838.                 }
  839.                 $boxes[$g]['formatted'.= imap_utf7_decode_local(readShortMailboxName($mailbox$delimiter));
  840.             else {
  841.                 $boxes[$g]['formatted']  imap_utf7_decode_local($mailbox);
  842.             }
  843.  
  844.             $boxes[$g]['unformatted-dm'$mailbox;
  845.             if (substr($mailbox-1== $delimiter{
  846.                 $mailbox substr($mailbox0strlen($mailbox1);
  847.             }
  848.             $boxes[$g]['unformatted'$mailbox;
  849.             $boxes[$g]['unformatted-disp'substr($mailbox,$fld_pre_length);
  850.  
  851.             $boxes[$g]['id'$g;
  852.  
  853.             /* Now lets get the flags for this mailbox */
  854.             $read_mlbx $read_ary[$i];
  855.  
  856. //            $read_mlbx = sqimap_run_command ($imap_stream, "LIST \"\" \"$mailbox\"",
  857. //                                             true, $response, $message);
  858.  
  859.             /* Another workaround for EIMS */
  860. //            if (isset($read_mlbx[1]) &&
  861. //                preg_match('/^(\* [A-Z]+.*)\{[0-9]+\}([ \n\r\t]*)$/', $read_mlbx[0], $regs)) {
  862. //                $read_mlbx[0] = $regs[1] . '"' . addslashes(trim($read_mlbx[1])) . '"' . $regs[2];
  863. //            }
  864. //            echo  $read_mlbx[0] .' raw 2 <br>';
  865.  
  866.             $flags substr($read_mlbxstrpos($read_mlbx'(')+1);
  867.             $flags substr($flags0strpos($flags')'));
  868.             $flags str_replace('\\'''$flags);
  869.             $flags trim(strtolower($flags));
  870.             if ($flags{
  871.                 $boxes[$g]['flags'explode(' '$flags);
  872.             else {
  873.                 $boxes[$g]['flags'array();
  874.             }
  875.         }
  876.         $g++;
  877.     }
  878.     if(is_array($boxes)) {
  879.         sort ($boxes);
  880.     }
  881.  
  882.     return $boxes;
  883. }

Documentation generated on Tue, 12 Dec 2017 04:26:20 +0100 by phpDocumentor 1.4.3