0.やりたいこと
自サーバにはphpファイル1個のみを置く。
file_get_contents(Googleドライブにアップしたhtmlファイル)
をやることで、
あたかもコンテンツを持ったサーバであるかのように扱いたい。
これができると、パソコンやスマホなどから容易にページが更新できて便利だ(ftp接続が要らない)。
1.課題
普通にhtmlファイルをアップしてGoogleドライブの画面から素直にリンクを取得しても、うまくいかない。2つ工夫する必要がある。
1-1. 課題1つ目
1つは、「Googleドライブ専用の画面」が開き、その内部でコンテンツを開いてしまうという問題。
例えば、こんな感じ。
https://drive.google.com/open?id=1QDGsTNesm_JKLy5Tgojz70kZdPDo5cjk
この問題を解決するには、urlをちょっといじる。
open
をuc
に書き換えるだけでよい。
こんな感じ。
https://drive.google.com/uc?id=1QDGsTNesm_JKLy5Tgojz70kZdPDo5cjk
確かに変な画面内でコンテンツを開くという問題はなくなった。
1-2. 課題2つ目
しかし、1-1節の方法でhtmlファイルを共有しようとすると、Googleドライブはhtmlファイルをダウンロードさせようとする。ダウンロードせずに直接表示したいのに。。。
https://drive.google.com/uc?id=1QDGsTNesm_JKLy5Tgojz70kZdPDo5cjk&export=viewとしても、https://drive.google.com/uc?id=1QDGsTNesm_JKLy5Tgojz70kZdPDo5cjk&export=view#dummy.htmlとしても結果は変わらず。
しかし、bmpなどの画像ファイルではなぜかうまくいく。(ダウンロードではなく普通にブラウザで表示してくれる)
こんな感じ。
[https://drive.google.com/uc?id=1LtcHFzaYa1bahScgEZRFjxuStIgZ0Udx]
(https://drive.google.com/uc?id=1LtcHFzaYa1bahScgEZRFjxuStIgZ0Udx)
いろいろやってみると、uc
を使ったとき、Googleドライブではファイルの種類ごとに異なる仮想サーバへリダイレクトし、そこからコンテンツ提供しているようだとわかった。
例えばbmp形式やpng形式では「doc-04-3c-docs.googleusercontent.com」から、
html形式では「doc-04-b4-docs.googleusercontent.com」からだった。
さらに、htmlファイルの拡張子を変更し、test.pngというファイルとしてアップロードしたものを表示しようとすると、これもバレて、「test.png.html」というファイルとしてダウンロードが開始してしまった。
きっと仮想サーバごとに、コンテンツ提供の方法がダウンロードか、そのままブラウザで表示させるかが異なるのだろう。
2. 実験
1-2節の問題を解消し、ブラウザ上でGoogleドライブに保存したhtmlファイルを表示させるため、次のような方法を考えた。
「空のbmpファイルを作り、内部にhtmlソースを書き込み、これをGoogleドライブにアップロードする(2-1節)。
これをサーバサイドプログラムがちゃんと認識すれば、内部にあるhtmlソース通りに表示できるだろう(2-2節)。」
2-1. bmpファイルにhtmlを埋め込む
bmpは画像のフォーマットの一種だ。他の形式と比較して極めて単純な構造を持っていて、バイナリエディタなどで16進(あるいは256進)表示すると、画像の画素の並びに従ってbitが記録されていることが分かる。構造が簡単な故に改編なども容易だ。そのため、「画像に画像以外の情報を埋め込む」には最適なフォーマットであるといえる。
次の手順でhtmlソースを埋め込んだ。
- c.bmpを作成し、ペイントで開き、24色1000px×1000pxとした
- バイナリエディタStirlingでb.bmpを開き、FFの連続が開始しているところから、
<html>hello world</html>
という文字列を上書きした。バイト数が変わらないように気を付けた。(これが変わるとファイルが壊れてしまう) - これをGoogleドライブにアップロードした。
https://drive.google.com/uc?id=1-G5TkDMgZBAeH2t8TudaVRF9BMwgRAGy
- 手順3のリンクを開くと、大きな白地の画像の、左下にかすかに黒い小さな線があるのが分かるだろうか。これが
<html>hello world</html>
という情報を表現している。 - このファイルをダウンロードし、再びバイナリエディタで開いた。確かに
<html>hello world</html>
という情報は残っていた(圧縮などが自動で書けられ、壊されてしまう可能性があり、調べた)
以上で、Googleドライブはhtmlファイルを、専用画面でもダウンロードでもなく、ブラウザに直接表示することになった。但しbmp画像として。
2-2. サーバ上でbmpファイルからhtmlを取り出す
2-1節で作ったbmp画像からhtmlファイルを取り出すのは自サーバのphpファイルの仕事だ。
次のようなプログラムを書こう。やってることは、「file_get_contensでページを取得したら、そこから<html>
~</html>
を取り出して、それを表示してね」という単純な処理だ。
<?php
$asBmp = file_get_contents("https://drive.google.com/uc?id=1-G5TkDMgZBAeH2t8TudaVRF9BMwgRAGy");
/* urlパラメータ「id」でファイルIDを動的に変えたいなら次の通り
$asBmp = file_get_contents("https://drive.google.com/uc?id=".$_GET['id']);
*/
$start = strpos($asBmp, '<html');
$end = strpos($asBmp, '</html>')+7;
$html = substr($asBmp, $start, $end-$start);
print $html;
3.感想
こんな手垢のつきまくったであろう手法で出来ることなのだから、きっとこれは想定外の脆弱性などではなく、裏技の類なのだろうと思った。(だからここで公開した。)
何はともあれ、これによって、「パソコン上でファイルを更新すれば後は自動でホームページが更新される」という仕組みが完成した。うれしい。