You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
5.7 KiB
PHP
186 lines
5.7 KiB
PHP
<?php
|
|
|
|
namespace Proxy\Plugin;
|
|
|
|
use Proxy\Plugin\AbstractPlugin;
|
|
use Proxy\Event\ProxyEvent;
|
|
use Proxy\Config;
|
|
use Proxy\Html;
|
|
|
|
class ProxifyPlugin extends AbstractPlugin {
|
|
|
|
private $base_url = '';
|
|
|
|
private function css_url($matches){
|
|
|
|
$url = trim($matches[1]);
|
|
|
|
if(stripos($url, 'data:') === 0){
|
|
return $matches[0];
|
|
}
|
|
|
|
return str_replace($matches[1], proxify_url($matches[1], $this->base_url), $matches[0]);
|
|
}
|
|
|
|
// this.params.logoImg&&(e="background-image: url("+this.params.logoImg+")")
|
|
private function css_import($matches){
|
|
return str_replace($matches[2], proxify_url($matches[2], $this->base_url), $matches[0]);
|
|
}
|
|
|
|
// replace src= and href=
|
|
private function html_attr($matches){
|
|
|
|
// could be empty?
|
|
$url = trim($matches[2]);
|
|
|
|
if(stripos($url, 'data:') === 0 || stripos($url, 'magnet:') === 0 ){
|
|
return $matches[0];
|
|
}
|
|
|
|
return str_replace($url, proxify_url($url, $this->base_url), $matches[0]);
|
|
}
|
|
|
|
private function form_action($matches){
|
|
|
|
// sometimes form action is empty - which means a postback to the current page
|
|
// $matches[1] holds single or double quote - whichever was used by webmaster
|
|
|
|
// $matches[2] holds form submit URL - can be empty which in that case should be replaced with current URL
|
|
if(!$matches[2]){
|
|
$matches[2] = $this->base_url;
|
|
}
|
|
|
|
$new_action = proxify_url($matches[2], $this->base_url);
|
|
|
|
// what is form method?
|
|
$form_post = preg_match('@method=(["\'])post\1@i', $matches[0]) == 1;
|
|
|
|
// take entire form string - find real url and replace it with proxified url
|
|
$result = str_replace($matches[2], $new_action, $matches[0]);
|
|
|
|
// must be converted to POST otherwise GET form would just start appending name=value pairs to your proxy url
|
|
if(!$form_post){
|
|
|
|
// may throw Duplicate Attribute warning but only first method matters
|
|
$result = str_replace("<form", '<form method="POST"', $result);
|
|
|
|
// got the idea from Glype - insert this input field to notify proxy later that this form must be converted to GET during http
|
|
$result .= '<input type="hidden" name="convertGET" value="1">';
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function onBeforeRequest(ProxyEvent $event){
|
|
|
|
$request = $event['request'];
|
|
|
|
// check if one of the POST pairs is convertGET - if so, convert this request to GET
|
|
if($request->post->has('convertGET')){
|
|
|
|
// we don't need this parameter anymore
|
|
$request->post->remove('convertGET');
|
|
|
|
// replace all GET parameters with POST data
|
|
$request->get->replace($request->post->all());
|
|
|
|
// remove POST data
|
|
$request->post->clear();
|
|
|
|
// This is now a GET request
|
|
$request->setMethod('GET');
|
|
|
|
$request->prepare();
|
|
}
|
|
}
|
|
|
|
private function meta_refresh($matches){
|
|
$url = $matches[2];
|
|
return str_replace($url, proxify_url($url, $this->base_url), $matches[0]);
|
|
}
|
|
|
|
// <title>, <base>, <link>, <style>, <meta>, <script>, <noscript>
|
|
private function proxify_head($str){
|
|
|
|
// let's replace page titles with something custom
|
|
if(Config::get('replace_title')){
|
|
$str = preg_replace('/<title[^>]*>(.*?)<\/title>/is', '<title>'.Config::get('replace_title').'</title>', $str);
|
|
}
|
|
|
|
|
|
// base - update base_url contained in href - remove <base> tag entirely
|
|
//$str = preg_replace_callback('/<base[^>]*href=
|
|
|
|
// link - replace href with proxified
|
|
// link rel="shortcut icon" - replace or remove
|
|
|
|
// meta - only interested in http-equiv - replace url refresh
|
|
// <meta http-equiv="refresh" content="5; url=http://example.com/">
|
|
$str = preg_replace_callback('/content=(["\'])\d+\s*;\s*url=(.*?)\1/is', array($this, 'meta_refresh'), $str);
|
|
|
|
return $str;
|
|
}
|
|
|
|
// The <body> background attribute is not supported in HTML5. Use CSS instead.
|
|
private function proxify_css($str){
|
|
|
|
// The HTML5 standard does not require quotes around attribute values.
|
|
|
|
// if {1} is not there then youtube breaks for some reason
|
|
$str = preg_replace_callback('@[^a-z]{1}url\s*\((?:\'|"|)(.*?)(?:\'|"|)\)@im', array($this, 'css_url'), $str);
|
|
|
|
// https://developer.mozilla.org/en-US/docs/Web/CSS/@import
|
|
// TODO: what about @import directives that are outside <style>?
|
|
$str = preg_replace_callback('/@import (\'|")(.*?)\1/i', array($this, 'css_import'), $str);
|
|
|
|
return $str;
|
|
}
|
|
|
|
public function onCompleted(ProxyEvent $event){
|
|
|
|
// to be used when proxifying all the relative links
|
|
$this->base_url = $event['request']->getUri();
|
|
|
|
$response = $event['response'];
|
|
$content_type = $response->headers->get('content-type');
|
|
|
|
$str = $response->getContent();
|
|
|
|
// DO NOT do any proxification on .js files and text/plain content type
|
|
if($content_type == 'text/javascript' || $content_type == 'application/javascript' || $content_type == 'application/x-javascript' || $content_type == 'text/plain'){
|
|
return;
|
|
}
|
|
|
|
// remove JS from urls
|
|
$js_remove = Config::get('js_remove');
|
|
if(is_array($js_remove)){
|
|
$domain = parse_url($this->base_url, PHP_URL_HOST);
|
|
|
|
foreach($js_remove as $pattern){
|
|
if(strpos($domain, $pattern) !== false){
|
|
$str = Html::remove_scripts($str);
|
|
}
|
|
}
|
|
}
|
|
|
|
// add html.no-js
|
|
|
|
// let's remove all frames?? does not protect against the frames created dynamically via javascript
|
|
$str = preg_replace('@<iframe[^>]*>[^<]*<\\/iframe>@is', '', $str);
|
|
|
|
$str = $this->proxify_head($str);
|
|
$str = $this->proxify_css($str);
|
|
|
|
// src= and href=
|
|
$str = preg_replace_callback('@(?:src|href)\s*=\s*(["|\'])(.*?)\1@is', array($this, 'html_attr'), $str);
|
|
|
|
// form
|
|
$str = preg_replace_callback('@<form[^>]*action=(["\'])(.*?)\1[^>]*>@i', array($this, 'form_action'), $str);
|
|
|
|
$response->setContent($str);
|
|
}
|
|
|
|
}
|
|
|
|
?>
|