'''"WhipIt"''' - Wikit run in a Slave Interpreter on TclHttpd Since I read the comments below this became an itch I just had to scratch! [Jeff Smith] Extracted from the [How to grow your own Wiki] page. ''[MDD]: What would be really nice would be if someone would create a Starkit that combines tclhttpd and the wikit into one turnkey wiki server. Performance should be better, since you wouldn't have to use CGI.'' ''11apr03 [jcw] - Yes, that would be cool, but it may need some work (either to make it properly keep state with repeated requests, or '''to make it work in a slave interp which gets re-inited on each access''').'' To try '''"WhipIt"''' place the following whipit.tcl code into the custom directory of your TclHttpd Starkit or get a ready made starkit, whipit.kit, from [http://www.freewebs.com/headsup/whipit.kit]. This starkit has a copy of wikit.kit inside and copies it to the outside directory at startup if the wikit.kit file does not exist. To launch on unix # ./tclkit whipit.kit On Windows from a dos window C:\tclkitsh whipit.kit from windows explorer drag and release whipit.kit on tclkit Point your browser to http://yourhost:8015/wikit/ This provides a nice wrapper around Wikit to allow you to dynamically control it. For example the WIKIT_BASE environment variable is dynamically set per request in the code below. Some ideas for the future * A readonly wiki with a seperate database that allows certain pages to be edited by dynamically removing "-readonly" flag for those pages. * A database which registers users and allows them to only edit the pages they created or edit pages of people in their group. [BAJ] uses whipit and finds it very useful, but just discovered that the history feature of wikit (enabled with "WIKIT_HIST" is broken by whipit (the puts that should write to a disk file ends up being remapped to the WktCGI_Puts command in script below). ***************** whipit.tcl ******************************** #Mount the wikit startkit vfs::mk4::Mount [file dir $starkit::topdir]/wikit.kit [file dir $starkit::topdir]/wikit.kit set WktDir [file dir $starkit::topdir]/wikit.kit # Append wikit library from the mounted wikit starkit to the auto_path lappend auto_path [file dir $starkit::topdir]/wikit.kit/lib Url_PrefixInstall /wikit [list wikitProc /wikit] proc wikitProc {prefix sock suffix} { upvar #0 Httpd$sock data global env auto_path # Set the CGI environment variables Cgi_SetEnv $sock $prefix set env(PATH_INFO) $suffix set env(SCRIPT_NAME) $prefix # This sets the WIKIT_BASE environment vaiable dynamically based on # the host portion of the url typed in the browser. set env(WIKIT_BASE) http://$env(HTTP_HOST)$prefix/ append data(query) "" # Use the Session Module in TclHttpd to create a slave interpreter. # A session state array is also created but we don't use it. This # maybe of some use if you have a need for a session based wiki. # # To emulate a CGI environment for Wikit, a slave interpreter is created # and then destroyed per request. # Destroy any old sessions that are laying around. Interpreters that have # been created but for some reason not destroyed. In this instance # 2 minutes is the setting. Session_Reap 120 Wkt # Create a new session. set session [Session_Create Wkt 0] set html [WktProcess $session $data(query)] Httpd_ReturnData $sock text/html $html Session_Destroy $session } proc WktProcess {session query} { upvar #0 Session:$session state set interp $state(interp) global auto_path WktDir set WktCGI_LineNumber 0 set html "" # Redirect the read and puts in the slave interpreter # that runs Wikit. interp eval $interp {rename puts real_puts} interp alias $interp puts {} WktCGI_Puts interp hidden $interp interp eval $interp {rename read real_read} interp alias $interp read {} WktCGI_Read $interp $query # Fool wikit to think it is running in it own Starkit so we can copy # the first ten pages from wikidoc.tkd interp eval $interp [list namespace eval starkit set topdir $WktDir] # Following taken from httpd.tcl for getting these variables into # a slave interpreter. # # Transfer the scalar global variables foreach var {::v ::auto_path} { $interp eval [list set $var [set $var]] } # Procedure that is run when the slave interpreter does a read. proc WktCGI_Read {interp query args} { if { [llength $args] == 2 && [lindex $args 0] == "stdin" } { return [$interp eval subst $query] } else { return [$interp eval real_read $args] } } # Precedure that is run when the slave interpreter does a puts. proc WktCGI_Puts {args} { upvar 1 WktCGI_LineNumber WktCGI_LineNumber upvar 1 html html incr WktCGI_LineNumber if {$WktCGI_LineNumber <= 4} { return "" } else { append html [lindex $args end] } } # Setup and run Wikit. $interp eval { set argv0 tclkit set argv {} set argc 0 package require cgi #cgi_debug -on # Work around for getting lassign into the slave interpreter. # From "Practical Programming in Tcl and Tk" Third Edition # by Brent B. Welch page 131. proc lassign {valueList args} { if {[llength $args] == 0 } { error "wrong # args: lassign list varname ?varname ..?" } if {[llength $valueList] == 0} { #Ensure one trip through the foreach loop set valueList [list {}] } uplevel 1 [list foreach $args $valueList {break}] return [lrange $valueList [llength $args] end] } # Source the starkit package require app-wikit } return $html } ****************************************************************************************** ---- [Category Wikit] - [Category TclHttpd]