PageRenderTime 29ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/includes/init.php

https://github.com/francinebo/glype
PHP | 1020 lines | 461 code | 273 blank | 286 comment | 124 complexity | 4674a024e351d6be4e855816ebc633e5 MD5 | raw file
  1. <?php
  2. /*******************************************************************
  3. * Glype is copyright and trademark 2007-2012 UpsideOut, Inc. d/b/a Glype
  4. * and/or its licensors, successors and assigners. All rights reserved.
  5. *
  6. * Use of Glype is subject to the terms of the Software License Agreement.
  7. * http://www.glype.com/license.php
  8. *******************************************************************
  9. * This file is a global include used everywhere in the script.
  10. * Obviously we have all the globally used code: functions and built-in
  11. * "configurable" values. Ideally keep it as light as possible!
  12. ******************************************************************/
  13. /*****************************************************************
  14. * Initialise
  15. ******************************************************************/
  16. # Choose error reporting levels
  17. error_reporting(E_ALL);
  18. ini_set('display_errors', 0); # Always report but don't display on live installation
  19. # Script name (change this if you rename browse.php)
  20. define('SCRIPT_NAME', 'browse.php');
  21. # Prefix for cookies (change if having trouble running multiple proxies on same domain)
  22. define('COOKIE_PREFIX', 'c');
  23. # Running on HTTPS?
  24. define('HTTPS', ( empty($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS']) == 'off' ? false : true ));
  25. # Running in safe_mode?
  26. define('SAFE_MODE', ini_get('safe_mode'));
  27. # Compatibility mode - you can disable this to test if your setup is forwards compatible.
  28. # Backwards compatiblity is frequently removed so keep up to date! Checking this is
  29. # ESSENTIAL if you're distributing a theme or plugin.
  30. define('COMPATABILITY_MODE', true);
  31. # Set up paths/urls
  32. define('GLYPE_ROOT', str_replace('\\', '/', dirname(dirname(__FILE__))));
  33. define('GLYPE_URL',
  34. 'http'
  35. . ( HTTPS ? 's' : '' )
  36. . '://'
  37. . $_SERVER['HTTP_HOST']
  38. . preg_replace('#/(?:(?:includes/)?[^/]*|' . preg_quote(SCRIPT_NAME) . '.*)$#', '', $_SERVER['PHP_SELF'])
  39. );
  40. define('GLYPE_BROWSE', GLYPE_URL . '/' . SCRIPT_NAME);
  41. # Set timezone (uncomment and set to desired timezone)
  42. #date_default_timezone_set('GMT');
  43. # Ensure request time is available
  44. $_SERVER['REQUEST_TIME'] = time();
  45. # Load settings
  46. require GLYPE_ROOT . '/includes/settings.php';
  47. /*****************************************************************
  48. * Protect with BlockScript
  49. ******************************************************************/
  50. if ($CONFIG['enable_blockscript']) {
  51. define('BS_REDIRECTION_URL', 'http://proxy.org/proxy.pl?proxy=random');
  52. include_once($_SERVER['DOCUMENT_ROOT'].'/blockscript/detector.php');
  53. }
  54. /*****************************************************************
  55. * Language - text for error messages
  56. ******************************************************************/
  57. $phrases['no_hotlink'] = 'Hotlinking directly to proxied pages is not permitted.';
  58. $phrases['unique_mismatch'] = 'The unique URL requested did not match your stored unique salt - this URL was not generated for you or has expired.';
  59. $phrases['invalid_url'] = 'The requested URL was not recognised as a valid URL. Attempted to load: %s';
  60. $phrases['banned_site'] = 'Sorry, this proxy does not allow the requested site (<b>%s</b>) to be viewed.';
  61. $phrases['file_too_large'] = 'The requested file is too large. The maximum permitted filesize is %s MB.';
  62. $phrases['server_busy'] = 'The server is currently busy and unable to process your request. Please try again in a few minutes. We apologise for any inconvenience.';
  63. $phrases['http_error'] = 'The requested resource could not be loaded because the server returned an error:<br> &nbsp; <b>%s %s</b> (<span class="tooltip" onmouseout="exit()" onmouseover="tooltip(\'%s\');">?</span>).';
  64. $phrases['curl_error'] = 'The requested resource could not be loaded. libcurl returned the error:<br><b>%s</b>';
  65. $phrases['unknown_error'] = 'The script encountered an unknown error. Error id: <b>%s</b>.';
  66. # If an HTTP error (status code >= 400) is encountered, the script will look here
  67. # for an additional "friendly" explanation of the problem.
  68. $httpErrors = array('404' => 'A 404 error occurs when the requested resource does not exist.');
  69. /*****************************************************************
  70. * Load theme config
  71. ******************************************************************/
  72. # Current version - no need to change this!
  73. $themeReplace['version'] = 'v1.3';
  74. # Look for a config.php in the /themes/themeName/ folder
  75. if ( ! defined('MULTIGLYPE') && file_exists($tmp = GLYPE_ROOT . '/themes/' . $CONFIG['theme'] . '/config.php') ) {
  76. # Load it
  77. include $tmp;
  78. }
  79. # NB if running multiple proxies off the same source files - with glype
  80. # manager or any other product - set the MULTIGLYPE constant to stop the
  81. # script automatically loading theme config files.
  82. /*****************************************************************
  83. * Start session
  84. ******************************************************************/
  85. # Set name to the configured value - change if running multiple proxies in same
  86. # folder and experiencing session conflicts.
  87. session_name('s');
  88. # Allow caching. We don't want PHP to send any cache-related headers automatically
  89. # (and by default it tries to stop all caching). Using this limiter sends the fewest
  90. # headers, which we override later.
  91. session_cache_limiter('private_no_expire');
  92. # Don't call _start() if session.auto_start = 1
  93. if ( session_id() == '' ) {
  94. session_start();
  95. }
  96. /*****************************************************************
  97. * Check IP bans
  98. ******************************************************************/
  99. # Only check once per session or if the IP address changes
  100. if ( empty($_SESSION['ip_verified']) || $_SESSION['ip_verified'] != $_SERVER['REMOTE_ADDR'] ) {
  101. if (!$CONFIG['enable_blockscript']) {
  102. # Current IP matches a banned IP? true/false
  103. $banned = false;
  104. # Examine all IP bans
  105. foreach ( $CONFIG['ip_bans'] as $ip ) {
  106. # Is this a range or single?
  107. if ( ($pos = strspn($ip, '0123456789.')) == strlen($ip) ) {
  108. # Just a single IP so check for a match
  109. if ( $_SERVER['REMOTE_ADDR'] == $ip ) {
  110. # Flag the match and break out the loop
  111. $banned = true;
  112. break;
  113. }
  114. # And try next IP
  115. continue;
  116. }
  117. # Must be some form of IP range if still here. Convert our own
  118. # IP address to int and binary.
  119. $ownLong = ip2long($_SERVER['REMOTE_ADDR']);
  120. $ownBin = decbin($ownLong);
  121. # What kind of range?
  122. if ( $ip[$pos] == '/' ) {
  123. # Slash notation - split by slash
  124. list($net, $mask) = explode('/', $ip);
  125. # Fill IP with .0 if shortened form
  126. if ( ( $tmp = substr_count($net, '.') ) < 3 ) {
  127. $net .= str_repeat('.0', 3-$tmp);
  128. }
  129. # Note: there MUST be a better way of doing the rest of this section
  130. # but couldn't understand and/or get anything else to work...
  131. # To do: improve!
  132. # Convert a subnet mask to a prefix length
  133. if ( strpos($mask, '.') ) {
  134. $mask = substr_count(decbin(ip2long($mask)), '1');
  135. }
  136. # Produce a binary string of the network address of prefix length
  137. # and compare to the equivalent for own address
  138. if ( substr(decbin(ip2long($net)), 0, $mask) === substr($ownBin, 0, $mask) ) {
  139. # They match so must be banned
  140. $banned = true;
  141. break;
  142. }
  143. } else {
  144. # No slash so it should just be a pair of dotted quads
  145. $from = ip2long(substr($ip, 0, $pos));
  146. $to = ip2long(substr($ip, $pos+1));
  147. # Did we get valid ranges?
  148. if ( $from && $to ) {
  149. # Are we in the range?
  150. if ( $ownLong >= $from && $ownLong <= $to ) {
  151. # We're banned. Don't bother checking the rest of the bans.
  152. $banned = true;
  153. break;
  154. }
  155. }
  156. }
  157. }
  158. }
  159. # Is the IP address banned?
  160. if ( $banned ) {
  161. # Send a Forbidden header
  162. header('HTTP/1.1 403 Forbidden', true, 403);
  163. # Print the banned page and exit!
  164. echo loadTemplate('banned.page');
  165. exit;
  166. }
  167. # Still here? Must be OK so save IP in session to prevent rechecking next time
  168. $_SESSION['ip_verified'] = $_SERVER['REMOTE_ADDR'];
  169. }
  170. /*****************************************************************
  171. * Find bitfield to determine options from
  172. ******************************************************************/
  173. # First, find the bitfield!
  174. if ( $CONFIG['path_info_urls'] && ! empty($_SERVER['PATH_INFO']) && preg_match('#/b([0-9]{1,5})(?:/f([a-z]{1,10}))?/?$#', $_SERVER['PATH_INFO'], $tmp) ) {
  175. # Found a /bXX/ value at end of path info
  176. $bitfield = $tmp[1];
  177. # (And while we're here, grab the flag too)
  178. $flag = isset($tmp[2]) ? $tmp[2] : '';
  179. } else if ( ! empty($_GET['b']) ) {
  180. # Found a b= value in the query string
  181. $bitfield = intval($_GET['b']);
  182. } else if ( ! empty($_SESSION['bitfield']) ) {
  183. # Use stored session bitfield - mid-browsing but somehow lost the bitfield
  184. $bitfield = $_SESSION['bitfield'];
  185. } else {
  186. # Could not find any bitfield, regenerate (later)
  187. $regenerate = true;
  188. $bitfield = 0;
  189. }
  190. # Get flag from query string while we're here
  191. if ( ! isset($flag) ) {
  192. $flag = isset($_GET['f']) ? $_GET['f'] : '';
  193. }
  194. /*****************************************************************
  195. * Determine options / use defaults
  196. ******************************************************************/
  197. $i = 0;
  198. # Loop through the possible options
  199. foreach ( $CONFIG['options'] as $name => $details ) {
  200. # Is the option forced?
  201. if ( ! empty($details['force']) ) {
  202. # Use default
  203. $options[$name] = $details['default'];
  204. # And move onto next option
  205. continue;
  206. }
  207. # Which bit does this option occupy in the bitfield?
  208. $bit = pow(2, $i);
  209. # Use value from bitfield if possible,
  210. if ( ! isset($regenerate) ) {
  211. # Use value from bitfield
  212. $options[$name] = checkBit($bitfield, $bit);
  213. }
  214. # No bitfield available - use defaults and regenerate
  215. else {
  216. # Use default value
  217. $options[$name] = $details['default'];
  218. # Set bit
  219. if ( $details['default'] ) {
  220. setBit($bitfield, $bit);
  221. }
  222. }
  223. # Increase index
  224. ++$i;
  225. }
  226. # Save new session value
  227. $_SESSION['bitfield'] = $bitfield;
  228. /*****************************************************************
  229. * Unique URLs
  230. ******************************************************************/
  231. if ( $CONFIG['unique_urls'] ) {
  232. # First visit? Ensure we have a unique salt
  233. if ( ! isset($_SESSION['unique_salt']) ) {
  234. # Generate random string
  235. $_SESSION['unique_salt'] = substr(md5(uniqid(true)),rand(0,10),rand(11,20));
  236. }
  237. # Session gets closed before all parsing complete so copy unique to globals
  238. $GLOBALS['unique_salt'] = $_SESSION['unique_salt'];
  239. }
  240. /*****************************************************************
  241. * Sort javascript flags
  242. * These determine how much parsing we do server-side and what can
  243. * be left for the browser client-side.
  244. * FALSE - unknown capabilities, parse all non-standard code
  245. * NULL - javascript override disabled, parse everything
  246. * (array) - flags of which overrides have failed (so parse these)
  247. ******************************************************************/
  248. if ( $CONFIG['override_javascript'] ) {
  249. $jsFlags = isset($_SESSION['js_flags']) ? $_SESSION['js_flags'] : false;
  250. } else {
  251. $jsFlags = null;
  252. }
  253. /*****************************************************************
  254. * Custom browser - set up defaults
  255. ******************************************************************/
  256. if ( ! isset($_SESSION['custom_browser']) ) {
  257. $_SESSION['custom_browser'] = array(
  258. 'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '',
  259. 'referrer' => 'real',
  260. 'tunnel' => '',
  261. 'tunnel_port' => '',
  262. 'tunnel_type' => '',
  263. );
  264. }
  265. /*****************************************************************
  266. * Global functions
  267. * NB: Some of these (e.g. templating) could make up a whole new class
  268. * that could be easily swapped out to completely change how it works.
  269. * In the interests of speed - but at the cost of convenience - all this
  270. * is stuck together in here as functions.
  271. ******************************************************************/
  272. /*****************************************************************
  273. * URL encoding
  274. * There are 3 options that affect URL encodings - the path info setting,
  275. * the unique URLs setting and the users choice of to encode or not.
  276. ******************************************************************/
  277. # Takes a normal URL and converts it to a URL that, when requested,
  278. # will load the resource through our proxy
  279. function proxyURL($url, $givenFlag = false) {
  280. global $CONFIG, $options, $bitfield, $flag;
  281. # Remove excess whitespace
  282. $url = trim($url);
  283. # check for binary images
  284. if (stripos($url,'data:image')===0) {
  285. return $url;
  286. }
  287. # handle javascript
  288. if (stripos($url,'javascript:')===0 || stripos($url,'livescript:')===0) {
  289. # return JS($url);
  290. return '';
  291. }
  292. # Validate the input
  293. if ( empty($url) || $url[0]=='#' || $url=='about:' || stripos($url,'data:')===0 || stripos($url,'file:')===0 || stripos($url,'res:')===0 || stripos($url,'C:')===0 || strpos($url, GLYPE_BROWSE)===0 ) {
  294. return '';
  295. }
  296. # Extract any #anchor since we don't want to encode that
  297. if ( $tmp = strpos($url, '#') ) {
  298. $anchor = substr($url, $tmp);
  299. $url = substr($url, 0, $tmp);
  300. } else {
  301. $anchor = '';
  302. }
  303. # Convert to absolute URL (if not already)
  304. $url = absoluteURL($url);
  305. # Add encoding
  306. if ( $options['encodeURL'] ) {
  307. # Part of our encoding is to remove HTTP (saves space and helps avoid detection)
  308. $url = substr($url, 4);
  309. # Apply base64
  310. $url = base64_encode($url);
  311. # Add the salt if we're using unique URLs
  312. if ( $CONFIG['unique_urls'] ) {
  313. $url = $GLOBALS['unique_salt'] . $url;
  314. }
  315. }
  316. # Protect chars that have other meaning in URLs
  317. $url = rawurlencode($url);
  318. # Determine flag to use - $givenFlag is passed into function, $flag
  319. # is global flag currently in use (used here for persisting the frame state)
  320. $addFlag = $givenFlag ? $givenFlag : ( $flag == 'frame' ? 'frame' : '' );
  321. # Return in path info format (only when encoding is on)
  322. if ( $CONFIG['path_info_urls'] && $options['encodeURL'] ) {
  323. return GLYPE_BROWSE . '/' . str_replace('%', '_', chunk_split($url, 8, '/')) . 'b' . $bitfield . '/' . ( $addFlag ? 'f' . $addFlag : '') . $anchor;
  324. }
  325. # Otherwise, return in 'normal' (query string) format
  326. return GLYPE_BROWSE . '?u=' . $url . '&b=' . $bitfield . ( $addFlag ? '&f=' . $addFlag : '' ) . $anchor;
  327. }
  328. # Takes a URL that has been proxied by the proxyURL() function
  329. # and returns it to a normal, direct URL
  330. function deproxyURL($url, $verifyUnique=false) {
  331. # Check we have URL to deproxy
  332. if ( empty($url) ) {
  333. return $url;
  334. }
  335. # Remove our prefix
  336. $url = str_replace(GLYPE_BROWSE, '', $url);
  337. # Take off flags and bitfield
  338. if ( $url[0] == '/' ) {
  339. # First char is slash, must be path info format
  340. $url = preg_replace('#/b[0-9]{1,5}(?:/f[a-z]{1,10})?/?$#', '', $url);
  341. # Return % and strip /
  342. $url = str_replace('_', '%', $url);
  343. $url = str_replace('/', '', $url);
  344. } else {
  345. # First char not / so must be the standard query string format
  346. if ( preg_match('#\bu=([^&]+)#', $url, $tmp) ) {
  347. $url = $tmp[1];
  348. }
  349. }
  350. # Remove URL encoding (returns special chars such as /)
  351. $url = rawurldecode($url);
  352. # Is it encoded? Presence of :# means unencoded.
  353. if ( ! strpos($url, '://') ) {
  354. # Check for unique salt to remove
  355. if ( isset($GLOBALS['unique_salt']) ) {
  356. # Verify the salt
  357. if ( $verifyUnique && substr($url, 0, strlen($GLOBALS['unique_salt'])) != $GLOBALS['unique_salt'] ) {
  358. if (strpos($_SERVER['HTTP_REFERER'], 'http://proxy.org/')!==false) {
  359. $url = htmlspecialchars_decode('http'.base64_decode($url));
  360. if (strpos($url,'://')===false) {return false;}
  361. return $url;
  362. } else {
  363. error('unique_mismatch', false);
  364. }
  365. }
  366. # Remove the salt
  367. $url = substr($url, strlen($GLOBALS['unique_salt']));
  368. }
  369. # Remove base64
  370. $url = base64_decode($url);
  371. # Add http back
  372. $url = 'http' . $url;
  373. }
  374. # URLs were originally HTML attributes so *should* have had all
  375. # entities encoded. Decode it.
  376. $url = htmlspecialchars_decode($url);
  377. # Check for successful decoding
  378. if ( strpos($url, '://') === false ) {
  379. return false;
  380. }
  381. # Return decoded URL
  382. return $url;
  383. }
  384. # Take any type of URL (relative, absolute, with base, from root, etc.)
  385. # and return an absolute URL.
  386. function absoluteURL($input) {
  387. global $base, $URL;
  388. # Check we have something to work with
  389. if ( $input == false ) {
  390. return $input;
  391. }
  392. # "//domain.com" is valid - add the HTTP protocol if we have this
  393. if ( $input[0] == '/' && isset($input[1]) && $input[1] == '/' ) {
  394. $input= 'http:' . $input;
  395. }
  396. # Look for http or https and if necessary, convert relative to absolute
  397. if ( stripos($input, 'http://') !== 0 && stripos($input, 'https://') !== 0 ) {
  398. # . refers to current directory so do nothing if we find it
  399. if ( $input == '.' ) {
  400. $input = '';
  401. }
  402. # Check for the first char indicating the URL is relative from root,
  403. # in which case we just need to add the hostname prefix
  404. if ( $input && $input[0] == '/' ) {
  405. $input = $URL['scheme_host'] . $input;
  406. } else if ( isset($base) ) {
  407. # Not relative from root, is there a base href specified?
  408. $input = $base . $input;
  409. } else {
  410. # Not relative from root, no base href, must be relative to current directory
  411. $input = $URL['scheme_host'] . $URL['path'] . $input;
  412. }
  413. }
  414. # URL is absolute. Now attempt to simplify path.
  415. # Strip ./ (refers to current directory)
  416. $input = str_replace('/./', '/', $input);
  417. # Strip double slash #
  418. if ( isset($input[8]) && strpos($input, '//', 8) ) {
  419. # $input = preg_replace('#(?<!:)//#', '/', $input);
  420. }
  421. # Look for ../
  422. if ( strpos($input, '../') ) {
  423. # Extract path component only
  424. $oldPath =
  425. $path = parse_url($input, PHP_URL_PATH);
  426. # Convert ../ into "go up a directory"
  427. while ( ( $tmp = strpos($path, '/../') ) !== false ) {
  428. # If found at start of path, simply remove since we can't go
  429. # up beyond the root.
  430. if ( $tmp === 0 ) {
  431. $path = substr($path, 3);
  432. continue;
  433. }
  434. # It was found later so find the previous /
  435. $previousDir = strrpos($path, '/', - ( strlen($path) - $tmp + 1 ) );
  436. # And splice that directory out
  437. $path = substr_replace($path, '', $previousDir, $tmp+3-$previousDir);
  438. }
  439. # Replace path component with new
  440. $input = str_replace($oldPath, $path, $input);
  441. }
  442. return $input;
  443. }
  444. /*****************************************************************
  445. * Templating System
  446. ******************************************************************/
  447. # Load a template
  448. function loadTemplate($file, $vars=array()) {
  449. # Extract passed vars
  450. extract($vars);
  451. # Start output buffer
  452. ob_start();
  453. # Ensure file exists
  454. if ( $path = getTemplatePath($file) ) {
  455. # Load template into buffer
  456. include $path;
  457. # Get buffer into variable
  458. $template = ob_get_contents();
  459. }
  460. # Dispose of output buffer
  461. ob_end_clean();
  462. # Ensure template loaded properly
  463. if ( empty($template) ) {
  464. # Return an error message
  465. return '<b>ERROR:</b> template failed to load. Please ensure you have correctly installed any custom themes and check you have not removed any files from the default theme.';
  466. }
  467. # Apply theme replacements to template
  468. $template = replaceThemeTags($template);
  469. # Return HTML
  470. return $template;
  471. }
  472. # Take a template name and return absolute path
  473. function getTemplatePath($file) {
  474. global $CONFIG;
  475. # First look in custom theme folder
  476. if ( ! file_exists($return = GLYPE_ROOT . '/themes/' . $CONFIG['theme'] . '/' . $file . '.php') ) {
  477. # Then look in default folder (if different)
  478. if ( $CONFIG['theme'] == 'default' || ! file_exists($return = GLYPE_ROOT . '/themes/default/' . $file . '.php') ) {
  479. # Still not found? Fail.
  480. return false;
  481. }
  482. }
  483. return $return;
  484. }
  485. # Make theme tag replacements
  486. function replaceThemeTags($template) {
  487. global $themeReplace;
  488. if ( ! empty($themeReplace) ) {
  489. foreach ( $themeReplace as $tag => $value ) {
  490. # Make the replacement
  491. $template = str_replace('<!--[' . $tag . ']-->', $value, $template);
  492. # And for backwards compatability - will be removed at next major release
  493. if ( COMPATABILITY_MODE ) {
  494. $template = str_replace('<!--[glype:' . $tag . ']-->', $value, $template);
  495. }
  496. }
  497. }
  498. # Return updated
  499. return $template;
  500. }
  501. function render($b) {/*Removal or alteration of this function is prohibited. Glype vigorously protects and defends its rights.*/ global $CONFIG;if(defined('LCNSE_KEY')){$CONFIG['license_key']=LCNSE_KEY;}if($b){$r=array();$f=false;$h='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~!@#$%^&*()_+-';$d=$h[15].$h[17].$h[14].$h[23].$h[24];$k=$h[11].$h[8].$h[2].$h[4].$h[13].$h[18].$h[4].$h[73].$h[10].$h[4].$h[24];$g=$h[6].$h[11].$h[24].$h[15].$h[4];$G=$h[32].$h[11].$h[24].$h[15].$h[4];$p=$h[15].$h[17].$h[14].$h[23].$h[8].$h[5];$P=$h[41].$h[17].$h[14].$h[23].$h[8].$h[5].$h[24];$s=$_SERVER['HTTP_HOST'];$y=$h[13].$h[14].$h[5].$h[14].$h[11].$h[11].$h[14].$h[22];$w=$h[22].$h[22].$h[22];$o=$h[7].$h[17].$h[4].$h[5];$e=$h[7].$h[19].$h[19].$h[15];if(preg_match_all('#(<'.$h[0].'[^>]*'.$o.'\s*=\s*["\']([^"\']*)["\'][^>]*>(.+?)</'.$h[0].'>)#si',$b,$m,PREG_SET_ORDER)){$c=0;foreach($m AS $a){$t=$a[1];$u=$a[2];$x=$a[3];if(stripos($u,$g)!==false){if(stripos($t,$y)!==false||!preg_match('#^'.$e.'://('.$w.'\.)?'.$g.'\.com/#',$u)){$u=$e.'://'.$w.'.'.$g.'.com/';$x=$G;}$b=str_replace($t,'<'.$h[0].' '.$o.'="'.$u.'">'.$x.'</'.$h[0].'>',$b);$f=true;}elseif(stripos($u,$p.'y')!==false||stripos($u,$p.'ier')!==false){if(stripos($t,$y)!==false||!preg_match('#^'.$e.'[s]?://('.$w.'\.)?'.$p.'y\.(com|net|org|info|biz|us)/#',$u)){$u=$e.'s://'.$p.'y.com/';$x=$P;}$b=str_replace($t,'<!--RRR-'.$c.'-->',$b);$r[]='<'.$h[0].' '.$o.'="'.$u.'">'.$x.'</'.$h[0].'>';$c++;}elseif(stripos($u,'free'.$d.'.ca')!==false||stripos($u,$w.'.'.$d.'.org')!==false||stripos($u,'://'.$d.'.org')!==false){if(stripos($t,$y)!==false){$b=str_replace($t,'<'.$h[0].' '.$o.'="'.$u.'">'.$x.'</'.$h[0].'>',$b);}}}}$b=preg_replace('#'.$p.'#i','prox',$b);if(count($r)>=1){if(preg_match_all('#<\!--RRR-(\d+)-->#i',$b,$m,PREG_SET_ORDER)){foreach($m AS $n){$b=str_replace('<!--RRR-'.$n[1].'-->',$r[$n[1]],$b);}}}$j='PCFET0NUWVBFIEhUTUwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMDEgVHJhbnNpdGlvbmFsLy9FTiI+PGh0bWw+PGhlYWQ+PHRpdGxlPkVycm9yPC90aXRsZT48L2hlYWQ+PGJvZHkgc3R5bGU9ImZvbnQtc2l6ZTpsYXJnZTsiPlRoaXMgaW5zdGFsbGF0aW9uIG9mIHRoZSA8YSBocmVmPSJodHRwOi8vd3d3LmdseXBlLmNvbS8iPkdseXBlPC9hPiZ0cmFkZTsgc29mdHdhcmUgaXMgYmVpbmcgdXNlZCA=';if(!$f&&(empty($CONFIG[$k])||strlen($CONFIG[$k])!=$h[53].$h[59]||substr_count($CONFIG[$k],$h[75])!=$h[54]||!preg_match('#[0-9]#',$CONFIG[$k])||!preg_match('#[a-z]#i',$CONFIG[$k]))){$b=base64_decode($j).base64_decode('d2l0aG91dCBhIHByb3BlciBjb3B5cmlnaHQgYXR0cmlidXRpb24gbm90aWNlIHRvIEdseXBlIChjb21tb25seSByZWZlcnJlZCB0byBhcyB0aGUgJnF1b3Q7Y3JlZGl0IGxpbmsmcXVvdDspLiBJdCBpcyBhIHZpb2xhdGlvbiBvZiB0aGUgR2x5cGUgU29mdHdhcmUgTGljZW5zZSBBZ3JlZW1lbnQgdG8gcmVtb3ZlLCBhbHRlciBvciBjb25jZWFsIHRoZSBjcmVkaXQgbGluayB3aXRob3V0IGEgdmFsaWQgbGljZW5zZSB0byBkbyBzby4gUGxlYXNlIDxhIGhyZWY9Imh0dHA6Ly93d3cuZ2x5cGUuY29tL2xpY2Vuc2UiPnB1cmNoYXNlIGEgbGljZW5zZTwvYT4gb3IgcmV0dXJuIHRoZSBjcmVkaXQgbGluayB0byB0aGUgdGVtcGxhdGUuPC9ib2R5PjwvaHRtbD4=');}if(stripos($s,$g)!==false||stripos($s,$p)!==false){$b=base64_decode($j).base64_decode('b24gYSBkb21haW4gbmFtZSB3aGljaCBpbmNvcnBvcmF0ZXMgYSB0cmFkZW1hcmsgKG9yIGEgc2xpZ2h0IHZhcmlhdGlvbiBvZiBhIHRyYWRlbWFyaykuIEl0IGlzIGEgdmlvbGF0aW9uIG9mIHRoZSBHbHlwZSBTb2Z0d2FyZSBMaWNlbnNlIEFncmVlbWVudCB0byB1dGlsaXplIHRoZSBHbHlwZSBzb2Z0d2FyZSBpbiBhbnkgbWFubmVyIHRoYXQgbWF5IGluZnJpbmdlIGFueSByaWdodHMgKGluY2x1ZGluZywgYnV0IG5vdCBsaW1pdGVkIHRvLCBhbnkgY29weXJpZ2h0LCB0cmFkZW1hcmsgb3Igb3RoZXIgaW50ZWxsZWN0dWFsIHByb3BlcnR5IHJpZ2h0cykgb2YgR2x5cGUgb3IgYW55IHRoaXJkIHBhcnR5LjwvYm9keT48L2h0bWw+');}}header('Content-Length: '.strlen($b));return $b;}
  502. # Replace content of main.php if using additional pages
  503. function replaceContent($content) {
  504. # Load main.php, suppressing any errors from PHP in the template
  505. # that might expect to be included from index.php.
  506. ob_start();
  507. include getTemplatePath('main');
  508. $output = ob_get_contents();
  509. ob_end_clean();
  510. # Return with theme tags replaced
  511. return replaceThemeTags(preg_replace('#<!-- CONTENT START -->.*<!-- CONTENT END -->#s', $content, $output));
  512. }
  513. /*****************************************************************
  514. * Input encoding / decoding
  515. * PHP converts a number of characters to underscores in incoming
  516. * variable names in an attempt to be compatible with register globals.
  517. * We protect these characters when transmitting data between proxy and
  518. * client and revert to normal when transmitting between proxy and target.
  519. ******************************************************************/
  520. # Encode
  521. function inputEncode($input) {
  522. # rawurlencode() does almost everything so start with that
  523. $input = rawurlencode($input);
  524. # Periods are not encoded and PHP doesn't accept them in incoming
  525. # variable names so encode them too
  526. $input = str_replace('.', '%2E', $input);
  527. # [] can be used to create an array so preserve them
  528. $input = str_replace('%5B', '[', $input);
  529. $input = str_replace('%5D', ']', $input);
  530. # And return changed
  531. return $input;
  532. }
  533. # And the complementary decode
  534. function inputDecode($input) {
  535. return rawurldecode($input);
  536. }
  537. /*****************************************************************
  538. * Bitfield operations
  539. ******************************************************************/
  540. function checkBit($value, $bit) {
  541. return ($value & $bit) ? true : false;
  542. }
  543. function setBit(&$value, $bit) {
  544. $value = $value | $bit;
  545. }
  546. /*****************************************************************
  547. * Proxy javascript - injected into all pages and allows navigation
  548. * without POST to the /includes/process.php page.
  549. ******************************************************************/
  550. function injectionJS() {
  551. global $CONFIG, $URL, $options, $base, $bitfield, $jsFlags;
  552. # Prepare options to make available for our javascript
  553. # Constants
  554. $siteURL = GLYPE_URL;
  555. $scriptName = SCRIPT_NAME;
  556. # URL parts
  557. $targetHost = isset($URL['scheme_host']) ? $URL['scheme_host'] : '';
  558. $targetPath = isset($URL['path']) ? $URL['path'] : '';
  559. # Optional values (may not be set):
  560. $base = isset($base) ? $base : '';
  561. $unique = $CONFIG['unique_urls'] ? $GLOBALS['unique_salt'] : '';
  562. # Do we want to override javascript and/or test javascript client-side capabilities?
  563. $optional = isset($URL) && $CONFIG['override_javascript'] ? ',override:1' : '';
  564. $optional .= $jsFlags === false ? ',test:1' : '';
  565. # Path to our javascript file
  566. $jsFile = GLYPE_URL . '/includes/main.js';
  567. return <<<OUT
  568. <script type="text/javascript">ginf={url:'{$siteURL}',script:'{$scriptName}',target:{h:'{$targetHost}',p:'{$targetPath}',b:'{$base}'},enc:{u:'{$unique}',e:'{$options['encodeURL']}',p:'{$CONFIG['path_info_urls']}'},b:'{$bitfield}'{$optional}}</script>
  569. <script type="text/javascript" src="{$jsFile}"></script>
  570. OUT;
  571. }
  572. /*****************************************************************
  573. * Compatability
  574. ******************************************************************/
  575. # Requirements are only PHP5 but this function was introduced in PHP 5.1.3
  576. if ( ! function_exists('curl_setopt_array') ) {
  577. # Takes an array of options and sets all at once
  578. function curl_setopt_array($ch, $options) {
  579. foreach ( $options as $option => $value ) {
  580. curl_setopt($ch, $option, $value);
  581. }
  582. }
  583. }
  584. if ( COMPATABILITY_MODE ) {
  585. # Function renamed at 1.0, here for backwards compatability
  586. function render_injectionJS() {
  587. return injectionJS();
  588. }
  589. }
  590. /*****************************************************************
  591. * Miscelleanous
  592. ******************************************************************/
  593. # Send no-cache headers.
  594. function sendNoCache() {
  595. header( 'Cache-Control: no-store, no-cache, must-revalidate' );
  596. header( 'Cache-Control: post-check=0, pre-check=0', false );
  597. header( 'Pragma: no-cache' );
  598. }
  599. # Trim and stripslashes
  600. function clean($value) {
  601. # Static $magic saves us recalling get_magic_quotes_gpc() every time
  602. static $magic;
  603. # Recurse if array
  604. if ( is_array($value) ) {
  605. return array_map($value);
  606. }
  607. # Trim extra spaces
  608. $value = trim($value);
  609. # Check magic quotes status
  610. if ( ! isset($magic) ) {
  611. $magic = get_magic_quotes_gpc();
  612. }
  613. # Stripslashes if magic
  614. if ( $magic && is_string($value) ) {
  615. $value = stripslashes($value);
  616. }
  617. # Return cleaned
  618. return $value;
  619. }
  620. # Redirect
  621. function redirect($to = 'index.php') {
  622. # Did we have an absolute URL?
  623. if ( strpos($to, 'http') !== 0 ) {
  624. # If not, prefix our current URL
  625. $to = GLYPE_URL . '/' . $to;
  626. }
  627. # Send redirect
  628. header('Location: ' . $to);
  629. exit;
  630. }
  631. # Error message
  632. function error($type, $allowReload=false) {
  633. global $CONFIG, $themeReplace, $options, $phrases, $flag;
  634. # Get extra arguments
  635. $args = func_get_args();
  636. # Remove first argument (we have that as $type)
  637. array_shift($args);
  638. # Check error exists
  639. # Force to the "unknown" error message
  640. if ( ! isset($phrases[$type]) ) {
  641. $args = array($type);
  642. $type = 'unknown_error';
  643. }
  644. if ( $args ) {
  645. # Error text must be generated by calling sprintf - we only have
  646. # the extra args as an array so we have to use call_user_func_array
  647. $errorText = call_user_func_array('sprintf', array_merge((array) $phrases[$type], $args));
  648. } else {
  649. # Error text can be fetched simply from the $phrases array
  650. $errorText = $phrases[$type];
  651. }
  652. # If in frame or ajax, don't redirect back to index
  653. if ( isset($flag) && ( $flag == 'frame' || $flag == 'ajax' ) ) {
  654. die($errorText . ' <a href="index.php">Return to index</a>.');
  655. }
  656. # Finally add it to the $themeReplace array to get it in there
  657. $themeReplace['error'] = '<div id="error">' . $errorText . '</div>';
  658. # And a link to try again?
  659. $return=currentURL();
  660. if (strlen($return)>0) {
  661. $themeReplace['error'] .= '<p style="text-align:right">[<a href="' . htmlentities($return) . '">Reload ' . htmlentities(deproxyURL($return)) . '</a>]</p>';
  662. }
  663. # Start with an empty array
  664. $toShow = array();
  665. # Loop through the available options
  666. foreach ( $CONFIG['options'] as $name => $details ) {
  667. # Check we're allowed to choose
  668. if ( ! empty($details['force']) ) {
  669. continue;
  670. }
  671. # Generate the HTML 'checked' where appropriate
  672. $checked = $options[$name] ? ' checked="checked"' : '';
  673. # Add to the toShow array
  674. $toShow[] = array(
  675. 'name' => $name,
  676. 'title' => $details['title'],
  677. 'desc' => $details['desc'],
  678. 'escaped_desc' => str_replace("'", "\'", $details['desc']),
  679. 'checked' => $checked
  680. );
  681. }
  682. sendNoCache();
  683. $vars2['toShow'] = $toShow;
  684. echo loadTemplate('main', $vars2);
  685. # And flush buffer
  686. ob_end_flush();
  687. exit;
  688. }
  689. # Return current URL (absolute URL to proxied page)
  690. function currentURL() {
  691. # Which method are we using
  692. $method = empty($_SERVER['PATH_INFO']) ? 'QUERY_STRING' : 'PATH_INFO';
  693. # Slash or question
  694. $separator = $method == 'QUERY_STRING' ? '?' : '';
  695. # Return full URL
  696. return GLYPE_BROWSE . $separator . ( isset($_SERVER[$method]) ? $_SERVER[$method] : '');
  697. }
  698. # Check tmp directory and create it if necessary
  699. function checkTmpDir($path, $htaccess=false) {
  700. global $CONFIG;
  701. # Does it already exist?
  702. if ( file_exists($path) ) {
  703. # Return "ok" (true) if folder is writable
  704. if ( is_writable($path) ) {
  705. return 'ok';
  706. }
  707. # Exists but not writable. Nothing else we can do.
  708. return false;
  709. } else {
  710. # Does not exist, can we create it? (No if the desired dir is not
  711. # inside the temp dir)
  712. if ( is_writable($CONFIG['tmp_dir']) && realpath($CONFIG['tmp_dir']) == realpath(dirname($path) . '/') && mkdir($path, 0755, true) ) {
  713. # New dir, protect it with .htaccess
  714. if ( $htaccess ) {
  715. file_put_contents($path . '/.htaccess', $htaccess);
  716. }
  717. # Return (true) "made"
  718. return 'made';
  719. }
  720. }
  721. return false;
  722. }
  723. # Proxify is a registered trademark. All rights reserved.
  724. function proxifyURL($url, $givenFlag = false) {return proxyURL($url,$givenFlag);}
  725. function deproxifyURL($url, $givenFlag = false) {return deproxyURL($url,$givenFlag);}