Changeset 716 in subversion
- Timestamp:
- Aug 28, 2007 8:00:15 AM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/devel-vnext/program/include/rcube_imap.inc
r702 r716 28 28 require_once 'lib/mime.inc'; 29 29 30 /** 31 * rcube_message_part 32 */ 33 require_once dirname(__FILE__) . '/rcube/message_part.php'; 34 35 /** 36 * rcube_header_sorter 37 */ 38 require_once dirname(__FILE__) . '/rcube/header_sorter.php'; 30 39 31 40 /** … … 295 304 /** 296 305 * Return the saved search set as hash array 306 * 307 * @return array 297 308 */ 298 309 function get_search_set() … … 372 383 } 373 384 else { 374 rc_main::tfk_debug('Filtered out: ' . $mbox_row);385 //rc_main::tfk_debug('Filtered out: ' . $mbox_row); 375 386 } 376 387 } … … 1436 1447 $moved = !($iil_move === false || $iil_move < 0); 1437 1448 1438 rc_main::tfk_debug('Iil_move: ' . $iil_move);1439 rc_main::tfk_debug('Moved? (#2): ' . $moved);1449 //rc_main::tfk_debug('Iil_move: ' . $iil_move); 1450 //rc_main::tfk_debug('Moved? (#2): ' . $moved); 1440 1451 1441 1452 // send expunge command in order to have the moved message … … 2083 2094 2084 2095 2085 function add_message_cache($key, $index, $headers, $struct=null) 2086 { 2087 if (!$this->caching_enabled || empty($key) || !is_object($headers) || empty($headers->uid)) 2088 return; 2089 2090 // check for an existing record (probly headers are cached but structure not) 2091 $sql_result = $this->db->query( 2092 "SELECT message_id 2093 FROM ". rc_main::get_table_name('messages')." 2094 WHERE user_id=? 2095 AND cache_key=? 2096 AND uid=? 2097 AND del<>1", 2098 $_SESSION['user_id'], 2099 $key, 2100 $headers->uid); 2101 2102 // update cache record 2103 if ($sql_arr = $this->db->fetch_assoc($sql_result)) 2104 { 2105 $this->db->query( 2106 "UPDATE ". rc_main::get_table_name('messages')." 2107 SET idx=?, headers=?, structure=? 2108 WHERE message_id=?", 2109 $index, 2110 serialize($headers), 2111 is_object($struct) ? serialize($struct) : NULL, 2112 $sql_arr['message_id'] 2096 /** 2097 * add_message_cache 2098 * @todo docs 2099 */ 2100 function add_message_cache($key, $index, $headers, $struct=null) 2101 { 2102 if (!$this->caching_enabled || empty($key) || !is_object($headers) || empty($headers->uid)) { 2103 return; 2104 } 2105 2106 // check for an existing record (probly headers are cached but structure not) 2107 $_query = "SELECT message_id FROM " . rc_main::get_table_name('messages'); 2108 $_query.= " WHERE user_id=?"; 2109 $_query.= " AND cache_key=?"; 2110 $_query.= " AND uid=?"; 2111 $_query.= " AND del<>1"; 2112 2113 $sql_result = $this->db->query( 2114 $_query, 2115 $_SESSION['user_id'], 2116 $key, 2117 $headers->uid 2113 2118 ); 2114 } 2115 else // insert new record 2116 { 2117 $this->db->query( 2118 "INSERT INTO ". rc_main::get_table_name('messages')." 2119 (user_id, del, cache_key, created, idx, uid, subject, ".$this->db->quoteIdentifier('from').", ".$this->db->quoteIdentifier('to').", cc, date, size, headers, structure) 2120 VALUES (?, 0, ?, ".$this->db->now().", ?, ?, ?, ?, ?, ?, ".$this->db->fromunixtime($headers->timestamp).", ?, ?, ?)", 2121 $_SESSION['user_id'], 2122 $key, 2123 $index, 2124 $headers->uid, 2125 (string)substr($this->decode_header($headers->subject, TRUE), 0, 128), 2126 (string)substr($this->decode_header($headers->from, TRUE), 0, 128), 2127 (string)substr($this->decode_header($headers->to, TRUE), 0, 128), 2128 (string)substr($this->decode_header($headers->cc, TRUE), 0, 128), 2129 (int)$headers->size, 2130 serialize($headers), 2131 is_object($struct) ? serialize($struct) : NULL 2119 2120 //rc_main::tfk_debug(var_export($headers, true)); 2121 2122 // update cache record 2123 if ($sql_arr = $this->db->fetch_assoc($sql_result)) { 2124 $_query = "UPDATE " . rc_main::get_table_name('messages'); 2125 $_query.= " SET idx=?, headers=?, structure=?"; 2126 $_query.= " WHERE message_id=?"; 2127 $this->db->query( 2128 $_query, 2129 $index, 2130 serialize($headers), 2131 is_object($struct) ? serialize($struct) : NULL, 2132 $sql_arr['message_id'] 2133 ); 2134 return; 2135 } 2136 2137 if (!isset($headers->timestamp) || empty($headers->timestamp)) { 2138 rc_main::tfk_debug('NO TIMESTAMP: ' . var_export($headers, true)); 2139 $headers->timestamp = mktime(); 2140 } 2141 2142 // insert new record 2143 $_query = "INSERT INTO " . rc_main::get_table_name('messages'); 2144 $_query.= " (user_id, del, cache_key, created, idx, uid, subject,"; 2145 $_query.= " " . $this->db->quoteIdentifier('from') . ","; 2146 $_query.= " " . $this->db->quoteIdentifier('to').","; 2147 $_query.= " cc, date, size, headers, structure)"; 2148 $_query.= " VALUES (?, 0, ?,"; 2149 $_query.= " " . $this->db->now() . ", ?, ?, ?, ?, ?, ?,"; 2150 $_query.= " " . $this->db->fromunixtime($headers->timestamp) . ","; 2151 $_query.= " ?, ?, ?)"; 2152 $this->db->query( 2153 $_query, 2154 $_SESSION['user_id'], 2155 $key, 2156 $index, 2157 $headers->uid, 2158 (string)substr($this->decode_header($headers->subject, TRUE), 0, 128), 2159 (string)substr($this->decode_header($headers->from, TRUE), 0, 128), 2160 (string)substr($this->decode_header($headers->to, TRUE), 0, 128), 2161 (string)substr($this->decode_header($headers->cc, TRUE), 0, 128), 2162 (int)$headers->size, 2163 serialize($headers), 2164 is_object($struct) ? serialize($struct) : NULL 2132 2165 ); 2133 } 2134 } 2135 2136 2137 function remove_message_cache($key, $index) 2138 { 2139 $this->db->query( 2140 "DELETE FROM ". rc_main::get_table_name('messages')." 2141 WHERE user_id=? 2142 AND cache_key=? 2143 AND idx=?", 2144 $_SESSION['user_id'], 2145 $key, 2146 $index); 2147 } 2148 2149 2150 function clear_message_cache($key, $start_index=1) 2151 { 2152 $this->db->query( 2153 "DELETE FROM ". rc_main::get_table_name('messages')." 2154 WHERE user_id=? 2155 AND cache_key=? 2156 AND idx>=?", 2157 $_SESSION['user_id'], 2158 $key, 2159 $start_index); 2160 } 2161 2162 2163 2164 2165 /* -------------------------------- 2166 * encoding/decoding methods 2167 * --------------------------------*/ 2168 2169 2170 function decode_address_list($input, $max=null, $decode=true) 2171 { 2172 $a = $this->_parse_address_list($input, $decode); 2173 $out = array(); 2174 2175 if (!is_array($a)) 2176 return $out; 2177 2178 $c = count($a); 2179 $j = 0; 2180 2181 foreach ($a as $val) 2182 { 2183 $j++; 2184 $address = $val['address']; 2185 $name = preg_replace(array('/^[\'"]/', '/[\'"]$/'), '', trim($val['name'])); 2186 if ($name && $address && $name != $address) 2187 $string = sprintf('%s <%s>', strpos($name, ',')!==FALSE ? '"'.$name.'"' : $name, $address); 2188 else if ($address) 2189 $string = $address; 2190 else if ($name) 2191 $string = $name; 2192 2193 $out[$j] = array('name' => $name, 2194 'mailto' => $address, 2195 'string' => $string); 2196 2197 if ($max && $j==$max) 2198 break; 2199 } 2200 2201 return $out; 2202 } 2203 2204 2205 function decode_header($input, $remove_quotes=FALSE) 2206 { 2207 $str = $this->decode_mime_string((string)$input); 2208 if ($str{0}=='"' && $remove_quotes) 2209 $str = str_replace('"', '', $str); 2210 2211 return $str; 2212 } 2213 2214 2215 /** 2216 * Decode a mime-encoded string to internal charset 2217 * 2218 * @access static 2219 */ 2220 function decode_mime_string($input, $fallback=null) 2221 { 2222 $out = ''; 2223 2224 $pos = strpos($input, '=?'); 2225 if ($pos !== false) 2226 { 2227 $out = substr($input, 0, $pos); 2228 2229 $end_cs_pos = strpos($input, "?", $pos+2); 2230 $end_en_pos = strpos($input, "?", $end_cs_pos+1); 2231 $end_pos = strpos($input, "?=", $end_en_pos+1); 2232 2233 $encstr = substr($input, $pos+2, ($end_pos-$pos-2)); 2234 $rest = substr($input, $end_pos+2); 2235 2236 $out .= rcube_imap::_decode_mime_string_part($encstr); 2237 $out .= rcube_imap::decode_mime_string($rest, $fallback); 2238 2239 return $out; 2240 } 2241 2242 // no encoding information, use fallback 2243 return rc_main::rcube_charset_convert($input, !empty($fallback) ? $fallback : 'ISO-8859-1'); 2244 } 2245 2246 2247 /** 2248 * Decode a part of a mime-encoded string 2249 * 2250 * @access static 2251 */ 2252 function _decode_mime_string_part($str) 2253 { 2254 $a = explode('?', $str); 2255 $count = count($a); 2256 2257 // should be in format "charset?encoding?base64_string" 2258 if ($count >= 3) 2259 { 2260 for ($i=2; $i<$count; $i++) 2261 $rest.=$a[$i]; 2262 2263 if (($a[1]=="B")||($a[1]=="b")) 2264 $rest = base64_decode($rest); 2265 else if (($a[1]=="Q")||($a[1]=="q")) 2266 { 2267 $rest = str_replace("_", " ", $rest); 2268 $rest = quoted_printable_decode($rest); 2269 } 2270 2271 return rc_main::rcube_charset_convert($rest, $a[0]); 2272 } 2273 else 2274 return $str; // we dont' know what to do with this 2275 } 2276 2277 2278 function mime_decode($input, $encoding='7bit') 2279 { 2280 switch (strtolower($encoding)) 2281 { 2282 case '7bit': 2283 return $input; 2284 break; 2285 2286 case 'quoted-printable': 2287 return quoted_printable_decode($input); 2288 break; 2289 2290 case 'base64': 2291 return base64_decode($input); 2292 break; 2293 2294 default: 2295 return $input; 2296 } 2297 } 2298 2299 2300 function mime_encode($input, $encoding='7bit') 2301 { 2302 switch ($encoding) 2303 { 2304 case 'quoted-printable': 2305 return quoted_printable_encode($input); 2306 break; 2307 2308 case 'base64': 2309 return base64_encode($input); 2310 break; 2311 2312 default: 2313 return $input; 2314 } 2315 } 2316 2317 2318 // convert body chars according to the ctype_parameters 2319 function charset_decode($body, $ctype_param) 2320 { 2321 if (is_array($ctype_param) && !empty($ctype_param['charset'])) 2322 return rc_main::rcube_charset_convert($body, $ctype_param['charset']); 2323 2324 // defaults to what is specified in the class header 2325 return rc_main::rcube_charset_convert($body, 'ISO-8859-1'); 2326 } 2327 2328 2329 2330 2331 /* -------------------------------- 2332 * private methods 2333 * --------------------------------*/ 2166 } 2167 2168 function remove_message_cache($key, $index) 2169 { 2170 $this->db->query( 2171 "DELETE FROM ". rc_main::get_table_name('messages')." 2172 WHERE user_id=? 2173 AND cache_key=? 2174 AND idx=?", 2175 $_SESSION['user_id'], 2176 $key, 2177 $index 2178 ); 2179 } 2180 2181 2182 function clear_message_cache($key, $start_index=1) 2183 { 2184 $this->db->query( 2185 "DELETE FROM ". rc_main::get_table_name('messages')." 2186 WHERE user_id=? 2187 AND cache_key=? 2188 AND idx>=?", 2189 $_SESSION['user_id'], 2190 $key, 2191 $start_index 2192 ); 2193 } 2194 2195 2196 2197 2198 /* -------------------------------- 2199 * encoding/decoding methods 2200 * --------------------------------*/ 2201 2202 2203 function decode_address_list($input, $max=null, $decode=true) 2204 { 2205 $a = $this->_parse_address_list($input, $decode); 2206 $out = array(); 2207 2208 if (!is_array($a)) { 2209 return $out; 2210 } 2211 2212 $c = count($a); 2213 $j = 0; 2214 2215 foreach ($a as $val) { 2216 $j++; 2217 $address = $val['address']; 2218 $name = preg_replace(array('/^[\'"]/', '/[\'"]$/'), '', trim($val['name'])); 2219 2220 if ($name && $address && $name != $address) { 2221 $string = sprintf('%s <%s>', strpos($name, ',')!==FALSE ? '"'.$name.'"' : $name, $address); 2222 } 2223 else if ($address) { 2224 $string = $address; 2225 } 2226 else if ($name) { 2227 $string = $name; 2228 } 2229 2230 $out[$j] = array( 2231 'name' => $name, 2232 'mailto' => $address, 2233 'string' => $string 2234 ); 2235 2236 if ($max && $j==$max) { 2237 break; 2238 } 2239 } 2240 return $out; 2241 } 2242 2243 2244 function decode_header($input, $remove_quotes=FALSE) 2245 { 2246 $str = $this->decode_mime_string((string)$input); 2247 if ($str{0}=='"' && $remove_quotes) { 2248 $str = str_replace('"', '', $str); 2249 } 2250 return $str; 2251 } 2252 2253 2254 /** 2255 * Decode a mime-encoded string to internal charset 2256 * 2257 * @access static 2258 */ 2259 static function decode_mime_string($input, $fallback=null) 2260 { 2261 $out = ''; 2262 2263 $pos = strpos($input, '=?'); 2264 if ($pos !== false) { 2265 $out = substr($input, 0, $pos); 2266 2267 $end_cs_pos = strpos($input, "?", $pos+2); 2268 $end_en_pos = strpos($input, "?", $end_cs_pos+1); 2269 $end_pos = strpos($input, "?=", $end_en_pos+1); 2270 2271 $encstr = substr($input, $pos+2, ($end_pos-$pos-2)); 2272 $rest = substr($input, $end_pos+2); 2273 2274 $out .= rcube_imap::_decode_mime_string_part($encstr); 2275 $out .= rcube_imap::decode_mime_string($rest, $fallback); 2276 2277 return $out; 2278 } 2279 2280 // no encoding information, use fallback 2281 return rc_main::rcube_charset_convert($input, !empty($fallback) ? $fallback : 'ISO-8859-1'); 2282 } 2283 2284 2285 /** 2286 * Decode a part of a mime-encoded string 2287 * 2288 * @access static 2289 */ 2290 static function _decode_mime_string_part($str) 2291 { 2292 $a = explode('?', $str); 2293 $count = count($a); 2294 2295 // should be in format "charset?encoding?base64_string" 2296 if ($count >= 3) { 2297 for ($i=2; $i<$count; $i++) { 2298 $rest.=$a[$i]; 2299 } 2300 2301 if (($a[1]=="B")||($a[1]=="b")) { 2302 $rest = base64_decode($rest); 2303 } 2304 else if (($a[1]=="Q")||($a[1]=="q")) { 2305 $rest = str_replace("_", " ", $rest); 2306 $rest = quoted_printable_decode($rest); 2307 } 2308 2309 return rc_main::rcube_charset_convert($rest, $a[0]); 2310 } 2311 return $str; // we dont' know what to do with this 2312 } 2313 2314 function mime_decode($input, $encoding='7bit') 2315 { 2316 switch (strtolower($encoding)) { 2317 case '7bit': 2318 return $input; 2319 break; 2320 2321 case 'quoted-printable': 2322 return quoted_printable_decode($input); 2323 break; 2324 2325 case 'base64': 2326 return base64_decode($input); 2327 break; 2328 2329 default: 2330 return $input; 2331 } 2332 } 2333 2334 function mime_encode($input, $encoding='7bit') 2335 { 2336 switch ($encoding) { 2337 case 'quoted-printable': 2338 return quoted_printable_encode($input); 2339 break; 2340 2341 case 'base64': 2342 return base64_encode($input); 2343 break; 2344 2345 default: 2346 return $input; 2347 } 2348 } 2349 2350 2351 // convert body chars according to the ctype_parameters 2352 function charset_decode($body, $ctype_param) 2353 { 2354 if (is_array($ctype_param) && !empty($ctype_param['charset'])) { 2355 return rc_main::rcube_charset_convert($body, $ctype_param['charset']); 2356 } 2357 2358 // defaults to what is specified in the class header 2359 return rc_main::rcube_charset_convert($body, 'ISO-8859-1'); 2360 } 2361 2362 2363 /* -------------------------------- 2364 * private methods 2365 * --------------------------------*/ 2334 2366 2335 2367 … … 2578 2610 return $result; 2579 2611 } 2580 }2581 2582 2583 /**2584 * Class representing a message part2585 */2586 class rcube_message_part2587 {2588 var $mime_id = '';2589 var $ctype_primary = 'text';2590 var $ctype_secondary = 'plain';2591 var $mimetype = 'text/plain';2592 var $disposition = '';2593 var $filename = '';2594 var $encoding = '8bit';2595 var $charset = '';2596 var $size = 0;2597 var $headers = array();2598 var $d_parameters = array();2599 var $ctype_parameters = array();2600 2601 }2602 2603 2604 /**2605 * rcube_header_sorter2606 *2607 * Class for sorting an array of iilBasicHeader objects in a predetermined order.2608 *2609 * @author Eric Stadtherr2610 */2611 class rcube_header_sorter2612 {2613 var $sequence_numbers = array();2614 2615 /**2616 * set the predetermined sort order.2617 *2618 * @param array $seqnums numerically indexed array of IMAP message sequence numbers2619 */2620 function set_sequence_numbers($seqnums)2621 {2622 $this->sequence_numbers = $seqnums;2623 }2624 2625 /**2626 * sort the array of header objects2627 *2628 * @param array $headers array of iilBasicHeader objects indexed by UID2629 */2630 function sort_headers(&$headers)2631 {2632 /*2633 * uksort would work if the keys were the sequence number, but unfortunately2634 * the keys are the UIDs. We'll use uasort instead and dereference the value2635 * to get the sequence number (in the "id" field).2636 *2637 * uksort($headers, array($this, "compare_seqnums"));2638 */2639 uasort($headers, array($this, "compare_seqnums"));2640 }2641 2642 /**2643 * get the position of a message sequence number in my sequence_numbers array2644 *2645 * @param integer $seqnum message sequence number contained in sequence_numbers2646 */2647 function position_of($seqnum)2648 {2649 $c = count($this->sequence_numbers);2650 for ($pos = 0; $pos <= $c; $pos++)2651 {2652 if ($this->sequence_numbers[$pos] == $seqnum)2653 return $pos;2654 }2655 return -1;2656 }2657 2658 /**2659 * Sort method called by uasort()2660 */2661 function compare_seqnums($a, $b)2662 {2663 // First get the sequence number from the header object (the 'id' field).2664 $seqa = $a->id;2665 $seqb = $b->id;2666 2667 // then find each sequence number in my ordered list2668 $posa = $this->position_of($seqa);2669 $posb = $this->position_of($seqb);2670 2671 // return the relative position as the comparison value2672 $ret = $posa - $posb;2673 return $ret;2674 }2675 2612 } 2676 2613 … … 2685 2622 */ 2686 2623 function quoted_printable_encode($input, $line_max=76, $space_conv=false) 2687 { 2688 $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); 2689 $lines = preg_split("/(?:\r\n|\r|\n)/", $input); 2690 $eol = "\r\n"; 2691 $escape = "="; 2692 $output = ""; 2693 2694 while( list(, $line) = each($lines)) 2695 { 2696 //$line = rtrim($line); // remove trailing white space -> no =20\r\n necessary 2697 $linlen = strlen($line); 2698 $newline = ""; 2699 for($i = 0; $i < $linlen; $i++) 2700 { 2701 $c = substr( $line, $i, 1 ); 2702 $dec = ord( $c ); 2703 if ( ( $i == 0 ) && ( $dec == 46 ) ) // convert first point in the line into =2E 2704 { 2705 $c = "=2E"; 2706 } 2707 if ( $dec == 32 ) 2708 { 2709 if ( $i == ( $linlen - 1 ) ) // convert space at eol only 2710 { 2711 $c = "=20"; 2712 } 2713 else if ( $space_conv ) 2714 { 2715 $c = "=20"; 2716 } 2717 } 2718 else if ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) // always encode "\t", which is *not* required 2719 { 2720 $h2 = floor($dec/16); 2721 $h1 = floor($dec%16); 2722 $c = $escape.$hex["$h2"].$hex["$h1"]; 2723 } 2724 2725 if ( (strlen($newline) + strlen($c)) >= $line_max ) // CRLF is not counted 2726 { 2727 $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay 2624 { 2625 $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); 2626 $lines = preg_split("/(?:\r\n|\r|\n)/", $input); 2627 $eol = "\r\n"; 2628 $escape = "="; 2629 $output = ""; 2630 2631 while( list(, $line) = each($lines)) { 2632 //$line = rtrim($line); // remove trailing white space -> no =20\r\n necessary 2633 $linlen = strlen($line); 2728 2634 $newline = ""; 2729 // check if newline first character will be point or not 2730 if ( $dec == 46 ) 2731 { 2732 $c = "=2E"; 2733 } 2734 } 2735 $newline .= $c; 2736 } // end of for 2737 $output .= $newline.$eol; 2635 for($i = 0; $i < $linlen; $i++) { 2636 $c = substr( $line, $i, 1 ); 2637 $dec = ord( $c ); 2638 if ( ( $i == 0 ) && ( $dec == 46 ) ) { 2639 // convert first point in the line into =2E 2640 $c = "=2E"; 2641 } 2642 if ( $dec == 32 ) 2643 { 2644 if ( $i == ( $linlen - 1 ) ) // convert space at eol only 2645 { 2646 $c = "=20"; 2647 } 2648 else if ( $space_conv ) 2649 { 2650 $c = "=20"; 2651 } 2652 } 2653 else if ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) // always encode "\t", which is *not* required 2654 { 2655 $h2 = floor($dec/16); 2656 $h1 = floor($dec%16); 2657 $c = $escape.$hex["$h2"].$hex["$h1"]; 2658 } 2659 2660 if ( (strlen($newline) + strlen($c)) >= $line_max ) // CRLF is not counted 2661 { 2662 $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay 2663 $newline = ""; 2664 // check if newline first character will be point or not 2665 if ( $dec == 46 ) { 2666 $c = "=2E"; 2667 } 2668 } 2669 $newline .= $c; 2670 } // end of for 2671 $output .= $newline.$eol; 2738 2672 } // end of while 2739 2673 2740 return trim($output); 2741 } 2742 2743 2744 ?> 2674 return trim($output); 2675 }
Note: See TracChangeset
for help on using the changeset viewer.
