Merge branch 'MDL-29201_20' of git://github.com/timhunt/moodle into MOODLE_20_STABLE
[moodle.git] / lib / simpletestlib / encoding.php
blob4a4b9749016af1fbed16e9d0ee034b09f459cb12
1 <?php
2 /**
3 * base include file for SimpleTest
4 * @package SimpleTest
5 * @subpackage WebTester
6 * @version $Id$
7 */
9 /**#@+
10 * include other SimpleTest class files
12 require_once(dirname(__FILE__) . '/socket.php');
13 /**#@-*/
15 /**
16 * Single post parameter.
17 * @package SimpleTest
18 * @subpackage WebTester
20 class SimpleEncodedPair {
21 var $_key;
22 var $_value;
24 /**
25 * Stashes the data for rendering later.
26 * @param string $key Form element name.
27 * @param string $value Data to send.
29 function SimpleEncodedPair($key, $value) {
30 $this->_key = $key;
31 $this->_value = $value;
34 /**
35 * The pair as a single string.
36 * @return string Encoded pair.
37 * @access public
39 function asRequest() {
40 return urlencode($this->_key) . '=' . urlencode($this->_value);
43 /**
44 * The MIME part as a string.
45 * @return string MIME part encoding.
46 * @access public
48 function asMime() {
49 $part = 'Content-Disposition: form-data; ';
50 $part .= "name=\"" . $this->_key . "\"\r\n";
51 $part .= "\r\n" . $this->_value;
52 return $part;
55 /**
56 * Is this the value we are looking for?
57 * @param string $key Identifier.
58 * @return boolean True if matched.
59 * @access public
61 function isKey($key) {
62 return $key == $this->_key;
65 /**
66 * Is this the value we are looking for?
67 * @return string Identifier.
68 * @access public
70 function getKey() {
71 return $this->_key;
74 /**
75 * Is this the value we are looking for?
76 * @return string Content.
77 * @access public
79 function getValue() {
80 return $this->_value;
84 /**
85 * Single post parameter.
86 * @package SimpleTest
87 * @subpackage WebTester
89 class SimpleAttachment {
90 var $_key;
91 var $_content;
92 var $_filename;
94 /**
95 * Stashes the data for rendering later.
96 * @param string $key Key to add value to.
97 * @param string $content Raw data.
98 * @param hash $filename Original filename.
100 function SimpleAttachment($key, $content, $filename) {
101 $this->_key = $key;
102 $this->_content = $content;
103 $this->_filename = $filename;
107 * The pair as a single string.
108 * @return string Encoded pair.
109 * @access public
111 function asRequest() {
112 return '';
116 * The MIME part as a string.
117 * @return string MIME part encoding.
118 * @access public
120 function asMime() {
121 $part = 'Content-Disposition: form-data; ';
122 $part .= 'name="' . $this->_key . '"; ';
123 $part .= 'filename="' . $this->_filename . '"';
124 $part .= "\r\nContent-Type: " . $this->_deduceMimeType();
125 $part .= "\r\n\r\n" . $this->_content;
126 return $part;
130 * Attempts to figure out the MIME type from the
131 * file extension and the content.
132 * @return string MIME type.
133 * @access private
135 function _deduceMimeType() {
136 if ($this->_isOnlyAscii($this->_content)) {
137 return 'text/plain';
139 return 'application/octet-stream';
143 * Tests each character is in the range 0-127.
144 * @param string $ascii String to test.
145 * @access private
147 function _isOnlyAscii($ascii) {
148 for ($i = 0, $length = strlen($ascii); $i < $length; $i++) {
149 if (ord($ascii[$i]) > 127) {
150 return false;
153 return true;
157 * Is this the value we are looking for?
158 * @param string $key Identifier.
159 * @return boolean True if matched.
160 * @access public
162 function isKey($key) {
163 return $key == $this->_key;
167 * Is this the value we are looking for?
168 * @return string Identifier.
169 * @access public
171 function getKey() {
172 return $this->_key;
176 * Is this the value we are looking for?
177 * @return string Content.
178 * @access public
180 function getValue() {
181 return $this->_filename;
186 * Bundle of GET/POST parameters. Can include
187 * repeated parameters.
188 * @package SimpleTest
189 * @subpackage WebTester
191 class SimpleEncoding {
192 var $_request;
195 * Starts empty.
196 * @param array $query Hash of parameters.
197 * Multiple values are
198 * as lists on a single key.
199 * @access public
201 function SimpleEncoding($query = false) {
202 if (! $query) {
203 $query = array();
205 $this->clear();
206 $this->merge($query);
210 * Empties the request of parameters.
211 * @access public
213 function clear() {
214 $this->_request = array();
218 * Adds a parameter to the query.
219 * @param string $key Key to add value to.
220 * @param string/array $value New data.
221 * @access public
223 function add($key, $value) {
224 if ($value === false) {
225 return;
227 if (is_array($value)) {
228 foreach ($value as $item) {
229 $this->_addPair($key, $item);
231 } else {
232 $this->_addPair($key, $value);
237 * Adds a new value into the request.
238 * @param string $key Key to add value to.
239 * @param string/array $value New data.
240 * @access private
242 function _addPair($key, $value) {
243 $this->_request[] = new SimpleEncodedPair($key, $value);
247 * Adds a MIME part to the query. Does nothing for a
248 * form encoded packet.
249 * @param string $key Key to add value to.
250 * @param string $content Raw data.
251 * @param hash $filename Original filename.
252 * @access public
254 function attach($key, $content, $filename) {
255 $this->_request[] = new SimpleAttachment($key, $content, $filename);
259 * Adds a set of parameters to this query.
260 * @param array/SimpleQueryString $query Multiple values are
261 * as lists on a single key.
262 * @access public
264 function merge($query) {
265 if (is_object($query)) {
266 $this->_request = array_merge($this->_request, $query->getAll());
267 } elseif (is_array($query)) {
268 foreach ($query as $key => $value) {
269 $this->add($key, $value);
275 * Accessor for single value.
276 * @return string/array False if missing, string
277 * if present and array if
278 * multiple entries.
279 * @access public
281 function getValue($key) {
282 $values = array();
283 foreach ($this->_request as $pair) {
284 if ($pair->isKey($key)) {
285 $values[] = $pair->getValue();
288 if (count($values) == 0) {
289 return false;
290 } elseif (count($values) == 1) {
291 return $values[0];
292 } else {
293 return $values;
298 * Accessor for listing of pairs.
299 * @return array All pair objects.
300 * @access public
302 function getAll() {
303 return $this->_request;
307 * Renders the query string as a URL encoded
308 * request part.
309 * @return string Part of URL.
310 * @access protected
312 function _encode() {
313 $statements = array();
314 foreach ($this->_request as $pair) {
315 if ($statement = $pair->asRequest()) {
316 $statements[] = $statement;
319 return implode('&', $statements);
324 * Bundle of GET parameters. Can include
325 * repeated parameters.
326 * @package SimpleTest
327 * @subpackage WebTester
329 class SimpleGetEncoding extends SimpleEncoding {
332 * Starts empty.
333 * @param array $query Hash of parameters.
334 * Multiple values are
335 * as lists on a single key.
336 * @access public
338 function SimpleGetEncoding($query = false) {
339 $this->SimpleEncoding($query);
343 * HTTP request method.
344 * @return string Always GET.
345 * @access public
347 function getMethod() {
348 return 'GET';
352 * Writes no extra headers.
353 * @param SimpleSocket $socket Socket to write to.
354 * @access public
356 function writeHeadersTo(&$socket) {
360 * No data is sent to the socket as the data is encoded into
361 * the URL.
362 * @param SimpleSocket $socket Socket to write to.
363 * @access public
365 function writeTo(&$socket) {
369 * Renders the query string as a URL encoded
370 * request part for attaching to a URL.
371 * @return string Part of URL.
372 * @access public
374 function asUrlRequest() {
375 return $this->_encode();
380 * Bundle of URL parameters for a HEAD request.
381 * @package SimpleTest
382 * @subpackage WebTester
384 class SimpleHeadEncoding extends SimpleGetEncoding {
387 * Starts empty.
388 * @param array $query Hash of parameters.
389 * Multiple values are
390 * as lists on a single key.
391 * @access public
393 function SimpleHeadEncoding($query = false) {
394 $this->SimpleGetEncoding($query);
398 * HTTP request method.
399 * @return string Always HEAD.
400 * @access public
402 function getMethod() {
403 return 'HEAD';
408 * Bundle of POST parameters. Can include
409 * repeated parameters.
410 * @package SimpleTest
411 * @subpackage WebTester
413 class SimplePostEncoding extends SimpleEncoding {
416 * Starts empty.
417 * @param array $query Hash of parameters.
418 * Multiple values are
419 * as lists on a single key.
420 * @access public
422 function SimplePostEncoding($query = false) {
423 if (is_array($query) and $this->hasMoreThanOneLevel($query)) {
424 $query = $this->rewriteArrayWithMultipleLevels($query);
426 $this->SimpleEncoding($query);
429 function hasMoreThanOneLevel($query) {
430 foreach ($query as $key => $value) {
431 if (is_array($value)) {
432 return true;
435 return false;
438 function rewriteArrayWithMultipleLevels($query) {
439 $query_ = array();
440 foreach ($query as $key => $value) {
441 if (is_array($value)) {
442 foreach ($value as $sub_key => $sub_value) {
443 $query_[$key."[".$sub_key."]"] = $sub_value;
445 } else {
446 $query_[$key] = $value;
449 if ($this->hasMoreThanOneLevel($query_)) {
450 $query_ = $this->rewriteArrayWithMultipleLevels($query_);
453 return $query_;
458 * HTTP request method.
459 * @return string Always POST.
460 * @access public
462 function getMethod() {
463 return 'POST';
467 * Dispatches the form headers down the socket.
468 * @param SimpleSocket $socket Socket to write to.
469 * @access public
471 function writeHeadersTo(&$socket) {
472 $socket->write("Content-Length: " . (integer)strlen($this->_encode()) . "\r\n");
473 $socket->write("Content-Type: application/x-www-form-urlencoded\r\n");
477 * Dispatches the form data down the socket.
478 * @param SimpleSocket $socket Socket to write to.
479 * @access public
481 function writeTo(&$socket) {
482 $socket->write($this->_encode());
486 * Renders the query string as a URL encoded
487 * request part for attaching to a URL.
488 * @return string Part of URL.
489 * @access public
491 function asUrlRequest() {
492 return '';
497 * Bundle of POST parameters in the multipart
498 * format. Can include file uploads.
499 * @package SimpleTest
500 * @subpackage WebTester
502 class SimpleMultipartEncoding extends SimplePostEncoding {
503 var $_boundary;
506 * Starts empty.
507 * @param array $query Hash of parameters.
508 * Multiple values are
509 * as lists on a single key.
510 * @access public
512 function SimpleMultipartEncoding($query = false, $boundary = false) {
513 $this->SimplePostEncoding($query);
514 $this->_boundary = ($boundary === false ? uniqid('st') : $boundary);
518 * Dispatches the form headers down the socket.
519 * @param SimpleSocket $socket Socket to write to.
520 * @access public
522 function writeHeadersTo(&$socket) {
523 $socket->write("Content-Length: " . (integer)strlen($this->_encode()) . "\r\n");
524 $socket->write("Content-Type: multipart/form-data, boundary=" . $this->_boundary . "\r\n");
528 * Dispatches the form data down the socket.
529 * @param SimpleSocket $socket Socket to write to.
530 * @access public
532 function writeTo(&$socket) {
533 $socket->write($this->_encode());
537 * Renders the query string as a URL encoded
538 * request part.
539 * @return string Part of URL.
540 * @access public
542 function _encode() {
543 $stream = '';
544 foreach ($this->_request as $pair) {
545 $stream .= "--" . $this->_boundary . "\r\n";
546 $stream .= $pair->asMime() . "\r\n";
548 $stream .= "--" . $this->_boundary . "--\r\n";
549 return $stream;