Archive for the ‘JavaScript’ Category

[IE7|IE8] jQueryのfadeIn/fadeOutした時にpng画像が変になる時のTips


2011
04.22

悪名高き IE6 がついに Yahoo さんからも干されてデベロッパー歓喜!となってから、それなりに時間が過ぎましたね。

あなたの会社では IE6 のサポート状況は如何なものでしょう?当社では Yahoo さんもこうしていますよ、せめて IE7 にしましょ?ね?ね?と言う地道な活動を続けて、それなりに効果が出ています。

実際 IE6 をサポートしなければ CSS がシンプルに書けたり、png のアルファチャンネルをプラグイン無しで描画出来…で、き…

 

出来てないじゃん!

 

と言う訳で今回は IE7 と IE8 で再現を確認したアルファチャンネルの描画バグをフィックスします、症状は下記のような感じ。

  • 普通に img 要素で描画する分には問題無い
  • 既に描画されている要素の opacity を弄るとアルファチャンネル部分が黒くなる

普通にサイトを作っていて、png ファイルの要素の opacity を弄るなんて事はまず無さそうですが、最近はスタイリッシュにファッファさせたくなるじゃないですか?マウスオーバーしたらメニューが、みたいな。

それをお手軽に使いたい時はなんと言っても jQuery の fadeIn / fadeOut ですよね、例えば fadeIn は要素の opacity を一旦 0 にしてから display:block 状態に、そこから opacity を 1 になるまで加算すると言う処理を勝手にやってくれます。

つまり opacity 弄っちゃってます、IE7 と IE8 はここにアルファチャンネルが含まれた png 画像が描画されていると残念な黒い何かが出てしまうと言う訳です。

M$さんは「png ファイルのアルファチャンネルに対応しました(笑)」って言ってたのにね。

 

それではサクッとフィックスしましょう、解決法は AlphaImageLoader を引き続き使う。これで良いと思います、IE 自慢の独自フィルターだし。そもそも IE しかこの症状出ないから、自己解決させるのが最上の手段でしょう。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
$(function() {
    if(navigator.userAgent.indexOf("MSIE") != -1) {
        $('img').each(function() {
            if($(this).attr('src').indexOf('.png') != -1) {
                $(this).css({
                    'filter': 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' +
                    $(this).attr('src') +
                    '", sizingMethod="scale");'
                });
            }
        });
    }
});

ページの読み込みが完了したらブラウザ判定、どうやら IE だなとなれば html 上の img 要素全てを each して、src 属性に “.png” が含まれていたら AlphaImageLoader をかける。

 

これで IE7 と IE8 で思う存分ファッファ出来るようになる、IE6 は多分これだと駄目だと思うけど。

Yahoo さんの非推奨ブラウザなので今回は無視する方向で、Yahoo さんいつもスケープゴートになってくれてありがとう。

 

それではまた。

 

JavaScript のソースは隠蔽するべきか? Vol.4


2011
04.21

皆さんこんにちわ、JavaScript のソース隠蔽について考えるコラムも今回で一応の結論を出そうと思います。

今回はもう既に色々出来上がっているので、無駄な前置きはググッと我慢して進めます。

 

それではこのミッションを遂行するための手持ち武器をまとめます。

  • JavaScript による navigator.userAgent と navigator.platform のチェックで偽装を認めない認証
  • Ajax による非同期なソース展開、送受信は POST とする事で URL 欄からの単純な攻撃を防ぐ
  • 開発は通常通り JavaScriptファイル(.js)で行い、呼び出す時は PHP 内でファイルを読み込んで文字列のみ送信
  • 認証を通らない時は何か画面に表示する
  • JS を切られたらもうそれは無視する

こんな感じですね、それでは解説を交え早速実装して行きましょう。

 

取りあえずファイル構成はこんな感じで想定してます。

/index.html
/js/jquery.js
/js/hoge.js
/js/foo.js
/js/piyo.php

適当なディレクトリに上記構成でファイルを作成してください、foo.js隠蔽したいファイルです。
条件を満たすと非同期に foo.js の中身が index.html に送信されるようにします。

 

まずは html 部分から、今回と言うか当 blog ではほぼ毎回 jQuery を使います、言うまでも無く色々と捗るので。

head 要素内に…

1
2
3
<script src="./js/jquery.js" type="text/javascript"></script>
<script src="./js/hoge.js" type="text/javascript"></script>
<script id="moge" type="text/javascript"></script>

jquery.js はご存知のライブラリ、まず呼び出しておきましょう。
hoge.js は判定文を書きます。
3行目は入れ子です、最終的に全て条件を満たすとこの中にソースを送信します。

 

次は hoge.js の中身です、前回の条件を踏まえて2つの condition を書いて上げましょう。

1
2
3
4
5
6
7
$(function() {
    if(navigator.platform.indexOf('iPhone') != -1 && navigator.userAgent.indexOf('iPhone') != -1) {
        $('#hoge').load('./js/piyo.php', {mode:'hoge'});
    } else {
        alert('error');
    }
});

iPhone シミュレータもハネたい場合は2行目を

1
if(navigator.platform == 'iPhone' && navigator.userAgent.indexOf('iPhone') != -1) {

にすれば良いかと思います。

navigator.userAgent も判定しているのは、将来的に webkit じゃないブラウザが出て来たら…と思うのですが  iOS の仕様的にあり得ない気もするので無くても良いと思います。

 

最後に piyo.php の中身です、使い回しが効くように switch で書いてみました。

1
2
3
4
5
6
7
8
9
switch($_POST['mode']) {
    case 'hoge':
        print(file_get_contents('./foo.js'));
        break;

    default:
        print('error');
        break;
}

 

えーと、これでおしまいです。

今回前置きを書かなかったのは、このシンプルなコードを書くために計3回もの記事を消費した訳で。このコラム自体が壮大な前置きだったんだよ!!と言う事に気づいたからです。

いや、まぁ実際に検証してみるってのは大事な事だと思うので無駄では無い。ハズ。

 

気を取り直して解説、

  • http request が来た
  • hoge.js Line:2 で判定
    • どちらも条件を満たした(次へ)
    • どちらかの条件が満たせなかった(エラー出力などして終了)
  • hoge.js Line:3 で id=hoge(script の入れ子)に piyo.php を呼び出す、mode と言うキーで hoge と言う文字列を POST する
  • piyo.php はコールされると $_POST[‘mode’] を見て分岐処理を行う、何も渡されずに呼ばれたら error と言う文字列を返す
  • piyo.php Line:3 にだけ書かれた foo.js のパスからファイルの内容をロードして print を実行、サーバサイドなのでブラウザからは解らない
  • PHP でプリント(出力)されたものは POST 値としてブラウザに返される、jQuery の .load() の効果で index.html に書かれた入れ子の<script id="hoge">〜</script>の間に返された文字列が出力される
  • 出力されると同時にその JS は勝手に実行される

こう言う動きになります、シンプルで良いですね。

 

切ない人の為に上記を実装したサンプルをこちらにアップしました、iPhone 以外からだときっと動かないハズ。

iPhone でアクセスするとやっつけ感満載のパズルゲームが始まると思います、何となく html5 の canvas 使ってみたくてサ。

 

そしてこれは下記環境下なら恐らく上手く隠蔽出来るハズ

  • ソースの保存や Firebug 系のツールが無い環境
  • JS の navigator.platform が偽装出来ない環境

あんまり調べてないからアレですけど、iOS 系なら大丈夫なんじゃなかろうか?どちらにせよ結構な手間をかけないとソースは見えないと思います。

 

 

いやー、長かったですね。お付き合い頂いた皆様、お疲れさまです。

今回良く解ったのは普通の Web ブラウザ上で JS のソースを完全に隠蔽するのは不可能、と言う事です。

完全に隠蔽した Web App を作りたいのなら、一旦素の状態で完成させた物をネイティブアプリの入れ子にリソースを全て埋め込んで、アプリの機能で html を表示して使うアプリをリリースする。と言う方法しか無いんじゃなかろうかと思います、何だか敗北感が凄いですがそう言うモノなんでしょうね。

 

では、最後に締めの言葉を。

 

デバイス限定だけど、そんなに手間をかけずに見え辛くするのは可能だよ!
やりたい人はやっても良いと思うよ!!

 

嗚呼、やはりこうなってしまうんですね。

今回の事は雑学として覚えておけば、妥協点のポイントとして役立つ時が来るかもしれません。

 

それではまた。

 

1 | 2 | 3 | 4

 

JavaScript のソースは隠蔽するべきか? Vol.3


2011
04.20

本日もやります、だんだんとノッてきましたしね。

ノリ過ぎて JavaScript の隠蔽の是非を問うようなタイトルなのに、何としても隠蔽してやろうと言う趣旨に変わって来ていますね。

サーチエンジン的に言うとタイトルと内容が一致していない評価が低いコンテンツになっているかも知れませんが、最終的な手間や再現可能環境をまとめて「JavaScript のソースは○○した方が良いかもね!」と強引に締める事で誤魔化そうと考えているので問題無いハズです。

 

それでは前回のおさらいから始めましょう。

  • サーバサイドでは精密なデバイス判定は難しい
  • ローカルサイトでも単純な UserAgent 比較だけではお話にならない
  • ラスボスは Mac Safari5 だった(今の所)

こんな感じでしょうか、要するに Mac Safari5 を攻略すれば取りあえず Oh Yeah と言う事で話しを進めます。

余談ですが iPhone のデバイス判定については色々調べてみました、中にはスクリーンサイズを取得して…と言う方法があり目から鱗だったワケですが結構簡単に破れちゃうなぁと言う事で今回は見送りました。

検証した所 iPhone4 の retina ディスプレイは 640 × 960 なのですが、3G/3GS との下位互換のためにスクリーンサイズは 320 × 480 が返される仕様でした。そんなサイズの PC モニタなんて無いですから一見強そうなんですが、VirtualPC や VMFusion みたいなバーチャルコンソールのシングルウィンドウモードで、その大きさにマウスでちょちょいとリサイズすればあっさり突破出来てしまいました。中々厳しいです。

 

navigator オブジェクトを突っついてみよう

前回目星をつけていると言いましたが、この Object には UserAgent の他にも様々な情報が格納されています。

詳しくは初めてのホームページ講座さんなんかで、navigator オブジェクトの仕様とか説明してくれているので眺めてみましょう。

パッと見だと navigator.appName とか navigator.platform 辺りはかなり有望なんじゃ無いでしょうか?だって通常はそんなの偽装する意味がないもの。

 

と言う事で検証用ファイルを作ります、body 要素内に script 要素を書いて…

1
2
3
4
5
6
7
document.write(
'appCodeName : ' + navigator.appCodeName + '改行' +
'appName : ' + navigator.appName + '改行' +
'appVersion : ' + navigator.appVersion + '改行' +
'anguage : ' + navigator.language + '改行' +
'platform : ' + navigator.platform
);

こんな感じで良いかな、解れば良いよね。そんな事よりこのコードビュープラグイン、<br />って書けないんだね!気持ち悪いけど「改行=<br />」と思って下さい。

例によって切ない人用にこちらにアップロードしましたので、色々見て行きましょう。

 

iPhone4 実機 + Safari5

appCodeName : Mozilla
appName : Netscape
appVersion : 5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; ja-jp) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5
language : ja-jp
platform : iPhone

これがベースとなります、これと違う点を発見すれば良いですね。

 

Mac OSX 10.6 + Firefox4(FireMobileSimulator)

appCodeName : Mozilla
appName : Netscape
appVersion : 5.0 (Macintosh)
language : ja-JP-mac
platform : MacIntel

なんか Firefox 可愛い。

 

Mac OSX 10.6 + Safari5(Developer Tools)

appCodeName : Mozilla
appName : Netscape
appVersion : 5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8B117 Safari/6531.22.7
language : ja-jp
platform : MacIntel

キタコレ!appVersion は偽装してるみたいだけど、platform は流石にそのままですね!

 

ラスボス破れたり

 

と、言う事で判定は JavaScript で UserAgent と Platform を見る事にしましょう。

 

これで全ての武器が揃った訳ですが、海千山千の読者様は突っ込み所満載だなオイ!と思われているでしょう。

そうです、沢山問題がありますので弱点も今回のウチにまとめておきましょう。

  • navigator の中身全てを偽装するプラグインとかあったら負け
  • Safari5 より凄い開発ツールのあるブラウザがあると負け
  • 無くてもそう言うのを作れば良いだけなので負け

なんと言うか穴だらけですね!それでもまぁ市販のゲームだって逆アセかけて解析したり出来るしさ、データ周りだけサーバサイドで処理して送信するとかすればもう及第点と言う事で一つ。

次回はついにこの検証結果を踏まえた上での隠蔽プログラムの実装を紹介して終わろうと思います、もう少しお付き合いください。

 

それではまた。

 

1 | 2 | 3 | 4

 

オマケ:真のラスボス(ADP の公式シミュレータ)

真のラスボス
Platform は iPhone Simulator になってますね、ここは正直に書くのが礼儀的なものなのかも知れない。

 

JavaScript のソースは隠蔽するべきか? Vol.2


2011
04.20

皆さんこんにちわ、JS のソースを見られるのが恥ずかしくて頭が沸騰しちゃいそうなんだけど、どうにかならない?と言う話の第2弾です。

今回は UserAgent の偽装について検証してみます、考えて見れば本物と偽装の UA 文字列を見比べる機会って意外と無いんじゃないでしょうか?

私と同じく見比べチェリーなデベロッパーの皆様は、是非これを機に偽装の精度がどれ程のものかを認識して、今後様々なシーンで苦笑いと洒落込もうではありませんか。

ちなみにこの blog は大体こんな感じで行きます、めんどくさい感じで行きます。

 

まずは前回のおさらいとして、このミッションをクリアする為の作戦内容の確認から。

  1. 最強の脅威である PC の Web ブラウザ各種で見ているときはソースを出力しない
  2. 猪口才な UserAgent 偽装を見破り容赦なく例外処理を叩き込む
  3. 唯一の対象機が来た時のみ非同期にソースを出力する
  4. 隠蔽は解るけど開発効率もちゃんと考えた作りにする

実は条件を満たした後の処理は既に出来ています(判定処理を組み込んだ上で、非同期な分岐テクニックとして後ほど紹介します)ので、やはり偽装を見破れるかどうかがカギになっています。

今回の検証内容は完全に偽装する事が出来るブラウザが存在するのか?です。

では早速検証して行きましょう、PHP が動くサーバに適当な html ファイルを .php で作って下さい。

 

script 要素内に

1
alert(navigator.userAgent);

body 要素内に <?php?> で括って

1
print($_SERVER['HTTP_USER_AGENT']);

これで準備完了です、ローカルサイドとサーバサイドから UserAgent が出力されますのでその違いについてなんかも見れたら良いな。

ソース用意すんの面倒だよー、切ないよーと言う困ったさんはこちらにアップロードしたものを用意しましたので色んなデバイスのブラウザで試してみて下さい。

 

iPhone4 実機の Safari5

JS からの出力

Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; ja-jp) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5

PHP からの出力

Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; ja-jp) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5

なんと言うか同じですね、当然っちゃ当然。次からが本番、次から本気出す。

 

Firefox の FireMobileSimulator

ド定番と言うかもはやこれ無しじゃ寂しい夜を乗り越えられないレベルのアドオン、UA 偽装と同時に表示までシミュレートしてくれる世紀末開発者の救世主。なんと iPhone までシミュレートしちゃうスゴイヤツです。

WordPress とか EC-CUBE の携帯検証とかでお世話になってる人数多である事でしょう、使ってない人は今すぐ本家サイトへGO。
※今気づいたんですが、前はかわゆい蛙のアイコンだったと思うんだけど Firefox4 バージョンはなんかしなびたキュウリと言うかピータンみたいなアイコンになってますね?それはそれでかわゆい気がするけど。

では、早速 iPhone に偽装して調べてみましょう。

 

JS からの出力

Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0) Gecko/20100101 Firefox/4.0

PHP からの出力

Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_0_1 like Mac OS X; ja-jp) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5B108 Safari/525.20

キタ!なんかサーバサイドの方はまんまと騙されてるけどローカルサイドの方は正直なのね。とにかく Firefox にはこれで勝つる!!

 

Safari の開発ツール

開発には専ら Firefox & Firebug なので知らなかったんですが…Safari の開発ツールってこんなに凄い事なってるんですね。
Safariの開発メニュー
これは最早兵器レベルじゃないか、Win 機で検証するのが面倒だからこれで良いですか?と言いたくなる程豊富なユーザーエージェント。

 

JS からの出力

Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8B117 Safari/6531.22.7

PHP からの出力

Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8B117 Safari/6531.22.7

ん…?

 

これはマズい、完全に偽装されています。

 

この検証で確認したかった事は完全に偽装出来るブラウザが有るかどうかなので、なんの事は無い。ここに有るじゃん、この時点で検証終了です。

と言うのも完全偽装可能なブラウザが1つでも存在するならば、そのブラウザを使えばサーバをだまくらかしてソースを引っ張って来れる事になるので今回のミッションは失敗となってしまうからです。

 

ぐぬぬ、やはり楽はさせてくれないですね。しかしまだ諦めません、まだ可能性はあります。

 

今回のまとめ

  • サーバサイドの UserAgent は渡された物を疑わずに信じ込む純真な子なので使わない方が良い
  • Safari は自らの UserAgent をも欺く恐ろしい子
  • 単純な UA 比較だけでは全く持って通用しない

こんな感じなので、サーバサイドでブラウザと言うかデバイスの判定はしない方が良いですね。あくまでローカルサイドでやってしまいましょう、どうせ JS を切られたら非同期で送信されるソースも飛ばない(ここ重要!)から目的は達成される訳ですし!

 

次回は更に踏み込んだデバイス判定処理を考えて行きます、一応の目星は付けています。
JS の UA は navigator と言うオブジェクトから取得しているので、この navigator オブジェクトを突っつけば iPhone とその他デバイスの差異を発見出来る可能性が高いと思います。

それではまた。

 

1 | 2 | 3 | 4

 

JavaScript のソースは隠蔽するべきか? Vol.1


2011
04.19

さて、皆さんは Web App にどんな印象をお持ちだろうか?

平たく言えば Web ブラウザ単品で、ネイティブアプリみたいな事しちゃおうぜ!みたいなノリのアプリケーション(Web サイト)です、個人的にも今最も HOT で KOOL な技術と言う位置づけなので、会社のリソースを少し使わせて貰いながら開発を進めています。

実際にメスを入れてみると、当然の事ながら色々な問題や懸念点が出てきました。

なんのプラグインも使わずに Web ブラウザ単品でネイティブアプリに近いモノを動かす、と言う事は JavaScript に依存すると同義である事は議論の余地がありません。

しかしこの JavaScript と言うものはローカルサイドスクリプトと言われるだけあって、ユーザーの手元にあるマシン上で全ての処理を行います。とどの詰まり、ソースやら何やらが全てユーザーのローカルマシンにダウンロードされると言う事になります。

結果 Firebug 系のツールで挙動を見放題ッ!ソースそのものも保存可能ッ!!

いや、もうそれは仕方ない事だと思うのですが…サーバサイドスクリプトを普段から使っている我々からすると、何だか底知れぬ恐怖があります。

 

だってあんなトコやこんなトコも全部見られちゃうって事でしょ!?

 

オー、ジーザス。頭痛で頭が痛いです、これは。

と言う訳でちょっと抵抗してみる事にした。

 

前提条件

  • JavaScript のソース隠蔽を試みるよ
  • サーバサイドスクリプト使うよ(PHP)
  • 今回保護を試みるデバイスは iPhone だけだよ
  • iApp にも Firebug 的なアプリがあったらお手上げだよ

一言で言うと iPhone 専用のコンテンツを作って、とにかく Firebug 系のツールや単純ダウンロードから逃れてみよう!と言った感じです。

 

まず条件を整えてみる

どう言う状態になれば目標を達成出来るのか、まずはこれをリストアップしてみよう。

  1. 最強の脅威である PC の Web ブラウザ各種で見ているときはソースを出力しない
  2. 猪口才な UserAgent 偽装を見破り容赦なく例外処理を叩き込む
  3. 唯一の対象機が来た時のみ非同期にソースを出力する
  4. 隠蔽は解るけど開発効率もちゃんと考えた作りにする

こんな所だろうか、ざっと見た感じでは偽装さえ見破ればどうとでもなりそうですね。フローチャートはこんな感じで単純明快です。

 

フローチャート

 

ちなみに携帯ブラウザは無視しようと思う、奴は四天王の中でも最弱のうんたらかんたらだし、詳しく知らないけどきっと何も出来ないでしょう。大丈夫だ、問題無い。

と言う訳で次回は UserAgent の偽装について調べてみようと思う。

 

1 | 2 | 3 | 4