HOT CAT QUERY FEVERS

雑多な覚書と雑種のぬこ画像あり〼

最終更新日:2018年12月11日232 Views

Opera 12 でセキュア処理できないページをプレビューするスクリプト

Opera 12 の証明書問題について。  ↓ 『セキュア処理を完了することができません』のページが増えてきた為、簡単にプレビューできるスクリプトを作る。2018年5月5日作成。  ↓ file_get_contents だけでは見られないページが増えてきた為、CURL を追加  ↓ クラウドフレアの DDos 弾きに対応。KyranRana 氏に多謝  ↓ 検索サイトなどのスペース区切りが「+」になる問題を修正  ↓ 画像等の保存時にファイル名が「default」になる問題を修正  ↓ Cookie のファイル名をホスト名に変更  ↓ 数字のみのページャーリンクに対応 ← New!

準備

下記リンクを参考に XAMPP を自動起動する。 Mint の起動時に XAMPP を起動する方法 - HOT CAT QUERY FEVERS

インストール

opera-preview.php を保存し htdocs に置く。
/opt/lampp/htdocs/opera-preview.phpDownload
<?php
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 *
 * ©2018 HOT CAT QUERY FEVERS.
 */

error_reporting(-1);
setlocale(LC_ALL'ja_JP.UTF8');
mb_language('ja');
mb_internal_encoding('UTF-8');
date_default_timezone_set('Asia/Tokyo');
ini_set('user_agent'getenv('HTTP_USER_AGENT'));
header('x-content-type-options: nosniff');

if (
$etoj filter_input(INPUT_GET'e2j'FILTER_SANITIZE_ENCODED))
    echo 
file_get_contents('https://www.excite.co.jp/world/english/?before='$etoj'&wb_lp=ENJA&ie=UTF-8');

elseif (
filter_has_var(INPUT_GET'url'))
{
    
$request_uri getenv('REQUEST_URI');
    
$exuri explode('='$request_uri);
    
$segment $exuri[0]. '=';
    
$uri substr_replace($request_uri''0strlen($segment));
    
$uri str_replace('+''%2B'$uri);
    
$url preg_match('/.*\?.*\=.*[\&.*]?/'$uri) || preg_match('/.*\%253F.*\=.*[\%26.*]?/'$uri) ? urldecode($uri) : $uri;
    
$extension strtolower(pathinfo(parse_url($urlPHP_URL_PATH), PATHINFO_EXTENSION));
    
$host parse_url($urlPHP_URL_HOST);
    
$scheme parse_url($urlPHP_URL_SCHEME);
    
$path parse_url($urlPHP_URL_PATH);
    
$query parse_url($urlPHP_URL_QUERY);
    
$server_name 'http://'getenv('SERVER_NAME'). $segment;
    
$cookie sys_get_temp_dir(). '/'$host;
    
$context stream_context_create(
    array(
            
'http' => array(
                
'method' => 'GET',
                
'header' => headers(),
                
'ignore_errors' => true,
                
'timeout' => 3,
            ),
            
'ssl' => array(
                
'verify_peer' => false,
                
'verify_peer_name' => false,
            ),
        )
    );
    if (
$post file_get_contents('php://input')) header('Location:'$server_name$url'?'$post);
    if (!
$curl curl($url)) $curl file_get_contents($urlfalse$context);

    if (
strpos($curl'cdn-cgi/l/chk_jschl') !== false)
        if (!
is_file($cookie) || basename($cookie) !== $host$curl curl(getClearanceLink($curl$url), $url);

    
$mime mime($curl);
    
$encoding preg_match('/(charset|encoding)=["\']?([a-zA-Z0-9-_]+)["\']?/i'$curl$match) ? $match[2] : 'auto';

    if (
array_search($extension, array('pdf''zip''gz''rar')) !== false)
    {
        
header('content-type: application/octet-stream');
        
header('content-disposition: attachment; filename="'basename($path). '"');
        exit(
$curl);
    }
    elseif (
strpos($mime'image') !== false)
    {
        
header('content-type: '$mime);
        
header('content-disposition: filename="'basename($path). '"');
        exit(
$curl);
    }
    elseif (
strpos($mime'video') !== false)
    {
        
header('content-type: '$mime);
        
header('content-disposition: filename="'basename($path). '"');
        exit(
$curl);
    }
    elseif ((
strpos($mime'xml') !== false && stripos($curl'<html') === false) || array_search($extension, array('atom''rss''xml')) !== false)
    {
        if (
stripos($curl'xmlns') !== false && stripos($curl'atom') !== false)
            
header('content-type: application/xml');
        
$xml mb_convert_encoding($curl'HTML-ENTITIES'$encoding);
        
$xml preg_replace_callback('/(<content[^>]*>)(.*?)(<\/content[^>]*>)/isu''cdata'$xml);
        
$xml preg_replace_callback('/(<description[^>]*>)(.*?)(<\/description[^>]*>)/isu''cdata'$xml);
        
$xml preg_replace_callback('/(<title[^>]*>)(.*?)(<\/title[^>]*>)/isu''cdata'$xml);
        
$xml preg_replace('/(href|src)="([a-zA-Z0-9.-_%]+)"?/''$1="'$server_name'$2"'$xml);
        
$xml preg_replace('/(<itunes:[^>]*>.*<\/itunes:[^>]*>)/isu'''$xml);
        
$xml preg_replace_callback('/(<guid[^>]*>)(.*?)(<\/guid[^>]*>)/isu''xlink'$xml);
        
$xml preg_replace_callback('/(<id[^>]*>)(.*?)(<\/id[^>]*>)/isu''xlink'$xml);
        
$xml preg_replace_callback('/(<link[^>]*>)(.*?)(<\/link[^>]*>)/isu''xlink'$xml);
        
$xml preg_replace_callback('/(?:&#\d++;)++/''mb_decode_entity'$xml);
        exit(
$xml);
    }
    elseif (
$contents mb_convert_encoding($curl'HTML-ENTITIES'$encoding))
    {
        if (isset(
$query) && strpos($query'start') !== false)
            
$query preg_replace('/search_id=\d+&start=\d+&/'''$query);

        
$dom = new DOMDocument();
        
libxml_use_internal_errors(true);
        
$dom->loadHTML($contents);

        if (
$dom->getElementsByTagName('base')->length 0)
            
$url $dom->getElementsByTagName('base')->item(0)->getAttribute('href');

        if (isset(
$dom->getElementsByTagName('title')->item(0)->textContent))
            
$dom->getElementsByTagName('title')->item(0)->textContent .= ' Ⓟⓡⓔⓥⓘⓔⓦ by ⒽⒸⓆⒻ';
#style
        
foreach($dom->getElementsByTagName('style') as $style)
        {
            
$styleimport preg_replace_callback('/(import url\()(.*?)(\))/is''export_url'$style->nodeValue);
            
$style->nodeValue preg_replace_callback('/(:url ?\()(.*?)(\))/is''export_url'$styleimport);
        }
#svg
        
foreach($dom->getElementsByTagName('svg') as $svg)
        {
            if (!
$svg->getAttribute('width'))
                
$svg->setAttribute('width''1em');
        }
        foreach(
$dom->getElementsByTagName('*') as $all)
        {
#href
            
if ($href $all->getAttribute('href'))
            {
                if (!
$all->getAttribute('rel') && isset($query) && strpos($href'search.php') !== false)
                    
$all->setAttribute('href'path2uri($href'&'$query$url));
                else
                    
$all->setAttribute('href'path2uri($href$url));
            }
#src
            
if ($all->getAttribute('data-original'))
                
$src $all->getAttribute('data-original');
            elseif (
$all->getAttribute('data-src'))
                
$src $all->getAttribute('data-src');
            elseif (
$all->getAttribute('file'))
                
$src $all->getAttribute('file');
            else
                
$src $all->getAttribute('src');
            if (
$src)
                
$all->setAttribute('src'path2uri($src$url));
#action
            
if ($all->getAttribute('action') || $all->getAttribute('method'))
            {
                
$action $all->getAttribute('action');
                
$act path2uri($action$url);
                
$all->setAttribute('action'$act);
                
$all->setAttribute('method''post');
            }
        }
        foreach(
$dom->getElementsByTagName('div') as $div)
        {
            if (
$style $div->getAttribute('style'))
            {
                if (
$bg preg_replace_callback('/url\(["\'](.*?)["\']\)/is', function($m){global $url;return 'url(\''path2uri($m[1], $url). '\')';}, $style))
                    
$div->setAttribute('style'$bg);
            }
        }
        if (
stripos($mime'html') !== false || stripos($mime'xml') !== false)
            exit(
preg_replace_callback('/(?:&#\d++;)++/''mb_decode_entity'$dom->saveHTML($dom->documentElement)));
        else
        {
            
$css preg_replace('/\/\*.*?\*\//is'''$contents);
            
$css preg_replace_callback('/(import url[\n|\r|\r\n| ]?\()(.*?)(\))/is''export_url'$css);
            
$css preg_replace_callback('/(import ?["\'])(.*?)(["\'])/is''export_url'$css);
            
$css preg_replace_callback('/(:url ?\(["\']?)(.*?)(["\']?\))/is''export_url'$css);
            exit(
preg_replace_callback('/(?:&#\d++;)++/''mb_decode_entity'$css));
        }
    }
}

function 
curl($url$referer='')
{
    
$ch curl_init();
    
curl_setopt($chCURLOPT_AUTOREFERERtrue);
    
curl_setopt($chCURLOPT_ENCODINGgetenv('HTTP_ACCEPT_ENCODING'));
    
curl_setopt($chCURLOPT_FOLLOWLOCATIONtrue);
    
curl_setopt($chCURLOPT_FORBID_REUSEtrue);
    
curl_setopt($chCURLOPT_HEADERfalse);
    
curl_setopt($chCURLOPT_HTTPHEADERheaders());
    
curl_setopt($chCURLOPT_MAXREDIRS5);
    
curl_setopt($chCURLOPT_RETURNTRANSFERtrue);
    
curl_setopt($chCURLOPT_SSLVERSIONCURL_SSLVERSION_DEFAULT);
    
curl_setopt($chCURLOPT_SSL_VERIFYPEERtrue);
    
curl_setopt($chCURLOPT_TIMEOUT30);
    
curl_setopt($chCURLOPT_URL$url);
    
curl_setopt($chCURLOPT_USERAGENTgetenv('HTTP_USER_AGENT'));
    global 
$host$cookie;
    if (
$referer || is_file($cookie) && basename($cookie) === $host)
    {
        
curl_setopt($chCURLOPT_COOKIE$cookie);
        
curl_setopt($chCURLOPT_COOKIEFILE$cookie);
        
curl_setopt($chCURLOPT_COOKIEJAR$cookie);
        
curl_setopt($chCURLOPT_REFERER$referer);
    }
    else
    {
        global 
$scheme;
        
curl_setopt($chCURLOPT_COOKIEtrue);
        
curl_setopt($chCURLOPT_COOKIESESSIONtrue);
        
curl_setopt($chCURLOPT_REFERER$scheme'://'$host);
    }
    return 
curl_exec($ch);
    
curl_close($ch);
}

function 
path2uri($path$url)
{
    global 
$server_name$scheme$extension;

    if (
substr($path01) === '#' || strpos($path'base64') !== false || strpos($path'mailto:') !== false || strpos($path'tel:') !== false)
        return 
$path;

    if (
stripos($path'http') === 0)
        return 
$server_name$path;

    if (
$path === './')
        return 
$server_namedirname($url);

    if (
substr($path02) === '//' && isset($scheme))
        return 
$server_name$scheme':'$path;

    if (
is_numeric($path) && is_numeric(basename($url)))
        return 
$server_namedirname($url). '/'basename($path);

    if (
substr($path01) !== '.' && substr($path01) !== '/' && is_numeric(basename($url)))
        return 
$server_namedirname($url). '/'$path;

    
$exurl explode('/'$url);

    if (!isset(
$exurl[2]))
        return 
$server_name$url;

    
$fqnd $scheme'://'$exurl[2];

    if (!
$exurl parse_url($url))
        return 
$server_name$url;

    
$xpath = isset($exurl['path']) ? $exurl['path'] : '/';

    if (
strpos($path'?') === 0)
        return 
$server_name$fqnd$xpath$path;

    if (
strpos($path'/') === 0)
        return 
$server_name$fqnd$path;

    
$xpathy array_filter(explode('/'$xpath), 'strlen');
    
$endpath end($xpathy);

    if (
strpos($endpath'.') !== falsearray_pop($xpathy);

    foreach(
explode('/'$path) as $expath)
    {
        if (
$expath === '.') continue;
        if (
$expath === '..')
        {
            
array_pop($xpathy);
            if (
substr($xpath, -1) === '/' || $extension) continue;
        }
        if (
$expath !== ''$xpathy[] = $expath;
    }
    
$uri $fqnd'/'implode('/'$xpathy);

    if (
substr($path, -1) === '/')
        
$uri .= '/';

    return 
$server_name$uri;
}

function 
mime($str)
{
    
$finfo = new finfo(FILEINFO_MIME_TYPE);
    return 
$finfo->buffer($str);
}

function 
cdata($m)
{
    if (
strpos($m[0], 'CDATA') !== false)
        return 
$m[0];
    else
        return 
$m[1]. '<![CDATA['html_entity_decode(str_replace(PHP_EOL''$m[2])). ']]>'$m[3];
}

function 
xlink($m)
{
    global 
$server_name;
    if (isset(
$m[1])) return $m[1]. $server_namestr_replace('&amp;''%26'trim($m[2])). $m[3];
}

function 
export_url($m)
{
    global 
$scheme$url;
    
$n str_replace(array("'"'"'), ''trim($m[2]));
    if (
substr($n02) === '//' && isset($scheme))
        
$n $scheme'://'$n;
    if (
strpos($n'data:') !== false)
        return 
$m[1]. $n$m[3];
    else
        return 
$m[1]. path2uri($n$url). $m[3];
}

function 
mb_decode_entity($m)
{
    return 
mb_convert_encoding($m[0], 'UTF-8''HTML-ENTITIES');
}

function 
headers()
{
    return array(
        
'Accept-Language: 'getenv('HTTP_ACCEPT_LANGUAGE'),
        
'Accept: 'getenv('HTTP_ACCEPT'),
        
'Cache-Control: 'getenv('HTTP_CACHE_CONTROL'),
        
'Connection: 'getenv('HTTP_CONNECTION'),
        
'DNT: 'getenv('HTTP_DNT'),
    );
}

function 
getClearanceLink($content$url)
{
    
#MIT License
    #Copyright (c) KyranRana
    #https://github.com/KyranRana/cloudflare-bypass/
    
sleep(4);
    
preg_match_all('/name="\w+" value="(.+?)"/'$content$matches);
    
$params = array();
    list(
$params['jschl_vc'], $params['pass']) = $matches[1];
    
$start strpos($content's,t,o,p,b,r,e,a,k,i,n,g,f,');
    
$end strpos($content'</script>'$start);
    
$script substr($content$start$end-$start);
    
preg_match_all('/:[\/!\[\]+()]+|[-*+\/]?=[\/!\[\]+()]+/'$script$matches);
    
$php_code '';
    foreach(
$matches[0] as $js_code)
    {
        
$js_code str_replace(array(')+(''![]''!+[]''[]'), array(').(''(!1)''(!0)''(0)'), $js_code);
        
$php_code .= '$params[\'jschl_answer\']'. ($js_code[0] == ':' '='substr($js_code1) : $js_code). ';';
    }
    eval(
$php_code);
    
$params['jschl_answer'] = round($params['jschl_answer'], 10);
    
$uri parse_url($url);
    
$params['jschl_answer'] += strlen($uri['host']);
    return 
sprintf("%s://%s/cdn-cgi/l/chk_jschl?%s"$uri['scheme'], $uri['host'], http_build_query($params));
}

search.ini に仕込む

/home/ユーザー名/.opera/search.ini の任意の箇所に下記のコードをペーストし、「xx」の番号などを適宜変更する。 [Search Engine yy] UNIQUEID=yyy Name=英和翻訳 Verbtext=0 URL=http://localhost/opera-preview.php?e2j=%s Query= Key=e Is post=0 UseTLD=0 Has endseparator=0 Encoding=utf-8 Search Type=0 Position=-1 Nameid=0 Deleted=0 [Search Engine xx] UNIQUEID=xxx Name=Preview Verbtext=0 URL=http://localhost/opera-preview.php?url=%s Query= Key=p Is post=0 UseTLD=0 Has endseparator=0 Encoding=utf-8 Search Type=0 Position=-1 Nameid=0 Deleted=0

使い方

プレビューしたいときは該当するページでアドレスバーの先頭に「p 」を入力しエンターを押す。 英和翻訳は「e 」。

注意点

1. PHP を経由することで見られるようになるのは何故のことか定かでなく、ややもすれば暗号化されているかも定かではないので、その点に不安を感じる方は使わぬが吉。 2. Javascript はスクリプト内の URL を変換していないため、サイトによっては問題が生じるかもしれないので、その点に不安を感じる方は使わぬが吉。 3. あくまでプレビュー用途であるため、当該サイトを完全に再現できるわけではないので、その点に不安を感じる方は使わぬが吉。 4. アクセスログなどの肥大に注意! → /opt/lampp/etc/httpd.conf および php.ini の編集推奨

追記

画像表示などに時間が掛かる場合は、php.ini を管理者で開いて以下のように編集する。
/opt/lampp/etc/php.ini ; http://php.net/output-buffering output_buffering=409600 ; http://php.net/memory-limit memory_limit=1280M
Opera 12 をテキストブラウザにする方法

類似する記事

インストールされているフォントの書体見本を作成するスクリプト - 43%
Opera 12 をテキストブラウザにする方法 - 40%
Linux Mint 17.1 で今は亡き Glippy のエラーを修復してみる - 37%

シェア

コメント

当フォームより収集される個人情報は、返信を要する際に使用されるものであり、法令に基づく行政機関等への提供を除き、ご本人の同意を得ずに第三者に提供することはありません。また、コメントが掲載される場合であってもメールアドレスが記載されることはありません。