1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace PhpXmlRpc; |
4
|
|
|
|
5
|
|
|
use PhpXmlRpc\Exception\HttpException; |
6
|
|
|
use PhpXmlRpc\Helper\Http; |
7
|
|
|
use PhpXmlRpc\Helper\XMLParser; |
8
|
|
|
use PhpXmlRpc\Traits\CharsetEncoderAware; |
9
|
|
|
use PhpXmlRpc\Traits\DeprecationLogger; |
10
|
|
|
use PhpXmlRpc\Traits\ParserAware; |
11
|
|
|
use PhpXmlRpc\Traits\PayloadBearer; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* This class provides the representation of a request to an XML-RPC server. |
15
|
|
|
* A client sends a PhpXmlrpc\Request to a server, and receives back an PhpXmlrpc\Response. |
16
|
|
|
* |
17
|
|
|
* @todo feature creep - add a protected $httpRequest member, in the same way the Response has one |
18
|
|
|
* |
19
|
|
|
* @property string $methodname deprecated - public access left in purely for BC. Access via method()/__construct() |
20
|
|
|
* @property Value[] $params deprecated - public access left in purely for BC. Access via getParam()/__construct() |
21
|
|
|
* @property int $debug deprecated - public access left in purely for BC. Access via .../setDebug() |
22
|
|
|
* @property string $payload deprecated - public access left in purely for BC. Access via getPayload()/setPayload() |
23
|
|
|
* @property string $content_type deprecated - public access left in purely for BC. Access via getContentType()/setPayload() |
24
|
|
|
*/ |
25
|
|
|
class Request |
26
|
|
|
{ |
27
|
|
|
use CharsetEncoderAware; |
28
|
|
|
use DeprecationLogger; |
29
|
|
|
use ParserAware; |
30
|
|
|
use PayloadBearer; |
31
|
|
|
|
32
|
|
|
/** @var string */ |
33
|
|
|
protected $methodname; |
34
|
3 |
|
/** @var Value[] */ |
35
|
|
|
protected $params = array(); |
36
|
3 |
|
/** @var int */ |
37
|
3 |
|
protected $debug = 0; |
38
|
|
|
|
39
|
3 |
|
/** |
40
|
|
|
* holds data while parsing the response. NB: Not a full Response object |
41
|
|
|
* @deprecated will be removed in a future release; still accessible by subclasses for the moment |
42
|
|
|
*/ |
43
|
|
|
private $httpResponse = array(); |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @param string $methodName the name of the method to invoke |
47
|
707 |
|
* @param Value[] $params array of parameters to be passed to the method (NB: Value objects, not plain php values) |
48
|
|
|
*/ |
49
|
707 |
|
public function __construct($methodName, $params = array()) |
50
|
8 |
|
{ |
51
|
|
|
$this->methodname = $methodName; |
52
|
707 |
|
foreach ($params as $param) { |
53
|
|
|
$this->addParam($param); |
54
|
|
|
} |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* Gets/sets the xml-rpc method to be invoked. |
59
|
|
|
* |
60
|
652 |
|
* @param string $methodName the method to be set (leave empty not to set it) |
61
|
|
|
* @return string the method that will be invoked |
62
|
652 |
|
*/ |
63
|
9 |
|
public function method($methodName = '') |
64
|
|
|
{ |
65
|
652 |
|
if ($methodName != '') { |
66
|
|
|
$this->methodname = $methodName; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
return $this->methodname; |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Add a parameter to the list of parameters to be used upon method invocation. |
74
|
|
|
* Checks that $params is actually a Value object and not a plain php value. |
75
|
|
|
* |
76
|
|
|
* @param Value $param |
77
|
715 |
|
* @return boolean false on failure |
78
|
|
|
*/ |
79
|
715 |
|
public function addParam($param) |
80
|
715 |
|
{ |
81
|
500 |
|
// check: do not add to self params which are not xml-rpc values |
82
|
|
|
if (is_object($param) && is_a($param, 'PhpXmlRpc\Value')) { |
83
|
715 |
|
$this->params[] = $param; |
84
|
|
|
|
85
|
|
|
return true; |
86
|
|
|
} else { |
87
|
|
|
$this->getLogger()->error('XML-RPC: ' . __METHOD__ . ': value passed in must be a PhpXmlRpc\Value'); |
88
|
|
|
return false; |
89
|
|
|
} |
90
|
652 |
|
} |
91
|
|
|
|
92
|
652 |
|
/** |
93
|
60 |
|
* Returns the nth parameter in the request. The index zero-based. |
94
|
|
|
* |
95
|
592 |
|
* @param integer $i the index of the parameter to fetch (zero based) |
96
|
|
|
* @return Value the i-th parameter |
97
|
|
|
*/ |
98
|
|
|
public function getParam($i) |
99
|
|
|
{ |
100
|
|
|
return $this->params[$i]; |
101
|
|
|
} |
102
|
|
|
|
103
|
652 |
|
/** |
104
|
|
|
* Returns the number of parameters in the message. |
105
|
652 |
|
* |
106
|
|
|
* @return integer the number of parameters currently set |
107
|
|
|
*/ |
108
|
|
|
public function getNumParams() |
109
|
|
|
{ |
110
|
|
|
return count($this->params); |
111
|
|
|
} |
112
|
652 |
|
|
113
|
|
|
/** |
114
|
652 |
|
* Returns xml representation of the message, XML prologue included. Sets `payload` and `content_type` properties |
115
|
60 |
|
* |
116
|
|
|
* @param string $charsetEncoding |
117
|
592 |
|
* @return string the xml representation of the message, xml prologue included |
118
|
|
|
*/ |
119
|
652 |
|
public function serialize($charsetEncoding = '') |
120
|
652 |
|
{ |
121
|
652 |
|
$this->createPayload($charsetEncoding); |
122
|
652 |
|
|
123
|
652 |
|
return $this->payload; |
124
|
609 |
|
} |
125
|
609 |
|
|
126
|
|
|
/** |
127
|
652 |
|
* @internal this function will become protected in the future (and be folded into serialize) |
128
|
652 |
|
* |
129
|
652 |
|
* @param string $charsetEncoding |
130
|
|
|
* @return void |
131
|
|
|
*/ |
132
|
|
|
public function createPayload($charsetEncoding = '') |
133
|
|
|
{ |
134
|
|
|
$this->logDeprecationUnlessCalledBy('serialize'); |
135
|
|
|
|
136
|
|
|
if ($charsetEncoding != '') { |
137
|
|
|
$this->content_type = 'text/xml; charset=' . $charsetEncoding; |
138
|
562 |
|
} else { |
139
|
|
|
$this->content_type = 'text/xml'; |
140
|
562 |
|
} |
141
|
|
|
|
142
|
|
|
$result = $this->xml_header($charsetEncoding); |
143
|
|
|
$result .= '<methodName>' . $this->getCharsetEncoder()->encodeEntities( |
144
|
562 |
|
$this->methodname, PhpXmlRpc::$xmlrpc_internalencoding, $charsetEncoding) . "</methodName>\n"; |
145
|
|
|
$result .= "<params>\n"; |
146
|
|
|
foreach ($this->params as $p) { |
147
|
|
|
$result .= "<param>\n" . $p->serialize($charsetEncoding) . |
148
|
|
|
"</param>\n"; |
149
|
|
|
} |
150
|
|
|
$result .= "</params>\n"; |
151
|
|
|
$result .= $this->xml_footer(); |
152
|
|
|
|
153
|
|
|
$this->payload = $result; |
154
|
652 |
|
} |
155
|
|
|
|
156
|
652 |
|
/** |
157
|
|
|
* @internal this function will become protected in the future (and be folded into serialize) |
158
|
652 |
|
* |
159
|
|
|
* @param string $charsetEncoding |
160
|
|
|
* @return string |
161
|
|
|
*/ |
162
|
|
|
public function xml_header($charsetEncoding = '') |
163
|
|
|
{ |
164
|
|
|
$this->logDeprecationUnlessCalledBy('createPayload'); |
165
|
|
|
|
166
|
|
|
if ($charsetEncoding != '') { |
167
|
|
|
return "<?xml version=\"1.0\" encoding=\"$charsetEncoding\" ?" . ">\n<methodCall>\n"; |
168
|
|
|
} else { |
169
|
|
|
return "<?xml version=\"1.0\"?" . ">\n<methodCall>\n"; |
170
|
657 |
|
} |
171
|
|
|
} |
172
|
|
|
|
173
|
657 |
|
/** |
174
|
657 |
|
* @internal this function will become protected in the future (and be folded into serialize) |
175
|
|
|
* |
176
|
657 |
|
* @return string |
177
|
|
|
*/ |
178
|
|
|
public function xml_footer() |
179
|
|
|
{ |
180
|
|
|
$this->logDeprecationUnlessCalledBy('createPayload'); |
181
|
|
|
|
182
|
|
|
return '</methodCall>'; |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
/** |
186
|
|
|
* Given an open file handle, read all data available and parse it as an xml-rpc response. |
187
|
|
|
* |
188
|
|
|
* NB: the file handle is not closed by this function. |
189
|
517 |
|
* NNB: might have trouble in rare cases to work on network streams, as we check for a read of 0 bytes instead of |
190
|
|
|
* feof($fp). But since checking for feof(null) returns false, we would risk an infinite loop in that case, |
191
|
517 |
|
* because we cannot trust the caller to give us a valid pointer to an open file... |
192
|
|
|
* |
193
|
|
|
* @param resource $fp stream pointer |
194
|
|
|
* @param bool $headersProcessed |
195
|
|
|
* @param string $returnType |
196
|
|
|
* @return Response |
197
|
|
|
* |
198
|
|
|
* @todo arsing Responses is not really the responsibility of the Request class. Maybe of the Client... |
199
|
538 |
|
* @todo feature creep - add a flag to disable trying to parse the http headers |
200
|
|
|
*/ |
201
|
538 |
|
public function parseResponseFile($fp, $headersProcessed = false, $returnType = 'xmlrpcvals') |
202
|
|
|
{ |
203
|
|
|
$ipd = ''; |
204
|
|
|
// q: is there an optimal buffer size? Is there any value in making the buffer size a tuneable? |
205
|
|
|
while ($data = fread($fp, 32768)) { |
206
|
|
|
$ipd .= $data; |
207
|
|
|
} |
208
|
|
|
return $this->parseResponse($ipd, $headersProcessed, $returnType); |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
/** |
212
|
|
|
* Parse the xml-rpc response contained in the string $data and return a Response object. |
213
|
|
|
* |
214
|
|
|
* When $this->debug has been set to a value greater than 0, will echo debug messages to screen while decoding. |
215
|
|
|
* |
216
|
|
|
* @param string $data the xml-rpc response, possibly including http headers |
217
|
|
|
* @param bool $headersProcessed when true prevents parsing HTTP headers for interpretation of content-encoding and |
218
|
|
|
* consequent decoding |
219
|
|
|
* @param string $returnType decides return type, i.e. content of response->value(). Either 'xmlrpcvals', 'xml' or |
220
|
|
|
* 'phpvals' |
221
|
|
|
* @return Response |
222
|
|
|
* |
223
|
|
|
* @todo parsing Responses is not really the responsibility of the Request class. Maybe of the Client... |
224
|
|
|
* @todo what about only populating 'raw_data' in httpResponse when debug mode is > 0? |
225
|
|
|
* @todo feature creep - allow parsing data gotten from a stream pointer instead of a string: read it piecewise, |
226
|
|
|
* looking first for separation between headers and body, then for charset indicators, server debug info and |
227
|
|
|
* </methodResponse>. That would require a notable increase in code complexity... |
228
|
|
|
*/ |
229
|
|
|
public function parseResponse($data = '', $headersProcessed = false, $returnType = XMLParser::RETURN_XMLRPCVALS) |
230
|
|
|
{ |
231
|
|
|
if ($this->debug > 0) { |
232
|
|
|
$this->getLogger()->debug("---GOT---\n$data\n---END---"); |
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
$this->httpResponse = array('raw_data' => $data, 'headers' => array(), 'cookies' => array()); |
|
|
|
|
236
|
|
|
|
237
|
|
|
if ($data == '') { |
238
|
|
|
$this->getLogger()->error('XML-RPC: ' . __METHOD__ . ': no response received from server.'); |
239
|
|
|
return new Response(0, PhpXmlRpc::$xmlrpcerr['no_data'], PhpXmlRpc::$xmlrpcstr['no_data']); |
240
|
|
|
} |
241
|
|
|
|
242
|
711 |
|
// parse the HTTP headers of the response, if present, and separate them from data |
243
|
|
|
if (substr($data, 0, 4) == 'HTTP') { |
244
|
711 |
|
$httpParser = new Http(); |
245
|
3 |
|
try { |
246
|
|
|
$httpResponse = $httpParser->parseResponseHeaders($data, $headersProcessed, $this->debug > 0); |
|
|
|
|
247
|
|
|
} catch (HttpException $e) { |
248
|
711 |
|
// failed processing of HTTP response headers |
249
|
|
|
// save into response obj the full payload received, for debugging |
250
|
711 |
|
return new Response(0, $e->getCode(), $e->getMessage(), '', array('raw_data' => $data, 'status_code' => $e->statusCode())); |
251
|
|
|
} catch(\Exception $e) { |
252
|
|
|
return new Response(0, $e->getCode(), $e->getMessage(), '', array('raw_data' => $data)); |
253
|
|
|
} |
254
|
|
|
} else { |
255
|
|
|
$httpResponse = $this->httpResponse; |
|
|
|
|
256
|
711 |
|
} |
257
|
699 |
|
|
258
|
|
|
// be tolerant of extra whitespace in response body |
259
|
699 |
|
$data = trim($data); |
260
|
3 |
|
|
261
|
|
|
/// @todo optimization creep - return an error msg if $data == '' |
262
|
|
|
|
263
|
3 |
|
// be tolerant of junk after methodResponse (e.g. javascript ads automatically inserted by free hosts) |
264
|
|
|
// idea from Luca Mariano, originally in PEARified version of the lib |
265
|
|
|
$pos = strrpos($data, '</methodResponse>'); |
266
|
|
|
if ($pos !== false) { |
267
|
|
|
$data = substr($data, 0, $pos + 17); |
268
|
|
|
} |
269
|
|
|
|
270
|
708 |
|
// try to 'guestimate' the character encoding of the received response |
271
|
|
|
$respEncoding = XMLParser::guessEncoding( |
272
|
|
|
isset($httpResponse['headers']['content-type']) ? $httpResponse['headers']['content-type'] : '', |
273
|
|
|
$data |
274
|
|
|
); |
275
|
|
|
|
276
|
708 |
|
if ($this->debug >= 0) { |
277
|
708 |
|
$this->httpResponse = $httpResponse; |
|
|
|
|
278
|
708 |
|
} else { |
279
|
|
|
$httpResponse = null; |
280
|
|
|
} |
281
|
|
|
|
282
|
708 |
|
if ($this->debug > 0) { |
283
|
|
|
$start = strpos($data, '<!-- SERVER DEBUG INFO (BASE64 ENCODED):'); |
284
|
708 |
|
if ($start) { |
285
|
3 |
|
$start += strlen('<!-- SERVER DEBUG INFO (BASE64 ENCODED):'); |
286
|
3 |
|
/// @todo what if there is no end tag? |
287
|
3 |
|
$end = strpos($data, '-->', $start); |
288
|
3 |
|
$comments = substr($data, $start, $end - $start); |
289
|
3 |
|
$this->getLogger()->debug("---SERVER DEBUG INFO (DECODED)---\n\t" . |
290
|
3 |
|
str_replace("\n", "\n\t", base64_decode($comments)) . "\n---END---", array('encoding' => $respEncoding)); |
291
|
3 |
|
} |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
// if the user wants back raw xml, give it to her |
295
|
|
|
if ($returnType == 'xml') { |
296
|
708 |
|
return new Response($data, 0, '', 'xml', $httpResponse); |
297
|
1 |
|
} |
298
|
|
|
|
299
|
|
|
/// @todo move this block of code into the XMLParser |
300
|
707 |
|
if ($respEncoding != '') { |
301
|
|
|
// Since parsing will fail if charset is not specified in the xml declaration, |
302
|
|
|
// the encoding is not UTF8 and there are non-ascii chars in the text, we try to work round that... |
303
|
|
|
// The following code might be better for mb_string enabled installs, but makes the lib about 200% slower... |
304
|
|
|
//if (!is_valid_charset($respEncoding, array('UTF-8'))) |
305
|
|
|
if (!in_array($respEncoding, array('UTF-8', 'US-ASCII')) && !XMLParser::hasEncoding($data)) { |
306
|
707 |
|
if (function_exists('mb_convert_encoding')) { |
307
|
1 |
|
$data = mb_convert_encoding($data, 'UTF-8', $respEncoding); |
308
|
1 |
|
} else { |
309
|
|
|
if ($respEncoding == 'ISO-8859-1') { |
310
|
|
|
$data = utf8_encode($data); |
311
|
|
|
} else { |
312
|
|
|
$this->getLogger()->error('XML-RPC: ' . __METHOD__ . ': unsupported charset encoding of received response: ' . $respEncoding); |
313
|
|
|
} |
314
|
|
|
} |
315
|
|
|
} |
316
|
|
|
} |
317
|
|
|
// PHP internally might use ISO-8859-1, so we have to tell the xml parser to give us back data in the expected charset. |
318
|
|
|
// What if internal encoding is not in one of the 3 allowed? We use the broadest one, i.e. utf8 |
319
|
|
|
if (in_array(PhpXmlRpc::$xmlrpc_internalencoding, array('UTF-8', 'ISO-8859-1', 'US-ASCII'))) { |
320
|
|
|
$options = array(XML_OPTION_TARGET_ENCODING => PhpXmlRpc::$xmlrpc_internalencoding); |
321
|
|
|
} else { |
322
|
|
|
$options = array(XML_OPTION_TARGET_ENCODING => 'UTF-8', 'target_charset' => PhpXmlRpc::$xmlrpc_internalencoding); |
323
|
|
|
} |
324
|
707 |
|
|
325
|
|
|
$xmlRpcParser = $this->getParser(); |
326
|
|
|
$_xh = $xmlRpcParser->parse($data, $returnType, XMLParser::ACCEPT_RESPONSE, $options); |
327
|
|
|
// BC |
328
|
707 |
|
if (!is_array($_xh)) { |
329
|
|
|
$_xh = $xmlRpcParser->_xh; |
330
|
|
|
} |
331
|
707 |
|
|
332
|
707 |
|
// first error check: xml not well-formed |
333
|
|
|
if ($_xh['isf'] == 3) { |
334
|
|
|
|
335
|
707 |
|
// BC break: in the past for some cases we used the error message: 'XML error at line 1, check URL' |
336
|
|
|
|
337
|
|
|
// Q: should we give back an error with variable error number, as we do server-side? But if we do, will |
338
|
|
|
// we be able to tell apart the two cases? In theory, we never emit invalid xml on our end, but |
339
|
3 |
|
// there could be proxies meddling with the request, or network data corruption... |
340
|
3 |
|
|
341
|
3 |
|
$r = new Response(0, PhpXmlRpc::$xmlrpcerr['invalid_xml'], |
342
|
|
|
PhpXmlRpc::$xmlrpcstr['invalid_xml'] . ' ' . $_xh['isf_reason'], '', $httpResponse); |
343
|
|
|
|
344
|
3 |
|
if ($this->debug > 0) { |
345
|
3 |
|
$this->getLogger()->debug($_xh['isf_reason']); |
346
|
|
|
} |
347
|
|
|
} |
348
|
|
|
// second error check: xml well-formed but not xml-rpc compliant |
349
|
707 |
|
elseif ($_xh['isf'] == 2) { |
350
|
4 |
|
$r = new Response(0, PhpXmlRpc::$xmlrpcerr['xml_not_compliant'], |
351
|
4 |
|
PhpXmlRpc::$xmlrpcstr['xml_not_compliant'] . ' ' . $_xh['isf_reason'], '', $httpResponse); |
352
|
4 |
|
|
353
|
|
|
/// @todo echo something for the user? check if it was already done by the parser... |
354
|
|
|
//if ($this->debug > 0) { |
355
|
4 |
|
// $this->getLogger()->debug($_xh['isf_reason']); |
356
|
|
|
//} |
357
|
|
|
} |
358
|
|
|
// third error check: parsing of the response has somehow gone boink. |
359
|
|
|
/// @todo shall we omit the 2nd part of this check, since we trust the parsing code? |
360
|
|
|
/// Either that, or check the fault results too... |
361
|
704 |
|
elseif ($_xh['isf'] > 3 || ($returnType == XMLParser::RETURN_XMLRPCVALS && !$_xh['isf'] && !is_object($_xh['value']))) { |
362
|
|
|
// something odd has happened and it's time to generate a client side error indicating something odd went on |
363
|
|
|
$r = new Response(0, PhpXmlRpc::$xmlrpcerr['xml_parsing_error'], PhpXmlRpc::$xmlrpcstr['xml_parsing_error'], |
364
|
|
|
'', $httpResponse |
365
|
|
|
); |
366
|
|
|
|
367
|
|
|
/// @todo echo something for the user? |
368
|
|
|
} else { |
369
|
704 |
|
if ($this->debug > 1) { |
370
|
2 |
|
$this->getLogger()->debug( |
371
|
2 |
|
"---PARSED---\n".var_export($_xh['value'], true)."\n---END---" |
372
|
|
|
); |
373
|
|
|
} |
374
|
|
|
|
375
|
704 |
|
$v = $_xh['value']; |
376
|
|
|
|
377
|
704 |
|
if ($_xh['isf']) { |
378
|
|
|
/// @todo we should test (here or preferably in the parser) if server sent an int and a string, and/or |
379
|
109 |
|
/// coerce them into such... |
380
|
109 |
|
if ($returnType == XMLParser::RETURN_XMLRPCVALS) { |
381
|
109 |
|
$errNo_v = $v['faultCode']; |
382
|
109 |
|
$errStr_v = $v['faultString']; |
383
|
109 |
|
$errNo = $errNo_v->scalarVal(); |
384
|
|
|
$errStr = $errStr_v->scalarVal(); |
385
|
|
|
} else { |
386
|
|
|
$errNo = $v['faultCode']; |
387
|
|
|
$errStr = $v['faultString']; |
388
|
|
|
} |
389
|
109 |
|
|
390
|
|
|
if ($errNo == 0) { |
391
|
|
|
// FAULT returned, errno needs to reflect that |
392
|
|
|
/// @todo feature creep - add this code to PhpXmlRpc::$xmlrpcerr |
393
|
|
|
$this->getLogger()->error('XML-RPC: ' . __METHOD__ . ': fault response received with faultCode 0 or null. Converted it to -1'); |
394
|
109 |
|
/// @todo in Encoder::decodeXML, we use PhpXmlRpc::$xmlrpcerr['invalid_return'] for this case (see |
395
|
|
|
/// also the todo 17 lines above) |
396
|
680 |
|
$errNo = -1; |
397
|
|
|
} |
398
|
|
|
|
399
|
|
|
$r = new Response(0, $errNo, $errStr, '', $httpResponse); |
400
|
707 |
|
} else { |
401
|
|
|
$r = new Response($v, 0, '', $returnType, $httpResponse); |
402
|
|
|
} |
403
|
|
|
} |
404
|
|
|
|
405
|
|
|
return $r; |
406
|
|
|
} |
407
|
|
|
|
408
|
150 |
|
/** |
409
|
|
|
* Kept the old name even if Request class was renamed, for BC. |
410
|
150 |
|
* |
411
|
|
|
* @return string |
412
|
|
|
*/ |
413
|
|
|
public function kindOf() |
414
|
|
|
{ |
415
|
|
|
return 'msg'; |
416
|
|
|
} |
417
|
|
|
|
418
|
712 |
|
/** |
419
|
|
|
* Enables/disables the echoing to screen of the xml-rpc responses received. |
420
|
712 |
|
* |
421
|
712 |
|
* @param integer $level values <0, 0, 1, >1 are supported |
422
|
|
|
* @return $this |
423
|
|
|
*/ |
424
|
|
|
public function setDebug($level) |
425
|
|
|
{ |
426
|
|
|
$this->debug = $level; |
427
|
|
|
return $this; |
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
// *** BC layer *** |
431
|
|
|
|
432
|
|
|
// we have to make this return by ref in order to allow calls such as `$resp->_cookies['name'] = ['value' => 'something'];` |
433
|
|
|
public function &__get($name) |
434
|
|
|
{ |
435
|
|
|
switch ($name) { |
436
|
|
|
case 'me': |
437
|
|
|
case 'mytype': |
438
|
|
|
case '_php_class': |
439
|
|
|
case 'payload': |
440
|
|
|
case 'content_type': |
441
|
|
|
$this->logDeprecation('Getting property Request::' . $name . ' is deprecated'); |
442
|
|
|
return $this->$name; |
443
|
|
|
case 'httpResponse': |
444
|
|
|
// manually implement the 'protected property' behaviour |
445
|
|
|
$canAccess = false; |
446
|
|
|
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); |
447
|
|
|
if (isset($trace[1]) && isset($trace[1]['class'])) { |
448
|
|
|
if (is_subclass_of($trace[1]['class'], 'PhpXmlRpc\Request')) { |
449
|
|
|
$canAccess = true; |
450
|
|
|
} |
451
|
|
|
} |
452
|
|
|
if ($canAccess) { |
453
|
|
|
$this->logDeprecation('Getting property Request::' . $name . ' is deprecated'); |
454
|
|
|
return $this->httpResponse; |
|
|
|
|
455
|
|
|
} else { |
456
|
|
|
trigger_error("Cannot access protected property Request::httpResponse in " . __FILE__, E_USER_ERROR); |
457
|
|
|
} |
458
|
|
|
break; |
459
|
|
|
default: |
460
|
|
|
/// @todo throw instead? There are very few other places where the lib trigger errors which can potentially reach stdout... |
461
|
|
|
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1); |
462
|
|
|
trigger_error('Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_WARNING); |
463
|
|
|
$result = null; |
464
|
|
|
return $result; |
465
|
|
|
} |
466
|
|
|
} |
467
|
|
|
|
468
|
|
|
public function __set($name, $value) |
469
|
|
|
{ |
470
|
|
|
switch ($name) { |
471
|
|
|
case 'methodname': |
472
|
|
|
case 'params': |
473
|
|
|
case 'debug': |
474
|
|
|
case 'payload': |
475
|
|
|
case 'content_type': |
476
|
|
|
$this->logDeprecation('Setting property Request::' . $name . ' is deprecated'); |
477
|
|
|
$this->$name = $value; |
478
|
|
|
break; |
479
|
|
|
case 'httpResponse': |
480
|
|
|
// manually implement the 'protected property' behaviour |
481
|
|
|
$canAccess = false; |
482
|
|
|
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); |
483
|
|
|
if (isset($trace[1]) && isset($trace[1]['class'])) { |
484
|
|
|
if (is_subclass_of($trace[1]['class'], 'PhpXmlRpc\Request')) { |
485
|
|
|
$canAccess = true; |
486
|
|
|
} |
487
|
|
|
} |
488
|
|
|
if ($canAccess) { |
489
|
|
|
$this->logDeprecation('Setting property Request::' . $name . ' is deprecated'); |
490
|
|
|
$this->httpResponse = $value; |
|
|
|
|
491
|
|
|
} else { |
492
|
|
|
trigger_error("Cannot access protected property Request::httpResponse in " . __FILE__, E_USER_ERROR); |
493
|
|
|
} |
494
|
|
|
break; |
495
|
|
|
default: |
496
|
|
|
/// @todo throw instead? There are very few other places where the lib trigger errors which can potentially reach stdout... |
497
|
|
|
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1); |
498
|
|
|
trigger_error('Undefined property via __set(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_WARNING); |
499
|
|
|
} |
500
|
|
|
} |
501
|
|
|
|
502
|
|
|
public function __isset($name) |
503
|
|
|
{ |
504
|
|
|
switch ($name) { |
505
|
|
|
case 'methodname': |
506
|
|
|
case 'params': |
507
|
|
|
case 'debug': |
508
|
|
|
case 'payload': |
509
|
|
|
case 'content_type': |
510
|
|
|
$this->logDeprecation('Checking property Request::' . $name . ' is deprecated'); |
511
|
|
|
return isset($this->$name); |
512
|
|
|
case 'httpResponse': |
513
|
|
|
// manually implement the 'protected property' behaviour |
514
|
|
|
$canAccess = false; |
515
|
|
|
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); |
516
|
|
|
if (isset($trace[1]) && isset($trace[1]['class'])) { |
517
|
|
|
if (is_subclass_of($trace[1]['class'], 'PhpXmlRpc\Request')) { |
518
|
|
|
$canAccess = true; |
519
|
|
|
} |
520
|
|
|
} |
521
|
|
|
if ($canAccess) { |
522
|
|
|
$this->logDeprecation('Checking property Request::' . $name . ' is deprecated'); |
523
|
|
|
return isset($this->httpResponse); |
|
|
|
|
524
|
|
|
} |
525
|
|
|
// break through voluntarily |
526
|
|
|
default: |
527
|
|
|
return false; |
528
|
|
|
} |
529
|
|
|
} |
530
|
|
|
|
531
|
|
|
public function __unset($name) |
532
|
|
|
{ |
533
|
|
|
switch ($name) { |
534
|
|
|
case 'methodname': |
535
|
|
|
case 'params': |
536
|
|
|
case 'debug': |
537
|
|
|
case 'payload': |
538
|
|
|
case 'content_type': |
539
|
|
|
$this->logDeprecation('Unsetting property Request::' . $name . ' is deprecated'); |
540
|
|
|
unset($this->$name); |
541
|
|
|
break; |
542
|
|
|
case 'httpResponse': |
543
|
|
|
// manually implement the 'protected property' behaviour |
544
|
|
|
$canAccess = false; |
545
|
|
|
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); |
546
|
|
|
if (isset($trace[1]) && isset($trace[1]['class'])) { |
547
|
|
|
if (is_subclass_of($trace[1]['class'], 'PhpXmlRpc\Request')) { |
548
|
|
|
$canAccess = true; |
549
|
|
|
} |
550
|
|
|
} |
551
|
|
|
if ($canAccess) { |
552
|
|
|
$this->logDeprecation('Unsetting property Request::' . $name . ' is deprecated'); |
553
|
|
|
unset($this->httpResponse); |
|
|
|
|
554
|
|
|
} else { |
555
|
|
|
trigger_error("Cannot access protected property Request::httpResponse in " . __FILE__, E_USER_ERROR); |
556
|
|
|
} |
557
|
|
|
break; |
558
|
|
|
default: |
559
|
|
|
/// @todo throw instead? There are very few other places where the lib trigger errors which can potentially reach stdout... |
560
|
|
|
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1); |
561
|
|
|
trigger_error('Undefined property via __unset(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_WARNING); |
562
|
|
|
} |
563
|
|
|
} |
564
|
|
|
} |
565
|
|
|
|
This property has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.