PageRenderTime 60ms CodeModel.GetById 31ms RepoModel.GetById 1ms app.codeStats 0ms

/server/php/old.php

https://bitbucket.org/Red54/wallproxy
PHP | 393 lines | 326 code | 55 blank | 12 comment | 82 complexity | be595f4499777461c0e4040f75dfb8f1 MD5 | raw file
  1. <?php
  2. $__author__ = 'phus.lu@gmail.com';
  3. $__version__ = '1.8.9';
  4. $__password__ = '';
  5. function encode_data($dic) {
  6. $a = array();
  7. foreach ($dic as $key => $value) {
  8. if ($value) {
  9. $a[] = $key. '=' . bin2hex($value);
  10. }
  11. }
  12. return join('&', $a);
  13. }
  14. function decode_data($qs) {
  15. $dic = array();
  16. foreach (explode('&', $qs) as $kv) {
  17. $pair = explode('=', $kv, 2);
  18. $dic[$pair[0]] = $pair[1] ? pack('H*', $pair[1]) : '';
  19. }
  20. return $dic;
  21. }
  22. function print_response($status, $headers, $content) {
  23. $strheaders = encode_data($headers);
  24. $content_type = isset($headers['content-type']) ? $headers['content-type'] : '';
  25. if ($content_type && (substr($content_type, 0, 5) == 'text/' || substr($content_type, 0, 16) == 'application/json' || substr($content_type, 0, 22) == 'application/javascript')) {
  26. $data = '1' . gzcompress(pack('NNN', $status, strlen($strheaders), strlen($content)) . $strheaders . $content);
  27. } else {
  28. $data = '0' . pack('NNN', $status, strlen($strheaders), strlen($content)) . $strheaders . $content;
  29. }
  30. header('Content-Type: text/html');
  31. header('Content-Length: '.strlen($data));
  32. print($data);
  33. }
  34. function print_notify($method, $url, $status, $content) {
  35. $content = "<h2>PHP Server Fetch Info</h2><hr noshade='noshade'><p>$method '$url'</p><p>Return Code: $status</p><p>Message: $content</p>";
  36. $headers = array('content-type' => 'text/html');
  37. print_response($status, $headers, $content);
  38. }
  39. function error_exit() {
  40. $status = 200;
  41. $headers = array('content-type' => 'text/html');
  42. $content = "<h2>PHP Server Debug Info</h2><hr noshade='noshade'>";
  43. foreach (func_get_args() as $key => $value) {
  44. $content .= '<p>' . var_export($value, true) . '</p>';
  45. }
  46. print_response($status, $headers, $content);
  47. exit(0);
  48. }
  49. class URLFetch {
  50. protected $body_maxsize = 4194304;
  51. protected $headers = array();
  52. protected $body = '';
  53. protected $body_size = 0;
  54. function __construct() {
  55. }
  56. function urlfetch_curl_readheader($ch, $header) {
  57. $kv = array_map('trim', explode(':', $header, 2));
  58. if (isset($kv[1])) {
  59. $key = strtolower($kv[0]);
  60. $value = $kv[1];
  61. if ($key == 'set-cookie') {
  62. if (!array_key_exists('set-cookie', $this->headers)) {
  63. $this->headers['set-cookie'] = $value;
  64. } else {
  65. $this->headers['set-cookie'] .= "\r\nSet-Cookie: " . $value;
  66. }
  67. } else {
  68. $this->headers[$key] = $kv[1];
  69. }
  70. }
  71. return strlen($header);
  72. }
  73. function urlfetch_curl_readbody($ch, $data) {
  74. $bytes = strlen($data);
  75. if ($this->body_size + $bytes > $this->body_maxsize) {
  76. return -1;
  77. }
  78. $this->body_size += $bytes;
  79. $this->body .= $data;
  80. return $bytes;
  81. }
  82. function urlfetch_curl($url, $payload, $method, $headers, $follow_redirects, $deadline, $validate_certificate) {
  83. $this->headers = array();
  84. $this->body = '';
  85. $this->body_size = 0;
  86. if ($payload) {
  87. $headers['content-length'] = strval(strlen($payload));
  88. }
  89. $headers['connection'] = 'close';
  90. $curl_opt = array();
  91. $curl_opt[CURLOPT_TIMEOUT] = $deadline;
  92. $curl_opt[CURLOPT_CONNECTTIMEOUT] = $deadline;
  93. $curl_opt[CURLOPT_RETURNTRANSFER] = true;
  94. $curl_opt[CURLOPT_BINARYTRANSFER] = true;
  95. $curl_opt[CURLOPT_FAILONERROR] = true;
  96. if (!$follow_redirects) {
  97. $curl_opt[CURLOPT_FOLLOWLOCATION] = false;
  98. }
  99. if ($deadline) {
  100. $curl_opt[CURLOPT_CONNECTTIMEOUT] = $deadline;
  101. $curl_opt[CURLOPT_TIMEOUT] = $deadline;
  102. }
  103. if (!$validate_certificate) {
  104. $curl_opt[CURLOPT_SSL_VERIFYPEER] = false;
  105. $curl_opt[CURLOPT_SSL_VERIFYHOST] = false;
  106. }
  107. switch (strtoupper($method)) {
  108. case 'HEAD':
  109. $curl_opt[CURLOPT_NOBODY] = true;
  110. break;
  111. case 'GET':
  112. break;
  113. case 'POST':
  114. $curl_opt[CURLOPT_POST] = true;
  115. $curl_opt[CURLOPT_POSTFIELDS] = $payload;
  116. break;
  117. case 'PUT':
  118. case 'DELETE':
  119. $curl_opt[CURLOPT_CUSTOMREQUEST] = $method;
  120. $curl_opt[CURLOPT_POSTFIELDS] = $payload;
  121. break;
  122. default:
  123. print_notify($method, $url, 501, 'Invalid Method');
  124. exit(-1);
  125. }
  126. $header_array = array();
  127. foreach ($headers as $key => $value) {
  128. if ($key) {
  129. $header_array[] = join('-', array_map('ucfirst', explode('-', $key))).': '.$value;
  130. }
  131. }
  132. $curl_opt[CURLOPT_HTTPHEADER] = $header_array;
  133. $curl_opt[CURLOPT_HEADER] = false;
  134. $curl_opt[CURLOPT_HEADERFUNCTION] = array(&$this, 'urlfetch_curl_readheader');
  135. $curl_opt[CURLOPT_WRITEFUNCTION] = array(&$this, 'urlfetch_curl_readbody');
  136. //error_exit('curl_opt:', $curl_opt);
  137. $ch = curl_init($url);
  138. curl_setopt_array($ch, $curl_opt);
  139. $ret = curl_exec($ch);
  140. $status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  141. $errno = curl_errno($ch);
  142. if ($errno)
  143. {
  144. $error = $errno . ': ' .curl_error($ch);
  145. } else {
  146. $error = '';
  147. }
  148. curl_close($ch);
  149. $this->headers['connection'] = 'close';
  150. $content_length = isset($this->headers["content-length"]) ? 1*$this->headers["content-length"] : 0;
  151. if ($status_code == 200 && $errno == 23 && $content_length && $this->body_size < $content_length) {
  152. //error_exit($status_code, $this->headers, strlen($this->body));
  153. $status_code = 206;
  154. $range_end = $this->body_size - 1;
  155. $this->headers["content-range"] = "bytes 0-$range_end/$content_length";
  156. $this->headers["accept-ranges"] = "bytes";
  157. $this->headers["content-length"] = $this->body_size;
  158. }
  159. //error_exit('urlfetch result:', array('status_code' => $status_code, 'headers' => $this->headers, 'content-size' => $this->body_size, 'error' => $error));
  160. $response = array('status_code' => $status_code, 'headers' => $this->headers, 'content' => $this->body, 'error' => $error);
  161. return $response;
  162. }
  163. function urlfetch_fopen($url, $payload, $method, $headers, $follow_redirects, $deadline, $validate_certificate) {
  164. $this->headers = array();
  165. $this->body = '';
  166. $this->body_size = 0;
  167. if ($payload) {
  168. $headers['content-length'] = strval(strlen($payload));
  169. }
  170. $headers['connection'] = 'close';
  171. $header_string = '';
  172. foreach ($headers as $key => $value) {
  173. if ($key) {
  174. $header_string .= join('-', array_map('ucfirst', explode('-', $key))).': '.$value."\r\n";
  175. }
  176. }
  177. //error_exit('header_string:', $header_string);
  178. $opt = array();
  179. $opt['http'] = array();
  180. $opt['http']['method'] = $method;
  181. $opt['http']['header'] = $header_string;
  182. if ($payload) {
  183. $opt['http']['content'] = $payload;
  184. }
  185. $opt['http']['timeout'] = $deadline;
  186. $opt['ssl'] = array();
  187. $opt['ssl']['ciphers'] = 'ALL:!AES:!3DES:!RC4:@STRENGTH';
  188. if (!$follow_redirects) {
  189. $opt['http']['follow_location'] = false;
  190. }
  191. if (!$validate_certificate) {
  192. $opt['ssl']['verify_peer'] = false;
  193. $opt['ssl']['capture_peer_cert'] = false;
  194. }
  195. $context = stream_context_create($opt);
  196. if ($context == false) {
  197. return array('status_code' => 500, 'error' => "stream_context_create fail");
  198. }
  199. $fp = @fopen($url, 'rb', false, $context);
  200. if ($fp == false) {
  201. return array('status_code' => 500, 'error' => "fopen $url fail");
  202. }
  203. $meta = stream_get_meta_data($fp);
  204. if ($meta == false) {
  205. return array('status_code' => 500, 'error' => "stream_get_meta_data $url fail");
  206. }
  207. //error_exit('meta_data', $meta);
  208. $response_terms = explode(' ', array_shift($meta['wrapper_data']), 3);
  209. $status_code = intval($response_terms[1]);
  210. foreach($meta['wrapper_data'] as $line) {
  211. $kv = array_map('trim', explode(':', $line, 2));
  212. if ($kv[1]) {
  213. $key = strtolower($kv[0]);
  214. $value = $kv[1];
  215. if ($key == 'set-cookie') {
  216. if (!array_key_exists('set-cookie', $this->headers)) {
  217. $this->headers['set-cookie'] = $value;
  218. } else {
  219. $this->headers['set-cookie'] .= "\r\nset-cookie: " . $value;
  220. }
  221. } else {
  222. $this->headers[$key] = $kv[1];
  223. }
  224. }
  225. }
  226. $content = @file_get_contents($url, false, $context);
  227. if ($content == false) {
  228. return array('status_code' => 500, 'error' => "file_get_contents $url fail");
  229. }
  230. $this->body_size = strlen($content);
  231. $this->body = $content;
  232. $this->headers['connection'] = 'close';
  233. $content_length = isset($this->headers["content-length"]) ? 1*$this->headers["content-length"] : 0;
  234. if ($status_code == 200 && $this->body_size > $this->body_maxsize && $content_length && $this->body_size < $content_length) {
  235. //error_exit($status_code, $this->headers, strlen($this->body));
  236. $status_code = 206;
  237. $range_end = $this->body_size - 1;
  238. $this->headers["content-range"] = "bytes 0-$range_end/$content_length";
  239. $this->headers["accept-ranges"] = "bytes";
  240. $this->headers["content-length"] = $this->body_size;
  241. }
  242. //error_exit('urlfetch result:', array('status_code' => $status_code, 'headers' => $this->headers, 'content-size' => $this->body_size, 'error' => $error));
  243. $response = array('status_code' => $status_code, 'headers' => $this->headers, 'content' => $this->body, 'error' => $error);
  244. return $response;
  245. }
  246. }
  247. function urlfetch($url, $payload, $method, $headers, $follow_redirects, $deadline, $validate_certificate) {
  248. $urlfetch = new URLFetch();
  249. if(function_exists('curl_version')) {
  250. return $urlfetch->urlfetch_curl($url, $payload, $method, $headers, $follow_redirects, $deadline, $validate_certificate);
  251. } else {
  252. //error_exit('urlfetch', "Enter urlfetch_fopen($url, $payload, $method, $headers, $follow_redirects, $deadline, $validate_certificate)");
  253. return $urlfetch->urlfetch_fopen($url, $payload, $method, $headers, $follow_redirects, $deadline, $validate_certificate);
  254. }
  255. }
  256. function post()
  257. {
  258. global $__password__;
  259. $request = @gzuncompress(@file_get_contents('php://input'));
  260. if ($request === False) {
  261. return print_notify($method, $url, 500, 'OOPS! gzuncompress php://input error!');
  262. }
  263. $request = decode_data($request);
  264. $method = $request['method'];
  265. $url = $request['url'];
  266. $payload = $request['payload'];
  267. $dns = isset($request['dns']) ? $request['dns'] : '';
  268. $password = isset($request['password']) ? $request['password'] : '';
  269. if ($__password__ && $__password__ != $password) {
  270. #return print_notify($method, $url, 403, 'Wrong password.');
  271. # prevent GFW detect
  272. return get();
  273. }
  274. if (substr($url, 0, 4) != 'http') {
  275. return print_notify($method, $url, 501, 'Unsupported Scheme');
  276. }
  277. $FetchMax = 3;
  278. $FetchMaxSize = 1024*1024;
  279. $Deadline = array(0 => 16, 1 => 32);
  280. $deadline = $Deadline[0];
  281. $headers = array();
  282. foreach (explode("\r\n", $request['headers']) as $line) {
  283. $pair = explode(':', $line, 2);
  284. if (count($pair) == 2) {
  285. $headers[trim(strtolower($pair[0]))] = trim($pair[1]);
  286. }
  287. }
  288. $headers['connection'] = 'close';
  289. $fetchrange = 'bytes=0-' . strval($FetchMaxSize - 1);
  290. if (array_key_exists('range', $headers)) {
  291. preg_match('/(\d+)?-(\d+)?/', $headers['range'], $matches, PREG_OFFSET_CAPTURE);
  292. $start = $matches[1][0];
  293. $end = $matches[2][0];
  294. if ($start || $end) {
  295. if (!$start and intval($end) > $FetchMaxSize) {
  296. $end = '1023';
  297. }
  298. else if (!$end || intval($end)-intval($start)+1 > $FetchMaxSize) {
  299. $end = strval($FetchMaxSize-1+intval($start));
  300. }
  301. $fetchrange = 'bytes='.$start.'-'.$end;
  302. }
  303. }
  304. if ($dns) {
  305. preg_match('@://(.+?)[:/]@', $url, $matches, PREG_OFFSET_CAPTURE);
  306. if ($matches[1][0]) {
  307. $headers['host'] = $matches[1][0];
  308. $url = preg_replace('@://.+?([:/])@', "://$dns\\1", $url);
  309. }
  310. //error_exit('matches', $matches);
  311. }
  312. //error_exit('url', $url, 'headers:', $headers);
  313. $errors = array();
  314. for ($i = 0; $i < $FetchMax; $i++) {
  315. $response = urlfetch($url, $payload, $method, $headers, False, $deadline, False);
  316. $status_code = $response['status_code'];
  317. if (200 <= $status_code && $status_code < 400) {
  318. return print_response($status_code, $response['headers'], $response['content']);
  319. } else {
  320. if ($response['error']) {
  321. $errors[] = $response['error'];
  322. } else {
  323. $errors[] = 'URLError: ' . $status_code;
  324. }
  325. }
  326. }
  327. print_notify($request['method'], $request['url'], 502, 'PHP Server Fetch Failed: ' . var_export($errors, true));
  328. }
  329. function get() {
  330. }
  331. function main() {
  332. if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  333. post();
  334. } else {
  335. get();
  336. }
  337. }
  338. main();