+proc RobotHref {task url hrefx hostx pathx} {
+ global URL control debuglevel
+ upvar $hrefx href
+ upvar $hostx host
+ upvar $pathx path
+
+ if {$debuglevel > 1} {
+ puts "Ref input url = $url href=$href"
+ }
+
+ if {[string first { } $href] >= 0} {
+ return 0
+ }
+ if {[string length $href] > 256} {
+ return 0
+ }
+
+# Skip pages that have ? in them
+# if {[string first {?} $url] >= 0 && [string first {?} $href] >= 0} {
+# return 0
+# }
+ # get method (if any)
+ if {![regexp {^([^/:]+):(.*)} $href x method hpath]} {
+ set hpath $href
+ set method http
+ } else {
+ if {[string compare $method http]} {
+ return 0
+ }
+ }
+ # get host (if any)
+ if {[regexp {^//([^/]+)([^\#]*)} $hpath x host surl]} {
+ if {![string length $surl]} {
+ set surl /
+ }
+ if {[info exist control($task,domains)]} {
+ set ok 0
+ foreach domain $control($task,domains) {
+ if {[string match $domain $host]} {
+ set ok 1
+ break
+ }
+ }
+ if {!$ok} {
+ return 0
+ }
+ }
+ } else {
+ regexp {^([^\#]*)} $hpath x surl
+ set host $URL($task,$url,hostport)
+ }
+ if {![string length $surl]} {
+ return 0
+ }
+ if {[string first / $surl]} {
+ # relative path
+ set curpath $URL($task,$url,path)
+ if {[info exists URL($task,$url,bpath)]} {
+ set curpath $URL($task,$url,bpath)
+ }
+ regexp {^([^\#?]*)} $curpath x dpart
+ set l [string last / $dpart]
+ if {[expr $l >= 0]} {
+ set surl [string range $dpart 0 $l]$surl
+ } else {
+ set surl $dpart/$surl
+ }
+ }
+ set surllist [split $surl /]
+ catch {unset path}
+ set pathl 0
+ foreach c $surllist {
+ switch -- $c {
+ .. {
+ if {$pathl > 1} {
+ incr pathl -2
+ set path [lrange $path 0 $pathl]
+ incr pathl
+ }
+ }
+ . {
+
+ }
+ default {
+ incr pathl
+ lappend path $c
+ }
+ }
+ }
+ if {$debuglevel > 4} {
+ puts "pathl=$pathl output path=$path"
+ }
+ set path [join $path /]
+ if {![string length $path]} {
+ set path /
+ }
+ regsub -all {~} $path {%7E} path
+ set href "$method://$host$path"
+
+ if {$debuglevel > 1} {
+ puts "Ref result = $href"
+ }
+ return [checkrule $task url $href]
+}
+
+proc RobotError {task url code} {
+ global URL
+
+ puts "Bad URL $url (code $code)"
+ set fromurl {}
+ set distance -1
+ if {[RobotFileExist $task unvisited $URL($task,$url,hostport) $URL($task,$url,path)]} {
+ set inf [RobotFileOpen $task unvisited $URL($task,$url,hostport) $URL($task,$url,path) r]
+ RobotReadRecord $inf fromurl distance
+ RobotFileClose $inf
+ }
+ RobotFileUnlink $task unvisited $URL($task,$url,hostport) $URL($task,$url,path)
+ if {![RobotFileExist $task bad $URL($task,$url,hostport) $URL($task,$url,path)]} {
+ set outf [RobotFileOpen $task bad $URL($task,$url,hostport) $URL($task,$url,path)]
+ RobotWriteRecord $outf $fromurl $distance
+ RobotFileClose $outf
+ }
+}
+
+proc RobotRedirect {task url tourl code} {
+ global URL
+
+ puts "Redirecting from $url to $tourl"
+
+ set distance {}
+ set fromurl {}
+ if {[RobotFileExist $task unvisited $URL($task,$url,hostport) $URL($task,$url,path)]} {
+ set inf [RobotFileOpen $task unvisited $URL($task,$url,hostport) $URL($task,$url,path) r]
+ RobotReadRecord $inf fromurl distance
+ RobotFileClose $inf
+ }
+ if {![RobotFileExist $task bad $URL($task,$url,hostport) $URL($task,$url,path)]} {
+ set outf [RobotFileOpen $task bad $URL($task,$url,hostport) $URL($task,$url,path)]
+ RobotWriteRecord $outf $fromurl $distance
+ RobotFileClose $outf
+ }
+ if {[RobotHref $task $url tourl host path]} {
+ if {![RobotFileExist $task visited $host $path]} {
+ if {![RobotFileExist $task unvisited $host $path]} {
+ set outf [RobotFileOpen $task unvisited $host $path]
+ RobotWriteRecord $outf $fromurl $distance
+ RobotFileClose $outf
+ }
+ } else {
+ set olddistance {}
+ set inf [RobotFileOpen $task visited $host $path r]
+ RobotReadRecord $inf oldurl olddistance
+ RobotFileClose $inf
+ if {[string length $olddistance] == 0} {
+ set olddistance 1000
+ }
+ if {[string length $distance] == 0} {
+ set distance 1000
+ }
+ puts "distance=$distance olddistance=$olddistance"
+ if {[expr $distance < $olddistance]} {
+ set outf [RobotFileOpen $task unvisited $host $path]
+ RobotWriteRecord $outf $tourl $distance
+ RobotFileClose $outf
+ }
+ }
+ }
+ if {[catch {RobotFileUnlink $task unvisited $URL($task,$url,hostport) $URL($task,$url,path)}]} {
+ puts "unlink failed"
+ exit 1
+ }
+}
+
+proc link {task url out href body distance} {
+ global URL control
+ if {[expr $distance > $control($task,distance)]} return