PageRenderTime 27ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/components/pomm/libs/js/JsHttpRequest/Php.php

https://code.google.com/p/mwenhanced/
PHP | 373 lines | 238 code | 29 blank | 106 comment | 31 complexity | 84f8fbf8277e3a2326343b0c0fdcb0bd MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-3.0, AGPL-1.0, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. <?php
  2. /**
  3. * Subsys_JsHttpRequest_Php: PHP backend for JavaScript DHTML loader.
  4. * (C) 2005 Dmitry Koterov, http://forum.dklab.ru/users/DmitryKoterov/
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. * See http://www.gnu.org/copyleft/lesser.html
  11. *
  12. * Do not remove this comment if you want to use the script!
  13. * ?? ????€??? ?????? ???????????, ???? ?? ?????? ???????????? ??????!
  14. *
  15. * This backend library also supports POST requests additionally to GET.
  16. *
  17. * @author Dmitry Koterov
  18. * @version 3.35
  19. */
  20. class Subsys_JsHttpRequest_Php
  21. {
  22. var $SCRIPT_ENCODING = "windows-1251";
  23. var $SCRIPT_DECODE_MODE = '';
  24. var $UNIQ_HASH;
  25. var $SCRIPT_ID;
  26. var $LOADER = null;
  27. var $QUOTING = null;
  28. /**
  29. * Constructor.
  30. *
  31. * Create new Subsys_JsHttpRequest_Php backend object and attach it
  32. * to script output buffer. As a result - script will always return
  33. * correct JavaScript code, even in case of fatal errors.
  34. */
  35. function Subsys_JsHttpRequest_Php($enc)
  36. {
  37. // QUERY_STRING is in form: PHPSESSID=<sid>&a=aaa&b=bbb&<id>
  38. // where <id> is request ID, <sid> - session ID (if present),
  39. // PHPSESSID - session parameter name (by default = "PHPSESSID").
  40. // Parse QUERY_STRING wrapper format.
  41. $this->LOADER = "SCRIPT";
  42. if (preg_match('/(\d+)((?:-\w+)?)$/s', $_SERVER['QUERY_STRING'], $m))
  43. {
  44. $this->SCRIPT_ID = $m[1];
  45. // XMLHttpRequest is used if URI ends with "&".
  46. if ($m[2] == '-xml')
  47. $this->LOADER = "XMLHttpRequest";
  48. }
  49. else
  50. {
  51. $this->SCRIPT_ID = 0;
  52. }
  53. // Start OB handling early.
  54. $this->UNIQ_HASH = md5(microtime().getmypid());
  55. ini_set('error_prepend_string', ini_get('error_prepend_string').$this->UNIQ_HASH);
  56. ini_set('error_append_string', ini_get('error_append_string') .$this->UNIQ_HASH);
  57. ob_start(array(&$this, "_obHandler"));
  58. // Set up encoding.
  59. $this->setEncoding($enc);
  60. // Check if headers are already sent (see Content-Type library usage).
  61. // If true - generate debug message and exit.
  62. $file = $line = null;
  63. if (headers_sent($file, $line))
  64. {
  65. trigger_error(
  66. "HTTP headers are already sent" . ($line !== null? " in $file on line $line" : "") . ". "
  67. . "Possibly you have extra spaces (or newlines) before first line of the script or any library. "
  68. . "Please note that Subsys_JsHttpRequest uses its own Content-Type header and fails if "
  69. . "this header cannot be set. See header() function documentation for details",
  70. E_USER_ERROR
  71. );
  72. exit();
  73. }
  74. }
  75. /**
  76. * string getJsCode()
  77. *
  78. * Return JavaScript part of library.
  79. */
  80. function getJsCode()
  81. {
  82. return file_get_contents(dirname(__FILE__).'/Js.js');
  83. }
  84. /**
  85. * void setEncoding(string $encoding)
  86. *
  87. * Set active script encoding & correct QUERY_STRING according to it.
  88. * Examples:
  89. * "windows-1251" - set plain encoding (non-windows characters,
  90. * e.g. hieroglyphs, are totally ignored)
  91. * "windows-1251 entities" - set windows encoding, BUT additionally replace:
  92. * "&" -> "&amp;"
  93. * hieroglyph -> &#XXXX; entity
  94. */
  95. function setEncoding($enc)
  96. {
  97. // Parse encoding.
  98. preg_match('/^(\S*)(?:\s+(\S*))$/', $enc, $p);
  99. $this->SCRIPT_ENCODING = strtolower(@$p[1]? $p[1] : $enc);
  100. $this->SCRIPT_DECODE_MODE = @$p[2]? $p[2] : '';
  101. // Manually parse QUERY_STRING because of damned Unicode's %uXXXX.
  102. $this->_correctQueryString();
  103. }
  104. /**
  105. * string quoteInput(string $input)
  106. *
  107. * Quote string according to input decoding mode.
  108. * If entities is used (see setEncoding()), no '&' character is quoted,
  109. * only '"', '>' and '<' (we presume than '&' is already quoted by
  110. * input reader function).
  111. *
  112. * Use this function INSTEAD of htmlspecialchars() for $_GET data
  113. * in your scripts.
  114. */
  115. function quoteInput($s)
  116. {
  117. if ($this->SCRIPT_DECODE_MODE == 'entities')
  118. return str_replace(array('"', '<', '>'), array('&quot;', '&lt;', '&gt;'), $s);
  119. else
  120. return htmlspecialchars($s);
  121. }
  122. /**
  123. * Convert PHP scalar, array or hash to JS scalar/array/hash.
  124. */
  125. function php2js($a)
  126. {
  127. if (is_null($a)) return 'null';
  128. if ($a === false) return 'false';
  129. if ($a === true) return 'true';
  130. if (is_scalar($a))
  131. {
  132. $a = addslashes($a);
  133. $a = str_replace("\n", '\n', $a);
  134. $a = str_replace("\r", '\r', $a);
  135. $a = preg_replace('{(</)(script)}i', "$1'+'$2", $a); // for FORM loader
  136. return "'$a'";
  137. }
  138. $isList = true;
  139. for ($i=0, reset($a); $i<count($a); $i++, next($a))
  140. if (key($a) !== $i)
  141. {
  142. $isList = false; break;
  143. }
  144. $result = array();
  145. if ($isList)
  146. {
  147. foreach ($a as $v)
  148. $result[] = Subsys_JsHttpRequest_Php::php2js($v);
  149. return '[ ' . join(',', $result) . ' ]';
  150. }
  151. else
  152. {
  153. foreach ($a as $k=>$v)
  154. $result[] = Subsys_JsHttpRequest_Php::php2js($k) . ': ' . Subsys_JsHttpRequest_Php::php2js($v);
  155. return '{ ' . join(',', $result) . ' }';
  156. }
  157. }
  158. /**
  159. * Internal methods.
  160. */
  161. /**
  162. * Parse & decode QUERY_STRING.
  163. */
  164. function _correctQueryString()
  165. {
  166. // ATTENTION!!!
  167. // HTTP_RAW_POST_DATA is only accessible when Content-Type of POST request
  168. // is NOT default "application/x-www-form-urlencoded"!!!
  169. // Library frontend sets "application/octet-stream" for that purpose,
  170. // see JavaScript code.
  171. foreach (array('_GET'=>$_SERVER['QUERY_STRING'], '_POST'=>@$GLOBALS['HTTP_RAW_POST_DATA']) as $dst=>$src)
  172. {
  173. if (isset($GLOBALS[$dst]))
  174. {
  175. // First correct all 2-byte entities.
  176. $s = preg_replace('/%(?!5B)(?!5D)([0-9a-f]{2})/si', '%u00\\1', $src);
  177. // Now we can use standard parse_str() with no worry!
  178. $data = null;
  179. parse_str($s, $data);
  180. $GLOBALS[$dst] = $this->_ucs2EntitiesDecode($data);
  181. }
  182. }
  183. $_REQUEST =
  184. (isset($_COOKIE)? $_COOKIE : array()) +
  185. (isset($_POST)? $_POST : array()) +
  186. (isset($_GET)? $_GET : array());
  187. if (ini_get('register_globals'))
  188. {
  189. // TODO?
  190. }
  191. }
  192. /**
  193. * Called in case of error too!
  194. */
  195. function _obHandler($text)
  196. {
  197. // Check for error.
  198. if (preg_match('{'.$this->UNIQ_HASH.'(.*?)'.$this->UNIQ_HASH.'}sx', $text))
  199. {
  200. $text = str_replace($this->UNIQ_HASH, '', $text);
  201. $this->WAS_ERROR = 1;
  202. }
  203. // Content-type header.
  204. // In XMLHttpRRequest mode we must return text/plain - damned stupid Opera 8.0. :(
  205. header("Content-type: " . ($this->LOADER=="SCRIPT"? "text/javascript" : "text/plain") . "; charset=" . $this->SCRIPT_ENCODING);
  206. // Make resulting hash.
  207. if (!isset($this->RESULT)) $this->RESULT = @$GLOBALS['_RESULT'];
  208. $result = $this->php2js($this->RESULT);
  209. $text =
  210. "// BEGIN Subsys_JsHttpRequest_Js\n" .
  211. "Subsys_JsHttpRequest_Js.dataReady(\n" .
  212. " " . $this->php2js($this->SCRIPT_ID) . ", // this ID is passed from JavaScript frontend\n" .
  213. " " . $this->php2js(trim($text)) . ",\n" .
  214. " " . $result . "\n" .
  215. ")\n" .
  216. "// END Subsys_JsHttpRequest_Js\n" .
  217. "";
  218. // $f = fopen("debug", "w"); fwrite($f, $text); fclose($f);
  219. return $text;
  220. }
  221. /**
  222. * Decode all %uXXXX entities in string or array (recurrent).
  223. * String must not contain %XX entities - they are ignored!
  224. */
  225. function _ucs2EntitiesDecode($data)
  226. {
  227. if (is_array($data))
  228. {
  229. $d = array();
  230. foreach ($data as $k=>$v)
  231. {
  232. $d[$this->_ucs2EntitiesDecode($k)] = $this->_ucs2EntitiesDecode($v);
  233. }
  234. return $d;
  235. }
  236. else
  237. {
  238. if (strpos($data, '%u') !== false)
  239. { // improve speed
  240. $data = preg_replace_callback('/%u([0-9A-F]{1,4})/si', array(&$this, '_ucs2EntitiesDecodeCallback'), $data);
  241. }
  242. return $data;
  243. }
  244. }
  245. /**
  246. * Decode one %uXXXX entity (RE callback).
  247. */
  248. function _ucs2EntitiesDecodeCallback($p)
  249. {
  250. $hex = $p[1];
  251. $dec = hexdec($hex);
  252. if ($dec === "38" && $this->SCRIPT_DECODE_MODE == 'entities')
  253. {
  254. // Process "&" separately in "entities" decode mode.
  255. $c = "&amp;";
  256. }
  257. else
  258. {
  259. if (is_callable('iconv'))
  260. {
  261. $c = @iconv('UCS-2BE', $this->SCRIPT_ENCODING, pack('n', $dec));
  262. }
  263. else
  264. {
  265. $c = $this->_decUcs2Decode($dec, $this->SCRIPT_ENCODING);
  266. }
  267. if (!strlen($c))
  268. {
  269. if ($this->SCRIPT_DECODE_MODE == 'entities')
  270. {
  271. $c = '&#'.$dec.';';
  272. }
  273. else
  274. {
  275. $c = '?';
  276. }
  277. }
  278. }
  279. return $c;
  280. }
  281. /**
  282. * If there is no ICONV, try to decode 1-byte characters manually
  283. * (for most popular charsets only).
  284. */
  285. /**
  286. * Convert from UCS-2BE decimal to $toEnc.
  287. */
  288. function _decUcs2Decode($code, $toEnc)
  289. {
  290. if ($code < 128) return chr($code);
  291. if (isset($this->_encTables[$toEnc]))
  292. {
  293. $p = array_search($code, $this->_encTables[$toEnc]);
  294. if ($p !== false)
  295. return chr(128 + $p);
  296. }
  297. return "";
  298. }
  299. /**
  300. * UCS-2BE -> 1-byte encodings (from #128).
  301. */
  302. var $_encTables = array
  303. (
  304. 'windows-1251' => array
  305. (
  306. 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
  307. 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
  308. 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
  309. 0x0098, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
  310. 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7,
  311. 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
  312. 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7,
  313. 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457,
  314. 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
  315. 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
  316. 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
  317. 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
  318. 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
  319. 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
  320. 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
  321. 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
  322. ),
  323. 'koi8-r' => array
  324. (
  325. 0x2500, 0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524,
  326. 0x252C, 0x2534, 0x253C, 0x2580, 0x2584, 0x2588, 0x258C, 0x2590,
  327. 0x2591, 0x2592, 0x2593, 0x2320, 0x25A0, 0x2219, 0x221A, 0x2248,
  328. 0x2264, 0x2265, 0x00A0, 0x2321, 0x00B0, 0x00B2, 0x00B7, 0x00F7,
  329. 0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556,
  330. 0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255d, 0x255E,
  331. 0x255F, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565,
  332. 0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x00A9,
  333. 0x044E, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
  334. 0x0445, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043d, 0x043E,
  335. 0x043F, 0x044F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
  336. 0x044C, 0x044B, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044A,
  337. 0x042E, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
  338. 0x0425, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041d, 0x041E,
  339. 0x041F, 0x042F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
  340. 0x042C, 0x042B, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042A
  341. ),
  342. );
  343. }
  344. ?>