Source for file imap_messages.php

Documentation is available at imap_messages.php

  1. <?php
  2.  
  3. /**
  4.  * imap_messages.php
  5.  *
  6.  * This implements functions that manipulate messages
  7.  * NOTE: Quite a few functions in this file are obsolete
  8.  *
  9.  * @copyright 1999-2020 The SquirrelMail Project Team
  10.  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  11.  * @version $Id: imap_messages.php 14840 2020-01-07 07:42:38Z pdontthink $
  12.  * @package squirrelmail
  13.  * @subpackage imap
  14.  */
  15.  
  16.  
  17. /**
  18.  * Copies a set of messages ($id) to another mailbox ($mailbox)
  19.  * 
  20.  * NOTE: Verions of this function BEFORE SquirrelMail 1.4.18
  21.  *       actually *moved* messages instead of copying them
  22.  * 
  23.  * @param int    $imap_stream The resource ID for the IMAP socket
  24.  * @param mixed  $id          A string or array of messages to copy
  25.  * @param string $mailbox     The mailbox to copy messages to
  26.  *
  27.  * @return bool Returns true on successful copy, false on failure
  28.  *
  29.  */
  30. function sqimap_msgs_list_copy($imap_stream$id$mailbox{
  31.     global $uid_support;
  32.     $msgs_id sqimap_message_list_squisher($id);
  33.     $read sqimap_run_command ($imap_stream"COPY $msgs_id \"$mailbox\""true$response$message$uid_support);
  34.     
  35.     if ($response == 'OK'{
  36.         return true;
  37.     else {
  38.         return false;
  39.     }
  40. }
  41.  
  42.  
  43. /**
  44.  * Moves a set of messages ($id) to another mailbox ($mailbox)
  45.  * 
  46.  * @param int    $imap_stream   The resource ID for the IMAP socket
  47.  * @param mixed  $id            A string or array of messages to move
  48.  * @param string $mailbox       The destination mailbox
  49.  * @param bool   $handle_errors Show error messages in case of a NO, BAD, or BYE response
  50.  *
  51.  * @return bool If move completed without error.
  52.  *
  53.  * @since 1.4.18
  54.  *
  55.  */
  56. function sqimap_msgs_list_move($imap_stream$id$mailbox$handle_errors true{
  57.     if (sqimap_msgs_list_copy ($imap_stream$id$mailbox$handle_errors)) {
  58.         return sqimap_toggle_flag($imap_stream$id'\\Deleted'truetrue);
  59.     else {
  60.         return false;
  61.     }
  62. }
  63.  
  64. /**
  65.  * Deletes one or more message(s) and move
  66.  * it/them to trash or expunge the mailbox
  67.  * 
  68.  * @param int    $imap_stream The resource ID for the IMAP socket
  69.  * @param string $mailbox     The mailbox to delete messages from
  70.  * @param mixed  $id          A string or array of messages to delete
  71.  *
  72.  */
  73. function sqimap_msgs_list_delete($imap_stream$mailbox$id{
  74.     global $move_to_trash$trash_folder$uid_support;
  75.     $msgs_id sqimap_message_list_squisher($id);
  76.     if (($move_to_trash == true&& (sqimap_mailbox_exists($imap_stream$trash_folder&& ($mailbox != $trash_folder))) {
  77.         /**
  78.          * turn off internal error handling (third argument = false) and
  79.          * ignore copy to trash errors (allows to delete messages when overquota)
  80.          */
  81.         $read sqimap_run_command ($imap_stream"COPY $msgs_id \"$trash_folder\""false$response$message$uid_support);
  82.     }
  83.     $read sqimap_run_command ($imap_stream"STORE $msgs_id +FLAGS (\\Deleted)"true$response$message$uid_support);
  84. }
  85.  
  86.  
  87. /**
  88.  * Sort the message list and crunch to be as small as possible
  89.  * (overflow could happen, so make it small if possible)
  90.  */
  91. function sqimap_message_list_squisher($messages_array{
  92.     if!is_array$messages_array ) ) {
  93.         return $messages_array;
  94.     }
  95.  
  96.     sort($messages_arraySORT_NUMERIC);
  97.     $msgs_str '';
  98.     while ($messages_array{
  99.         $start array_shift($messages_array);
  100.         $end $start;
  101.         while (isset($messages_array[0]&& $messages_array[0== $end 1{
  102.             $end array_shift($messages_array);
  103.         }
  104.         if ($msgs_str != ''{
  105.             $msgs_str .= ',';
  106.         }
  107.         $msgs_str .= $start;
  108.         if ($start != $end{
  109.             $msgs_str .= ':' $end;
  110.         }
  111.     }
  112.     return $msgs_str;
  113. }
  114.  
  115.  
  116. /**
  117.  * Returns the references header lines
  118.  */
  119. function get_reference_header($imap_stream$message{
  120.     global $uid_support;
  121.     $responses array ();
  122.     $results array();
  123.     $references "";
  124.     $responses sqimap_run_command_list ($imap_stream"FETCH $message BODY[HEADER.FIELDS (References)]"true$response$message$uid_support);
  125.     if (!preg_match("/^\* ([0-9]+) FETCH/i"$responses[0][0]$regs)) {
  126.         $responses array ();
  127.     }
  128.     return $responses;
  129. }
  130.  
  131.  
  132. /**
  133.  * Get sort order from server and return it as the $id array for mailbox_display
  134.  */
  135. function sqimap_get_sort_order($imap_stream$sort$mbxresponse{
  136.     global  $default_charset$thread_sort_messages,
  137.             $internal_date_sort$server_sort_array,
  138.             $sent_folder$mailbox$uid_support,
  139.             $imap_server_type;
  140.  
  141.     if (sqsession_is_registered('server_sort_array')) {
  142.         sqsession_unregister('server_sort_array');
  143.     }
  144.  
  145.     $sort_on array();
  146.     $reverse 0;
  147.     $server_sort_array array();
  148.     $sort_test array();
  149.     $sort_query '';
  150.  
  151.     // gmail does not support sorting I guess, so it always should have default sort
  152.     //
  153.     if ($sort == || $imap_server_type == 'gmail'{
  154.         if ($uid_support{
  155.             if (isset($mbxresponse['UIDNEXT']&& $mbxresponse['UIDNEXT']{
  156.                 $uidnext $mbxresponse['UIDNEXT']-1;
  157.             else {
  158.                 $uidnext '*';
  159.             }
  160.             $query "SEARCH UID 1:$uidnext";
  161.             $uids sqimap_run_command_list ($imap_stream$querytrue$response$messagetrue);
  162.             if (isset($uids[0])) {
  163.                 for ($i=0,$iCnt=count($uids);$i<$iCnt;++$i{
  164.                     for ($j 0$jCnt=count($uids[$i]);$j<$jCnt;++$j{
  165.                         if (preg_match("/^\* SEARCH (.+)$/"$uids[$i][$j]$regs)) {
  166.                             $server_sort_array += preg_split("/ /"trim($regs[1]));
  167.                         }
  168.                     }
  169.                 }
  170.             }
  171.             if (!preg_match("/OK/"$response)) {
  172.                 $server_sort_array 'no';
  173.             }
  174.         else {
  175.             $qty $mbxresponse['EXISTS'];
  176.             $server_sort_array range(1$qty);
  177.         }
  178.         $server_sort_array array_reverse($server_sort_array);
  179.         sqsession_register($server_sort_array'server_sort_array');
  180.         return $server_sort_array;
  181.     }
  182.  
  183.     $sort_on array (0=> 'DATE',
  184.                       1=> 'DATE',
  185.                       2=> 'FROM',
  186.                       3=> 'FROM',
  187.                       4=> 'SUBJECT',
  188.                       5=> 'SUBJECT',
  189.                       8=> 'SIZE',
  190.                       9=> 'SIZE');
  191.     if ($internal_date_sort == true{
  192.         $sort_on[0'ARRIVAL';
  193.         $sort_on[1'ARRIVAL';
  194.     }
  195.     if ($sent_folder == $mailbox{
  196.         $sort_on[2'TO';
  197.         $sort_on[3'TO';
  198.     }
  199.     if (!empty($sort_on[$sort])) {
  200.         $query "SORT ($sort_on[$sort]".strtoupper($default_charset).' ALL';
  201.         $sort_test sqimap_run_command_list ($imap_stream$querytrue$response$message$uid_support);
  202.     }
  203.     if (isset($sort_test[0])) {
  204.       for ($i=0,$iCnt=count($sort_test);$i<$iCnt;++$i{
  205.         for ($j 0$jCnt=count($sort_test[$i]);$j<$jCnt;++$j{
  206.             if (preg_match("/^\* SORT (.+)$/"$sort_test[$i][$j]$regs)) {
  207.                 $server_sort_array += preg_split("/ /"trim($regs[1]));
  208.             }
  209.         }
  210.       }
  211.     }
  212.  
  213.     if ($sort == || $sort == || $sort == || $sort == 8{
  214.        $server_sort_array array_reverse($server_sort_array);
  215.     }
  216.     if (!preg_match("/OK/"$response)) {
  217.        $server_sort_array 'no';
  218.     }
  219.     sqsession_register($server_sort_array'server_sort_array');
  220.     return $server_sort_array;
  221. }
  222.  
  223.  
  224. /**
  225.  * Get sort order from server if server does not have the SORT extension
  226.  * and return it as array for mailbox_display.
  227.  *
  228.  * @param  resource $imap_stream 
  229.  * @param  array    $mbxresponse response from a sqimap_mailbox_select
  230.  * @return array    $php_sort_array
  231.  */
  232. function sqimap_get_php_sort_order($imap_stream$mbxresponse{
  233.     global $uid_support;
  234.  
  235.     if (sqsession_is_registered('php_sort_array')) {
  236.         sqsession_unregister('php_sort_array');
  237.     }
  238.  
  239.     $php_sort_array array();
  240.  
  241.     if ($uid_support{
  242.         if (isset($mbxresponse['UIDNEXT']&& $mbxresponse['UIDNEXT']{
  243.                 $uidnext $mbxresponse['UIDNEXT']-1;
  244.         else {
  245.             $uidnext '*';
  246.         }
  247.         $query "SEARCH UID 1:$uidnext";
  248.         $uids sqimap_run_command ($imap_stream$querytrue$response$messagetrue);
  249.         if (isset($uids[0])) {
  250.             $php_sort_array array();
  251.             // EIMS workaround. EIMS returns the result as multiple untagged SEARCH responses
  252.             foreach($uids as $line{
  253.                 if (preg_match("/^\* SEARCH (.+)$/"$line$regs)) {
  254.                      $php_sort_array += preg_split("/ /"trim($regs[1]));
  255.                 }
  256.             }
  257.         }
  258.         if (!preg_match("/OK/"$response)) {
  259.             $php_sort_array 'no';
  260.         }
  261.     else {
  262.        $qty $mbxresponse['EXISTS'];
  263.        $php_sort_array range(1$qty);
  264.     }
  265.     sqsession_register($php_sort_array'php_sort_array');
  266.     return $php_sort_array;
  267. }
  268.  
  269.  
  270. /**
  271.  * Returns an indent array for printMessageinfo()
  272.  * This represents the amount of indent needed (value),
  273.  * for this message number (key)
  274.  *
  275.  * @param  resource $imap_stream 
  276.  * @return array message ID to indent level mappings
  277.  */
  278. function get_parent_level($imap_stream{
  279.     global $thread_new;
  280.     $parent "";
  281.     $child "";
  282.     $cutoff 0;
  283.  
  284.     $indent_array array();
  285.     if (!$thread_new{
  286.         $thread_new array();
  287.     }
  288.  
  289.     /* loop through the threads and take unwanted characters out
  290.        of the thread string then chop it up
  291.      */
  292.     $thread_count count($thread_new);
  293.     for ($i 0$i $thread_count$i++{
  294.         $thread_new[$ipreg_replace("/\s\(/""("$thread_new[$i]);
  295.         $thread_new[$ipreg_replace("/(\d+)/""$1|"$thread_new[$i]);
  296.         $thread_new[$ipreg_split("/\|/"$thread_new[$i]-1PREG_SPLIT_NO_EMPTY);
  297.     }
  298.  
  299.     /* looping through the parts of one message thread */
  300.     for ($i 0$i $thread_count$i++{
  301.         /* first grab the parent, it does not indent */
  302.  
  303.         if (isset($thread_new[$i][0])) {
  304.             if (preg_match("/(\d+)/"$thread_new[$i][0]$regs)) {
  305.                 $parent $regs[1];
  306.             }
  307.         }
  308.         $indent_array[$parent0;
  309.  
  310.         /*
  311.          * now the children, checking each thread portion for
  312.          * ),(, and space, adjusting the level and space values
  313.          * to get the indent level
  314.          */
  315.         $level 0;
  316.         $spaces array();
  317.         $spaces_total 0;
  318.         $indent 0;
  319.         $fake FALSE;
  320.         $thread_length count($thread_new[$i]);
  321.         for ($k=1;$k<$thread_length-1;$k++{
  322.             $chars count_chars($thread_new[$i][$k]1);
  323.             if (isset($chars['40'])) {       /* testing for ( */
  324.                 $level += $chars['40'];
  325.             }
  326.             if (isset($chars['41'])) {      /* testing for ) */
  327.                 $level -= $chars['41'];
  328.                 $spaces[$level0;
  329.                 /* if we were faking lets stop, this portion
  330.                  * of the thread is over
  331.                  */
  332.                 if ($level == $cutoff{
  333.                     $fake FALSE;
  334.                 }
  335.             }
  336.             if (isset($chars['32'])) {      /* testing for space */
  337.                 if (!isset($spaces[$level])) {
  338.                     $spaces[$level0;
  339.                 }
  340.                 $spaces[$level+= $chars['32'];
  341.             }
  342.             for ($x=0;$x<=$level;$x++{
  343.                 if (isset($spaces[$x])) {
  344.                     $spaces_total += $spaces[$x];
  345.                 }
  346.             }
  347.             $indent $level $spaces_total;
  348.             /* must have run into a message that broke the thread
  349.              * so we are adjusting for that portion
  350.              */
  351.             if ($fake == TRUE{
  352.                 $indent $indent +1;
  353.             }
  354.             if (preg_match("/(\d+)/"$thread_new[$i][$k]$regs)) {
  355.                 $child $regs[1];
  356.             }
  357.             /* the thread must be broken if $indent == 0
  358.              * so indent the message once and start faking it
  359.              */
  360.             if ($indent == 0{
  361.                 $indent 1;
  362.                 $fake TRUE;
  363.                 $cutoff $level;
  364.             }
  365.             /* dont need abs but if indent was negative
  366.              * errors would occur
  367.              */
  368.             $indent_array[$childabs($indent);
  369.             $spaces_total 0;
  370.         }
  371.     }
  372.     return $indent_array;
  373. }
  374.  
  375.  
  376. /**
  377.  * Returns an array with each element as a string representing one
  378.  * message-thread as returned by the IMAP server.
  379.  */
  380. function get_thread_sort($imap_stream{
  381.     global $thread_new$sort_by_ref$default_charset$server_sort_array$uid_support;
  382.     if (sqsession_is_registered('thread_new')) {
  383.         sqsession_unregister('thread_new');
  384.     }
  385.     if (sqsession_is_registered('server_sort_array')) {
  386.         sqsession_unregister('server_sort_array');
  387.     }
  388.     $thread_temp array ();
  389.     if ($sort_by_ref == 1{
  390.         $sort_type 'REFERENCES';
  391.     else {
  392.         $sort_type 'ORDEREDSUBJECT';
  393.     }
  394.     $query "THREAD $sort_type ".strtoupper($default_charset)." ALL";
  395.  
  396.     $thread_test sqimap_run_command ($imap_stream$querytrue$response$message$uid_support);
  397.     if (isset($thread_test[0])) {
  398.         for ($i=0,$iCnt=count($thread_test);$i<$iCnt;++$i{
  399.             if (preg_match("/^\* THREAD (.+)$/"$thread_test[$i]$regs)) {
  400.                 $thread_list trim($regs[1]);
  401.                 break;
  402.             }
  403.         }
  404.     else {
  405.         $thread_list "";
  406.     }
  407.     if (!preg_match("/OK/"$response)) {
  408.         $server_sort_array 'no';
  409.         return $server_sort_array;
  410.     }
  411.     if (isset($thread_list)) {
  412.         $thread_temp preg_split("//"$thread_list-1PREG_SPLIT_NO_EMPTY);
  413.     }
  414.  
  415.     $char_count count($thread_temp);
  416.     $counter 0;
  417.     $thread_new array();
  418.     $k 0;
  419.     $thread_new[0"";
  420.     for ($i=0;$i<$char_count;$i++{
  421.         if ($thread_temp[$i!= ')' && $thread_temp[$i!= '('{
  422.             $thread_new[$k$thread_new[$k$thread_temp[$i];
  423.         elseif ($thread_temp[$i== '('{
  424.             $thread_new[$k.= $thread_temp[$i];
  425.             $counter++;
  426.         elseif ($thread_temp[$i== ')'{
  427.             if ($counter 1{
  428.                 $thread_new[$k.= $thread_temp[$i];
  429.                 $counter $counter 1;
  430.             else {
  431.                 $thread_new[$k.= $thread_temp[$i];
  432.                 $k++;
  433.                 $thread_new[$k"";
  434.                 $counter $counter 1;
  435.             }
  436.         }
  437.     }
  438.  
  439.     sqsession_register($thread_new'thread_new');
  440.     $thread_new array_reverse($thread_new);
  441.     $thread_list implode(" "$thread_new);
  442.     $thread_list str_replace("("" "$thread_list);
  443.     $thread_list str_replace(")"" "$thread_list);
  444.     $thread_list preg_split("/\s/"$thread_list-1PREG_SPLIT_NO_EMPTY);
  445.     $server_sort_array $thread_list;
  446.  
  447.     sqsession_register($server_sort_array'server_sort_array');
  448.     return $thread_list;
  449. }
  450.  
  451.  
  452. function elapsedTime($start{
  453.     $stop gettimeofday();
  454.     $timepassed =  1000000 ($stop['sec'$start['sec']$stop['usec'$start['usec'];
  455.     return $timepassed;
  456. }
  457.  
  458.  
  459. /**
  460.  * Parses a string in an imap response. String starts with " or { which means it
  461.  * can handle double quoted strings and literal strings
  462.  *
  463.  * @param string $read imap response
  464.  * @param integer $i (reference) offset in string
  465.  * @return string $s parsed string without the double quotes or literal count
  466.  */
  467. function parseString($read,&$i{
  468.     $char $read{$i};
  469.     $s '';
  470.     if ($char == '"'{
  471.         $iPos = ++$i;
  472.         while (true{
  473.             $iPos strpos($read,'"',$iPos);
  474.             if (!$iPosbreak;
  475.             if ($iPos && $read{$iPos -1!= '\\'{
  476.                 $s substr($read,$i,($iPos-$i));
  477.                 $i $iPos;
  478.                 break;
  479.             }
  480.             $iPos++;
  481.             if ($iPos strlen($read)) {
  482.                 break;
  483.             }
  484.         }
  485.     else if ($char == '{'{
  486.         $lit_cnt '';
  487.         ++$i;
  488.         $iPos strpos($read,'}',$i);
  489.         if ($iPos{
  490.             $lit_cnt substr($read$i$iPos $i);
  491.             $i += strlen($lit_cnt3/* skip } + \r + \n */
  492.             /* Now read the literal */
  493.             $s ($lit_cnt substr($read,$i,$lit_cnt)'');
  494.             $i += $lit_cnt;
  495.             /* temp bugfix (SM 1.5 will have a working clean version)
  496.                too much work to implement that version right now */
  497.             --$i;
  498.         else /* should never happen */
  499.             $i += 3/* } + \r + \n */
  500.             $s '';
  501.         }
  502.     else {
  503.         return false;
  504.     }
  505.     ++$i;
  506.     return $s;
  507. }
  508.  
  509.  
  510. /**
  511.  * Parses a string containing an array from an imap response. String starts with ( and end with )
  512.  *
  513.  * @param string $read imap response
  514.  * @param integer $i (reference) offset in string
  515.  * @return array $a
  516.  */
  517. function parseArray($read,&$i{
  518.     $i strpos($read,'(',$i);
  519.     $i_pos strpos($read,')',$i);
  520.     $s substr($read,$i+1,$i_pos $i -1);
  521.     $a explode(' ',$s);
  522.     if ($i_pos{
  523.         $i $i_pos+1;
  524.         return $a;
  525.     else {
  526.         return false;
  527.     }
  528. }
  529.  
  530.  
  531. /**
  532.  * Parses a fetch response
  533.  * 
  534.  * @param array        $aResponse IMAP Response
  535.  * @param array        $aMessageList Placeholder array for results.  The keys of the
  536.  *                              placeholder array should be the UID so we can reconstruct the order.
  537.  * @return array    $aMessageList Associative array with messages.
  538.  */
  539. function parseFetch(&$aResponse$aMessageList array()) {
  540.     for($j=0$iCnt count($aResponse);$j<$iCnt++$j{
  541.         $aMsg array();
  542.         
  543.         $read implode(''$aResponse[$j]);
  544.         // Clear up some memory
  545.         unset($aResponse[$j]);
  546.         
  547.         /*
  548.             *<space>#id<space>FETCH<space>(....
  549.          */
  550.         
  551.         $i_space strpos($read,' '2);
  552.         $id substr($read2$i_space 2);
  553.         $aMsg['ID'$id;
  554.         $fetch substr($read$i_space+1,5);
  555.         
  556.         if (!is_numeric($id&& $fetch !== 'FETCH'{
  557.             $aMsg['ERROR'$read;
  558.             break;
  559.         }
  560.         
  561.         $i strpos($read'('$i_space+5);
  562.         $read substr($read$i+1);
  563.         $i_len strlen($read);
  564.         $i 0;
  565.         
  566.         while($i $i_len && $i !== false{
  567.             $read trim(substr($read$i));
  568.             $i_len strlen($read);
  569.             $i strpos($read' ');
  570.             $arg substr($read,0,$i);
  571.             ++$i;
  572.             
  573.             switch($arg{
  574.                 case 'UID':
  575.                     $i_pos strpos($read,' ',$i);
  576.                     if (!$i_pos{
  577.                         $i_pos strpos($read')'$i);
  578.                     }
  579.                     if ($i_pos{
  580.                         $unique_id substr($read$i$i_pos-$i);
  581.                         $i $i_pos 1;
  582.                     else {
  583.                         break 3;
  584.                     }
  585.                     break;
  586.                 case 'FLAGS':
  587.                     $flags parseArray($read$i);
  588.                     if (!$flagsbreak 3;
  589.                     $aFlags array();
  590.                     foreach($flags as $flag{
  591.                         $flag strtolower($flag);
  592.                         $aFlags[$flagtrue;                        
  593.                     }
  594.                     $aMsg['FLAGS'$aFlags;
  595.                     break;
  596.                 case 'RFC822.SIZE':
  597.                     $i_pos strpos($read' '$i);
  598.                     if (!$i_pos{
  599.                         $i_pos strpos($read')'$i);                    
  600.                     }
  601.                     if ($i_pos{
  602.                         $aMsg['SIZE'substr($read,$i,$i_pos-$i);
  603.                         $i $i_pos 1;
  604.                     else {
  605.                         break 3;
  606.                     }
  607.                     break;
  608.             case 'ENVELOPE':
  609.                 // sqimap_parse_address($read,$i,$aMsg);
  610.                 break// to be implemented, moving imap code out of the Message class
  611.             case 'BODYSTRUCTURE':
  612.                 break// to be implemented, moving imap code out of the Message class
  613.             case 'INTERNALDATE':
  614.                 $aMsg['INTERNALDATE'trim(str_replace('  '' ',parseString($read,$i)));
  615.                 break;
  616.             case 'BODY.PEEK[HEADER.FIELDS':
  617.             case 'BODY[HEADER.FIELDS':
  618.                 $i strpos($read,'{',$i)// header is always returned as literal because it contain \n characters
  619.                 $header parseString($read,$i);
  620.                 if ($header === falsebreak 2;
  621.                 /* First we replace all \r\n by \n, and unfold the header */
  622.                 $hdr trim(str_replace(array("\r\n""\n\t""\n "),array("\n"' '' ')$header));
  623.                 /* Now we can make a new header array with
  624.                    each element representing a headerline  */
  625.                 $aHdr explode("\n" $hdr);
  626.                 $aReceived array();
  627.                 foreach ($aHdr as $line{
  628.                     $pos strpos($line':');
  629.                     if ($pos 0{
  630.                         $field strtolower(substr($line0$pos));
  631.                         if (!strstr($field,' ')) /* valid field */
  632.                             $value trim(substr($line$pos+1));
  633.                             switch($field{
  634.                                 case 'date':
  635.                                     $aMsg['date'trim(str_replace('  '' '$value));
  636.                                     break;
  637.                                 case 'x-priority'$aMsg['x-priority'($value? (int) $value{03break;
  638.                                 case 'priority':
  639.                                 case 'importance':
  640.                                     // duplicate code with Rfc822Header.cls:parsePriority()
  641.                                     if (!isset($aMsg['x-priority'])) {
  642.                                         $aPrio preg_split('/\s/',trim($value));
  643.                                         $sPrio strtolower(array_shift($aPrio));
  644.                                         if  (is_numeric($sPrio)) {
  645.                                             $iPrio = (int) $sPrio;
  646.                                         elseif $sPrio == 'non-urgent' || $sPrio == 'low' {
  647.                                             $iPrio 5;
  648.                                         elseif $sPrio == 'urgent' || $sPrio == 'high' {
  649.                                             $iPrio 1;
  650.                                         else {
  651.                                             // default is normal priority
  652.                                             $iPrio 3;
  653.                                         }
  654.                                         $aMsg['x-priority'$iPrio;
  655.                                     }
  656.                                     break;
  657.                                 case 'content-type':
  658.                                     $type $value;
  659.                                     if ($pos strpos($type";")) {
  660.                                         $type substr($type0$pos);
  661.                                     }
  662.                                     $type explode("/"$type);
  663.                                     if(!is_array($type|| count($type2{
  664.                                         $aMsg['content-type'array('text','plain');
  665.                                     else {
  666.                                         $aMsg['content-type'array(strtolower($type[0]),strtolower($type[1]));
  667.                                     }
  668.                                     break;
  669.                                 case 'received':
  670.                                     $aMsg['received'][$value;
  671.                                     break;
  672.                                 default:
  673.                                     $aMsg[$field$value;
  674.                                     break;
  675.                             }
  676.                         }
  677.                     }
  678.                 }
  679.                 break;
  680.             default:
  681.                 ++$i;
  682.                 break;
  683.             }
  684.         }
  685.         if (!empty($unique_id)) {
  686.             $msgi "$unique_id";
  687.             $aMsg['UID'$unique_id;
  688.        else {
  689.             $msgi '';
  690.        }
  691.        $aMessageList[$msgi$aMsg;
  692.        $aResponse[$jNULL;
  693.     }
  694.     return $aMessageList;
  695. }
  696.  
  697. /**
  698.  * Normalise the different Priority headers into a uniform value,
  699.  * namely that of the X-Priority header (1, 3, 5). Supports:
  700.  * Prioirty, X-Priority, Importance.
  701.  * X-MS-Mail-Priority is not parsed because it always coincides
  702.  * with one of the other headers.
  703.  *
  704.  * DUPLICATE CODE ALERT:
  705.  * NOTE: this is actually a duplicate from the function in
  706.  * class/mime/Rfc822Header.php.
  707.  */
  708. function parsePriority($sValue{
  709.     $aValue=preg_split('/\s/',trim($sValue));
  710.     $value strtolower(array_shift($aValue));
  711.     if is_numeric($value) ) {
  712.         return $value;
  713.     }
  714.     if $value == 'urgent' || $value == 'high' {
  715.         return 1;
  716.     elseif $value == 'non-urgent' || $value == 'low' {
  717.         return 5;
  718.     }
  719.     return 3;
  720. }
  721.  
  722.  
  723. /**
  724.  * Retrieves a list with headers, flags, size or internaldate from the imap server
  725.  */
  726. function sqimap_get_small_header_list($imap_stream$msg_list$show_num=false{
  727.     global $squirrelmail_language$color$data_dir$username$imap_server_type;
  728.     global $uid_support$allow_server_sort;
  729.     /* Get the small headers for each message in $msg_list */
  730.     $maxmsg sizeof($msg_list);
  731.     if ($show_num != '999999'{
  732.         $msgs_str sqimap_message_list_squisher($msg_list);
  733.     else {
  734.         $msgs_str '1:*';
  735.     }
  736.     $messages array();
  737.     $read_list array();
  738.  
  739.     /*
  740.      * We need to return the data in the same order as the caller supplied
  741.      * in $msg_list, but IMAP servers are free to return responses in
  742.      * whatever order they wish... So we need to re-sort manually
  743.      */
  744.     for ($i 0$i sizeof($msg_list)$i++{
  745.         $messages["$msg_list[$i]"array();
  746.     }
  747.  
  748.     $internaldate getPref($data_dir$username'internal_date_sort'SMPREF_ON);
  749.     if ($internaldate{
  750.         $query "FETCH $msgs_str (FLAGS UID RFC822.SIZE INTERNALDATE BODY.PEEK[HEADER.FIELDS (Date To Cc From Subject X-Priority Importance Priority Content-Type)])";
  751.     else {
  752.         $query "FETCH $msgs_str (FLAGS UID RFC822.SIZE BODY.PEEK[HEADER.FIELDS (Date To Cc From Subject X-Priority Importance Priority Content-Type)])";
  753.     }
  754.     $read_list sqimap_run_command_list ($imap_stream$querytrue$response$message$uid_support);
  755.     $i 0;
  756.  
  757.     foreach ($read_list as $r{
  758.         /* initialize/reset vars */
  759.         $subject _("(no subject)");
  760.         $from _("Unknown Sender");
  761.         $priority 0;
  762.         $messageid '<>';
  763.         $type array('','');
  764.         $cc $to $inrepto '';
  765.         $size 0;
  766.  
  767.         // use unset because we do isset below
  768.         unset($date);
  769.         unset($internal_date);
  770.  
  771.         $flag_seen $flag_answered $flag_deleted $flag_flagged false;
  772.  
  773.         $read implode('',$r);
  774.  
  775.         /*
  776.          * #id<space>FETCH<space>(
  777.          */
  778.  
  779.         /* extract the message id */
  780.         $i_space strpos($read,' ',2);
  781.         $id substr($read,2,$i_space-2);
  782.         $fetch substr($read,$i_space+1,5);
  783.         if (!is_numeric($id&& $fetch !== 'FETCH'{
  784.             set_up_language($squirrelmail_language);
  785.             echo '<br /><b><font color="'.$color[2].'">' .
  786.                  _("ERROR: Could not complete request.".
  787.                  '</b><br />' .
  788.                  _("Unknown response from IMAP server:"' 1.' .
  789.                  sm_encode_html_special_chars($read"</font><br />\n";
  790.                  break;
  791.         }
  792.         $i strpos($read,'(',$i_space+5);
  793.         $read substr($read,$i+1);
  794.         $i_len strlen($read);
  795.         $i 0;
  796.         while ($i $i_len && $i !== false{
  797.             /* get argument */
  798.             $read trim(substr($read,$i));
  799.             $i_len strlen($read);
  800.             $i strpos($read,' ');
  801.             $arg substr($read,0,$i);
  802.             ++$i;
  803.             switch ($arg)
  804.             {
  805.             case 'UID':
  806.                 $i_pos strpos($read,' ',$i);
  807.                 if (!$i_pos{
  808.                     $i_pos strpos($read,')',$i);
  809.                 }
  810.                 if ($i_pos{
  811.                     $unique_id substr($read,$i,$i_pos-$i);
  812.                     $i $i_pos+1;
  813.                 else {
  814.                     break 3;
  815.                 }
  816.                 break;
  817.             case 'FLAGS':
  818.                 $flags parseArray($read,$i);
  819.                 if (!$flagsbreak 3;
  820.                 foreach ($flags as $flag{
  821.                     $flag strtolower($flag);
  822.                     switch ($flag)
  823.                     {
  824.                     case '\\seen'$flag_seen truebreak;
  825.                     case '\\answered'$flag_answered truebreak;
  826.                     case '\\deleted'$flag_deleted truebreak;
  827.                     case '\\flagged'$flag_flagged truebreak;
  828.                     defaultbreak;
  829.                     }
  830.                 }
  831.                 break;
  832.             case 'RFC822.SIZE':
  833.                 $i_pos strpos($read,' ',$i);
  834.                 if (!$i_pos{
  835.                     $i_pos strpos($read,')',$i);
  836.                 }
  837.                 if ($i_pos{
  838.                     $size substr($read,$i,$i_pos-$i);
  839.                     $i $i_pos+1;
  840.                 else {
  841.                     break 3;
  842.                 }
  843.  
  844.                 break;
  845.             case 'INTERNALDATE':
  846.                 $internal_date parseString($read,$i);
  847.                 //if ($tmpdate === false) break 3;
  848.                 //$tmpdate = str_replace('  ',' ',$tmpdate);
  849.                 //$tmpdate = explode(' ',$tmpdate);
  850.                 //$date = str_replace('-',' ',$tmpdate[0]) . " " .
  851.                 //                            $tmpdate[1] . ' ' . $tmpdate[2];
  852.                 break;
  853.             case 'BODY.PEEK[HEADER.FIELDS':
  854.             case 'BODY[HEADER.FIELDS':
  855.                 $i strpos($read,'{',$i);
  856.                 $header parseString($read,$i);
  857.                 if ($header === falsebreak 2;
  858.                 /* First we replace all \r\n by \n, and unfold the header */
  859.                 $hdr trim(str_replace(array("\r\n""\n\t""\n "),array("\n"' '' ')$header));
  860.                 /* Now we can make a new header array with */
  861.                 /* each element representing a headerline  */
  862.                 $hdr explode("\n" $hdr);
  863.                 foreach ($hdr as $line{
  864.                     $pos strpos($line':');
  865.                     if ($pos 0{
  866.                         $field strtolower(substr($line0$pos));
  867.                         if (!strstr($field,' ')) /* valid field */
  868.                             $value trim(substr($line$pos+1));
  869.                             switch($field)
  870.                             {
  871.                             case 'to'$to $valuebreak;
  872.                             case 'cc'$cc $valuebreak;
  873.                             case 'from'$from $valuebreak;
  874.                             case 'date'$date $valuebreak;
  875.                             case 'x-priority':
  876.                             case 'importance':
  877.                             case 'priority':
  878.                                 $priority parsePriority($value)break;
  879.                             case 'subject':
  880.                                 $subject $value;
  881.                                 if ($subject == ""{
  882.                                     $subject _("(no subject)");
  883.                                 }
  884.                                 break;
  885.                             case 'content-type':
  886.                                 $type strtolower($value);
  887.                                 if ($pos strpos($type";")) {
  888.                                     $type substr($type0$pos);
  889.                                 }
  890.                                 $type explode("/"$type);
  891.                                 if empty($type[0]) ) {
  892.                                     $type[0'text';
  893. // I had this added, but not committed to CVS.... did it help fix something?
  894. //                                    $type[1] = 'plain';
  895.                                 }
  896.                                 if empty($type[1]) ) {
  897.                                     $type[1'plain';
  898.                                 }
  899.                                 break;
  900.                             defaultbreak;
  901.                             }
  902.                         }
  903.                     }
  904.                 }
  905.                 break;
  906.             default:
  907.                 ++$i;
  908.                 break;
  909.             }
  910.         }
  911.         if (isset($date|| isset($internal_date)) {
  912.             if (isset($internal_date)) {
  913.                 $internal_date str_replace('  '' '$internal_date);
  914.                 $tmpinternal_date  explode(' 'trim($internal_date));
  915.                 if (!isset($date)) {
  916.                     $date $internal_date;
  917.                     $tmpdate $tmpinternal_date;
  918.                 }
  919.             }
  920.             if (isset($date)) {
  921.                 $date str_replace('  '' '$date);
  922.                 $tmpdate  explode(' 'trim($date));
  923.                 if (!isset($internal_date)) {
  924.                     $internal_date $date;
  925.                     $tmpinternal_date $tmpdate;
  926.                 }
  927.             }
  928.         else {
  929.             $internal_date $tmpinternal_date $tmpdate $date array();
  930.         }
  931.         if ($uid_support{
  932.             $msgi ="$unique_id";
  933.             $messages[$msgi]['ID'$unique_id;
  934.         else {
  935.             $msgi "$id";
  936.             $messages[$msgi]['ID'$id;
  937.         }
  938.         $messages[$msgi]['RECEIVED_TIME_STAMP'getTimeStamp($tmpinternal_date);
  939.         $messages[$msgi]['RECEIVED_DATE_STRING'getDateString($messages[$msgi]['RECEIVED_TIME_STAMP']);
  940.         $messages[$msgi]['RECEIVED_DATE_STRING_FULL'getDateString($messages[$msgi]['RECEIVED_TIME_STAMP']TRUE);
  941.         $messages[$msgi]['TIME_STAMP'getTimeStamp($tmpdate);
  942.         $messages[$msgi]['DATE_STRING'getDateString($messages[$msgi]['TIME_STAMP']);
  943.         $messages[$msgi]['DATE_STRING_FULL'getDateString($messages[$msgi]['TIME_STAMP']TRUE);
  944.         $messages[$msgi]['FROM'$from//parseAddress($from);
  945.         $messages[$msgi]['SUBJECT'$subject;
  946. //        if (handleAsSent($mailbox)) {
  947.             $messages[$msgi]['TO'$to//parseAddress($to);
  948. //        }
  949.         $messages[$msgi]['PRIORITY'$priority;
  950.         $messages[$msgi]['CC'$cc//parseAddress($cc);
  951.         $messages[$msgi]['SIZE'$size;
  952.         $messages[$msgi]['TYPE0'$type[0];
  953.         $messages[$msgi]['TYPE1'$type[1];
  954.         $messages[$msgi]['FLAG_DELETED'$flag_deleted;
  955.         $messages[$msgi]['FLAG_ANSWERED'$flag_answered;
  956.         $messages[$msgi]['FLAG_SEEN'$flag_seen;
  957.         $messages[$msgi]['FLAG_FLAGGED'$flag_flagged;
  958.  
  959.         /* non server sort stuff */
  960.         if (!$allow_server_sort{
  961.             $from parseAddress($from);
  962.             if ($from[0][1]{
  963.                 $from decodeHeader($from[0][1]truefalse);
  964.             else {
  965.                 $from $from[0][0];
  966.             }
  967.             $messages[$msgi]['FROM-SORT'$from;
  968.             $subject_sort strtolower(decodeHeader($subjecttruefalse));
  969.             if (preg_match("/^(?:(?:vedr|sv|re|aw|fw|fwd|\[\w\]):\s*)*\s*(.*)$/si"$subject_sort$matches)){
  970.                 $messages[$msgi]['SUBJECT-SORT'$matches[1];
  971.             else {
  972.                 $messages[$msgi]['SUBJECT-SORT'$subject_sort;
  973.             }
  974.             
  975.             $to parseAddress($to);
  976.             if ($to[0][1]{
  977.                    $to decodeHeader($to[0][1]truefalse);
  978.             else {
  979.                 $to $to[0][0];
  980.             }
  981.             $messages[$msgi]['TO-SORT'$to;
  982.         }
  983.         ++$msgi;
  984.     }
  985.     array_reverse($messages);
  986.     $new_messages array();
  987.     foreach ($messages as $i =>$message{
  988.         $new_messages[$message;
  989.     }
  990.     return $new_messages;
  991. }
  992.  
  993.  
  994. /**
  995.  * Obsolete?
  996.  */
  997. function sqimap_get_headerfield($imap_stream$field{
  998.     global $uid_support$squirrelmail_language;
  999.     $sid sqimap_session_id(false);
  1000.  
  1001.     $results array();
  1002.     $read_list array();
  1003.  
  1004.     $query "FETCH 1:* (UID BODY.PEEK[HEADER.FIELDS ($field)])";
  1005.     $readin_list sqimap_run_command_list ($imap_stream$querytrue$response$message$uid_support);
  1006.     $i 0;
  1007.  
  1008.     foreach ($readin_list as $r{
  1009.         $r implode('',$r);
  1010.         /* first we unfold the header */
  1011.         $r str_replace(array("\r\n""\n\t","\n\s"),array("\n",'',''),$r);
  1012.         /*
  1013.          * now we can make a new header array with each element representing
  1014.          * a headerline
  1015.          */
  1016.         $r explode("\n" $r);
  1017.         if (!$uid_support{
  1018.             if (!preg_match("/^\\*\s+([0-9]+)\s+FETCH/iAU",$r[0]$regs)) {
  1019.                 set_up_language($squirrelmail_language);
  1020.                 echo '<br /><b><font color="'.$color[2].'">' .
  1021.                       _("ERROR: Could not complete request.".
  1022.                       '</b><br />' .
  1023.                       _("Unknown response from IMAP server:"' 1.' .
  1024.                       $r[0"</font><br />\n";
  1025.             else {
  1026.                 $id $regs[1];
  1027.             }
  1028.         else {
  1029.             if (!preg_match("/^\\*\s+([0-9]+)\s+FETCH.*UID\s+([0-9]+)\s+/iAU",$r[0]$regs)) {
  1030.                 set_up_language($squirrelmail_language);
  1031.                 echo '<br /><b><font color="'.$color[2].'">' .
  1032.                      _("ERROR: Could not complete request.".
  1033.                      '</b><br />' .
  1034.                      _("Unknown response from IMAP server:"' 1.' .
  1035.                      $r[0"</font><br />\n";
  1036.             else {
  1037.                 $id $regs[2];
  1038.             }
  1039.         }
  1040.         $field $r[1];
  1041.         $field substr($field,strlen($field)+2);
  1042.         $result[array($id,$field);
  1043.     }
  1044.     return $result;
  1045. }
  1046.  
  1047.  
  1048. /**
  1049.  * Returns a message array with all the information about a message.
  1050.  * See the documentation folder for more information about this array.
  1051.  */
  1052. function sqimap_get_message($imap_stream$id$mailbox{
  1053.     global $uid_support;
  1054.  
  1055.     // typecast to int to prohibit 1:* msgs sets
  1056.     $id = (int) $id;
  1057.     $flags array();
  1058.     $read sqimap_run_command($imap_stream"FETCH $id (FLAGS BODYSTRUCTURE)"true$response$message$uid_support);
  1059.     if ($read{
  1060.         if (preg_match('/.+FLAGS\s\((.*)\)\s/AUi',$read[0],$regs)) {
  1061.             if (trim($regs[1])) {
  1062.                 $flags preg_split('/ /'$regs[1],-1,PREG_SPLIT_NO_EMPTY);
  1063.             }
  1064.         }
  1065.     else {
  1066.         /* the message was not found, maybe the mailbox was modified? */
  1067.         global $sort$startMessage$color;
  1068.  
  1069.         $errmessage _("The server couldn't find the message you requested.".
  1070.             '<p>'._("Most probably your message list was out of date and the message has been moved away or deleted (perhaps by another program accessing the same mailbox).");
  1071.         /* this will include a link back to the message list */
  1072.         error_message($errmessage$mailbox$sort(int) $startMessage$color);
  1073.         exit;
  1074.     }
  1075.     $bodystructure implode('',$read);
  1076.     $msg =  mime_structure($bodystructure,$flags);
  1077.     $read sqimap_run_command($imap_stream"FETCH $id BODY[HEADER]"true$response$message$uid_support);
  1078.     $rfc822_header new Rfc822Header();
  1079.     $rfc822_header->parseHeader($read);
  1080.     $msg->rfc822_header $rfc822_header;
  1081.  
  1082.     parse_message_entities($msg$id$imap_stream);
  1083.     return $msg;
  1084. }
  1085.  
  1086.  
  1087. /**
  1088.  * Recursively parse embedded messages (if any) in the given
  1089.  * message, building correct rfc822 headers for each one
  1090.  *
  1091.  * @param object $msg The message object to scan for attached messages
  1092.  *                     NOTE: this is passed by reference!  Changes made
  1093.  *                     within will affect the caller's copy of $msg!
  1094.  * @param int $id The top-level message UID on the IMAP server, even
  1095.  *                 if the $msg being passed in is only an attached entity
  1096.  *                 thereof.
  1097.  * @param resource $imap_stream A live connection to the IMAP server.
  1098.  *
  1099.  * @return void 
  1100.  *
  1101.  * @since 1.4.11
  1102.  *
  1103.  */
  1104. function parse_message_entities(&$msg$id$imap_stream{
  1105.     global $uid_support;
  1106.     if (!empty($msg->entities)) foreach ($msg->entities as $i => $entity{
  1107.         if (is_object($entity&& strtolower(get_class($entity)) == 'message'{
  1108.             if (!empty($entity->rfc822_header)) {
  1109.                 $read sqimap_run_command($imap_stream"FETCH $id BODY["$entity->entity_id .".HEADER]"true$response$message$uid_support);
  1110.                 $rfc822_header new Rfc822Header();
  1111.                 $rfc822_header->parseHeader($read);
  1112.                 $msg->entities[$i]->rfc822_header $rfc822_header;
  1113.             }
  1114.             parse_message_entities($msg->entities[$i]$id$imap_stream);
  1115.         }
  1116.     }
  1117. }
  1118.  
  1119.  
  1120. /**
  1121.  * Copies specified messages to specified folder
  1122.  *
  1123.  * This function is removed from SquirrelMail 1.5.1 and later versions.
  1124.  * @param stream $imap_stream IMAP connection resource
  1125.  * @param string $start starting message id or uid.
  1126.  * @param string $end end message id or uid
  1127.  * @param string $mailbox target mailbox
  1128.  * @param boolean $handle_errors (since 1.4.8) handle errors
  1129.  * @return boolean (since 1.4.8) true, if message copy command was successful.
  1130.  *   false on error.
  1131.  * @since 0.4
  1132.  * @deprecated Use sqimap_msgs_list_copy() instead.
  1133.  */
  1134. function sqimap_messages_copy($imap_stream$start$end$mailbox$handle_errors=true{
  1135.     global $uid_support;
  1136.     $read sqimap_run_command ($imap_stream"COPY $start:$end \"$mailbox\""$handle_errors$response$message$uid_support);
  1137.     return ($response == 'OK');
  1138. }
  1139.  
  1140.  
  1141. /**
  1142.  * Deletes specified messages and moves them to trash if possible
  1143.  * Obsolete
  1144.  */
  1145. function sqimap_messages_delete($imap_stream$start$end$mailbox{
  1146.     global $move_to_trash$trash_folder$auto_expunge$uid_support;
  1147.  
  1148.     if (($move_to_trash == true&& (sqimap_mailbox_exists($imap_stream$trash_folder&& ($mailbox != $trash_folder))) {
  1149.         /**
  1150.          * turn off internal error handling (fifth argument = false) and
  1151.          * ignore copy to trash errors (allows to delete messages when overquota)
  1152.          */
  1153.         sqimap_messages_copy ($imap_stream$start$end$trash_folderfalse);
  1154.     }
  1155.     sqimap_messages_flag ($imap_stream$start$end"Deleted"true);
  1156. }
  1157.  
  1158.  
  1159. /**
  1160.  * Sets the specified messages with specified flag
  1161.  */
  1162. function sqimap_messages_flag($imap_stream$start$end$flag$handle_errors{
  1163.     global $uid_support;
  1164.     $read sqimap_run_command ($imap_stream"STORE $start:$end +FLAGS (\\$flag)"$handle_errors$response$message$uid_support);
  1165. }
  1166.  
  1167.  
  1168. /* Remove specified flag from specified messages */
  1169. function sqimap_messages_remove_flag($imap_stream$start$end$flag$handle_errors{
  1170.     global $uid_support;
  1171.     $read sqimap_run_command ($imap_stream"STORE $start:$end -FLAGS (\\$flag)"$handle_errors$response$message$uid_support);
  1172. }
  1173.  
  1174.  
  1175. function sqimap_toggle_flag($imap_stream$id$flag$set$handle_errors{
  1176.     global $uid_support;
  1177.     $msgs_id sqimap_message_list_squisher($id);
  1178.     $set_string ($set '+' '-');
  1179.     return sqimap_run_command ($imap_stream"STORE $msgs_id ".$set_string."FLAGS ($flag)"$handle_errors$response$message$uid_support);
  1180. }
  1181.  
  1182.  
  1183. /**
  1184.  * Obsolete?
  1185.  */
  1186. function sqimap_get_small_header($imap_stream$id$sent{
  1187.     $res sqimap_get_small_header_list($imap_stream$id$sent);
  1188.     return $res[0];
  1189. }

Documentation generated on Mon, 13 Jan 2020 04:24:48 +0100 by phpDocumentor 1.4.3