fixed small port fail in HTTPConnector.class.php
[CodeSnippets.git] / PHP / HTTPConnector.class.php
1 <?php
2 /* HTTPConnector.class.php - HTTP Connector Class
3  * Copyright (C) 2011-2013  Philipp Kreil (pk910)
4  * 
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License 
16  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
17  */
18
19 class HTTPConnector {
20         private $cookies = array();
21         public $debug = false;
22         
23         private $default_header = array(
24                         "Accept-Encoding" => "deflate",
25                         "Accept-Language" => "de-DE",
26                         "User-Agent" => "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0",
27                         "Connection" => "Keep-Alive",
28                         "Cache-Control" => "no-cache",
29                 );
30         
31         private function fputs($fp, $line) {
32                 if($this->debug)
33                         echo $line;
34                 fputs($fp, $line);
35         }
36         
37         private function create_request($host) {
38                 if(!preg_match('#^((http|https)://|)(([a-zA-Z0-9][a-zA-Z0-9_-]+[a-zA-Z0-9]\.)+[a-zA-Z]{2,5}|[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})(:([0-9]{1,5})|)(/.*|)$#', $host, $matches))
39                         return null;
40                 if(empty($matches[3]))
41                         return null;
42                 $request = array();
43                 $request['host'] = $matches[3];
44                 $request['ssl'] = (strtolower($matches[2]) == "https");
45                 $request['port'] = ($matches[6] ? $matches[6] : ($request['ssl'] ? 443 : 80));
46                 $request['path'] = ($matches[7] ? $matches[7] : "/");
47                 $request['header'] = $this->default_header;
48                 $request['header_only'] = false;
49                 $this->set_header($request, "Host", $request['host']);
50                 
51                 $host = ($request['ssl'] ? "ssl://" : "").$request['host'];
52                 $request['fp'] = fsockopen($host, $request['port']);
53                 return $request;
54         }
55         
56         private function set_header(&$req, $header, $value) {
57                 foreach($req['header'] as $name => $val) {
58                         if(strtolower($name) == strtolower($header)) {
59                                 unset($req['header'][$name]);
60                                 break;
61                         }
62                 }
63                 $req['header'][$header] = $value;
64         }
65         
66         private function send_header($req) {
67                 foreach($req['header'] as $name => $val) {
68                         $this->fputs($req['fp'], $name.": ".$val."\r\n");
69                 }
70                 $cookiestr = NULL;
71                 foreach($this->cookies as $cookiename => $cookievalue) {
72                         if($cookiestr)
73                                 $cookiestr.="; ";
74                         $cookiestr .= $cookiename."=".$cookievalue;
75                 }
76                 if($cookiestr)
77                         $this->fputs($req['fp'], "Cookie: ".$cookiestr."\r\n");
78         }
79         
80         private function process_request(&$req, $data = null) {
81                 $this->fputs($req['fp'], $req['method']." ".$req['path']." HTTP/1.1\r\n");
82                 $this->send_header($req);
83                 $this->fputs($req['fp'], "\r\n");
84                 if($data)
85                         $this->fputs($req['fp'], $data);
86                 
87                 $req['reply_header'] = array();
88                 $req['reply'] = "";
89                 $recv_state = true;
90                 $recv_header = true;
91                 while(!feof($req['fp'])) {
92                         if($recv_header) {
93                                 $recv = fgets($req['fp']);
94                                 if($this->debug)
95                                         echo $recv;
96                                 $line = str_replace(array("\r", "\n"), array("", ""), $recv);
97                                 if($recv_state) {
98                                         $exp = explode(" ", $line, 3);
99                                         $req['state'] = $exp[1];
100                                         $req['state_text'] = $exp[2];
101                                         $recv_state = false;
102                                         continue;
103                                 }
104                                 else if($line == "") {
105                                         $recv_header = false;
106                                         if($req['header_only'])
107                                                 break;
108                                         else
109                                                 continue;
110                                 }
111                                 $line = explode(": ", $line, 2);
112                                 if(strtolower($line[0]) == "set-cookie") {
113                                         $cookie = explode("=", $line[1], 2);
114                                         $cookieval = explode(";", $cookie[1]);
115                                         $this->cookies[$cookie[0]] = $cookieval[0];
116                                 }
117                                 $req['reply_header'][$line[0]] = $line[1];
118                         } else {
119                                 $recv = fread($req['fp'], 512);
120                                 if($this->debug)
121                                         echo $recv;
122                                 $req['reply'] .= $recv;
123                         }
124                 }
125                 if(!$req['header_only'])
126                         fclose($req['fp']);
127         }
128         
129         public function post($host, $post, $full = false) {
130                 $req = $this->create_request($host);
131                 if(!$req)
132                         return null;
133                 $req['method'] = "POST";
134                 
135                 $data = "";
136                 foreach($post as $key => $val) {
137             if(is_array($val)) {
138                 foreach($val as $subval) {
139                     if($data != "") { $data.="&"; }
140                     $data .= urlencode($key)."=".urlencode($subval);
141                 }
142             } else {
143                 if($data != "") { $data.="&"; }
144                 $data .= urlencode($key)."=".urlencode($val);
145             }
146                 }
147                 
148                 $this->set_header($req, "Content-Type", "application/x-www-form-urlencoded");
149                 $this->set_header($req, "Content-Length", strlen($data));
150                 $this->process_request($req, $data);
151                 
152                 if($full)
153                         return $req;
154                 return $req['reply'];
155         }
156         
157         public function get($host, $full) {
158                 $req = $this->create_request($host);
159                 if(!$req)
160                         return null;
161                 $req['method'] = "GET";
162                 
163                 $this->process_request($req);
164                 
165                 if($full)
166                         return $req;
167                 return $req['reply'];
168         }
169         
170         public function connect($host, $target, $full = false) {
171                 $req = $this->create_request($host);
172                 if(!$req)
173                         return null;
174                 $req['method'] = "CONNECT";
175                 $req['path'] = $target;
176                 $req['header_only'] = true;
177                 
178                 $this->process_request($req);
179                 
180                 if($full)
181                         return $req;
182                 return ($req['state'] == "200" ? $req['fp'] : NULL);
183         }
184         
185 }
186
187 ?>