Initial commit
This commit is contained in:
parent
0a00b0b27f
commit
56f53d15ff
57
config.php
Normal file
57
config.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
// all possible options will be stored
|
||||
$config = array();
|
||||
|
||||
$config['website-name'] = "Web Proxy";
|
||||
$config['access-password'] = "MY_PASSWORD_TO_ACCESS";
|
||||
$config['website-url'] = "MY_FQDN/webproxy";
|
||||
$config['website-description'] = "Web Proxy";
|
||||
|
||||
// a unique key that identifies this application - DO NOT LEAVE THIS EMPTY!
|
||||
$config['app_key'] = 'ADD_HERE_SOME_RANDOM_STRING';
|
||||
|
||||
// a secret key to be used during encryption
|
||||
$config['encryption_key'] = '';
|
||||
|
||||
/*
|
||||
how unique is each URL that is generated by this proxy app?
|
||||
0 - no encoding of any sort. People can link to proxy pages directly: ?q=http://www.yahoo.com
|
||||
1 - Base64 encoding only, people can hotlink to your proxy
|
||||
2 - unique to the IP address that generated it. A person that generated that URL, can bookmark it and visit it and any point
|
||||
3 - unique to that session and IP address - URL no longer valid anywhere when that browser session that generated it ends
|
||||
*/
|
||||
|
||||
$config['url_mode'] = 2;
|
||||
|
||||
// plugins to load - plugins will be loaded in this exact order as in array
|
||||
$config['plugins'] = array(
|
||||
'HeaderRewrite',
|
||||
'Stream',
|
||||
// ^^ do not disable any of the plugins above
|
||||
'Cookie',
|
||||
'Proxify',
|
||||
'UrlForm',
|
||||
// site specific plugins below
|
||||
'Youtube',
|
||||
'DailyMotion',
|
||||
'Twitter'
|
||||
);
|
||||
|
||||
// additional curl options to go with each request
|
||||
$config['curl'] = array(
|
||||
// CURLOPT_PROXY => '',
|
||||
// CURLOPT_CONNECTTIMEOUT => 5
|
||||
);
|
||||
|
||||
//$config['replace_title'] = 'Google Search';
|
||||
|
||||
//$config['error_redirect'] = "https://unblockvideos.com/#error={error_msg}";
|
||||
//$config['index_redirect'] = 'https://unblockvideos.com/';
|
||||
|
||||
// $config['replace_icon'] = 'icon_url';
|
||||
|
||||
// this better be here other Config::load fails
|
||||
return $config;
|
||||
|
||||
?>
|
BIN
favicon.ico
Normal file
BIN
favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 104 KiB |
145
index.php
Normal file
145
index.php
Normal file
@ -0,0 +1,145 @@
|
||||
<?php
|
||||
require(__DIR__.'/login.php');
|
||||
|
||||
define('PROXY_START', microtime(true));
|
||||
require("vendor/autoload.php");
|
||||
|
||||
use Proxy\Http\Request;
|
||||
use Proxy\Http\Response;
|
||||
use Proxy\Plugin\AbstractPlugin;
|
||||
use Proxy\Event\FilterEvent;
|
||||
use Proxy\Config;
|
||||
use Proxy\Proxy;
|
||||
|
||||
// start the session
|
||||
session_start();
|
||||
|
||||
// load config...
|
||||
Config::load('./config.php');
|
||||
|
||||
// custom config file to be written to by a bash script or something
|
||||
Config::load('./custom_config.php');
|
||||
|
||||
if (!Config::get('app_key')) {
|
||||
die("app_key inside config.php cannot be empty!");
|
||||
}
|
||||
|
||||
if (!function_exists('curl_version')) {
|
||||
die("cURL extension is not loaded!");
|
||||
}
|
||||
|
||||
// how are our URLs be generated from this point? this must be set here so the proxify_url function below can make use of it
|
||||
if (Config::get('url_mode') == 2) {
|
||||
Config::set('encryption_key', md5(Config::get('app_key') . $_SERVER['REMOTE_ADDR']));
|
||||
} else if (Config::get('url_mode') == 3) {
|
||||
Config::set('encryption_key', md5(Config::get('app_key') . session_id()));
|
||||
}
|
||||
|
||||
// very important!!! otherwise requests are queued while waiting for session file to be unlocked
|
||||
session_write_close();
|
||||
|
||||
// form submit in progress...
|
||||
if (isset($_POST['url'])) {
|
||||
|
||||
$url = $_POST['url'];
|
||||
if (strpos ($url, '.') !== false){
|
||||
$url = add_http($url);
|
||||
header("HTTP/1.1 302 Found");
|
||||
header('Location: '.proxify_url($url));
|
||||
exit;
|
||||
}
|
||||
else {
|
||||
$url = 'http://www.google.com/search?q=' . urlencode($url);
|
||||
$url = add_http($url);
|
||||
header("HTTP/1.1 302 Found");
|
||||
header('Location: '.proxify_url($url));
|
||||
exit;
|
||||
}
|
||||
|
||||
} else if (!isset($_GET['q'])) {
|
||||
|
||||
// must be at homepage - should we redirect somewhere else?
|
||||
if (Config::get('index_redirect')) {
|
||||
|
||||
// redirect to...
|
||||
header("HTTP/1.1 302 Found");
|
||||
header("Location: " . Config::get('index_redirect'));
|
||||
|
||||
} else {
|
||||
if (isset($_GET["tos"]) != "") {
|
||||
echo render_template("./templates/tos.php", array(
|
||||
'version' => Proxy::VERSION
|
||||
));
|
||||
} else {
|
||||
echo render_template("./templates/main.php", array('version' => Proxy::VERSION));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
// decode q parameter to get the real URL
|
||||
$url = url_decrypt($_GET['q']);
|
||||
|
||||
$proxy = new Proxy();
|
||||
|
||||
// load plugins
|
||||
foreach (Config::get('plugins', array()) as $plugin) {
|
||||
|
||||
$plugin_class = $plugin . 'Plugin';
|
||||
|
||||
if (file_exists('./plugins/' . $plugin_class . '.php')) {
|
||||
|
||||
// use user plugin from /plugins/
|
||||
require_once('./plugins/' . $plugin_class . '.php');
|
||||
|
||||
} else if (class_exists('\\Proxy\\Plugin\\' . $plugin_class)) {
|
||||
|
||||
// does the native plugin from php-proxy package with such name exist?
|
||||
$plugin_class = '\\Proxy\\Plugin\\' . $plugin_class;
|
||||
}
|
||||
|
||||
// otherwise plugin_class better be loaded already through composer.json and match namespace exactly \\Vendor\\Plugin\\SuperPlugin
|
||||
$proxy->getEventDispatcher()->addSubscriber(new $plugin_class());
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// request sent to index.php
|
||||
$request = Request::createFromGlobals();
|
||||
|
||||
// remove all GET parameters such as ?q=
|
||||
$request->get->clear();
|
||||
|
||||
// forward it to some other URL
|
||||
$response = $proxy->forward($request, $url);
|
||||
|
||||
// if that was a streaming response, then everything was already sent and script will be killed before it even reaches this line
|
||||
$response->send();
|
||||
|
||||
} catch (Exception $ex) {
|
||||
|
||||
// if the site is on server2.proxy.com then you may wish to redirect it back to proxy.com
|
||||
if (Config::get("error_redirect")) {
|
||||
|
||||
$url = render_string(Config::get("error_redirect"), array(
|
||||
'error_msg' => rawurlencode($ex->getMessage())
|
||||
));
|
||||
|
||||
// Cannot modify header information - headers already sent
|
||||
header("HTTP/1.1 302 Found");
|
||||
header("Location: {$url}");
|
||||
|
||||
} else {
|
||||
|
||||
echo render_template("./templates/main.php", array(
|
||||
'url' => $url,
|
||||
'error_msg' => $ex->getMessage(),
|
||||
'version' => Proxy::VERSION
|
||||
));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
9
language.php
Normal file
9
language.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
$lang["slogan"] = "remove the borders";
|
||||
$lang["wikipedia"] = "Wikipedia";
|
||||
$lang["back"] = "Back";
|
||||
$lang["go"] = "Go";
|
||||
$lang["home"] = "Home";
|
||||
$lang["tos"] = "This is an private Web Proxy - Unauthorized use is strictly prohibited!";
|
||||
$lang["agree"] = "michu-IT";
|
||||
$lang["tos_2"] = "terms of use";
|
25
plugins/TestPlugin.php
Normal file
25
plugins/TestPlugin.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
use Proxy\Plugin\AbstractPlugin;
|
||||
use Proxy\Event\ProxyEvent;
|
||||
|
||||
class TestPlugin extends AbstractPlugin {
|
||||
|
||||
public function onBeforeRequest(ProxyEvent $event){
|
||||
// fired right before a request is being sent to a proxy
|
||||
}
|
||||
|
||||
public function onHeadersReceived(ProxyEvent $event){
|
||||
// fired right after response headers have been fully received - last chance to modify before sending it back to the user
|
||||
}
|
||||
|
||||
public function onCurlWrite(ProxyEvent $event){
|
||||
// fired as the data is being written piece by piece
|
||||
}
|
||||
|
||||
public function onCompleted(ProxyEvent $event){
|
||||
// fired after the full response=headers+body has been read - will only be called on "non-streaming" responses
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
39
plugins/UrlFormPlugin.php
Normal file
39
plugins/UrlFormPlugin.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
use Proxy\Plugin\AbstractPlugin;
|
||||
use Proxy\Event\ProxyEvent;
|
||||
|
||||
class UrlFormPlugin extends AbstractPlugin {
|
||||
|
||||
public function onCompleted(ProxyEvent $event){
|
||||
|
||||
$request = $event['request'];
|
||||
$response = $event['response'];
|
||||
|
||||
$url = $request->getUri();
|
||||
|
||||
// we attach url_form only if this is a html response
|
||||
if(!is_html($response->headers->get('content-type'))){
|
||||
return;
|
||||
}
|
||||
|
||||
// this path would be relative to index.php that included it?
|
||||
$url_form = render_template("./templates/url_form.php", array(
|
||||
'url' => $url
|
||||
));
|
||||
|
||||
$output = $response->getContent();
|
||||
|
||||
// does the html page contain <body> tag, if so insert our form right after <body> tag starts
|
||||
$output = preg_replace('@<body.*?>@is', '$0'.PHP_EOL.$url_form, $output, 1, $count);
|
||||
|
||||
// <body> tag was not found, just put the form at the top of the page
|
||||
if($count == 0){
|
||||
$output = $url_form.$output;
|
||||
}
|
||||
|
||||
$response->setContent($output);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
84
templates/main.php
Normal file
84
templates/main.php
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
require(__DIR__ . "/../language.php");
|
||||
require(__DIR__ . "/../config.php");
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title><?php echo $config['website-name']; ?></title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="description" content="<?php echo $config["website-description"]; ?>">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel='shortcut icon' type='image/x-icon' href='favicon.ico' />
|
||||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css">
|
||||
<style type="text/css">
|
||||
body {
|
||||
background-color: #373737 !important;
|
||||
background-image: url(https://www.blackgate.org/wood.jpg);
|
||||
}
|
||||
.jumbotron {
|
||||
background-color: #e9ecefc9 !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container text-center" style="margin-top:7%;">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<?php if (isset($error_msg)) { ?>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<p><?php echo $error_msg; ?></p>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<div class="jumbotron">
|
||||
<h1 class="display-3"><?php echo $config['website-name']; ?></h1>
|
||||
<p class="lead"><?php echo $lang["slogan"]; ?></p>
|
||||
<div class="btn-group" role="group">
|
||||
<a id="twitter" class="btn btn-info" href="#">Twitter</a>
|
||||
<a id="youtube" class="btn btn-danger" href="#">YouTube</a>
|
||||
<a id="facebook" class="btn btn-primary" href="#">Facebook</a>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<div class="btn-group" role="group">
|
||||
<a id="vikipedi" class="btn btn-secondary" href="#"><?php echo $lang["wikipedia"]; ?></a>
|
||||
<a id="google" class="btn btn-success" href="#">Google</a>
|
||||
</div>
|
||||
<p class="lead">
|
||||
<form class="form-group" action="index.php" method="post">
|
||||
<input id="url" name="url" type="text" class="form-control" autocomplete="on" placeholder="URL or Search"
|
||||
autofocus required/>
|
||||
<br>
|
||||
<input class="btn btn-primary btn-lg" type="submit" value="<?php echo $lang["go"]; ?>"/>
|
||||
</form>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<p style="font-size:15px; color:white">
|
||||
<small><?php echo $lang["agree"]; ?> <a
|
||||
href="<?php echo $config['website-url']; ?>/?tos"><?php echo $lang["tos_2"]; ?></a>
|
||||
</small>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="//code.jquery.com/jquery-1.9.1.js"></script>
|
||||
<script>
|
||||
$('#twitter').click(function () {
|
||||
$('#url').val('https://twitter.com');
|
||||
});
|
||||
$('#youtube').click(function () {
|
||||
$('#url').val('https://youtube.com');
|
||||
});
|
||||
$('#facebook').click(function () {
|
||||
$('#url').val('https://facebook.com');
|
||||
});
|
||||
$('#google').click(function () {
|
||||
$('#url').val('https://google.com');
|
||||
});
|
||||
$('#vikipedi').click(function () {
|
||||
$('#url').val('https://wikipedia.org');
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
BIN
templates/proxy.png
Normal file
BIN
templates/proxy.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
30
templates/tos.php
Normal file
30
templates/tos.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
require(__DIR__ . "/../language.php");
|
||||
require(__DIR__ . "/../config.php");
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title><?php echo $config['website-name']; ?></title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="description" content="<?php echo $config["website-description"]; ?>">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel='shortcut icon' type='image/x-icon' href='favicon.ico' />
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container text-center" style="margin-top:5%;">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="jumbotron">
|
||||
<h1 class="display-3"><?php echo $config['website-name']; ?></h1>
|
||||
<p class="lead"><?php echo $lang["slogan"]; ?></p>
|
||||
<p><?php echo $lang["tos"]; ?></p>
|
||||
<a href="<?php echo $config['website-url']; ?>"
|
||||
class="btn btn-primary btn-lg"><?php echo $lang["back"]; ?></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
80
templates/url_form.php
Normal file
80
templates/url_form.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
require(__DIR__ . "/../language.php");
|
||||
?>
|
||||
<style type="text/css">
|
||||
|
||||
html body {
|
||||
margin-top: 50px !important;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#top_form {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
|
||||
margin: 0;
|
||||
|
||||
z-index: 2100000000;
|
||||
-moz-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-o-user-select: none;
|
||||
|
||||
border-bottom: 1px solid #151515;
|
||||
|
||||
background: #CCCCCC;
|
||||
|
||||
height: 45px;
|
||||
line-height: 45px;
|
||||
}
|
||||
|
||||
#top_form input[name=url] {
|
||||
width: 550px;
|
||||
height: 20px;
|
||||
padding: 5px;
|
||||
font: 13px "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
border: 0px none;
|
||||
background: none repeat scroll 0% 0% #FFF;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
var url_text_selected = false;
|
||||
|
||||
function smart_select(ele) {
|
||||
|
||||
ele.onblur = function () {
|
||||
url_text_selected = false;
|
||||
};
|
||||
|
||||
ele.onclick = function () {
|
||||
if (url_text_selected == false) {
|
||||
this.focus();
|
||||
this.select();
|
||||
url_text_selected = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<div id="top_form">
|
||||
|
||||
<div style="width:800px; margin:0 auto;">
|
||||
|
||||
<form method="post" action="index.php" target="_top" style="margin:0; padding:0;">
|
||||
<input type="button" value="<?php echo $lang["home"]; ?>" onclick=" window.location.href='index.php'">
|
||||
<input type="text" name="url" value="<?php echo $url; ?>" autocomplete="off">
|
||||
<input type="hidden" name="form" value="1">
|
||||
<input type="submit" value="<?php echo $lang["go"]; ?>">
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script type=" text/javascript">
|
||||
smart_select(document.getElementsByName("url")[0]);
|
||||
</script>
|
1
vendor/athlon1600/php-proxy-plugin-bundle
vendored
Submodule
1
vendor/athlon1600/php-proxy-plugin-bundle
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 172202c9b7913dc397b0a2eeacb68984a73f5c6e
|
3
vendor/athlon1600/php-proxy/.gitignore
vendored
Normal file
3
vendor/athlon1600/php-proxy/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
/vendor/*
|
||||
composer.lock
|
||||
.htaccess
|
21
vendor/athlon1600/php-proxy/LICENSE
vendored
Normal file
21
vendor/athlon1600/php-proxy/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
99
vendor/athlon1600/php-proxy/README.md
vendored
Normal file
99
vendor/athlon1600/php-proxy/README.md
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
php-proxy
|
||||
=========
|
||||
|
||||
Proxy script built on PHP, Symfony and cURL.
|
||||
This library borrows ideas from Glype, Jenssegers proxy, and Guzzle.
|
||||
|
||||
PHP-Proxy Web Application
|
||||
-------
|
||||
|
||||
If you're looking for a **project** version of this script that functions as a Web Application similar to Glype, then visit
|
||||
[**php-proxy-app**](https://github.com/Athlon1600/php-proxy-app)
|
||||
|
||||
See this php-proxy in action:
|
||||
<a href="https://unblockvideos.com/" target="_blank">UnblockVideos.com</a>
|
||||
|
||||
Installation
|
||||
-------
|
||||
|
||||
Install it using [Composer](http://getcomposer.org):
|
||||
|
||||
```bash
|
||||
composer require athlon1600/php-proxy
|
||||
```
|
||||
|
||||
Example
|
||||
--------
|
||||
|
||||
```php
|
||||
require('vendor/autoload.php');
|
||||
|
||||
use Proxy\Http\Request;
|
||||
use Proxy\Proxy;
|
||||
|
||||
$request = Request::createFromGlobals();
|
||||
|
||||
$proxy = new Proxy();
|
||||
|
||||
$proxy->getEventDispatcher()->addListener('request.before_send', function($event){
|
||||
|
||||
$event['request']->headers->set('X-Forwarded-For', 'php-proxy');
|
||||
|
||||
});
|
||||
|
||||
$proxy->getEventDispatcher()->addListener('request.sent', function($event){
|
||||
|
||||
if($event['response']->getStatusCode() != 200){
|
||||
die("Bad status code!");
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
$proxy->getEventDispatcher()->addListener('request.complete', function($event){
|
||||
|
||||
$content = $event['response']->getContent();
|
||||
$content .= '<!-- via php-proxy -->';
|
||||
|
||||
$event['response']->setContent($content);
|
||||
|
||||
});
|
||||
|
||||
$response = $proxy->forward($request, "https://www.yahoo.com");
|
||||
|
||||
// send the response back to the client
|
||||
$response->send();
|
||||
|
||||
```
|
||||
|
||||
Plugin Example
|
||||
--------
|
||||
|
||||
```php
|
||||
namespace Proxy\Plugin;
|
||||
|
||||
use Proxy\Plugin\AbstractPlugin;
|
||||
use Proxy\Event\ProxyEvent;
|
||||
|
||||
use Proxy\Html;
|
||||
|
||||
class MultiSiteMatchPlugin extends AbstractPlugin {
|
||||
|
||||
// Matches multiple domain names (abc.com, abc.de, abc.pl) using regex (you MUST use / character)
|
||||
protected $url_pattern = '/^abc\.(com|de|pl)$/is';
|
||||
// Matches a single domain name
|
||||
//protected $url_pattern = 'abc.com';
|
||||
|
||||
public function onCompleted(ProxyEvent $event){
|
||||
|
||||
$response = $event['response'];
|
||||
|
||||
$html = $response->getContent();
|
||||
|
||||
// do your stuff here...
|
||||
|
||||
$response->setContent($html);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Notice that you must use the **/** character for regexes on ```$url_pattern```
|
21
vendor/athlon1600/php-proxy/composer.json
vendored
Normal file
21
vendor/athlon1600/php-proxy/composer.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "athlon1600/php-proxy",
|
||||
"type": "library",
|
||||
"keywords": ["php proxy", "proxy script", "php web proxy", "web proxy", "php proxy script"],
|
||||
"homepage": "https://www.php-proxy.com/",
|
||||
"require": {
|
||||
"ext-curl": "*",
|
||||
"symfony/event-dispatcher": "~3.2"
|
||||
},
|
||||
"suggest": {
|
||||
"predis/predis": "For caching purposes"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Proxy\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/helpers.php"
|
||||
]
|
||||
}
|
||||
}
|
39
vendor/athlon1600/php-proxy/src/Config.php
vendored
Normal file
39
vendor/athlon1600/php-proxy/src/Config.php
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy;
|
||||
|
||||
// based off of this:
|
||||
// http://v3.golaravel.com/api/source-class-Laravel.Config.html#3-235
|
||||
|
||||
class Config {
|
||||
|
||||
private static $config = array();
|
||||
|
||||
public static function get($key, $default = null){
|
||||
return self::has($key) ? static::$config[$key] : $default;
|
||||
}
|
||||
|
||||
public static function set($key, $value){
|
||||
self::$config[$key] = $value;
|
||||
}
|
||||
|
||||
public static function has($key){
|
||||
return isset(static::$config[$key]);
|
||||
}
|
||||
|
||||
public static function load($path){
|
||||
|
||||
if(file_exists($path)){
|
||||
|
||||
// Successful includes, unless overridden by the included file, return 1.
|
||||
$data = require($path);
|
||||
|
||||
if(is_array($data)){
|
||||
self::$config = array_merge(self::$config, $data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
39
vendor/athlon1600/php-proxy/src/Event/ProxyEvent.php
vendored
Normal file
39
vendor/athlon1600/php-proxy/src/Event/ProxyEvent.php
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy\Event;
|
||||
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
|
||||
// http://symfony.com/doc/current/components/event_dispatcher/generic_event.html
|
||||
class ProxyEvent extends Event implements \ArrayAccess {
|
||||
|
||||
private $data;
|
||||
|
||||
public function __construct($data = array()){
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value){
|
||||
|
||||
if(is_null($offset)) {
|
||||
$this->data[] = $value;
|
||||
} else {
|
||||
$this->data[$offset] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function offsetExists($offset){
|
||||
return isset($this->data[$offset]);
|
||||
}
|
||||
|
||||
public function offsetUnset($offset){
|
||||
unset($this->data[$offset]);
|
||||
}
|
||||
|
||||
public function offsetGet($offset){
|
||||
return isset($this->data[$offset]) ? $this->data[$offset] : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
182
vendor/athlon1600/php-proxy/src/Html.php
vendored
Normal file
182
vendor/athlon1600/php-proxy/src/Html.php
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy;
|
||||
|
||||
class Html {
|
||||
|
||||
public static function remove_scripts($html){
|
||||
$html = preg_replace('/<\s*script[^>]*>(.*?)<\s*\/\s*script\s*>/is', '', $html);
|
||||
return $html;
|
||||
}
|
||||
|
||||
public static function remove_styles($html){
|
||||
$html = preg_replace('/<\s*style[^>]*>(.*?)<\s*\/\s*style\s*>/is', '', $html);
|
||||
return $html;
|
||||
}
|
||||
|
||||
public static function remove_comments($html){
|
||||
return preg_replace('/<!--(.*?)-->/s', '', $html);
|
||||
}
|
||||
|
||||
private static function find($selector, $html, $start_from = 0){
|
||||
|
||||
$html = substr($html, $start_from);
|
||||
|
||||
$inner_start = 0;
|
||||
$inner_end = 0;
|
||||
|
||||
$pattern = '//';
|
||||
|
||||
if(substr($selector, 0, 1) == '#'){
|
||||
$pattern = '/<(\w+)[^>]+id="'.substr($selector, 1).'"[^>]*>/is';
|
||||
} else if(substr($selector, 0, 1) == '.'){
|
||||
$pattern = '/<(\w+)[^>]+class="'.substr($selector, 1).'"[^>]*>/is';
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(preg_match($pattern, $html, $matches, PREG_OFFSET_CAPTURE)){
|
||||
|
||||
$outer_start = $matches[0][1];
|
||||
$inner_start = $matches[0][1] + strlen($matches[0][0]);
|
||||
|
||||
// tag stuff
|
||||
$tag_name = $matches[1][0];
|
||||
$tag_len = strlen($tag_name);
|
||||
|
||||
$run_count = 300;
|
||||
|
||||
// "open" <tag elements we found so far
|
||||
$open_count = 1;
|
||||
$start = $inner_start;
|
||||
|
||||
while($open_count != 0 && $run_count-- > 0){
|
||||
|
||||
$open_tag = strpos($html, "<{$tag_name}", $start);
|
||||
$close_tag = strpos($html, "</{$tag_name}", $start);
|
||||
|
||||
// nothing was found?
|
||||
if($open_tag === false && $close_tag === false){
|
||||
break;
|
||||
}
|
||||
|
||||
//echo "open_tag: {$open_tag}, close_tag {$close_tag}\r\n";
|
||||
|
||||
// found OPEN tag
|
||||
if($close_tag === false || ($open_tag !== false && $open_tag < $close_tag) ){
|
||||
$open_count++;
|
||||
$start = $open_tag + $tag_len + 1;
|
||||
|
||||
//echo "found open tag: ".substr($html, $open_tag, 20)." at {$open_tag} \r\n";
|
||||
|
||||
// found CLOSE tag
|
||||
} else if($open_tag === false || ($close_tag !== false && $close_tag < $open_tag) ){
|
||||
$open_count--;
|
||||
$start = $close_tag + $tag_len + 2;
|
||||
|
||||
//echo "found close tag: ".substr($html, $close_tag, 20)." at {$close_tag} \r\n";
|
||||
}
|
||||
}
|
||||
|
||||
// something went wrong... don't bother returning anything
|
||||
if($open_count != 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
$outer_end = $close_tag + $tag_len + 3;
|
||||
$inner_end = $close_tag;
|
||||
|
||||
return array(
|
||||
'outer_start' => $outer_start + $start_from,
|
||||
'inner_start' => $inner_start + $start_from,
|
||||
'inner_end' => $inner_end + $start_from,
|
||||
'outer_end' => $outer_end + $start_from
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function extract_inner($selector, $html){
|
||||
return self::extract($selector, $html, true);
|
||||
}
|
||||
|
||||
public static function extract_outer($selector, $html){
|
||||
return self::extract($selector, $html, false);
|
||||
}
|
||||
|
||||
private static function extract($selector, $html, $inner = false){
|
||||
|
||||
$pos = 0;
|
||||
$limit = 300;
|
||||
|
||||
$result = array();
|
||||
$data = false;
|
||||
|
||||
do {
|
||||
|
||||
$data = self::find($selector, $html, $pos);
|
||||
|
||||
if($data){
|
||||
|
||||
$code = substr($html, $inner ? $data['inner_start'] : $data['outer_start'],
|
||||
$inner ? $data['inner_end'] - $data['inner_start'] : $data['outer_end'] - $data['outer_start']);
|
||||
|
||||
$result[] = $code;
|
||||
$pos = $data['outer_end'];
|
||||
}
|
||||
|
||||
} while ($data && --$limit > 0);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function remove($selector, $html){
|
||||
return self::replace($selector, '', $html, false);
|
||||
}
|
||||
|
||||
public static function replace_outer($selector, $replace, $html, &$matches = NULL){
|
||||
return self::replace($selector, $replace, $html, false, $matches);
|
||||
}
|
||||
|
||||
public static function replace_inner($selector, $replace, $html, &$matches = NULL){
|
||||
return self::replace($selector, $replace, $html, true, $matches);
|
||||
}
|
||||
|
||||
private static function replace($selector, $replace, $html, $replace_inner = false, &$matches = NULL){
|
||||
|
||||
$start_from = 0;
|
||||
$limit = 300;
|
||||
|
||||
$data = false;
|
||||
$replace = (array)$replace;
|
||||
|
||||
do {
|
||||
|
||||
$data = self::find($selector, $html, $start_from);
|
||||
|
||||
if($data){
|
||||
|
||||
$r = array_shift($replace);
|
||||
|
||||
// from where to where will we be replacing?
|
||||
$replace_space = $replace_inner ? $data['inner_end'] - $data['inner_start'] : $data['outer_end'] - $data['outer_start'];
|
||||
$replace_len = strlen($r);
|
||||
|
||||
if($matches !== NULL){
|
||||
$matches[] = substr($html, $replace_inner ? $data['inner_start'] : $data['outer_start'], $replace_space);
|
||||
}
|
||||
|
||||
$html = substr_replace($html, $r, $replace_inner ? $data['inner_start'] : $data['outer_start'], $replace_space);
|
||||
|
||||
// next time we resume search at position right at the end of this element
|
||||
$start_from = $data['outer_end'] + ($replace_len - $replace_space);
|
||||
}
|
||||
|
||||
} while ($data && --$limit > 0);
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
84
vendor/athlon1600/php-proxy/src/Http/ParamStore.php
vendored
Normal file
84
vendor/athlon1600/php-proxy/src/Http/ParamStore.php
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy\Http;
|
||||
|
||||
/*
|
||||
|
||||
heavily borrowed from Symfony's ParameterBag and Guzzle Collection
|
||||
|
||||
https://github.com/guzzle/guzzle/blob/v3.5.0/src/Guzzle/Common/Collection.php
|
||||
|
||||
*/
|
||||
|
||||
|
||||
class ParamStore {
|
||||
|
||||
protected $data = array();
|
||||
protected $case_sensitive;
|
||||
|
||||
public function __construct($parameters = array(), $case_sensitive = false){
|
||||
$this->data = $parameters;
|
||||
$this->case_sensitive = $case_sensitive;
|
||||
}
|
||||
|
||||
private function normalizeKey($key){
|
||||
return $this->case_sensitive ? $key : strtolower($key);
|
||||
}
|
||||
|
||||
public function set($key, $value, $replace = true){
|
||||
|
||||
$key = $this->normalizeKey($key);
|
||||
|
||||
// replacing or does not have existing key filled yet
|
||||
if($replace || !$this->has($key)){
|
||||
$this->data[$key] = $value;
|
||||
} else {
|
||||
|
||||
if(is_array($this->data[$key])){
|
||||
$this->data[$key][] = $value;
|
||||
} else {
|
||||
$this->data[$key] = array($this->data[$key], $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function replace(array $data){
|
||||
|
||||
// remove all existing items first
|
||||
$this->clear();
|
||||
|
||||
foreach($data as $key => $value){
|
||||
$this->set($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
public function remove($key){
|
||||
unset($this->data[$this->normalizeKey($key)]);
|
||||
}
|
||||
|
||||
public function clear(){
|
||||
$this->data = array();
|
||||
}
|
||||
|
||||
public function has($key){
|
||||
return isset($this->data[$this->normalizeKey($key)]);
|
||||
}
|
||||
|
||||
public function get($key, $default = null){
|
||||
|
||||
$key = $this->normalizeKey($key);
|
||||
|
||||
return $this->has($key) ? $this->data[$key] : $default;
|
||||
}
|
||||
|
||||
// Returns an array of all values currently stored
|
||||
public function all(){
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function __toString(){
|
||||
return json_encode($this->data, true);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
362
vendor/athlon1600/php-proxy/src/Http/Request.php
vendored
Normal file
362
vendor/athlon1600/php-proxy/src/Http/Request.php
vendored
Normal file
@ -0,0 +1,362 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy\Http;
|
||||
|
||||
use Proxy\Http\ParamStore;
|
||||
|
||||
class Request {
|
||||
|
||||
private $method;
|
||||
private $url;
|
||||
|
||||
private $protocol_version = '1.1';
|
||||
|
||||
// Custom attributes to go with each Request instance - has nothing to do with HTTP
|
||||
public $params; // parameters
|
||||
|
||||
// HTTP headers for this request - all in lowercase
|
||||
public $headers;
|
||||
|
||||
// Here we store cookies for that request
|
||||
//public $cookies;
|
||||
|
||||
// Collection of POST fields to be submitted
|
||||
public $post;
|
||||
|
||||
// Query string parameters for URL
|
||||
public $get;
|
||||
|
||||
// Files to be uploaded with POST
|
||||
public $files;
|
||||
|
||||
// User set body contents
|
||||
private $body = null;
|
||||
|
||||
// Library generated body that is regenerated through prepare method
|
||||
private $prepared_body = null;
|
||||
|
||||
public function __construct($method, $url, $headers = array(), $body = null){
|
||||
|
||||
$this->params = new ParamStore();
|
||||
$this->headers = new ParamStore();
|
||||
|
||||
// http params
|
||||
$this->post = new ParamStore(null, true);
|
||||
$this->get = new ParamStore(null, true);
|
||||
|
||||
$this->files = new ParamStore(null, true);
|
||||
|
||||
$this->setMethod($method);
|
||||
$this->setUrl($url);
|
||||
$this->setBody($body);
|
||||
|
||||
// make the request ready to be sent right from the start - prepare must be called manually from this point on if you ever add post or file parameters
|
||||
$this->prepare();
|
||||
}
|
||||
|
||||
/*
|
||||
Does multiple things
|
||||
- regenerate content body based on $post and $files parameters
|
||||
- set content-type, content-length headers
|
||||
- set transfer-encoding, expect headers
|
||||
*/
|
||||
public function prepare(){
|
||||
|
||||
/*
|
||||
Any HTTP/1.1 message containing an entity-body SHOULD include a Content-Type header field defining the media type of that body.
|
||||
http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.2.1
|
||||
*/
|
||||
|
||||
// Must be a multipart request
|
||||
if($this->files->all()){
|
||||
|
||||
$boundary = self::generateBoundary();
|
||||
|
||||
$this->prepared_body = Request::buildPostBody($this->post->all(), $this->files->all(), $boundary);
|
||||
$this->headers->set('content-type', 'multipart/form-data; boundary='.$boundary);
|
||||
|
||||
} else if($this->post->all()){
|
||||
|
||||
$this->prepared_body = http_build_query($this->post->all());
|
||||
$this->headers->set('content-type', 'application/x-www-form-urlencoded');
|
||||
|
||||
} else {
|
||||
|
||||
$this->headers->set('content-type', $this->detectContentType($this->body));
|
||||
$this->prepared_body = $this->body;
|
||||
}
|
||||
|
||||
/*
|
||||
The transfer-length of a message is the length of the message-body as it appears in the message; that is, after any transfer-codings have been applied.
|
||||
http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4
|
||||
*/
|
||||
|
||||
$len = strlen($this->prepared_body);
|
||||
|
||||
if($len > 0){
|
||||
$this->headers->set('content-length', $len);
|
||||
} else {
|
||||
$this->headers->remove('content-length');
|
||||
$this->headers->remove('content-type');
|
||||
}
|
||||
}
|
||||
|
||||
public function __toString(){
|
||||
$str = $this->getMethod().' '.$this->getUrl().' HTTP/'.$this->getProtocolVersion()."\r\n";
|
||||
return $str.$this->getRawHeaders()."\r\n\r\n".$this->getRawBody();
|
||||
}
|
||||
|
||||
public function setMethod($method){
|
||||
$this->method = strtoupper($method);
|
||||
}
|
||||
|
||||
public function getMethod(){
|
||||
return $this->method;
|
||||
}
|
||||
|
||||
// this was no longer working --- https://github.com/guzzle/psr7/blob/master/src/functions.php
|
||||
public static function parseQuery($query){
|
||||
$result = array();
|
||||
parse_str($query, $result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function setUrl($url){
|
||||
// remove hashtag - preg_replace so we don't have to check for its existence first - is it possible preserving hashtag?
|
||||
$url = preg_replace('/#.*/', '', $url);
|
||||
|
||||
// check if url has any query parameters
|
||||
$query = parse_url($url, PHP_URL_QUERY);
|
||||
|
||||
// remove it and add the query params to get collection
|
||||
if($query){
|
||||
//$url = str_replace('?'.$query, '', $url);
|
||||
$url = preg_replace('/\?.*/', '', $url);
|
||||
|
||||
$result = self::parseQuery($query);
|
||||
$this->get->replace($result);
|
||||
}
|
||||
|
||||
// url without query params - those will be appended later
|
||||
$this->url = $url;
|
||||
$this->headers->set('host', parse_url($url, PHP_URL_HOST));
|
||||
}
|
||||
|
||||
public function getRawHeaders(){
|
||||
|
||||
$result = array();
|
||||
|
||||
$headers = $this->headers->all();
|
||||
|
||||
// Sort headers by name
|
||||
//ksort($headers);
|
||||
|
||||
// Turn this into name=value pairs
|
||||
foreach($headers as $name => $values){
|
||||
|
||||
// could be an array if multiple headers are sent with the same name?
|
||||
foreach( (array)$values as $value){
|
||||
$name = implode('-', array_map('ucfirst', explode('-', $name)));
|
||||
$result[] = sprintf("%s: %s", $name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return implode("\r\n", $result);
|
||||
}
|
||||
|
||||
public function getUrl(){
|
||||
|
||||
// does this URL have any query parameters?
|
||||
if($this->get->all()){
|
||||
return $this->url.'?'.http_build_query($this->get->all());
|
||||
}
|
||||
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
public function getUri(){
|
||||
return call_user_func_array(array($this, "getUrl"), func_get_args());
|
||||
}
|
||||
|
||||
public function setProtocolVersion($version){
|
||||
$this->protocol_version = $version;
|
||||
}
|
||||
|
||||
public function getProtocolVersion(){
|
||||
return $this->protocol_version;
|
||||
}
|
||||
|
||||
// Set raw contents of the body
|
||||
// this will clear all the values currently stored in POST and FILES
|
||||
// will be ignored during PREPARE if post or files contain any values
|
||||
public function setBody($body, $content_type = false){
|
||||
|
||||
// clear old body data
|
||||
$this->post->clear();
|
||||
$this->files->clear();
|
||||
|
||||
// is this form data?
|
||||
if(is_array($body)){
|
||||
$body = http_build_query($body);
|
||||
}
|
||||
|
||||
$this->body = (string)$body;
|
||||
|
||||
// plain text should be: text/plain; charset=UTF-8
|
||||
if($content_type){
|
||||
$this->headers->set('content-type', $content_type);
|
||||
}
|
||||
|
||||
// do it!
|
||||
$this->prepare();
|
||||
}
|
||||
|
||||
private static function generateBoundary(){
|
||||
return '-----'.md5(microtime().rand());
|
||||
}
|
||||
|
||||
// can be $_POST and $_FILES
|
||||
public static function buildPostBody($fields, $files, $boundary = null){
|
||||
|
||||
// the reason BODY part is not included in sprintf pattern is because of limits
|
||||
$part_field = "--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n";
|
||||
$part_file = "--%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\nContent-Type: %s\r\n\r\n";
|
||||
|
||||
// each part should be preceeded by this line
|
||||
if(!$boundary){
|
||||
$boundary = self::generateBoundary();
|
||||
}
|
||||
|
||||
$body = '';
|
||||
|
||||
foreach($fields as $name => $value){
|
||||
$body .= sprintf($part_field, $boundary, $name, $value);
|
||||
$body .= "{$value}\r\n";
|
||||
}
|
||||
|
||||
// data better have [name, tmp_name, and optional type]
|
||||
foreach($files as $name => $values) {
|
||||
// Multiple files can be uploaded using different name for input.
|
||||
// See http://php.net/manual/en/features.file-upload.multiple.php
|
||||
if (!is_array($values['tmp_name'])) {
|
||||
$multiValues = array_map(function ($a) {
|
||||
return (array)$a;
|
||||
}, $values);
|
||||
$fieldName = $name;
|
||||
} else {
|
||||
$multiValues = $values;
|
||||
$fieldName = "{$name}[]";
|
||||
}
|
||||
|
||||
foreach (array_keys($multiValues['tmp_name']) as $key) {
|
||||
|
||||
// There must be no error http://php.net/manual/en/features.file-upload.errors.php
|
||||
if (!$multiValues['tmp_name'][$key] || $multiValues['error'][$key] !== 0 || !is_readable($multiValues['tmp_name'][$key])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$body .= sprintf($part_file, $boundary, $fieldName, $multiValues['name'][$key], $multiValues['type'][$key]);
|
||||
$body .= file_get_contents($multiValues['tmp_name'][$key]);
|
||||
$body .= "\r\n";
|
||||
}
|
||||
}
|
||||
$body .= "--{$boundary}--\r\n\r\n";
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
private function detectContentType($data){
|
||||
|
||||
// http://www.w3.org/Protocols/rfc1341/4_Content-Type.html
|
||||
|
||||
// If the media type remains unknown, the recipient SHOULD treat it as type "application/octet-stream".
|
||||
$content_type = 'application/octet-stream';
|
||||
|
||||
if(preg_match('/^{\s*"[^"]+"\s*:/', $data)){
|
||||
$content_type = 'application/json';
|
||||
} else if(preg_match('/^(?:<\?xml[^?>]+\?>)\s*<[^>]+>/i', $data)){
|
||||
$content_type = 'application/xml';
|
||||
} else if(preg_match('/^[a-zA-Z0-9_.~-]+=[^&]*&/', $data)){
|
||||
$content_type = 'application/x-www-form-urlencoded';
|
||||
}
|
||||
|
||||
return $content_type;
|
||||
}
|
||||
|
||||
// Returns a parsed version of the body
|
||||
/*
|
||||
public function getBody(){
|
||||
|
||||
// what is the content type?
|
||||
$content_type = $this->headers->get('content-type', '');
|
||||
|
||||
switch($content_type){
|
||||
case 'application/x-www-form-urlencoded':
|
||||
$result = array();
|
||||
mb_parse_str($this->body, $result);
|
||||
return $result;
|
||||
case 'application/json':
|
||||
return json_decode($this->body);
|
||||
case 'text/xml':
|
||||
case 'application/xml':
|
||||
case 'application/x-xml':
|
||||
return simplexml_load_string($this->body);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
*/
|
||||
|
||||
// Returns raw body string exactly as it appears in the HTTP request
|
||||
public function getRawBody(){
|
||||
return $this->prepared_body;
|
||||
}
|
||||
|
||||
public static function createFromGlobals(){
|
||||
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
$scheme = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']) ? 'https' : 'http';
|
||||
|
||||
$url = $scheme.'://'. $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
|
||||
|
||||
$request = new Request($method, $url);
|
||||
|
||||
// fill in headers
|
||||
foreach($_SERVER as $name => $value){
|
||||
|
||||
if(strpos($name, 'HTTP_') === 0){
|
||||
|
||||
$name = substr($name, 5);
|
||||
$name = str_replace('_', ' ', $name);
|
||||
$name = ucwords(strtolower($name));
|
||||
$name = str_replace(' ', '-', $name);
|
||||
|
||||
$request->headers->set($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
// for extra convenience
|
||||
//$request->params->set('user-ip', $_SERVER['REMOTE_ADDR']);
|
||||
|
||||
// will be empty if content-type is multipart
|
||||
$input = file_get_contents("php://input");
|
||||
|
||||
if(count($_FILES) > 0){
|
||||
$request->post->replace($_POST);
|
||||
$request->files->replace($_FILES);
|
||||
} else if(count($_POST) > 0){
|
||||
$request->post->replace($_POST);
|
||||
} else {
|
||||
$request->setBody($input);
|
||||
}
|
||||
|
||||
// for extra convenience
|
||||
$request->prepare();
|
||||
|
||||
return $request;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
120
vendor/athlon1600/php-proxy/src/Http/Response.php
vendored
Normal file
120
vendor/athlon1600/php-proxy/src/Http/Response.php
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy\Http;
|
||||
|
||||
use Proxy\Http\ParamStore;
|
||||
|
||||
class Response {
|
||||
|
||||
protected $statusCodes = array(
|
||||
100 => 'Continue',
|
||||
101 => 'Switching Protocols',
|
||||
200 => 'OK',
|
||||
201 => 'Created',
|
||||
202 => 'Accepted',
|
||||
203 => 'Non-Authoritative Information',
|
||||
204 => 'No Content',
|
||||
205 => 'Reset Content',
|
||||
206 => 'Partial Content',
|
||||
300 => 'Multiple Choices',
|
||||
301 => 'Moved Permanently',
|
||||
302 => 'Found',
|
||||
303 => 'See Other',
|
||||
304 => 'Not Modified',
|
||||
305 => 'Use Proxy',
|
||||
307 => 'Temporary Redirect',
|
||||
400 => 'Bad Request',
|
||||
401 => 'Unauthorized',
|
||||
402 => 'Payment Required',
|
||||
403 => 'Forbidden',
|
||||
404 => 'Not Found',
|
||||
405 => 'Method Not Allowed',
|
||||
406 => 'Not Acceptable',
|
||||
407 => 'Proxy Authentication Required',
|
||||
408 => 'Request Time-out',
|
||||
409 => 'Conflict',
|
||||
410 => 'Gone',
|
||||
411 => 'Length Required',
|
||||
412 => 'Precondition Failed',
|
||||
413 => 'Request Entity Too Large',
|
||||
414 => 'Request-URI Too Large',
|
||||
415 => 'Unsupported Media Type',
|
||||
416 => 'Requested range not satisfiable',
|
||||
417 => 'Expectation Failed',
|
||||
429 => 'Too Many Requests',
|
||||
500 => 'Internal Server Error',
|
||||
501 => 'Not Implemented',
|
||||
502 => 'Bad Gateway',
|
||||
503 => 'Service Unavailable',
|
||||
504 => 'Gateway Time-out',
|
||||
505 => 'Unsupported Version'
|
||||
);
|
||||
|
||||
public $status;
|
||||
|
||||
public $headers;
|
||||
|
||||
private $content;
|
||||
|
||||
// getHeaderLines
|
||||
public function __construct($content = '', $status = 200, $headers = array()){
|
||||
|
||||
$this->headers = new ParamStore($headers);
|
||||
|
||||
$this->setContent($content);
|
||||
$this->setStatusCode($status);
|
||||
}
|
||||
|
||||
public function setStatusCode($code){
|
||||
$this->status = $code;
|
||||
}
|
||||
|
||||
public function getStatusCode(){
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
public function getStatusText(){
|
||||
return $this->statusCodes[$this->getStatusCode()];
|
||||
}
|
||||
|
||||
public function setContent($content){
|
||||
$this->content = (string)$content;
|
||||
}
|
||||
|
||||
public function getContent(){
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
public function sendHeaders(){
|
||||
|
||||
if(headers_sent()){
|
||||
return;
|
||||
}
|
||||
|
||||
header(sprintf('HTTP/1.1 %s %s', $this->status, $this->getStatusText()), true, $this->status);
|
||||
|
||||
foreach($this->headers->all() as $name => $value){
|
||||
|
||||
/*
|
||||
Multiple message-header fields with the same field-name MAY be present in a message
|
||||
if and only if the entire field-value for that header field is defined as a comma-separated list
|
||||
http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
|
||||
*/
|
||||
|
||||
$values = is_array($value) ? $value : array($value);
|
||||
|
||||
// false = do not replace previous identical header
|
||||
foreach($values as $value){
|
||||
header("{$name}: {$value}", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function send(){
|
||||
$this->sendHeaders();
|
||||
echo $this->content;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
80
vendor/athlon1600/php-proxy/src/Plugin/AbstractPlugin.php
vendored
Normal file
80
vendor/athlon1600/php-proxy/src/Plugin/AbstractPlugin.php
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Proxy\Plugin;
|
||||
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Proxy\Event\ProxyEvent;
|
||||
|
||||
abstract class AbstractPlugin implements EventSubscriberInterface {
|
||||
|
||||
// apply these methods only to those events whose request URL passes this filter
|
||||
protected $url_pattern;
|
||||
|
||||
public function onBeforeRequest(ProxyEvent $event){
|
||||
// fired right before a request is being sent to a proxy
|
||||
}
|
||||
|
||||
public function onHeadersReceived(ProxyEvent $event){
|
||||
// fired right after response headers have been fully received - last chance to modify before sending it back to the user
|
||||