Removed php_test.
[siap.git] / nusoap / lib / nusoapmime.php
1 <?php
2 /*
3 $Id: nusoapmime.php,v 1.13 2010/04/26 20:15:08 snichol Exp $
4
5 NuSOAP - Web Services Toolkit for PHP
6
7 Copyright (c) 2002 NuSphere Corporation
8
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.
13
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.
18
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
22
23 The NuSOAP project home is:
24 http://sourceforge.net/projects/nusoap/
25
26 The primary support for NuSOAP is the mailing list:
27 nusoap-general@lists.sourceforge.net
28
29 If you have any questions or comments, please email:
30
31 Dietrich Ayala
32 dietrich@ganx4.com
33 http://dietrich.ganx4.com/nusoap
34
35 NuSphere Corporation
36 http://www.nusphere.com
37
38 */
39
40 /*require_once('nusoap.php');*/
41 /* PEAR Mail_MIME library */
42 require_once('Mail/mimeDecode.php');
43 require_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 */
54 class 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  */
270 if (!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 */
284 class 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  */
498 class nusoapservermime extends nusoap_server_mime {
499 }
500
501 ?>