WordPress 4.6で追加されたdns-prefetchを無効化する

WordPress 4.6からヘッダーに<link rel="dns-prefetch" href="//s.w.org/">が追加されるようになりました。
見つけた瞬間サイトがクラックされたのか?!とヒヤっとしたけれど、s.w.orgはWordPressのショートドメインて事がわかって一安心しましたw

うちはWordPressの絵文字とかを使っていないのでs.w.orgのDNSプリフェッチは必要なし。
なのでこれを無効化してみました。

作成したPHPコードはこれ。

<?php
 
add_filter('wp_resource_hints', function ($urls, $relation_type) {
    if (is_admin() === false) {
        if ($relation_type === 'dns-prefetch') {
            return array();
        }
    }
 
    return $urls;
}, 10, 2);
 
?>

コードは簡単でwp_resource_hintsにフィルターをかけて、管理ページ以外かつタイプがdns-prefetchの場合は定義されている内容を空っぽにして返すって感じ。
管理ページの場合は、なにかあるとダメなので引数をそのまま返すようにしてあります。

全く使わないならremove_action('wp_head', 'wp_resource_hints');の方がはやいんじゃない?って思ったんだけど、なぜかこれが効かなかったのでadd_filterで対処する荒療治に。

ちなみに、この記事を書いた時の$relation_typeの種類はdns-prefetch、preconnect、prefetch、prerenderとありました。
詳しい動作を追いたい場合はwp-includes/general-template.phpの2800行付近にfunction wp_resource_hints()があるのでそこから見てください。

archive.isにアーカイブされたページで警告を表示する。

archive.isをブロックしたりして対策をしてもアーカイブされちゃう事があります。
その対策の間をぬってアーカイブされちゃったページに警告を表示するJavaScriptを作ってみました。

if (location.hostname != "yourdomain") {
    document.title = "[不正コピー]";
    document.getElementsByTagName("body")[0].innerHTML = "";
 
    var i, html = "";
    for (i = 0; i <3000; ++i) {
        html += "/// 不正コピーです! /// ";
    };
    document.getElementsByTagName("body")[0].innerHTML = html;
    html = null;
};

コードは簡単、location.hostnameを比較してyourdomain以外なら警告を表示するコードを実行するだけ。
動作内容はタイトルを「[不正コピー]」に変更し、BODYエレメント内容を全部削除し代わりに「/// 不正コピーです! ///」の文字を3000回並べます。
yourdomainはあなたのサイトのドメイン名に変更して下さい、変更しないと本物のサイトでこのメッセージが表示されて悲惨なことになりますw

JavaScriptなので当然JavaScriptを動作しないようにしてある環境では動きませんが、現在はJavaScriptが動かない環境の方が少ないのである程度の効果はあると思います。

序で・・と言ったらあれですが・・
この文字を表示する動作を重くしたい場合は以下のようにコードを変更するだけ。

if (location.hostname != "yourdomain") {
    document.title = "[不正コピー]";
    document.getElementsByTagName("body")[0].innerHTML = "";
 
    for (var i = 0; i <3000; ++i) {
        document.getElementsByTagName("body")[0].innerHTML += "/// 不正コピーです! /// ";
    };
};

これは文字が追加される毎にDOMのレンダリングが発生するのでレンダリング負荷が増えます。
低スペックのPCやモバイル端末ではクラッシュさせる事もできるかも。
本当に重くさせるのであれば無限ループ化すればOK。

ちょっと応用すればarchive.isのロボットを狙い撃ちでクラッシュさせアーカイブを中断させる事も可能です。

Twitterにアップされている動画のTSファイル一覧を表示&保存する

Twitterにアップされている動画で保存したい物があったので、HTTPリクエストログからURLをゲットしようとおもったら・・・
なんとm3u8の再生リスト形式になっていて動画自体も.tsに分割されていました。

#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=320000,RESOLUTION=240x180,CODECS="mp4a.40.2,avc1.42001f"
/ext_tw_video/.../pu/pl/240x180/???.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=832000,RESOLUTION=480x360,CODECS="mp4a.40.2,avc1.42001f"
/ext_tw_video/.../pu/pl/480x360/???.m3u8
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-TARGETDURATION:3
#EXTINF:3.000,
/ext_tw_video/.../pu/vid/0/3000/480x360/???.ts
#EXTINF:3.000,
/ext_tw_video/.../pu/vid/3000/6000/480x360/???.ts
#EXTINF:3.000,
/ext_tw_video/.../pu/vid/6000/9000/480x360/???.ts
#EXTINF:3.000,
/ext_tw_video/.../pu/vid/9000/12000/480x360/???.ts
#EXTINF:3.000,
/ext_tw_video/.../pu/vid/12000/15000/480x360/???.ts
....

再生リストから欲しいサイズの動画を選んで分割ファイルをダウンロードすれば良いんだろうけど面倒くさいw
それに、分割は3秒毎なので2分を超える動画は70ファイル超え!

そんなの1つずつURLをコピペなんてやってられない・・って事で、動画サイズ毎のURLとファイルを一覧表示するGreasemonkeyスクリプトを作ってみました。
動作してる動画はこちら。

1ファイル毎に手動保存なのはローカルに自動でファイルを保存するAPIが呼び出せないから。
userChrome.jsとして動かせばできるんだけど、セキュリティ的にあまり宜しくない。

まあ随分と楽になるんじゃないかなーと。
保存時にはINDEXに表示されている番号と同じファイル名にしないと、TSファイルの連結時に時系列がごちゃごちゃになりますw

おまけ?として法人など業界用の動画VMAP形式の動画も落とせるようにしました。
分割されていないので楽ちんですw
続きを読む »

WordPressが生成したサムネイル画像からexif情報を削除する

WordPressで画像をアップロードするとサムネイル画像が生成されますよねー。
そのサムネイル生成方法はサーバー設定でImagickが有効化されているとImagickがGDが有効な場合はGDが使用されています。
うちの環境はImagickを実行するとApacheを巻き込んでクラッシュするので仕方なくというかPHPではメジャーで軽いGDほぼ一択。

しかしGDでJPEGを生成するとexifコメントに「CREATOR: gd-jpeg v1.0 (using IJG JPEG v90), quality = ...」って情報が追加されてしまいます。
たかが数バイトのデータですが、Yslow等のWebサイトの計測ページでは警告されマイナスポイントになりますし、要らないデータなのでない方がいいかなー。

なので、アップロードした画像と作成されるサムネイルのexif情報を削除するプラグインを作ってみました。
サムネイルのexif削除はGDを使用しているサーバー向けで、Imagickを使ってる場合はサムネイルにはexif情報は記録されません。

exifを削除するのに使用する物はImageMagickのスタンドアローンバージョン又はIMagick。
スタンドアローンを使う場合は、ImageMagickがインストールされている環境でないとダメ。

まずは完成PHPソース。

<?php
/*
Plugin Name: Remove EXIF
Plugin URI: http://blog.wolfs.jp/20160707-3638/
Description: アップロードした画像とサムネイル画像のexif情報を削除します。
Version: 1.0.0
Author: Kerberos
Author URI: http://blog.wolfs.jp/
*/
 
class removeExif {
    private $imagemagick_cli = true;
    private $imagemagick_path = '/usr/imagemagick/convert';
 
    public function __construct() {
        add_filter('wp_handle_upload', array($this, 'wp_handle_upload'));
        add_filter('wp_generate_attachment_metadata', array($this, 'wp_generate_attachment_metadata'), 10, 2);
    }
 
    public function wp_handle_upload($arg) {
        if ($this->check_mime($arg['type']) === true) {
            $this->remove_exif($arg['file']);
        }
 
        return $arg;
    }
 
    public function wp_generate_attachment_metadata($metadata, $attachment_id) {
        $dirArr = explode('/', $metadata['file']);
        $baseDir = wp_upload_dir(null, false);
        $uploadDir = $baseDir['basedir'].'/'.$dirArr[0].'/'.$dirArr[1].'/';
 
        foreach ($metadata['sizes'] as $entry) {
            if ($this->check_mime($entry['mime-type']) === true) {
                $this->remove_exif($uploadDir.$entry['file']);
            }
        }
 
        return $metadata;
    }
 
    private function check_mime($mime = null) {
        return ($mime === 'image/jpeg' || $mime === 'image/jpg');
    }
 
    private function remove_exif($filePath) {
        $filePath = addslashes($filePath);
 
        if (file_exists($filePath) === true) {
            if ($this->imagemagick_cli === true) {
                if (is_executable($this->imagemagick_path) === true) {
                    try {
                        exec('"'.$this->imagemagick_path.'" "'.$filePath.'" -strip "'.$filePath.'"');
                    } catch (Exception $e) {}
                }
            } else {
                if (class_exists('Imagick') === true) {
                    $im = new Imagick($filePath);
 
                    try {
                        $im->stripImage();
                        $im->writeImage($filePath);
                        $im->clear();
                        $im->destroy();
                    } catch (Exception $e) {}
                }
            }
        }
    }
}
 
new removeExif();
?>

かなり簡単なコード。(`・ω・)b

各ファンクションの簡単な説明は・・・
続きを読む »

TaoTronics Selfie Stick TT-ST001を買ってみた

今まで使っていたダイソー製300円の自撮り棒は、伸縮部分は回転する、アーム部分は破損する等あまり良い物ではなかった。
アーム部分は買い換えるのが高く付くほど壊れるので、グルーガンで補強したりして使ってましたw
ダイソー自撮り棒
まあ汎用のカメラ三脚ネジで色々連結できるので、長い三脚として使ったりできるのは楽だったけれど、やっぱりダイソークオリティ。

なので、海外ではSelfie Stickで有名なTaoTronicsの自撮り棒「TaoTronics Selfie Stick TT-ST001」を買ってみました。
値段はこの記事を書いた時点で2,199円、まあそこそこの値段。

TT-ST001の特徴は、
 ・Bluetoothでシャッターを操作 (Android、iPhone対応)
 ・バッテリー30時間
 ・エアロスペースアルミニウム製
 ・最大荷重5Kg
 ・アーム角度270度、伸縮76cm
 ・重さ120g、折りたたみ時 全長18cm 幅5cm
って所です。
 
早速届いた商品を開封。
TaoTronics TT-ST001 - パッケージ TaoTronics TT-ST001 - パッケージ中身
外箱はツルっとした厚紙で内箱とピッチリサイズなので若干取り出しに手こずりましたw
内箱にはサラっとした半透明のビニールに包まれた本体が。
続きを読む »