ページ更新: 2005-01-29 (土) (5165日前)

(2001.09.14 作成)

User-Agentでフレームの有無を切り替える

User-Agentの種類に応じて、フレームの有無を切り替えます。

目的は、

  • NejiFactory のChibiboardを使いたいが、MS-IE 以外で見たときにマトモに表示されないのはイヤなので、User-Agentに応じて Chibiboard あり(=フレームあり)/なしを切り替えようと思った。
  • でも、discypus.jp へのアクセスの大多数は サーチエンジンやリンクから。そういったアクセスでも Chibiboardを表示したい。

環境は Apache 1.3.19 + Debian GNU/Linux Woody kernel 2.2.19 です。

[編集]

2001.09.19補足 #

自分のサイトでフレーム使った場合、外部リンクをクリックしたときはフレームを解除したい。

でも、既存のリンクはともかく、今後の外部リンクにいちいちtargetを追加するのはイヤなので、中止。今回の話題はお題を「User-Agentでページを切り替える」にでも変更しようかと。

[編集]

情報源 #

Apache-Tech ML の[Apache-Tech 110] about a USER_AGENT からのスレッド

[編集]

実現方法 #

[編集]

DirectoryIndex と ExecCGI と ScriptHandler を使う #

まず最初に思いつくのがコレか?

DirectoryIndex に index.cgi を追加、さらに ExecCGIと ScriptHandler も追加、 index.cgi で HTTP_USER_AGENT に応じて Location で frame.html / index.shtml を切り替える

毎回cgiを起動すると結構重そう……とはいえ、どうせChibiboardを起動するわけだし。mod_perl 併用するかぁ?

[編集]

mod_docroot を使う #

[Apache-Tech 110] about a USER_AGENT からのスレッドから。

今回の用途ではこのセンはなしですが、他のことに役に立つ(iモードなどのアクセスでページを切り替える)ので、試してみました。mod_docroot.c とそのパッチを手動で当ててから、

$ apxs -c mod_docroot.c モジュールのコンパイル
# apcs -i mod_docroot.so モジュールのインストール
# apachectl configtest
# /etc/init.d/apache reload
# tail /var/log/apache/error.log
[編集]

mod_doc パッチを使う #

[Apache-Tech 110] about a USER_AGENT からのスレッドから。

こいつも今回の用途にはちょっと向かないかも。途中までやってみて、面白かったですが。

# apt-get source apache Apacheのソースコードを入手
$ patch < mod_dir.patch mod_dirのパッチを当てて、
$ apxs -c mod_dir.c コンパイルして、
# apxs -i mod_dir.so インストールする。

httpd.conf に追加

EnvDocumentRoot .*MSIE.* frame.html

これで、MSIEからのアクセスで、 http://.*/ のみ、frame.html が表示された。

ただし、http://.*/index.shtml へのアクセスは従来通りであるので、今回の目的にはちと。

[編集]

mod_rewrite とか BrowserMatch ディレクティブとか、SetEnvIf ディレクティブとか。 #

いけると思う。でも、rewriteと格闘するのは久しぶりだし……。

Rewrite + sbox で suexec もどきをやったときも結構苦労したし(ミスると全部のコンテンツが見えなくなる)。sboxの改造にちと時間がかかったせいでもあるが。

[編集]

mod_layout を使う #

無料ホームページの広告の自動挿入と同じ……だと思う。

それに User-Agent 判別を付けてしまう。

mod_layoutを改造するか、mod_rewrite / BrowserMatch ディレクティブと併用か?

[編集]

Chibiboard を改造して、SSIにしてしまう #

フレームを使わずに、SSIにして、ブラウザを判別して、Chibiboard自体の出力を切り替えてしまう。

問題は、Chibiboardのバージョンアップに追従するのが面倒だということ、そして画面をスクロールしないとChibiboardが見えないということ(Chibiboardのメリットがなくなる)

[編集]

Chibiboard の出力を受け取って、SSIとして出力する #

(2001.09.19追加)

フレームを使わずに、SSIにして、ブラウザを判別して、Chibiboardの出力を修正する。

具体的には、<html></html>と <style>以外の <head>〜</head> の内容の削除、<body>タグを他のタグへ書き換え、漢字コード変換(必要なら)を行えばよいだろう……たぶん。

問題は、画面をスクロールしないとChibiboardが見えないということ。

[編集]

Chibiboard でブラウザを判別して、MS-IE以外の時は飛ばす #

chibiboard.cgi にフレームなしのURLを渡して、chibiboard.cgi でUser-Agentを判別して、MS-IE以外の時はフレームなしのURLに飛ばしてしまう。

改造個所も少なそうだ。chibiboard.cgi の先頭でパラメータ取得→User-Agent解析→Refresh出力。

[編集]

ブラウザ判別SSI作って、MS-IEのときだけフレームありのページに飛ばす #

HEAD>〜</HEAD> にブラウザ判別SSI入れて、MS-IEの時だけフレームありのページに Refreshで飛ばす。

index.cgiの変形なので、mod_perl併用したほうがいいなあ……各ページにcount.cgi入ってるからいまさら、だけど。

あと、コレ使うときは index.shtml を別の名前でもう1個用意しなきゃループするのが問題。あるいはJavaScript併用で判別させるか……メリットがないなあ。

#!/usr/bin/perl

use strict;

# Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)
# AGENT = MSIE
# VERSION >= 4.0

    print "Content-type: plain/text\n\n";

    if( $ENV{'HTTP_USER_AGENT'} =~ /MSIE ([\d.]+)/ ) {
        if( $1 >= 4.0 ) {
            # frame
            print "<META http-equiv=\"refresh\" content=\"0:url=frame.html\">\n";
        } else {
            # no-frame
            print '\n';
        }
    } else {
        # no-frame
        print '\n';
    }
[編集]

JavaScriptでフレームの有無を切り替える #

最初に考えたのがこれ。JavaScriptは不得手なのだが……。

<SCRIPT language="JavaScript">
<!--
  var ie = (navigator.appName.indexOf("Microsoft") >= 0); // MSIEで
  var vr = (navigator.appVersion.charAt(0) >= 4);         // Mozilla 4以上で、
  var fl = (top.frames.length == 0);                      // フレームがない場合、
  if (ie && vr && fl) {
   location.replace("index_f.html");  // フレームのページに飛ぶ
  }
//-->
</SCRIPT>