public static function addGoogleAnalyticsId($id)
    {
        static $i;
        if (!isset($i)) {
            $i = 0;
        }
        $i++;
        $name = 'wmbp' . $i;
        $ga_script = <<<EOF
<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

  ga('create', '{$id}', 'auto', {'name': '{$name}'});
  ga('{$name}.send', 'pageview');

</script>
EOF;
        // Appends to main page / iframe container.
        RedirectWhenBlockedFull::appendToHtmlBody($ga_script);
        // Appends to iframed content.
        self::appendToHtmlBody($ga_script);
    }
 function run()
 {
     if (count(RedirectWhenBlockedFull::getAltBaseUrls()) == 0) {
         $this->messages[] = 'Empty alt base urls';
         return;
     }
     $domains = array();
     foreach (RedirectWhenBlockedFull::getAltBaseUrls() as $url) {
         // Test DNS poisoning.
         $domain = parse_url($url, PHP_URL_HOST);
         $domains[] = $domain;
     }
     if (!Conf::$china_ip_for_dns_poisoning_test) {
         $this->messages[] = 'china_ip_for_dns_poisoning_test not set';
         $this->n_failed++;
     } else {
         $command = '';
         foreach ($domains as $domain) {
             $command .= '(dig +time=5 +tries=1 @' . Conf::$china_ip_for_dns_poisoning_test . ' ' . $domain . ' > /dev/null ; echo "' . $domain . ':"$?)  & ';
         }
         $command = trim($command) . '& wait';
         exec($command, $output);
         $n_domains_not_poisoned = 0;
         foreach ($output as $line) {
             $line_chunks = explode(':', $line, 2);
             if (count($line_chunks) == 2 && $line_chunks[0] && $line_chunks[1] >= 0) {
                 list($domain, $dig_exit_code) = $line_chunks;
                 if ($dig_exit_code == 0) {
                     $this->messages[] = $domain . ' is poisoned (' . $dig_exit_code . ')';
                 } else {
                     $this->messages[] = $domain . ' is not poisoned (' . $dig_exit_code . ')';
                     $n_domains_not_poisoned++;
                 }
             } else {
                 $this->messages[] = 'unknown dig result (' . $line . ')';
             }
         }
         if (!$n_domains_not_poisoned) {
             $this->messages[] = 'no unpoisoned domains available';
             $this->n_failed++;
         }
     }
     $alt_base_urls_file = dirname(dirname(__DIR__)) . '/rwb/conf/alt_base_urls.txt';
     $alt_base_urls_modified_ago = time() - filemtime($alt_base_urls_file);
     $this->messages[] = "{$alt_base_urls_file} modified {$alt_base_urls_modified_ago} seconds ago";
     if ($alt_base_urls_modified_ago > Conf::$alt_base_urls_modified_ago_max) {
         $this->messages[] = "{$alt_base_urls_file} expired";
         return false;
     }
     return true;
 }
function getDownstreamOrigin()
{
    static $downstream_origin_verified;
    if (!isset($downstream_origin_verified)) {
        $downstream_origin_verified = NULL;
        if (isset($_SERVER['HTTP_ORIGIN'])) {
            $downstream_origin = $_SERVER['HTTP_ORIGIN'];
        } elseif (isset($_SERVER['HTTP_REFERER'])) {
            $downstream_origin = http_build_scheme_host($_SERVER['HTTP_REFERER']);
        }
        if (isset($downstream_origin)) {
            foreach (RedirectWhenBlockedFull::getAltBaseUrls() as $alt_url_base) {
                if ($downstream_origin == http_build_scheme_host($alt_url_base)) {
                    $downstream_origin_verified = $downstream_origin;
                    break;
                }
            }
        }
    }
    return $downstream_origin_verified;
}
<?php

$apk_url = RedirectWhenBlockedFull::getBaseUrl() . '?' . RedirectWhenBlockedFull::QUERY_STRING_PARAM_NAME . '=' . Conf::OUTPUT_TYPE_APK;
$url = 'https://chart.googleapis.com/chart?chs=200x200&cht=qr&chl=' . urlencode($apk_url) . '&choe=UTF-8';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
curl_close($ch);
if ($response) {
    header('Cache-Control: ' . getCacheControlHeader(60 * 60 * 24, 60 * 60 * 24 * 7, 60 * 60 * 24 * 7));
    header('Content-Type: image/png');
    print $response;
}
 public function getUrl()
 {
     static $url;
     if (!isset($url)) {
         if (isset($_GET[RedirectWhenBlockedFull::QUERY_STRING_PARAM_NAME]) && $_GET[RedirectWhenBlockedFull::QUERY_STRING_PARAM_NAME] == Conf::OUTPUT_TYPE_APK && Conf::$apk_url) {
             $url = Conf::$apk_url;
             $filename = basename(parse_url($url, PHP_URL_PATH));
             header('Content-Disposition: attachment; filename=' . $filename);
             // Run after all other code to override other content-type header.
             register_shutdown_function(function () {
                 header('Content-Type: application/vnd.android.package-archive');
             });
         } else {
             $url = RedirectWhenBlockedFull::getRequestUriWithoutQueryStringParam();
             $this->removeThisScriptDirFromUrl($url);
             if (startsWith($url, '/http://') || startsWith($url, '/https://')) {
                 $url = substr($url, 1);
                 if (!TextExternalUrlFilters::matchesUrl($url)) {
                     header('HTTP/1.0 403 Forbidden');
                     exit;
                 }
                 // If we for some reason have the default upstream host and scheme in the URL, remove them.
                 $url_components = parse_url($url);
                 if ($url_components['host'] == Conf::getDefaultUpstreamBaseUrlComponent('host') && $url_components['scheme'] == Conf::getDefaultUpstreamBaseUrlComponent('scheme')) {
                     $new_url = http_build_path_query_fragment($url_components);
                     $new_url = RedirectWhenBlockedFull::getBaseUrl() . ltrim($new_url, '/');
                     header('Location: ' . $new_url);
                     exit;
                 }
                 // Use in DomUtlFilters for relative URLs.
                 $base_url_suffix = rtrim(http_build_scheme_host($url), '/') . '/';
                 RedirectWhenBlockedFull::setBaseUrlSuffix($base_url_suffix);
             } else {
                 if ($url == '/') {
                     if (Conf::$default_upstream_url) {
                         $url = Conf::$default_upstream_url;
                     }
                 }
                 $url = Conf::$default_upstream_base_url . $url;
             }
         }
     }
     // Reverse rewrites of parameters inside URL.
     TextExternalUrlFilters::applyReverse($url);
     Log::add($url, 'url');
     return $url;
 }
Пример #6
0
     exit;
 }
 if ($_GET[RedirectWhenBlockedFull::QUERY_STRING_PARAM_NAME] == Conf::OUTPUT_TYPE_APK_URLS) {
     header('Content-Type: application/javascript');
     $urls = array();
     foreach (RedirectWhenBlockedFull::getAltBaseUrls() as $url) {
         $url .= '?' . RedirectWhenBlockedFull::QUERY_STRING_PARAM_NAME . '=' . Conf::OUTPUT_TYPE_APK;
         $urls[] = $url;
     }
     print json_encode($urls);
     exit;
 }
 if ($_GET[RedirectWhenBlockedFull::QUERY_STRING_PARAM_NAME] == Conf::OUTPUT_TYPE_APP_URLS) {
     header('Content-Type: application/javascript');
     $urls = array();
     foreach (RedirectWhenBlockedFull::getAltBaseUrls() as $url) {
         $url .= '?' . RedirectWhenBlockedFull::QUERY_STRING_PARAM_NAME . '=' . Conf::OUTPUT_TYPE_APP;
         $urls[] = $url;
     }
     print json_encode($urls);
     exit;
 }
 if ($_GET[RedirectWhenBlockedFull::QUERY_STRING_PARAM_NAME] == Conf::OUTPUT_TYPE_STATUS) {
     header('Cache-Control: max-age=0');
     header('Content-Type: text/plain');
     require 'status_tests/StatusTest.inc';
     foreach (scandir('status_tests/enabled') as $file) {
         if ($file[0] == '.') {
             continue;
         }
         require 'status_tests/enabled/' . $file;
Пример #7
0
<?php

if (!defined('WEBSITE_TITLE')) {
    define('WEBSITE_TITLE', 'Redirect When Blocked Full Edition Demo Website Index');
}
require 'rwb/RedirectWhenBlockedFull.inc';
RedirectWhenBlockedFull::setUrlsFromConfDir();
RedirectWhenBlockedFull::setWebsiteTitle(WEBSITE_TITLE);
RedirectWhenBlockedFull::run();
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><?php 
print WEBSITE_TITLE;
?>
</title>
</head>
<body>
	<h1><?php 
print WEBSITE_TITLE;
?>
</h1>
	<p>Current time: <?php 
print date('Y-m-d H:i:s');
?>
</p>
	<ul>
		<li><a href="index.php">Index</a></li>
		<li><a href="slow.php">Slow Page</a></li>
 private static function getBaseUrlHostAndPath()
 {
     static $host_and_path;
     if (!isset($host_and_path)) {
         $base_url_components = parse_url(RedirectWhenBlockedFull::getBaseUrl());
         $host_and_path = $base_url_components['host'];
         if (isset($base_url_components['path'])) {
             $host_and_path .= $base_url_components['path'];
         }
     }
     return $host_and_path;
 }
 public static function setWebsiteTitle($website_title)
 {
     self::$website_title = $website_title;
 }
 private function getBodyFilteredByContentType($body, $content_type)
 {
     switch ($content_type) {
         case self::CONTENT_TYPE_TEXT_CSS:
             $css_base_url = $this->getCssBaseUrl();
             // Convert protocol relative URLs to HTTPS.
             $body = str_replace('url(//', 'url(https://', $body);
             $body = str_replace('url("//', 'url("https://', $body);
             $body = str_replace('url(\'//', 'url(\'https://', $body);
             // Disabling this part. Not sure why it was added in the first place.
             /*
              * $body = str_replace('url("../', 'url("' . $css_base_url . '../',
              * $body);
              * $body = str_replace('url(\'../',
              * 'url(\'' . $css_base_url . '../', $body);
              * $body = str_replace('url(../', 'url(' . $css_base_url . '../',
              * $body);
              */
             $body = str_replace('url("/', 'url("' . $css_base_url, $body);
             $body = str_replace('url(\'/', 'url(\'' . $css_base_url, $body);
             $body = str_replace('url(/', 'url(' . $css_base_url, $body);
             break;
         case self::CONTENT_TYPE_TEXT_HTML:
             $dom = $this->getDomFromHtml($body);
             if ($dom) {
                 foreach ($dom->find('head title') as $title_element) {
                     $title = mb_convert_encoding_plus($title_element->text(), 'UTF-8', $this->getCharsetFromHeadersOrDom($dom));
                     if ($title) {
                         $title .= ' | 免翻墙镜像';
                         // Update title in DOM.
                         $title_element->innertext = mb_convert_encoding_plus($title, $this->getCharsetFromHeadersOrDom($dom), 'UTF-8');
                         break;
                     }
                 }
             }
             // Default title.
             if (!isset($title) || !$title) {
                 $title = '免翻墙镜像';
             }
             // Special - override meta redirects since RWB would just slow them down.
             if ($dom && count($dom->find('<META[http-equiv=refresh]'))) {
                 foreach ($dom->find('<META[http-equiv=refresh]') as $meta) {
                     $content = $meta->getAttribute('content');
                     if ($content) {
                         $content_chunks = explode(';', $content, 2);
                         if (isset($content_chunks[1])) {
                             $url_chunks = explode('=', $content_chunks[1], 2);
                             if (isset($url_chunks[1])) {
                                 $url = trim($url_chunks[1], '\'" ');
                                 if ($url) {
                                     $this->headers['Location'] = $url;
                                     return '';
                                 }
                             }
                         }
                     }
                 }
             }
             if ($this->shouldUseRedirectWhenBlocked()) {
                 RedirectWhenBlockedFull::setCharset($this->getCharsetFromHeadersOrDom($dom));
                 RedirectWhenBlockedFull::setWebsiteTitle($title);
                 RedirectWhenBlockedFull::run();
                 if (RedirectWhenBlockedFull::getOutputType() == RedirectWhenBlockedFull::OUTPUT_TYPE_JSONP) {
                     // RWB will turn output into JSONP. Remove content-type header to keep header sent by RWB.
                     if (isset($this->headers['Content-Type'])) {
                         unset($this->headers['Content-Type']);
                     }
                     // Also remove charset specification in inline HTML.
                     if ($dom) {
                         foreach ($dom->find('meta[http-equiv=Content-Type], meta[charset]') as $meta) {
                             $meta->outertext = '';
                         }
                     }
                 }
             }
             // Might be for example JSONP data served with an incorrect header.
             if (!$dom || !$dom->find('body')) {
                 break;
             }
             DomUrlFilters::applyAll($dom, $this->request);
             // Special for iframes. Prevent RWB from hijacking content (iframe in iframe problem).
             foreach ($dom->find('iframe') as $iframe) {
                 $src = $iframe->getAttribute('src');
                 if ($src) {
                     $src = http_add_query_component($src, RedirectWhenBlockedFull::QUERY_STRING_PARAM_NAME, RedirectWhenBlockedFull::OUTPUT_TYPE_IFRAME);
                     $iframe->setAttribute('src', $src);
                 }
             }
             // Special for style attributes - apply CSS filter.
             foreach ($dom->find('*[style]') as $style_element) {
                 $style_element->setAttribute('style', $this->getBodyFilteredByContentType($style_element->getAttribute('style'), self::CONTENT_TYPE_TEXT_CSS));
             }
             $dom_do_reset = false;
             // Don't insert stuff if request failed.
             if ($this->getResponseCode() == 200) {
                 if (Conf::$html_body_appendix) {
                     foreach ($dom->find('body') as $b) {
                         $b->innertext .= Conf::$html_body_appendix;
                         break;
                     }
                     $dom_do_reset = true;
                 }
                 if (Conf::$html_head_appendix) {
                     foreach ($dom->find('head') as $h) {
                         $h->innertext .= Conf::$html_head_appendix;
                         break;
                     }
                     $dom_do_reset = true;
                 }
             }
             if (count($dom->find('script[async]'))) {
                 if ($dom_do_reset) {
                     // Bug in Simple HTML Dom means that DOM has to be reloaded before further edits.
                     $this->resetDom($dom);
                     $dom_do_reset = false;
                 }
                 // Remove 'async' attributes because they break the page in IE11 when loaded in our iframe.
                 foreach ($dom->find('script[async]') as $x) {
                     $x->removeAttribute('async', '');
                 }
             }
             if (count($dom->find('style'))) {
                 if ($dom_do_reset) {
                     // Bug in Simple HTML Dom means that DOM has to be reloaded before further edits.
                     $this->resetDom($dom);
                     $dom_do_reset = false;
                 }
                 foreach ($dom->find('style') as $style) {
                     $style->innertext = $this->getBodyFilteredByContentType($style->innertext, self::CONTENT_TYPE_TEXT_CSS);
                 }
             }
             $body = $dom->__toString();
             $this->destroyDom($dom);
             break;
     }
     return $body;
 }