M.C.P.C.

―むり・くり―プラスコミュニケーション(更新終了)


| トップページ |

2012年3月16日 23:25

ムーバ停波を受けて、XHTMLでケータイ3キャリア別URLに振り分けるPerlのCGI

このエントリーをはてなブックマークに追加 mixiチェック

昨日作った

M.C.P.C.: ケータイ3キャリア別URLに振り分けるPerlのCGI

ですが、よくかんがえると今月末(2012年3月31日)でdocomoのムーバ(PDC)が停波になるのです。そうすると、別にCHTMLで作る必要はなくね? XHTMLで作ればよくね? となります。厳密にいえば、900i以前のモデル(東芝とかの4ケタ型番のやつとか)はXHTMLはだめらしいのですけれども、実質試験機みたいなものだったので(すこぶるでかい)、コンテンツが見れなくてもしゃーなしだと思います。

というわけで、3キャリア対応でXHTMLで表示URLを振り分けるPerl CGIを作りました。ポイントは、docomoのXHTMLの古い仕様で、外部CSSファイルは使えないという制約があるのですが、PerlのHTML::MobileJpCSSでdocomo端末の時だけインラインCSSに展開してしまう、ていうところです。これにより3社対応ページが共通のHTMLとCSSで作ることができるようになりました。

Filename: index.cgi

#!/usr/bin/perl
 
use strict;
use warnings;
use utf8;
use CGI;
use Encode;
use Encode::JP::Mobile qw(:props);
use File::Spec;
use FindBin::Real;
use HTML::Template;
use HTTP::MobileAgent;
use HTTP::MobileAgent::Plugin::Charset;
use HTML::MobileJpCSS;
 
my $basedir = FindBin::Real::Bin();
my $q = CGI->new();
my $agent = HTTP::MobileAgent->new;
my $inliner = HTML::MobileJpCSS->new( base_dir => "$basedir");
 
my $emoticons = {
 'E63E' => 'sun',
 'E63F' => 'cloud',
 'E640' => 'rain',
 'E641' => 'snow',
 'E642' => 'thunder',
 'E643' => 'typhoon',
 'E644' => 'mist',
 'E645' => 'sprinkle',
 'E646' => 'aries',
 'E647' => 'taurus',
 'E648' => 'gemini',
 'E649' => 'cancer',
 'E64A' => 'leo',
 'E64B' => 'virgo',
 'E64C' => 'libra',
 'E64D' => 'scorpius',
 'E64E' => 'sagittarius',
 'E64F' => 'capricornus',
 
 'E650' => 'aquarius',
 'E651' => 'pisces',
 'E652' => 'sports',
 'E653' => 'baseball',
 'E654' => 'golf',
 'E655' => 'tennis',
 'E656' => 'soccer',
 'E657' => 'ski',
 'E658' => 'basketball',
 'E659' => 'motorsports',
 'E65A' => 'pocketbell',
 'E65B' => 'train',
 'E65C' => 'subway',
 'E65D' => 'bullettrain',
 'E65E' => 'car',
 'E65F' => 'rvcar',
 
 'E660' => 'bus',
 'E661' => 'ship',
 'E662' => 'airplane',
 'E663' => 'house',
 'E664' => 'building',
 'E665' => 'postoffice',
 'E666' => 'hospital',
 'E667' => 'bank',
 'E668' => 'atm',
 'E669' => 'hotel',
 'E66A' => '24hours',
 'E66B' => 'gasstation',
 'E66C' => 'parking',
 'E66D' => 'signaler',
 'E66E' => 'toilet',
 'E66F' => 'restaurant',
 
 'E670' => 'cafe',
 'E671' => 'bar',
 'E672' => 'beer',
 'E673' => 'fastfood',
 'E674' => 'boutique',
 'E675' => 'hairsalon',
 'E676' => 'karaoke',
 'E677' => 'movie',
 'E678' => 'upwardright',
 'E679' => 'carouselpony',
 'E67A' => 'music',
 'E67B' => 'art',
 'E67C' => 'drama',
 'E67D' => 'event',
 'E67E' => 'ticket',
 'E67F' => 'smoking',
 
 'E680' => 'nosmoking',
 'E681' => 'camera',
 'E682' => 'bag',
 'E683' => 'book',
 'E684' => 'ribbon',
 'E685' => 'present',
 'E686' => 'birthday',
 'E687' => 'telephone',
 'E688' => 'mobilephone',
 'E689' => 'memo',
 'E68A' => 'tv',
 'E68B' => 'game',
 'E68C' => 'cd',
 'E68D' => 'heart',
 'E68E' => 'spade',
 'E68F' => 'diamond',
 
 'E690' => 'club',
 'E691' => 'eye',
 'E692' => 'ear',
 'E693' => 'rock',
 'E694' => 'scissors',
 'E695' => 'paper',
 'E696' => 'downwardright',
 'E697' => 'upwardleft',
 'E698' => 'foot',
 'E699' => 'shoe',
 'E69A' => 'eyeglass',
 'E69B' => 'wheelchair',
 'E69C' => 'newmoon',
 'E69D' => 'moon1',
 'E69E' => 'moon2',
 'E69F' => 'moon3',
 
 'E6A0' => 'fullmoon',
 'E6A1' => 'dog',
 'E6A2' => 'cat',
 'E6A3' => 'yacht',
 'E6A4' => 'xmas',
 'E6A5' => 'downwardleft',
 
 'E6AC' => 'slate',
 'E6AD' => 'pouch',
 'E6AE' => 'pen',
 
 'E6B1' => 'shadow',
 'E6B2' => 'chair',
 'E6B3' => 'night',
 
 'E6B7' => 'soon',
 'E6B8' => 'on',
 'E6B9' => 'end',
 'E6BA' => 'clock',
 
 'E6CE' => 'phoneto',
 'E6CF' => 'mailto',
 
 'E6D0' => 'faxto',
 'E6D1' => 'info01',
 'E6D2' => 'info02',
 'E6D3' => 'mail',
 'E6D4' => 'by-d',
 'E6D5' => 'd-point',
 'E6D6' => 'yen',
 'E6D7' => 'free',
 'E6D8' => 'id',
 'E6D9' => 'key',
 'E6DA' => 'enter',
 'E6DB' => 'clear',
 'E6DC' => 'search',
 'E6DD' => 'new',
 'E6DE' => 'flag',
 'E6DF' => 'freedial',
 
 'E6E0' => 'sharp',
 'E6E1' => 'mobaq',
 'E6E2' => 'one',
 'E6E3' => 'two',
 'E6E4' => 'three',
 'E6E5' => 'four',
 'E6E6' => 'five',
 'E6E7' => 'six',
 'E6E8' => 'seven',
 'E6E9' => 'eight',
 'E6EA' => 'nine',
 'E6EB' => 'zero',
 'E6EC' => 'heart01',
 'E6ED' => 'heart02',
 'E6EE' => 'heart03',
 'E6EF' => 'heart04',
 
 'E6F0' => 'happy01',
 'E6F1' => 'angry',
 'E6F2' => 'despair',
 'E6F3' => 'sad',
 'E6F4' => 'wobbly',
 'E6F5' => 'up',
 'E6F6' => 'note',
 'E6F7' => 'spa',
 'E6F8' => 'cute',
 'E6F9' => 'kissmark',
 'E6FA' => 'shine',
 'E6FB' => 'flair',
 'E6FC' => 'annoy',
 'E6FD' => 'punch',
 'E6FE' => 'bomb',
 'E6FF' => 'notes',
 
 'E700' => 'down',
 'E701' => 'sleepy',
 'E702' => 'sign01',
 'E703' => 'sign02',
 'E704' => 'sign03',
 'E705' => 'impact',
 'E706' => 'sweat01',
 'E707' => 'sweat02',
 'E708' => 'dash',
 'E709' => 'sign04',
 'E70A' => 'sign05',
 'E70B' => 'ok',
 'E70C' => 'appli01',
 'E70D' => 'appli02',
 'E70E' => 't-shirt',
 'E70F' => 'moneybag',
 
 'E710' => 'rouge',
 'E711' => 'denim',
 'E712' => 'snowboard',
 'E713' => 'bell',
 'E714' => 'door',
 'E715' => 'dollar',
 'E716' => 'pc',
 'E717' => 'loveletter',
 'E718' => 'wrench',
 'E719' => 'pencil',
 'E71A' => 'crown',
 'E71B' => 'ring',
 'E71C' => 'sandclock',
 'E71D' => 'bicycle',
 'E71E' => 'japanesetea',
 'E71F' => 'watch',
 
 'E720' => 'think',
 'E721' => 'confident',
 'E722' => 'coldsweats01',
 'E723' => 'coldsweats02',
 'E724' => 'pout',
 'E725' => 'gawk',
 'E726' => 'lovely',
 'E727' => 'good',
 'E728' => 'bleah',
 'E729' => 'wink',
 'E72A' => 'happy02',
 'E72B' => 'bearing',
 'E72C' => 'catface',
 'E72D' => 'crying',
 'E72E' => 'weep',
 'E72F' => 'ng',
 
 'E730' => 'clip',
 'E731' => 'copyright',
 'E732' => 'tm',
 'E733' => 'run',
 'E734' => 'secret',
 'E735' => 'recycle',
 'E736' => 'r-mark',
 'E737' => 'danger',
 'E738' => 'ban',
 'E739' => 'empty',
 'E73A' => 'pass',
 'E73B' => 'full',
 'E73C' => 'leftright',
 'E73D' => 'updown',
 'E73E' => 'school',
 'E73F' => 'wave',
 
 'E740' => 'fuji',
 'E741' => 'clover',
 'E742' => 'cherry',
 'E743' => 'tulip',
 'E744' => 'banana',
 'E745' => 'apple',
 'E746' => 'bud',
 'E747' => 'maple',
 'E748' => 'cherryblossom',
 'E749' => 'riceball',
 'E74A' => 'cake',
 'E74B' => 'bottle',
 'E74C' => 'noodle',
 'E74D' => 'bread',
 'E74E' => 'snail',
 'E74F' => 'chick',
 
 'E750' => 'penguin',
 'E751' => 'fish',
 'E752' => 'delicious',
 'E753' => 'smile',
 'E754' => 'horse',
 'E755' => 'pig',
 'E756' => 'wine',
 'E757' => 'shock',
};
 
# テンプレートファイル読み込み
my $template = sub {
  open my $fh, '<', shift or die $!;
  local $/ = undef; my $s = <$fh>;
  close $fh;
  return $s;
}->('index.tmpl');
$template = decode_utf8( $template );
$template =~s|\\x{(.+?)}|chr(hex($1))|eg; # 絵文字記述をUnicode文字列に
 
# キャリア別処理
my $params;  # TemplateにUserAgent(キャリア名)をまとめて渡す
my $carrier; # Templateに渡すキャリア名
if      ( $agent->is_docomo   ) { $carrier  = 'docomo';
} elsif ( $agent->is_ezweb    ) { $carrier  = 'AU';
} elsif ( $agent->is_vodafone ) { $carrier  = 'SoftBank';
} else {
  $carrier  = 'パソコン/スマートフォン';
  $params->{pc} = $carrier;
  $template =~ s{(\p{InMobileJPPictograms})}{
    my $char = Encode::JP::Mobile::Character->from_unicode(ord $1);
    sprintf '<img src="/emoticons/%s.gif" />', $emoticons->{$char->unicode_hex};
  }ge;
}
my $encoding = $agent->encoding; # Encode用のキャリアごとのエンコーディング
my $charset = $encoding =~ /sjis/ ? 'Shift_JIS' : 'UTF-8'; # HTML用のcharset
my $content = $encoding =~ /x-utf8-docomo/ ? 'application/xhtml+xml' : 'text/html';
 
$params->{ carrier} = $carrier; # <tmpl_var name="carrier">でdocomoとか表示できる
$params->{$carrier} = $carrier; # <tmpl_if name="docomo">でdocomo用処理振り分けできる
$params->{ charset} = $charset; # <meta~charset=<tmpl_var name="charset">" />
$params->{ content} = $content; # <meta~content="<tmpl_var name="content">" />
 
# テンプレート処理
my $t = HTML::Template->new(
  scalarref => \$template,
  die_on_bad_params => 0
);
$t->param( $params );
my $html = $t->output;
$html = $inliner->apply( $html ); # CSSをキャリアごとに適用するよう書き換え
 
# 出力
print $q->header( -type => $content, -charset => $charset );
print encode( $encoding, $html );
 
exit;
 
__END__

Filename: index.tmpl

<?xml version="1.0" encoding="<tmpl_var name="charset">"?>
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
  <head>
    <meta http-equiv="Content-Type" content="<tmpl_var name="content"
      >; charset=<tmpl_var name="charset">" />
    <title>エロいリンク</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes," />
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <div id="hd">
      <h1>エロいページ</h1>
      <h2>ケータイ版リンク集</h2>
    </div>
    <hr />
    <div>
      <dl>
        <dt>
          <span style="color: #0077ff;">\x{e6e2}</span
          ><a accesskey="1"
            href="<tmpl_if name="pc"
            >http://www.example.com/<tmpl_else><tmpl_if name="docomo"
            >http://www.example.com/i/</tmpl_if><tmpl_if name="au"
            >http://www.example.com/e/</tmpl_if><tmpl_if name="softbank"
            >http://www.example.com/j/</tmpl_if></tmpl_if
            >">お世話になったVHS</a>\x{E6DD}</dt>
        <dd>
          ツメオリのVHS情報がご覧になれます。
        </dd>
      </dl>
    </div>
    <hr />
    <div id="ft">
      <span>&copy;DTPWiki 2012</span>
    </div>
  </body>
</html>

Filename: styles.css

#ft {
  text-align: right;
  font-size: x-small;
  color: red;
}


どうでもいいけれども、ムーバ端末がネットから切り離されると、CHTMLを正確に展開できるのはiモードHTMLシミュレータだけになりそうですが、インターネット上にiモードHTMLブラウザでしか読めない新天地ができたりとか、iモードが絶滅した後の世界で刊行された小説に、「iモードブラウザで隠されたメッセージを探し出す」とかいうのがあったりすると胸アツなので、今のうちにiモードHTMLシミュレータをダウンロードしておくのはどうでしょうか。

投稿 大野 義貴 [XHTML/XHTML5] | |

トラックバック(0)

トラックバックURL: http://blog.dtpwiki.jp/MTOS/mt-tb.cgi/3893

コメントする