#! /home/jcw/bin/tclkit # This cgi script gets called for all requests in the get/ directory. # It expects to be called with an url such as: # https://www.equi4.com/starch/get/3dmaze.kit # https://www.equi4.com/starch/get/3dmaze-12345-23456.kit # Such urls are listed in the "listing.html" output of "listall.tcl". # The returned result is an on-the-fly (re-)constructed starkit. # # TODO: # - construct zip files on the fly too, using critlib's "zipper" package # (it's not hard, it could even be done for tar.gz's with a bit more work) # - optimize this (cache generated files?), it's way too slow for big sk's # (note that creating "get/U9..8B/3dmaze.kit" would automatically cache it) # # jcw, 2003-09-04 source [file join [file dirname [info script]] util.tcl] if {[catch { set start [clock clicks -milli] # requests have a very strict format set t [file tail $env(REQUEST_URI)] if {![regexp {^(.+)\.(kit)$} $t - name e]} { error "can't parse request URL" } if {![regexp {(.*)-(\d{5}-\d{5})$} $name - name vid]} { error "can't parse version id" } if {![file exists kits/$name-$vid]} { error "can't fine $name-$vid" } set fd [open kits/$name-$vid] set kinfo [read $fd] close $fd foreach {ip date - - user msg a2 l2 a1 l1} $kinfo break if {$e eq "kit"} { # get the head, i.e. the data preceding the MK data set head [readone $a2] catch { set head [vfs::zip -mode decompress $head] } } else { # other file formats don't use header set head "" error "file type '$e' not currently supported" ;# TODO } # get the tail, i.e. the MK data portion set tail [readone $a1] catch { set tail [vfs::zip -mode decompress $tail] } # load tail string into a MK in-mem db, via memchan stream set fd [vfs::memchan] fconfigure $fd -translation binary puts -nonewline $fd $tail seek $fd 0 mk::file open db mk::file load db $fd close $fd # restucture catalog to drop the "md5" and add the "contents" property # note that all md5 values are still available *until* commit or close! mk::view layout db.dirs \ {name parent:I {files {name size:I date:I contents:B}}} # go through all entries, loading datafiles for each md5 value set count 0 if 1 { mk::loop c db.dirs { mk::loop d $c.files { set x [amspath [mk::get $d md5] [mk::get $d size]] set x [lindex [split $x /] end] mk::set $d contents [readone $x] incr count } } } # append a log entry with some statistics, if possible catch { set finish [clock clicks -milli] set fd [open /home/jcw/data/sgetlog.txt a] set t [clock format [clock seconds] -format {%Y/%m/%d %H:%M:%S} -gmt 1] puts $fd "$t [list [expr {($finish-$start)/1000.0}]s ${count}f \ $env(REMOTE_ADDR) $env(REQUEST_URI)]" close $fd } # done, return the resulting starkit puts "Content-type: application/octet-stream" puts "" fconfigure stdout -translation binary puts -nonewline $head mk::file save db stdout mk::file close db }]} { # error handling: present error message as html output puts "Content-type: text/plain" puts "" puts $errorInfo puts "" parray env }