Sample CGI


dirlist.cgi



reported by s-suzuki@aikis.or.jp

1.機能の説明
私がメインで使用しているプロバイダ(aikis)のユーザーページ一覧機能を模して作ってみたCGIスクリプトです。

機能的には、WWWサーバーのドキュメントルート(ユーザーディレクトリ)をサーチし、各ユーザーのフォルダにindex.htmlがある場合にHTML文書の<TITLE>タグのタイトルを取得してます。その後、更新時刻順にソートして表示しています。

2.動作の説明
まず、opendir()、readdir()でターゲットになるディレクトリにあるファイルリストを取得します。このリストにはディレクトリだけでなくファイルもリストされているので、次の処理でディレクトリだけを検索します。

続いて、取得したリストで opendir()出来るかどうかテストします。オープンできない場合はファイルと見なし、次のリストの処理に移ります。オープンできる場合はディレクトリですので、その中のindex.htmlを open()してみます。

open()出来る場合は、ファイルの先頭から適当なバイト数(今回は999999バイト。実際にはファイルサイズ分で終わるでしょう)を読み込みます。読み込んだら、処理の都合上、改行コードを削除します。この後<TITLE>を基準に split()関数を使ってタイトルを取得します。(この処理は、ややトリッキーな処理ですね)

この後、ソートのために更新時刻等のファイル情報を stat()関数をつかって取得します。最終更新時刻は $mtimeに格納されているので、これを localtime()関数で時刻データに変換します。

ここまできたら、ディレクトリ名やタイトル、更新時刻等を push()関数で配列にリストしていきます。この時にソートしやすくするために、先頭フィールドに stat()で取得した$mtimeのデータを加えているのが特徴です。

リストアップが終わったら、先頭フィールドの $mtimeをもとに sort()関数で逆順ソートしています。あとは、これを適当な形式(今回はテーブルを使用)で表示していくだけです。

3.スクリプトのソース
#!/usr/local/bin/perl # require 'jcode.pl'; $taget_dir = "./"; # 検索対象のディレクトリ、サーバーに応じて変更のこと #--------------------------------------------------------- # ターゲットディレクトリの一覧を取得する # ここで得られるリストにはファイルも含まれているので、 # 次の処理でディレクトリのみを検索するようにしている #--------------------------------------------------------- opendir(DIR, $taget_dir); @readlist = readdir(DIR); closedir(DIR); #--------------------------------------------------------- # ターゲットディレクトリ自身をのぞいて、ディレクトリ内の # index.htmlを読み込んで、タイトルを取得する #--------------------------------------------------------- foreach $dir (@readlist) { #------------------------------------------------ # ターゲットディレクトリ以外を検索 #------------------------------------------------ if ( $dir ne "." ) { #-------------------------------------- # ディレクトリとしてオープンできるか? #-------------------------------------- if (opendir(DIR,"$dir")) { # opendir() がtrueの時 #-------------------------------- # index.htmlをオープンできるか? #-------------------------------- if( open( DB, "$taget_dir$dir/index.html")) { #--------------------------------------- # 先頭から999999バイト読み込む # 実際にはファイルサイズ分のことが多い #--------------------------------------- sysread( DB, $line, 999999 ); close(DB); &jcode'convert(*line,'sjis'); $line =~ s/\n//g; $line =~ s/\r//g; $line =~ s/title>/TITLE>/ig; ($temp1, $temp2) = split(/<TITLE>/ig, $line); ($title, $temp1) = split(/<\/TITLE>/ig, $temp2); #--------------------------------- # ファイル情報(更新時刻)の取得 #--------------------------------- ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat("$taget_dir$dir/index.html"); ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($mtime); $month = ($mon + 1); if ($month < 10) { $month = "0$month"; } if ($mday < 10) { $mday = "0$mday"; } #------------------------------------------------------------- # 検索データリストの作成 #------------------------------------------------------------- # 先頭に更新時刻の元データをつけておくことで、ソートしやすく # している #------------------------------------------------------------- push( @dirdata, "$mtime\,$year-$month-$mday\,$dir\,$title" ); } } closedir(DIR); } } #------------------------------------- # 更新された順番にソート(逆順) #------------------------------------- @index = sort {$b cmp $a;} @dirdata; #------------------------------------- # HTML画面の出力 #------------------------------------- print "Content-type: text/html\n\n"; print "<HTML>\n<HEAD>\n"; print "<TITLE>ホームページ一覧</TITLE>\n"; print "</HEAD>\n\n"; print "<BASE TARGET=\"_top\">\n\n"; print "<BODY BGCOLOR=\"#ffffff\" TEXT=\"#000000\" LINK=\"#ffdddd\" ALINK=\"#ff2222\" VLINK=\"#ffaaaa\">\n\n"; print "<HR>\n"; print "<DIV ALIGN=\"center\">\n"; print "<FONT SIZE=+2>ホームページ一覧</FONT><HR>\n"; print "aikisに対抗して、同じようなものを作ってみました。<BR>更新順に表\示されます。</TD></TR>\n"; print "<TABLE BORDER=0>\n"; print "<TR VALIGN=\"middle\">\n"; print "<TH BGCOLOR=\"#117733\" ALIGN=\"right\"><FONT COLOR=\"#FFFFFF\">&nbsp;No.&nbsp;</FONT></TH>\n"; print "<TH BGCOLOR=\"#114499\"><FONT COLOR=\"#FFFFFF\">User</FONT></TH>\n"; print "<TH BGCOLOR=\"#ddeeff\">Title</TH>\n"; print "<TH BGCOLOR=\"#ddeeff\">Update</TH>\n"; print "</TR>\n"; $i =1; #----------------------------------- # 各項目の出力 #----------------------------------- foreach $temp (@index) { ( $mtime,$fdate,$dir,$title) = split( /,/, $temp); print "<TR VALIGN=\"middle\">\n"; print "<TD BGCOLOR=\"#117733\" ALIGN=\"right\"><FONT COLOR=\"#FFFFFF\"><B>&nbsp;$i&nbsp;</B></FONT></TD>\n"; print "<TD BGCOLOR=\"#114499\">&nbsp;<A HREF=\"./$dir/\">$dir</A>&nbsp;</TD>\n"; print "<TD BGCOLOR=\"#ddeeff\">&nbsp;<FONT SIZE=-1>$title</FONT>&nbsp;</TD>\n"; print "<TD NOWRAP BGCOLOR=\"#ddeeff\">&nbsp;<FONT SIZE=-1>$fdate</FONT>&nbsp;</TD>\n"; print "</TR>\n"; $i++; } print "</TABLE>\n"; print "<HR>\n"; print "</DIV>\n"; print "</BODY>\n</HTML>"; exit;