Directory structure refactoring.
[siap.git] / ws / nusoap / lib / nusoapmime.php
CommitLineData
1c21f490
MS
1<?php
2/*
3$Id: nusoapmime.php,v 1.13 2010/04/26 20:15:08 snichol Exp $
4
5NuSOAP - Web Services Toolkit for PHP
6
7Copyright (c) 2002 NuSphere Corporation
8
9This library is free software; you can redistribute it and/or
10modify it under the terms of the GNU Lesser General Public
11License as published by the Free Software Foundation; either
12version 2.1 of the License, or (at your option) any later version.
13
14This library is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public
20License along with this library; if not, write to the Free Software
21Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23The NuSOAP project home is:
24http://sourceforge.net/projects/nusoap/
25
26The primary support for NuSOAP is the mailing list:
27nusoap-general@lists.sourceforge.net
28
29If you have any questions or comments, please email:
30
31Dietrich Ayala
32dietrich@ganx4.com
33http://dietrich.ganx4.com/nusoap
34
35NuSphere Corporation
36http://www.nusphere.com
37
38*/
39
40/*require_once('nusoap.php');*/
41/* PEAR Mail_MIME library */
42require_once('Mail/mimeDecode.php');
43require_once('Mail/mimePart.php');
44
45/**
46* nusoap_client_mime client supporting MIME attachments defined at
47* http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
48*
49* @author Scott Nichol <snichol@users.sourceforge.net>
50* @author Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list
51* @version $Id: nusoapmime.php,v 1.13 2010/04/26 20:15:08 snichol Exp $
52* @access public
53*/
54class nusoap_client_mime extends nusoap_client {
55 /**
56 * @var array Each array element in the return is an associative array with keys
57 * data, filename, contenttype, cid
58 * @access private
59 */
60 var $requestAttachments = array();
61 /**
62 * @var array Each array element in the return is an associative array with keys
63 * data, filename, contenttype, cid
64 * @access private
65 */
66 var $responseAttachments;
67 /**
68 * @var string
69 * @access private
70 */
71 var $mimeContentType;
72
73 /**
74 * adds a MIME attachment to the current request.
75 *
76 * If the $data parameter contains an empty string, this method will read
77 * the contents of the file named by the $filename parameter.
78 *
79 * If the $cid parameter is false, this method will generate the cid.
80 *
81 * @param string $data The data of the attachment
82 * @param string $filename The filename of the attachment (default is empty string)
83 * @param string $contenttype The MIME Content-Type of the attachment (default is application/octet-stream)
84 * @param string $cid The content-id (cid) of the attachment (default is false)
85 * @return string The content-id (cid) of the attachment
86 * @access public
87 */
88 function addAttachment($data, $filename = '', $contenttype = 'application/octet-stream', $cid = false) {
89 if (! $cid) {
90 $cid = md5(uniqid(time()));
91 }
92
93 $info['data'] = $data;
94 $info['filename'] = $filename;
95 $info['contenttype'] = $contenttype;
96 $info['cid'] = $cid;
97
98 $this->requestAttachments[] = $info;
99
100 return $cid;
101 }
102
103 /**
104 * clears the MIME attachments for the current request.
105 *
106 * @access public
107 */
108 function clearAttachments() {
109 $this->requestAttachments = array();
110 }
111
112 /**
113 * gets the MIME attachments from the current response.
114 *
115 * Each array element in the return is an associative array with keys
116 * data, filename, contenttype, cid. These keys correspond to the parameters
117 * for addAttachment.
118 *
119 * @return array The attachments.
120 * @access public
121 */
122 function getAttachments() {
123 return $this->responseAttachments;
124 }
125
126 /**
127 * gets the HTTP body for the current request.
128 *
129 * @param string $soapmsg The SOAP payload
130 * @return string The HTTP body, which includes the SOAP payload
131 * @access private
132 */
133 function getHTTPBody($soapmsg) {
134 if (count($this->requestAttachments) > 0) {
135 $params['content_type'] = 'multipart/related; type="text/xml"';
136 $mimeMessage = new Mail_mimePart('', $params);
137 unset($params);
138
139 $params['content_type'] = 'text/xml';
140 $params['encoding'] = '8bit';
141 $params['charset'] = $this->soap_defencoding;
142 $mimeMessage->addSubpart($soapmsg, $params);
143
144 foreach ($this->requestAttachments as $att) {
145 unset($params);
146
147 $params['content_type'] = $att['contenttype'];
148 $params['encoding'] = 'base64';
149 $params['disposition'] = 'attachment';
150 $params['dfilename'] = $att['filename'];
151 $params['cid'] = $att['cid'];
152
153 if ($att['data'] == '' && $att['filename'] <> '') {
154 if ($fd = fopen($att['filename'], 'rb')) {
155 $data = fread($fd, filesize($att['filename']));
156 fclose($fd);
157 } else {
158 $data = '';
159 }
160 $mimeMessage->addSubpart($data, $params);
161 } else {
162 $mimeMessage->addSubpart($att['data'], $params);
163 }
164 }
165
166 $output = $mimeMessage->encode();
167 $mimeHeaders = $output['headers'];
168
169 foreach ($mimeHeaders as $k => $v) {
170 $this->debug("MIME header $k: $v");
171 if (strtolower($k) == 'content-type') {
172 // PHP header() seems to strip leading whitespace starting
173 // the second line, so force everything to one line
174 $this->mimeContentType = str_replace("\r\n", " ", $v);
175 }
176 }
177
178 return $output['body'];
179 }
180
181 return parent::getHTTPBody($soapmsg);
182 }
183
184 /**
185 * gets the HTTP content type for the current request.
186 *
187 * Note: getHTTPBody must be called before this.
188 *
189 * @return string the HTTP content type for the current request.
190 * @access private
191 */
192 function getHTTPContentType() {
193 if (count($this->requestAttachments) > 0) {
194 return $this->mimeContentType;
195 }
196 return parent::getHTTPContentType();
197 }
198
199 /**
200 * gets the HTTP content type charset for the current request.
201 * returns false for non-text content types.
202 *
203 * Note: getHTTPBody must be called before this.
204 *
205 * @return string the HTTP content type charset for the current request.
206 * @access private
207 */
208 function getHTTPContentTypeCharset() {
209 if (count($this->requestAttachments) > 0) {
210 return false;
211 }
212 return parent::getHTTPContentTypeCharset();
213 }
214
215 /**
216 * processes SOAP message returned from server
217 *
218 * @param array $headers The HTTP headers
219 * @param string $data unprocessed response data from server
220 * @return mixed value of the message, decoded into a PHP type
221 * @access private
222 */
223 function parseResponse($headers, $data) {
224 $this->debug('Entering parseResponse() for payload of length ' . strlen($data) . ' and type of ' . $headers['content-type']);
225 $this->responseAttachments = array();
226 if (strstr($headers['content-type'], 'multipart/related')) {
227 $this->debug('Decode multipart/related');
228 $input = '';
229 foreach ($headers as $k => $v) {
230 $input .= "$k: $v\r\n";
231 }
232 $params['input'] = $input . "\r\n" . $data;
233 $params['include_bodies'] = true;
234 $params['decode_bodies'] = true;
235 $params['decode_headers'] = true;
236
237 $structure = Mail_mimeDecode::decode($params);
238
239 foreach ($structure->parts as $part) {
240 if (!isset($part->disposition) && (strstr($part->headers['content-type'], 'text/xml'))) {
241 $this->debug('Have root part of type ' . $part->headers['content-type']);
242 $root = $part->body;
243 $return = parent::parseResponse($part->headers, $part->body);
244 } else {
245 $this->debug('Have an attachment of type ' . $part->headers['content-type']);
246 $info['data'] = $part->body;
247 $info['filename'] = isset($part->d_parameters['filename']) ? $part->d_parameters['filename'] : '';
248 $info['contenttype'] = $part->headers['content-type'];
249 $info['cid'] = $part->headers['content-id'];
250 $this->responseAttachments[] = $info;
251 }
252 }
253
254 if (isset($return)) {
255 $this->responseData = $root;
256 return $return;
257 }
258
259 $this->setError('No root part found in multipart/related content');
260 return '';
261 }
262 $this->debug('Not multipart/related');
263 return parent::parseResponse($headers, $data);
264 }
265}
266
267/*
268 * For backwards compatiblity, define soapclientmime unless the PHP SOAP extension is loaded.
269 */
270if (!extension_loaded('soap')) {
271 class soapclientmime extends nusoap_client_mime {
272 }
273}
274
275/**
276* nusoap_server_mime server supporting MIME attachments defined at
277* http://www.w3.org/TR/SOAP-attachments. It depends on the PEAR Mail_MIME library.
278*
279* @author Scott Nichol <snichol@users.sourceforge.net>
280* @author Thanks to Guillaume and Henning Reich for posting great attachment code to the mail list
281* @version $Id: nusoapmime.php,v 1.13 2010/04/26 20:15:08 snichol Exp $
282* @access public
283*/
284class nusoap_server_mime extends nusoap_server {
285 /**
286 * @var array Each array element in the return is an associative array with keys
287 * data, filename, contenttype, cid
288 * @access private
289 */
290 var $requestAttachments = array();
291 /**
292 * @var array Each array element in the return is an associative array with keys
293 * data, filename, contenttype, cid
294 * @access private
295 */
296 var $responseAttachments;
297 /**
298 * @var string
299 * @access private
300 */
301 var $mimeContentType;
302
303 /**
304 * adds a MIME attachment to the current response.
305 *
306 * If the $data parameter contains an empty string, this method will read
307 * the contents of the file named by the $filename parameter.
308 *
309 * If the $cid parameter is false, this method will generate the cid.
310 *
311 * @param string $data The data of the attachment
312 * @param string $filename The filename of the attachment (default is empty string)
313 * @param string $contenttype The MIME Content-Type of the attachment (default is application/octet-stream)
314 * @param string $cid The content-id (cid) of the attachment (default is false)
315 * @return string The content-id (cid) of the attachment
316 * @access public
317 */
318 function addAttachment($data, $filename = '', $contenttype = 'application/octet-stream', $cid = false) {
319 if (! $cid) {
320 $cid = md5(uniqid(time()));
321 }
322
323 $info['data'] = $data;
324 $info['filename'] = $filename;
325 $info['contenttype'] = $contenttype;
326 $info['cid'] = $cid;
327
328 $this->responseAttachments[] = $info;
329
330 return $cid;
331 }
332
333 /**
334 * clears the MIME attachments for the current response.
335 *
336 * @access public
337 */
338 function clearAttachments() {
339 $this->responseAttachments = array();
340 }
341
342 /**
343 * gets the MIME attachments from the current request.
344 *
345 * Each array element in the return is an associative array with keys
346 * data, filename, contenttype, cid. These keys correspond to the parameters
347 * for addAttachment.
348 *
349 * @return array The attachments.
350 * @access public
351 */
352 function getAttachments() {
353 return $this->requestAttachments;
354 }
355
356 /**
357 * gets the HTTP body for the current response.
358 *
359 * @param string $soapmsg The SOAP payload
360 * @return string The HTTP body, which includes the SOAP payload
361 * @access private
362 */
363 function getHTTPBody($soapmsg) {
364 if (count($this->responseAttachments) > 0) {
365 $params['content_type'] = 'multipart/related; type="text/xml"';
366 $mimeMessage = new Mail_mimePart('', $params);
367 unset($params);
368
369 $params['content_type'] = 'text/xml';
370 $params['encoding'] = '8bit';
371 $params['charset'] = $this->soap_defencoding;
372 $mimeMessage->addSubpart($soapmsg, $params);
373
374 foreach ($this->responseAttachments as $att) {
375 unset($params);
376
377 $params['content_type'] = $att['contenttype'];
378 $params['encoding'] = 'base64';
379 $params['disposition'] = 'attachment';
380 $params['dfilename'] = $att['filename'];
381 $params['cid'] = $att['cid'];
382
383 if ($att['data'] == '' && $att['filename'] <> '') {
384 if ($fd = fopen($att['filename'], 'rb')) {
385 $data = fread($fd, filesize($att['filename']));
386 fclose($fd);
387 } else {
388 $data = '';
389 }
390 $mimeMessage->addSubpart($data, $params);
391 } else {
392 $mimeMessage->addSubpart($att['data'], $params);
393 }
394 }
395
396 $output = $mimeMessage->encode();
397 $mimeHeaders = $output['headers'];
398
399 foreach ($mimeHeaders as $k => $v) {
400 $this->debug("MIME header $k: $v");
401 if (strtolower($k) == 'content-type') {
402 // PHP header() seems to strip leading whitespace starting
403 // the second line, so force everything to one line
404 $this->mimeContentType = str_replace("\r\n", " ", $v);
405 }
406 }
407
408 return $output['body'];
409 }
410
411 return parent::getHTTPBody($soapmsg);
412 }
413
414 /**
415 * gets the HTTP content type for the current response.
416 *
417 * Note: getHTTPBody must be called before this.
418 *
419 * @return string the HTTP content type for the current response.
420 * @access private
421 */
422 function getHTTPContentType() {
423 if (count($this->responseAttachments) > 0) {
424 return $this->mimeContentType;
425 }
426 return parent::getHTTPContentType();
427 }
428
429 /**
430 * gets the HTTP content type charset for the current response.
431 * returns false for non-text content types.
432 *
433 * Note: getHTTPBody must be called before this.
434 *
435 * @return string the HTTP content type charset for the current response.
436 * @access private
437 */
438 function getHTTPContentTypeCharset() {
439 if (count($this->responseAttachments) > 0) {
440 return false;
441 }
442 return parent::getHTTPContentTypeCharset();
443 }
444
445 /**
446 * processes SOAP message received from client
447 *
448 * @param array $headers The HTTP headers
449 * @param string $data unprocessed request data from client
450 * @return mixed value of the message, decoded into a PHP type
451 * @access private
452 */
453 function parseRequest($headers, $data) {
454 $this->debug('Entering parseRequest() for payload of length ' . strlen($data) . ' and type of ' . $headers['content-type']);
455 $this->requestAttachments = array();
456 if (strstr($headers['content-type'], 'multipart/related')) {
457 $this->debug('Decode multipart/related');
458 $input = '';
459 foreach ($headers as $k => $v) {
460 $input .= "$k: $v\r\n";
461 }
462 $params['input'] = $input . "\r\n" . $data;
463 $params['include_bodies'] = true;
464 $params['decode_bodies'] = true;
465 $params['decode_headers'] = true;
466
467 $structure = Mail_mimeDecode::decode($params);
468
469 foreach ($structure->parts as $part) {
470 if (!isset($part->disposition) && (strstr($part->headers['content-type'], 'text/xml'))) {
471 $this->debug('Have root part of type ' . $part->headers['content-type']);
472 $return = parent::parseRequest($part->headers, $part->body);
473 } else {
474 $this->debug('Have an attachment of type ' . $part->headers['content-type']);
475 $info['data'] = $part->body;
476 $info['filename'] = isset($part->d_parameters['filename']) ? $part->d_parameters['filename'] : '';
477 $info['contenttype'] = $part->headers['content-type'];
478 $info['cid'] = $part->headers['content-id'];
479 $this->requestAttachments[] = $info;
480 }
481 }
482
483 if (isset($return)) {
484 return $return;
485 }
486
487 $this->setError('No root part found in multipart/related content');
488 return;
489 }
490 $this->debug('Not multipart/related');
491 return parent::parseRequest($headers, $data);
492 }
493}
494
495/*
496 * For backwards compatiblity
497 */
498class nusoapservermime extends nusoap_server_mime {
499}
500
501?>