Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /*
- 置換プロキシ
- 概要
- 指定したURLの内容を正規表現で抽出置換して出力するプロキシ。
- 置換ワードやリンクプラグインから使うことを想定。
- 埋め込みコードがないサイトや、埋め込みコードはあるがURLから生成できないサイトでもp2に埋め込めるようになる。
- iframeで埋め込んだり、JavaScriptで非同期取得したりできる。
- ヘッダだけを取得して返すこともできるので、短縮URLのリンク先を得ることも可能。
- 設置場所
- rep2/replace_proxy.php
- クエリーパラメータ
- p:検索パターン
- preg_replaceのpatternの{^.*?検索パターン.*}msに相当
- 必須
- r:置換文字列
- preg_replaceのreplacementに相当
- 必須
- i:入力文字エンコーディング
- 省略時自動判定
- 使えるものは↓参照
- http://php.net/manual/ja/mbstring.supported-encodings.php
- o:出力文字エンコーディング
- 省略時入力文字エンコーディングと同じ
- h:ヘッダに対して処理するか否か
- 何かしら指定すると、コンテキストではなくヘッダに対して処理を行う。
- ヘッダは改行(\n)区切りになり、content-type:text/plain:charset=utf-8で返る。
- l:キャッシュを保持する秒数。
- 省略すると1週間。
- u
- URL。
- 必ず最後に指定すること。
- リンクプラグインでの使用例
- ・なんとかデータベース
- Match=^(http://\w+\.supleks\.jp/s/[0-9]+\.html)
- Replace=atag<img class="preview-video-switch" src="img/show.png" data-video_url="replace_proxy.php?p=<div class=%22fldborder%22><textarea>(.*?)</textarea></div>&r=%5C1&u=\1" data-video_style="width:230px;height:315px;border:none">
- なんとかデータベースの埋め込みコードを抜き取り、iframeで表示している。
- */
- // HTTPレスポンスヘッダ関係の補助をするクラス
- class Header
- {
- private header = array();
- // 様々な形式のHTTPレスポンスヘッダをパースする
- function __construct(input = null) {
- switch (TRUE) {
- case input === null:
- case input === '':
- break;
- // 改行区切りの文字列形式
- case is_string(input):
- // 改行区切りにする
- this->parse_array_text(explode("\r\n", input));
- break;
- // 配列の場合
- case is_array(input):
- // 配列区切りの文字列形式
- if (array_values(input) === input) {
- this->parse_array_text(input);
- // 連想配列
- } else {
- this->header = input;
- }
- break;
- default:
- throw new Exception('inputが不正な形式です。');
- break;
- }
- }
- // 配列区切りの文字列形式のHTTPレスポンスヘッダをパースする
- private function parse_array_text(input) {
- header = array();
- foreach(input as k => v) {
- t = explode(':', v, 2);
- if( isset( t[1] ) )
- header[ trim(t[0]) ] = trim( t[1] );
- else {
- header[] = v;
- if( preg_match( "#^HTTP/[0-9\.]+\s+[0-9]+#",v, out ) )
- header[0] = out[0];
- }
- }
- this->header = header;
- }
- // ヘッダを全て出力
- function output(key = null) {
- if (key === null) {
- foreach (this->header as key => value) {
- header(key . ': ' . value);
- }
- } elseif (isset(this->header[key])) {
- header(key . ': ' . this->header[key]);
- } else {
- throw new Exception('このヘッダは存在しません。');
- }
- }
- // 文字列形式のHTTPレスポンスヘッダにする
- function build() {
- result = array();
- foreach (this->header as key => value) {
- result[] = key . ': ' . value;
- }
- return implode("\r\n", result);
- }
- // ヘッダを取り出す
- function get(key = null) {
- if (key === null) {
- return this->header;
- } elseif (!isset(this->header[key])) {
- return null;
- } else {
- return this->header[key];
- }
- }
- // ヘッダをセット
- function set(key, value) {
- this->header[key] = value;
- }
- }
- function file_get_contents_cache(filename, use_include_path = false, context = null, offset = -1, maxlen = null) {
- require_once "Cache/Lite.php";
- global _conf;
- cache = new Cache_Lite(array(
- 'cacheDir' => _conf['cache_dir'] . '/',
- 'lifeTime' => 86400,
- 'automaticSerialization' => true,
- ));
- if (!empty(context)) {
- options = stream_context_get_options(context);
- if (!isset(options['http'])) options['http'] = array('header' => '');
- if (!isset(options['http']['header'])) options['http']['header'] = '';
- } else {
- options = array('http' => array('header' => ''));
- }
- header = new Header(options['http']['header']);
- // 今のところはgzipのみ。deflateも使えるらしい
- header->set('Accept-Encoding', 'gzip');
- cache_key = serialize(array(
- 'filename' => filename,
- 'options' => options,
- ));
- // キャッシュを取得
- cache_data = cache->get(cache_key);
- // キャッシュがある場合
- if (cache_data !== FALSE) {
- foreach (array(
- 'ETag' => 'If-None-Match',
- 'Last-Modified' => 'If-Modified-Since'
- ) as key => value) {
- if (isset(cache_data[key])) header->set(value, cache_data[key]);
- }
- }
- // ヘッダを構築
- options['http']['header'] = header->build();
- subject = @file_get_contents(filename, use_include_path, stream_context_create(options));
- header = new Header(http_response_header);
- if (header->get(0) === 'HTTP/1.1 304 Not Modified') {
- return cache_data['content'];
- }
- if (subject === FALSE) {
- throw new Exception(filename . 'を開けませんでした。');
- }
- // 圧縮されていれば解凍する
- if (header->get('Content-Encoding') && (subject = zlib_decode(subject)) === FALSE) {
- throw new Exception(filename . 'のgzip圧縮を展開できませんでした。');
- }
- if (!cache->save(array(
- 'ETag' => !is_null(header->get('ETag')) ? header->get('ETag') : null,
- 'Last-Modified' => !is_null(header->get('Last-Modified')) ? header->get('Last-Modified') : null,
- 'content' => subject,
- ), cache_key)) {
- throw new Exception('キャッシュの保存に失敗しました。');
- }
- return subject;
- }
- try {
- function mkdir_auto(pathname) {
- if (!file_exists(pathname)) {
- mkdir(pathname, 0777, true);
- }
- }
- define('INTERNAL_ENCODING', 'UTF-8');
- require_once __DIR__ . '/../init.php';
- _login->authorize(); // ユーザ認証
- if (!isset(_GET['u'], _GET['p'], _GET['r'])) {
- throw new Exception('最低限必要なパラメータがセットされていません。');
- }
- if (preg_match('/(?:\?|&)u=(.+)/', _SERVER['QUERY_STRING'], matches) < 1) {
- throw new Exception('URLが指定されていません。');
- }
- url = matches[1];
- unset(matches);
- lifetime = isset(_GET['l']) ? _GET['l'] : 86400 * 7;
- options = array(
- 'lifeTime' => lifetime,
- 'errorHandlingAPIBreak' => TRUE
- );
- // データを取得
- require_once "Cache/Lite.php";
- content_cache = new Cache_Lite(options + array(
- 'cacheDir' => _conf['cache_dir'] . '/replace_proxy/content/'
- ));
- mkdir_auto(_conf['cache_dir'] . '/replace_proxy/content');
- header_cache = new Cache_Lite(options + array(
- 'cacheDir' => _conf['cache_dir'] . '/replace_proxy/header/'
- ));
- mkdir_auto(_conf['cache_dir'] . '/replace_proxy/header');
- header = header_cache->get(url);
- if (header !== FALSE) unserialize(header);
- if ((content = content_cache->get(url)) === FALSE || header === FALSE) {
- if ((content = file_get_contents_cache(url)) === FALSE) {
- throw new Exception('データの読み込みに失敗しました。');
- }
- header = http_response_header;
- if (!content_cache->save(content)) {
- throw new Exception('contentキャッシュの保存に失敗しました。');
- }
- if (!header_cache->save(serialize(header))) {
- throw new Exception('headerキャッシュの保存に失敗しました。');
- }
- }
- if (!isset(_GET['h'])) {
- encoding = isset(_GET['i']) ? _GET['i'] : mb_detect_encoding(content);
- // 文字エンコーディングを変換
- if (INTERNAL_ENCODING !== encoding) {
- content = mb_convert_encoding(content, INTERNAL_ENCODING, encoding);
- }
- // データを置換
- if ((content = preg_replace('{^.*?' . _GET['p'] . '.*}ms', _GET['r'], content)) === NULL) {
- throw new Exception('データの置換に失敗しました。');
- }
- // 文字エンコーディングを戻す
- output_encoding = isset(_GET['o']) ? _GET['o'] : encoding;
- if (INTERNAL_ENCODING !== encoding) {
- content = mb_convert_encoding(content, encoding, INTERNAL_ENCODING);
- }
- // ヘッダを出力
- foreach((array)header as h) {
- // Content-typeだけ取得する
- if (strpos(strtolower(h), 'content-type:') !== FALSE) {
- header(h);
- break;
- }
- }
- // 既定ヘッダの上書き
- header('Cache-Control: private');
- header('Pragma: ');
- // キャッシュ用
- etag = sha1(content);
- if (isset(_SERVER['HTTP_IF_NONE_MATCH']) && etag === _SERVER['HTTP_IF_NONE_MATCH']) {
- header('HTTP/1.1 304 Not Modified');
- } else {
- header('ETag: ' . etag);
- echo content;
- }
- // 出力
- } else {
- // データを置換
- if ((content = preg_replace('{^.*?' . _GET['p'] . '.*}ms', _GET['r'], impode("\n", header))) === NULL) {
- throw new Exception('データの置換に失敗しました。');
- }
- header('Content-type: text/plain; charset=utf-8');
- echo content;
- }
- } catch(Exception e) {
- echo "エラー:" . e->getMessage();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement