LoginSignup
0
0

More than 3 years have passed since last update.

IEでしか見られないサイトをモダンブラウザで見られるようにする

Last updated at Posted at 2019-06-13

化石を発見

どことは言わないが,とある有名企業で残骸を発見した.
ご丁寧に「Internet Explorerでしか開けません」と書いてある.
MacやLinuxでは見られないというのはなんとも悲しい.

中身を見たらVBScriptで書いてあるではないか!
残念,2年前(2017/07)にInternet Explorer 11からデフォで外されると発表されたので,もはやIEですらエミュレーションモードでしか開けないページとなっているのである.
良いサービスではあるので,なんとか自分用に使えるようにしてみた.
利用規約に引っかかるとは思いませんが,なにかあると嫌なので実際にどのWebサイトかへの言及は避けます.

HTML5/JavaScriptで書き直す

といってもサーバに手を加えることはできない.
ローカルでhtml/jsのそれぞれを用意して,GETしてきてはbodyだけをすげかえて描画する,ということをしてなんとか表示できるようにした.

(準備)CORSをすり抜ける

ローカルにあるhtmlファイルのoriginはnullなので,XMLHttpRequestのような関数で該当のWebページを取ってこようとするとCORSに引っかかる.

/path/to/chrome --disable-web-security --user-data-dir

のように,2つのオプションをつけてChromeを起動すれば,CORSを無効にすることができる.

JavaScriptでフェッチして描画

該当のWebページは以下のような構成になっている.

<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=x-sjis" />
  <script language="vbscript">
    Sub hoge
      location.href = "fuga.html"
  </script>
</head>
<body>
  <button onclick="Call hoge">
</body>
</html>

ボタンアクションなどに合わせてVBScriptでページの遷移をしているから,IE以外では使えないということらしい.
最近は減ったはずだが,Shift_JIS(x-sjis)を使っているのでこの際UTF-8になおしてやろう.
文字エンコーディングを変更するためには,一度Blobで取得して,それをテキストとして解釈すればよい.
あとはDOMにパースして必要な部分を描画する.

こっちで用意したhtml/jsから読み込むにはこんな感じのコードを用意する.

<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <script type="text/javascript">
    window.onload = () => {
      getBlob("piyo.html").then(
        (blob) => translateFrom(blob, "x-sjis").then(
          (doc) => displayBody(doc)
        )
      )
    }

    var getBlob = (url) => {
      return new Promise((resolve, reject) => {
        var xhr = new XMLHttpRequest();
        xhr.onload = () => {
          resolve(xhr.response);
        }
        xhr.responseType = "blob";
        xhr.open("GET", url);
        xhr.send();
      });
    }

    var translateFrom = (blob, encoding) => {
      return new Promise((resolve, reject) => {
        var rdr = new FileReader();
        rdr.onload = (event) => {
          // text/html -> DOM
          var psr = new DOMParser();
          var doc = psr.parseFromString(event.target.result, "text/html")
          resolve(doc);
        }
        // x-sjis(encoding) -> utf-8
        rdr.readAsText(blob, encoding);
      });
    }

    var displayBody = (doc) => {
      // deeply copy the body
      var body = document.importNode(doc.body, true);

      // replace original body with fetched one
      var html = document.body.parentNode;
      html.removeChild(document.body);
      html.appendChild(body);
    }
  </script>
</head>
<body>
  <p>loading...</p>
</body>
</html>

ひとまずこれで,body以下を取り込むことができる.

ボタンの中身を入れ替える

ボタンはいまだにCall hogeになっていて,これはVBScriptを呼び出している.
そこでこのボタンを見つけて,onclick時のイベントを書き換えてあげよう.
下は変更する部分のみを記述する.

window.onload = () => {
  getBlob("piyo.html").then(
    (blob) => translateFrom(blob, "x-sjis").then(
      (doc) => useJSFunction(doc).then(
        (doc) => displayBody(doc)
      )
    )
  )
}

var useJSFunction = (doc) => {
  var buttons = doc.getElementsByTagName("button");
  for (var i = 0; i < buttons.length; i++) {
    var b = buttons[i];
    var oldFunc = b.getAttribute("onclick");
    var newFunc = oldFunc.replace("Call ", "javascript: ");
    b.setAttribute("onclick", newFunc);
  }
}

var hoge = () => {
  getBlob("fuga.html").then(
    (blob) => translateFrom(blob, "x-sjis").then(
      (doc) => displayBody(doc)
    )
  )
}

ほとんどのブラウザで,onclickなどの処理はJavaScriptで解釈されるのがデフォルトのはずだが,一応JavaScriptのコードですよーということを明記しておく.
実際にボタンが押されるとJavaScriptのhoge関数が呼ばれて,fuga.htmlのbodyを表示するようになる.
もちろんfuga.htmlでVBScriptが使われていて変更する必要があるなら,変更した上でbodyに描画する.
取ってきたhtmlのタグに含まれていないデザインは吹き飛ぶので,適宜<head>内にcssへの参照を入れておいたり,styleをJavaScriptからいじるなどしても良い.

formタグへの対応

上の例ではボタンクリック時のページ遷移を,フェッチしてbodyに描画するというものに置き換えていた.
これは,あくまで自分のローカル内に用意したhtmlファイルから外に出ないためだ.
なので<a>タグなども同様に,hrefをjavascript: void(0)などにしてリンクを無効にして,onclickで対象のページを取ってくる作業が必要だ.

しかし<form>タグなどでactionへの送信後にページにジャンプするものは,これでは対処できない.
タグの仕様で,ジャンプすることが原則になっているためだ.
ならば,<form>でやっていることをJavaScriptから実行してしまえばいい.

var submitForm = (url, data) => {
  // data: e.g. [hoge: "hogehoge", fuga: "fugafuga"]
  var urlEncodedDataPairs = [];

  for(var name in data) {
    urlEncodedDataPairs.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[name]));
  }
  var urlEncodedData = urlEncodedDataPairs.join('&').replace(/%20/g, '+');

  var xhr = new XMLHttpRequest();
  xhr.onload = (event) => {
    alert("done");
  }
  xhr.open("POST", url);
  xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  xhr.send(urlEncodedData);
}

まとめ

おわかりいただけたとおり,エラーハンドリングはほとんどしていません.
Promiseでreject使ってるくせに何やってんだよ!
というお叱りもいただくかもしれません.
また私がJavaScriptの初心者なので,変な書き方やブラウザ互換性のないコードになっているかもしれません.
そのあたりのブラッシュアップのためにも,コメントはどんどん待っております.

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0