Advertisement
Guest User

Untitled

a guest
Apr 28th, 2017
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 21.89 KB | None | 0 0
  1. <?php
  2. /*
  3. DodeProxy
  4. */
  5.  
  6. /****************************** START CONFIGURATION ******************************/
  7.  
  8. //To allow proxying any URL, set $whitelistPatterns to an empty array (the default).
  9. //To only allow proxying of specific URLs (whitelist), add corresponding regular expressions
  10. //to the $whitelistPatterns array. Enter the most specific patterns possible, to prevent possible abuse.
  11. //You can optionally use the "getHostnamePattern()" helper function to build a regular expression that
  12. //matches all URLs for a given hostname.
  13. $whitelistPatterns = array(
  14.   //Usage example: To support any URL at example.net, including sub-domains, uncomment the
  15.   //line below (which is equivalent to [ @^https?://([a-z0-9-]+\.)*example\.net@i ]):
  16.   //getHostnamePattern("example.net")
  17. );
  18.  
  19. //To enable CORS (cross-origin resource sharing) for proxied sites, set $forceCORS to true.
  20. $forceCORS = false;
  21.  
  22. /****************************** END CONFIGURATION ******************************/
  23.  
  24. ob_start("ob_gzhandler");
  25.  
  26. if (version_compare(PHP_VERSION, "5.4.7", "<")) {
  27.     die("DodeProxy requires PHP version 5.4.7 or later.");
  28. }
  29.  
  30. if (!function_exists("curl_init")) die("DodeProxy requires PHP's cURL extension. Please install/enable it on your server and try again.");
  31.  
  32. //Helper function for use inside $whitelistPatterns.
  33. //Returns a regex that matches all HTTP[S] URLs for a given hostname.
  34. function getHostnamePattern($hostname) {
  35.   $escapedHostname = str_replace(".", "\.", $hostname);
  36.   return "@^https?://([a-z0-9-]+\.)*" . $escapedHostname . "@i";
  37. }
  38.  
  39. //Helper function used to removes/unset keys from an associative array using case insensitive matching
  40. function removeKeys(&$assoc, $keys2remove) {
  41.   $keys = array_keys($assoc);
  42.   $map = array();
  43.   foreach ($keys as $key) {
  44.      $map[strtolower($key)] = $key;
  45.   }
  46.  
  47.   foreach ($keys2remove as $key) {
  48.     $key = strtolower($key);
  49.     if (isset($map[$key])) {
  50.        unset($assoc[$map[$key]]);
  51.     }
  52.   }
  53. }
  54.  
  55. if (!function_exists("getallheaders")) {
  56.   //Adapted from http://www.php.net/manual/en/function.getallheaders.php#99814
  57.   function getallheaders() {
  58.     $result = array();
  59.     foreach($_SERVER as $key => $value) {
  60.       if (substr($key, 0, 5) == "HTTP_") {
  61.         $key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5)))));
  62.         $result[$key] = $value;
  63.       }
  64.     }
  65.     return $result;
  66.   }
  67. }
  68.  
  69. $usingDefaultPort =  (!isset($_SERVER["HTTPS"]) && $_SERVER["SERVER_PORT"] === 80) || (isset($_SERVER["HTTPS"]) && $_SERVER["SERVER_PORT"] === 443);
  70. $prefixPort = $usingDefaultPort ? "" : ":" . $_SERVER["SERVER_PORT"];
  71. //Use HTTP_HOST to support client-configured DNS (instead of SERVER_NAME), but remove the port if one is present
  72. $prefixHost = $_SERVER["HTTP_HOST"];
  73. $prefixHost = strpos($prefixHost, ":") ? implode(":", explode(":", $_SERVER["HTTP_HOST"], -1)) : $prefixHost;
  74.  
  75. define("PROXY_PREFIX", "http" . (isset($_SERVER["HTTPS"]) ? "s" : "") . "://" . $prefixHost . $prefixPort . $_SERVER["SCRIPT_NAME"] . "?");
  76.  
  77. //Makes an HTTP request via cURL, using request data that was passed directly to this script.
  78. function makeRequest($url) {
  79.  
  80.   //Tell cURL to make the request using the brower's user-agent if there is one, or a fallback user-agent otherwise.
  81.   $user_agent = $_SERVER["HTTP_USER_AGENT"];
  82.   if (empty($user_agent)) {
  83.     $user_agent = "Mozilla/5.0 (compatible; DodeProxy)";
  84.   }
  85.   $ch = curl_init();
  86.   curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
  87.  
  88.   //Get ready to proxy the browser's request headers...
  89.   $browserRequestHeaders = getallheaders();
  90.  
  91.   //...but let cURL set some headers on its own.
  92.   removeKeys($browserRequestHeaders, array(
  93.     "Host",
  94.     "Content-Length",
  95.     "Accept-Encoding" //Throw away the browser's Accept-Encoding header if any and let cURL make the request using gzip if possible.
  96.   ));
  97.  
  98.   curl_setopt($ch, CURLOPT_ENCODING, "");
  99.   //Transform the associative array from getallheaders() into an
  100.   //indexed array of header strings to be passed to cURL.
  101.   $curlRequestHeaders = array();
  102.   foreach ($browserRequestHeaders as $name => $value) {
  103.     $curlRequestHeaders[] = $name . ": " . $value;
  104.   }
  105.   curl_setopt($ch, CURLOPT_HTTPHEADER, $curlRequestHeaders);
  106.  
  107.   //Proxy any received GET/POST/PUT data.
  108.   switch ($_SERVER["REQUEST_METHOD"]) {
  109.     case "POST":
  110.       curl_setopt($ch, CURLOPT_POST, true);
  111.       //For some reason, $HTTP_RAW_POST_DATA isn't working as documented at
  112.       //http://php.net/manual/en/reserved.variables.httprawpostdata.php
  113.       //but the php://input method works. This is likely to be flaky
  114.       //across different server environments.
  115.       //More info here: http://stackoverflow.com/questions/8899239/http-raw-post-data-not-being-populated-after-upgrade-to-php-5-3
  116.       //If the miniProxyFormAction field appears in the POST data, remove it so the destination server doesn't receive it.
  117.       $postData = Array();
  118.       parse_str(file_get_contents("php://input"), $postData);
  119.       if (isset($postData["miniProxyFormAction"])) {
  120.         unset($postData["miniProxyFormAction"]);
  121.       }
  122.       curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData));
  123.     break;
  124.     case "PUT":
  125.       curl_setopt($ch, CURLOPT_PUT, true);
  126.       curl_setopt($ch, CURLOPT_INFILE, fopen("php://input", "r"));
  127.     break;
  128.   }
  129.  
  130.   //Other cURL options.
  131.   curl_setopt($ch, CURLOPT_HEADER, true);
  132.   curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  133.   curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  134.  
  135.   //Set the request URL.
  136.   curl_setopt($ch, CURLOPT_URL, $url);
  137.  
  138.   //Make the request.
  139.   $response = curl_exec($ch);
  140.   $responseInfo = curl_getinfo($ch);
  141.   $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
  142.   curl_close($ch);
  143.  
  144.   //Setting CURLOPT_HEADER to true above forces the response headers and body
  145.   //to be output together--separate them.
  146.   $responseHeaders = substr($response, 0, $headerSize);
  147.   $responseBody = substr($response, $headerSize);
  148.  
  149.   return array("headers" => $responseHeaders, "body" => $responseBody, "responseInfo" => $responseInfo);
  150. }
  151.  
  152. //Converts relative URLs to absolute ones, given a base URL.
  153. //Modified version of code found at http://nashruddin.com/PHP_Script_for_Converting_Relative_to_Absolute_URL
  154. function rel2abs($rel, $base) {
  155.   if (empty($rel)) $rel = ".";
  156.   if (parse_url($rel, PHP_URL_SCHEME) != "" || strpos($rel, "//") === 0) return $rel; //Return if already an absolute URL
  157.   if ($rel[0] == "#" || $rel[0] == "?") return $base.$rel; //Queries and anchors
  158.   extract(parse_url($base)); //Parse base URL and convert to local variables: $scheme, $host, $path
  159.   $path = isset($path) ? preg_replace("#/[^/]*$#", "", $path) : "/"; //Remove non-directory element from path
  160.   if ($rel[0] == "/") $path = ""; //Destroy path if relative url points to root
  161.   $port = isset($port) && $port != 80 ? ":" . $port : "";
  162.   $auth = "";
  163.   if (isset($user)) {
  164.     $auth = $user;
  165.     if (isset($pass)) {
  166.       $auth .= ":" . $pass;
  167.     }
  168.     $auth .= "@";
  169.   }
  170.   $abs = "$auth$host$port$path/$rel"; //Dirty absolute URL
  171.   for ($n = 1; $n > 0; $abs = preg_replace(array("#(/\.?/)#", "#/(?!\.\.)[^/]+/\.\./#"), "/", $abs, -1, $n)) {} //Replace '//' or '/./' or '/foo/../' with '/'
  172.   return $scheme . "://" . $abs; //Absolute URL is ready.
  173. }
  174.  
  175. //Proxify contents of url() references in blocks of CSS text.
  176. function proxifyCSS($css, $baseURL) {
  177.   // Add a "url()" wrapper to any CSS @import rules that only specify a URL without the wrapper,
  178.   // so that they're proxified when searching for "url()" wrappers below.
  179.   $sourceLines = explode("\n", $css);
  180.   $normalizedLines = [];
  181.   foreach ($sourceLines as $line) {
  182.     if (preg_match("/@import\s+url/i", $line)) {
  183.       $normalizedLines[] = $line;
  184.     } else {
  185.       $normalizedLines[] = preg_replace_callback(
  186.         "/(@import\s+)([^;\s]+)([\s;])/i",
  187.         function($matches) use ($baseURL) {
  188.           return $matches[1] . "url(" . $matches[2] . ")" . $matches[3];
  189.         },
  190.         $line);
  191.     }
  192.   }
  193.   $normalizedCSS = implode("\n", $normalizedLines);
  194.   return preg_replace_callback(
  195.     "/url\((.*?)\)/i",
  196.     function($matches) use ($baseURL) {
  197.         $url = $matches[1];
  198.         //Remove any surrounding single or double quotes from the URL so it can be passed to rel2abs - the quotes are optional in CSS
  199.         //Assume that if there is a leading quote then there should be a trailing quote, so just use trim() to remove them
  200.         if (strpos($url, "'") === 0) {
  201.           $url = trim($url, "'");
  202.         }
  203.         if (strpos($url, "\"") === 0) {
  204.           $url = trim($url, "\"");
  205.         }
  206.         if (stripos($url, "data:") === 0) return "url(" . $url . ")"; //The URL isn't an HTTP URL but is actual binary data. Don't proxify it.
  207.         return "url(" . PROXY_PREFIX . rel2abs($url, $baseURL) . ")";
  208.     },
  209.     $normalizedCSS);
  210. }
  211.  
  212. //Proxify "srcset" attributes (normally associated with <img> tags.)
  213. function proxifySrcset($srcset, $baseURL) {
  214.   $sources = array_map("trim", explode(",", $srcset)); //Split all contents by comma and trim each value
  215.   $proxifiedSources = array_map(function($source) use ($baseURL) {
  216.     $components = array_map("trim", str_split($source, strrpos($source, " "))); //Split by last space and trim
  217.     $components[0] = PROXY_PREFIX . rel2abs(ltrim($components[0], "/"), $baseURL); //First component of the split source string should be an image URL; proxify it
  218.     return implode($components, " "); //Recombine the components into a single source
  219.   }, $sources);
  220.   $proxifiedSrcset = implode(", ", $proxifiedSources); //Recombine the sources into a single "srcset"
  221.   return $proxifiedSrcset;
  222. }
  223.  
  224. //Extract and sanitize the requested URL, handling cases where forms have been rewritten to point to the proxy.
  225. if (isset($_POST["miniProxyFormAction"])) {
  226.   $url = $_POST["miniProxyFormAction"];
  227.   unset($_POST["miniProxyFormAction"]);
  228. } else {
  229.   $queryParams = Array();
  230.   parse_str($_SERVER["QUERY_STRING"], $queryParams);
  231.   if (isset($queryParams["miniProxyFormAction"])) {
  232.     $formAction = $queryParams["miniProxyFormAction"];
  233.     unset($queryParams["miniProxyFormAction"]);
  234.     $url = $formAction . "?" . http_build_query($queryParams);
  235.   } else {
  236.     $url = substr($_SERVER["REQUEST_URI"], strlen($_SERVER["SCRIPT_NAME"]) + 1);
  237.   }
  238. }
  239. if (empty($url)) {
  240.     echo "<body style='background: url(http://2.bp.blogspot.com/-4GWPZCJJUyk/VhdLOukxqII/AAAAAAAAB5o/67PpyZF0sMk/s1600/T%25E1%25BA%25A3i%2Bh%25C3%25ACnh%2B%25E1%25BA%25A3nh%2Bn%25E1%25BB%2581n%2BHacker%2B%25C4%2591%25E1%25BA%25B9p%2Bnh%25E1%25BA%25A5t%2Bfull%2BHD25.jpg);'>;background-size: cover; background-repeat: none; background-color: black;"   
  241.     echo "<h2><div style=\"color: green;\">Please pardon any bugs, as this is only Beta Mode!</div></h2>";"background-size: cover; background-repeat: none; background-color black;"
  242.     echo "<p><div style=\"color: green;\">DodeProxy can be directly invoked like this: http://www.skidz.xyz:80/Home/bypass.php?http://example.net/</div></p>";
  243.     echo "<p><div style=\"color: green;\">Or you can simply put the URL you would like to visit below!</div></p>";
  244.     die("<html><br /><br /><form onsubmit=\"window.location.href='" . PROXY_PREFIX . "' + document.getElementById('site').value; return false;\"><input id=\"site\" type=\"text\" size=\"50\" /><input type=\"submit\" value=\"Proxy It!\" /></form></body></html>");
  245. } else if (strpos($url, ":/") !== strpos($url, "://")) {
  246.     $pos = strpos($url, ":/");
  247.     $url = substr_replace($url, "://", $pos, strlen(":/"));
  248. }
  249. $scheme = parse_url($url, PHP_URL_SCHEME);
  250. if (empty($scheme)) {
  251.   //Assume that any supplied URLs starting with // are HTTP URLs.
  252.   if (strpos($url, "//") === 0) {
  253.     $url = "http:" . $url;
  254.   }
  255. } else if (!preg_match("/^https?$/i", $scheme)) {
  256.     die('Error: Detected a "' . $scheme . '" URL. miniProxy exclusively supports http[s] URLs.');
  257. }
  258.  
  259. //Validate the requested URL against the whitelist.
  260. $urlIsValid = count($whitelistPatterns) === 0;
  261. foreach ($whitelistPatterns as $pattern) {
  262.   if (preg_match($pattern, $url)) {
  263.     $urlIsValid = true;
  264.     break;
  265.   }
  266. }
  267. if (!$urlIsValid) {
  268.   die("Error: The requested URL was disallowed by the server administrator. Sorry :'( -Dode");
  269. }
  270.  
  271. $response = makeRequest($url);
  272. $rawResponseHeaders = $response["headers"];
  273. $responseBody = $response["body"];
  274. $responseInfo = $response["responseInfo"];
  275.  
  276. //If CURLOPT_FOLLOWLOCATION landed the proxy at a diferent URL than
  277. //what was requested, explicitly redirect the proxy there.
  278. $responseURL = $responseInfo["url"];
  279. if ($responseURL !== $url) {
  280.   header("Location: " . PROXY_PREFIX . $responseURL, true);
  281.   exit(0);
  282. }
  283.  
  284. //A regex that indicates which server response headers should be stripped out of the proxified response.
  285. $header_blacklist_pattern = "/^Content-Length|^Transfer-Encoding|^Content-Encoding.*gzip/i";
  286.  
  287. //cURL can make multiple requests internally (for example, if CURLOPT_FOLLOWLOCATION is enabled), and reports
  288. //headers for every request it makes. Only proxy the last set of received response headers,
  289. //corresponding to the final request made by cURL for any given call to makeRequest().
  290. $responseHeaderBlocks = array_filter(explode("\r\n\r\n", $rawResponseHeaders));
  291. $lastHeaderBlock = end($responseHeaderBlocks);
  292. $headerLines = explode("\r\n", $lastHeaderBlock);
  293. foreach ($headerLines as $header) {
  294.   $header = trim($header);
  295.   if (!preg_match($header_blacklist_pattern, $header)) {
  296.     header($header, false);
  297.   }
  298. }
  299. //Prevent robots from indexing proxified pages
  300. header("X-Robots-Tag: noindex, nofollow", true);
  301.  
  302. if ($forceCORS) {
  303.   //This logic is based on code found at: http://stackoverflow.com/a/9866124/278810
  304.   //CORS headers sent below may conflict with CORS headers from the original response,
  305.   //so these headers are sent after the original response headers to ensure their values
  306.   //are the ones that actually end up getting sent to the browser.
  307.   //Explicit [ $replace = true ] is used for these headers even though this is PHP's default behavior.
  308.  
  309.   //Allow access from any origin.
  310.   header("Access-Control-Allow-Origin: *", true);
  311.   header("Access-Control-Allow-Credentials: true", true);
  312.  
  313.   //Handle CORS headers received during OPTIONS requests.
  314.   if ($_SERVER["REQUEST_METHOD"] == "OPTIONS") {
  315.     if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_METHOD"])) {
  316.       header("Access-Control-Allow-Methods: GET, POST, OPTIONS", true);
  317.     }
  318.     if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_HEADERS"])) {
  319.       header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}", true);
  320.     }
  321.     //No further action is needed for OPTIONS requests.
  322.     exit(0);
  323.   }
  324.  
  325. }
  326.  
  327. $contentType = "";
  328. if (isset($responseInfo["content_type"])) $contentType = $responseInfo["content_type"];
  329.  
  330. //This is presumably a web page, so attempt to proxify the DOM.
  331. if (stripos($contentType, "text/html") !== false) {
  332.  
  333.   //Attempt to normalize character encoding.
  334.   $detectedEncoding = mb_detect_encoding($responseBody, "UTF-8, ISO-8859-1");
  335.   if ($detectedEncoding) {
  336.     $responseBody = mb_convert_encoding($responseBody, "HTML-ENTITIES", $detectedEncoding);
  337.   }
  338.  
  339.   //Parse the DOM.
  340.   $doc = new DomDocument();
  341.   @$doc->loadHTML($responseBody);
  342.   $xpath = new DOMXPath($doc);
  343.  
  344.   //Rewrite forms so that their actions point back to the proxy.
  345.   foreach($xpath->query("//form") as $form) {
  346.     $method = $form->getAttribute("method");
  347.     $action = $form->getAttribute("action");
  348.     //If the form doesn't have an action, the action is the page itself.
  349.     //Otherwise, change an existing action to an absolute version.
  350.     $action = empty($action) ? $url : rel2abs($action, $url);
  351.     //Rewrite the form action to point back at the proxy.
  352.     $form->setAttribute("action", rtrim(PROXY_PREFIX, "?"));
  353.     //Add a hidden form field that the proxy can later use to retreive the original form action.
  354.     $actionInput = $doc->createDocumentFragment();
  355.     $actionInput->appendXML('<input type="hidden" name="miniProxyFormAction" value="' . htmlspecialchars($action) . '" />');
  356.     $form->appendChild($actionInput);
  357.   }
  358.   //Proxify <meta> tags with an 'http-equiv="refresh"' attribute.
  359.   foreach ($xpath->query("//meta[@http-equiv]") as $element) {
  360.     if (strcasecmp($element->getAttribute("http-equiv"), "refresh") === 0) {
  361.       $content = $element->getAttribute("content");
  362.       if (!empty($content)) {
  363.         $splitContent = preg_split("/=/", $content);
  364.         if (isset($splitContent[1])) {
  365.           $element->setAttribute("content", $splitContent[0] . "=" . PROXY_PREFIX . rel2abs($splitContent[1], $url));
  366.         }
  367.       }
  368.     }
  369.   }
  370.   //Profixy <style> tags.
  371.   foreach($xpath->query("//style") as $style) {
  372.     $style->nodeValue = proxifyCSS($style->nodeValue, $url);
  373.   }
  374.   //Proxify tags with a "style" attribute.
  375.   foreach ($xpath->query("//*[@style]") as $element) {
  376.     $element->setAttribute("style", proxifyCSS($element->getAttribute("style"), $url));
  377.   }
  378.   //Proxify "srcset" attributes in <img> tags.
  379.   foreach ($xpath->query("//img[@srcset]") as $element) {
  380.     $element->setAttribute("srcset", proxifySrcset($element->getAttribute("srcset"), $url));
  381.   }
  382.   //Proxify any of these attributes appearing in any tag.
  383.   $proxifyAttributes = array("href", "src");
  384.   foreach($proxifyAttributes as $attrName) {
  385.     foreach($xpath->query("//*[@" . $attrName . "]") as $element) { //For every element with the given attribute...
  386.       $attrContent = $element->getAttribute($attrName);
  387.       if ($attrName == "href" && preg_match("/^(about|javascript|magnet|mailto):/i", $attrContent)) continue;
  388.       $attrContent = rel2abs($attrContent, $url);
  389.       $attrContent = PROXY_PREFIX . $attrContent;
  390.       $element->setAttribute($attrName, $attrContent);
  391.     }
  392.   }
  393.  
  394.   //Attempt to force AJAX requests to be made through the proxy by
  395.   //wrapping window.XMLHttpRequest.prototype.open in order to make
  396.   //all request URLs absolute and point back to the proxy.
  397.   //The rel2abs() JavaScript function serves the same purpose as the server-side one in this file,
  398.   //but is used in the browser to ensure all AJAX request URLs are absolute and not relative.
  399.   //Uses code from these sources:
  400.   //http://stackoverflow.com/questions/7775767/javascript-overriding-xmlhttprequest-open
  401.   //https://gist.github.com/1088850
  402.   //TODO: This is obviously only useful for browsers that use XMLHttpRequest but
  403.   //it's better than nothing.
  404.  
  405.   $head = $xpath->query("//head")->item(0);
  406.   $body = $xpath->query("//body")->item(0);
  407.   $prependElem = $head != NULL ? $head : $body;
  408.  
  409.   //Only bother trying to apply this hack if the DOM has a <head> or <body> element;
  410.   //insert some JavaScript at the top of whichever is available first.
  411.   //Protects against cases where the server sends a Content-Type of "text/html" when
  412.   //what's coming back is most likely not actually HTML.
  413.   //TODO: Do this check before attempting to do any sort of DOM parsing?
  414.   if ($prependElem != NULL) {
  415.  
  416.     $scriptElem = $doc->createElement("script",
  417.       '(function() {
  418.  
  419.        if (window.XMLHttpRequest) {
  420.  
  421.          function parseURI(url) {
  422.            var m = String(url).replace(/^\s+|\s+$/g, "").match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);
  423.            // authority = "//" + user + ":" + pass "@" + hostname + ":" port
  424.            return (m ? {
  425.              href : m[0] || "",
  426.              protocol : m[1] || "",
  427.              authority: m[2] || "",
  428.              host : m[3] || "",
  429.              hostname : m[4] || "",
  430.              port : m[5] || "",
  431.              pathname : m[6] || "",
  432.              search : m[7] || "",
  433.              hash : m[8] || ""
  434.            } : null);
  435.          }
  436.  
  437.          function rel2abs(base, href) { // RFC 3986
  438.  
  439.            function removeDotSegments(input) {
  440.              var output = [];
  441.              input.replace(/^(\.\.?(\/|$))+/, "")
  442.                .replace(/\/(\.(\/|$))+/g, "/")
  443.                .replace(/\/\.\.$/, "/../")
  444.                .replace(/\/?[^\/]*/g, function (p) {
  445.                  if (p === "/..") {
  446.                    output.pop();
  447.                  } else {
  448.                    output.push(p);
  449.                  }
  450.                });
  451.              return output.join("").replace(/^\//, input.charAt(0) === "/" ? "/" : "");
  452.            }
  453.  
  454.            href = parseURI(href || "");
  455.            base = parseURI(base || "");
  456.  
  457.            return !href || !base ? null : (href.protocol || base.protocol) +
  458.            (href.protocol || href.authority ? href.authority : base.authority) +
  459.            removeDotSegments(href.protocol || href.authority || href.pathname.charAt(0) === "/" ? href.pathname : (href.pathname ? ((base.authority && !base.pathname ? "/" : "") + base.pathname.slice(0, base.pathname.lastIndexOf("/") + 1) + href.pathname) : base.pathname)) +
  460.            (href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) +
  461.            href.hash;
  462.  
  463.          }
  464.  
  465.          var proxied = window.XMLHttpRequest.prototype.open;
  466.          window.XMLHttpRequest.prototype.open = function() {
  467.              if (arguments[1] !== null && arguments[1] !== undefined) {
  468.                var url = arguments[1];
  469.                url = rel2abs("' . $url . '", url);
  470.                url = "' . PROXY_PREFIX . '" + url;
  471.                arguments[1] = url;
  472.              }
  473.              return proxied.apply(this, [].slice.call(arguments));
  474.          };
  475.  
  476.        }
  477.  
  478.      })();'
  479.     );
  480.     $scriptElem->setAttribute("type", "text/javascript");
  481.  
  482.     $prependElem->insertBefore($scriptElem, $prependElem->firstChild);
  483.  
  484.   }
  485.  
  486.   echo "<!-- Proxified page constructed by Hazmat & Dode -->\n" . $doc->saveHTML();
  487. } else if (stripos($contentType, "text/css") !== false) { //This is CSS, so proxify url() references.
  488.   echo proxifyCSS($responseBody, $url);
  489. } else { //This isn't a web page or CSS, so serve unmodified through the proxy with the correct headers (images, JavaScript, etc.)
  490.   header("Content-Length: " . strlen($responseBody), true);
  491.   echo $responseBody;
  492. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement