2010年6月23日水曜日

検索サイトのリンクの色の比較

最適 なテキストリンクの色は? | ウェブ力学に触発されて、大手検索エンジンの検索結果ページのリンクの色を調べてみた。


調査結果


GoogleYahoo! JAPANYahoo!Bing
a#1111CC#0000DE#0000DE#0033CC
a:visited#551A8B#941D55#551A8B#663399
a:active#CC1111#663399#0000DE指定なし
a:hover指定なし#CC3434指定なし指定なし

※Yahoo! JAPANのvisitedは、検索結果のリンクをクリックした後の色。再度検索すると、同じ検索結果でもvisitedにならない(また青色に戻る)。


所感
  • Yahooは本家と日本で違う。
  • hoverの指定をしないのが主流なのが意外だった。
  • activeも指定しない方向で?
  • Bingが一番すっきりしていて好き。



また、こんな調査結果もあった。
自分が調べたのとちょっと違う。検索サイトも細かい改良をし続けているということかな?

Google Appsのカレンダーを携帯で閲覧する方法

下記のようなURLにアクセスすると、携帯用のGoogleカレンダーを閲覧できる。

https://www.google.com/calendar/hosted/<Google Appsのドメイン>/m


このURLはPCからでも接続できる。
しかし携帯からアクセスすると、なぜかhttpになる。(httpsだとauでUTF-8が使えないから?)


ちなみに携帯で下記URLにアクセスすると、サーバ証明書が不正だといって接続を拒否された。
https://calendar.google.com/a/<Google Appsのドメイン>/m
このURLは昔使ってたみたいで、未だにGoogleの公式サイトを含めてこのURLが書いてあるところが多い。
PCでこのURLにアクセスすると、上のURLの方にリダイレクトされる。


また、携帯版のカレンダーでは見たい日付を指定できないので、遠い日付を見たい場合には「前」あるいは「次」リンクを連打する羽目になる。
Google Calendar Mobile Gatewayを使うしかないのか。

2010年6月15日火曜日

PHPの json_encode()で配列になるかハッシュになるか

json_encode()でPHPの配列をJSONにする場合に、PHPの配列の内容によってJSONの配列(Array)になるかハッシュ(JSONの場合KEYが文字列のプロパティの集合)になるかを調べてみた。


PHPの連想配列(KEYあり)の場合

$arr = array('foo' => 'a', 'bar' => 'b', 'baz' => 'c');
echo json_encode($arr);
// => {"foo":"a","bar":"b","baz":"c"}
→JSONのハッシュになった。


PHPの配列(KEY指定なし=ゼロから始まる連番)の場合
$arr = array('a', 'b', 'c');
echo json_encode($arr);
// => ["a","b","c"]
→JSONの配列になった。


PHPの配列を、json_encode()のオプション指定で強制的にハッシュにした場合
$arr = array('a', 'b', 'c');
echo json_encode($arr, JSON_FORCE_OBJECT);
// => {"0":"a","1":"b","2":"c"}
→JSONのハッシュになった。


PHPの連想配列で、一部だけKEY指定なしの場合
$arr = array('foo' => 'a', 'b', 'baz' => 'c');
echo json_encode($arr);
// => {"foo":"a","0":"b","baz":"c"}
→JSONのハッシュになった。


PHPの配列から最初の要素を消した場合
$arr = array('a', 'b', 'c');
unset($arr[0]);
echo json_encode($arr);
// => {"1":"b","2":"c"}
→JSONのハッシュになった。


PHPの配列から最初 途中の要素を消した場合
$arr = array('a', 'b', 'c');
unset($arr[1]);
echo json_encode($arr);
// => {"0":"a","2":"c"}
→JSONのハッシュになった。


PHPの配列から最後の要素を消した場合
$arr = array('a', 'b', 'c');
unset($arr[2]);
echo json_encode($arr);
// => ["a","b"]
→JSONの配列になった!


PHPの連想配列でKEYをゼロから始まる連番で指定した場合
$arr = array(0 => 'a', 1 => 'b', 2 => 'c');
echo json_encode($arr);
// => ["a","b","c"]
→JSONの配列になった。


PHPの連想配列でKEYを数値だけど連番じゃないものにした場合
$arr = array(0 => 'a', 1 => 'b', 4 => 'c');
echo json_encode($arr);
// => {"0":"a","1":"b","4":"c"}
→JSONのハッシュになった。



結論
json_encode()により配列(Array)になるのは、PHPの(連想)配列のKEYがゼロから始まる連番の場合のみ

Google AJAX Libraries APIのブラウザキャッシュ期間

Google AJAX Libraries APIではバージョンの指定の際にマイナーバージョンやリビジョンを省略できる。

例えばYahoo! User Interface Libraryには2.8.1というバージョンがあるので、下記のようにバージョンを指定できる。

  • 2 → バージョン2系の中の最新版をロードする
  • 2.8 → バージョン2.8系の中の最新版をロードする
  • 2.8.1 → バージョン2.8.1系の中の最新版をロードする


で、それぞれの場合のHTTP Headerによるキャッシュ制御を調べてみる。
yuiloader-min.jsを静的に読み込んだ場合で調べてみた。

指定方法max-ageExpiresEtag
メジャーバージョン(2)1時間1時間後なし
マイナーバージョン(2.8)1時間1時間後なし
リビジョン(2.8.1)1年1年後なし

YUIは「2.8.1.1」のような2.8.1系の新しいバージョンが出ることはない(※)ので、リビジョンまで指定した場合はキャッシュ期間を1年にしている。
それ以外は1時間。ちょっと短いせめて1日くらいでも良さそうな気がするが。

※これまでのバージョンの付け方を見る限りはない。もしあったとしたら2.8.1-1のようにドット以外で繋ぐことにより回避するかもね。

PHPで ob_start()後に exitするとどうなるか

PHPでob_start()でコールバック関数を指定した場合、スクリプトを終了した後にコールバック関数が呼ばれる。

ではスクリプトの途中でexitしたらどうなるかというと、exit後にコールバック関数が呼ばれた。

<?php
function callback($buf) {
    return $buf . ' callback'; //呼ばれる
}

ob_start('callback');

echo 'foo';

exit;

echo 'bar'; //呼ばれない

// => foo callback


コールバック関数を指定せずに、exit後にob_get_clean()等でバッファを処理しようとした場合は、(当然ながら)exit後の処理は実行されない。
<?php
ob_start();

echo 'foo';

exit;

echo ob_get_clean();

echo 'bar'; //呼ばれない

// => foo

2010年6月14日月曜日

PHPを mod_cache (mod_disk_cache)でキャッシュする

Apacheのmod_cacheとmod_disk_cacheを使って、PHPで生成したHTMLをキャッシュする方法のメモ。


Apacheの設定では、LoadModuleでmod_cacheとmod_disk_cacheを有効にする。
そして下記のようにキャッシュの設定をする。

CacheRoot /path/to/cache/dir
#キャッシュ方法と、キャッシュを有効にするURLの先頭部分
CacheEnable disk /test
#上記URLのうち、キャッシュを無効にするURL
CacheDisable /test/not_cache
CacheDirLevels 4
CacheDirLength 5
#クライアントの挙動に関わらずキャッシュを有効にする
CacheIgnoreCacheControl On


PHP側では下記のようにHTTP Response HeaderのLast-ModifiedとExpiresをセットする。(max-ageもセットした方がよい?)
$now = time();
$maxAge = 60;
header('Last-Modified: ' . gmdate('D, d M Y H:i:s T', $now));
header('Expires: ' . gmdate('D, d M Y H:i:s T', $now + $maxAge));
//header("Cache-Control: max-age=$maxAge");

これで60秒間、サーバサイドでもキャッシュされる。
同一クライアントからのアクセスなら、60秒間はクライアントキャッシュが有効。それでもGETしようとしてきた場合(Firefoxで更新ボタンをクリックした場合等)はmod_cacheが304を返してくれる。



PHPでHTTP Response Headerを指定しない場合は、Apacheのキャッシュ設定に下記を追加する。
CacheIgnoreNoLastMod On
CacheDefaultExpire 86400
#キャッシュから1秒以上過ぎたら1日キャッシュを有効にする場合はこんな値で
CacheLastModifiedFactor 86400
CacheMaxExpire 86400

これでHTTP Response Headerを指定しない場合でもサーバサイドのキャッシュが有効になったが、クライアントキャッシュは有効にならないのが残念。
気を利かせて適切なHTTP Response Headerをセットしてくれればいいのに。



キャッシュファイルは定期的にhtcachecleanで掃除する。
(空のディレクトリがうまく削除されない?)



参考

システム開発で使うオンラインの日本語マニュアル



意外とマニュアル内検索が無かったり、あっても検索しづらかったりすることが少なくない。
また、普通にGoogle検索から探そうとすると古いマニュアルばかりヒットすることも(Postgresとか)。
素直に英語のマニュアルで調べればいいんだろうけど...

Google Reader plus Hatenaで「リスト表示」でもコメントを表示する方法

Firefox用GreasemonkeyのGoogle Reader plus Hatenaは、Googleリーダーに はてなブックマークのブックマーク数やリンクが付けてくれる便利なスクリプト。
Googleリーダーでの表示方法が「全文表示」の場合は、はてなブックマークのコメントを取得して記事の下に表示するという機能もある。
しかし、表示方法が「リスト表示」の場合は、このコメント表示機能が動かない。

下記に「リスト表示」でも動かす方法が書いてあったが、自分の環境ではこの方法では動かなかった。(GoogleリーダーのHTML構成が変わった?)
googleリーダー内ではてなブックマークのコメントを参照したいです。 Google Reader plus Hatenaというグリモン... - 人力検索はてな


そこで、自分の環境で「リスト表示」でも はてなブックマークを表示する方法のメモ。

  • 172行目を下記のように変更

    //var entryURL = findNode( eventTarget, 'ancestor::div[@class=...

    var entryURL = findNode( eventTarget, 'ancestor::div[@id="current-entry"] //a[@class="entry-title-link"]/@href' ) ;
  • 200行目を下記のように変更

    //eval("(" + x.responseText + ")");

    eval(x.responseText);


全文表示では動かなくなるかもしれないが、リスト表示しか使わないのでこれでいいや。

2010年6月10日木曜日

Zend Frameworkと PEARの命名規約に相違点

Zend Frameworkの命名規約とPEARの命名規約。両方ともJavaの命名規約を元にしていると思われる。変数でアンダーバーを使わないところとか。($foo_barではなく$fooBarとキャメルケースにする。)

Zend FrameworkとPEARの命名規約はかなり似てるが、細部まで見ると少し違う。
相違点を洗い出してみた。


Zend Framework
PEAR
アルファベットの略語先頭だけ大文字にする
例:Zend_Pdf
略語全体を大文字にする
例:HTML_Upload_Error
抽象クラスクラス名の後ろに"Abstract"を付ける
例:FooAbstract
言及なし
インターフェイスクラス名の後ろに"Interface"を付ける
例:FooInterface
言及なし
protectedアンダーバーで始める
例:$_foo
アンダーバーで始めない
例:$foo


Zend Frameworkの方がいいと思う。


参考:
Zend Framework: Documentation: 命名規約 - Zend Framework Manual
Manual :: 命名規約 (← PEAR)

PHPの DateIntervalクラスで経過日数を調べる場合の注意点

PHP5.3で新しく追加されたDateIntervalクラス。
一見便利そうだが、DateTimeクラスやstrToTime()のように日付等の繰り上がりを計算してくれないので注意が必要。
しかも、オブジェクトの生成方法により内部的なデータの持ち方が違う。


DateTimeクラスのdiff()(またはdate_diff())でDateIntervalオブジェクトを生成した場合、1ヶ月以上の日数は「月」に繰り上がる。
総日数は format('%a') で得られる。

$d1 = new DateTime('2010-01-01 01:01');
$d2 = new DateTime('2010-02-02 02:02');
$interval = $d2->diff($d1);

echo $interval->format('%m') . 'ヶ月と' . $interval->format('%d') . '日<br />';
// => 1ヶ月と1日

echo '全部で' . $interval->format('%a') . '日';
// => 全部で32日


でもDateIntervalクラスのコンストラクタで「1ヶ月と1日」としてDateIntervalオブジェクトを生成した場合、総日数は format('%d') でも format('%a') でも得られない。
$interval = new DateInterval('P1M1D');

echo $interval->format('%m') . 'ヶ月と' . $interval->format('%d') . '日<br />';
// => 1ヶ月と1日

echo '全部で' . $interval->format('%a') . '日';
// => 全部で0日


DateIntervalクラスのコンストラクタで「32日」としてDateIntervalオブジェクトを生成した場合、総日数は format('%d') で得られる。format('%a') は使えない。
$interval = new DateInterval('P32D');

echo $interval->format('%m') . 'ヶ月と' . $interval->format('%d') . '日<br />';
// => 0ヶ月と32日

echo '全部で' . $interval->format('%a') . '日';
// => 全部で0日


format()する際には、DateIntervalオブジェクトをどうやって作ったかを意識する必要がある。

DateInterval::format()のマニュアルにも書いてあるとおり、これは仕様なのだろう。(月により1ヶ月の日数が違うため、コンストラクタでnヶ月と指定された場合にその総日数は不定のため。)

DNS Rebinding(リバインディング)についての調査メモ

DNS Rebindingは質(たち)が悪いらしい

【White Hat Security調査】2010年に最も警戒すべき脅威は「DNSリバインディング」 : セキュリティ・マネジメント - Computerworld.jp
(補足)はてなブックマーク - ockeghemのブックマーク - 2010年3月19日



DNS Rebindingについてのわかり易い説明

DNS Rebinding | 鳩丸ぐろっさり (用語集)



DNS Rebindingを悪用する具体例

セキュリティ情報 - iモードIDを用いた「かんたんログイン」のDNS Rebinding脆弱性
ケータイtwitter(twtr.jp)においてDNS Rebinding攻撃に対する脆弱性を発見・通報し、即座に修正された - 徳丸浩の日記

これらの例ではLANではなく、携帯の「かんたんログイン」との合わせ技により脆弱性を突いている。



簡易テスト

「かんたんログイン」DNSリバインディング耐性のチェック方法 - 自分でできる - HASHコンサルティング徳丸浩の日記



サーバ側での対策




参考
untitled - Powered by Google ドキュメント

2010年6月7日月曜日

PHPの バージョン5.xで追加された便利なクラス

PHPの5.xで組み込みオブジェクトとして提供される便利なクラス。
たまに古いPHPを使うときに、どのバージョンで何を使えるか/使えないか分からなくなるのでメモ。

バージョン追加された便利なクラス
PHP 5.0.1SimpleXML
PHP 5.1.0PDO
PHP 5.2.0DateTime, ZipArchive, JSON関数(※)

※JSON関数はクラスではないけど



PHP5.3では下記のクラスが便利そうだけど、まだきちんと使ったことはない
  • DateInterval (DateTimeの加減算等に使える)
  • DatePeriod (日時を指定した範囲でループできる)
    • 例1:7/1から7/7までの日付を出力

      $dp = new DatePeriod(new DateTime('2010-07-01'), new DateInterval('P1D'), 6);

      foreach ($dp as $dt) {
          echo $dt->format('Y/m/d') . '<br />';
      }
    • 例2:同じく、7/1から7/7までの日付を出力

      $dp = new DatePeriod(
          new DateTime('2010-07-01'),
          new DateInterval('P1D'),
          new DateTime('2010-07-08')
      );

      foreach ($dp as $dt) {
          echo $dt->format('Y/m/d') . '<br />';
      }
  • FilesystemIterator (指定したディレクトリにあるファイルをループ)



PHP5.2.0、5.3.0で追加されたクラスは、PHPマニュアルにまとめページがある。

CSSによる背景色グラデーションのブラウザごとの書き方

例えば、上から下に白から青のグラデーションを表示したい場合はこう書く。(省略可能なパラメータは省略した。)

/* IE */
filter: progid:DXImageTransform.Microsoft.Gradient(StartColorStr=#ffffffff, EndColorStr=#ff0000ff);

/* IE8 */
-ms-filter: "progid:DXImageTransform.Microsoft.Gradient(StartColorStr=#ffffffff, EndColorStr=#ff0000ff)";

/* Firefox */
background: -moz-linear-gradient(white, blue);

/* Chrome, Safari */
background: -webkit-gradient(linear, left top, left bottom, from(white), to(blue));

IE8は右辺をクォートで囲う必要があるので注意。

IE以外は、詳細な指定をすれば複数の濃淡を指定できたり球状の効果を表現できたりと色々できる。

Operaは未対応らしい。


参考
IE:Gradient - filter,フィルタ
Firefox:-moz-linear-gradient - MDC
Chrome, Safari:CSSでグラデーションを表現する - builder by ZDNet Japan

Googleドキュメントで他のユーザーを招待する場合のセキュリティ

Googleドキュメント(Google Docs)で他のユーザーを招待すると、招待用のURLが記載されたメールが送られる。
実はこのURLにアクセスすると、招待されたユーザー以外でもそのページにアクセスすることができる

この件については下記が詳しい。

高木浩光@自宅の日記 - Googleドキュメントの「招待メール」の危険

上記記事が書かれた時からの変更点として、現在は招待用URLからGoogleドキュメントにアクセスする前にGoogleアカウントでのログインが求められるため、Googleアカウントを持っていないユーザーはアクセスできなくなった。

しかし、招待用URLさえ分かれば、Googleアカウントを持っているユーザーなら誰でもアクセスできてしまうことに変わりはない。

(参考:そのドキュメントに誰も招待していなければ、招待用URL自体が作成されないので他のユーザーはアクセスできない。)



以上がデフォルト設定の場合の話。

Googleドキュメントではオプション設定により、アクセスできるユーザーを招待した人だけに限定することができる。

共有ボタンから「他の人と共有」ダイアログを表示させて、下記のように「権限オプション」タブを見ると、「招待状の転送を許可する」というチェックボックスがある。



デフォルトではチェックが付いているので、転送してもらった人でもアクセス可能、つまりURLさえ分かればアクセス可能になる。
このチェックを外して保存すれば、アクセスできるのは招待されたユーザーのみになる



この設定はなかなか分かりにくいので、Googleさんは「許可しない」をデフォルトにした方がいいと思う。あるいは、ユーザーごとの設定でデフォルトを決められるようにするか。

ブログ アーカイブ

tags