Subversion Repositories oidplus

Rev

Rev 277 | Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /*
  4.  * This file includes:
  5.  *
  6.  * 1. PHP HTTP protocol client: HTTP client to access Web site pages
  7.  *    by Manuel Lemos
  8.  *    http://www.phpclasses.org/httpclient
  9.  *    License: BSD License
  10.  *
  11.  *    http.php
  12.  *        @(#) $Header: /opt2/ena/metal/http/http.php,v 1.94 2016/05/03 02:07:04 mlemos Exp $
  13.  *        Modified by Daniel Marschall, ViaThinkSoft, Revision 2020-09-12
  14.  *
  15.  *
  16.  * 2. Simple Authentication and Security Layer client
  17.  *    (Included because of dependency)
  18.  *    by Manuel Lemos
  19.  *    http://www.phpclasses.org/sasl
  20.  *    License: BSD License
  21.  *
  22.  *    sasl.php
  23.  *        @(#) $Id: sasl.php,v 1.11 2005/10/31 18:43:27 mlemos Exp $
  24.  *    basic_sasl_client.php
  25.  *        @(#) $Id: basic_sasl_client.php,v 1.1 2004/11/17 08:01:23 mlemos Exp $
  26.  *    cram_md5_sasl_client.php
  27.  *        @(#) $Id: cram_md5_sasl_client.php,v 1.3 2004/11/17 08:00:37 mlemos Exp $
  28.  *    digest_sasl_client.php
  29.  *        @(#) $Id: digest_sasl_client.php,v 1.1 2005/10/27 05:24:15 mlemos Exp $
  30.  *    login_sasl_client.php
  31.  *        @(#) $Id: login_sasl_client.php,v 1.2 2004/11/17 08:00:37 mlemos Exp $
  32.  *    ntlm_sasl_client.php
  33.  *        @(#) $Id: ntlm_sasl_client.php,v 1.3 2004/11/17 08:00:37 mlemos Exp $
  34.  *    plain_sasl_client.php
  35.  *        @(#) $Id: plain_sasl_client.php,v 1.2 2004/11/17 08:00:37 mlemos Exp $
  36.  */
  37.  
  38. // =============================================================================
  39.  
  40. /*
  41.  * basic_sasl_client.php
  42.  *
  43.  * @(#) $Id: basic_sasl_client.php,v 1.1 2004/11/17 08:01:23 mlemos Exp $
  44.  *
  45.  */
  46.  
  47. define("SASL_BASIC_STATE_START",    0);
  48. define("SASL_BASIC_STATE_DONE",     1);
  49.  
  50. class basic_sasl_client_class
  51. {
  52.         var $credentials=array();
  53.         var $state=SASL_BASIC_STATE_START;
  54.  
  55.         Function Initialize(&$client)
  56.         {
  57.                 return(1);
  58.         }
  59.  
  60.         Function Start(&$client, &$message, &$interactions)
  61.         {
  62.                 if($this->state!=SASL_BASIC_STATE_START)
  63.                 {
  64.                         $client->error="Basic authentication state is not at the start";
  65.                         return(SASL_FAIL);
  66.                 }
  67.                 $this->credentials=array(
  68.                         "user"=>"",
  69.                         "password"=>""
  70.                 );
  71.                 $defaults=array(
  72.                 );
  73.                 $status=$client->GetCredentials($this->credentials,$defaults,$interactions);
  74.                 if($status==SASL_CONTINUE)
  75.                 {
  76.                         $message=$this->credentials["user"].":".$this->credentials["password"];
  77.                         $this->state=SASL_BASIC_STATE_DONE;
  78.                 }
  79.                 else
  80.                         Unset($message);
  81.                 return($status);
  82.         }
  83.  
  84.         Function Step(&$client, $response, &$message, &$interactions)
  85.         {
  86.                 switch($this->state)
  87.                 {
  88.                         case SASL_BASIC_STATE_DONE:
  89.                                 $client->error="Basic authentication was finished without success";
  90.                                 return(SASL_FAIL);
  91.                         default:
  92.                                 $client->error="invalid Basic authentication step state";
  93.                                 return(SASL_FAIL);
  94.                 }
  95.                 return(SASL_CONTINUE);
  96.         }
  97. };
  98.  
  99. // =============================================================================
  100.  
  101. /*
  102.  * cram_md5_sasl_client.php
  103.  *
  104.  * @(#) $Id: cram_md5_sasl_client.php,v 1.3 2004/11/17 08:00:37 mlemos Exp $
  105.  *
  106.  */
  107.  
  108. define("SASL_CRAM_MD5_STATE_START",             0);
  109. define("SASL_CRAM_MD5_STATE_RESPOND_CHALLENGE", 1);
  110. define("SASL_CRAM_MD5_STATE_DONE",              2);
  111.  
  112. class cram_md5_sasl_client_class
  113. {
  114.         var $credentials=array();
  115.         var $state=SASL_CRAM_MD5_STATE_START;
  116.  
  117.         Function Initialize(&$client)
  118.         {
  119.                 return(1);
  120.         }
  121.  
  122.         Function HMACMD5($key,$text)
  123.         {
  124.                 $key=(strlen($key)<64 ? str_pad($key,64,"\0") : substr($key,0,64));
  125.                 return(md5((str_repeat("\x5c", 64)^$key).pack("H32", md5((str_repeat("\x36", 64)^$key).$text))));
  126.         }
  127.  
  128.         Function Start(&$client, &$message, &$interactions)
  129.         {
  130.                 if($this->state!=SASL_CRAM_MD5_STATE_START)
  131.                 {
  132.                         $client->error="CRAM-MD5 authentication state is not at the start";
  133.                         return(SASL_FAIL);
  134.                 }
  135.                 $this->credentials=array(
  136.                         "user"=>"",
  137.                         "password"=>""
  138.                 );
  139.                 $defaults=array();
  140.                 $status=$client->GetCredentials($this->credentials,$defaults,$interactions);
  141.                 if($status==SASL_CONTINUE)
  142.                         $this->state=SASL_CRAM_MD5_STATE_RESPOND_CHALLENGE;
  143.                 Unset($message);
  144.                 return($status);
  145.         }
  146.  
  147.         Function Step(&$client, $response, &$message, &$interactions)
  148.         {
  149.                 switch($this->state)
  150.                 {
  151.                         case SASL_CRAM_MD5_STATE_RESPOND_CHALLENGE:
  152.                                 $message=$this->credentials["user"]." ".$this->HMACMD5($this->credentials["password"], $response);
  153.                                 $this->state=SASL_CRAM_MD5_STATE_DONE;
  154.                                 break;
  155.                         case SASL_CRAM_MD5_STATE_DONE:
  156.                                 $client->error="CRAM-MD5 authentication was finished without success";
  157.                                 return(SASL_FAIL);
  158.                         default:
  159.                                 $client->error="invalid CRAM-MD5 authentication step state";
  160.                                 return(SASL_FAIL);
  161.                 }
  162.                 return(SASL_CONTINUE);
  163.         }
  164. };
  165.  
  166. // =============================================================================
  167.  
  168. /*
  169.  * digest_sasl_client.php
  170.  *
  171.  * @(#) $Id: digest_sasl_client.php,v 1.1 2005/10/27 05:24:15 mlemos Exp $
  172.  *
  173.  */
  174.  
  175. define('SASL_DIGEST_STATE_START',             0);
  176. define('SASL_DIGEST_STATE_RESPOND_CHALLENGE', 1);
  177. define('SASL_DIGEST_STATE_DONE',              2);
  178.  
  179. class digest_sasl_client_class
  180. {
  181.         var $credentials=array();
  182.         var $state=SASL_DIGEST_STATE_START;
  183.  
  184.         Function unq($string)
  185.         {
  186.                 return(($string[0]=='"' && $string[strlen($string)-1]=='"') ? substr($string, 1, strlen($string)-2) : $string);
  187.         }
  188.  
  189.         Function H($data)
  190.         {
  191.                 return md5($data);
  192.         }
  193.  
  194.         Function KD($secret, $data)
  195.         {
  196.                 return $this->H($secret.':'.$data);
  197.         }
  198.  
  199.         Function Initialize(&$client)
  200.         {
  201.                 return(1);
  202.         }
  203.  
  204.         Function Start(&$client, &$message, &$interactions)
  205.         {
  206.                 if($this->state!=SASL_DIGEST_STATE_START)
  207.                 {
  208.                         $client->error='Digest authentication state is not at the start';
  209.                         return(SASL_FAIL);
  210.                 }
  211.                 $this->credentials=array(
  212.                         'user'=>'',
  213.                         'password'=>'',
  214.                         'uri'=>'',
  215.                         'method'=>'',
  216.                         'session'=>''
  217.                 );
  218.                 $defaults=array();
  219.                 $status=$client->GetCredentials($this->credentials,$defaults,$interactions);
  220.                 if($status==SASL_CONTINUE)
  221.                         $this->state=SASL_DIGEST_STATE_RESPOND_CHALLENGE;
  222.                 Unset($message);
  223.                 return($status);
  224.         }
  225.  
  226.         Function Step(&$client, $response, &$message, &$interactions)
  227.         {
  228.                 switch($this->state)
  229.                 {
  230.                         case SASL_DIGEST_STATE_RESPOND_CHALLENGE:
  231.                                 $values=explode(',',$response);
  232.                                 $parameters=array();
  233.                                 for($v=0; $v<count($values); $v++)
  234.                                         $parameters[strtok(trim($values[$v]), '=')]=strtok('');
  235.  
  236.                                 $message='username="'.$this->credentials['user'].'"';
  237.                                 if(!IsSet($parameters[$p='realm'])
  238.                                 && !IsSet($parameters[$p='nonce']))
  239.                                 {
  240.                                         $client->error='Digest authentication parameter '.$p.' is missing from the server response';
  241.                                         return(SASL_FAIL);
  242.                                 }
  243.                                 $message.=', realm='.$parameters['realm'];
  244.                                 $message.=', nonce='.$parameters['nonce'];
  245.                                 $message.=', uri="'.$this->credentials['uri'].'"';
  246.                                 if(IsSet($parameters['algorithm']))
  247.                                 {
  248.                                         $algorithm=$this->unq($parameters['algorithm']);
  249.                                         $message.=', algorithm='.$parameters['algorithm'];
  250.                                 }
  251.                                 else
  252.                                         $algorithm='';
  253.  
  254.                                 $realm=$this->unq($parameters['realm']);
  255.                                 $nonce=$this->unq($parameters['nonce']);
  256.                                 if(IsSet($parameters['qop']))
  257.                                 {
  258.                                         switch($qop=$this->unq($parameters['qop']))
  259.                                         {
  260.                                                 case "auth":
  261.                                                         $cnonce=$this->credentials['session'];
  262.                                                         break;
  263.                                                 default:
  264.                                                         $client->error='Digest authentication quality of protection '.$qop.' is not yet supported';
  265.                                                         return(SASL_FAIL);
  266.                                         }
  267.                                 }
  268.                                 $nc_value='00000001';
  269.                                 if(IsSet($parameters['qop'])
  270.                                 && !strcmp($algorithm, 'MD5-sess'))
  271.                                         $A1=$this->H($this->credentials['user'].':'. $realm.':'. $this->credentials['password']).':'.$nonce.':'.$cnonce;
  272.                                 else
  273.                                         $A1=$this->credentials['user'].':'. $realm.':'. $this->credentials['password'];
  274.                                 $A2=$this->credentials['method'].':'.$this->credentials['uri'];
  275.                                 if(IsSet($parameters['qop']))
  276.                                         $response=$this->KD($this->H($A1), $nonce.':'. $nc_value.':'. $cnonce.':'. $qop.':'. $this->H($A2));
  277.                                 else
  278.                                         $response=$this->KD($this->H($A1), $nonce.':'. $this->H($A2));
  279.                                 $message.=', response="'.$response.'"';
  280.                                 if(IsSet($parameters['opaque']))
  281.                                         $message.=', opaque='.$parameters['opaque'];
  282.                                 if(IsSet($parameters['qop']))
  283.                                         $message.=', qop="'.$qop.'"';
  284.                                 $message.=', nc='.$nc_value;
  285.                                 if(IsSet($parameters['qop']))
  286.                                         $message.=', cnonce="'.$cnonce.'"';
  287.                                 $client->encode_response=0;
  288.                                 $this->state=SASL_DIGEST_STATE_DONE;
  289.                                 break;
  290.                         case SASL_DIGEST_STATE_DONE:
  291.                                 $client->error='Digest authentication was finished without success';
  292.                                 return(SASL_FAIL);
  293.                         default:
  294.                                 $client->error='invalid Digest authentication step state';
  295.                                 return(SASL_FAIL);
  296.                 }
  297.                 return(SASL_CONTINUE);
  298.         }
  299. };
  300.  
  301. // =============================================================================
  302.  
  303. /*
  304.  * login_sasl_client.php
  305.  *
  306.  * @(#) $Id: login_sasl_client.php,v 1.2 2004/11/17 08:00:37 mlemos Exp $
  307.  *
  308.  */
  309.  
  310. define("SASL_LOGIN_STATE_START",             0);
  311. define("SASL_LOGIN_STATE_IDENTIFY_USER",     1);
  312. define("SASL_LOGIN_STATE_IDENTIFY_PASSWORD", 2);
  313. define("SASL_LOGIN_STATE_DONE",              3);
  314.  
  315. class login_sasl_client_class
  316. {
  317.         var $credentials=array();
  318.         var $state=SASL_LOGIN_STATE_START;
  319.  
  320.         Function Initialize(&$client)
  321.         {
  322.                 return(1);
  323.         }
  324.  
  325.         Function Start(&$client, &$message, &$interactions)
  326.         {
  327.                 if($this->state!=SASL_LOGIN_STATE_START)
  328.                 {
  329.                         $client->error="LOGIN authentication state is not at the start";
  330.                         return(SASL_FAIL);
  331.                 }
  332.                 $this->credentials=array(
  333.                         "user"=>"",
  334.                         "password"=>"",
  335.                         "realm"=>""
  336.                 );
  337.                 $defaults=array(
  338.                         "realm"=>""
  339.                 );
  340.                 $status=$client->GetCredentials($this->credentials,$defaults,$interactions);
  341.                 if($status==SASL_CONTINUE)
  342.                         $this->state=SASL_LOGIN_STATE_IDENTIFY_USER;
  343.                 Unset($message);
  344.                 return($status);
  345.         }
  346.  
  347.         Function Step(&$client, $response, &$message, &$interactions)
  348.         {
  349.                 switch($this->state)
  350.                 {
  351.                         case SASL_LOGIN_STATE_IDENTIFY_USER:
  352.                                 $message=$this->credentials["user"].(strlen($this->credentials["realm"]) ? "@".$this->credentials["realm"] : "");
  353.                                 $this->state=SASL_LOGIN_STATE_IDENTIFY_PASSWORD;
  354.                                 break;
  355.                         case SASL_LOGIN_STATE_IDENTIFY_PASSWORD:
  356.                                 $message=$this->credentials["password"];
  357.                                 $this->state=SASL_LOGIN_STATE_DONE;
  358.                                 break;
  359.                         case SASL_LOGIN_STATE_DONE:
  360.                                 $client->error="LOGIN authentication was finished without success";
  361.                                 break;
  362.                         default:
  363.                                 $client->error="invalid LOGIN authentication step state";
  364.                                 return(SASL_FAIL);
  365.                 }
  366.                 return(SASL_CONTINUE);
  367.         }
  368. };
  369.  
  370. // =============================================================================
  371.  
  372. /*
  373.  * ntlm_sasl_client.php
  374.  *
  375.  * @(#) $Id: ntlm_sasl_client.php,v 1.3 2004/11/17 08:00:37 mlemos Exp $
  376.  *
  377.  */
  378.  
  379. define("SASL_NTLM_STATE_START",             0);
  380. define("SASL_NTLM_STATE_IDENTIFY_DOMAIN",   1);
  381. define("SASL_NTLM_STATE_RESPOND_CHALLENGE", 2);
  382. define("SASL_NTLM_STATE_DONE",              3);
  383.  
  384. class ntlm_sasl_client_class
  385. {
  386.         var $credentials=array();
  387.         var $state=SASL_NTLM_STATE_START;
  388.  
  389.         Function Initialize(&$client)
  390.         {
  391.                 if(!function_exists($function="mcrypt_encrypt")
  392.                 || !function_exists($function="mhash"))
  393.                 {
  394.                         $extensions=array(
  395.                                 "mcrypt_encrypt"=>"mcrypt",
  396.                                 "mhash"=>"mhash"
  397.                         );
  398.                         $client->error="the extension ".$extensions[$function]." required by the NTLM SASL client class is not available in this PHP configuration";
  399.                         return(0);
  400.                 }
  401.                 return(1);
  402.         }
  403.  
  404.         Function ASCIIToUnicode($ascii)
  405.         {
  406.                 for($unicode="",$a=0;$a<strlen($ascii);$a++)
  407.                         $unicode.=substr($ascii,$a,1).chr(0);
  408.                 return($unicode);
  409.         }
  410.  
  411.         Function TypeMsg1($domain,$workstation)
  412.         {
  413.                 $domain_length=strlen($domain);
  414.                 $workstation_length=strlen($workstation);
  415.                 $workstation_offset=32;
  416.                 $domain_offset=$workstation_offset+$workstation_length;
  417.                 return(
  418.                         "NTLMSSP\0".
  419.                         "\x01\x00\x00\x00".
  420.                         "\x07\x32\x00\x00".
  421.                         pack("v",$domain_length).
  422.                         pack("v",$domain_length).
  423.                         pack("V",$domain_offset).
  424.                         pack("v",$workstation_length).
  425.                         pack("v",$workstation_length).
  426.                         pack("V",$workstation_offset).
  427.                         $workstation.
  428.                         $domain
  429.                 );
  430.         }
  431.  
  432.         Function NTLMResponse($challenge,$password)
  433.         {
  434.                 $unicode=$this->ASCIIToUnicode($password);
  435.                 $md4=mhash(MHASH_MD4,$unicode);
  436.                 $padded=$md4.str_repeat(chr(0),21-strlen($md4));
  437.                 $iv_size=mcrypt_get_iv_size(MCRYPT_DES,MCRYPT_MODE_ECB);
  438.                 $iv=mcrypt_create_iv($iv_size,MCRYPT_RAND);
  439.                 for($response="",$third=0;$third<21;$third+=7)
  440.                 {
  441.                         for($packed="",$p=$third;$p<$third+7;$p++)
  442.                                 $packed.=str_pad(decbin(ord(substr($padded,$p,1))),8,"0",STR_PAD_LEFT);
  443.                         for($key="",$p=0;$p<strlen($packed);$p+=7)
  444.                         {
  445.                                 $s=substr($packed,$p,7);
  446.                                 $b=$s.((substr_count($s,"1") % 2) ? "0" : "1");
  447.                                 $key.=chr(bindec($b));
  448.                         }
  449.                         $ciphertext=mcrypt_encrypt(MCRYPT_DES,$key,$challenge,MCRYPT_MODE_ECB,$iv);
  450.                         $response.=$ciphertext;
  451.                 }
  452.                 return $response;
  453.         }
  454.  
  455.         Function TypeMsg3($ntlm_response,$user,$domain,$workstation)
  456.         {
  457.                 $domain_unicode=$this->ASCIIToUnicode($domain);
  458.                 $domain_length=strlen($domain_unicode);
  459.                 $domain_offset=64;
  460.                 $user_unicode=$this->ASCIIToUnicode($user);
  461.                 $user_length=strlen($user_unicode);
  462.                 $user_offset=$domain_offset+$domain_length;
  463.                 $workstation_unicode=$this->ASCIIToUnicode($workstation);
  464.                 $workstation_length=strlen($workstation_unicode);
  465.                 $workstation_offset=$user_offset+$user_length;
  466.                 $lm="";
  467.                 $lm_length=strlen($lm);
  468.                 $lm_offset=$workstation_offset+$workstation_length;
  469.                 $ntlm=$ntlm_response;
  470.                 $ntlm_length=strlen($ntlm);
  471.                 $ntlm_offset=$lm_offset+$lm_length;
  472.                 $session="";
  473.                 $session_length=strlen($session);
  474.                 $session_offset=$ntlm_offset+$ntlm_length;
  475.                 return(
  476.                         "NTLMSSP\0".
  477.                         "\x03\x00\x00\x00".
  478.                         pack("v",$lm_length).
  479.                         pack("v",$lm_length).
  480.                         pack("V",$lm_offset).
  481.                         pack("v",$ntlm_length).
  482.                         pack("v",$ntlm_length).
  483.                         pack("V",$ntlm_offset).
  484.                         pack("v",$domain_length).
  485.                         pack("v",$domain_length).
  486.                         pack("V",$domain_offset).
  487.                         pack("v",$user_length).
  488.                         pack("v",$user_length).
  489.                         pack("V",$user_offset).
  490.                         pack("v",$workstation_length).
  491.                         pack("v",$workstation_length).
  492.                         pack("V",$workstation_offset).
  493.                         pack("v",$session_length).
  494.                         pack("v",$session_length).
  495.                         pack("V",$session_offset).
  496.                         "\x01\x02\x00\x00".
  497.                         $domain_unicode.
  498.                         $user_unicode.
  499.                         $workstation_unicode.
  500.                         $lm.
  501.                         $ntlm
  502.                 );
  503.         }
  504.  
  505.         Function Start(&$client, &$message, &$interactions)
  506.         {
  507.                 if($this->state!=SASL_NTLM_STATE_START)
  508.                 {
  509.                         $client->error="NTLM authentication state is not at the start";
  510.                         return(SASL_FAIL);
  511.                 }
  512.                 $this->credentials=array(
  513.                         "user"=>"",
  514.                         "password"=>"",
  515.                         "realm"=>"",
  516.                         "workstation"=>""
  517.                 );
  518.                 $defaults=array();
  519.                 $status=$client->GetCredentials($this->credentials,$defaults,$interactions);
  520.                 if($status==SASL_CONTINUE)
  521.                         $this->state=SASL_NTLM_STATE_IDENTIFY_DOMAIN;
  522.                 Unset($message);
  523.                 return($status);
  524.         }
  525.  
  526.         Function Step(&$client, $response, &$message, &$interactions)
  527.         {
  528.                 switch($this->state)
  529.                 {
  530.                         case SASL_NTLM_STATE_IDENTIFY_DOMAIN:
  531.                                 $message=$this->TypeMsg1($this->credentials["realm"],$this->credentials["workstation"]);
  532.                                 $this->state=SASL_NTLM_STATE_RESPOND_CHALLENGE;
  533.                                 break;
  534.                         case SASL_NTLM_STATE_RESPOND_CHALLENGE:
  535.                                 $ntlm_response=$this->NTLMResponse(substr($response,24,8),$this->credentials["password"]);
  536.                                 $message=$this->TypeMsg3($ntlm_response,$this->credentials["user"],$this->credentials["realm"],$this->credentials["workstation"]);
  537.                                 $this->state=SASL_NTLM_STATE_DONE;
  538.                                 break;
  539.                         case SASL_NTLM_STATE_DONE:
  540.                                 $client->error="NTLM authentication was finished without success";
  541.                                 return(SASL_FAIL);
  542.                         default:
  543.                                 $client->error="invalid NTLM authentication step state";
  544.                                 return(SASL_FAIL);
  545.                 }
  546.                 return(SASL_CONTINUE);
  547.         }
  548. };
  549.  
  550. // =============================================================================
  551.  
  552. /*
  553.  * plain_sasl_client.php
  554.  *
  555.  * @(#) $Id: plain_sasl_client.php,v 1.2 2004/11/17 08:00:37 mlemos Exp $
  556.  *
  557.  */
  558.  
  559. define("SASL_PLAIN_STATE_START",    0);
  560. define("SASL_PLAIN_STATE_IDENTIFY", 1);
  561. define("SASL_PLAIN_STATE_DONE",     2);
  562.  
  563. define("SASL_PLAIN_DEFAULT_MODE",            0);
  564. define("SASL_PLAIN_EXIM_MODE",               1);
  565. define("SASL_PLAIN_EXIM_DOCUMENTATION_MODE", 2);
  566.  
  567. class plain_sasl_client_class
  568. {
  569.         var $credentials=array();
  570.         var $state=SASL_PLAIN_STATE_START;
  571.  
  572.         Function Initialize(&$client)
  573.         {
  574.                 return(1);
  575.         }
  576.  
  577.         Function Start(&$client, &$message, &$interactions)
  578.         {
  579.                 if($this->state!=SASL_PLAIN_STATE_START)
  580.                 {
  581.                         $client->error="PLAIN authentication state is not at the start";
  582.                         return(SASL_FAIL);
  583.                 }
  584.                 $this->credentials=array(
  585.                         "user"=>"",
  586.                         "password"=>"",
  587.                         "realm"=>"",
  588.                         "mode"=>""
  589.                 );
  590.                 $defaults=array(
  591.                         "realm"=>"",
  592.                         "mode"=>""
  593.                 );
  594.                 $status=$client->GetCredentials($this->credentials,$defaults,$interactions);
  595.                 if($status==SASL_CONTINUE)
  596.                 {
  597.                         switch($this->credentials["mode"])
  598.                         {
  599.                                 case SASL_PLAIN_EXIM_MODE:
  600.                                         $message=$this->credentials["user"]."\0".$this->credentials["password"]."\0";
  601.                                         break;
  602.                                 case SASL_PLAIN_EXIM_DOCUMENTATION_MODE:
  603.                                         $message="\0".$this->credentials["user"]."\0".$this->credentials["password"];
  604.                                         break;
  605.                                 default:
  606.                                         $message=$this->credentials["user"]."\0".$this->credentials["user"].(strlen($this->credentials["realm"]) ? "@".$this->credentials["realm"] : "")."\0".$this->credentials["password"];
  607.                                         break;
  608.                         }
  609.                         $this->state=SASL_PLAIN_STATE_DONE;
  610.                 }
  611.                 else
  612.                         Unset($message);
  613.                 return($status);
  614.         }
  615.  
  616.         Function Step(&$client, $response, &$message, &$interactions)
  617.         {
  618.                 switch($this->state)
  619.                 {
  620. /*
  621.                         case SASL_PLAIN_STATE_IDENTIFY:
  622.                                 switch($this->credentials["mode"])
  623.                                 {
  624.                                         case SASL_PLAIN_EXIM_MODE:
  625.                                                 $message=$this->credentials["user"]."\0".$this->credentials["password"]."\0";
  626.                                                 break;
  627.                                         case SASL_PLAIN_EXIM_DOCUMENTATION_MODE:
  628.                                                 $message="\0".$this->credentials["user"]."\0".$this->credentials["password"];
  629.                                                 break;
  630.                                         default:
  631.                                                 $message=$this->credentials["user"]."\0".$this->credentials["user"].(strlen($this->credentials["realm"]) ? "@".$this->credentials["realm"] : "")."\0".$this->credentials["password"];
  632.                                                 break;
  633.                                 }
  634.                                 var_dump($message);
  635.                                 $this->state=SASL_PLAIN_STATE_DONE;
  636.                                 break;
  637. */
  638.                         case SASL_PLAIN_STATE_DONE:
  639.                                 $client->error="PLAIN authentication was finished without success";
  640.                                 return(SASL_FAIL);
  641.                         default:
  642.                                 $client->error="invalid PLAIN authentication step state";
  643.                                 return(SASL_FAIL);
  644.                 }
  645.                 return(SASL_CONTINUE);
  646.         }
  647. };
  648.  
  649. // =============================================================================
  650.  
  651. /*
  652.  * sasl.php
  653.  *
  654.  * @(#) $Id: sasl.php,v 1.11 2005/10/31 18:43:27 mlemos Exp $
  655.  *
  656.  */
  657.  
  658. define("SASL_INTERACT", 2);
  659. define("SASL_CONTINUE", 1);
  660. define("SASL_OK",       0);
  661. define("SASL_FAIL",    -1);
  662. define("SASL_NOMECH",  -4);
  663.  
  664. class sasl_interact_class
  665. {
  666.     var $id;
  667.     var $challenge;
  668.     var $prompt;
  669.     var $default_result;
  670.     var $result;
  671. };
  672.  
  673. class sasl_client_class
  674. {
  675.     /* Public variables */
  676.  
  677.     var $error='';
  678.  
  679.     var $mechanism='';
  680.  
  681.     var $encode_response=1;
  682.  
  683.     /* Private variables */
  684.  
  685.     var $driver;
  686.     var $drivers=array(
  687.         "Digest"   => array("digest_sasl_client_class"/*,   "digest_sasl_client.php"   */),
  688.         "CRAM-MD5" => array("cram_md5_sasl_client_class"/*, "cram_md5_sasl_client.php" */),
  689.         "LOGIN"    => array("login_sasl_client_class"/*,    "login_sasl_client.php"    */),
  690.         "NTLM"     => array("ntlm_sasl_client_class"/*,     "ntlm_sasl_client.php"     */),
  691.         "PLAIN"    => array("plain_sasl_client_class"/*,    "plain_sasl_client.php"    */),
  692.         "Basic"    => array("basic_sasl_client_class"/*,    "basic_sasl_client.php"    */)
  693.     );
  694.     var $credentials=array();
  695.  
  696.     /* Public functions */
  697.  
  698.     Function SetCredential($key,$value)
  699.     {
  700.         $this->credentials[$key]=$value;
  701.     }
  702.  
  703.     Function GetCredentials(&$credentials,$defaults,&$interactions)
  704.     {
  705.         Reset($credentials);
  706.         $end=(GetType($key=Key($credentials))!="string");
  707.         for(;!$end;)
  708.         {
  709.             if(!IsSet($this->credentials[$key]))
  710.             {
  711.                 if(IsSet($defaults[$key]))
  712.                     $credentials[$key]=$defaults[$key];
  713.                     else
  714.                     {
  715.                         $this->error="the requested credential ".$key." is not defined";
  716.                         return(SASL_NOMECH);
  717.                     }
  718.             }
  719.             else
  720.                 $credentials[$key]=$this->credentials[$key];
  721.                 Next($credentials);
  722.                 $end=(GetType($key=Key($credentials))!="string");
  723.         }
  724.         return(SASL_CONTINUE);
  725.     }
  726.  
  727.     Function Start($mechanisms, &$message, &$interactions)
  728.     {
  729.         if(strlen($this->error))
  730.             return(SASL_FAIL);
  731.         if(IsSet($this->driver))
  732.             return($this->driver->Start($this,$message,$interactions));
  733.         $no_mechanism_error="";
  734.         for($m=0;$m<count($mechanisms);$m++)
  735.         {
  736.             $mechanism=$mechanisms[$m];
  737.             if(IsSet($this->drivers[$mechanism]))
  738.             {
  739.                 /*
  740.                  * if(!class_exists($this->drivers[$mechanism][0]))
  741.                  *      require(dirname(__FILE__)."/".$this->drivers[$mechanism][1]);
  742.                  */
  743.                 $this->driver=new $this->drivers[$mechanism][0];
  744.                 if($this->driver->Initialize($this))
  745.                 {
  746.                     $this->encode_response=1;
  747.                     $status=$this->driver->Start($this,$message,$interactions);
  748.                     switch($status)
  749.                     {
  750.                         case SASL_NOMECH:
  751.                             Unset($this->driver);
  752.                             if(strlen($no_mechanism_error)==0)
  753.                                 $no_mechanism_error=$this->error;
  754.                                 $this->error="";
  755.                                 break;
  756.                         case SASL_CONTINUE:
  757.                             $this->mechanism=$mechanism;
  758.                             return($status);
  759.                         default:
  760.                             Unset($this->driver);
  761.                             $this->error="";
  762.                             return($status);
  763.                     }
  764.                 }
  765.                 else
  766.                 {
  767.                     Unset($this->driver);
  768.                     if(strlen($no_mechanism_error)==0)
  769.                         $no_mechanism_error=$this->error;
  770.                         $this->error="";
  771.                 }
  772.             }
  773.         }
  774.         $this->error=(strlen($no_mechanism_error) ? $no_mechanism_error : "it was not requested any of the authentication mechanisms that are supported");
  775.         return(SASL_NOMECH);
  776.     }
  777.  
  778.     Function Step($response, &$message, &$interactions)
  779.     {
  780.         if(strlen($this->error))
  781.             return(SASL_FAIL);
  782.             return($this->driver->Step($this,$response,$message,$interactions));
  783.     }
  784.  
  785. };
  786.  
  787. // =============================================================================
  788.  
  789.  
  790. /*
  791.  * http.php
  792.  *
  793.  * @(#) $Header: /opt2/ena/metal/http/http.php,v 1.94 2016/05/03 02:07:04 mlemos Exp $
  794.  *
  795.  */
  796.  
  797. class http_class {
  798.  
  799.         /*public*/ const HTTP_CLIENT_ERROR_UNSPECIFIED_ERROR =       -1;
  800.         /*public*/ const HTTP_CLIENT_ERROR_NO_ERROR =                 0;
  801.         /*public*/ const HTTP_CLIENT_ERROR_INVALID_SERVER_ADDRESS =   1;
  802.         /*public*/ const HTTP_CLIENT_ERROR_CANNOT_CONNECT =           2;
  803.         /*public*/ const HTTP_CLIENT_ERROR_COMMUNICATION_FAILURE =    3;
  804.         /*public*/ const HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE = 4;
  805.         /*public*/ const HTTP_CLIENT_ERROR_PROTOCOL_FAILURE =         5;
  806.         /*public*/ const HTTP_CLIENT_ERROR_INVALID_PARAMETERS =       6;
  807.  
  808.         public $host_name="";
  809.         public $host_port=0;
  810.         public $proxy_host_name="";
  811.         public $proxy_host_port=80;
  812.         public $socks_host_name = '';
  813.         public $socks_host_port = 1080;
  814.         public $socks_version = '5';
  815.  
  816.         public $protocol="http";
  817.         public $request_method="GET";
  818.         public $user_agent='httpclient (http://www.phpclasses.org/httpclient $Revision: 1.94 $)';
  819.         public $accept='';
  820.         public $authentication_mechanism="";
  821.         public $user;
  822.         public $password;
  823.         public $realm;
  824.         public $workstation;
  825.         public $proxy_authentication_mechanism="";
  826.         public $proxy_user;
  827.         public $proxy_password;
  828.         public $proxy_realm;
  829.         public $proxy_workstation;
  830.         public $request_uri="";
  831.         public $request="";
  832.         public $request_headers=array();
  833.         public $request_user;
  834.         public $request_password;
  835.         public $request_realm;
  836.         public $request_workstation;
  837.         public $proxy_request_user;
  838.         public $proxy_request_password;
  839.         public $proxy_request_realm;
  840.         public $proxy_request_workstation;
  841.         public $request_body="";
  842.         public $request_arguments=array();
  843.         public $protocol_version="1.1";
  844.         public $timeout=0;
  845.         public $data_timeout=0;
  846.         public $debug=0;
  847.         public $log_debug=0;
  848.         public $debug_response_body=1;
  849.         public $html_debug=0;
  850.         public $support_cookies=1;
  851.         public $cookies=array();
  852.         public $error="";
  853.         public $error_code = self::HTTP_CLIENT_ERROR_NO_ERROR;
  854.         public $exclude_address="";
  855.         public $follow_redirect=0;
  856.         public $redirection_limit=5;
  857.         public $response_status="";
  858.         public $response_message="";
  859.         public $file_buffer_length=8000;
  860.         public $force_multipart_form_post=0;
  861.         public $prefer_curl = 0;
  862.         public $keep_alive = 1;
  863.         public $sasl_authenticate = 1;
  864.  
  865.         /* private variables - DO NOT ACCESS */
  866.  
  867.         public $state="Disconnected";
  868.         public $use_curl=0;
  869.         public $connection=0;
  870.         public $content_length=0;
  871.         public $response="";
  872.         public $read_response=0;
  873.         public $read_length=0;
  874.         public $request_host="";
  875.         public $next_token="";
  876.         public $redirection_level=0;
  877.         public $chunked=0;
  878.         public $remaining_chunk=0;
  879.         public $last_chunk_read=0;
  880.         public $months=array(
  881.                 "Jan"=>"01",
  882.                 "Feb"=>"02",
  883.                 "Mar"=>"03",
  884.                 "Apr"=>"04",
  885.                 "May"=>"05",
  886.                 "Jun"=>"06",
  887.                 "Jul"=>"07",
  888.                 "Aug"=>"08",
  889.                 "Sep"=>"09",
  890.                 "Oct"=>"10",
  891.                 "Nov"=>"11",
  892.                 "Dec"=>"12");
  893.         public $session='';
  894.         public $connection_close=0;
  895.         public $force_close = 0;
  896.         public $connected_host = '';
  897.         public $connected_port = -1;
  898.         public $connected_ssl = 0;
  899.  
  900.         /* Private methods - DO NOT CALL */
  901.  
  902.         Function Tokenize($string,$separator="")
  903.         {
  904.                 if(!strcmp($separator,""))
  905.                 {
  906.                         $separator=$string;
  907.                         $string=$this->next_token;
  908.                 }
  909.                 for($character=0;$character<strlen($separator);$character++)
  910.                 {
  911.                         $found = null;
  912.                         if(GetType($position=strpos($string,$separator[$character]))=="integer")
  913.                                 $found=(!is_null($found) ? min($found,$position) : $position);
  914.                 }
  915.                 if(IsSet($found))
  916.                 {
  917.                         $this->next_token=substr($string,$found+1);
  918.                         return(substr($string,0,$found));
  919.                 }
  920.                 else
  921.                 {
  922.                         $this->next_token="";
  923.                         return($string);
  924.                 }
  925.         }
  926.  
  927.         Function CookieEncode($value, $name)
  928.         {
  929.                 return($name ? str_replace("=", "%25", $value) : str_replace(";", "%3B", $value));
  930.         }
  931.  
  932.         Function SetError($error, $error_code = self::HTTP_CLIENT_ERROR_UNSPECIFIED_ERROR)
  933.         {
  934.                 $this->error_code = $error_code;
  935.                 return($this->error=$error);
  936.         }
  937.  
  938.         Function SetPHPError($error, &$php_error_message, $error_code = self::HTTP_CLIENT_ERROR_UNSPECIFIED_ERROR)
  939.         {
  940.                 if(IsSet($php_error_message)
  941.                 && strlen($php_error_message))
  942.                         $error.=": ".$php_error_message;
  943.                 return($this->SetError($error, $error_code));
  944.         }
  945.  
  946.         Function SetDataAccessError($error,$check_connection=0)
  947.         {
  948.                 $this->error=$error;
  949.                 $this->error_code = self::HTTP_CLIENT_ERROR_COMMUNICATION_FAILURE;
  950.                 if(!$this->use_curl
  951.                 && function_exists("socket_get_status"))
  952.                 {
  953.                         $status=socket_get_status($this->connection);
  954.                         if($status["timed_out"])
  955.                                 $this->error.=": data access time out";
  956.                         elseif($status["eof"])
  957.                         {
  958.                                 if($check_connection)
  959.                                         $this->error="";
  960.                                 else
  961.                                         $this->error.=": the server disconnected";
  962.                         }
  963.                 }
  964.         }
  965.  
  966.         Function OutputDebug($message)
  967.         {
  968.                 if($this->log_debug)
  969.                 {
  970.                         if(strlen($this->log_file_name))
  971.                                 error_log($message."\n", 3, $this->log_file_name);
  972.                         else
  973.                                 error_log($message);
  974.                 }
  975.                 else
  976.                 {
  977.                         $message.="\n";
  978.                         if($this->html_debug)
  979.                                 $message=str_replace("\n","<br />\n",HtmlEntities($message));
  980.                         echo $message;
  981.                         flush();
  982.                 }
  983.         }
  984.  
  985.         Function GetLine()
  986.         {
  987.                 for($line="";;)
  988.                 {
  989.                         if($this->use_curl)
  990.                         {
  991.                                 $eol=strpos($this->response,"\n",$this->read_response);
  992.                                 $data=($eol ? substr($this->response,$this->read_response,$eol+1-$this->read_response) : "");
  993.                                 $this->read_response+=strlen($data);
  994.                         }
  995.                         else
  996.                         {
  997.                                 if(feof($this->connection))
  998.                                 {
  999.                                         $this->SetDataAccessError("reached the end of data while reading from the HTTP server connection");
  1000.                                         return(0);
  1001.                                 }
  1002.                                 $data=fgets($this->connection,100);
  1003.                         }
  1004.                         if(GetType($data)!="string"
  1005.                         || strlen($data)==0)
  1006.                         {
  1007.                                 $this->SetDataAccessError("it was not possible to read line from the HTTP server");
  1008.                                 return(0);
  1009.                         }
  1010.                         $line.=$data;
  1011.                         $length=strlen($line);
  1012.                         if($length
  1013.                         && !strcmp(substr($line,$length-1,1),"\n"))
  1014.                         {
  1015.                                 $length-=(($length>=2 && !strcmp(substr($line,$length-2,1),"\r")) ? 2 : 1);
  1016.                                 $line=substr($line,0,$length);
  1017.                                 if($this->debug)
  1018.                                         $this->OutputDebug("S $line");
  1019.                                 return($line);
  1020.                         }
  1021.                 }
  1022.         }
  1023.  
  1024.         Function PutLine($line)
  1025.         {
  1026.                 if($this->debug)
  1027.                         $this->OutputDebug("C $line");
  1028.                 if(!fputs($this->connection,$line."\r\n"))
  1029.                 {
  1030.                         $this->SetDataAccessError("it was not possible to send a line to the HTTP server");
  1031.                         return(0);
  1032.                 }
  1033.                 return(1);
  1034.         }
  1035.  
  1036.         Function PutData($data)
  1037.         {
  1038.                 if(strlen($data))
  1039.                 {
  1040.                         if($this->debug)
  1041.                                 $this->OutputDebug('C '.$data);
  1042.                         if(!fputs($this->connection,$data))
  1043.                         {
  1044.                                 $this->SetDataAccessError("it was not possible to send data to the HTTP server");
  1045.                                 return(0);
  1046.                         }
  1047.                 }
  1048.                 return(1);
  1049.         }
  1050.  
  1051.         Function FlushData()
  1052.         {
  1053.                 if(!fflush($this->connection))
  1054.                 {
  1055.                         $this->SetDataAccessError("it was not possible to send data to the HTTP server");
  1056.                         return(0);
  1057.                 }
  1058.                 return(1);
  1059.         }
  1060.  
  1061.         Function ReadChunkSize()
  1062.         {
  1063.                 if($this->remaining_chunk==0)
  1064.                 {
  1065.                         $debug=$this->debug;
  1066.                         if(!$this->debug_response_body)
  1067.                                 $this->debug=0;
  1068.                         $line=$this->GetLine();
  1069.                         $this->debug=$debug;
  1070.                         if(GetType($line)!="string")
  1071.                                 return($this->SetError("could not read chunk start: ".$this->error, $this->error_code));
  1072.                         $this->remaining_chunk=hexdec($line);
  1073.                         if($this->remaining_chunk == 0)
  1074.                         {
  1075.                                 if(!$this->debug_response_body)
  1076.                                         $this->debug=0;
  1077.                                 $line=$this->GetLine();
  1078.                                 $this->debug=$debug;
  1079.                                 if(GetType($line)!="string")
  1080.                                         return($this->SetError("could not read chunk end: ".$this->error, $this->error_code));
  1081.                         }
  1082.                 }
  1083.                 return("");
  1084.         }
  1085.  
  1086.         Function ReadBytes($length)
  1087.         {
  1088.                 if($this->use_curl)
  1089.                 {
  1090.                         $bytes=substr($this->response,$this->read_response,min($length,strlen($this->response)-$this->read_response));
  1091.                         $this->read_response+=strlen($bytes);
  1092.                         if($this->debug
  1093.                         && $this->debug_response_body
  1094.                         && strlen($bytes))
  1095.                                 $this->OutputDebug("S ".$bytes);
  1096.                 }
  1097.                 else
  1098.                 {
  1099.                         if($this->chunked)
  1100.                         {
  1101.                                 for($bytes="",$remaining=$length;$remaining;)
  1102.                                 {
  1103.                                         if(strlen($this->ReadChunkSize()))
  1104.                                                 return("");
  1105.                                         if($this->remaining_chunk==0)
  1106.                                         {
  1107.                                                 $this->last_chunk_read=1;
  1108.                                                 break;
  1109.                                         }
  1110.                                         $ask=min($this->remaining_chunk,$remaining);
  1111.                                         $chunk=@fread($this->connection,$ask);
  1112.                                         $read=strlen($chunk);
  1113.                                         if($read==0)
  1114.                                         {
  1115.                                                 $this->SetDataAccessError("it was not possible to read data chunk from the HTTP server");
  1116.                                                 return("");
  1117.                                         }
  1118.                                         if($this->debug
  1119.                                         && $this->debug_response_body)
  1120.                                                 $this->OutputDebug("S ".$chunk);
  1121.                                         $bytes.=$chunk;
  1122.                                         $this->remaining_chunk-=$read;
  1123.                                         $remaining-=$read;
  1124.                                         if($this->remaining_chunk==0)
  1125.                                         {
  1126.                                                 if(feof($this->connection))
  1127.                                                         return($this->SetError("reached the end of data while reading the end of data chunk mark from the HTTP server", self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE));
  1128.                                                 $data=@fread($this->connection,2);
  1129.                                                 if(strcmp($data,"\r\n"))
  1130.                                                 {
  1131.                                                         $this->SetDataAccessError("it was not possible to read end of data chunk from the HTTP server");
  1132.                                                         return("");
  1133.                                                 }
  1134.                                         }
  1135.                                 }
  1136.                         }
  1137.                         else
  1138.                         {
  1139.                                 $bytes=@fread($this->connection,$length);
  1140.                                 if(strlen($bytes))
  1141.                                 {
  1142.                                         if($this->debug
  1143.                                         && $this->debug_response_body)
  1144.                                                 $this->OutputDebug("S ".$bytes);
  1145.                                 }
  1146.                                 else
  1147.                                         $this->SetDataAccessError("it was not possible to read data from the HTTP server", $this->connection_close);
  1148.                         }
  1149.                 }
  1150.                 return($bytes);
  1151.         }
  1152.  
  1153.         Function EndOfInput()
  1154.         {
  1155.                 if($this->use_curl)
  1156.                         return($this->read_response>=strlen($this->response));
  1157.                 if($this->chunked)
  1158.                         return($this->last_chunk_read);
  1159.                 if($this->content_length_set)
  1160.                         return($this->content_length <= $this->read_length);
  1161.                 return(feof($this->connection));
  1162.         }
  1163.  
  1164.         Function Resolve($domain, &$ip, $server_type)
  1165.         {
  1166.                 if(preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/',$domain))
  1167.                         $ip=$domain;
  1168.                 else
  1169.                 {
  1170.                         if($this->debug)
  1171.                                 $this->OutputDebug('Resolving '.$server_type.' server domain "'.$domain.'"...');
  1172.                         if(!strcmp($ip=@gethostbyname($domain),$domain))
  1173.                                 $ip="";
  1174.                 }
  1175.                 if(strlen($ip)==0
  1176.                 || (strlen($this->exclude_address)
  1177.                 && !strcmp(@gethostbyname($this->exclude_address),$ip)))
  1178.                         return($this->SetError("could not resolve the host domain \"".$domain."\"", self::HTTP_CLIENT_ERROR_INVALID_SERVER_ADDRESS));
  1179.                 return('');
  1180.         }
  1181.  
  1182.         Function Connect($host_name, $host_port, $ssl, $server_type = 'HTTP')
  1183.         {
  1184.                 $domain=$host_name;
  1185.                 $port = $host_port;
  1186.                 $ip = '';
  1187.                 if(strlen($error = $this->Resolve($domain, $ip, $server_type)))
  1188.                         return($error);
  1189.                 if(strlen($this->socks_host_name))
  1190.                 {
  1191.                         switch($this->socks_version)
  1192.                         {
  1193.                                 case '4':
  1194.                                         $version = 4;
  1195.                                         break;
  1196.                                 case '5':
  1197.                                         $version = 5;
  1198.                                         break;
  1199.                                 default:
  1200.                                         return('it was not specified a supported SOCKS protocol version');
  1201.                                         break;
  1202.                         }
  1203.                         $host_ip = $ip;
  1204.                         $port = $this->socks_host_port;
  1205.                         $host_server_type = $server_type;
  1206.                         $server_type = 'SOCKS';
  1207.                         if(strlen($error = $this->Resolve($this->socks_host_name, $ip, $server_type)))
  1208.                                 return($error);
  1209.                 }
  1210.                 if($this->debug)
  1211.                         $this->OutputDebug('Connecting to '.$server_type.' server IP '.$ip.' port '.$port.'...');
  1212.                 if($ssl)
  1213.                         $ip="ssl://".$host_name;
  1214.                 $errno = -1;
  1215.                 if(($this->connection=($this->timeout ? @fsockopen($ip, $port, $errno, $error, $this->timeout) : @fsockopen($ip, $port, $errno)))==0)
  1216.                 {
  1217.                         $error_code = self::HTTP_CLIENT_ERROR_CANNOT_CONNECT;
  1218.                         switch($errno)
  1219.                         {
  1220.                                 case -3:
  1221.                                         return($this->SetError("socket could not be created", $error_code));
  1222.                                 case -4:
  1223.                                         return($this->SetError("dns lookup on hostname \"".$host_name."\" failed", $error_code));
  1224.                                 case -5:
  1225.                                         return($this->SetError("connection refused or timed out", $error_code));
  1226.                                 case -6:
  1227.                                         return($this->SetError("fdopen() call failed", $error_code));
  1228.                                 case -7:
  1229.                                         return($this->SetError("setvbuf() call failed", $error_code));
  1230.                                 default:
  1231.                                         $php_errormsg = '';
  1232.                                         return($this->SetPHPError($errno." could not connect to the host \"".$host_name."\"",$php_errormsg, $error_code));
  1233.                         }
  1234.                 }
  1235.                 else
  1236.                 {
  1237.                         if($this->data_timeout
  1238.                         && function_exists("socket_set_timeout"))
  1239.                                 socket_set_timeout($this->connection,$this->data_timeout,0);
  1240.                         if(strlen($this->socks_host_name))
  1241.                         {
  1242.                                 if($this->debug)
  1243.                                         $this->OutputDebug('Connected to the SOCKS server '.$this->socks_host_name);
  1244.                                 $send_error = 'it was not possible to send data to the SOCKS server';
  1245.                                 $receive_error = 'it was not possible to receive data from the SOCKS server';
  1246.                                 switch($version)
  1247.                                 {
  1248.                                         case 4:
  1249.                                                 $command = 1;
  1250.                                                 $user = '';
  1251.                                                 if(!fputs($this->connection, chr($version).chr($command).pack('nN', $host_port, ip2long($host_ip)).$user.Chr(0)))
  1252.                                                         $error = $this->SetDataAccessError($send_error);
  1253.                                                 else
  1254.                                                 {
  1255.                                                         $response = fgets($this->connection, 9);
  1256.                                                         if(strlen($response) != 8)
  1257.                                                                 $error = $this->SetDataAccessError($receive_error);
  1258.                                                         else
  1259.                                                         {
  1260.                                                                 $socks_errors = array(
  1261.                                                                         "\x5a"=>'',
  1262.                                                                         "\x5b"=>'request rejected',
  1263.                                                                         "\x5c"=>'request failed because client is not running identd (or not reachable from the server)',
  1264.                                                                         "\x5d"=>'request failed because client\'s identd could not confirm the user ID string in the request',
  1265.                                                                 );
  1266.                                                                 $error_code = $response[1];
  1267.                                                                 $error = (IsSet($socks_errors[$error_code]) ? $socks_errors[$error_code] : 'unknown');
  1268.                                                                 if(strlen($error))
  1269.                                                                         $error = 'SOCKS error: '.$error;
  1270.                                                         }
  1271.                                                 }
  1272.                                                 break;
  1273.                                         case 5:
  1274.                                                 if($this->debug)
  1275.                                                         $this->OutputDebug('Negotiating the authentication method ...');
  1276.                                                 $methods = 1;
  1277.                                                 $method = 0;
  1278.                                                 if(!fputs($this->connection, chr($version).chr($methods).chr($method)))
  1279.                                                         $error = $this->SetDataAccessError($send_error);
  1280.                                                 else
  1281.                                                 {
  1282.                                                         $response = fgets($this->connection, 3);
  1283.                                                         if(strlen($response) != 2)
  1284.                                                                 $error = $this->SetDataAccessError($receive_error);
  1285.                                                         elseif(Ord($response[1]) != $method)
  1286.                                                                 $error = 'the SOCKS server requires an authentication method that is not yet supported';
  1287.                                                         else
  1288.                                                         {
  1289.                                                                 if($this->debug)
  1290.                                                                         $this->OutputDebug('Connecting to '.$host_server_type.' server IP '.$host_ip.' port '.$host_port.'...');
  1291.                                                                 $command = 1;
  1292.                                                                 $address_type = 1;
  1293.                                                                 if(!fputs($this->connection, chr($version).chr($command)."\x00".chr($address_type).pack('Nn', ip2long($host_ip), $host_port)))
  1294.                                                                         $error = $this->SetDataAccessError($send_error);
  1295.                                                                 else
  1296.                                                                 {
  1297.                                                                         $response = fgets($this->connection, 11);
  1298.                                                                         if(strlen($response) != 10)
  1299.                                                                                 $error = $this->SetDataAccessError($receive_error);
  1300.                                                                         else
  1301.                                                                         {
  1302.                                                                                 $socks_errors = array(
  1303.                                                                                         "\x00"=>'',
  1304.                                                                                         "\x01"=>'general SOCKS server failure',
  1305.                                                                                         "\x02"=>'connection not allowed by ruleset',
  1306.                                                                                         "\x03"=>'Network unreachable',
  1307.                                                                                         "\x04"=>'Host unreachable',
  1308.                                                                                         "\x05"=>'Connection refused',
  1309.                                                                                         "\x06"=>'TTL expired',
  1310.                                                                                         "\x07"=>'Command not supported',
  1311.                                                                                         "\x08"=>'Address type not supported'
  1312.                                                                                 );
  1313.                                                                                 $error_code = $response[1];
  1314.                                                                                 $error = (IsSet($socks_errors[$error_code]) ? $socks_errors[$error_code] : 'unknown');
  1315.                                                                                 if(strlen($error))
  1316.                                                                                         $error = 'SOCKS error: '.$error;
  1317.                                                                         }
  1318.                                                                 }
  1319.                                                         }
  1320.                                                 }
  1321.                                                 break;
  1322.                                         default:
  1323.                                                 $error = 'support for SOCKS protocol version '.$this->socks_version.' is not yet implemented';
  1324.                                                 break;
  1325.                                 }
  1326.                                 if(strlen($error))
  1327.                                 {
  1328.                                         fclose($this->connection);
  1329.                                         return($error);
  1330.                                 }
  1331.                         }
  1332.                         if($this->debug)
  1333.                                 $this->OutputDebug("Connected to $host_name");
  1334.                         if(strlen($this->proxy_host_name)
  1335.                         && !strcmp(strtolower($this->protocol), 'https'))
  1336.                         {
  1337.                                 if(function_exists('stream_socket_enable_crypto')
  1338.                                 && in_array('ssl', stream_get_transports()))
  1339.                                         $this->state = "ConnectedToProxy";
  1340.                                 else
  1341.                                 {
  1342.                                         $this->OutputDebug("It is not possible to start SSL after connecting to the proxy server. If the proxy refuses to forward the SSL request, you may need to upgrade to PHP 5.1 or later with OpenSSL support enabled.");
  1343.                                         $this->state="Connected";
  1344.                                 }
  1345.                         }
  1346.                         else
  1347.                                 $this->state="Connected";
  1348.                         return("");
  1349.                 }
  1350.         }
  1351.  
  1352.         Function Disconnect()
  1353.         {
  1354.                 if($this->debug)
  1355.                         $this->OutputDebug("Disconnected from ".$this->connected_host);
  1356.                 if($this->use_curl)
  1357.                 {
  1358.                         curl_close($this->connection);
  1359.                         $this->response="";
  1360.                 }
  1361.                 else
  1362.                         fclose($this->connection);
  1363.                 $this->state="Disconnected";
  1364.                 return("");
  1365.         }
  1366.  
  1367.         /* Public methods */
  1368.  
  1369.         Function GetRequestArguments($url, &$arguments)
  1370.         {
  1371.                 $this->error = '';
  1372.                 $this->error_code = self::HTTP_CLIENT_ERROR_NO_ERROR;
  1373.                 $arguments=array();
  1374.                 $url = str_replace(' ', '%20', $url);
  1375.                 $parameters=@parse_url($url);
  1376.                 if(!$parameters)
  1377.                         return($this->SetError("it was not specified a valid URL", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1378.                 if(!IsSet($parameters["scheme"]))
  1379.                         return($this->SetError("it was not specified the protocol type argument", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1380.                 switch(strtolower($parameters["scheme"]))
  1381.                 {
  1382.                         case "http":
  1383.                         case "https":
  1384.                                 $arguments["Protocol"]=$parameters["scheme"];
  1385.                                 break;
  1386.                         default:
  1387.                                 return($parameters["scheme"]." connection scheme is not yet supported");
  1388.                 }
  1389.                 if(!IsSet($parameters["host"]))
  1390.                         return($this->SetError("it was not specified the connection host argument", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1391.                 $arguments["HostName"]=$parameters["host"];
  1392.                 $arguments["Headers"]=array("Host"=>$parameters["host"].(IsSet($parameters["port"]) ? ":".$parameters["port"] : ""));
  1393.                 if(IsSet($parameters["user"]))
  1394.                 {
  1395.                         $arguments["AuthUser"]=UrlDecode($parameters["user"]);
  1396.                         if(!IsSet($parameters["pass"]))
  1397.                                 $arguments["AuthPassword"]="";
  1398.                 }
  1399.                 if(IsSet($parameters["pass"]))
  1400.                 {
  1401.                         if(!IsSet($parameters["user"]))
  1402.                                 $arguments["AuthUser"]="";
  1403.                         $arguments["AuthPassword"]=UrlDecode($parameters["pass"]);
  1404.                 }
  1405.                 if(IsSet($parameters["port"]))
  1406.                 {
  1407.                         if(strcmp($parameters["port"],strval(intval($parameters["port"]))))
  1408.                                 return($this->SetError("it was not specified a valid connection host argument", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1409.                         $arguments["HostPort"]=intval($parameters["port"]);
  1410.                 }
  1411.                 else
  1412.                         $arguments["HostPort"]=0;
  1413.                 $arguments["RequestURI"]=(IsSet($parameters["path"]) ? $parameters["path"] : "/").(IsSet($parameters["query"]) ? "?".$parameters["query"] : "");
  1414.                 if(strlen($this->user_agent))
  1415.                         $arguments["Headers"]["User-Agent"]=$this->user_agent;
  1416.                 if(strlen($this->accept))
  1417.                         $arguments["Headers"]["Accept"]=$this->accept;
  1418.                 return("");
  1419.         }
  1420.  
  1421.         Function Open($arguments)
  1422.         {
  1423.                 if(strlen($this->error))
  1424.                         return($this->error);
  1425.                 $error_code = self::HTTP_CLIENT_ERROR_UNSPECIFIED_ERROR;
  1426.                 if(IsSet($arguments["HostName"]))
  1427.                         $this->host_name=$arguments["HostName"];
  1428.                 if(IsSet($arguments["HostPort"]))
  1429.                         $this->host_port=$arguments["HostPort"];
  1430.                 if(IsSet($arguments["ProxyHostName"]))
  1431.                         $this->proxy_host_name=$arguments["ProxyHostName"];
  1432.                 if(IsSet($arguments["ProxyHostPort"]))
  1433.                         $this->proxy_host_port=$arguments["ProxyHostPort"];
  1434.                 if(IsSet($arguments["SOCKSHostName"]))
  1435.                         $this->socks_host_name=$arguments["SOCKSHostName"];
  1436.                 if(IsSet($arguments["SOCKSHostPort"]))
  1437.                         $this->socks_host_port=$arguments["SOCKSHostPort"];
  1438.                 if(IsSet($arguments["SOCKSVersion"]))
  1439.                         $this->socks_version=$arguments["SOCKSVersion"];
  1440.                 if(IsSet($arguments["PreferCurl"]))
  1441.                         $this->prefer_curl=$arguments["PreferCurl"];
  1442.                 if(IsSet($arguments["Protocol"]))
  1443.                         $this->protocol=$arguments["Protocol"];
  1444.                 switch(strtolower($this->protocol))
  1445.                 {
  1446.                         case "http":
  1447.                                 $default_port=80;
  1448.                                 break;
  1449.                         case "https":
  1450.                                 $default_port=443;
  1451.                                 break;
  1452.                         default:
  1453.                                 return($this->SetError("it was not specified a valid connection protocol", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1454.                 }
  1455.                 if(strlen($this->proxy_host_name)==0)
  1456.                 {
  1457.                         if(strlen($this->host_name)==0)
  1458.                                 return($this->SetError("it was not specified a valid hostname", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1459.                         $host_name=$this->host_name;
  1460.                         $host_port=($this->host_port ? $this->host_port : $default_port);
  1461.                         $server_type = 'HTTP';
  1462.                 }
  1463.                 else
  1464.                 {
  1465.                         $host_name=$this->proxy_host_name;
  1466.                         $host_port=$this->proxy_host_port;
  1467.                         $server_type = 'HTTP proxy';
  1468.                 }
  1469.                 $ssl=(strtolower($this->protocol)=="https" && strlen($this->proxy_host_name)==0);
  1470.                 if($ssl
  1471.                 && strlen($this->socks_host_name))
  1472.                         return($this->SetError('establishing SSL connections via a SOCKS server is not yet supported', self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1473.                 $this->use_curl=($ssl && $this->prefer_curl && function_exists("curl_init"));
  1474.                 switch($this->state)
  1475.                 {
  1476.                         case 'Connected':
  1477.                                 if(!strcmp($host_name, $this->connected_host)
  1478.                                 && intval($host_port) == $this->connected_port
  1479.                                 && intval($ssl) == $this->connected_ssl)
  1480.                                 {
  1481.                                         if($this->debug)
  1482.                                                 $this->OutputDebug("Reusing connection to ".$this->connected_host);
  1483.                                         return('');
  1484.                                 }
  1485.                                 if(strlen($error = $this->Disconnect()))
  1486.                                         return($error);
  1487.                         case "Disconnected":
  1488.                                 break;
  1489.                         default:
  1490.                                 return("1 already connected");
  1491.                 }
  1492.                 if($this->debug)
  1493.                         $this->OutputDebug("Connecting to ".$this->host_name);
  1494.                 if($this->use_curl)
  1495.                 {
  1496.                         $error=(($this->connection=curl_init($this->protocol."://".$this->host_name.($host_port==$default_port ? "" : ":".strval($host_port))."/")) ? "" : "Could not initialize a CURL session");
  1497.                         if(strlen($error)==0)
  1498.                         {
  1499.                                 if(IsSet($arguments["SSLCertificateFile"]))
  1500.                                         curl_setopt($this->connection,CURLOPT_SSLCERT,$arguments["SSLCertificateFile"]);
  1501.                                 if(IsSet($arguments["SSLCertificatePassword"]))
  1502.                                         curl_setopt($this->connection,CURLOPT_SSLCERTPASSWD,$arguments["SSLCertificatePassword"]);
  1503.                                 if(IsSet($arguments["SSLKeyFile"]))
  1504.                                         curl_setopt($this->connection,CURLOPT_SSLKEY,$arguments["SSLKeyFile"]);
  1505.                                 if(IsSet($arguments["SSLKeyPassword"]))
  1506.                                         curl_setopt($this->connection,CURLOPT_SSLKEYPASSWD,$arguments["SSLKeyPassword"]);
  1507.                         }
  1508.                         $this->state="Connected";
  1509.                 }
  1510.                 else
  1511.                 {
  1512.                         $error="";
  1513.                         if(strlen($this->proxy_host_name)
  1514.                         && (IsSet($arguments["SSLCertificateFile"])
  1515.                         || IsSet($arguments["SSLCertificateFile"])))
  1516.                                 $error="establishing SSL connections using certificates or private keys via non-SSL proxies is not supported";
  1517.                         else
  1518.                         {
  1519.                                 if($ssl)
  1520.                                 {
  1521.                                         if(IsSet($arguments["SSLCertificateFile"]))
  1522.                                                 $error="establishing SSL connections using certificates is only supported when the cURL extension is enabled";
  1523.                                         elseif(IsSet($arguments["SSLKeyFile"]))
  1524.                                                 $error="establishing SSL connections using a private key is only supported when the cURL extension is enabled";
  1525.                                         else
  1526.                                         {
  1527.                                                 $version=explode(".",function_exists("phpversion") ? phpversion() : "3.0.7");
  1528.                                                 $php_version=intval($version[0])*1000000+intval($version[1])*1000+intval($version[2]);
  1529.                                                 if($php_version<4003000)
  1530.                                                         $error="establishing SSL connections requires at least PHP version 4.3.0 or having the cURL extension enabled";
  1531.                                                 elseif(!function_exists("extension_loaded")
  1532.                                                 || !extension_loaded("openssl"))
  1533.                                                         $error="establishing SSL connections requires the OpenSSL extension enabled";
  1534.                                         }
  1535.                                 }
  1536.                                 if(strlen($error)==0)
  1537.                                 {
  1538.                                         $error=$this->Connect($host_name, $host_port, $ssl, $server_type);
  1539.                                         $error_code = $this->error_code;
  1540.                                 }
  1541.                         }
  1542.                 }
  1543.                 if(strlen($error))
  1544.                         return($this->SetError($error, $error_code));
  1545.                 $this->session=md5(uniqid(""));
  1546.                 $this->connected_host = $host_name;
  1547.                 $this->connected_port = intval($host_port);
  1548.                 $this->connected_ssl = intval($ssl);
  1549.                 return("");
  1550.         }
  1551.  
  1552.         Function Close($force = 0)
  1553.         {
  1554.                 if($this->state=="Disconnected")
  1555.                         return("1 already disconnected");
  1556.                 if(!$this->force_close
  1557.                 && $this->keep_alive
  1558.                 && !$force
  1559.                 && $this->state == 'ResponseReceived')
  1560.                 {
  1561.                         if($this->debug)
  1562.                                 $this->OutputDebug('Keeping the connection alive to '.$this->connected_host);
  1563.                         $this->state = 'Connected';
  1564.                         return('');
  1565.                 }
  1566.                 return($this->Disconnect());
  1567.         }
  1568.  
  1569.         Function PickCookies(&$cookies,$secure)
  1570.         {
  1571.                 if(IsSet($this->cookies[$secure]))
  1572.                 {
  1573.                         $now=gmdate("Y-m-d H-i-s");
  1574.                         for($domain=0,Reset($this->cookies[$secure]);$domain<count($this->cookies[$secure]);Next($this->cookies[$secure]),$domain++)
  1575.                         {
  1576.                                 $domain_pattern=Key($this->cookies[$secure]);
  1577.                                 $match=strlen($this->request_host)-strlen($domain_pattern);
  1578.                                 if($match>=0
  1579.                                 && !strcmp($domain_pattern,substr($this->request_host,$match))
  1580.                                 && ($match==0
  1581.                                 || $domain_pattern[0]=="."
  1582.                                 || $this->request_host[$match-1]=="."))
  1583.                                 {
  1584.                                         for(Reset($this->cookies[$secure][$domain_pattern]),$path_part=0;$path_part<count($this->cookies[$secure][$domain_pattern]);Next($this->cookies[$secure][$domain_pattern]),$path_part++)
  1585.                                         {
  1586.                                                 $path=Key($this->cookies[$secure][$domain_pattern]);
  1587.                                                 if(strlen($this->request_uri)>=strlen($path)
  1588.                                                 && substr($this->request_uri,0,strlen($path))==$path)
  1589.                                                 {
  1590.                                                         for(Reset($this->cookies[$secure][$domain_pattern][$path]),$cookie=0;$cookie<count($this->cookies[$secure][$domain_pattern][$path]);Next($this->cookies[$secure][$domain_pattern][$path]),$cookie++)
  1591.                                                         {
  1592.                                                                 $cookie_name=Key($this->cookies[$secure][$domain_pattern][$path]);
  1593.                                                                 $expires=$this->cookies[$secure][$domain_pattern][$path][$cookie_name]["expires"];
  1594.                                                                 if($expires==""
  1595.                                                                 || strcmp($now,$expires)<0)
  1596.                                                                         $cookies[$cookie_name]=$this->cookies[$secure][$domain_pattern][$path][$cookie_name];
  1597.                                                         }
  1598.                                                 }
  1599.                                         }
  1600.                                 }
  1601.                         }
  1602.                 }
  1603.         }
  1604.  
  1605.         Function GetFileDefinition($file, &$definition)
  1606.         {
  1607.                 $name="";
  1608.                 if(IsSet($file["FileName"]))
  1609.                         $name=basename($file["FileName"]);
  1610.                 if(IsSet($file["Name"]))
  1611.                         $name=$file["Name"];
  1612.                 if(strlen($name)==0)
  1613.                         return("it was not specified the file part name");
  1614.                 if(IsSet($file["Content-Type"]))
  1615.                 {
  1616.                         $content_type=$file["Content-Type"];
  1617.                         $type=$this->Tokenize(strtolower($content_type),"/");
  1618.                         $sub_type=$this->Tokenize("");
  1619.                         switch($type)
  1620.                         {
  1621.                                 case "text":
  1622.                                 case "image":
  1623.                                 case "audio":
  1624.                                 case "video":
  1625.                                 case "application":
  1626.                                 case "message":
  1627.                                         break;
  1628.                                 case "automatic":
  1629.                                         switch($sub_type)
  1630.                                         {
  1631.                                                 case "name":
  1632.                                                         switch(GetType($dot=strrpos($name,"."))=="integer" ? strtolower(substr($name,$dot)) : "")
  1633.                                                         {
  1634.                                                                 case ".xls":
  1635.                                                                         $content_type="application/excel";
  1636.                                                                         break;
  1637.                                                                 case ".hqx":
  1638.                                                                         $content_type="application/macbinhex40";
  1639.                                                                         break;
  1640.                                                                 case ".doc":
  1641.                                                                 case ".dot":
  1642.                                                                 case ".wrd":
  1643.                                                                         $content_type="application/msword";
  1644.                                                                         break;
  1645.                                                                 case ".pdf":
  1646.                                                                         $content_type="application/pdf";
  1647.                                                                         break;
  1648.                                                                 case ".pgp":
  1649.                                                                         $content_type="application/pgp";
  1650.                                                                         break;
  1651.                                                                 case ".ps":
  1652.                                                                 case ".eps":
  1653.                                                                 case ".ai":
  1654.                                                                         $content_type="application/postscript";
  1655.                                                                         break;
  1656.                                                                 case ".ppt":
  1657.                                                                         $content_type="application/powerpoint";
  1658.                                                                         break;
  1659.                                                                 case ".rtf":
  1660.                                                                         $content_type="application/rtf";
  1661.                                                                         break;
  1662.                                                                 case ".tgz":
  1663.                                                                 case ".gtar":
  1664.                                                                         $content_type="application/x-gtar";
  1665.                                                                         break;
  1666.                                                                 case ".gz":
  1667.                                                                         $content_type="application/x-gzip";
  1668.                                                                         break;
  1669.                                                                 case ".php":
  1670.                                                                 case ".php3":
  1671.                                                                         $content_type="application/x-httpd-php";
  1672.                                                                         break;
  1673.                                                                 case ".js":
  1674.                                                                         $content_type="application/x-javascript";
  1675.                                                                         break;
  1676.                                                                 case ".ppd":
  1677.                                                                 case ".psd":
  1678.                                                                         $content_type="application/x-photoshop";
  1679.                                                                         break;
  1680.                                                                 case ".swf":
  1681.                                                                 case ".swc":
  1682.                                                                 case ".rf":
  1683.                                                                         $content_type="application/x-shockwave-flash";
  1684.                                                                         break;
  1685.                                                                 case ".tar":
  1686.                                                                         $content_type="application/x-tar";
  1687.                                                                         break;
  1688.                                                                 case ".zip":
  1689.                                                                         $content_type="application/zip";
  1690.                                                                         break;
  1691.                                                                 case ".mid":
  1692.                                                                 case ".midi":
  1693.                                                                 case ".kar":
  1694.                                                                         $content_type="audio/midi";
  1695.                                                                         break;
  1696.                                                                 case ".mp2":
  1697.                                                                 case ".mp3":
  1698.                                                                 case ".mpga":
  1699.                                                                         $content_type="audio/mpeg";
  1700.                                                                         break;
  1701.                                                                 case ".ra":
  1702.                                                                         $content_type="audio/x-realaudio";
  1703.                                                                         break;
  1704.                                                                 case ".wav":
  1705.                                                                         $content_type="audio/wav";
  1706.                                                                         break;
  1707.                                                                 case ".bmp":
  1708.                                                                         $content_type="image/bitmap";
  1709.                                                                         break;
  1710.                                                                 case ".gif":
  1711.                                                                         $content_type="image/gif";
  1712.                                                                         break;
  1713.                                                                 case ".iff":
  1714.                                                                         $content_type="image/iff";
  1715.                                                                         break;
  1716.                                                                 case ".jb2":
  1717.                                                                         $content_type="image/jb2";
  1718.                                                                         break;
  1719.                                                                 case ".jpg":
  1720.                                                                 case ".jpe":
  1721.                                                                 case ".jpeg":
  1722.                                                                         $content_type="image/jpeg";
  1723.                                                                         break;
  1724.                                                                 case ".jpx":
  1725.                                                                         $content_type="image/jpx";
  1726.                                                                         break;
  1727.                                                                 case ".png":
  1728.                                                                         $content_type="image/png";
  1729.                                                                         break;
  1730.                                                                 case ".tif":
  1731.                                                                 case ".tiff":
  1732.                                                                         $content_type="image/tiff";
  1733.                                                                         break;
  1734.                                                                 case ".wbmp":
  1735.                                                                         $content_type="image/vnd.wap.wbmp";
  1736.                                                                         break;
  1737.                                                                 case ".xbm":
  1738.                                                                         $content_type="image/xbm";
  1739.                                                                         break;
  1740.                                                                 case ".css":
  1741.                                                                         $content_type="text/css";
  1742.                                                                         break;
  1743.                                                                 case ".txt":
  1744.                                                                         $content_type="text/plain";
  1745.                                                                         break;
  1746.                                                                 case ".htm":
  1747.                                                                 case ".html":
  1748.                                                                         $content_type="text/html";
  1749.                                                                         break;
  1750.                                                                 case ".xml":
  1751.                                                                         $content_type="text/xml";
  1752.                                                                         break;
  1753.                                                                 case ".mpg":
  1754.                                                                 case ".mpe":
  1755.                                                                 case ".mpeg":
  1756.                                                                         $content_type="video/mpeg";
  1757.                                                                         break;
  1758.                                                                 case ".qt":
  1759.                                                                 case ".mov":
  1760.                                                                         $content_type="video/quicktime";
  1761.                                                                         break;
  1762.                                                                 case ".avi":
  1763.                                                                         $content_type="video/x-ms-video";
  1764.                                                                         break;
  1765.                                                                 case ".eml":
  1766.                                                                         $content_type="message/rfc822";
  1767.                                                                         break;
  1768.                                                                 default:
  1769.                                                                         $content_type="application/octet-stream";
  1770.                                                                         break;
  1771.                                                         }
  1772.                                                         break;
  1773.                                                 default:
  1774.                                                         return($content_type." is not a supported automatic content type detection method");
  1775.                                         }
  1776.                                         break;
  1777.                                 default:
  1778.                                         return($content_type." is not a supported file content type");
  1779.                         }
  1780.                 }
  1781.                 else
  1782.                         $content_type="application/octet-stream";
  1783.                 $definition=array(
  1784.                         "Content-Type"=>$content_type,
  1785.                         "NAME"=>$name
  1786.                 );
  1787.                 if(IsSet($file["FileName"]))
  1788.                 {
  1789.                         if(GetType($length=@filesize($file["FileName"]))!="integer")
  1790.                         {
  1791.                                 $error="it was not possible to determine the length of the file ".$file["FileName"];
  1792.                                 /*
  1793.                                 if(IsSet($php_errormsg)
  1794.                                 && strlen($php_errormsg))
  1795.                                         $error.=": ".$php_errormsg;
  1796.                                 */
  1797.                                 if(!file_exists($file["FileName"]))
  1798.                                         $error="it was not possible to access the file ".$file["FileName"];
  1799.                                 return($error);
  1800.                         }
  1801.                         $definition["FILENAME"]=$file["FileName"];
  1802.                         $definition["Content-Length"]=$length;
  1803.                 }
  1804.                 elseif(IsSet($file["Data"]))
  1805.                         $definition["Content-Length"]=strlen($definition["DATA"]=$file["Data"]);
  1806.                 else
  1807.                         return("it was not specified a valid file name");
  1808.                 return("");
  1809.         }
  1810.  
  1811.         Function ConnectFromProxy($arguments, &$headers)
  1812.         {
  1813.                 $host = $this->host_name.':'.($this->host_port ? $this->host_port : 443);
  1814.                 $this->OutputDebug('Connecting from proxy to host '.$host);
  1815.                 if(!$this->PutLine('CONNECT '.$host.' HTTP/1.0')
  1816.                 || (strlen($this->user_agent)
  1817.                 && !$this->PutLine('User-Agent: '.$this->user_agent))
  1818.                 || (strlen($this->accept)
  1819.                 && !$this->PutLine('Accept: '.$this->accept))
  1820.                 || (IsSet($arguments['Headers']['Proxy-Authorization'])
  1821.                 && !$this->PutLine('Proxy-Authorization: '.$arguments['Headers']['Proxy-Authorization']))
  1822.                 || !$this->PutLine(''))
  1823.                 {
  1824.                         $this->Disconnect();
  1825.                         return($this->error);
  1826.                 }
  1827.                 $this->state = "ConnectSent";
  1828.                 if(strlen($error=$this->ReadReplyHeadersResponse($headers)))
  1829.                         return($error);
  1830.                 $proxy_authorization="";
  1831.                 while(!strcmp($this->response_status, "100"))
  1832.                 {
  1833.                         $this->state="ConnectSent";
  1834.                         if(strlen($error=$this->ReadReplyHeadersResponse($headers)))
  1835.                                 return($error);
  1836.                 }
  1837.                 switch($this->response_status)
  1838.                 {
  1839.                         case "200":
  1840.                                 $this->OutputDebug('Establishing the cryptography layer with host '.$host);
  1841.                                 if(!stream_socket_enable_crypto($this->connection, 1, STREAM_CRYPTO_METHOD_SSLv23_CLIENT))
  1842.                                 {
  1843.                                         $this->OutputDebug('Failed establishing the cryptography layer with host '.$host);
  1844.                                         $php_errormsg = '';
  1845.                                         $this->SetPHPError('it was not possible to start a SSL encrypted connection via this proxy', $php_errormsg, self::HTTP_CLIENT_ERROR_COMMUNICATION_FAILURE);
  1846.                                         $this->Disconnect();
  1847.                                         return($this->error);
  1848.                                 }
  1849.                                 $this->OutputDebug('Succeeded establishing the cryptography layer with host '.$host);
  1850.                                 $this->state = "Connected";
  1851.                                 break;
  1852.                         case "407":
  1853.                                 if(strlen($error=$this->Authenticate($headers, -1, $proxy_authorization, $this->proxy_request_user, $this->proxy_request_password, $this->proxy_request_realm, $this->proxy_request_workstation)))
  1854.                                         return($error);
  1855.                                 break;
  1856.                         default:
  1857.                                 return($this->SetError("unable to send request via proxy", self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE));
  1858.                 }
  1859.                 return("");
  1860.         }
  1861.  
  1862.         Function SendRequest($arguments)
  1863.         {
  1864.                 if(strlen($this->error))
  1865.                         return($this->error);
  1866.                 if(IsSet($arguments["ProxyUser"]))
  1867.                         $this->proxy_request_user=$arguments["ProxyUser"];
  1868.                 elseif(IsSet($this->proxy_user))
  1869.                         $this->proxy_request_user=$this->proxy_user;
  1870.                 if(IsSet($arguments["ProxyPassword"]))
  1871.                         $this->proxy_request_password=$arguments["ProxyPassword"];
  1872.                 elseif(IsSet($this->proxy_password))
  1873.                         $this->proxy_request_password=$this->proxy_password;
  1874.                 if(IsSet($arguments["ProxyRealm"]))
  1875.                         $this->proxy_request_realm=$arguments["ProxyRealm"];
  1876.                 elseif(IsSet($this->proxy_realm))
  1877.                         $this->proxy_request_realm=$this->proxy_realm;
  1878.                 if(IsSet($arguments["ProxyWorkstation"]))
  1879.                         $this->proxy_request_workstation=$arguments["ProxyWorkstation"];
  1880.                 elseif(IsSet($this->proxy_workstation))
  1881.                         $this->proxy_request_workstation=$this->proxy_workstation;
  1882.                 switch($this->state)
  1883.                 {
  1884.                         case "Disconnected":
  1885.                                 return($this->SetError("connection was not yet established", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1886.                         case "Connected":
  1887.                                 $connect = 0;
  1888.                                 break;
  1889.                         case "ConnectedToProxy":
  1890.                                 $headers = array();
  1891.                                 if(strlen($error = $this->ConnectFromProxy($arguments, $headers)))
  1892.                                         return($error);
  1893.                                 $connect = 1;
  1894.                                 break;
  1895.                         default:
  1896.                                 return($this->SetError("can not send request in the current connection state", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1897.                 }
  1898.                 if(IsSet($arguments["RequestMethod"]))
  1899.                         $this->request_method=$arguments["RequestMethod"];
  1900.                 if(IsSet($arguments["User-Agent"]))
  1901.                         $this->user_agent=$arguments["User-Agent"];
  1902.                 if(!IsSet($arguments["Headers"]["User-Agent"])
  1903.                 && strlen($this->user_agent))
  1904.                         $arguments["Headers"]["User-Agent"]=$this->user_agent;
  1905.                 if(IsSet($arguments["KeepAlive"]))
  1906.                         $this->keep_alive=intval($arguments["KeepAlive"]);
  1907.                 if(!IsSet($arguments["Headers"]["Connection"])
  1908.                 && $this->keep_alive)
  1909.                         $arguments["Headers"]["Connection"]='Keep-Alive';
  1910.                 if(IsSet($arguments["Accept"]))
  1911.                         $this->user_agent=$arguments["Accept"];
  1912.                 if(!IsSet($arguments["Headers"]["Accept"])
  1913.                 && strlen($this->accept))
  1914.                         $arguments["Headers"]["Accept"]=$this->accept;
  1915.                 if(strlen($this->request_method)==0)
  1916.                         return($this->SetError("it was not specified a valid request method", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1917.                 if(IsSet($arguments["RequestURI"]))
  1918.                         $this->request_uri=$arguments["RequestURI"];
  1919.                 if(strlen($this->request_uri)==0
  1920.                 || substr($this->request_uri,0,1)!="/")
  1921.                         return($this->SetError("it was not specified a valid request URI", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1922.                 $this->request_arguments=$arguments;
  1923.                 $this->request_headers=(IsSet($arguments["Headers"]) ? $arguments["Headers"] : array());
  1924.                 $body_length=0;
  1925.                 $this->request_body="";
  1926.                 $get_body=1;
  1927.                 if($this->request_method=="POST"
  1928.                 || $this->request_method=="PUT")
  1929.                 {
  1930.                         if(IsSet($arguments['StreamRequest']))
  1931.                         {
  1932.                                 $get_body = 0;
  1933.                                 $this->request_headers["Transfer-Encoding"]="chunked";
  1934.                         }
  1935.                         elseif(IsSet($arguments["PostFiles"])
  1936.                         || ($this->force_multipart_form_post
  1937.                         && IsSet($arguments["PostValues"])))
  1938.                         {
  1939.                                 $boundary="--".md5(uniqid(time()));
  1940.                                 $this->request_headers["Content-Type"]="multipart/form-data; boundary=".$boundary.(IsSet($arguments["CharSet"]) ? "; charset=".$arguments["CharSet"] : "");
  1941.                                 $post_parts=array();
  1942.                                 if(IsSet($arguments["PostValues"]))
  1943.                                 {
  1944.                                         $values=$arguments["PostValues"];
  1945.                                         if(GetType($values)!="array")
  1946.                                                 return($this->SetError("it was not specified a valid POST method values array", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1947.                                         for(Reset($values),$value=0;$value<count($values);Next($values),$value++)
  1948.                                         {
  1949.                                                 $input=Key($values);
  1950.                                                 $headers="--".$boundary."\r\nContent-Disposition: form-data; name=\"".$input."\"\r\n\r\n";
  1951.                                                 $data=$values[$input];
  1952.                                                 $post_parts[]=array("HEADERS"=>$headers,"DATA"=>$data);
  1953.                                                 $body_length+=strlen($headers)+strlen($data)+strlen("\r\n");
  1954.                                         }
  1955.                                 }
  1956.                                 $body_length+=strlen("--".$boundary."--\r\n");
  1957.                                 $files=(IsSet($arguments["PostFiles"]) ? $arguments["PostFiles"] : array());
  1958.                                 Reset($files);
  1959.                                 $end=(GetType($input=Key($files))!="string");
  1960.                                 for(;!$end;)
  1961.                                 {
  1962.                                         $definition = array();
  1963.                                         if(strlen($error=$this->GetFileDefinition($files[$input],$definition)))
  1964.                                                 return("3 ".$error);
  1965.                                         $headers="--".$boundary."\r\nContent-Disposition: form-data; name=\"".$input."\"; filename=\"".$definition["NAME"]."\"\r\nContent-Type: ".$definition["Content-Type"]."\r\n\r\n";
  1966.                                         $part=count($post_parts);
  1967.                                         $post_parts[$part]=array("HEADERS"=>$headers);
  1968.                                         if(IsSet($definition["FILENAME"]))
  1969.                                         {
  1970.                                                 $post_parts[$part]["FILENAME"]=$definition["FILENAME"];
  1971.                                                 $data="";
  1972.                                         }
  1973.                                         else
  1974.                                                 $data=$definition["DATA"];
  1975.                                         $post_parts[$part]["DATA"]=$data;
  1976.                                         $body_length+=strlen($headers)+$definition["Content-Length"]+strlen("\r\n");
  1977.                                         Next($files);
  1978.                                         $end=(GetType($input=Key($files))!="string");
  1979.                                 }
  1980.                                 $get_body=0;
  1981.                         }
  1982.                         elseif(IsSet($arguments["PostValues"]))
  1983.                         {
  1984.                                 $values=$arguments["PostValues"];
  1985.                                 if(GetType($values)!="array")
  1986.                                         return($this->SetError("it was not specified a valid POST method values array", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  1987.                                 for(Reset($values),$value=0;$value<count($values);Next($values),$value++)
  1988.                                 {
  1989.                                         $k=Key($values);
  1990.                                         if(GetType($values[$k])=="array")
  1991.                                         {
  1992.                                                 for($v = 0; $v < count($values[$k]); $v++)
  1993.                                                 {
  1994.                                                         if($value+$v>0)
  1995.                                                                 $this->request_body.="&";
  1996.                                                         $this->request_body.=UrlEncode($k)."=".UrlEncode($values[$k][$v]);
  1997.                                                 }
  1998.                                         }
  1999.                                         else
  2000.                                         {
  2001.                                                 if($value>0)
  2002.                                                         $this->request_body.="&";
  2003.                                                 $this->request_body.=UrlEncode($k)."=".UrlEncode($values[$k]);
  2004.                                         }
  2005.                                 }
  2006.                                 $this->request_headers["Content-Type"]="application/x-www-form-urlencoded".(IsSet($arguments["CharSet"]) ? "; charset=".$arguments["CharSet"] : "");
  2007.                                 $get_body=0;
  2008.                         }
  2009.                 }
  2010.                 if($get_body
  2011.                 && (IsSet($arguments["Body"])
  2012.                 || IsSet($arguments["BodyStream"])))
  2013.                 {
  2014.                         if(IsSet($arguments["Body"]))
  2015.                                 $this->request_body=$arguments["Body"];
  2016.                         else
  2017.                         {
  2018.                                 $stream=$arguments["BodyStream"];
  2019.                                 $this->request_body="";
  2020.                                 for($part=0; $part<count($stream); $part++)
  2021.                                 {
  2022.                                         if(IsSet($stream[$part]["Data"]))
  2023.                                                 $this->request_body.=$stream[$part]["Data"];
  2024.                                         elseif(IsSet($stream[$part]["File"]))
  2025.                                         {
  2026.                                                 if(!($file=@fopen($stream[$part]["File"],"rb"))) {
  2027.                                                         $php_errormsg = '';
  2028.                                                         return($this->SetPHPError("could not open upload file ".$stream[$part]["File"], $php_errormsg, self::HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE));
  2029.                                                 }
  2030.                                                 while(!feof($file))
  2031.                                                 {
  2032.                                                         if(GetType($block=@fread($file,$this->file_buffer_length))!="string")
  2033.                                                         {
  2034.                                                                 $error=$this->SetPHPError("could not read body stream file ".$stream[$part]["File"], $php_errormsg, self::HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE);
  2035.                                                                 fclose($file);
  2036.                                                                 return($error);
  2037.                                                         }
  2038.                                                         $this->request_body.=$block;
  2039.                                                 }
  2040.                                                 fclose($file);
  2041.                                         }
  2042.                                         else
  2043.                                                 return("5 it was not specified a valid file or data body stream element at position ".$part);
  2044.                                 }
  2045.                         }
  2046.                         if(!IsSet($this->request_headers["Content-Type"]))
  2047.                                 $this->request_headers["Content-Type"]="application/octet-stream".(IsSet($arguments["CharSet"]) ? "; charset=".$arguments["CharSet"] : "");
  2048.                 }
  2049.                 if(IsSet($arguments["AuthUser"]))
  2050.                         $this->request_user=$arguments["AuthUser"];
  2051.                 elseif(IsSet($this->user))
  2052.                         $this->request_user=$this->user;
  2053.                 if(IsSet($arguments["AuthPassword"]))
  2054.                         $this->request_password=$arguments["AuthPassword"];
  2055.                 elseif(IsSet($this->password))
  2056.                         $this->request_password=$this->password;
  2057.                 if(IsSet($arguments["AuthRealm"]))
  2058.                         $this->request_realm=$arguments["AuthRealm"];
  2059.                 elseif(IsSet($this->realm))
  2060.                         $this->request_realm=$this->realm;
  2061.                 if(IsSet($arguments["AuthWorkstation"]))
  2062.                         $this->request_workstation=$arguments["AuthWorkstation"];
  2063.                 elseif(IsSet($this->workstation))
  2064.                         $this->request_workstation=$this->workstation;
  2065.                 if(strlen($this->proxy_host_name)==0
  2066.                 || $connect)
  2067.                         $request_uri=$this->request_uri;
  2068.                 else
  2069.                 {
  2070.                         switch(strtolower($this->protocol))
  2071.                         {
  2072.                                 case "http":
  2073.                                         $default_port=80;
  2074.                                         break;
  2075.                                 case "https":
  2076.                                         $default_port=443;
  2077.                                         break;
  2078.                         }
  2079.                         $request_uri=strtolower($this->protocol)."://".$this->host_name.(($this->host_port==0 || $this->host_port==$default_port) ? "" : ":".$this->host_port).$this->request_uri;
  2080.                 }
  2081.                 if($this->use_curl)
  2082.                 {
  2083.                         $m = array();
  2084.                         $version=(GetType($v=curl_version())=="array" ? (IsSet($v["version"]) ? $v["version"] : "0.0.0") : (preg_match("/^libcurl\\/([0-9]+\\.[0-9]+\\.[0-9]+)/",$v,$m) ? $m[1] : "0.0.0"));
  2085.                         $curl_version=100000*intval($this->Tokenize($version,"."))+1000*intval($this->Tokenize("."))+intval($this->Tokenize(""));
  2086.                         $protocol_version=($curl_version<713002 ? "1.0" : $this->protocol_version);
  2087.                 }
  2088.                 else
  2089.                         $protocol_version=$this->protocol_version;
  2090.                 $this->request=$this->request_method." ".$request_uri." HTTP/".$protocol_version;
  2091.                 if($body_length
  2092.                 || ($body_length=strlen($this->request_body))
  2093.                 || !strcmp($this->request_method, 'POST'))
  2094.                         $this->request_headers["Content-Length"]=$body_length;
  2095.                 for($headers=array(),$host_set=0,Reset($this->request_headers),$header=0;$header<count($this->request_headers);Next($this->request_headers),$header++)
  2096.                 {
  2097.                         $header_name=Key($this->request_headers);
  2098.                         $header_value=$this->request_headers[$header_name];
  2099.                         if(GetType($header_value)=="array")
  2100.                         {
  2101.                                 for(Reset($header_value),$value=0;$value<count($header_value);Next($header_value),$value++)
  2102.                                         $headers[]=$header_name.": ".$header_value[Key($header_value)];
  2103.                         }
  2104.                         else
  2105.                                 $headers[]=$header_name.": ".$header_value;
  2106.                         if(strtolower(Key($this->request_headers))=="host")
  2107.                         {
  2108.                                 $this->request_host=strtolower($header_value);
  2109.                                 $host_set=1;
  2110.                         }
  2111.                 }
  2112.                 if(!$host_set)
  2113.                 {
  2114.                         $headers[]="Host: ".$this->host_name;
  2115.                         $this->request_host=strtolower($this->host_name);
  2116.                 }
  2117.                 if(count($this->cookies))
  2118.                 {
  2119.                         $cookies=array();
  2120.                         $this->PickCookies($cookies,0);
  2121.                         if(strtolower($this->protocol)=="https")
  2122.                                 $this->PickCookies($cookies,1);
  2123.                         if(count($cookies))
  2124.                         {
  2125.                                 $h=count($headers);
  2126.                                 $headers[$h]="Cookie:";
  2127.                                 for(Reset($cookies),$cookie=0;$cookie<count($cookies);Next($cookies),$cookie++)
  2128.                                 {
  2129.                                         $cookie_name=Key($cookies);
  2130.                                         $headers[$h].=" ".$cookie_name."=".$cookies[$cookie_name]["value"].";";
  2131.                                 }
  2132.                         }
  2133.                 }
  2134.                 $next_state = "RequestSent";
  2135.                 if($this->use_curl)
  2136.                 {
  2137.                         if(IsSet($arguments['StreamRequest']))
  2138.                                 return($this->SetError("Streaming request data is not supported when using Curl", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2139.                         if($body_length
  2140.                         && strlen($this->request_body)==0)
  2141.                         {
  2142.                                 for($request_body="",$success=1,$part=0;$part<count($post_parts);$part++)
  2143.                                 {
  2144.                                         $request_body.=$post_parts[$part]["HEADERS"].$post_parts[$part]["DATA"];
  2145.                                         if(IsSet($post_parts[$part]["FILENAME"]))
  2146.                                         {
  2147.                                                 if(!($file=@fopen($post_parts[$part]["FILENAME"],"rb")))
  2148.                                                 {
  2149.                                                         $php_errormsg = '';
  2150.                                                         $this->SetPHPError("could not open upload file ".$post_parts[$part]["FILENAME"], $php_errormsg, self::HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE);
  2151.                                                         $success=0;
  2152.                                                         break;
  2153.                                                 }
  2154.                                                 while(!feof($file))
  2155.                                                 {
  2156.                                                         if(GetType($block=@fread($file,$this->file_buffer_length))!="string")
  2157.                                                         {
  2158.                                                                 $this->SetPHPError("could not read upload file", $php_errormsg, self::HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE);
  2159.                                                                 $success=0;
  2160.                                                                 break;
  2161.                                                         }
  2162.                                                         $request_body.=$block;
  2163.                                                 }
  2164.                                                 fclose($file);
  2165.                                                 if(!$success)
  2166.                                                         break;
  2167.                                         }
  2168.                                         $request_body.="\r\n";
  2169.                                 }
  2170.                                 $request_body.="--".$boundary."--\r\n";
  2171.                         }
  2172.                         else
  2173.                                 $request_body=$this->request_body;
  2174.                         curl_setopt($this->connection,CURLOPT_HEADER,1);
  2175.                         curl_setopt($this->connection,CURLOPT_RETURNTRANSFER,1);
  2176.                         if($this->timeout)
  2177.                                 curl_setopt($this->connection,CURLOPT_TIMEOUT,$this->timeout);
  2178.                         curl_setopt($this->connection,CURLOPT_SSL_VERIFYPEER,0);
  2179.                         curl_setopt($this->connection,CURLOPT_SSL_VERIFYHOST,0);
  2180.                         $request=$this->request."\r\n".implode("\r\n",$headers)."\r\n\r\n".$request_body;
  2181.                         curl_setopt($this->connection,CURLOPT_CUSTOMREQUEST,$request);
  2182.                         if($this->debug)
  2183.                                 $this->OutputDebug("C ".$request);
  2184.                         if(!($success=(strlen($this->response=@curl_exec($this->connection))!=0)))
  2185.                         {
  2186.                                 $error=curl_error($this->connection);
  2187.                                 $this->SetError("Could not execute the request".(strlen($error) ? ": ".$error : ""), self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE);
  2188.                         }
  2189.                 }
  2190.                 else
  2191.                 {
  2192.                         if(($success=$this->PutLine($this->request)))
  2193.                         {
  2194.                                 for($header=0;$header<count($headers);$header++)
  2195.                                 {
  2196.                                         if(!$success=$this->PutLine($headers[$header]))
  2197.                                                 break;
  2198.                                 }
  2199.                                 if($success
  2200.                                 && ($success=$this->PutLine("")))
  2201.                                 {
  2202.                                         if(IsSet($arguments['StreamRequest']))
  2203.                                                 $next_state = "SendingRequestBody";
  2204.                                         elseif($body_length)
  2205.                                         {
  2206.                                                 if(strlen($this->request_body))
  2207.                                                         $success=$this->PutData($this->request_body);
  2208.                                                 else
  2209.                                                 {
  2210.                                                         for($part=0;$part<count($post_parts);$part++)
  2211.                                                         {
  2212.                                                                 if(!($success=$this->PutData($post_parts[$part]["HEADERS"]))
  2213.                                                                 || !($success=$this->PutData($post_parts[$part]["DATA"])))
  2214.                                                                         break;
  2215.                                                                 if(IsSet($post_parts[$part]["FILENAME"]))
  2216.                                                                 {
  2217.                                                                         if(!($file=@fopen($post_parts[$part]["FILENAME"],"rb")))
  2218.                                                                         {
  2219.                                                                                 $this->SetPHPError("could not open upload file ".$post_parts[$part]["FILENAME"], $php_errormsg, self::HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE);
  2220.                                                                                 $success=0;
  2221.                                                                                 break;
  2222.                                                                         }
  2223.                                                                         while(!feof($file))
  2224.                                                                         {
  2225.                                                                                 if(GetType($block=@fread($file,$this->file_buffer_length))!="string")
  2226.                                                                                 {
  2227.                                                                                         $this->SetPHPError("could not read upload file", $php_errormsg, self::HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE);
  2228.                                                                                         $success=0;
  2229.                                                                                         break;
  2230.                                                                                 }
  2231.                                                                                 if(!($success=$this->PutData($block)))
  2232.                                                                                         break;
  2233.                                                                         }
  2234.                                                                         fclose($file);
  2235.                                                                         if(!$success)
  2236.                                                                                 break;
  2237.                                                                 }
  2238.                                                                 if(!($success=$this->PutLine("")))
  2239.                                                                         break;
  2240.                                                         }
  2241.                                                         if($success)
  2242.                                                                 $success=$this->PutLine("--".$boundary."--");
  2243.                                                 }
  2244.                                                 if($success)
  2245.                                                         $sucess=$this->FlushData();
  2246.                                         }
  2247.                                 }
  2248.                         }
  2249.                 }
  2250.                 if(!$success)
  2251.                         return($this->SetError("could not send the HTTP request: ".$this->error, $this->error_code));
  2252.                 $this->state=$next_state;
  2253.                 return("");
  2254.         }
  2255.  
  2256.         Function SetCookie($name, $value, $expires="" , $path="/" , $domain="" , $secure=0, $verbatim=0)
  2257.         {
  2258.                 if(strlen($this->error))
  2259.                         return($this->error);
  2260.                 if(strlen($name)==0)
  2261.                         return($this->SetError("it was not specified a valid cookie name", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2262.                 if(strlen($path)==0
  2263.                 || strcmp($path[0],"/"))
  2264.                         return($this->SetError($path." is not a valid path for setting cookie ".$name, self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2265.                 if($domain==""
  2266.                 || !strpos($domain,".",$domain[0]=="." ? 1 : 0))
  2267.                         return($this->SetError($domain." is not a valid domain for setting cookie ".$name, self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2268.                 $domain=strtolower($domain);
  2269.                 if(!strcmp($domain[0],"."))
  2270.                         $domain=substr($domain,1);
  2271.                 if(!$verbatim)
  2272.                 {
  2273.                         $name=$this->CookieEncode($name,1);
  2274.                         $value=$this->CookieEncode($value,0);
  2275.                 }
  2276.                 $secure=intval($secure);
  2277.                 $this->cookies[$secure][$domain][$path][$name]=array(
  2278.                         "name"=>$name,
  2279.                         "value"=>$value,
  2280.                         "domain"=>$domain,
  2281.                         "path"=>$path,
  2282.                         "expires"=>$expires,
  2283.                         "secure"=>$secure
  2284.                 );
  2285.                 return("");
  2286.         }
  2287.  
  2288.         Function SendRequestBody($data, $end_of_data)
  2289.         {
  2290.                 if(strlen($this->error))
  2291.                         return($this->error);
  2292.                 switch($this->state)
  2293.                 {
  2294.                         case "Disconnected":
  2295.                                 return($this->SetError("connection was not yet established", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2296.                         case "Connected":
  2297.                         case "ConnectedToProxy":
  2298.                                 return($this->SetError("request was not sent", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2299.                         case "SendingRequestBody":
  2300.                                 break;
  2301.                         case "RequestSent":
  2302.                                 return($this->SetError("request body was already sent", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2303.                         default:
  2304.                                 return($this->SetError("can not send the request body in the current connection state", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2305.                 }
  2306.                 $length = strlen($data);
  2307.                 if($length)
  2308.                 {
  2309.                         $size = dechex($length)."\r\n";
  2310.                         if(!$this->PutData($size)
  2311.                         || !$this->PutData($data))
  2312.                                 return($this->error);
  2313.                 }
  2314.                 if($end_of_data)
  2315.                 {
  2316.                         $size = "0\r\n";
  2317.                         if(!$this->PutData($size))
  2318.                                 return($this->error);
  2319.                         $this->state = "RequestSent";
  2320.                 }
  2321.                 return("");
  2322.         }
  2323.  
  2324.         Function ReadReplyHeadersResponse(&$headers)
  2325.         {
  2326.                 $headers=array();
  2327.                 if(strlen($this->error))
  2328.                         return($this->error);
  2329.                 switch($this->state)
  2330.                 {
  2331.                         case "Disconnected":
  2332.                                 return($this->SetError("connection was not yet established", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2333.                         case "Connected":
  2334.                                 return($this->SetError("request was not sent", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2335.                         case "ConnectedToProxy":
  2336.                                 return($this->SetError("connection from the remote server from the proxy was not yet established", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2337.                         case "SendingRequestBody":
  2338.                                 return($this->SetError("request body data was not completely sent", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2339.                         case "ConnectSent":
  2340.                                 $connect = 1;
  2341.                                 break;
  2342.                         case "RequestSent":
  2343.                                 $connect = 0;
  2344.                                 break;
  2345.                         default:
  2346.                                 return($this->SetError("can not get request headers in the current connection state", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2347.                 }
  2348.                 $this->content_length=$this->read_length=$this->read_response=$this->remaining_chunk=0;
  2349.                 $this->content_length_set=$this->chunked=$this->last_chunk_read=$chunked=0;
  2350.                 $this->force_close = $this->connection_close=0;
  2351.                 for($this->response_status="";;)
  2352.                 {
  2353.                         $line=$this->GetLine();
  2354.                         if(GetType($line)!="string")
  2355.                                 return($this->SetError("could not read request reply: ".$this->error, $this->error_code));
  2356.                         if(strlen($this->response_status)==0)
  2357.                         {
  2358.                                 $matches = array();
  2359.                                 if(!preg_match($match="/^http\\/[0-9]+\\.[0-9]+[ \t]+([0-9]+)[ \t]*(.*)\$/i",$line,$matches))
  2360.                                         return($this->SetError("it was received an unexpected HTTP response status", self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE));
  2361.                                 $this->response_status=$matches[1];
  2362.                                 $this->response_message=$matches[2];
  2363.                                 if($this->response_status == 204)
  2364.                                 {
  2365.                                         $this->content_length = 0;
  2366.                                         $this->content_length_set = 1;
  2367.                                 }
  2368.                         }
  2369.                         if($line=="")
  2370.                         {
  2371.                                 if(strlen($this->response_status)==0)
  2372.                                         return($this->SetError("it was not received HTTP response status", self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE));
  2373.                                 $this->state=($connect ? "GotConnectHeaders" : "GotReplyHeaders");
  2374.                                 break;
  2375.                         }
  2376.                         $header_name=strtolower($this->Tokenize($line,":"));
  2377.                         $header_value=Trim(Chop($this->Tokenize("\r\n")));
  2378.                         if(IsSet($headers[$header_name]))
  2379.                         {
  2380.                                 if(GetType($headers[$header_name])=="string")
  2381.                                         $headers[$header_name]=array($headers[$header_name]);
  2382.                                 $headers[$header_name][]=$header_value;
  2383.                         }
  2384.                         else
  2385.                                 $headers[$header_name]=$header_value;
  2386.                         if(!$connect)
  2387.                         {
  2388.                                 switch($header_name)
  2389.                                 {
  2390.                                         case "content-length":
  2391.                                                 $this->content_length=intval($headers[$header_name]);
  2392.                                                 $this->content_length_set=1;
  2393.                                                 break;
  2394.                                         case "transfer-encoding":
  2395.                                                 $encoding=$this->Tokenize($header_value,"; \t");
  2396.                                                 if(!$this->use_curl
  2397.                                                 && !strcmp($encoding,"chunked"))
  2398.                                                         $chunked=1;
  2399.                                                 break;
  2400.                                         case "set-cookie":
  2401.                                                 if($this->support_cookies)
  2402.                                                 {
  2403.                                                         if(GetType($headers[$header_name])=="array")
  2404.                                                                 $cookie_headers=$headers[$header_name];
  2405.                                                         else
  2406.                                                                 $cookie_headers=array($headers[$header_name]);
  2407.                                                         for($cookie=0;$cookie<count($cookie_headers);$cookie++)
  2408.                                                         {
  2409.                                                                 $cookie_name=trim($this->Tokenize($cookie_headers[$cookie],"="));
  2410.                                                                 $cookie_value=$this->Tokenize(";");
  2411.                                                                 $domain=$this->request_host;
  2412.                                                                 $path="/";
  2413.                                                                 $expires="";
  2414.                                                                 $secure=0;
  2415.                                                                 while(($name = strtolower(trim(UrlDecode($this->Tokenize("=")))))!="")
  2416.                                                                 {
  2417.                                                                         $value=UrlDecode($this->Tokenize(";"));
  2418.                                                                         switch($name)
  2419.                                                                         {
  2420.                                                                                 case "domain":
  2421.                                                                                         $domain=$value;
  2422.                                                                                         break;
  2423.                                                                                 case "path":
  2424.                                                                                         $path=$value;
  2425.                                                                                         break;
  2426.                                                                                 case "expires":
  2427.                                                                                         if(preg_match("/^((Mon|Monday|Tue|Tuesday|Wed|Wednesday|Thu|Thursday|Fri|Friday|Sat|Saturday|Sun|Sunday), )?([0-9]{2})\\-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\\-([0-9]{2,4}) ([0-9]{2})\\:([0-9]{2})\\:([0-9]{2}) GMT\$/",$value,$matches))
  2428.                                                                                         {
  2429.                                                                                                 $year=intval($matches[5]);
  2430.                                                                                                 if($year<1900)
  2431.                                                                                                         $year+=($year<70 ? 2000 : 1900);
  2432.                                                                                                 $expires="$year-".$this->months[$matches[4]]."-".$matches[3]." ".$matches[6].":".$matches[7].":".$matches[8];
  2433.                                                                                         }
  2434.                                                                                         break;
  2435.                                                                                 case "secure":
  2436.                                                                                         $secure=1;
  2437.                                                                                         break;
  2438.                                                                         }
  2439.                                                                 }
  2440.                                                                 if(strlen($this->SetCookie($cookie_name, $cookie_value, $expires, $path , $domain, $secure, 1)))
  2441.                                                                         $this->error="";
  2442.                                                         }
  2443.                                                 }
  2444.                                                 break;
  2445.                                         case "connection":
  2446.                                                 $this->force_close = $this->connection_close=!strcmp(strtolower($header_value),"close");
  2447.                                                 break;
  2448.                                 }
  2449.                         }
  2450.                 }
  2451.                 $this->chunked=$chunked;
  2452.                 if($this->content_length_set)
  2453.                         $this->connection_close=0;
  2454.                 return("");
  2455.         }
  2456.  
  2457.         Function Redirect(&$headers)
  2458.         {
  2459.                 if($this->follow_redirect)
  2460.                 {
  2461.                         if(!IsSet($headers["location"])
  2462.                         || (GetType($headers["location"])!="array"
  2463.                         && strlen($location=$headers["location"])==0)
  2464.                         || (GetType($headers["location"])=="array"
  2465.                         && strlen($location=$headers["location"][0])==0))
  2466.                                 return($this->SetError("it was received a redirect without location URL", self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE));
  2467.                         if(strcmp($location[0],"/"))
  2468.                         {
  2469.                                 if(!($location_arguments=@parse_url($location)))
  2470.                                         return($this->SetError("the server did not return a valid redirection location URL", self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE));
  2471.                                 if(!IsSet($location_arguments["scheme"]))
  2472.                                         $location=((GetType($end=strrpos($this->request_uri,"/"))=="integer" && $end>1) ? substr($this->request_uri,0,$end) : "")."/".$location;
  2473.                         }
  2474.                         if(!strcmp($location[0],"/"))
  2475.                                 $location=$this->protocol."://".$this->host_name.($this->host_port ? ":".$this->host_port : "").$location;
  2476.                         $arguments = array();
  2477.                         $error=$this->GetRequestArguments($location,$arguments);
  2478.                         if(strlen($error))
  2479.                                 return($this->SetError("could not process redirect url: ".$error, self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE));
  2480.                         $arguments["RequestMethod"]="GET";
  2481.                         if(strlen($error=$this->Close())==0
  2482.                         && strlen($error=$this->Open($arguments))==0
  2483.                         && strlen($error=$this->SendRequest($arguments))==0)
  2484.                         {
  2485.                                 $this->redirection_level++;
  2486.                                 if($this->redirection_level>$this->redirection_limit)
  2487.                                 {
  2488.                                         $error="it was exceeded the limit of request redirections";
  2489.                                         $this->error_code = self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE;
  2490.                                 }
  2491.                                 else
  2492.                                         $error=$this->ReadReplyHeaders($headers);
  2493.                                 $this->redirection_level--;
  2494.                         }
  2495.                         if(strlen($error))
  2496.                                 return($this->SetError($error, $this->error_code));
  2497.                 }
  2498.                 return("");
  2499.         }
  2500.  
  2501.         Function Authenticate(&$headers, $proxy, &$proxy_authorization, &$user, &$password, &$realm, &$workstation)
  2502.         {
  2503.                 if($proxy)
  2504.                 {
  2505.                         $authenticate_header="proxy-authenticate";
  2506.                         $authorization_header="Proxy-Authorization";
  2507.                         $authenticate_status="407";
  2508.                         $authentication_mechanism=$this->proxy_authentication_mechanism;
  2509.                 }
  2510.                 else
  2511.                 {
  2512.                         $authenticate_header="www-authenticate";
  2513.                         $authorization_header="Authorization";
  2514.                         $authenticate_status="401";
  2515.                         $authentication_mechanism=$this->authentication_mechanism;
  2516.                 }
  2517.                 if(IsSet($headers[$authenticate_header])
  2518.                 && $this->sasl_authenticate)
  2519.                 {
  2520.                         if(function_exists("class_exists")
  2521.                         && !class_exists("sasl_client_class"))
  2522.                                 return($this->SetError("the SASL client class needs to be loaded to be able to authenticate".($proxy ? " with the proxy server" : "")." and access this site", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2523.                         if(GetType($headers[$authenticate_header])=="array")
  2524.                                 $authenticate=$headers[$authenticate_header];
  2525.                         else
  2526.                                 $authenticate=array($headers[$authenticate_header]);
  2527.                         for($response="", $mechanisms=array(),$m=0;$m<count($authenticate);$m++)
  2528.                         {
  2529.                                 $mechanism=$this->Tokenize($authenticate[$m]," ");
  2530.                                 $response=$this->Tokenize("");
  2531.                                 if(strlen($authentication_mechanism))
  2532.                                 {
  2533.                                         if(!strcmp($authentication_mechanism,$mechanism))
  2534.                                         {
  2535.                                                 $mechanisms[]=$mechanism;
  2536.                                                 break;
  2537.                                         }
  2538.                                 }
  2539.                                 else
  2540.                                         $mechanisms[]=$mechanism;
  2541.                         }
  2542.                         $sasl=new sasl_client_class;
  2543.                         if(IsSet($user))
  2544.                                 $sasl->SetCredential("user",$user);
  2545.                         if(IsSet($password))
  2546.                                 $sasl->SetCredential("password",$password);
  2547.                         if(IsSet($realm))
  2548.                                 $sasl->SetCredential("realm",$realm);
  2549.                         if(IsSet($workstation))
  2550.                                 $sasl->SetCredential("workstation",$workstation);
  2551.                         $sasl->SetCredential("uri",$this->request_uri);
  2552.                         $sasl->SetCredential("method",$this->request_method);
  2553.                         $sasl->SetCredential("session",$this->session);
  2554.                         do
  2555.                         {
  2556.                                 $message = null;
  2557.                                 $interactions = null;
  2558.                                 $status=$sasl->Start($mechanisms,$message,$interactions);
  2559.                         }
  2560.                         while($status==SASL_INTERACT);
  2561.                         switch($status)
  2562.                         {
  2563.                                 case SASL_CONTINUE:
  2564.                                         break;
  2565.                                 case SASL_NOMECH:
  2566.                                         return($this->SetError(($proxy ? "proxy " : "")."authentication error: ".(strlen($authentication_mechanism) ? "authentication mechanism ".$authentication_mechanism." may not be used: " : "").$sasl->error, self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2567.                                 default:
  2568.                                         return($this->SetError("Could not start the SASL ".($proxy ? "proxy " : "")."authentication client: ".$sasl->error, self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2569.                         }
  2570.                         if($proxy >= 0)
  2571.                         {
  2572.                                 for(;;)
  2573.                                 {
  2574.                                         $body = '';
  2575.                                         if(strlen($error=$this->ReadReplyBody($body,$this->file_buffer_length)))
  2576.                                                 return($error);
  2577.                                         if(strlen($body)==0)
  2578.                                                 break;
  2579.                                 }
  2580.                         }
  2581.                         $authorization_value=$sasl->mechanism.(IsSet($message) ? " ".($sasl->encode_response ? base64_encode($message) : $message) : "");
  2582.                         $request_arguments=$this->request_arguments;
  2583.                         $arguments=$request_arguments;
  2584.                         $arguments["Headers"][$authorization_header]=$authorization_value;
  2585.                         if(!$proxy
  2586.                         && strlen($proxy_authorization))
  2587.                                 $arguments["Headers"]["Proxy-Authorization"]=$proxy_authorization;
  2588.                         if(strlen($error=$this->Close())
  2589.                         || strlen($error=$this->Open($arguments)))
  2590.                                 return($this->SetError($error, $this->error_code));
  2591.                         $authenticated=0;
  2592.                         if(IsSet($message))
  2593.                         {
  2594.                                 if($proxy < 0)
  2595.                                 {
  2596.                                         if(strlen($error=$this->ConnectFromProxy($arguments, $headers)))
  2597.                                                 return($this->SetError($error, $this->error_code));
  2598.                                 }
  2599.                                 else
  2600.                                 {
  2601.                                         if(strlen($error=$this->SendRequest($arguments))
  2602.                                         || strlen($error=$this->ReadReplyHeadersResponse($headers)))
  2603.                                                 return($this->SetError($error, $this->error_code));
  2604.                                 }
  2605.                                 if(!IsSet($headers[$authenticate_header]))
  2606.                                         $authenticate=array();
  2607.                                 elseif(GetType($headers[$authenticate_header])=="array")
  2608.                                         $authenticate=$headers[$authenticate_header];
  2609.                                 else
  2610.                                         $authenticate=array($headers[$authenticate_header]);
  2611.                                 for($mechanism=0;$mechanism<count($authenticate);$mechanism++)
  2612.                                 {
  2613.                                         if(!strcmp($this->Tokenize($authenticate[$mechanism]," "),$sasl->mechanism))
  2614.                                         {
  2615.                                                 $response=$this->Tokenize("");
  2616.                                                 break;
  2617.                                         }
  2618.                                 }
  2619.                                 switch($this->response_status)
  2620.                                 {
  2621.                                         case $authenticate_status:
  2622.                                                 break;
  2623.                                         case "301":
  2624.                                         case "302":
  2625.                                         case "303":
  2626.                                         case "307":
  2627.                                                 if($proxy >= 0)
  2628.                                                         return($this->Redirect($headers));
  2629.                                         default:
  2630.                                                 if(intval($this->response_status/100)==2)
  2631.                                                 {
  2632.                                                         if($proxy)
  2633.                                                                 $proxy_authorization=$authorization_value;
  2634.                                                         $authenticated=1;
  2635.                                                         break;
  2636.                                                 }
  2637.                                                 if($proxy
  2638.                                                 && !strcmp($this->response_status,"401"))
  2639.                                                 {
  2640.                                                         $proxy_authorization=$authorization_value;
  2641.                                                         $authenticated=1;
  2642.                                                         break;
  2643.                                                 }
  2644.                                                 return($this->SetError(($proxy ? "proxy " : "")."authentication error: ".$this->response_status." ".$this->response_message, self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE));
  2645.                                 }
  2646.                         }
  2647.                         for(;!$authenticated;)
  2648.                         {
  2649.                                 do
  2650.                                 {
  2651.                                         $status=$sasl->Step($response,$message,$interactions);
  2652.                                 }
  2653.                                 while($status==SASL_INTERACT);
  2654.                                 switch($status)
  2655.                                 {
  2656.                                         case SASL_CONTINUE:
  2657.                                                 $authorization_value=$sasl->mechanism.(IsSet($message) ? " ".($sasl->encode_response ? base64_encode($message) : $message) : "");
  2658.                                                 $arguments=$request_arguments;
  2659.                                                 $arguments["Headers"][$authorization_header]=$authorization_value;
  2660.                                                 if(!$proxy
  2661.                                                 && strlen($proxy_authorization))
  2662.                                                         $arguments["Headers"]["Proxy-Authorization"]=$proxy_authorization;
  2663.                                                 if($proxy < 0)
  2664.                                                 {
  2665.                                                         if(strlen($error=$this->ConnectFromProxy($arguments, $headers)))
  2666.                                                                 return($this->SetError($error, $this->error_code));
  2667.                                                 }
  2668.                                                 else
  2669.                                                 {
  2670.                                                         if(strlen($error=$this->SendRequest($arguments))
  2671.                                                         || strlen($error=$this->ReadReplyHeadersResponse($headers)))
  2672.                                                                 return($this->SetError($error, $this->error_code));
  2673.                                                 }
  2674.                                                 switch($this->response_status)
  2675.                                                 {
  2676.                                                         case $authenticate_status:
  2677.                                                                 if(GetType($headers[$authenticate_header])=="array")
  2678.                                                                         $authenticate=$headers[$authenticate_header];
  2679.                                                                 else
  2680.                                                                         $authenticate=array($headers[$authenticate_header]);
  2681.                                                                 for($response="",$mechanism=0;$mechanism<count($authenticate);$mechanism++)
  2682.                                                                 {
  2683.                                                                         if(!strcmp($this->Tokenize($authenticate[$mechanism]," "),$sasl->mechanism))
  2684.                                                                         {
  2685.                                                                                 $response=$this->Tokenize("");
  2686.                                                                                 break;
  2687.                                                                         }
  2688.                                                                 }
  2689.                                                                 if($proxy >= 0)
  2690.                                                                 {
  2691.                                                                         for(;;)
  2692.                                                                         {
  2693.                                                                                 if(strlen($error=$this->ReadReplyBody($body,$this->file_buffer_length)))
  2694.                                                                                         return($error);
  2695.                                                                                 if(strlen($body)==0)
  2696.                                                                                         break;
  2697.                                                                         }
  2698.                                                                 }
  2699.                                                                 $this->state="Connected";
  2700.                                                                 break;
  2701.                                                         case "301":
  2702.                                                         case "302":
  2703.                                                         case "303":
  2704.                                                         case "307":
  2705.                                                                 if($proxy >= 0)
  2706.                                                                         return($this->Redirect($headers));
  2707.                                                         default:
  2708.                                                                 if(intval($this->response_status/100)==2)
  2709.                                                                 {
  2710.                                                                         if($proxy)
  2711.                                                                                 $proxy_authorization=$authorization_value;
  2712.                                                                         $authenticated=1;
  2713.                                                                         break;
  2714.                                                                 }
  2715.                                                                 if($proxy
  2716.                                                                 && !strcmp($this->response_status,"401"))
  2717.                                                                 {
  2718.                                                                         $proxy_authorization=$authorization_value;
  2719.                                                                         $authenticated=1;
  2720.                                                                         break;
  2721.                                                                 }
  2722.                                                                 return($this->SetError(($proxy ? "proxy " : "")."authentication error: ".$this->response_status." ".$this->response_message));
  2723.                                                 }
  2724.                                                 break;
  2725.                                         default:
  2726.                                                 return($this->SetError("Could not process the SASL ".($proxy ? "proxy " : "")."authentication step: ".$sasl->error, self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE));
  2727.                                 }
  2728.                         }
  2729.                 }
  2730.                 return("");
  2731.         }
  2732.  
  2733.         Function ReadReplyHeaders(&$headers)
  2734.         {
  2735.                 if(strlen($error=$this->ReadReplyHeadersResponse($headers)))
  2736.                         return($error);
  2737.                 $proxy_authorization="";
  2738.                 while(!strcmp($this->response_status, "100"))
  2739.                 {
  2740.                         $this->state="RequestSent";
  2741.                         if(strlen($error=$this->ReadReplyHeadersResponse($headers)))
  2742.                                 return($error);
  2743.                 }
  2744.                 switch($this->response_status)
  2745.                 {
  2746.                         case "301":
  2747.                         case "302":
  2748.                         case "303":
  2749.                         case "307":
  2750.                                 if(strlen($error=$this->Redirect($headers)))
  2751.                                         return($error);
  2752.                                 break;
  2753.                         case "407":
  2754.                                 if(strlen($error=$this->Authenticate($headers, 1, $proxy_authorization, $this->proxy_request_user, $this->proxy_request_password, $this->proxy_request_realm, $this->proxy_request_workstation)))
  2755.                                         return($error);
  2756.                                 if(strcmp($this->response_status,"401"))
  2757.                                         return("");
  2758.                         case "401":
  2759.                                 return($this->Authenticate($headers, 0, $proxy_authorization, $this->request_user, $this->request_password, $this->request_realm, $this->request_workstation));
  2760.                 }
  2761.                 return("");
  2762.         }
  2763.  
  2764.         Function ReadReplyBody(&$body,$length)
  2765.         {
  2766.                 $body="";
  2767.                 if(strlen($this->error))
  2768.                         return($this->error);
  2769.                 switch($this->state)
  2770.                 {
  2771.                         case "Disconnected":
  2772.                                 return($this->SetError("connection was not yet established", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2773.                         case "Connected":
  2774.                         case "ConnectedToProxy":
  2775.                                 return($this->SetError("request was not sent", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2776.                         case "RequestSent":
  2777.                                 $headers = array();
  2778.                                 if(($error=$this->ReadReplyHeaders($headers))!="")
  2779.                                         return($error);
  2780.                                 break;
  2781.                         case "GotReplyHeaders":
  2782.                                 break;
  2783.                         case 'ResponseReceived':
  2784.                                 $body = '';
  2785.                                 return('');
  2786.                         default:
  2787.                                 return($this->SetError("can not get request headers in the current connection state", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2788.                 }
  2789.                 if($this->content_length_set)
  2790.                         $length=min($this->content_length-$this->read_length,$length);
  2791.                 $body = '';
  2792.                 if($length>0)
  2793.                 {
  2794.                         if(!$this->EndOfInput()
  2795.                         && ($body=$this->ReadBytes($length))=="")
  2796.                         {
  2797.                                 if(strlen($this->error))
  2798.                                         return($this->SetError("could not get the request reply body: ".$this->error, $this->error_code));
  2799.                         }
  2800.                         $this->read_length+=strlen($body);
  2801.                         if($this->EndOfInput())
  2802.                                 $this->state = 'ResponseReceived';
  2803.                 }
  2804.                 return("");
  2805.         }
  2806.  
  2807.         Function ReadWholeReplyBody(&$body)
  2808.         {
  2809.                 $body = '';
  2810.                 for(;;)
  2811.                 {
  2812.                         $body = '';
  2813.                         $block = '';
  2814.                         if(strlen($error = $this->ReadReplyBody($block, $this->file_buffer_length)))
  2815.                                 return($error);
  2816.                         if(strlen($block) == 0)
  2817.                                 return('');
  2818.                         $body .= $block;
  2819.                 }
  2820.         }
  2821.  
  2822.         Function ReadWholeReplyIntoTemporaryFile(&$file)
  2823.         {
  2824.                 if(!($file = tmpfile())) {
  2825.                         $php_errormsg = '';
  2826.                         return $this->SetPHPError('could not create the temporary file to save the response', $php_errormsg, self::HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE);
  2827.                 }
  2828.                 for(;;)
  2829.                 {
  2830.                         $block = '';
  2831.                         if(strlen($error = $this->ReadReplyBody($block, $this->file_buffer_length)))
  2832.                         {
  2833.                                 fclose($file);
  2834.                                 return($error);
  2835.                         }
  2836.                         if(strlen($block) == 0)
  2837.                         {
  2838.                                 if(@fseek($file, 0) != 0)
  2839.                                 {
  2840.                                         $error = $this->SetPHPError('could not seek to the beginning of temporary file with the response', $php_errormsg, self::HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE);
  2841.                                         fclose($file);
  2842.                                         return $error;
  2843.                                 }
  2844.                                 return('');
  2845.                         }
  2846.                         if(!@fwrite($file, $block))
  2847.                         {
  2848.                                 $php_errormsg = '';
  2849.                                 $error = $this->SetPHPError('could not write to the temporary file to save the response', $php_errormsg, self::HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE);
  2850.                                 fclose($file);
  2851.                                 return $error;
  2852.                         }
  2853.                 }
  2854.         }
  2855.  
  2856.         Function SaveCookies(&$cookies, $domain='', $secure_only=0, $persistent_only=0)
  2857.         {
  2858.                 $now=gmdate("Y-m-d H-i-s");
  2859.                 $cookies=array();
  2860.                 for($secure_cookies=0,Reset($this->cookies);$secure_cookies<count($this->cookies);Next($this->cookies),$secure_cookies++)
  2861.                 {
  2862.                         $secure=Key($this->cookies);
  2863.                         if(!$secure_only
  2864.                         || $secure)
  2865.                         {
  2866.                                 for($cookie_domain=0,Reset($this->cookies[$secure]);$cookie_domain<count($this->cookies[$secure]);Next($this->cookies[$secure]),$cookie_domain++)
  2867.                                 {
  2868.                                         $domain_pattern=Key($this->cookies[$secure]);
  2869.                                         $match=strlen($domain)-strlen($domain_pattern);
  2870.                                         if(strlen($domain)==0
  2871.                                         || ($match>=0
  2872.                                         && !strcmp($domain_pattern,substr($domain,$match))
  2873.                                         && ($match==0
  2874.                                         || $domain_pattern[0]=="."
  2875.                                         || $domain[$match-1]==".")))
  2876.                                         {
  2877.                                                 for(Reset($this->cookies[$secure][$domain_pattern]),$path_part=0;$path_part<count($this->cookies[$secure][$domain_pattern]);Next($this->cookies[$secure][$domain_pattern]),$path_part++)
  2878.                                                 {
  2879.                                                         $path=Key($this->cookies[$secure][$domain_pattern]);
  2880.                                                         for(Reset($this->cookies[$secure][$domain_pattern][$path]),$cookie=0;$cookie<count($this->cookies[$secure][$domain_pattern][$path]);Next($this->cookies[$secure][$domain_pattern][$path]),$cookie++)
  2881.                                                         {
  2882.                                                                 $cookie_name=Key($this->cookies[$secure][$domain_pattern][$path]);
  2883.                                                                 $expires=$this->cookies[$secure][$domain_pattern][$path][$cookie_name]["expires"];
  2884.                                                                 if((!$persistent_only
  2885.                                                                 && strlen($expires)==0)
  2886.                                                                 || (strlen($expires)
  2887.                                                                 && strcmp($now,$expires)<0))
  2888.                                                                         $cookies[$secure][$domain_pattern][$path][$cookie_name]=$this->cookies[$secure][$domain_pattern][$path][$cookie_name];
  2889.                                                         }
  2890.                                                 }
  2891.                                         }
  2892.                                 }
  2893.                         }
  2894.                 }
  2895.         }
  2896.  
  2897.         Function SavePersistentCookies(&$cookies, $domain='', $secure_only=0)
  2898.         {
  2899.                 $this->SaveCookies($cookies, $domain, $secure_only, 1);
  2900.         }
  2901.  
  2902.         Function GetPersistentCookies(&$cookies, $domain='', $secure_only=0)
  2903.         {
  2904.                 $this->SavePersistentCookies($cookies, $domain, $secure_only);
  2905.         }
  2906.  
  2907.         Function RestoreCookies($cookies, $clear=1)
  2908.         {
  2909.                 $new_cookies=($clear ? array() : $this->cookies);
  2910.                 for($secure_cookies=0, Reset($cookies); $secure_cookies<count($cookies); Next($cookies), $secure_cookies++)
  2911.                 {
  2912.                         $secure=Key($cookies);
  2913.                         if(GetType($secure)!="integer")
  2914.                                 return($this->SetError("invalid cookie secure value type (".serialize($secure).")", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2915.                         for($cookie_domain=0,Reset($cookies[$secure]);$cookie_domain<count($cookies[$secure]);Next($cookies[$secure]),$cookie_domain++)
  2916.                         {
  2917.                                 $domain_pattern=Key($cookies[$secure]);
  2918.                                 if(GetType($domain_pattern)!="string")
  2919.                                         return($this->SetError("invalid cookie domain value type (".serialize($domain_pattern).")", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2920.                                 for(Reset($cookies[$secure][$domain_pattern]),$path_part=0;$path_part<count($cookies[$secure][$domain_pattern]);Next($cookies[$secure][$domain_pattern]),$path_part++)
  2921.                                 {
  2922.                                         $path=Key($cookies[$secure][$domain_pattern]);
  2923.                                         if(GetType($path)!="string"
  2924.                                         || strcmp(substr($path, 0, 1), "/"))
  2925.                                                 return($this->SetError("invalid cookie path value type (".serialize($path).")", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2926.                                         for(Reset($cookies[$secure][$domain_pattern][$path]),$cookie=0;$cookie<count($cookies[$secure][$domain_pattern][$path]);Next($cookies[$secure][$domain_pattern][$path]),$cookie++)
  2927.                                         {
  2928.                                                 $cookie_name=Key($cookies[$secure][$domain_pattern][$path]);
  2929.                                                 $expires=$cookies[$secure][$domain_pattern][$path][$cookie_name]["expires"];
  2930.                                                 $value=$cookies[$secure][$domain_pattern][$path][$cookie_name]["value"];
  2931.                                                 if(GetType($expires)!="string"
  2932.                                                 || (strlen($expires)
  2933.                                                 && !preg_match("/^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\$/", $expires)))
  2934.                                                         return($this->SetError("invalid cookie expiry value type (".serialize($expires).")", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS));
  2935.                                                 $new_cookies[$secure][$domain_pattern][$path][$cookie_name]=array(
  2936.                                                         "name"=>$cookie_name,
  2937.                                                         "value"=>$value,
  2938.                                                         "domain"=>$domain_pattern,
  2939.                                                         "path"=>$path,
  2940.                                                         "expires"=>$expires,
  2941.                                                         "secure"=>$secure
  2942.                                                 );
  2943.                                         }
  2944.                                 }
  2945.                         }
  2946.                 }
  2947.                 $this->cookies=$new_cookies;
  2948.                 return("");
  2949.         }
  2950. };
  2951.