#! /usr/bin/perl # # mobile.cgi --- HTML2MOBILE lite # 〜ONC以外は実機で確認していません(^_^;)〜 # # by typea # # 改造、再配布など煮るなり焼くなり好きにしてください。 # # ChangeLog: # 0.1 2000/04/25 typea first release # 0.2 2000/05/05 typea 丸文字対応 # 0.3 2000/05/05 typea 文字コード変換, Table対応強化(ホンの少し) # 0.4 2000/05/18 typea URLエンコードのバグつぶし # 0.5 2000/05/19 typea imode,EZweb対応?に伴い名称変更。 # 0.6 2000/05/25 typea ロジック変更。 # 0.61 2000/05/25 typea $omax値変更。 Thanks NJさん # 0.62 2000/05/26 typea 可変$imax。 Thanks yar-3 # 0.7 2000/06/01 typea WAPの表示強化。 # 0.8 2000/06/20 typea URL解釈の表示強化。 # 0.9 2000/07/21 typea タグ解析を2重化(TAG分割の前処理追加)。 # 0.91 2000/08/04 typea tagで分割前の処理(pre_conv)の処理の強化。 # FROMをカットするパラメーターを追加。 # # Length処理について # 一応、こんなことを考えつつええかげんにやってます。 # CHTML : HTMLベースなのでタグの途中でもスパっとカット(問題ありです) # WAP : タグをほとんど使っていないので文章の適当なとこでカット。 # ONC : 同上 # Lengthの設定値をオーバーした段階でページを分けるので、 # $*maxの初期値は若干控えめにしてください。 # # -------------------------------------------------------- # おのひろき onohiroki@cup.com # mobile.cgi HTML2MOBILE lite は typea さんによります. # typea さんのページ http://www.digimaga.com/typea/h2m.html # おのひろきがテキトウに書き換えました.typea さんの 0.91 との # 違いは,0.91 を実際に入手して比べてください. # 改造、再配布などについての条件は,typea さんに準じることにします. # 2002.1.23 # # ChangeLog: # 0.91-o1 2000 おのひろき アンカーの問題を回避 # 0.91-o2 2001/01/24 おのひろき J-Sky 対応 # 0.91-o3 2001/01/24 おのひろき dot-i 対応 # 0.91-o4 2001/12/17 おのひろき iモード google 対応 # 0.91-o5 2001/12/17 おのひろき UA 名に動作モードを付加 # 0.91-o6 2002/01/23 おのひろき 公開用サブセット # 0.91-o6 2002/01/30 おのひろき 間違い 修正 # #  おのひろきのバージョンのページ http://onohiroki.cycling.jp/comp-h2m.html # -------------------------------------------------------- ###### 各種設定 ###### # HTML2MOBILEで変換したいページのURL。 # ONC,EZwebの場合はこれ以下のディレクトリはリンクする。 #$top_url = 'http://tomo.spage.org/'; $top_url = 'http://onohiroki.cycling.jp/index3.html'; # このプログラムはGWとして動作しないため、imodeの場合を除き他サイトへのリンクはしません。 # このプログラムのURL。 #$cgi_url = 'http://tomo.spage.org/cgi-bin/mobile.cgi'; $cgi_url = 'http://onohiroki.cycling.jp/m/o-mobile.cgi'; # 各ケータイ向けトップページのURL。 # (未記入の場合は、$cgi-urlを使用します。) $i_url = ''; $ez_url = ''; $onc_url = ''; $j_url = ''; $doti_url = ''; # jcode.plの使用。1:使用、0:未使用 $use_jcode = 1; # ホームページをEUCコードで作られている場合には、1にしてください。 # デフォルト表示(IE,NN等でアクセスした場合) # 1:imode 2:WAP 3:ONC 4:J-sky 5:Dot-i $mode = 1; # フォームのカット(フォームを表示させたくない場合は1) $form_cut = 1; # ページを区切る文字数の目安。 #$imax = 1900; #? 502の場合は自動で拡張します。 $imax = 1700; #$wmax = 1300; $wmax = 600; #$omax = 4800; $omax = 4500; $amax = 7000; ###### ここからプログラム ###### use Socket; if($use_jcode){ require 'jcode.pl'; } &read_form; # $top_urlからトップのディレクトリを取得 $top_dir = substr($top_url, 0, rindex($top_url, '/')+1); &parse_url; # ブラウザ判定 $ua = $ENV{'HTTP_USER_AGENT'}; if($FORM{'ua'}){ # debug $mode = $FORM{'ua'}; } if($FORM{'c'}){ # debug $imax = $wmax = $omax = $amax = $FORM{'c'} * 1000 - 100 ; } if($ua =~ /DoCoMo\//) { # imode $mode = 1; if($ua =~ /502i\//) { $imax = 4000; } #catch 5K if($ua =~ /\/c(\d+)$/) { $imax = $1 * 1000 - 900 ; } #catch拡張 } if($ua =~ /UP\.Browser\//) { $mode = 2; } # WAP if($ua =~ /PDXGW\//) { $mode = 3; } # ONC if($ua =~ /J-PHONE\//) { $mode = 4; } # J-Sky if($ua =~ /ASTEL\//) { # dot-i $mode = 5; $imax = $amax; } # いろいろ初期化 $data = ''; $page = 0; $p = 0; $page = $FORM{'P'} if $FORM{'P'}; # ページを取得 &get_html_text ($open_file); # タグに分割する前にある程度処理 &pre_conv; # タグに分割 &conv_tag ($intext); if($mode == 1){ $i_url = $cgi_url if ( !$i_url ); &conv_imode; &print_imode; exit; }elsif($mode == 2){ $ez_url = $cgi_url if ( !$ez_url ); &conv_wap; &print_wap; exit; }elsif($mode == 3){ $onc_url = $cgi_url if ( !$onc_url ); $cgi_url = substr($cgi_url, 5); # 文字数短縮(http:のカット) &conv_onc; &print_onc; exit; }elsif($mode == 4){ $j_url = $cgi_url if ( !$j_url ); &conv_imode; #imode とおなじ &print_jsky; exit; }elsif($mode == 5){ $doti_url = $cgi_url if ( !$doti_url ); &conv_imode; #imode とおなじ &print_doti; exit; }else{ &print_error( 'ブラウザー判定に失敗しました。' ); } ###### サブルーチン ###### # form解析 sub read_form{ $form = $ENV{ 'QUERY_STRING' }; @group = split(/&/, $form); foreach $ans (@group){($name, $value) = split(/=/, $ans); $value =~ tr/+/ /; $FORM{$name} = $value; } } # URL解析 # $FORM{'U'}の形式 # $FORM{'U'} = 'sample/test.html'; # 常に$top_urlからの相対パス。 sub parse_url{ if($FORM{'U'}){ $FORM{'U'} =~ s/%(..)/pack("c", hex($1))/ge; $open_file = $top_dir.$FORM{'U'}; }else{ $open_file = $top_url; } $open_dir = substr($open_file, 0, rindex($open_file, '/')+1); } # tagで分割前の処理 sub pre_conv { $intext =~ s/\r\n|\r|\n/ /g; # 改行コード除去 if( $intext =~ s/]*>(.*?)<\/TITLE>//i ){ # title $title = $1; $title =~ s/ +/ /g; # titleの複数空白は1つに } $intext =~ s/]*>.*?<\/HEAD>//gi; #…の除去 $intext =~ s/]*>.*?<\/SCRIPT>//gi; #の除去 $intext =~ s///g; #コメント削除 if($form_cut){ $intext =~ s/]*>.*?<\/FORM>//gi; #
の除去 } $intext =~ s/]*ALT[^"]*"([^"]+)"[^>]*>/[$1]/gi; # IMGタグ(ALT指定付き) $intext =~ s/]*>/[IMG]/gi; # IMGタグ(ALT指定無し) #
に置換したいタグの処理 $intext =~ s/]*>/
/gi; $intext =~ s/<(TABLE|\/TABLE)[^>]*>/
/gi; $intext =~ s/]*>|>)/
/gi; $intext =~ s/]*>|>)/
/gi; $intext =~ s/<\/P>/
/gi; $intext =~ s/<(H|\/H)[1-6](\s[^>]*>|>)/
/gi; # 複数
処理 # $intext =~ s/

(
)+/

/gi; $intext =~ s/(\t| )/ /g; # タブと全角スペースは、半角スペースに $intext =~ s/ / /g; # 整形のためのスペースを変換 $intext =~ s/ +/ /g; # 行中の複数空白は1つに $intext =~ s/> + $imax && !$dont_cut){ &make_cdata; } $_ = $tag[$j++]; if( /^[^<]/ ){ $data .= "$_\n"; next; } # if( /^); # }else{ # # http:// or ローカルファイル # $url = &make_query($url, $open_dir); # $data .= qq(\n); # } # next; # } # おのひろき リンク関係改変 ここから if( /^); $dont_cut = 1; }elsif($url =~ /google\.co/ || $url =~ /mb\.mm\-b\.net/ || $url=~/sjk\.co\.jp/ || $url =~ /tosp\.co\.jp/ ){ # google など iモード対応サイトの処理 hiroki $data .= qq(\n); $dont_cut = 1; }elsif( $url =~ /^[a-z]+:/ && $url !~ /^$top_dir/ ) { # 自分とこ以外のリンク $googleurl = $url; $googleurl =~ s/http\:\/\///; $googleurl =~ s/\//\@2F/g; $googleurl =~ s/\?/\@3F/g; $googleurl =~ s/\+/\@2B/g; $data .= qq(\n\(\) ); $dont_cut = 1; # }elsif(($url !~ /\.htm/ && $url !~ /\.txt/) && $url !~ /\.cgi/){ # # HTML, TEXT, CGI 以外のリンク # ; }elsif($url =~ /#/ && $url !~ /\.htm/){ # アンカーは無視 hiroki ; }elsif($url !~ /\./ && $url !~ /\//){ # アンカーは無視 hiroki ; }elsif($url =~ /\.JPG/i || $url =~ /\.GIF/i || $url =~ /\.PNG/i){ # 画像は無視 hiroki ; }else{ # http:// or ローカルファイル $url = &make_query($url, $open_dir); $data .= qq(\n); $dont_cut = 1; } next; } # おのひろき リンク関係改変 ここまで if( /^
/i ) { $data .= "
"; next; } # if( /^<\/A/i ){ # $dont_cut = 0; # $data .= '
'; # next; # } #おのひろき 改変 if( /^<\/A/i && $dont_cut) { $data .= ""; $dont_cut = 0; next; } #ここまで if( /^
)/i ) { $data .= "
  • "; next; } if( /^
      +
      (
      )+/

      /g; $data =~ s/^(
      )+//g; $out[$p] = $data; $p++; $data = ''; } # WAP用にタグをカット sub conv_wap { $j = 0; $body_flag = 0; while ($tag[$j]) { if(length($data) > $wmax && !$dont_cut){ &make_wdata; } $_ = $tag[$j++]; if( /^[^<]/ ){ $data .= $_; next; } # if( /^); # $dont_cut = 1; # } # next; # } # おのひろき 改変 if( /^); $dont_cut = 1; } next; } #ここまで if( /^<\/A/i && $dont_cut) { $data .= ""; $dont_cut = 0; next; } if( /^
      /i ) || ( /^<(DIV|\/DIV)/i ) || ( /^<\/TD/i ) || ( /^<(LI|DT)/i )) { $data .= "
      \n"; next; } next; } &make_wdata; } # 整形 sub make_wdata{ $data =~ s/ \n/\n/g; # 行末空白除去 $data =~ s/\n /\n/g; # 行頭空白除去 $data =~ s/\n\n+/\n/g; # 複数改行は1つに #$data =~ s/ +/ /g; # 行中の複数空白は1つに $data =~ s/
      \n
      (\n
      )+/
      \n
      /g; $out[$p] = $data; $p++; $data = ''; } # onc用にタグをカット sub conv_onc { # 初期化 $j = 0; $data = ''; # outputデータ格納 $i = 0; # 丸文字用 $data_sel = ''; # SELデータ格納 while ($tag[$j]) { if(length($data)+($i * 100) > $omax && !$dont_cut){ # 文字数が、$omaxを超えたらページを生成。 # 100(SELの文字数)はええかげん &make_onc_output; # 初期化 $data = ''; # outputデータ格納 $i = 0; # 丸文字用 $data_sel = ''; # SELデータ格納 } $_ = $tag[$j++]; if( /^[^<]/ ){ $data .= $_; next; } # if( /^)/i ) { $dont_cut = 0; next; } if( /^
      /i ) || ( /^<(DIV|\/DIV)/i ) || ( /^<\/TD/i ) ) { $data .= "\n"; next; } } &make_onc_output; } # 整形 # 1ページ目は$p=1としてメモリに保存。 # 文字数がオーバーしそうになると呼び出されて、ページ(ボディー部分)を作成。 sub make_onc_output { $data =~ s/<//g; $data =~ s//>>/g; $data =~ s/"/"/g; $data =~ s/\n /\n/g; # 改頭のスペース除去 $data =~ s/ \n/\n/g; # 改末のスペース除去 $data =~ s/\n\n+/\n\n/g; # 複数改行は1つに $sel[$p] = $data_sel; $out[$p] = $data; $num[$p] = $i; $p++; } # 出力 iモード sub print_imode { print qq(Content-Type: text/html; charset=Shift_JIS\n); # おのひろき拡張 print qq(Content-Language: ja\n); # print qq(ROBOTS: NOINDEX,NOFOLLOW\n); # print qq(Pragma: no-cache\n); # print qq(Cache-Control: no-cache\n\n); print qq(\n); # print qq(\n); print "$title\n\n"; print $out[$page]; print qq(
      1\) Top\n); if($page > 0){ $prev = $FORM{'P'} - 1; if ($FORM{'U'}){ print qq(0\) Prev\n); }else{ print qq(0\) Prev\n); } } if($page < --$p){ $next = $FORM{'P'} + 1; if ($FORM{'U'}){ print qq(9\) Next\n); }else{ print qq(9\) Next\n); } } print qq(

      ※\)注意:※のリンクは Google の変換サービスにリンクします.それに続くリンクは当サイトの変換サービス対象外です.

      \n); # おのひろき拡張 print ""; } # 出力 sub print_onc { $num1 = ++$num[$page]; $prev = $FORM{'P'} - 1; $next = $FORM{'P'} + 1; print qq(Content-Type: text/plain; charset=Shift_JIS\n); # おのひろき拡張 print qq(Content-Language: ja\n); # print qq(ROBOTS: NOINDEX,NOFOLLOW\n); # print qq(Pragma: no-cache\n); # print qq(Cache-Control: no-cache\n\n); print qq(\n); print "From: $onc_url\n"; print "Subject: $title\n"; print "Content-Type: Text/X-PmailDX\n\n"; print $sel[$page]; # Prev用SEL表示 if($page > 0){ $num2 = ++$num[$page]; print "\n"; } # Next用SEL表示 if($page < --$p){ $num3 = ++$num[$page]; print "\n"; } print $out[$page]; # FOOTER出力 print "\n------\n"; print '['.$num1.']Top'; print "\n"; if($num2){ print '['.$num2.']Prev'; print "\n"; } if($num3){ print '['.$num3.']Next'; print "\n"; } } # 出力 sub print_wap { print "Content-type: text/x-hdml;charset=Shift_JIS\n"; print qq(Content-Language: ja\n); # print qq(ROBOTS: NOINDEX,NOFOLLOW\n); # print qq(Pragma: no-cache\n); # print qq(Cache-Control: no-cache\n\n); print qq(\n); print "\n"; print qq(\n); print qq(\n); print "$title
      \n"; print $out[$page]; print qq(\n
      ---
      \n); if($page > 0){ $prev = $FORM{'P'} - 1; if ($FORM{'U'}){ print qq(Prev\n); }else{ print qq(Prev\n); } } if($page < --$p){ $next = $FORM{'P'} + 1; if ($FORM{'U'}){ print qq(Next\n); }else{ print qq(Next\n); } } print "
      \n"; } # 出力 J-Sky おのひろき sub print_jsky { print qq(Content-Type: text/html; charset=Shift_JIS\n); print qq(Content-Language: ja\n); # print qq(ROBOTS: NOINDEX,NOFOLLOW\n); # print qq(Pragma: no-cache\n); # print qq(Cache-Control: no-cache\n\n); print qq(\n); print qq($title\n\n); print $out[$page]; print qq(

      \top\n); if($page > 0){ $prev = $FORM{'P'} - 1; if ($FORM{'U'}){ print qq(Prev \|\n); }else{ print qq(Prev |\n); } } if($page < --$p){ $next = $FORM{'P'} + 1; if ($FORM{'U'}){ print qq(Next\n); }else{ print qq(Next\n); } } print qq(

      ※のリンクは変換サービス対象外

      \n); print ""; } # 出力 dot-i おのひろき sub print_doti { print qq(Content-Type: text/html; charset=Shift_JIS\n); print qq(Content-Language: ja\n); # print qq(ROBOTS: NOINDEX,NOFOLLOW\n); # print qq(Pragma: no-cache\n); # print qq(Cache-Control: no-cache\n\n); print qq(\n); # print qq(\n); print qq($title\n\n); print qq(

      \0\) TOP\n); print $out[$page]; print qq(


      0\) TOP \|\n); print qq(3\) menu<\/A>
      \n); if($page > 0){ $prev = $FORM{'P'} - 1; if ($FORM{'U'}){ print qq(
      *\) \戻\る \|\n); }else{ print qq(*\) \戻\る |\n); } } if($page < --$p){ $next = $FORM{'P'} + 1; if ($FORM{'U'}){ print qq(9\) \次\n); }else{ print qq(9\) \次\n); } } print "

      #)ドットiホーム

      "; print qq(

      ※\)注意:先頭に\(※\)の付いたリンクは変換サービス対象外.

      \n); print ""; } # 自前でHTMLテキストを得る # HTML to ONCコンバータ(onccnv.pl)を参考にしています。 # onccnv.pl --- by M.Kawakami # sub get_html_text ($) { my ($url) = @_; $intext = ''; local (*IN); return '' if ($url eq ''); my ($h, $d, $server, $file) = split(/\//, $url, 4); my ($server, $port)= split(/\:/, $server); $port = 80 if ($port eq ''); $remote_address = sockaddr_in($port, inet_aton($server)); $proto = getprotobyname('tcp'); socket(IN,PF_INET,SOCK_STREAM,$proto) || die "Socket: $!"; my $c = 0; do { $result = connect(IN, $remote_address); if ($c++ >= 10) { &print_error( 'CONNECT ERROR' ); } if ($result != 1) { sleep(1); } } while ($result != 1); select((select(IN), $| = 1)[0]); print IN "GET /$file HTTP/1.0\r\n"; print IN "Referer: $top_url\r\n"; print IN "Host: $server\r\n"; print IN "Accept: */*\r\n"; print IN "User-Agent: HTML2MOBILE/0.91-o6(mode$mode)\r\n"; # おのひろき拡張 # $mode に応じて UA 名が変化します. # iモードなら HTML2MOBILE/0.91-o6(mode1) # HDML なら HTML2MOBILE/0.91-o6(mode2) など print IN "Connection: close\n"; print IN "\r\n"; #header 非表示 while () { m/^\r\n$/ && last; } while(){ # s/\n//g; $intext .= $_ ; } close(IN); if($use_jcode){ jcode::convert( \$intext , 'sjis' ) ; } $intext; } # error出力 sub print_error($) { print "Content-Type: text/plain\n\n"; print "@_\n"; exit; } # tagで分割 sub conv_tag ($) { @tag = grep { !/^$/ } split( /(<[^>]*>)/, "@_" ); }