Completed
Pull Request — 3.6 (#7850)
by Jono
07:19
created

SimpleAttachment::asRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 *  base include file for SimpleTest
4
 *  @package    SimpleTest
5
 *  @subpackage WebTester
6
 *  @version    $Id: encoding.php 1723 2008-04-08 00:34:10Z lastcraft $
7
 */
8
    
9
/**#@+
10
 *  include other SimpleTest class files
11
 */
12
require_once(dirname(__FILE__) . '/socket.php');
13
/**#@-*/
14
15
/**
16
 *    Single post parameter.
17
 *    @package SimpleTest
18
 *    @subpackage WebTester
19
 */
20
class SimpleEncodedPair {
21
    var $_key;
22
    var $_value;
23
    
24
    /**
25
     *    Stashes the data for rendering later.
26
     *    @param string $key       Form element name.
27
     *    @param string $value     Data to send.
28
     */
29
    function SimpleEncodedPair($key, $value) {
30
        $this->_key = $key;
31
        $this->_value = $value;
32
    }
33
    
34
    /**
35
     *    The pair as a single string.
36
     *    @return string        Encoded pair.
37
     *    @access public
38
     */
39
    function asRequest() {
40
        return urlencode($this->_key) . '=' . urlencode($this->_value);
41
    }
42
    
43
    /**
44
     *    The MIME part as a string.
45
     *    @return string        MIME part encoding.
46
     *    @access public
47
     */
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;
53
    }
54
    
55
    /**
56
     *    Is this the value we are looking for?
57
     *    @param string $key    Identifier.
58
     *    @return boolean       True if matched.
59
     *    @access public
60
     */
61
    function isKey($key) {
62
        return $key == $this->_key;
63
    }
64
    
65
    /**
66
     *    Is this the value we are looking for?
67
     *    @return string       Identifier.
68
     *    @access public
69
     */
70
    function getKey() {
71
        return $this->_key;
72
    }
73
    
74
    /**
75
     *    Is this the value we are looking for?
76
     *    @return string       Content.
77
     *    @access public
78
     */
79
    function getValue() {
80
        return $this->_value;
81
    }
82
}
83
84
/**
85
 *    Single post parameter.
86
 *    @package SimpleTest
87
 *    @subpackage WebTester
88
 */
89
class SimpleAttachment {
90
    var $_key;
91
    var $_content;
92
    var $_filename;
93
    
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.
99
     */
100
    function SimpleAttachment($key, $content, $filename) {
101
        $this->_key = $key;
102
        $this->_content = $content;
103
        $this->_filename = $filename;
104
    }
105
    
106
    /**
107
     *    The pair as a single string.
108
     *    @return string        Encoded pair.
109
     *    @access public
110
     */
111
    function asRequest() {
112
        return '';
113
    }
114
    
115
    /**
116
     *    The MIME part as a string.
117
     *    @return string        MIME part encoding.
118
     *    @access public
119
     */
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;
127
    }
128
    
129
    /**
130
     *    Attempts to figure out the MIME type from the
131
     *    file extension and the content.
132
     *    @return string        MIME type.
133
     *    @access private
134
     */
135
    function _deduceMimeType() {
136
        if ($this->_isOnlyAscii($this->_content)) {
137
            return 'text/plain';
138
        }
139
        return 'application/octet-stream';
140
    }
141
    
142
    /**
143
     *    Tests each character is in the range 0-127.
144
     *    @param string $ascii    String to test.
145
     *    @access private
146
     */
147
    function _isOnlyAscii($ascii) {
148
        for ($i = 0, $length = strlen($ascii); $i < $length; $i++) {
149
            if (ord($ascii[$i]) > 127) {
150
                return false;
151
            }
152
        }
153
        return true;
154
    }
155
    
156
    /**
157
     *    Is this the value we are looking for?
158
     *    @param string $key    Identifier.
159
     *    @return boolean       True if matched.
160
     *    @access public
161
     */
162
    function isKey($key) {
163
        return $key == $this->_key;
164
    }
165
    
166
    /**
167
     *    Is this the value we are looking for?
168
     *    @return string       Identifier.
169
     *    @access public
170
     */
171
    function getKey() {
172
        return $this->_key;
173
    }
174
    
175
    /**
176
     *    Is this the value we are looking for?
177
     *    @return string       Content.
178
     *    @access public
179
     */
180
    function getValue() {
181
        return $this->_filename;
182
    }
183
}
184
185
/**
186
 *    Bundle of GET/POST parameters. Can include
187
 *    repeated parameters.
188
 *    @package SimpleTest
189
 *    @subpackage WebTester
190
 */
191
class SimpleEncoding {
192
    var $_request;
193
    
194
    /**
195
     *    Starts empty.
196
     *    @param array $query       Hash of parameters.
197
     *                              Multiple values are
198
     *                              as lists on a single key.
199
     *    @access public
200
     */
201
    function SimpleEncoding($query = false) {
202
        if (! $query) {
203
            $query = array();
204
        }
205
        $this->clear();
206
        $this->merge($query);
207
    }
208
    
209
    /**
210
     *    Empties the request of parameters.
211
     *    @access public
212
     */
213
    function clear() {
214
        $this->_request = array();
215
    }
216
    
217
    /**
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
222
     */
223
    function add($key, $value) {
224
        if ($value === false) {
225
            return;
226
        }
227
        if (is_array($value)) {
228
            foreach ($value as $item) {
229
                $this->_addPair($key, $item);
230
            }
231
        } else {
232
            $this->_addPair($key, $value);
233
        }
234
    }
235
    
236
    /**
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
241
     */
242
    function _addPair($key, $value) {
243
        $this->_request[] = new SimpleEncodedPair($key, $value);
244
    }
245
    
246
    /**
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
253
     */
254
    function attach($key, $content, $filename) {
255
        $this->_request[] = new SimpleAttachment($key, $content, $filename);
256
    }
257
    
258
    /**
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
263
     */
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);
270
            }
271
        }
272
    }
273
    
274
    /**
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
280
     */
281
    function getValue($key) {
282
        $values = array();
283
        foreach ($this->_request as $pair) {
284
            if ($pair->isKey($key)) {
285
                $values[] = $pair->getValue();
286
            }
287
        }
288
        if (count($values) == 0) {
289
            return false;
290
        } elseif (count($values) == 1) {
291
            return $values[0];
292
        } else {
293
            return $values;
294
        }
295
    }
296
    
297
    /**
298
     *    Accessor for listing of pairs.
299
     *    @return array        All pair objects.
300
     *    @access public
301
     */
302
    function getAll() {
303
        return $this->_request;
304
    }
305
    
306
    /**
307
     *    Renders the query string as a URL encoded
308
     *    request part.
309
     *    @return string        Part of URL.
310
     *    @access protected
311
     */
312
    function _encode() {
313
        $statements = array();
314
        foreach ($this->_request as $pair) {
315
            if ($statement = $pair->asRequest()) {
316
                $statements[] = $statement;
317
            }
318
        }
319
        return implode('&', $statements);
320
    }
321
}
322
323
/**
324
 *    Bundle of GET parameters. Can include
325
 *    repeated parameters.
326
 *    @package SimpleTest
327
 *    @subpackage WebTester
328
 */
329
class SimpleGetEncoding extends SimpleEncoding {
330
    
331
    /**
332
     *    Starts empty.
333
     *    @param array $query       Hash of parameters.
334
     *                              Multiple values are
335
     *                              as lists on a single key.
336
     *    @access public
337
     */
338
    function SimpleGetEncoding($query = false) {
339
        $this->SimpleEncoding($query);
340
    }
341
    
342
    /**
343
     *    HTTP request method.
344
     *    @return string        Always GET.
345
     *    @access public
346
     */
347
    function getMethod() {
348
        return 'GET';
349
    }
350
    
351
    /**
352
     *    Writes no extra headers.
353
     *    @param SimpleSocket $socket        Socket to write to.
354
     *    @access public
355
     */
356
    function writeHeadersTo(&$socket) {
357
    }
358
    
359
    /**
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
364
     */
365
    function writeTo(&$socket) {
366
    }
367
    
368
    /**
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
373
     */
374
    function asUrlRequest() {
375
        return $this->_encode();
376
    }
377
}
378
379
/**
380
 *    Bundle of URL parameters for a HEAD request.
381
 *    @package SimpleTest
382
 *    @subpackage WebTester
383
 */
384
class SimpleHeadEncoding extends SimpleGetEncoding {
385
    
386
    /**
387
     *    Starts empty.
388
     *    @param array $query       Hash of parameters.
389
     *                              Multiple values are
390
     *                              as lists on a single key.
391
     *    @access public
392
     */
393
    function SimpleHeadEncoding($query = false) {
394
        $this->SimpleGetEncoding($query);
395
    }
396
    
397
    /**
398
     *    HTTP request method.
399
     *    @return string        Always HEAD.
400
     *    @access public
401
     */
402
    function getMethod() {
403
        return 'HEAD';
404
    }
405
}
406
407
/**
408
 *    Bundle of POST parameters. Can include
409
 *    repeated parameters.
410
 *    @package SimpleTest
411
 *    @subpackage WebTester
412
 */
413
class SimplePostEncoding extends SimpleEncoding {
414
    
415
    /**
416
     *    Starts empty.
417
     *    @param array $query       Hash of parameters.
418
     *                              Multiple values are
419
     *                              as lists on a single key.
420
     *    @access public
421
     */
422
    function SimplePostEncoding($query = false) {
423
        if (is_array($query) and $this->hasMoreThanOneLevel($query)) {
424
            $query = $this->rewriteArrayWithMultipleLevels($query);
425
        }
426
        $this->SimpleEncoding($query);
427
    }
428
    
429
    function hasMoreThanOneLevel($query) {
430
        foreach ($query as $key => $value) {
431
            if (is_array($value)) {
432
                return true;
433
            }
434
        }
435
        return false;
436
    }
437
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;
444
                }
445
            } else {
446
                $query_[$key] = $value;
447
            }
448
        }
449
        if ($this->hasMoreThanOneLevel($query_)) {
450
            $query_ = $this->rewriteArrayWithMultipleLevels($query_);
451
        }
452
        
453
        return $query_;
454
    }
455
    
456
    
457
    /**
458
     *    HTTP request method.
459
     *    @return string        Always POST.
460
     *    @access public
461
     */
462
    function getMethod() {
463
        return 'POST';
464
    }
465
    
466
    /**
467
     *    Dispatches the form headers down the socket.
468
     *    @param SimpleSocket $socket        Socket to write to.
469
     *    @access public
470
     */
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");
474
    }
475
    
476
    /**
477
     *    Dispatches the form data down the socket.
478
     *    @param SimpleSocket $socket        Socket to write to.
479
     *    @access public
480
     */
481
    function writeTo(&$socket) {
482
        $socket->write($this->_encode());
483
    }
484
    
485
    /**
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
490
     */
491
    function asUrlRequest() {
492
        return '';
493
    }
494
}
495
496
/**
497
 *    Bundle of POST parameters in the multipart
498
 *    format. Can include file uploads.
499
 *    @package SimpleTest
500
 *    @subpackage WebTester
501
 */
502
class SimpleMultipartEncoding extends SimplePostEncoding {
503
    var $_boundary;
504
    
505
    /**
506
     *    Starts empty.
507
     *    @param array $query       Hash of parameters.
508
     *                              Multiple values are
509
     *                              as lists on a single key.
510
     *    @access public
511
     */
512
    function SimpleMultipartEncoding($query = false, $boundary = false) {
513
        $this->SimplePostEncoding($query);
514
        $this->_boundary = ($boundary === false ? uniqid('st') : $boundary);
515
    }
516
    
517
    /**
518
     *    Dispatches the form headers down the socket.
519
     *    @param SimpleSocket $socket        Socket to write to.
520
     *    @access public
521
     */
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");
525
    }
526
    
527
    /**
528
     *    Dispatches the form data down the socket.
529
     *    @param SimpleSocket $socket        Socket to write to.
530
     *    @access public
531
     */
532
    function writeTo(&$socket) {
533
        $socket->write($this->_encode());
534
    }
535
    
536
    /**
537
     *    Renders the query string as a URL encoded
538
     *    request part.
539
     *    @return string        Part of URL.
540
     *    @access public
541
     */
542
    function _encode() {
543
        $stream = '';
544
        foreach ($this->_request as $pair) {
545
            $stream .= "--" . $this->_boundary . "\r\n";
546
            $stream .= $pair->asMime() . "\r\n";
547
        }
548
        $stream .= "--" . $this->_boundary . "--\r\n";
549
        return $stream;
550
    }
551
}
552
?>
553