[ Index ] |
|
Code source de Horde 3.1.3 |
1 <?php 2 3 require_once dirname(__FILE__) . '/Message.php'; 4 require_once dirname(__FILE__) . '/Part.php'; 5 require_once dirname(__FILE__) . '/../MIME.php'; 6 7 /** 8 * $Horde: framework/MIME/MIME/Structure.php,v 1.87.10.19 2006/05/04 18:03:25 slusarz Exp $ 9 * 10 * The MIME_Structure:: class provides methods for dealing with MIME mail. 11 * 12 * The default character set to use for messages should be defined in the 13 * variable $GLOBALS['mime_structure']['default_charset'] (defaults to US-ASCII 14 * per RFC 2045). 15 * 16 * TODO: Convert to OO 17 * 18 * Copyright 1999-2006 Chuck Hagenbuch <chuck@horde.org> 19 * Copyright 2002-2006 Michael Slusarz <slusarz@bigworm.colorado.edu> 20 * 21 * See the enclosed file COPYING for license information (LGPL). If you 22 * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. 23 * 24 * @author Chuck Hagenbuch <chuck@horde.org> 25 * @author Michael Slusarz <slusarz@bigworm.colorado.edu> 26 * @since Horde 1.3 27 * @package Horde_MIME 28 */ 29 class MIME_Structure { 30 31 /** 32 * Given the results of imap_fetchstructure(), parse the structure 33 * of the message, figuring out correct bodypart numbers, etc. 34 * 35 * @param stdClass $body The result of imap_fetchstructure(). 36 * 37 * @return &MIME_Message The message parsed into a MIME_Message object. 38 */ 39 function &parse($body) 40 { 41 $msgOb = &new MIME_Message(); 42 $msgOb->addPart(MIME_Structure::_parse($body)); 43 $msgOb->buildMessage(); 44 45 $ptr = array(&$msgOb); 46 MIME_Structure::_addMultipartInfo($ptr); 47 48 return $msgOb; 49 } 50 51 /** 52 * Given the results of imap_fetchstructure(), parse the structure 53 * of the message, figuring out correct bodypart numbers, etc. 54 * 55 * @access private 56 * 57 * @param stdClass $body The result of imap_fetchstructure(). 58 * @param string $ref The current bodypart. 59 * 60 * @return MIME_Part A MIME_Part object. 61 */ 62 function &_parse($body, $ref = 0) 63 { 64 static $message, $multipart; 65 66 if (!isset($message)) { 67 $message = MIME::type('message'); 68 $multipart = MIME::type('multipart'); 69 } 70 71 $mime_part = &new MIME_Part(); 72 73 /* Top multiparts don't get their own line. */ 74 if (empty($ref) && 75 (!isset($body->type) || ($body->type != $multipart))) { 76 $ref = 1; 77 } 78 79 MIME_Structure::_setInfo($body, $mime_part, $ref); 80 81 if (isset($body->type) && ($body->type == $message) && 82 $body->ifsubtype && ($body->subtype == 'RFC822')) { 83 $mime_part->setMIMEId($ref . '.0'); 84 } else { 85 $mime_part->setMIMEId($ref); 86 } 87 88 /* Deal with multipart data. */ 89 if (isset($body->parts)) { 90 $sub_id = 1; 91 foreach ($body->parts as $sub_part) { 92 /* Are we dealing with a multipart message? */ 93 if (isset($body->type) && ($body->type == $message) && 94 isset($sub_part->type) && ($sub_part->type == $multipart)) { 95 $sub_ref = $ref; 96 } else { 97 $sub_ref = (empty($ref)) ? $sub_id : $ref . '.' . $sub_id; 98 } 99 $mime_part->addPart(MIME_Structure::_parse($sub_part, $sub_ref), $sub_id++); 100 } 101 } 102 103 return $mime_part; 104 } 105 106 /** 107 * Given a mime part from imap_fetchstructure(), munge it into a 108 * useful form and make sure that any parameters which are missing 109 * are given default values. 110 * 111 * To specify the default character set, define the global variable 112 * $GLOBALS['mime_strucutre']['default_charset']. 113 * 114 * @access private 115 * 116 * @param stdClass $part The original part info. 117 * @param MIME_Part &$ob A MIME_Part object. 118 * @param string $ref The ID of this part. 119 */ 120 function _setInfo($part, &$ob, $ref) 121 { 122 /* Store Content-type information. */ 123 $primary_type = (isset($part->type)) ? String::lower($part->type) : MIME::type('text'); 124 $sec_type = ($part->ifsubtype && $part->subtype) ? String::lower($part->subtype) : 'x-unknown'; 125 $ob->setType($primary_type . '/' . $sec_type); 126 127 /* Set transfer encoding. */ 128 if (isset($part->encoding)) { 129 $encoding = $part->encoding; 130 $ob->setTransferEncoding($encoding); 131 } else { 132 $encoding = null; 133 } 134 135 /* Set transfer disposition. */ 136 $ob->setDisposition(($part->ifdisposition) ? String::lower($part->disposition) : MIME_DEFAULT_DISPOSITION); 137 138 /* If 'body' is set, set as the contents of the part. */ 139 if (isset($part->body)) { 140 $ob->setContents($part->body, $encoding); 141 } 142 143 /* If 'bytes' is set, store as information variable. */ 144 if (isset($part->bytes)) { 145 $ob->setBytes($part->bytes); 146 } 147 148 /* Set the part's identification string, if available. */ 149 if (!empty($ref) && $part->ifid) { 150 $ob->setContentID($part->id); 151 } 152 153 /* Go through the content-type parameters, if any. */ 154 foreach (MIME_Structure::_getParameters($part, 1) as $key => $val) { 155 if ($key == 'charset') { 156 $ob->setCharset($val); 157 } else { 158 $ob->setContentTypeParameter($key, $val); 159 } 160 } 161 162 /* Set the default character set. */ 163 if (($ob->getCharset() == 'us-ascii') && 164 isset($GLOBALS['mime_structure']['default_charset'])) { 165 $ob->setCharset($GLOBALS['mime_structure']['default_charset']); 166 } 167 168 /* Go through the disposition parameters, if any. */ 169 foreach (MIME_Structure::_getParameters($part, 2) as $key => $val) { 170 $ob->setDispositionParameter($key, $val); 171 } 172 173 /* Set the name. */ 174 if ($ob->getContentTypeParameter('filename')) { 175 $ob->setName($ob->getContentTypeParameter('filename')); 176 } elseif ($ob->getDispositionParameter('filename')) { 177 $ob->setName($ob->getDispositionParameter('filename')); 178 } 179 180 /* Set the description. */ 181 if (isset($part->description)) { 182 $ob->setDescription($part->description); 183 } 184 } 185 186 /** 187 * Get all parameters for a given portion of a message. 188 * 189 * @access private 190 * 191 * @param stdClass $part The original part info. 192 * @param integer $type The parameter type to retrieve. 193 * 1 = content 194 * 2 = disposition 195 * 196 * @return array An array of parameter key/value pairs. 197 */ 198 function _getParameters($part, $type) 199 { 200 $param_list = array(); 201 202 if ($type == 1) { 203 $ptype = 'parameters'; 204 } elseif ($type == 2) { 205 $ptype = 'dparameters'; 206 } 207 $pexists = 'if' . $ptype; 208 209 if ($part->$pexists) { 210 foreach ($part->$ptype as $param) { 211 $param->value = str_replace(array("\t", '\"'), array(' ', '"'), $param->value); 212 213 $res = MIME::decodeRFC2231($param->attribute . '=' . $param->value); 214 if ($res) { 215 $param->attribute = $res['attribute']; 216 $param->value = $res['value']; 217 } 218 $field = String::lower($param->attribute); 219 if ($field == 'type') { 220 if (($type = MIME::type($param->value))) { 221 $param_list['type'] = $type; 222 } 223 } else { 224 $param_list[$field] = $param->value; 225 } 226 } 227 } 228 229 return $param_list; 230 } 231 232 /** 233 * Set the special information for certain MIME types. 234 * 235 * @access private 236 * 237 * @param array &$parts The list of parts contained within the multipart 238 * object. 239 * @param array $info Information about the multipart structure. 240 */ 241 function _addMultipartInfo(&$parts, $info = array()) 242 { 243 if (empty($parts)) { 244 return; 245 } 246 247 foreach (array_keys($parts) as $key) { 248 $ptr = &$parts[$key]; 249 $new_info = $info; 250 251 if (isset($info['alt'])) { 252 $ptr->setInformation('alternative', (is_null($info['alt'])) ? '-' : $info['alt']); 253 } 254 if (isset($info['related'])) { 255 $ptr->setInformation('related_part', $info['related']->getMIMEId()); 256 if ($id = $ptr->getContentID()) { 257 $info['related']->addCID(array($ptr->getMIMEId() => $id)); 258 } 259 } 260 if (isset($info['rfc822'])) { 261 $ptr->setInformation('rfc822_part', $info['rfc822']); 262 } 263 264 switch ($ptr->getType()) { 265 case 'multipart/alternative': 266 $new_info['alt'] = $ptr->getMIMEId(); 267 break; 268 269 case 'multipart/related': 270 $new_info['related'] = &$ptr; 271 break; 272 273 case 'message/rfc822': 274 $new_info['rfc822'] = $ptr->getMIMEId(); 275 $ptr->setInformation('header', true); 276 break; 277 } 278 279 MIME_Structure::_addMultipartInfo($ptr->_parts, $new_info); 280 } 281 } 282 283 284 /** 285 * Attempts to build a MIME_Message object from a text message. 286 * 287 * @param string $text The text of the MIME message. 288 * 289 * @return MIME_Message A MIME_Message object, or false on error. 290 */ 291 function &parseTextMIMEMessage($text) 292 { 293 require_once 'Mail/mimeDecode.php'; 294 295 /* Set up the options for the mimeDecode class. */ 296 $decode_args = array(); 297 $decode_args['include_bodies'] = true; 298 $decode_args['decode_bodies'] = false; 299 $decode_args['decode_headers'] = false; 300 301 $mimeDecode = &new Mail_mimeDecode($text, MIME_PART_EOL); 302 if (!($structure = $mimeDecode->decode($decode_args))) { 303 $message = false; 304 } else { 305 /* Put the object into imap_parsestructure() form. */ 306 MIME_Structure::_convertMimeDecodeData($structure); 307 308 $message = MIME_Structure::parse($structure); 309 } 310 311 return $message; 312 } 313 314 /** 315 * Convert the output from mimeDecode::decode() into a structure that 316 * matches imap_fetchstructure() output. 317 * 318 * @access private 319 * 320 * @param stdClass &$ob The output from mimeDecode::decode(). 321 */ 322 function _convertMimeDecodeData(&$ob) 323 { 324 /* Primary content-type. */ 325 $ob->type = intval(MIME::type($ob->ctype_primary)); 326 327 /* Secondary content-type. */ 328 if (isset($ob->ctype_secondary)) { 329 $ob->subtype = String::upper($ob->ctype_secondary); 330 $ob->ifsubtype = 1; 331 } else { 332 $ob->ifsubtype = 0; 333 } 334 335 /* Content transfer encoding. */ 336 if (isset($ob->headers['content-transfer-encoding'])) { 337 $ob->encoding = MIME::encoding($ob->headers['content-transfer-encoding']); 338 } 339 340 /* Content-type and Disposition parameters. */ 341 $param_types = array ('ctype_parameters' => 'parameters', 342 'd_parameters' => 'dparameters'); 343 foreach ($param_types as $param_key => $param_value) { 344 $if_var = 'if' . $param_value; 345 if (isset($ob->$param_key)) { 346 $ob->$if_var = 1; 347 $ob->$param_value = array(); 348 foreach ($ob->$param_key as $key => $val) { 349 $newOb = &new stdClass; 350 $newOb->attribute = $key; 351 $newOb->value = $val; 352 array_push($ob->$param_value, $newOb); 353 } 354 } else { 355 $ob->$if_var = 0; 356 } 357 } 358 359 /* Content-Disposition. */ 360 if (isset($ob->headers['content-disposition'])) { 361 $ob->ifdisposition = 1; 362 $hdr = $ob->headers['content-disposition']; 363 $pos = strpos($hdr, ';'); 364 if ($pos !== false) { 365 $hdr = substr($hdr, 0, $pos); 366 } 367 $ob->disposition = $hdr; 368 } else { 369 $ob->ifdisposition = 0; 370 } 371 372 /* Content-ID. */ 373 if (isset($ob->headers['content-id'])) { 374 $ob->ifid = 1; 375 $ob->id = $ob->headers['content-id']; 376 } else { 377 $ob->ifid = 0; 378 } 379 380 /* Get file size (if 'body' text is set). */ 381 if (isset($ob->body)) { 382 $ob->bytes = strlen($ob->body); 383 } 384 385 /* Process parts also. */ 386 if (isset($ob->parts)) { 387 foreach (array_keys($ob->parts) as $key) { 388 MIME_Structure::_convertMimeDecodeData($ob->parts[$key]); 389 } 390 } 391 } 392 393 /** 394 * Builds an array consisting of MIME header/value pairs. 395 * 396 * @param string $headers A text string containing the headers (e.g. 397 * output from imap_fetchheader()). 398 * @param boolean $decode Should the headers be decoded? 399 * @param boolean $lowercase Should the keys be in lowercase? 400 * 401 * @return array An array consisting of the header name as the key and 402 * the header value as the value. 403 * A header with multiple entries will be stored in 404 * 'value' as an array. 405 */ 406 function parseMIMEHeaders($headers, $decode = true, $lowercase = false) 407 { 408 $header = ''; 409 $ob = array(); 410 411 foreach (explode("\n", $headers) as $val) { 412 if ($decode) { 413 $val = MIME::decode($val); 414 } 415 if (preg_match("/^([^\s]+)\:(.*)/", $val, $matches)) { 416 $val = trim($matches[2]); 417 $header = $matches[1]; 418 if (isset($ob[$header])) { 419 if (!is_array($ob[$header])) { 420 $temp = $ob[$header]; 421 $ob[$header] = array(); 422 $ob[$header][] = $temp; 423 } 424 $ob[$header][] = $val; 425 continue; 426 } 427 } else { 428 $val = ' ' . trim($val); 429 } 430 431 if (!empty($header)) { 432 if (isset($ob[$header])) { 433 if (is_array($ob[$header])) { 434 end($ob[$header]); 435 $ob[$header][key($ob[$header])] .= $val; 436 } else { 437 $ob[$header] .= $val; 438 } 439 } else { 440 $ob[$header] = $val; 441 } 442 } 443 } 444 445 return ($lowercase) ? array_change_key_case($ob, CASE_LOWER) : $ob; 446 } 447 448 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 18:01:28 2007 | par Balluche grâce à PHPXref 0.7 |