3 $Id: nusoapmime.php,v 1.12 2007/04/17 16:34:03 snichol Exp $
5 NuSOAP - Web Services Toolkit for PHP
7 Copyright (c) 2002 NuSphere Corporation
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 The NuSOAP project home is:
24 http://sourceforge.net/projects/nusoap/
26 The primary support for NuSOAP is the mailing list:
27 nusoap-general@lists.sourceforge.net
29 If you have any questions or comments, please email:
33 http://dietrich.ganx4.com/nusoap
36 http://www.nusphere.com
40 /*require_once('nusoap.php');*/
41 /* PEAR Mail_MIME library */
42 require_once('Mail/mimeDecode.php');
43 require_once('Mail/mimePart.php');
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.
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.12 2007/04/17 16:34:03 snichol Exp $
54 class nusoap_client_mime extends nusoap_client {
56 * @var array Each array element in the return is an associative array with keys
57 * data, filename, contenttype, cid
60 var $requestAttachments = array();
62 * @var array Each array element in the return is an associative array with keys
63 * data, filename, contenttype, cid
66 var $responseAttachments;
74 * adds a MIME attachment to the current request.
76 * If the $data parameter contains an empty string, this method will read
77 * the contents of the file named by the $filename parameter.
79 * If the $cid parameter is false, this method will generate the cid.
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
88 function addAttachment($data, $filename = '', $contenttype = 'application/octet-stream', $cid = false) {
90 $cid = md5(uniqid(time()));
93 $info['data'] = $data;
94 $info['filename'] = $filename;
95 $info['contenttype'] = $contenttype;
98 $this->requestAttachments[] = $info;
104 * clears the MIME attachments for the current request.
108 function clearAttachments() {
109 $this->requestAttachments = array();
113 * gets the MIME attachments from the current response.
115 * Each array element in the return is an associative array with keys
116 * data, filename, contenttype, cid. These keys correspond to the parameters
119 * @return array The attachments.
122 function getAttachments() {
123 return $this->responseAttachments;
127 * gets the HTTP body for the current request.
129 * @param string $soapmsg The SOAP payload
130 * @return string The HTTP body, which includes the SOAP payload
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);
139 $params['content_type'] = 'text/xml';
140 $params['encoding'] = '8bit';
141 $params['charset'] = $this->soap_defencoding;
142 $mimeMessage->addSubpart($soapmsg, $params);
144 foreach ($this->requestAttachments as $att) {
147 $params['content_type'] = $att['contenttype'];
148 $params['encoding'] = 'base64';
149 $params['disposition'] = 'attachment';
150 $params['dfilename'] = $att['filename'];
151 $params['cid'] = $att['cid'];
153 if ($att['data'] == '' && $att['filename'] <> '') {
154 if ($fd = fopen($att['filename'], 'rb')) {
155 $data = fread($fd, filesize($att['filename']));
160 $mimeMessage->addSubpart($data, $params);
162 $mimeMessage->addSubpart($att['data'], $params);
166 $output = $mimeMessage->encode();
167 $mimeHeaders = $output['headers'];
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);
178 return $output['body'];
181 return parent::getHTTPBody($soapmsg);
185 * gets the HTTP content type for the current request.
187 * Note: getHTTPBody must be called before this.
189 * @return string the HTTP content type for the current request.
192 function getHTTPContentType() {
193 if (count($this->requestAttachments) > 0) {
194 return $this->mimeContentType;
196 return parent::getHTTPContentType();
200 * gets the HTTP content type charset for the current request.
201 * returns false for non-text content types.
203 * Note: getHTTPBody must be called before this.
205 * @return string the HTTP content type charset for the current request.
208 function getHTTPContentTypeCharset() {
209 if (count($this->requestAttachments) > 0) {
212 return parent::getHTTPContentTypeCharset();
216 * processes SOAP message returned from server
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
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');
229 foreach ($headers as $k => $v) {
230 $input .= "$k: $v\r\n";
232 $params['input'] = $input . "\r\n" . $data;
233 $params['include_bodies'] = true;
234 $params['decode_bodies'] = true;
235 $params['decode_headers'] = true;
237 $structure = Mail_mimeDecode::decode($params);
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']);
243 $return = parent::parseResponse($part->headers, $part->body);
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;
254 if (isset($return)) {
255 $this->responseData = $root;
259 $this->setError('No root part found in multipart/related content');
262 $this->debug('Not multipart/related');
263 return parent::parseResponse($headers, $data);
268 * For backwards compatiblity, define soapclientmime unless the PHP SOAP extension is loaded.
270 if (!extension_loaded('soap')) {
271 class soapclientmime extends nusoap_client_mime {
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.
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.12 2007/04/17 16:34:03 snichol Exp $
284 class nusoap_server_mime extends nusoap_server {
286 * @var array Each array element in the return is an associative array with keys
287 * data, filename, contenttype, cid
290 var $requestAttachments = array();
292 * @var array Each array element in the return is an associative array with keys
293 * data, filename, contenttype, cid
296 var $responseAttachments;
301 var $mimeContentType;
304 * adds a MIME attachment to the current response.
306 * If the $data parameter contains an empty string, this method will read
307 * the contents of the file named by the $filename parameter.
309 * If the $cid parameter is false, this method will generate the cid.
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
318 function addAttachment($data, $filename = '', $contenttype = 'application/octet-stream', $cid = false) {
320 $cid = md5(uniqid(time()));
323 $info['data'] = $data;
324 $info['filename'] = $filename;
325 $info['contenttype'] = $contenttype;
328 $this->responseAttachments[] = $info;
334 * clears the MIME attachments for the current response.
338 function clearAttachments() {
339 $this->responseAttachments = array();
343 * gets the MIME attachments from the current request.
345 * Each array element in the return is an associative array with keys
346 * data, filename, contenttype, cid. These keys correspond to the parameters
349 * @return array The attachments.
352 function getAttachments() {
353 return $this->requestAttachments;
357 * gets the HTTP body for the current response.
359 * @param string $soapmsg The SOAP payload
360 * @return string The HTTP body, which includes the SOAP payload
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);
369 $params['content_type'] = 'text/xml';
370 $params['encoding'] = '8bit';
371 $params['charset'] = $this->soap_defencoding;
372 $mimeMessage->addSubpart($soapmsg, $params);
374 foreach ($this->responseAttachments as $att) {
377 $params['content_type'] = $att['contenttype'];
378 $params['encoding'] = 'base64';
379 $params['disposition'] = 'attachment';
380 $params['dfilename'] = $att['filename'];
381 $params['cid'] = $att['cid'];
383 if ($att['data'] == '' && $att['filename'] <> '') {
384 if ($fd = fopen($att['filename'], 'rb')) {
385 $data = fread($fd, filesize($att['filename']));
390 $mimeMessage->addSubpart($data, $params);
392 $mimeMessage->addSubpart($att['data'], $params);
396 $output = $mimeMessage->encode();
397 $mimeHeaders = $output['headers'];
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);
408 return $output['body'];
411 return parent::getHTTPBody($soapmsg);
415 * gets the HTTP content type for the current response.
417 * Note: getHTTPBody must be called before this.
419 * @return string the HTTP content type for the current response.
422 function getHTTPContentType() {
423 if (count($this->responseAttachments) > 0) {
424 return $this->mimeContentType;
426 return parent::getHTTPContentType();
430 * gets the HTTP content type charset for the current response.
431 * returns false for non-text content types.
433 * Note: getHTTPBody must be called before this.
435 * @return string the HTTP content type charset for the current response.
438 function getHTTPContentTypeCharset() {
439 if (count($this->responseAttachments) > 0) {
442 return parent::getHTTPContentTypeCharset();
446 * processes SOAP message received from client
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
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');
459 foreach ($headers as $k => $v) {
460 $input .= "$k: $v\r\n";
462 $params['input'] = $input . "\r\n" . $data;
463 $params['include_bodies'] = true;
464 $params['decode_bodies'] = true;
465 $params['decode_headers'] = true;
467 $structure = Mail_mimeDecode::decode($params);
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);
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;
483 if (isset($return)) {
487 $this->setError('No root part found in multipart/related content');
490 $this->debug('Not multipart/related');
491 return parent::parseRequest($headers, $data);
496 * For backwards compatiblity
498 class nusoapservermime extends nusoap_server_mime {