11 const WSC_CHARSET =
'UTF-8';
17 protected $params = array(
18 'include_bodies' =>
true,
19 'decode_bodies' =>
true,
20 'decode_headers' =>
true,
22 'default_charset' => self::WSC_CHARSET,
29 private $allowMTOMPart =
true;
48 if (!empty($params)) {
49 $this->params = array_merge($this->params, (array) $params);
60 public function decode($input, $convert =
true)
62 list($header, $body) = $this->splitBodyHeader($input);
63 $struct = $this->doDecode($header, $body);
64 if ($struct && $convert) {
65 $struct = $this->structure_part($struct);
82 $retorno = new \stdClass;
83 for ($iPart = 1; $iPart < count($vData)-1; $iPart++)
85 list($part_header, $part_body) = $this->splitBodyHeader( $vData[$iPart] );
86 $retorno->parts[] = $this->doDecode($part_header, $part_body);
88 $retorno->body = null;
91 if ($struct && $convert)
93 $struct = $this->structure_part($struct);
111 protected function doDecode($headers, $body, $default_ctype =
'text/plain')
114 $return = new \stdClass;
115 $headers = $this->parseHeaders($headers);
116 while (list(, $value) = each($headers)) {
117 $header_name = strtolower($value[
'name']);
118 if (isset($return->headers[$header_name]) && !is_array($return->headers[$header_name])) {
119 $return->headers[$header_name] = array($return->headers[$header_name]);
120 $return->headers[$header_name][] = $value[
'value'];
122 else if (isset($return->headers[$header_name])) {
123 $return->headers[$header_name][] = $value[
'value'];
126 $return->headers[$header_name] = $value[
'value'];
128 switch ($header_name) {
130 $content_type = $this->parseHeaderValue($value[
'value']);
131 if (preg_match(
'/([0-9a-z+.-]+)\/([0-9a-z+.-]+)/i', $content_type[
'value'], $regs)) {
132 $return->ctype_primary = $regs[1];
133 $return->ctype_secondary = $regs[2];
135 if (isset($content_type[
'other'])) {
136 while (list($p_name, $p_value) = each($content_type[
'other'])) {
137 $return->ctype_parameters[$p_name] = $p_value;
141 case 'content-disposition';
142 $content_disposition = $this->parseHeaderValue($value[
'value']);
143 $return->disposition = $content_disposition[
'value'];
144 if (isset($content_disposition[
'other'])) {
145 while (list($p_name, $p_value) = each($content_disposition[
'other'])) {
146 $return->d_parameters[$p_name] = $p_value;
150 case 'content-transfer-encoding':
151 $content_transfer_encoding = $this->parseHeaderValue($value[
'value']);
155 if (isset($content_type))
157 $ctype = strtolower($content_type[
'value']);
159 if ($ctype ==
'application/xop+xml') {
160 $ctype =
'application/xml';
165 case 'application/xop+xml':
166 $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding[
'value'] :
'7bit';
168 if (!isset($content_type[
'other'][
'boundary']))
170 $content_type[
'other'][
'boundary']=
'MIME_Boundary';
171 $parts = $this->boundarySplit($body, $content_type[
'other'][
'boundary']);
173 if (count($parts)==0)
175 $content_type[
'other'][
'boundary']=
'uuid:';
176 $parts = $this->boundarySplit($body, $content_type[
'other'][
'boundary']);
179 for ($i = 0; $i < count($parts); $i++)
181 list($part_header, $part_body) = $this->splitBodyHeader($parts[$i]);
182 $return->parts[] = $this->doDecode($part_header, $part_body, $default_ctype);
184 $return->body = $body;
187 $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding[
'value'] :
'7bit';
188 if ($this->params[
'include_bodies']) {
189 $return->body = $this->params[
'decode_bodies'] ? WSCMime::decode($body, $encoding) : $body;
193 $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding[
'value'] :
'7bit';
194 if ($this->params[
'include_bodies']) {
195 $return->body = $this->params[
'decode_bodies'] ? WSCMime::decode($body, $encoding) : $body;
198 case 'multipart/digest':
199 case 'multipart/alternative':
200 case 'multipart/related':
201 case 'multipart/mixed':
202 case 'multipart/signed':
203 case 'multipart/encrypted':
204 if (!isset($content_type[
'other'][
'boundary'])) {
207 $default_ctype = $ctype ===
'multipart/digest' ?
'message/rfc822' :
'text/plain';
208 $parts = $this->boundarySplit($body, $content_type[
'other'][
'boundary']);
209 for ($i = 0; $i < count($parts); $i++) {
210 list($part_header, $part_body) = $this->splitBodyHeader($parts[$i]);
211 $return->parts[] = $this->doDecode($part_header, $part_body, $default_ctype);
214 case 'message/rfc822':
216 $return->parts[] = $obj->decode($body,
false);
220 if ($this->params[
'include_bodies']) {
221 $return->body = $this->params[
'decode_bodies'] ? WSCMime::decode($body, $content_transfer_encoding[
'value']) : $body;
227 $ctype = explode(
'/', $default_ctype);
228 $return->ctype_primary = $ctype[0];
229 $return->ctype_secondary = $ctype[1];
230 if ($this->params[
'include_bodies']) {
231 $return->body = $this->params[
'decode_bodies'] ? WSCMime::decode($body) : $body;
249 $pos = strpos($input, $this->params[
'crlf'] . $this->params[
'crlf']);
250 if ($pos ===
false) {
253 $crlf_len = strlen($this->params[
'crlf']);
254 $header = substr($input, 0, $pos);
255 $body = substr($input, $pos + 2 * $crlf_len);
256 if (substr_compare($body, $this->params[
'crlf'], -$crlf_len) === 0) {
257 $body = substr($body, 0, -$crlf_len);
259 return array($header, $body);
273 $input = preg_replace(
'/' . $this->params[
'crlf'] .
"(\t| )/",
' ', $input);
274 $headers = explode($this->params[
'crlf'], trim($input));
275 foreach ($headers as $value) {
276 $hdr_name = substr($value, 0, $pos = strpos($value,
':'));
277 $hdr_value = substr($value, $pos+1);
278 if ($hdr_value[0] ==
' ') {
279 $hdr_value = substr($hdr_value, 1);
283 'value' => $this->params[
'decode_headers'] ? $this->decodeHeader($hdr_value) : $hdr_value,
302 $parts = preg_split(
'/;\s*/', $input);
303 if (!empty($parts)) {
304 $return[
'value'] = trim($parts[0]);
305 for ($n = 1; $n < count($parts); $n++) {
306 if (preg_match_all(
'/(([[:alnum:]]+)="?([^"]*)"?\s?;?)+/i', $parts[$n], $matches)) {
307 for ($i = 0; $i < count($matches[2]); $i++) {
308 $return[
'other'][strtolower($matches[2][$i])] = $matches[3][$i];
314 $return[
'value'] = trim($input);
329 $tmp = explode(
'--' . $boundary, $input);
330 for ($i = 1; $i < count($tmp)-1; $i++) {
346 return WSCMime::decode_mime_string($input, $this->params[
'default_charset']);
364 $mimeId = isset($part->mime_id)?$part->mime_id:FALSE;
365 $struct->mime_id = $mimeId?: (empty($parent) ? (string)$count :
"$parent.$count");
367 $headers = isset($part->headers)?$part->headers:null;
368 $struct->headers = $headers;
370 $ctype_primary = isset($part->ctype_primary)?$part->ctype_primary:null;
371 $struct->ctype_primary = $ctype_primary;
373 $ctype_secondary = isset($part->ctype_secondary)?$part->ctype_secondary:null;;
374 $struct->ctype_secondary = $ctype_secondary;
376 $ctype_parameters = isset($part->ctype_parameters)?$part->ctype_parameters:null;
377 $struct->ctype_parameters = $ctype_parameters;
379 $struct->mimetype = $ctype_primary .
'/' . $ctype_secondary;
382 if (isset($struct->headers[
'content-transfer-encoding']))
384 $struct->encoding = $struct->headers[
'content-transfer-encoding'];
387 if (isset($struct->ctype_parameters[
'charset']))
389 $struct->charset = $struct->ctype_parameters[
'charset'];
394 if (isset($part->d_parameters))
396 if (isset($part->d_parameters[
'filename']))
398 $filename = $part->d_parameters[
'filename'];
399 if (!$this->params[
'decode_headers'])
401 $filename = $this->decodeHeader($filename);
406 if (empty($filename) && (isset($part->ctype_parameters)))
408 if (isset($part->ctype_parameters[
'name']))
410 $filename = $part->ctype_parameters[
'name'];
411 if (!$this->params[
'decode_headers'])
413 $filename = $this->decodeHeader($filename);
417 $struct->filename = $filename;
419 $struct->body = $part->body;
420 $struct->size = strlen($part->body);
422 $disposition = isset($part->disposition)?$part->disposition:
'';
423 $struct->disposition = $disposition;
426 $parts = isset($part->parts)?(array)$part->parts:array();
428 foreach ($parts as $child_part)
430 $struct->parts[] = $this->structure_part($child_part, ++$count, $struct->mime_id);
structure_part(\stdClass $part, $count=0, $parent= '')
decodeMTOM($vData, $convert=true)
boundarySplit($input, $boundary)
decode($input, $convert=true)
doDecode($headers, $body, $default_ctype= 'text/plain')
__construct($params=array())