Rev 277 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
171 | daniel-mar | 1 | <?php |
2 | |||
3 | /* |
||
386 | daniel-mar | 4 | * This file includes: |
5 | * |
||
6 | * 1. PHP HTTP protocol client: HTTP client to access Web site pages |
||
171 | daniel-mar | 7 | * by Manuel Lemos |
8 | * http://www.phpclasses.org/httpclient |
||
9 | * License: BSD License |
||
10 | * |
||
386 | daniel-mar | 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 | * |
||
171 | daniel-mar | 793 | * @(#) $Header: /opt2/ena/metal/http/http.php,v 1.94 2016/05/03 02:07:04 mlemos Exp $ |
794 | * |
||
795 | */ |
||
796 | |||
251 | daniel-mar | 797 | class http_class { |
171 | daniel-mar | 798 | |
269 | daniel-mar | 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; |
||
171 | daniel-mar | 807 | |
251 | daniel-mar | 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'; |
||
171 | daniel-mar | 815 | |
251 | daniel-mar | 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 | |||
171 | daniel-mar | 865 | /* private variables - DO NOT ACCESS */ |
866 | |||
251 | daniel-mar | 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( |
||
171 | daniel-mar | 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"); |
||
251 | daniel-mar | 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; |
||
171 | daniel-mar | 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 | { |
||
386 | daniel-mar | 911 | $found = null; |
171 | daniel-mar | 912 | if(GetType($position=strpos($string,$separator[$character]))=="integer") |
386 | daniel-mar | 913 | $found=(!is_null($found) ? min($found,$position) : $position); |
171 | daniel-mar | 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 | |||
251 | daniel-mar | 932 | Function SetError($error, $error_code = self::HTTP_CLIENT_ERROR_UNSPECIFIED_ERROR) |
171 | daniel-mar | 933 | { |
934 | $this->error_code = $error_code; |
||
935 | return($this->error=$error); |
||
936 | } |
||
937 | |||
251 | daniel-mar | 938 | Function SetPHPError($error, &$php_error_message, $error_code = self::HTTP_CLIENT_ERROR_UNSPECIFIED_ERROR) |
171 | daniel-mar | 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; |
||
251 | daniel-mar | 949 | $this->error_code = self::HTTP_CLIENT_ERROR_COMMUNICATION_FAILURE; |
171 | daniel-mar | 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)) |
||
251 | daniel-mar | 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)); |
171 | daniel-mar | 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))) |
||
251 | daniel-mar | 1178 | return($this->SetError("could not resolve the host domain \"".$domain."\"", self::HTTP_CLIENT_ERROR_INVALID_SERVER_ADDRESS)); |
171 | daniel-mar | 1179 | return(''); |
1180 | } |
||
1181 | |||
1182 | Function Connect($host_name, $host_port, $ssl, $server_type = 'HTTP') |
||
1183 | { |
||
1184 | $domain=$host_name; |
||
1185 | $port = $host_port; |
||
386 | daniel-mar | 1186 | $ip = ''; |
171 | daniel-mar | 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; |
||
386 | daniel-mar | 1214 | $errno = -1; |
171 | daniel-mar | 1215 | if(($this->connection=($this->timeout ? @fsockopen($ip, $port, $errno, $error, $this->timeout) : @fsockopen($ip, $port, $errno)))==0) |
1216 | { |
||
251 | daniel-mar | 1217 | $error_code = self::HTTP_CLIENT_ERROR_CANNOT_CONNECT; |
171 | daniel-mar | 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: |
||
386 | daniel-mar | 1231 | $php_errormsg = ''; |
171 | daniel-mar | 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 = ''; |
||
251 | daniel-mar | 1372 | $this->error_code = self::HTTP_CLIENT_ERROR_NO_ERROR; |
171 | daniel-mar | 1373 | $arguments=array(); |
1374 | $url = str_replace(' ', '%20', $url); |
||
1375 | $parameters=@parse_url($url); |
||
1376 | if(!$parameters) |
||
251 | daniel-mar | 1377 | return($this->SetError("it was not specified a valid URL", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 1378 | if(!IsSet($parameters["scheme"])) |
251 | daniel-mar | 1379 | return($this->SetError("it was not specified the protocol type argument", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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"])) |
||
251 | daniel-mar | 1390 | return($this->SetError("it was not specified the connection host argument", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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"])))) |
||
251 | daniel-mar | 1408 | return($this->SetError("it was not specified a valid connection host argument", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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); |
||
251 | daniel-mar | 1425 | $error_code = self::HTTP_CLIENT_ERROR_UNSPECIFIED_ERROR; |
171 | daniel-mar | 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: |
||
251 | daniel-mar | 1453 | return($this->SetError("it was not specified a valid connection protocol", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 1454 | } |
1455 | if(strlen($this->proxy_host_name)==0) |
||
1456 | { |
||
1457 | if(strlen($this->host_name)==0) |
||
251 | daniel-mar | 1458 | return($this->SetError("it was not specified a valid hostname", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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)) |
||
251 | daniel-mar | 1472 | return($this->SetError('establishing SSL connections via a SOCKS server is not yet supported', self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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"]; |
||
386 | daniel-mar | 1792 | /* |
171 | daniel-mar | 1793 | if(IsSet($php_errormsg) |
1794 | && strlen($php_errormsg)) |
||
1795 | $error.=": ".$php_errormsg; |
||
386 | daniel-mar | 1796 | */ |
171 | daniel-mar | 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); |
||
386 | daniel-mar | 1844 | $php_errormsg = ''; |
251 | daniel-mar | 1845 | $this->SetPHPError('it was not possible to start a SSL encrypted connection via this proxy', $php_errormsg, self::HTTP_CLIENT_ERROR_COMMUNICATION_FAILURE); |
171 | daniel-mar | 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: |
||
251 | daniel-mar | 1857 | return($this->SetError("unable to send request via proxy", self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE)); |
171 | daniel-mar | 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": |
||
251 | daniel-mar | 1885 | return($this->SetError("connection was not yet established", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 1886 | case "Connected": |
1887 | $connect = 0; |
||
1888 | break; |
||
1889 | case "ConnectedToProxy": |
||
386 | daniel-mar | 1890 | $headers = array(); |
171 | daniel-mar | 1891 | if(strlen($error = $this->ConnectFromProxy($arguments, $headers))) |
1892 | return($error); |
||
1893 | $connect = 1; |
||
1894 | break; |
||
1895 | default: |
||
251 | daniel-mar | 1896 | return($this->SetError("can not send request in the current connection state", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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) |
||
251 | daniel-mar | 1916 | return($this->SetError("it was not specified a valid request method", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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)!="/") |
||
251 | daniel-mar | 1921 | return($this->SetError("it was not specified a valid request URI", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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") |
||
251 | daniel-mar | 1946 | return($this->SetError("it was not specified a valid POST method values array", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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 | { |
||
386 | daniel-mar | 1962 | $definition = array(); |
171 | daniel-mar | 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") |
||
251 | daniel-mar | 1986 | return($this->SetError("it was not specified a valid POST method values array", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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 | { |
||
386 | daniel-mar | 2026 | if(!($file=@fopen($stream[$part]["File"],"rb"))) { |
2027 | $php_errormsg = ''; |
||
251 | daniel-mar | 2028 | return($this->SetPHPError("could not open upload file ".$stream[$part]["File"], $php_errormsg, self::HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE)); |
386 | daniel-mar | 2029 | } |
171 | daniel-mar | 2030 | while(!feof($file)) |
2031 | { |
||
2032 | if(GetType($block=@fread($file,$this->file_buffer_length))!="string") |
||
2033 | { |
||
251 | daniel-mar | 2034 | $error=$this->SetPHPError("could not read body stream file ".$stream[$part]["File"], $php_errormsg, self::HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE); |
171 | daniel-mar | 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 | { |
||
386 | daniel-mar | 2083 | $m = array(); |
171 | daniel-mar | 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'])) |
||
251 | daniel-mar | 2138 | return($this->SetError("Streaming request data is not supported when using Curl", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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 | { |
||
386 | daniel-mar | 2149 | $php_errormsg = ''; |
251 | daniel-mar | 2150 | $this->SetPHPError("could not open upload file ".$post_parts[$part]["FILENAME"], $php_errormsg, self::HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE); |
171 | daniel-mar | 2151 | $success=0; |
2152 | break; |
||
2153 | } |
||
2154 | while(!feof($file)) |
||
2155 | { |
||
2156 | if(GetType($block=@fread($file,$this->file_buffer_length))!="string") |
||
2157 | { |
||
251 | daniel-mar | 2158 | $this->SetPHPError("could not read upload file", $php_errormsg, self::HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE); |
171 | daniel-mar | 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); |
||
239 | daniel-mar | 2184 | if(!($success=(strlen($this->response=@curl_exec($this->connection))!=0))) |
171 | daniel-mar | 2185 | { |
2186 | $error=curl_error($this->connection); |
||
251 | daniel-mar | 2187 | $this->SetError("Could not execute the request".(strlen($error) ? ": ".$error : ""), self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE); |
171 | daniel-mar | 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 | { |
||
251 | daniel-mar | 2219 | $this->SetPHPError("could not open upload file ".$post_parts[$part]["FILENAME"], $php_errormsg, self::HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE); |
171 | daniel-mar | 2220 | $success=0; |
2221 | break; |
||
2222 | } |
||
2223 | while(!feof($file)) |
||
2224 | { |
||
2225 | if(GetType($block=@fread($file,$this->file_buffer_length))!="string") |
||
2226 | { |
||
251 | daniel-mar | 2227 | $this->SetPHPError("could not read upload file", $php_errormsg, self::HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE); |
171 | daniel-mar | 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) |
||
251 | daniel-mar | 2261 | return($this->SetError("it was not specified a valid cookie name", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 2262 | if(strlen($path)==0 |
2263 | || strcmp($path[0],"/")) |
||
251 | daniel-mar | 2264 | return($this->SetError($path." is not a valid path for setting cookie ".$name, self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 2265 | if($domain=="" |
2266 | || !strpos($domain,".",$domain[0]=="." ? 1 : 0)) |
||
251 | daniel-mar | 2267 | return($this->SetError($domain." is not a valid domain for setting cookie ".$name, self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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": |
||
251 | daniel-mar | 2295 | return($this->SetError("connection was not yet established", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 2296 | case "Connected": |
2297 | case "ConnectedToProxy": |
||
251 | daniel-mar | 2298 | return($this->SetError("request was not sent", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 2299 | case "SendingRequestBody": |
2300 | break; |
||
2301 | case "RequestSent": |
||
251 | daniel-mar | 2302 | return($this->SetError("request body was already sent", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 2303 | default: |
251 | daniel-mar | 2304 | return($this->SetError("can not send the request body in the current connection state", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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": |
||
251 | daniel-mar | 2332 | return($this->SetError("connection was not yet established", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 2333 | case "Connected": |
251 | daniel-mar | 2334 | return($this->SetError("request was not sent", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 2335 | case "ConnectedToProxy": |
251 | daniel-mar | 2336 | return($this->SetError("connection from the remote server from the proxy was not yet established", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 2337 | case "SendingRequestBody": |
251 | daniel-mar | 2338 | return($this->SetError("request body data was not completely sent", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 2339 | case "ConnectSent": |
2340 | $connect = 1; |
||
2341 | break; |
||
2342 | case "RequestSent": |
||
2343 | $connect = 0; |
||
2344 | break; |
||
2345 | default: |
||
251 | daniel-mar | 2346 | return($this->SetError("can not get request headers in the current connection state", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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 | { |
||
386 | daniel-mar | 2358 | $matches = array(); |
171 | daniel-mar | 2359 | if(!preg_match($match="/^http\\/[0-9]+\\.[0-9]+[ \t]+([0-9]+)[ \t]*(.*)\$/i",$line,$matches)) |
251 | daniel-mar | 2360 | return($this->SetError("it was received an unexpected HTTP response status", self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE)); |
171 | daniel-mar | 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) |
||
251 | daniel-mar | 2372 | return($this->SetError("it was not received HTTP response status", self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE)); |
171 | daniel-mar | 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)) |
||
251 | daniel-mar | 2466 | return($this->SetError("it was received a redirect without location URL", self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE)); |
171 | daniel-mar | 2467 | if(strcmp($location[0],"/")) |
2468 | { |
||
2469 | if(!($location_arguments=@parse_url($location))) |
||
251 | daniel-mar | 2470 | return($this->SetError("the server did not return a valid redirection location URL", self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE)); |
171 | daniel-mar | 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; |
||
386 | daniel-mar | 2476 | $arguments = array(); |
171 | daniel-mar | 2477 | $error=$this->GetRequestArguments($location,$arguments); |
2478 | if(strlen($error)) |
||
251 | daniel-mar | 2479 | return($this->SetError("could not process redirect url: ".$error, self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE)); |
171 | daniel-mar | 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"; |
||
251 | daniel-mar | 2489 | $this->error_code = self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE; |
171 | daniel-mar | 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")) |
||
251 | daniel-mar | 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)); |
171 | daniel-mar | 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 | { |
||
386 | daniel-mar | 2556 | $message = null; |
2557 | $interactions = null; |
||
171 | daniel-mar | 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: |
||
251 | daniel-mar | 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)); |
171 | daniel-mar | 2567 | default: |
251 | daniel-mar | 2568 | return($this->SetError("Could not start the SASL ".($proxy ? "proxy " : "")."authentication client: ".$sasl->error, self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 2569 | } |
2570 | if($proxy >= 0) |
||
2571 | { |
||
2572 | for(;;) |
||
2573 | { |
||
386 | daniel-mar | 2574 | $body = ''; |
171 | daniel-mar | 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 | } |
||
251 | daniel-mar | 2644 | return($this->SetError(($proxy ? "proxy " : "")."authentication error: ".$this->response_status." ".$this->response_message, self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE)); |
171 | daniel-mar | 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: |
||
251 | daniel-mar | 2726 | return($this->SetError("Could not process the SASL ".($proxy ? "proxy " : "")."authentication step: ".$sasl->error, self::HTTP_CLIENT_ERROR_PROTOCOL_FAILURE)); |
171 | daniel-mar | 2727 | } |
2728 | } |
||
2729 | } |
||
2730 | return(""); |
||
2731 | } |
||
386 | daniel-mar | 2732 | |
171 | daniel-mar | 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": |
||
251 | daniel-mar | 2772 | return($this->SetError("connection was not yet established", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 2773 | case "Connected": |
2774 | case "ConnectedToProxy": |
||
251 | daniel-mar | 2775 | return($this->SetError("request was not sent", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 2776 | case "RequestSent": |
386 | daniel-mar | 2777 | $headers = array(); |
171 | daniel-mar | 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: |
||
251 | daniel-mar | 2787 | return($this->SetError("can not get request headers in the current connection state", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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 | { |
||
386 | daniel-mar | 2812 | $body = ''; |
2813 | $block = ''; |
||
171 | daniel-mar | 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 | { |
||
386 | daniel-mar | 2824 | if(!($file = tmpfile())) { |
2825 | $php_errormsg = ''; |
||
251 | daniel-mar | 2826 | return $this->SetPHPError('could not create the temporary file to save the response', $php_errormsg, self::HTTP_CLIENT_ERROR_CANNOT_ACCESS_LOCAL_FILE); |
386 | daniel-mar | 2827 | } |
171 | daniel-mar | 2828 | for(;;) |
2829 | { |
||
386 | daniel-mar | 2830 | $block = ''; |
171 | daniel-mar | 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 | { |
||
251 | daniel-mar | 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); |
171 | daniel-mar | 2841 | fclose($file); |
2842 | return $error; |
||
2843 | } |
||
2844 | return(''); |
||
2845 | } |
||
2846 | if(!@fwrite($file, $block)) |
||
2847 | { |
||
386 | daniel-mar | 2848 | $php_errormsg = ''; |
251 | daniel-mar | 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); |
171 | daniel-mar | 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") |
||
251 | daniel-mar | 2914 | return($this->SetError("invalid cookie secure value type (".serialize($secure).")", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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") |
||
251 | daniel-mar | 2919 | return($this->SetError("invalid cookie domain value type (".serialize($domain_pattern).")", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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), "/")) |
||
251 | daniel-mar | 2925 | return($this->SetError("invalid cookie path value type (".serialize($path).")", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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))) |
||
251 | daniel-mar | 2934 | return($this->SetError("invalid cookie expiry value type (".serialize($expires).")", self::HTTP_CLIENT_ERROR_INVALID_PARAMETERS)); |
171 | daniel-mar | 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 | }; |