Bug fix for relative links.
[tclrobot.git] / robot.tcl
index ddbfb82..fa3c595 100755 (executable)
--- a/robot.tcl
+++ b/robot.tcl
@@ -1,8 +1,8 @@
 #!/usr/bin/tclsh 
-# $Id: robot.tcl,v 1.10 2001/01/23 09:20:32 adam Exp $
+# $Id: robot.tcl,v 1.17 2001/06/07 08:10:10 adam Exp $
 #
 proc RobotFileNext1 {area lead} {
-    puts "RobotFileNext1 area=$area lead=$lead"
+    # puts "RobotFileNext1 area=$area lead=$lead"
     if {[catch {set ns [glob ${area}/*]}]} {
         return {}
     }
@@ -43,7 +43,7 @@ proc RobotReadRecord {inf fromurlx distancex} {
     gets $inf
     gets $inf
     set distance [string trim [gets $inf]]
-    puts "got distance = $distance"
+    # puts "got distance = $distance"
     gets $inf
     gets $inf
     set fromurl [string trim [gets $inf]]
@@ -52,7 +52,7 @@ proc RobotReadRecord {inf fromurlx distancex} {
 proc RobotFileNext {area} {
     global robotSeq global idleTime ns
 
-    puts "RobotFileNext robotSeq=$robotSeq"
+    # puts "RobotFileNext robotSeq=$robotSeq"
     if {$robotSeq < 0} {
        return {}
     }
@@ -87,27 +87,27 @@ proc RobotFileNext {area} {
 
 
 proc RobotFileExist {area host path} {
-    puts "RobotFileExist begin area=$area host=$host path=$path"
+    # puts "RobotFileExist begin area=$area host=$host path=$path"
     set lpath [split $path /]
     set l [llength $lpath]
     incr l -1
     set t [lindex $lpath $l]
     incr l -1
     set npath $area/$host[join [lrange $lpath 0 $l] /d]/f$t
-    puts "RobotFileExist end npath=$npath"
+    # puts "RobotFileExist end npath=$npath"
     return [file exists $npath]
 }
 
 proc RobotFileUnlink {area host path} {
-    puts "RobotFileUnlink begin"
-    puts "area=$area host=$host path=$path"
+    # puts "RobotFileUnlink begin"
+    # puts "area=$area host=$host path=$path"
     set lpath [split $path /]
     set l [llength $lpath]
     incr l -1
     set t [lindex $lpath $l]
     incr l -1
     set npath $area/$host[join [lrange $lpath 0 $l] /d]/f$t
-    puts "npath=$npath"
+    # puts "npath=$npath"
     set comp [split $npath /]
     set l [llength $comp]
     incr l -1
@@ -118,7 +118,7 @@ proc RobotFileUnlink {area host path} {
        if {![catch {glob $path/*}]} return
         exec rmdir ./$path
     }
-    puts "RobotFileUnlink end"
+    # puts "RobotFileUnlink end"
 }
 
 proc RobotFileClose {out} {
@@ -134,7 +134,7 @@ proc RobotFileOpen {area host path {mode w}} {
     if {![info exists workdir]} {
        return stdout
     }
-    puts "RobotFileOpen orgPwd=$orgPwd area=$area host=$host path=$path mode=$mode"
+    #puts "RobotFileOpen orgPwd=$orgPwd area=$area host=$host path=$path mode=$mode"
     if {[string compare $orgPwd $workdir]} {
         puts "ooops. RobotFileOpen failed"
        puts "workdir = $workdir"
@@ -203,7 +203,7 @@ proc RobotStart {} {
     global URL
     global robotsRunning robotsMax idleTime
   
-    puts "RobotStart"
+    # puts "RobotStart"
     while {1} {
         set url [RobotFileNext unvisited]
         if {![string length $url]} {
@@ -260,6 +260,16 @@ proc RobotHref {url hrefx hostx pathx} {
     upvar $pathx path
 
     puts "Ref url = $url href=$href"
+
+    if {[string first { } $href] >= 0} {
+       return 0
+    }
+    if {[string length $href] > 256} {
+       return 0
+    }
+    if {[string first {?} $url] >= 0 && [string first {?} $href] >= 0} {
+       return 0
+    }
     # get method (if any)
     if {![regexp {^([^/:]+):(.*)} $href x method hpath]} {
        set hpath $href
@@ -274,16 +284,18 @@ proc RobotHref {url hrefx hostx pathx} {
        if {![string length $surl]} {
            set surl /
        }
-       set ok 0
-       foreach domain $domains {
-           if {[string match $domain $host]} {
-               set ok 1
-               break
+        if {[info exist domains]} {
+           set ok 0
+           foreach domain $domains {
+               if {[string match $domain $host]} {
+                   set ok 1
+                   break
+                }
            }
-       }
-       if {!$ok} {
-           return 0
-       }
+           if {!$ok} {
+               return 0
+           }
+        }
     } else {
        regexp {^([^\#]*)} $hpath x surl
        set host $URL($url,hostport)
@@ -301,28 +313,31 @@ proc RobotHref {url hrefx hostx pathx} {
            set surl $dpart/$surl
        }
     }
-    set c [split $surl /]
-    set i [llength $c]
-    incr i -1
-    set path [lindex $c $i]
-    incr i -1
-    while {$i >= 0} {
-       switch -- [lindex $c $i] {
+    set surllist [split $surl /]
+    catch {unset path}
+    set pathl 0
+    foreach c $surllist {
+        switch -- $c {
            .. {
-               incr i -2
-               if {$i < 0} {
-                   set i 0
+               if {$pathl > 0} {
+                   incr pathl -1
+                   set path [lrange $path 0 $pathl]
                }
            }
-           . {
-               incr i -1
-           }
-           default {
-               set path [lindex $c $i]/$path
-               incr i -1
+            . {
+
+            }
+            default {
+               incr pathl
+                lappend path $c
            }
        }
     }
+    if {$pathl} {
+       set path [join $path /]
+    } else {
+       set path ""
+    }
     regsub -all {~} $path {%7E} path
     set href "$method://$host$path"
     puts "Ref href = $href"
@@ -417,12 +432,12 @@ proc RobotTextHtml {url out} {
             }
            puts $out {></meta>}
        } body {
-           regsub -all -nocase {<script.*</script>} $body {} abody
+           regsub -all -nocase {<script([^<]|(<!.*>))*</script>} $body {} abody
            regsub -all {<[^\>]+>} $abody {} nbody
            puts $out "<documentcontent>"
             puts $out $nbody
             puts $out "</documentcontent>"
-        } a {
+        } -nonest a {
             if {![info exists parm(href)]} {
                puts "no href"
                continue
@@ -472,6 +487,56 @@ proc RobotTextHtml {url out} {
                    }
                }
            }
+        } -nonest area {
+            if {![info exists parm(href)]} {
+               puts "no href"
+               continue
+            }
+           if {[expr $distance <= $maxDistance]} {
+               set href [string trim $parm(href)]
+               if {![RobotHref $url href host path]} continue
+               
+               puts $out "<cr>"
+               puts $out "<identifier>$href</identifier>"
+               puts $out "<description></description>"
+               puts $out "</cr>"
+
+               if {![RobotFileExist visited $host $path]} {
+                   set olddistance 1000
+                   if {![RobotFileExist bad $host $path]} {
+                       if {[RobotFileExist unvisited $host $path]} {
+                           set inf [RobotFileOpen unvisited $host $path r]
+                           RobotReadRecord $inf oldurl olddistance
+                           RobotFileClose $inf
+                       }
+                   } else {
+                       set olddistance 0
+                   }
+                   if {[string length $olddistance] == 0} {
+                       set olddistance 1000
+                   }
+                   if {[expr $distance < $olddistance]} {
+                       set outf [RobotFileOpen unvisited $host $path]
+                       RobotWriteRecord $outf $url $distance
+                       RobotFileClose $outf
+                   }
+               } elseif {[string compare $href $url]} {
+                   set inf [RobotFileOpen visited $host $path r]
+                   RobotReadRecord $inf xurl olddistance
+                   close $inf
+                   if {[string length $olddistance] == 0} {
+                       set olddistance 1000
+                   }
+                   if {[expr $distance < $olddistance]} {
+                       puts "OK remarking url=$url href=$href"
+                       puts "olddistance = $olddistance"
+                       puts "newdistance = $distance"
+                       set outf [RobotFileOpen unvisited $host $path]
+                       RobotWriteRecord $outf $url $distance
+                       RobotFileClose $outf
+                   }
+               }
+           }
        }
 }
 
@@ -485,21 +550,21 @@ proc RobotsTxt0 {v buf} {
     global URL agent
     set section 0
     foreach l [split $buf \n] {
-       if {[regexp {([-A-Za-z]+):[ \t]*([^\#]+)} $l match cmd arg]} {
+       if {[regexp {([-A-Za-z]+):[ \t]*([^\#\t ]+)} $l match cmd arg]} {
            puts "cmd=$cmd arg=$arg"
-           switch $cmd {
-               User-Agent {
+           switch -- [string tolower $cmd] {
+               user-agent {
                    if {$section} break
                    set pat [string tolower $arg]*
                    set section [string match $pat $agent]
                }
-               Disallow {
+               disallow {
                    if {$section} {
                        puts "rule [list 0 $arg]"
                        lappend $v [list 0 $arg]
                    }
                }
-               Allow {
+               allow {
                    if {$section} {
                        puts "rule [list 1 $arg]"
                        lappend $v [list 1 $arg]
@@ -525,6 +590,10 @@ proc RobotTextPlain {url out} {
 proc Robot200 {url} {
     global URL domains
     
+    set out [RobotFileOpen raw $URL($url,hostport) $URL($url,path)]
+    puts -nonewline $out $URL($url,buf)
+    RobotFileClose $out
+
     set out [RobotFileOpen visited $URL($url,hostport) $URL($url,path)]
     puts $out "<zmbot>"
 
@@ -547,7 +616,7 @@ proc Robot200 {url} {
            }
        }
        text/plain {
-           RobotTextPlain $url $out
+           RobotTextPlain $url $out $outr
        }
        application/pdf {
            set pdff [open test.pdf w]
@@ -608,7 +677,7 @@ proc RobotReadHeader {url sock} {
            regexp {^HTTP/([0-9.]+)[ ]+([0-9]+)} $headbuf x version code
            set lines [split $headbuf \n]
            foreach line $lines {
-               if {[regexp {^([^:]+):[ ]+(.*)} $line x name value]} {
+               if {[regexp {^([^:]+):[ ]+([^;]*)} $line x name value]} {
                    set URL($url,head,[string tolower $name]) [string trim $value]
                }
            }
@@ -695,7 +764,7 @@ proc RobotGetUrl {url phost} {
                set buf [read $inf 32768]
                close $inf
            } else {
-               set buf "User-Agent: *\nAllow: /\n"
+               set buf "User-agent: *\nAllow: /\n"
            }
            RobotsTxt0 URL($hostport,robots) $buf
        }
@@ -708,6 +777,7 @@ proc RobotGetUrl {url phost} {
            }
        }
        if {!$ok} {
+           puts "skipped due to robots.txt"
            return -1
        }
     }
@@ -729,9 +799,10 @@ if {![llength [info commands htmlSwitch]]} {
 set agent "zmbot/0.0"
 if {![catch {set os [exec uname -s -r]}]} {
     set agent "$agent ($os)"
-       puts "agent: $agent"
 }
 
+puts "agent: $agent"
+
 proc bgerror {m} {
     global errorInfo
     puts "BGERROR $m"
@@ -739,29 +810,86 @@ proc bgerror {m} {
 }
 
 set robotsRunning 0
-set robotsMax 5
 set robotSeq 0
 set workdir [pwd]
 set idleTime 60000
 
-if {[llength $argv] < 2} {
-    puts "Tclrobot: usage <range> <domain> <start>"
-    puts " Example: 3 '*.indexdata.dk' http://www.indexdata.dk/"
+set i 0
+set l [llength $argv]
+
+# For testing only
+if {0} {
+    set url "http://www.sportsfiskeren.dk/sportsfiskeren/corner/index.htm"
+    set href "../../data/../../data2/newsovs.asp?Mode=5"
+
+    set URL($url,path) /sportsfiskeren/corner/index.htm
+    set URL($url,hostport) www.sportsfiskeren.dk
+    RobotHref $url href host path
+    exit 0
+}
+
+if {$l < 2} {
+    puts {tclrobot: usage [-j jobs] [-i idle] [-c count] [-d domain] [url ..]}
+    puts " Example: -c 3 -d '*.dk' http://www.indexdata.dk/"
     exit 1
 }
 
-set maxDistance [lindex $argv 0]
-set domains [lindex $argv 1]
-foreach href [lindex $argv 2] {
-    if {[RobotHref http://www.indexdata.dk/ href host path]} {
-       if {![RobotFileExist visited $host $path]} {
-           set outf [RobotFileOpen unvisited $host $path]
-           RobotWriteRecord $outf $href 0
-           RobotFileClose $outf
+while  {$i < $l} {
+    set arg [lindex $argv $i]
+    switch -glob -- $arg {
+       -j* {
+           set robotsMax [string range $arg 2 end]
+           if {![string length $robotsMax]} {
+               set robotsMax [lindex $argv [incr i]]
+           }
+       }
+       -c* {
+           set maxDistance [string range $arg 2 end]
+           if {![string length $maxDistance]} {
+               set maxDistance [lindex $argv [incr i]]
+           }
+       }
+       -d* {
+           set dom [string range $arg 2 end]
+           if {![string length $dom]} {
+               set dom [lindex $argv [incr i]]
+           }
+           lappend domains $dom
+       }
+       -i* {
+           set idleTime [string range $arg 2 end]
+           if {![string length $idleTime]} {
+               set idleTime [lindex $argv [incr i]]
+           }
+       }
+       default {
+           set href $arg
+           if {[RobotHref http://www.indexdata.dk/ href host path]} {
+               if {![RobotFileExist visited $host $path]} {
+                   set outf [RobotFileOpen unvisited $host $path]
+                   RobotWriteRecord $outf href 0
+                   RobotFileClose $outf
+               }
+           }
        }
     }
+    incr i
 }
 
+if {![info exist domains]} {
+    set domains {*}
+}
+if {![info exist maxDistance]} {
+    set maxDistance 50
+}
+if {![info exist robotsMax]} {
+    set robotsMax 5
+}
+
+puts "domains=$domains"
+puts "max distance=$maxDistance"
+puts "max jobs=$robotsMax"
+
 RobotStart
 
 while {$robotsRunning} {