#!/usr/local/bin/perl #################################################################### # 程式名稱:RS-Counter 1.10 # 網頁瀏覽次數記錄器 - 不同的網頁可單獨或共同記錄在一個檔內 # 初始設計:1998/12/06 (ver 1.00) # 最後修改:1999/12/05 (ver 1.10) # 作  者:傅鴻銘 # 信  箱:redsnow@pemail.net # 網  頁:http://tacocity.com.tw/redsnow/index.htm # # 作者宣告: # 1.本程式圖形產生與輸出部分參考自 Kevin Meltzer 先生所設計製作之 # img_counter.pl 程式,該作者與程式的相關資料為: # 最後修改:1 January 1999 # 程式網頁:http://www.perlguy.com/perl/img_cnt.htm # 聯絡信箱:kmeltz@cris.com # 2.本程式免費提供給有需要的個人所使用,您可以修改程式碼以便符合您 # 的需求,但是請將本段表頭資料保留不動,表示對作者的尊重,至於您 # 自己的記載事項及其它說明請修改於本段資料之後。 ###################################################################### # 1.10 版:1999/12/05 # # 使用說明: # 1.修改本程式第一行之 #!/usr/local/bin/perl 為您的網站所適用的設定。 # 2.修改本程式之 rec_file 及 log_file 兩個參數,使其指向您的網頁目錄。 # 3.將本程式及記錄檔(.cnt 及 .log)上傳至網站上。 # 4.更改 RSCounter.pl 屬性為 755。 # 5.更改記錄檔(.cnt 及 .log)屬性為 666 或 777。 # 6.在 HTML 檔欲讓使用者下載檔案之處填入以下敘述: # # PATH_TO_SCRIPT = 本 CGI 程式所放置的位置(HTTP 格式的路徑)。 # file: 欲使用之紀錄檔名稱,若 name 參數未予設定時,將不適用於多頁面的計數。 # name: 欲紀錄及計數的識別字樣: # 1.不可使用中文及空白字元以及 (、)、&、=、+、# 數個符號 # 可用數字及英文字母與 -'":;/\<>~1+-*!?@,.|$%^`_ 符號混合使用的字樣 # 2.大小寫字元將視為不同的識別字樣 # 3.可直接以檔案名稱或是文字簡述為參數,例如: # 檔案名稱 - index.htm # 文字簡述 - HomePage # 4.本參數若省略掉不設定,file 參數所設的紀錄檔將僅紀錄一個數字資料, # 且每次存取都會重新改寫掉,因此僅適用於紀錄首頁等特定的單頁計數。 # log : 1 = 記錄網頁被載入時之日期時間及瀏覽者 IP 等資料,0 = 不記錄(內定值) # len : 最小顯示位數(內定值為 5),若累計數字的位數超過本項所設,將會在左方補上 "0" # high: 0 = 數字高度為 10 pixels,1 = 16 pixels # (內定值為 1,字型與 10 pixels 同,但是在上下各加三個空行) # inv : 1 = 黑底白字(內定值),0 = 白底黑字 # add : 1 = 累加數字(內定值),0 = 不累加 # ip : 1 = $wantlog 參數設為 1 時紀錄 IP 位址,0 = 不紀錄 # 範例: # 若您是 TacoMax 的居民且帳號為 GUEST,並且欲紀錄首頁檔被載入次數, # 則宣告看起來將如下所示: # # 將以上敘設定放到 index.htm 檔適當的位置就可以了。 #################################################################### my($realPath); # 擺放記錄下載次數的實體目錄 my($RecordFile); # 存取紀錄資料的檔案名稱 my($recFile); # 擺放記錄下載次數的檔案 my($logFile); # 擺放記錄下載次數及下載者資訊的檔案 $realPath = "/www/htdocs/sccid/group/NTUHakka/"; # TacoMax 居民適用本設定,其它網站請自行查明後修改之 $RecordFile = "RSCounter"; # 存取紀錄資料的檔案名稱 my($minLen) = 5; # 最小顯示位數,若紀錄數字的位數小於本項所設,將會在左方補上 "0" my($isHigh) = 1; # 0 = 數字高度為 10 pixels,0 = 16 pixels(字型與 10 pixels 同,在上下各加三個空行) my($isInverse) = 1; # 1 = 黑底白字,0 = 白底黑字 my($wantlog) = 0; # 1 = 記錄網頁被載入時之日期時間及瀏覽者 IP 等資料,0 = 不記錄 my($ip) = 1; # 1 = $wantlog 參數設為 1 時紀錄 IP 位址,0 = 不紀錄 my($addNumber) = 1; # 1 = 累加數字,0 = 不累加 &initialize; &incrementCount; &generateBitmap; &writeBitmap; exit(0); ############################# sub writeBitmap { print ("Content-type: image/x-xbitmap\n\n"); if($isHigh){ printf ("#define count_width %d\n#define count_height 16\n", $len*8); }else{ printf ("#define count_width %d\n#define count_height 10\n", $len*8); } printf STDOUT "static char count_bits[] = {\n"; for($i = 0; $i < ($#bytes + 1); $i++){ print("0x$bytes[$i]"); if($i != $#bytes){ print(","); if(($i+1) % $high == 0){ print("\n"); } } } print("};\n"); } sub generateBitmap { @bytes = (); $len = length($count) > $minLen ? length($count) : $minLen; $formattedCount = sprintf("%0${len}d",$count); if($isHigh){ for($i = 0; $i < $len*3; $i++){ if($isInverse){ push(@bytes,"ff"); # add three blank rows to each digit }else{ push(@bytes,"00"); } } } for($y=0; $y < 10; $y++){ for($x=0; $x < $len; $x++){ $digit = substr($formattedCount,$x,1); if($isInverse){ # $inv = 1 for inverted text $byte = substr(@invdigits[$digit],$y*3,2); }else{ $byte = substr(@digits[$digit],$y*3,2); } push(@bytes,$byte); } } if($isHigh){ for($i = 0; $i < $len*3; $i++){ if($isInverse){ push(@bytes,"ff"); # add three blank rows to each digit }else{ push(@bytes,"00"); } } } } sub initialize { read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); if ($buffer eq "") { $buffer = $ENV{'QUERY_STRING'}; } @pairs = split(/&/, $buffer); foreach $pair (@pairs) { $pair =~ tr/ //; ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg; $data{lc($name)} = $value; } if($data{'name'} ne ""){ $PageName="$data{'name'}"; } if($data{'file'} ne ""){ $RecordFile="$data{'file'}";} if($data{'log'} ne ""){ $wantlog="$data{'log'}";} if($data{'len'} ne ""){ $minLen="$data{'len'}";} if($data{'high'} ne ""){ $isHigh="$data{'high'}";} if($data{'inv'} ne ""){ $isInverse="$data{'inv'}";} if($data{'add'} ne ""){ $addNumber="$data{'add'}";} if($data{'ip'} ne ""){ $ip="$data{'ip'}";} $recFile = "$realPath$RecordFile.cnt"; # 擺放記錄下載次數的檔案 $logFile = "$realPath$RecordFile.log"; # 擺放記錄下載次數及下載者資訊的檔案 if($isHigh){ $high = 16; }else{ $high = 10; } @invdigits = ("c3 99 99 99 99 99 99 99 99 c3", # 0 "e7 e3 e7 e7 e7 e7 e7 e7 e7 c3", # 1 "c3 99 9f 9f cf e7 f3 f9 f9 81", # 2 "c3 99 9f 9f c7 9f 9f 9f 99 c3", # 3 "cf cf c7 c7 cb cb cd 81 cf 87", # 4 "81 f9 f9 f9 c1 9f 9f 9f 99 c3", # 5 "c7 f3 f9 f9 c1 99 99 99 99 c3", # 6 "81 99 9f 9f cf cf e7 e7 f3 f3", # 7 "c3 99 99 99 c3 99 99 99 99 c3", # 8 "c3 99 99 99 99 83 9f 9f cf e3"); # 9 @digits = ("3c 66 66 66 66 66 66 66 66 3c", # 0 "18 1c 18 18 18 18 18 18 18 3c", # 1 "3c 66 60 60 30 18 0c 06 06 7e", # 2 "3c 66 60 60 38 60 60 60 66 3c", # 3 "30 30 38 38 34 34 32 7e 30 78", # 4 "7e 06 06 06 3e 60 60 60 66 3c", # 5 "38 0c 06 06 3e 66 66 66 66 3c", # 6 "7e 66 60 60 30 30 18 18 0c 0c", # 7 "3c 66 66 66 3c 66 66 66 66 3c", # 8 "3c 66 66 66 66 7c 60 60 30 1c"); # 9 } sub incrementCount{ $count = 0; if($PageName ne ""){ if(-e $recFile) { open(FILE,"$recFile") || die("無法開啟 $recFile 這個檔案,系統錯誤訊息為:$!\n"); } @lines = ; close(FILE); $ok=0; $PageName2 = quotemeta $PageName; $lastno=@lines; foreach($j = 0;$j <= @lines;$j++){ if($lines[$j] =~ m#(\d+) \:\: $PageName2\n#o && $ok==0){ splice(@lines, $j, 1); $j -= 1; $count = $1; if($addNumber == 1){ $count++; } $ok=1; } } if($count == 0){ $count = 1; } $lines[$lastno]=sprintf("% 6d :: %s\n", $count, $PageName); open (FILE,">$recFile"); flock (FILE, 2); print FILE @lines; flock (FILE, 8); close (FILE); }else{ open(FILE,"$recFile"); flock (FILE, 1); $count = ; flock (FILE, 8); close(FILE); $count++; open(FILE,">$recFile"); flock (FILE, 2); print FILE "$count"; flock (FILE, 8); close(FILE); } if($wantlog == 1){ # 本註解的下兩行為第一種取得指定地區時間的設定,要使用時下兩行行首不可有 # 字元, # 並且要將第二種方式的敘述行行首加上 # 字元或刪除 # $ENV{TZ} = 'Asia/Taipei'; # ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); # 本註解的下一行為第二種取得指定地區時間的設定,要使用時下一行行首不可有 # 字元 # 並且要將第一種方式的敘述行行首加上 # 字元或刪除 ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time+8*60*60); $mon++; $shortdate = sprintf("$year%02d%02d %02d:%02d", $mon, $mday, $hour, $min); $mtime = (stat($logFile))[9]; $mtime = time unless ($mtime); ($fday,$fmon,$fyear) = (localtime($mtime))[3,4,5]; $fmon++; $size = -s "$logFile"; # 每月備份才用本行 if ($size > 51200 && $mday == 1 && $fday > 1){ if($size > 51200 && $mday ne $fday){ $bakFile = sprintf("%2d%02d%02d", $fyear, $fmon, $fday); $bakFile = "$realPath$RecordFile.$bakFile"; rename("$logFile","$bakFile"); } open (LOG, ">>$logFile"); flock (LOG, 2); if($PageName ne ""){ print LOG "$PageName-$count"; }else{ print LOG "$count-"; } $site = $ENV{'REMOTE_HOST'}; if($site eq ""){ $site = $ENV{'REMOTE_ADDR'}; } if($PageName ne ""){ if($ip == 1){ print LOG "-$site"; } print LOG "\[$shortdate\]"; }else{ print LOG "\[$shortdate\]"; if($ip == 1){ print LOG " $site"; } } print LOG "\n"; flock (LOG, 8); close (LOG); } }