PageRenderTime 32ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/gulliver/thirdparty/pear/HTTP/HTTP.php

https://bitbucket.org/ferOnti/processmaker
PHP | 343 lines | 170 code | 29 blank | 144 comment | 48 complexity | c7b8596c09ad1b7806cd23e4b9426bd9 MD5 | raw file
  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PEAR :: HTTP |
  4. // +----------------------------------------------------------------------+
  5. // | This source file is subject to version 3.0 of the PHP license, |
  6. // | that is available at http://www.php.net/license/3_0.txt |
  7. // | If you did not receive a copy of the PHP license and are unable |
  8. // | to obtain it through the world-wide-web, please send a note to |
  9. // | license@php.net so we can mail you a copy immediately. |
  10. // +----------------------------------------------------------------------+
  11. // | Authors: Stig Bakken <ssb@fast.no> |
  12. // | Sterling Hughes <sterling@php.net> |
  13. // | Tomas V.V.Cox <cox@idecnet.com> |
  14. // | Richard Heyes <richard@php.net> |
  15. // | Philippe Jausions <Philippe.Jausions@11abacus.com> |
  16. // | Michael Wallner <mike@php.net> |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: HTTP.php,v 1.35 2004/09/21 15:28:07 mike Exp $
  20. /**
  21. * HTTP
  22. *
  23. * HTTP utility functions
  24. *
  25. * @package HTTP
  26. * @category HTTP
  27. * @license PHP License
  28. * @access public
  29. * @version $Revision: 1.35 $
  30. */
  31. class HTTP
  32. {
  33. /**
  34. * Date
  35. *
  36. * Format a RFC compliant GMT date HTTP header. This function honors the
  37. * "y2k_compliance" php.ini directive and formats the GMT date corresponding
  38. * to either RFC850 or RFC822.
  39. *
  40. * @static
  41. * @access public
  42. * @return mixed GMT date string, or false for an invalid $time parameter
  43. * @param mixed $time unix timestamp or date (default = current time)
  44. */
  45. function Date($time = null)
  46. {
  47. if (!isset($time)) {
  48. $time = time();
  49. } elseif (!is_numeric($time) && (-1 === $time = strtotime($time))) {
  50. return false;
  51. }
  52. // RFC822 or RFC850
  53. $format = ini_get('y2k_compliance') ? 'D, d M Y' : 'l, d-M-y';
  54. return gmdate($format .' H:i:s \G\M\T', $time);
  55. }
  56. /**
  57. * Negotiate Language
  58. *
  59. * Negotiate language with the user's browser through the Accept-Language
  60. * HTTP header or the user's host address. Language codes are generally in
  61. * the form "ll" for a language spoken in only one country, or "ll-CC" for a
  62. * language spoken in a particular country. For example, U.S. English is
  63. * "en-US", while British English is "en-UK". Portugese as spoken in
  64. * Portugal is "pt-PT", while Brazilian Portugese is "pt-BR".
  65. *
  66. * Quality factors in the Accept-Language: header are supported, e.g.:
  67. * Accept-Language: en-UK;q=0.7, en-US;q=0.6, no, dk;q=0.8
  68. *
  69. * <code>
  70. * require_once 'HTTP.php';
  71. * $langs = array(
  72. * 'en' => 'locales/en',
  73. * 'en-US'=> 'locales/en',
  74. * 'en-UK'=> 'locales/en',
  75. * 'de' => 'locales/de',
  76. * 'de-DE'=> 'locales/de',
  77. * 'de-AT'=> 'locales/de',
  78. * );
  79. * $neg = HTTP::negotiateLanguage($langs);
  80. * $dir = $langs[$neg];
  81. * </code>
  82. *
  83. * @static
  84. * @access public
  85. * @return string The negotiated language result or the supplied default.
  86. * @param array $supported An associative array of supported languages,
  87. * whose values must evaluate to true.
  88. * @param string $default The default language to use if none is found.
  89. */
  90. function negotiateLanguage($supported, $default = 'en-US')
  91. {
  92. $supp = array();
  93. foreach ($supported as $lang => $isSupported) {
  94. if ($isSupported) {
  95. $supp[strToLower($lang)] = $lang;
  96. }
  97. }
  98. if (!count($supp)) {
  99. return $default;
  100. }
  101. $matches = array();
  102. if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
  103. foreach (explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']) as $lang) {
  104. @list($l, $q) = array_map('strtolower',
  105. array_map('trim', explode(';', $lang)));
  106. if (isset($supp[$l])) {
  107. if (isset($q)) {
  108. $matches[$l] = (float) str_replace('q=', '', $q);
  109. } else {
  110. $matches[$l] = 1000 - count($matches);
  111. }
  112. }
  113. }
  114. }
  115. if (count($matches)) {
  116. asort($matches, SORT_NUMERIC);
  117. return $supp[array_pop(array_keys($matches))];
  118. }
  119. if (isset($_SERVER['REMOTE_HOST'])) {
  120. $lang = strtolower(array_pop(explode('.', $_SERVER['REMOTE_HOST'])));
  121. if (isset($supp[$lang])) {
  122. return $supp[$lang];
  123. }
  124. }
  125. return $default;
  126. }
  127. /**
  128. * Head
  129. *
  130. * Sends a "HEAD" HTTP command to a server and returns the headers
  131. * as an associative array. Example output could be:
  132. * <code>
  133. * Array
  134. * (
  135. * [response_code] => 200 // The HTTP response code
  136. * [response] => HTTP/1.1 200 OK // The full HTTP response string
  137. * [Date] => Fri, 11 Jan 2002 01:41:44 GMT
  138. * [Server] => Apache/1.3.20 (Unix) PHP/4.1.1
  139. * [X-Powered-By] => PHP/4.1.1
  140. * [Connection] => close
  141. * [Content-Type] => text/html
  142. * )
  143. * </code>
  144. *
  145. * @see HTTP_Client::head()
  146. * @see HTTP_Request
  147. *
  148. * @static
  149. * @access public
  150. * @return mixed Returns associative array of response headers on success
  151. * or PEAR error on failure.
  152. * @param string $url A valid URL, e.g.: http://pear.php.net/credits.php
  153. * @param integer $timeout Timeout in seconds (default = 10)
  154. */
  155. function head($url, $timeout = 10)
  156. {
  157. $p = parse_url($url);
  158. if (!isset($p['scheme'])) {
  159. $p = parse_url(HTTP::absoluteURI($url));
  160. } elseif ($p['scheme'] != 'http') {
  161. return HTTP::raiseError('Unsupported protocol: '. $p['scheme']);
  162. }
  163. $port = isset($p['port']) ? $p['port'] : 80;
  164. if (!$fp = @fsockopen($p['host'], $port, $eno, $estr, $timeout)) {
  165. return HTTP::raiseError("Connection error: $estr ($eno)");
  166. }
  167. $path = !empty($p['path']) ? $p['path'] : '/';
  168. $path .= !empty($p['query']) ? '?' . $p['query'] : '';
  169. fputs($fp, "HEAD $path HTTP/1.0\r\n");
  170. fputs($fp, 'Host: ' . $p['host'] . ':' . $port . "\r\n");
  171. fputs($fp, "Connection: close\r\n\r\n");
  172. $response = rtrim(fgets($fp, 4096));
  173. if (preg_match("|^HTTP/[^\s]*\s(.*?)\s|", $response, $status)) {
  174. $headers['response_code'] = $status[1];
  175. }
  176. $headers['response'] = $response;
  177. while ($line = fgets($fp, 4096)) {
  178. if (!trim($line)) {
  179. break;
  180. }
  181. if (($pos = strpos($line, ':')) !== false) {
  182. $header = substr($line, 0, $pos);
  183. $value = trim(substr($line, $pos + 1));
  184. $headers[$header] = $value;
  185. }
  186. }
  187. fclose($fp);
  188. return $headers;
  189. }
  190. /**
  191. * Redirect
  192. *
  193. * This function redirects the client. This is done by issuing
  194. * a "Location" header and exiting if wanted. If you set $rfc2616 to true
  195. * HTTP will output a hypertext note with the location of the redirect.
  196. *
  197. * @static
  198. * @access public
  199. * @return mixed Returns true on succes (or exits) or false if headers
  200. * have already been sent.
  201. * @param string $url URL where the redirect should go to.
  202. * @param bool $exit Whether to exit immediately after redirection.
  203. * @param bool $rfc2616 Wheter to output a hypertext note where we're
  204. * redirecting to (Redirecting to <a href="...">...</a>.)
  205. */
  206. function redirect($url, $exit = true, $rfc2616 = false)
  207. {
  208. if (headers_sent()) {
  209. return false;
  210. }
  211. $url = HTTP::absoluteURI($url);
  212. header('Location: '. $url);
  213. if ($rfc2616 && @$_SERVER['REQUEST_METHOD'] != 'HEAD') {
  214. printf('Redirecting to: <a href="%s">%s</a>.', $url, $url);
  215. }
  216. if ($exit) {
  217. exit;
  218. }
  219. return true;
  220. }
  221. /**
  222. * Absolute URI
  223. *
  224. * This function returns the absolute URI for the partial URL passed.
  225. * The current scheme (HTTP/HTTPS), host server, port, current script
  226. * location are used if necessary to resolve any relative URLs.
  227. *
  228. * Offsets potentially created by PATH_INFO are taken care of to resolve
  229. * relative URLs to the current script.
  230. *
  231. * You can choose a new protocol while resolving the URI. This is
  232. * particularly useful when redirecting a web browser using relative URIs
  233. * and to switch from HTTP to HTTPS, or vice-versa, at the same time.
  234. *
  235. * @author Philippe Jausions <Philippe.Jausions@11abacus.com>
  236. * @static
  237. * @access public
  238. * @return string The absolute URI.
  239. * @param string $url Absolute or relative URI the redirect should go to.
  240. * @param string $protocol Protocol to use when redirecting URIs.
  241. * @param integer $port A new port number.
  242. */
  243. function absoluteURI($url = null, $protocol = null, $port = null)
  244. {
  245. // Mess around with already absolute URIs
  246. if (preg_match('!^([a-z0-9]+)://!i', $url)) {
  247. if (empty($protocol) && empty($port)) {
  248. return $url;
  249. }
  250. if (!empty($protocol)) {
  251. $url = $protocol .':'. array_pop(explode(':', $url, 2));
  252. }
  253. if (!empty($port)) {
  254. $url = preg_replace('!^(([a-z0-9]+)://[^/:]+)(:[\d]+)?!i',
  255. '\1:'. $port, $url);
  256. }
  257. return $url;
  258. }
  259. $host = 'localhost';
  260. if (!empty($_SERVER['HTTP_HOST'])) {
  261. list($host) = explode(':', $_SERVER['HTTP_HOST']);
  262. } elseif (!empty($_SERVER['SERVER_NAME'])) {
  263. list($host) = explode(':', $_SERVER['SERVER_NAME']);
  264. }
  265. if (empty($protocol)) {
  266. $protocol = isset($_SERVER['HTTPS']) ? 'https' : 'http';
  267. if (!isset($port) || $port != intval($port)) {
  268. $port = isset($_SERVER['SERVER_PORT']) ? $_SERVER['SERVER_PORT'] : 80;
  269. }
  270. }
  271. if ($protocol == 'http' && $port == 80) {
  272. unset($port);
  273. }
  274. if ($protocol == 'https' && $port == 443) {
  275. unset($port);
  276. }
  277. $server = $protocol .'://'. $host . (isset($port) ? ':'. $port : '');
  278. if (!strlen($url)) {
  279. $url = isset($_SERVER['REQUEST_URI']) ?
  280. $_SERVER['REQUEST_URI'] : $_SERVER['PHP_SELF'];
  281. }
  282. if ($url{0} == '/') {
  283. return $server . $url;
  284. }
  285. // Check for PATH_INFO
  286. if (isset($_SERVER['PATH_INFO'])) {
  287. $path = dirname(substr($_SERVER['PHP_SELF'], 0, -strlen($_SERVER['PATH_INFO'])));
  288. } else {
  289. $path = dirname($_SERVER['PHP_SELF']);
  290. }
  291. if (substr($path, -1) != '/') {
  292. $path .= '/';
  293. }
  294. return $server . strtr($path, '\\', '/') . $url;
  295. }
  296. /**
  297. * Raise Error
  298. *
  299. * Lazy raising of PEAR_Errors.
  300. *
  301. * @static
  302. * @access protected
  303. * @return object PEAR_Error
  304. * @param mixed $error
  305. * @param int $code
  306. */
  307. function raiseError($error = null, $code = null)
  308. {
  309. require_once 'PEAR.php';
  310. return PEAR::raiseError($error, $code);
  311. }
  312. }
  313. ?>