source: branches/2.4/include/ws_protocols/rest_encoder.php @ 16075

Revision 16075, 7.3 KB checked in by rvelices, 7 years ago (diff)

bug 2666 Fix invalid xml on web service output with xml format (merge from trunk to branch 2.4)

  • Property svn:eol-style set to LF
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | Piwigo - a PHP based photo gallery                                    |
4// +-----------------------------------------------------------------------+
5// | Copyright(C) 2008-2012 Piwigo Team                  http://piwigo.org |
6// | Copyright(C) 2003-2008 PhpWebGallery Team    http://phpwebgallery.net |
7// | Copyright(C) 2002-2003 Pierrick LE GALL   http://le-gall.net/pierrick |
8// +-----------------------------------------------------------------------+
9// | This program is free software; you can redistribute it and/or modify  |
10// | it under the terms of the GNU General Public License as published by  |
11// | the Free Software Foundation                                          |
12// |                                                                       |
13// | This program is distributed in the hope that it will be useful, but   |
14// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
15// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
16// | General Public License for more details.                              |
17// |                                                                       |
18// | You should have received a copy of the GNU General Public License     |
19// | along with this program; if not, write to the Free Software           |
20// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
21// | USA.                                                                  |
22// +-----------------------------------------------------------------------+
23
24
25class PwgXmlWriter
26{
27  var $_indent;
28  var $_indentStr;
29
30  var $_elementStack;
31  var $_lastTagOpen;
32  var $_indentLevel;
33
34  var $_encodedXml;
35
36  function PwgXmlWriter()
37  {
38    $this->_elementStack = array();
39    $this->_lastTagOpen = false;
40    $this->_indentLevel = 0;
41
42    $this->_encodedXml = '';
43    $this->_indent = true;
44    $this->_indentStr = "\t";
45  }
46
47  function &getOutput()
48  {
49    return $this->_encodedXml;
50  }
51
52
53  function start_element($name)
54  {
55    $this->_end_prev(false);
56    if (!empty($this->_elementStack))
57    {
58      $this->_eol_indent();
59    }
60    $this->_indentLevel++;
61    $this->_indent();
62                $diff = ord($name[0])-ord('0');
63                if ($diff>=0 && $diff<=9)
64                {
65                        $name='_'.$name;
66                }
67    $this->_output( '<'.$name );
68    $this->_lastTagOpen = true;
69    array_push( $this->_elementStack, $name);
70  }
71
72  function end_element($x)
73  {
74    $close_tag = $this->_end_prev(true);
75    $name = array_pop( $this->_elementStack );
76    if ($close_tag)
77    {
78      $this->_indentLevel--;
79      $this->_indent();
80//      $this->_eol_indent();
81      $this->_output('</'.$name.">");
82    }
83  }
84
85  function write_content($value)
86  {
87    $this->_end_prev(false);
88    $value = (string)$value;
89    $this->_output( htmlspecialchars( $value ) );
90  }
91
92  function write_cdata($value)
93  {
94    $this->_end_prev(false);
95    $value = (string)$value;
96    $this->_output(
97      '<![CDATA['
98      . str_replace(']]>', ']]&gt;', $value)
99      . ']]>' );
100  }
101
102  function write_attribute($name, $value)
103  {
104    $this->_output(' '.$name.'="'.$this->encode_attribute($value).'"');
105  }
106
107  function encode_attribute($value)
108  {
109    return htmlspecialchars( (string)$value);
110  }
111
112  function _end_prev($done)
113  {
114    $ret = true;
115    if ($this->_lastTagOpen)
116    {
117      if ($done)
118      {
119        $this->_indentLevel--;
120        $this->_output( ' />' );
121        //$this->_eol_indent();
122        $ret = false;
123      }
124      else
125      {
126        $this->_output( '>' );
127      }
128      $this->_lastTagOpen = false;
129    }
130    return $ret;
131  }
132
133  function _eol_indent()
134  {
135    if ($this->_indent)
136      $this->_output("\n");
137  }
138
139  function _indent()
140  {
141    if ($this->_indent and
142        $this->_indentLevel > count($this->_elementStack) )
143    {
144      $this->_output(
145        str_repeat( $this->_indentStr, count($this->_elementStack) )
146       );
147    }
148  }
149
150  function _output($raw_content)
151  {
152    $this->_encodedXml .= $raw_content;
153  }
154}
155
156class PwgRestEncoder extends PwgResponseEncoder
157{
158  function encodeResponse($response)
159  {
160    $respClass = strtolower( @get_class($response) );
161    if ($respClass=='pwgerror')
162    {
163      $ret = '<?xml version="1.0"?>
164<rsp stat="fail">
165        <err code="'.$response->code().'" msg="'.htmlspecialchars($response->message()).'" />
166</rsp>';
167      return $ret;
168    }
169
170    $this->_writer = new PwgXmlWriter();
171    $this->encode($response);
172    $ret = $this->_writer->getOutput();
173    $ret = '<?xml version="1.0" encoding="'.get_pwg_charset().'" ?>
174<rsp stat="ok">
175'.$ret.'
176</rsp>';
177
178    return $ret;
179  }
180
181  function getContentType()
182  {
183    return 'text/xml';
184  }
185
186  function encode_array($data, $itemName, $xml_attributes=array())
187  {
188    foreach ($data as $item)
189    {
190      $this->_writer->start_element( $itemName );
191      $this->encode($item, $xml_attributes);
192      $this->_writer->end_element( $itemName );
193    }
194  }
195
196  function encode_struct($data, $skip_underscore, $xml_attributes=array())
197  {
198    foreach ($data as $name => $value)
199    {
200      if (is_numeric($name))
201        continue;
202      if ($skip_underscore and $name[0]=='_')
203        continue;
204      if ( is_null($value) )
205        continue; // null means we dont put it
206      if ( $name==WS_XML_ATTRIBUTES)
207      {
208        foreach ($value as $attr_name => $attr_value)
209        {
210          $this->_writer->write_attribute($attr_name, $attr_value);
211        }
212        unset($data[$name]);
213      }
214      else if ( isset($xml_attributes[$name]) )
215      {
216        $this->_writer->write_attribute($name, $value);
217        unset($data[$name]);
218      }
219    }
220
221    foreach ($data as $name => $value)
222    {
223      if (is_numeric($name))
224        continue;
225      if ($skip_underscore and $name[0]=='_')
226        continue;
227      if ( is_null($value) )
228        continue; // null means we dont put it
229      if ($name!=WS_XML_CONTENT)
230        $this->_writer->start_element($name);
231      $this->encode($value);
232      if ($name!=WS_XML_CONTENT)
233        $this->_writer->end_element($name);
234    }
235  }
236
237  function encode($data, $xml_attributes=array() )
238  {
239    switch (gettype($data))
240    {
241      case 'null':
242      case 'NULL':
243        $this->_writer->write_content('');
244        break;
245      case 'boolean':
246        $this->_writer->write_content($data ? '1' : '0');
247        break;
248      case 'integer':
249      case 'double':
250        $this->_writer->write_content($data);
251        break;
252      case 'string':
253        $this->_writer->write_content($data);
254        break;
255      case 'array':
256        $is_array = range(0, count($data) - 1) === array_keys($data);
257        if ($is_array)
258        {
259          $this->encode_array($data, 'item' );
260        }
261        else
262        {
263          $this->encode_struct($data, false, $xml_attributes);
264        }
265        break;
266      case 'object':
267        switch ( strtolower(@get_class($data)) )
268        {
269          case 'pwgnamedarray':
270            $this->encode_array($data->_content, $data->_itemName, $data->_xmlAttributes);
271            break;
272          case 'pwgnamedstruct':
273            $this->encode_array( array($data->_content), $data->_name, $data->_xmlAttributes);
274            break;
275          default:
276            $this->encode_struct(get_object_vars($data), true);
277            break;
278        }
279        break;
280      default:
281        trigger_error("Invalid type ". gettype($data)." ".@get_class($data), E_USER_WARNING );
282    }
283  }
284}
285
286?>
Note: See TracBrowser for help on using the repository browser.