Source for file encoding.php

Documentation is available at encoding.php

  1. <?php
  2. /**
  3.  *  base include file for SimpleTest
  4.  *  @package    SimpleTest
  5.  *  @subpackage WebTester
  6.  *  @version    $Id: encoding.php 1964 2009-10-13 15:27:31Z maetl_ $
  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.     private $key;
  21.     private $value;
  22.     
  23.     /**
  24.      *    Stashes the data for rendering later.
  25.      *    @param string $key       Form element name.
  26.      *    @param string $value     Data to send.
  27.      */
  28.     function __construct($key$value{
  29.         $this->key $key;
  30.         $this->value $value;
  31.     }
  32.     
  33.     /**
  34.      *    The pair as a single string.
  35.      *    @return string        Encoded pair.
  36.      *    @access public
  37.      */
  38.     function asRequest({
  39.         return urlencode($this->key'=' urlencode($this->value);
  40.     }
  41.     
  42.     /**
  43.      *    The MIME part as a string.
  44.      *    @return string        MIME part encoding.
  45.      *    @access public
  46.      */
  47.     function asMime({
  48.         $part 'Content-Disposition: form-data; ';
  49.         $part .= "name=\"" $this->key "\"\r\n";
  50.         $part .= "\r\n" $this->value;
  51.         return $part;
  52.     }
  53.     
  54.     /**
  55.      *    Is this the value we are looking for?
  56.      *    @param string $key    Identifier.
  57.      *    @return boolean       True if matched.
  58.      *    @access public
  59.      */
  60.     function isKey($key{
  61.         return $key == $this->key;
  62.     }
  63.     
  64.     /**
  65.      *    Is this the value we are looking for?
  66.      *    @return string       Identifier.
  67.      *    @access public
  68.      */
  69.     function getKey({
  70.         return $this->key;
  71.     }
  72.     
  73.     /**
  74.      *    Is this the value we are looking for?
  75.      *    @return string       Content.
  76.      *    @access public
  77.      */
  78.     function getValue({
  79.         return $this->value;
  80.     }
  81. }
  82.  
  83. /**
  84.  *    Single post parameter.
  85.  *    @package SimpleTest
  86.  *    @subpackage WebTester
  87.  */
  88.     private $key;
  89.     private $content;
  90.     private $filename;
  91.     
  92.     /**
  93.      *    Stashes the data for rendering later.
  94.      *    @param string $key          Key to add value to.
  95.      *    @param string $content      Raw data.
  96.      *    @param hash $filename       Original filename.
  97.      */
  98.     function __construct($key$content$filename{
  99.         $this->key $key;
  100.         $this->content $content;
  101.         $this->filename $filename;
  102.     }
  103.     
  104.     /**
  105.      *    The pair as a single string.
  106.      *    @return string        Encoded pair.
  107.      *    @access public
  108.      */
  109.     function asRequest({
  110.         return '';
  111.     }
  112.     
  113.     /**
  114.      *    The MIME part as a string.
  115.      *    @return string        MIME part encoding.
  116.      *    @access public
  117.      */
  118.     function asMime({
  119.         $part 'Content-Disposition: form-data; ';
  120.         $part .= 'name="' $this->key '"; ';
  121.         $part .= 'filename="' $this->filename '"';
  122.         $part .= "\r\nContent-Type: " $this->deduceMimeType();
  123.         $part .= "\r\n\r\n" $this->content;
  124.         return $part;
  125.     }
  126.     
  127.     /**
  128.      *    Attempts to figure out the MIME type from the
  129.      *    file extension and the content.
  130.      *    @return string        MIME type.
  131.      *    @access private
  132.      */
  133.     protected function deduceMimeType({
  134.         if ($this->isOnlyAscii($this->content)) {
  135.             return 'text/plain';
  136.         }
  137.         return 'application/octet-stream';
  138.     }
  139.     
  140.     /**
  141.      *    Tests each character is in the range 0-127.
  142.      *    @param string $ascii    String to test.
  143.      *    @access private
  144.      */
  145.     protected function isOnlyAscii($ascii{
  146.         for ($i 0$length strlen($ascii)$i $length$i++{
  147.             if (ord($ascii[$i]127{
  148.                 return false;
  149.             }
  150.         }
  151.         return true;
  152.     }
  153.     
  154.     /**
  155.      *    Is this the value we are looking for?
  156.      *    @param string $key    Identifier.
  157.      *    @return boolean       True if matched.
  158.      *    @access public
  159.      */
  160.     function isKey($key{
  161.         return $key == $this->key;
  162.     }
  163.     
  164.     /**
  165.      *    Is this the value we are looking for?
  166.      *    @return string       Identifier.
  167.      *    @access public
  168.      */
  169.     function getKey({
  170.         return $this->key;
  171.     }
  172.     
  173.     /**
  174.      *    Is this the value we are looking for?
  175.      *    @return string       Content.
  176.      *    @access public
  177.      */
  178.     function getValue({
  179.         return $this->filename;
  180.     }
  181. }
  182.  
  183. /**
  184.  *    Bundle of GET/POST parameters. Can include
  185.  *    repeated parameters.
  186.  *    @package SimpleTest
  187.  *    @subpackage WebTester
  188.  */
  189. class SimpleEncoding {
  190.     private $request;
  191.     
  192.     /**
  193.      *    Starts empty.
  194.      *    @param array $query       Hash of parameters.
  195.      *                               Multiple values are
  196.      *                               as lists on a single key.
  197.      *    @access public
  198.      */
  199.     function __construct($query false{
  200.         if ($query{
  201.             $query array();
  202.         }
  203.         $this->clear();
  204.         $this->merge($query);
  205.     }
  206.     
  207.     /**
  208.      *    Empties the request of parameters.
  209.      *    @access public
  210.      */
  211.     function clear({
  212.         $this->request array();
  213.     }
  214.     
  215.     /**
  216.      *    Adds a parameter to the query.
  217.      *    @param string $key            Key to add value to.
  218.      *    @param string/array $value    New data.
  219.      *    @access public
  220.      */
  221.     function add($key$value{
  222.         if ($value === false{
  223.             return;
  224.         }
  225.         if (is_array($value)) {
  226.             foreach ($value as $item{
  227.                 $this->addPair($key$item);
  228.             }
  229.         else {
  230.             $this->addPair($key$value);
  231.         }
  232.     }
  233.     
  234.     /**
  235.      *    Adds a new value into the request.
  236.      *    @param string $key            Key to add value to.
  237.      *    @param string/array $value    New data.
  238.      *    @access private
  239.      */
  240.     protected function addPair($key$value{
  241.         $this->request[new SimpleEncodedPair($key$value);
  242.     }
  243.     
  244.     /**
  245.      *    Adds a MIME part to the query. Does nothing for a
  246.      *    form encoded packet.
  247.      *    @param string $key          Key to add value to.
  248.      *    @param string $content      Raw data.
  249.      *    @param hash $filename       Original filename.
  250.      *    @access public
  251.      */
  252.     function attach($key$content$filename{
  253.         $this->request[new SimpleAttachment($key$content$filename);
  254.     }
  255.     
  256.     /**
  257.      *    Adds a set of parameters to this query.
  258.      *    @param array/SimpleQueryString $query  Multiple values are
  259.      *                                            as lists on a single key.
  260.      *    @access public
  261.      */
  262.     function merge($query{
  263.         if (is_object($query)) {
  264.             $this->request array_merge($this->request$query->getAll());
  265.         elseif (is_array($query)) {
  266.             foreach ($query as $key => $value{
  267.                 $this->add($key$value);
  268.             }
  269.         }
  270.     }
  271.     
  272.     /**
  273.      *    Accessor for single value.
  274.      *    @return string/array    False if missing, string
  275.      *                             if present and array if
  276.      *                             multiple entries.
  277.      *    @access public
  278.      */
  279.     function getValue($key{
  280.         $values array();
  281.         foreach ($this->request as $pair{
  282.             if ($pair->isKey($key)) {
  283.                 $values[$pair->getValue();
  284.             }
  285.         }
  286.         if (count($values== 0{
  287.             return false;
  288.         elseif (count($values== 1{
  289.             return $values[0];
  290.         else {
  291.             return $values;
  292.         }
  293.     }
  294.     
  295.     /**
  296.      *    Accessor for listing of pairs.
  297.      *    @return array        All pair objects.
  298.      *    @access public
  299.      */
  300.     function getAll({
  301.         return $this->request;
  302.     }
  303.     
  304.     /**
  305.      *    Renders the query string as a URL encoded
  306.      *    request part.
  307.      *    @return string        Part of URL.
  308.      *    @access protected
  309.      */
  310.     protected function encode({
  311.         $statements array();
  312.         foreach ($this->request as $pair{
  313.             if ($statement $pair->asRequest()) {
  314.                 $statements[$statement;
  315.             }
  316.         }
  317.         return implode('&'$statements);
  318.     }
  319. }
  320.  
  321. /**
  322.  *    Bundle of GET parameters. Can include
  323.  *    repeated parameters.
  324.  *    @package SimpleTest
  325.  *    @subpackage WebTester
  326.  */
  327. class SimpleGetEncoding extends SimpleEncoding {
  328.     
  329.     /**
  330.      *    Starts empty.
  331.      *    @param array $query       Hash of parameters.
  332.      *                               Multiple values are
  333.      *                               as lists on a single key.
  334.      *    @access public
  335.      */
  336.     function __construct($query false{
  337.         parent::__construct($query);
  338.     }
  339.     
  340.     /**
  341.      *    HTTP request method.
  342.      *    @return string        Always GET.
  343.      *    @access public
  344.      */
  345.     function getMethod({
  346.         return 'GET';
  347.     }
  348.     
  349.     /**
  350.      *    Writes no extra headers.
  351.      *    @param SimpleSocket $socket        Socket to write to.
  352.      *    @access public
  353.      */
  354.     function writeHeadersTo(&$socket{
  355.     }
  356.     
  357.     /**
  358.      *    No data is sent to the socket as the data is encoded into
  359.      *    the URL.
  360.      *    @param SimpleSocket $socket        Socket to write to.
  361.      *    @access public
  362.      */
  363.     function writeTo(&$socket{
  364.     }
  365.     
  366.     /**
  367.      *    Renders the query string as a URL encoded
  368.      *    request part for attaching to a URL.
  369.      *    @return string        Part of URL.
  370.      *    @access public
  371.      */
  372.     function asUrlRequest({
  373.         return $this->encode();
  374.     }
  375. }
  376.  
  377. /**
  378.  *    Bundle of URL parameters for a HEAD request.
  379.  *    @package SimpleTest
  380.  *    @subpackage WebTester
  381.  */
  382.     
  383.     /**
  384.      *    Starts empty.
  385.      *    @param array $query       Hash of parameters.
  386.      *                               Multiple values are
  387.      *                               as lists on a single key.
  388.      *    @access public
  389.      */
  390.     function __construct($query false{
  391.         parent::__construct($query);
  392.     }
  393.     
  394.     /**
  395.      *    HTTP request method.
  396.      *    @return string        Always HEAD.
  397.      *    @access public
  398.      */
  399.     function getMethod({
  400.         return 'HEAD';
  401.     }
  402. }
  403.  
  404. /**
  405.  *    Bundle of URL parameters for a DELETE request.
  406.  *    @package SimpleTest
  407.  *    @subpackage WebTester
  408.  */
  409.     
  410.     /**
  411.      *    Starts empty.
  412.      *    @param array $query       Hash of parameters.
  413.      *                               Multiple values are
  414.      *                               as lists on a single key.
  415.      *    @access public
  416.      */
  417.     function __construct($query false{
  418.         parent::__construct($query);
  419.     }
  420.     
  421.     /**
  422.      *    HTTP request method.
  423.      *    @return string        Always DELETE.
  424.      *    @access public
  425.      */
  426.     function getMethod({
  427.         return 'DELETE';
  428.     }
  429. }
  430.  
  431. /**
  432.  *    Bundles an entity-body for transporting
  433.  *    a raw content payload with the request.
  434.  *    @package SimpleTest
  435.  *    @subpackage WebTester
  436.  */
  437.     private $content_type;
  438.     private $body;
  439.     
  440.     function __construct($query false$content_type false{
  441.         $this->content_type $content_type;
  442.         if (is_string($query)) {
  443.             $this->body $query;
  444.             parent::__construct();
  445.         else {
  446.             parent::__construct($query);
  447.         }
  448.     }
  449.     
  450.     /**
  451.      *    Returns the media type of the entity body
  452.      *    @return string 
  453.      *    @access public
  454.      */
  455.     function getContentType({
  456.         if (!$this->content_type{
  457.             return ($this->body'text/plain' 'application/x-www-form-urlencoded';
  458.         }
  459.         return $this->content_type;
  460.     }
  461.        
  462.     /**
  463.      *    Dispatches the form headers down the socket.
  464.      *    @param SimpleSocket $socket        Socket to write to.
  465.      *    @access public
  466.      */
  467.     function writeHeadersTo(&$socket{
  468.         $socket->write("Content-Length: " . (integer)strlen($this->encode()) "\r\n");
  469.         $socket->write("Content-Type: " .  $this->getContentType("\r\n");
  470.     }
  471.     
  472.     /**
  473.      *    Dispatches the form data down the socket.
  474.      *    @param SimpleSocket $socket        Socket to write to.
  475.      *    @access public
  476.      */
  477.     function writeTo(&$socket{
  478.         $socket->write($this->encode());
  479.     }
  480.     
  481.     /**
  482.      *    Renders the request body
  483.      *    @return Encoded entity body
  484.      *    @access protected
  485.      */
  486.     protected function encode({
  487.         return ($this->body$this->body parent::encode();
  488.     }
  489. }
  490.  
  491. /**
  492.  *    Bundle of POST parameters. Can include
  493.  *    repeated parameters.
  494.  *    @package SimpleTest
  495.  *    @subpackage WebTester
  496.  */
  497.     
  498.     /**
  499.      *    Starts empty.
  500.      *    @param array $query       Hash of parameters.
  501.      *                               Multiple values are
  502.      *                               as lists on a single key.
  503.      *    @access public
  504.      */
  505.     function __construct($query false$content_type false{
  506.         if (is_array($queryand $this->hasMoreThanOneLevel($query)) {
  507.             $query $this->rewriteArrayWithMultipleLevels($query);
  508.         }
  509.         parent::__construct($query$content_type);
  510.     }
  511.     
  512.     function hasMoreThanOneLevel($query{
  513.         foreach ($query as $key => $value{
  514.             if (is_array($value)) {
  515.                 return true;
  516.             }
  517.         }
  518.         return false;
  519.     }
  520.  
  521.     function rewriteArrayWithMultipleLevels($query{
  522.         $query_ array();
  523.         foreach ($query as $key => $value{
  524.             if (is_array($value)) {
  525.                 foreach ($value as $sub_key => $sub_value{
  526.                     $query_[$key."[".$sub_key."]"$sub_value;
  527.                 }
  528.             else {
  529.                 $query_[$key$value;
  530.             }
  531.         }
  532.         if ($this->hasMoreThanOneLevel($query_)) {
  533.             $query_ $this->rewriteArrayWithMultipleLevels($query_);
  534.         }
  535.         
  536.         return $query_;
  537.     }
  538.     
  539.     /**
  540.      *    HTTP request method.
  541.      *    @return string        Always POST.
  542.      *    @access public
  543.      */
  544.     function getMethod({
  545.         return 'POST';
  546.     }
  547.     
  548.     /**
  549.      *    Renders the query string as a URL encoded
  550.      *    request part for attaching to a URL.
  551.      *    @return string        Part of URL.
  552.      *    @access public
  553.      */
  554.     function asUrlRequest({
  555.         return '';
  556.     }
  557. }
  558.  
  559. /**
  560.  *    Encoded entity body for a PUT request.
  561.  *    @package SimpleTest
  562.  *    @subpackage WebTester
  563.  */
  564.     
  565.     /**
  566.      *    Starts empty.
  567.      *    @param array $query       Hash of parameters.
  568.      *                               Multiple values are
  569.      *                               as lists on a single key.
  570.      *    @access public
  571.      */
  572.     function __construct($query false$content_type false{
  573.         parent::__construct($query$content_type);
  574.     }
  575.     
  576.     /**
  577.      *    HTTP request method.
  578.      *    @return string        Always PUT.
  579.      *    @access public
  580.      */
  581.     function getMethod({
  582.         return 'PUT';
  583.     }
  584. }
  585.  
  586. /**
  587.  *    Bundle of POST parameters in the multipart
  588.  *    format. Can include file uploads.
  589.  *    @package SimpleTest
  590.  *    @subpackage WebTester
  591.  */
  592.     private $boundary;
  593.     
  594.     /**
  595.      *    Starts empty.
  596.      *    @param array $query       Hash of parameters.
  597.      *                               Multiple values are
  598.      *                               as lists on a single key.
  599.      *    @access public
  600.      */
  601.     function __construct($query false$boundary false{
  602.         parent::__construct($query);
  603.         $this->boundary ($boundary === false uniqid('st'$boundary);
  604.     }
  605.     
  606.     /**
  607.      *    Dispatches the form headers down the socket.
  608.      *    @param SimpleSocket $socket        Socket to write to.
  609.      *    @access public
  610.      */
  611.     function writeHeadersTo(&$socket{
  612.         $socket->write("Content-Length: " . (integer)strlen($this->encode()) "\r\n");
  613.         $socket->write("Content-Type: multipart/form-data; boundary=" $this->boundary "\r\n");
  614.     }
  615.     
  616.     /**
  617.      *    Dispatches the form data down the socket.
  618.      *    @param SimpleSocket $socket        Socket to write to.
  619.      *    @access public
  620.      */
  621.     function writeTo(&$socket{
  622.         $socket->write($this->encode());
  623.     }
  624.     
  625.     /**
  626.      *    Renders the query string as a URL encoded
  627.      *    request part.
  628.      *    @return string        Part of URL.
  629.      *    @access public
  630.      */
  631.     function encode({
  632.         $stream '';
  633.         foreach ($this->getAll(as $pair{
  634.             $stream .= "--" $this->boundary "\r\n";
  635.             $stream .= $pair->asMime("\r\n";
  636.         }
  637.         $stream .= "--" $this->boundary "--\r\n";
  638.         return $stream;
  639.     }
  640. }
  641. ?>

Documentation generated on Sun, 31 Oct 2010 16:31:19 -0500 by phpDocumentor 1.4.3