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-2016 The SquirrelMail Project Team
  9.  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  10.  * @version $Id: imap_mailbox.php 14576 2016-10-28 02:35:25Z 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.     ksort($line)// get physical ordering same as alphabetical sort we did before now (might be a better place for this)
  432.     foreach ($line as $g => $l)
  433.     // was this but array not guaranteed to be contiguous: for ($g = 0, $cnt = count($line); $g < $cnt; ++$g)
  434.     {
  435.         /* Store the raw IMAP reply */
  436.         if (isset($line[$g])) {
  437.             $boxesall[$g]['raw'$line[$g];
  438.         else {
  439.             $boxesall[$g]['raw''';
  440.         }
  441.  
  442.         /* Count number of delimiters ($delimiter) in folder name */
  443.         $mailbox  $line_lsub[$g];
  444.         $dm_count substr_count($mailbox$delimiter);
  445.         if (substr($mailbox-1== $delimiter{
  446.             /* If name ends in delimiter, decrement count by one */
  447.             $dm_count--;
  448.         }
  449.  
  450.         /* Format folder name, but only if it's a INBOX.* or has a parent. */
  451.         $boxesallbyname[$mailbox$g;
  452.         $parentfolder readMailboxParent($mailbox$delimiter);
  453.         if ( (strtolower(substr($mailbox05)) == "inbox"||
  454.              (substr($mailbox0strlen($folder_prefix)) == $folder_prefix||
  455.              (isset($boxesallbyname[$parentfolder]&&
  456.               (strlen($parentfolder0) ) ) {
  457.             $indent $dm_count (substr_count($folder_prefix$delimiter));
  458.             if ($indent 0{
  459.                 $boxesall[$g]['formatted'str_repeat('&nbsp;&nbsp;'$indent);
  460.             else {
  461.                 $boxesall[$g]['formatted''';
  462.             }
  463.             $boxesall[$g]['formatted'.= imap_utf7_decode_local(readShortMailboxName($mailbox$delimiter));
  464.         else {
  465.             $boxesall[$g]['formatted']  imap_utf7_decode_local($mailbox);
  466.         }
  467.  
  468.         $boxesall[$g]['unformatted-dm'$mailbox;
  469.         if (substr($mailbox-1== $delimiter{
  470.             $mailbox substr($mailbox0strlen($mailbox1);
  471.         }
  472.         $boxesall[$g]['unformatted'$mailbox;
  473.         if (substr($mailbox,0,strlen($folder_prefix))==$folder_prefix{
  474.             $mailbox substr($mailboxstrlen($folder_prefix));
  475.         }
  476.         $boxesall[$g]['unformatted-disp'$mailbox;
  477.         $boxesall[$g]['id'$g;
  478.  
  479.         $boxesall[$g]['flags'array();
  480.         if (isset($line[$g])) {
  481.             if preg_match('/\(([^)]*)\)/',$line[$g],$regs) ) {
  482.                 $flags trim(strtolower(str_replace('\\''',$regs[1])));
  483.                 if ($flags{
  484.                     $boxesall[$g]['flags'explode(' '$flags);
  485.                 }
  486.             }
  487.         }
  488.     }
  489.     return $boxesall;
  490. }
  491.  
  492. /**
  493.  * Sorting function used to sort mailbox names.
  494.  *     + Original patch from dave_michmerhuizen@yahoo.com
  495.  *     + Allows case insensitivity when sorting folders
  496.  *     + Takes care of the delimiter being sorted to the end, causing
  497.  *       subfolders to be listed in below folders that are prefixed
  498.  *       with their parent folders name.
  499.  *
  500.  *       For example: INBOX.foo, INBOX.foobar, and INBOX.foo.bar
  501.  *       Without special sort function: foobar between foo and foo.bar
  502.  *       With special sort function: foobar AFTER foo and foo.bar :)
  503.  */
  504. function user_strcasecmp($a$b{
  505.     return  strnatcasecmp($a$b);
  506. }
  507.  
  508. /**
  509.  * Returns list of options (to be echoed into select statement
  510.  * based on available mailboxes and separators
  511.  * Caller should surround options with <select ...> </select> and
  512.  * any formatting.
  513.  *   $imap_stream - $imapConnection to query for mailboxes
  514.  *   $show_selected - array containing list of mailboxes to pre-select (0 if none)
  515.  *   $folder_skip - array of folders to keep out of option list (compared in lower)
  516.  *   $boxes - list of already fetched boxes (for places like folder panel, where
  517.  *            you know these options will be shown 3 times in a row.. (most often unset).
  518.  *   $flag - flag to check for in mailbox flags, used to filter out mailboxes.
  519.  *           'noselect' by default to remove unselectable mailboxes.
  520.  *           'noinferiors' used to filter out folders that can not contain subfolders.
  521.  *           NULL to avoid flag check entirely.
  522.  *   $use_long_format - override folder display preference and always show full folder name.
  523.  */
  524. function sqimap_mailbox_option_list($imap_stream$show_selected 0$folder_skip 0$boxes 0,
  525.                                     $flag 'noselect'$use_long_format false {
  526.     global $username$data_dir;
  527.     $mbox_options '';
  528.     if $use_long_format {
  529.         $shorten_box_names 0;
  530.     else {
  531.         $shorten_box_names getPref($data_dir$username'mailbox_select_style'1);
  532.     }
  533.  
  534.     if ($boxes == 0{
  535.         $boxes sqimap_mailbox_list($imap_stream);
  536.     }
  537.  
  538.     foreach ($boxes as $boxes_part{
  539.         if ($flag == NULL || !in_array($flag$boxes_part['flags'])) {
  540.             $box $boxes_part['unformatted'];
  541.  
  542.             if ($folder_skip != && in_array($box$folder_skip) ) {
  543.                 continue;
  544.             }
  545.             $lowerbox strtolower($box);
  546.             // mailboxes are casesensitive => inbox.sent != inbox.Sent
  547.             // nevermind, to many dependencies this should be fixed!
  548.  
  549.             if (strtolower($box== 'inbox'// inbox is special and not casesensitive
  550.                 $box2 _("INBOX");
  551.             else {
  552.                 switch ($shorten_box_names)
  553.                 {
  554.                   case 2:   /* delimited, style = 2 */
  555.                     $box2 str_replace('&nbsp;&nbsp;''.&nbsp;'$boxes_part['formatted']);
  556.                     break;
  557.                   case 1:   /* indent, style = 1 */
  558.                     $box2 $boxes_part['formatted'];
  559.                     break;
  560.                   default:  /* default, long names, style = 0 */
  561.                     $box2 str_replace(' ''&nbsp;'sm_encode_html_special_chars(imap_utf7_decode_local($boxes_part['unformatted-disp'])));
  562.                     break;
  563.                 }
  564.             }
  565.             $box2 str_replace(array('<','>')array('&lt;','&gt;'$box2);
  566.  
  567.             if ($show_selected != && in_array($lowerbox$show_selected) ) {
  568.                 $mbox_options .= '<option value="' sm_encode_html_special_chars($box.'" selected="selected">'.$box2.'</option>' "\n";
  569.             else {
  570.                 $mbox_options .= '<option value="' sm_encode_html_special_chars($box.'">'.$box2.'</option>' "\n";
  571.             }
  572.         }
  573.     }
  574.     return $mbox_options;
  575. }
  576.  
  577. /**
  578.  * Mailboxes with some chars (like -) can mess up the order, this fixes it
  579.  */
  580. function mailtree_sort(&$lsub{
  581.     if(!is_array($lsub)) return;
  582.     
  583.     global $delimiter;
  584.     
  585.     foreach($lsub as $index => $mailbox)
  586.         $lsub[$indexstr_replace($delimiter,' -#- ',$lsub[$index]);
  587.  
  588.     usort($lsub'user_strcasecmp');
  589.  
  590.     foreach($lsub as $index => $mailbox)
  591.         $lsub[$indexstr_replace(' -#- ',$delimiter,$lsub[$index]);
  592. }
  593.  
  594. /**
  595.  * Returns sorted mailbox lists in several different ways.
  596.  * See comment on sqimap_mailbox_parse() for info about the returned array.
  597.  */
  598.  
  599.  
  600. function sqimap_mailbox_list($imap_stream$force=false{
  601.  
  602.     if (!sqgetGlobalVar('boxesnew',$boxesnew,SQ_SESSION|| $force{
  603.         global $data_dir$username$list_special_folders_first,
  604.                $folder_prefix$trash_folder$sent_folder$draft_folder,
  605.                $move_to_trash$move_to_sent$save_as_draft,
  606.                $delimiter$noselect_fix_enable;
  607.         $inbox_in_list false;
  608.         $inbox_subscribed false;
  609.  
  610.         require_once(SM_PATH 'include/load_prefs.php');
  611.  
  612.         if ($noselect_fix_enable{
  613.             $lsub_args "LSUB \"$folder_prefix\" \"*%\"";
  614.         else {
  615.             $lsub_args "LSUB \"$folder_prefix\" \"*\"";
  616.         }
  617.         /* LSUB array */
  618.         $lsub_ary sqimap_run_command ($imap_stream$lsub_args,
  619.                                         true$response$message);
  620.  
  621.         $sorted_lsub_ary array();
  622.         for ($i 0$cnt count($lsub_ary);$i $cnt$i++{
  623.             /*
  624.              * Workaround for mailboxes returned as literal
  625.              * Doesn't work if the mailbox name is multiple lines
  626.              * (larger then fgets buffer)
  627.              */
  628.             if (isset($lsub_ary[$i 1]&& substr($lsub_ary[$i],-3== "}\r\n"{
  629.                 if (preg_match('/^(\* [A-Z]+.*)\{[0-9]+\}([ \n\r\t]*)$/',
  630.                      $lsub_ary[$i]$regs)) {
  631.                         $i++;
  632.                         $lsub_ary[$i$regs[1'"' addslashes(trim($lsub_ary[$i])) '"' $regs[2];
  633.                 }
  634.             }
  635.             $temp_mailbox_name find_mailbox_name($lsub_ary[$i]);
  636.             $sorted_lsub_ary[$temp_mailbox_name;
  637.             if (!$inbox_subscribed && strtoupper($temp_mailbox_name== 'INBOX'{
  638.                 $inbox_subscribed true;
  639.             }
  640.         }
  641.         /* remove duplicates */
  642.         $sorted_lsub_ary array_unique($sorted_lsub_ary);
  643.        
  644.         /* natural sort mailboxes */
  645.         if (isset($sorted_lsub_ary)) {
  646.             mailtree_sort($sorted_lsub_ary);
  647.         }
  648.         /*
  649.          * The LSUB response doesn't provide us information about \Noselect
  650.          * mail boxes. The LIST response does, that's why we need to do a LIST
  651.          * call to retrieve the flags for the mailbox
  652.            * Note: according RFC2060 an imap server may provide \NoSelect flags in the LSUB response.
  653.            * in other words, we cannot rely on it.
  654.          */
  655.         if ($noselect_fix_enable{
  656.             $list_args "LIST \"$folder_prefix\" \"*%\"";
  657.         else {
  658.             $list_args "LIST \"$folder_prefix\" \"*\"";
  659.         }
  660.         /* LIST array */
  661.         $list_ary sqimap_run_command ($imap_stream$list_args,
  662.                                         true$response$message);
  663.         $sorted_list_ary array();
  664.         for ($i 0$cnt count($list_ary);$i $cnt$i++{
  665.             /*
  666.              * Workaround for mailboxes returned as literal
  667.              * Doesn't work if the mailbox name is multiple lines
  668.              * (larger then fgets buffer)
  669.              */
  670.             if (isset($list_ary[$i 1]&& substr($list_ary[$i],-3== "}\r\n"{
  671.                 if (preg_match('/^(\* [A-Z]+.*)\{[0-9]+\}([ \n\r\t]*)$/',
  672.                      $list_ary[$i]$regs)) {
  673.                         $i++;
  674.                         $list_ary[$i$regs[1'"' addslashes(trim($list_ary[$i])) '"' $regs[2];
  675.                 }
  676.             }
  677.             $temp_mailbox_name find_mailbox_name($list_ary[$i]);
  678.  
  679.             // is_numeric() because before PHP 4.2.0, bad return
  680.             // value is NULL; whereas in newer versions, it's FALSE
  681.             if (is_numeric($key array_search($temp_mailbox_name$sorted_lsub_ary))) {
  682.                 $sorted_list_ary[$key$list_ary[$i];
  683.             }
  684.         }
  685.  
  686.         /*
  687.          * Just in case they're not subscribed to their inbox,
  688.          * we'll get it for them anyway
  689.          */
  690.         if (!$inbox_subscribed{
  691.             $inbox_ary sqimap_run_command ($imap_stream"LIST \"\" \"INBOX\"",
  692.                                              true$response$message);
  693.             /* Another workaround for literals */
  694.             if (isset($inbox_ary[1]&& substr($inbox_ary[0],-3== "}\r\n"{
  695.                 if (preg_match('/^(\* [A-Z]+.*)\{[0-9]+\}([ \n\r\t]*)$/',
  696.                      $inbox_ary[0]$regs)) {
  697.                     $inbox_ary[0$regs[1'"' addslashes(trim($inbox_ary[1])) .
  698.                                 '"' $regs[2];
  699.                 }
  700.             }
  701.             $sorted_list_ary[$inbox_ary[0];
  702.             $sorted_lsub_ary[find_mailbox_name($inbox_ary[0]);
  703.         }
  704.  
  705.         $boxesall sqimap_mailbox_parse ($sorted_list_ary$sorted_lsub_ary);
  706.  
  707.         /* Now, lets sort for special folders */
  708.         $boxesnew $used array();
  709.  
  710.         /* Find INBOX */
  711.         $cnt count($boxesall);
  712.         $used array_pad($used,$cnt,false);
  713.         foreach ($boxesall as $k => $b)
  714.         // was this but array not guaranteed to be contiguous: for($k = 0; $k < $cnt; ++$k)
  715.         {
  716.             if (strtolower($boxesall[$k]['unformatted']== 'inbox'{
  717.                 $boxesnew[$boxesall[$k];
  718.                 $used[$ktrue;
  719.                 break;
  720.             }
  721.         }
  722.  
  723.         /* 
  724.          * For systems where folders might be either under the INBOX or
  725.          * at the top-level (Dovecot, hMailServer), INBOX subfolders have
  726.          * to be added before special folders
  727.          */
  728.         if (!$default_sub_of_inbox{
  729.             foreach ($boxesall as $k => $b)
  730.             // was this but array not guaranteed to be contiguous: for($k = 0; $k < $cnt; ++$k)
  731.             {
  732.                 if (!$used[$k&& isBoxBelow(strtolower($boxesall[$k]['unformatted'])'inbox'&&
  733.                     strtolower($boxesall[$k]['unformatted']!= 'inbox'{
  734.                     $boxesnew[$boxesall[$k];
  735.                     $used[$ktrue;
  736.                 }
  737.             }
  738.         }
  739.  
  740.  
  741.         /* List special folders and their subfolders, if requested. */
  742.         if ($list_special_folders_first{
  743.             foreach ($boxesall as $k => $b)
  744.             // was this but array not guaranteed to be contiguous: for($k = 0; $k < $cnt; ++$k)
  745.             {
  746.                 if (!$used[$k&& isSpecialMailbox($boxesall[$k]['unformatted'])) {
  747.                     $boxesnew[$boxesall[$k];
  748.                     $used[$k]   true;
  749.                 }
  750.             }
  751.         }
  752.  
  753.  
  754.         /* Find INBOX's children for systems where folders are ONLY under INBOX */
  755.         if ($default_sub_of_inbox{
  756.             foreach ($boxesall as $k => $b)
  757.             // was this but array not guaranteed to be contiguous: for($k = 0; $k < $cnt; ++$k)
  758.             {
  759.                 if (!$used[$k&& isBoxBelow(strtolower($boxesall[$k]['unformatted'])'inbox'&&
  760.                     strtolower($boxesall[$k]['unformatted']!= 'inbox'{
  761.                     $boxesnew[$boxesall[$k];
  762.                     $used[$ktrue;
  763.                 }
  764.             }
  765.         }
  766.  
  767.  
  768.         /* Rest of the folders */
  769.         foreach ($boxesall as $k => $b)
  770.         // was this but array not guaranteed to be contiguous: for($k = 0; $k < $cnt; $k++)
  771.         {
  772.             if (!$used[$k]{
  773.                 $boxesnew[$boxesall[$k];
  774.             }
  775.         }
  776.         sqsession_register($boxesnew,'boxesnew');
  777.     }
  778.     return $boxesnew;
  779. }
  780.  
  781. /**
  782.  *  Returns a list of all folders, subscribed or not
  783.  */
  784. function sqimap_mailbox_list_all($imap_stream{
  785.     global $list_special_folders_first$folder_prefix$delimiter;
  786.  
  787.     $ssid sqimap_session_id();
  788.     $lsid strlen$ssid );
  789.     fputs ($imap_stream$ssid " LIST \"$folder_prefix\" *\r\n");
  790.     $read_ary sqimap_read_data ($imap_stream$ssidtrue$response$message);
  791.     $g 0;
  792.     $phase 'inbox';
  793.     $fld_pre_length strlen($folder_prefix);
  794.  
  795.     for ($i 0$cnt count($read_ary)$i $cnt$i++{
  796.         /* Another workaround for EIMS */
  797.         if (isset($read_ary[$i 1]&&
  798.             preg_match('/^(\* [A-Z]+.*)\{[0-9]+\}([ \n\r\t]*)$/',
  799.                  $read_ary[$i]$regs)) {
  800.             $i ++;
  801.             $read_ary[$i$regs[1'"' addslashes(trim($read_ary[$i])) '"' $regs[2];
  802.         }
  803.         if (substr($read_ary[$i]0$lsid!= $ssid {
  804.             /* Store the raw IMAP reply */
  805.             $boxes[$g]['raw'$read_ary[$i];
  806.  
  807.             /* Count number of delimiters ($delimiter) in folder name */
  808.             $mailbox find_mailbox_name($read_ary[$i]);
  809.             $dm_count =  substr_count($mailbox$delimiter);
  810.             if (substr($mailbox-1== $delimiter{
  811.                 /* If name ends in delimiter - decrement count by one */
  812.                 $dm_count--;
  813.             }
  814.  
  815.             /* Format folder name, but only if it's a INBOX.* or has a parent. */
  816.             $boxesallbyname[$mailbox$g;
  817.             $parentfolder readMailboxParent($mailbox$delimiter);
  818.             /* @FIXME shouldn't use preg_match for simple string matching */
  819.             if((preg_match('|^inbox'.quotemeta($delimiter).'|i'$mailbox)) ||
  820.                (preg_match('|^'.$folder_prefix.'|'$mailbox)) ||
  821.                isset($boxesallbyname[$parentfolder]&& (strlen($parentfolder0) ) ) {
  822.                 if ($dm_count{
  823.                     $boxes[$g]['formatted']  str_repeat('&nbsp;&nbsp;'$dm_count);
  824.                 else {
  825.                     $boxes[$g]['formatted''';
  826.                 }
  827.                 $boxes[$g]['formatted'.= imap_utf7_decode_local(readShortMailboxName($mailbox$delimiter));
  828.             else {
  829.                 $boxes[$g]['formatted']  imap_utf7_decode_local($mailbox);
  830.             }
  831.  
  832.             $boxes[$g]['unformatted-dm'$mailbox;
  833.             if (substr($mailbox-1== $delimiter{
  834.                 $mailbox substr($mailbox0strlen($mailbox1);
  835.             }
  836.             $boxes[$g]['unformatted'$mailbox;
  837.             $boxes[$g]['unformatted-disp'substr($mailbox,$fld_pre_length);
  838.  
  839.             $boxes[$g]['id'$g;
  840.  
  841.             /* Now lets get the flags for this mailbox */
  842.             $read_mlbx $read_ary[$i];
  843.  
  844. //            $read_mlbx = sqimap_run_command ($imap_stream, "LIST \"\" \"$mailbox\"",
  845. //                                             true, $response, $message);
  846.  
  847.             /* Another workaround for EIMS */
  848. //            if (isset($read_mlbx[1]) &&
  849. //                preg_match('/^(\* [A-Z]+.*)\{[0-9]+\}([ \n\r\t]*)$/', $read_mlbx[0], $regs)) {
  850. //                $read_mlbx[0] = $regs[1] . '"' . addslashes(trim($read_mlbx[1])) . '"' . $regs[2];
  851. //            }
  852. //            echo  $read_mlbx[0] .' raw 2 <br>';
  853.  
  854.             $flags substr($read_mlbxstrpos($read_mlbx'(')+1);
  855.             $flags substr($flags0strpos($flags')'));
  856.             $flags str_replace('\\'''$flags);
  857.             $flags trim(strtolower($flags));
  858.             if ($flags{
  859.                 $boxes[$g]['flags'explode(' '$flags);
  860.             else {
  861.                 $boxes[$g]['flags'array();
  862.             }
  863.         }
  864.         $g++;
  865.     }
  866.     if(is_array($boxes)) {
  867.         sort ($boxes);
  868.     }
  869.  
  870.     return $boxes;
  871. }

Documentation generated on Fri, 02 Dec 2016 04:27:19 +0100 by phpDocumentor 1.4.3