Index: mod_nsd/tcl_modules/fastpath.tcl =================================================================== RCS file: /usr/local/cvsroot/mod_nsd/tcl_modules/fastpath.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ mod_nsd/tcl_modules/fastpath.tcl 6 May 2001 18:54:01 -0000 1.1 @@ -0,0 +1,467 @@ +# +# The contents of this file are subject to the AOLserver Public License +# Version 1.1 (the "License"); you may not use this file except in +# compliance with the License. You may obtain a copy of the License at +# http://aolserver.com/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# The Original Code is AOLserver Code and related documentation +# distributed by AOL. +# +# The Initial Developer of the Original Code is America Online, +# Inc. Portions created by AOL are Copyright (C) 1999 America Online, +# Inc. All Rights Reserved. +# +# Alternatively, the contents of this file may be used under the terms +# of the GNU General Public License (the "GPL"), in which case the +# provisions of GPL are applicable instead of those above. If you wish +# to allow use of your version of this file only under the terms of the +# GPL and not to allow others to use your version of this file under the +# License, indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by the GPL. +# If you do not delete the provisions above, a recipient may use your +# version of this file under either the License or the GPL. +# + +# +# $Header: /usr/local/cvsroot/mod_nsd/tcl_modules/fastpath.tcl,v 1.1 2001/05/06 18:54:01 petrup Exp $ +# + +# +# fastpath.tcl -- +# +# AOLserver 2.x fastpath routines moved from C. The C code +# now only handles the simple case of returning a file through +# an optimized caching routines. All legacy AOLpress publishing +# functions are handled with the Tcl code below. In addition, +# the C code will dispatch to the _ns_dirlist proc below to +# handle directory listings and AOLpress MiniWeb top pages. +# + +set path "ns/server/[ns_info server]" +nsv_set _ns_fastpath type [ns_config $path directorylisting none] +nsv_set _ns_fastpath hidedot [ns_config -bool $path hidedotfiles 1] +nsv_set _ns_fastpath toppage [ns_config -bool $path returnmwtoppage 0] +nsv_set _ns_fastpath aolpress [ns_config -bool $path enableaolpress 0] + +# +# Register the publishing procs if enabled. Note that you must +# load a permission module (e.g., nsperm) or the server +# will deny access to all these publishing methods. +# + +if [nsv_get _ns_fastpath aolpress] { + ns_register_proc PUT / _ns_publish _ns_put + ns_register_proc DELETE / _ns_publish _ns_delete + ns_register_proc BROWSE / _ns_publish _ns_browse + ns_register_proc MKDIR / _ns_publish _ns_mkdir + ns_register_proc OPTIONS / _ns_publish _ns_options +} + + +# +# _ns_isaolpress -- +# +# Is the client AOLpress? +# + +proc _ns_isaolpress {} { + set agent [ns_set iget [ns_conn headers] user-agent] + return [string match NaviPress/* $agent] +} + + +# +# _ns_getnvd -- +# +# Return the MiniWeb control file for a directory. +# + +proc _ns_getnvd dir { + return $dir/document.nvd +} + + +# +# _ns_ismw -- +# +# Is the directory a MiniWeb? +# + +proc _ns_ismw dir { + return [file exists [_ns_getnvd $dir]] +} + + +# +# _ns_dirlist -- +# +# Handle directory listings. This code is invoked from C. +# + +proc _ns_dirlist {} { + set url [ns_conn url] + set dir [ns_url2file $url] + + # + # Handle special case of AOLpress MiniWebs. + # + + if {[nsv_get _ns_fastpath toppage] && [_ns_ismw $dir]} { + set nvd [_ns_getnvd $dir] + if [_ns_isaolpress] { + return [ns_returnfile 200 application/x-navidoc $file] + } + set fp [open $nvd] + while {[gets $fp line] >= 0} { + if [string match Pages:* $line] { + break + } + } + gets $fp line + close $fp + set file [lindex [split $line \"] 1] + if [file exists $dir/$file] { + return [ns_returnredirect $file] + } + } + + # + # Handle default case of directory listing. Simple + # format is just the files while fancy includes + # the size and modify time (which is more expensive). + # + + switch [nsv_get _ns_fastpath type] { + simple { + set simple 1 + } + fancy { + set simple 0 + } + none - + default { + return [ns_returnnotfound] + } + } + + set hidedot [nsv_get _ns_fastpath hidedot] + set location [ns_conn location] + + set prefix "${location}${url}/" + set up ".." + if $simple { + append list " +
+$up
+"
+    } else {
+	append list "
+
+
+
+"
+    }
+
+    foreach f [lsort [glob -nocomplain $dir/*]] {
+	set tail [file tail $f]
+	if {$hidedot && [string match .* $tail]} {
+	    continue
+	}
+	
+	set link "${tail}"
+
+	if $simple {
+	    append list $link\n
+	} else {
+	    
+	    if [catch {
+		file stat $f stat
+	    } errMsg ] {
+		append list "
+\n
+"
+	    } else {
+		set size [expr $stat(size) / 1000 + 1]K
+		set mtime $stat(mtime)
+		set time [clock format $mtime -format "%d-%h-%Y %H:%M"]
+		append list "
+\n
+"
+	    }
+	}
+    }
+    if $simple {
+	append list ""
+    } else {
+	append list "
FileSizeDate
$up
$linkN/AN/A
$link$size$time
" + } + ns_returnnotice 200 $url $list +} + + +# +# _ns_publish -- +# +# Wrapper to log publishing actions. +# + +proc _ns_publish proc { + ns_log notice "fastpath:[ns_conn authuser]:$proc [ns_conn url]" + $proc +} + +proc ns_returnok {} { + ns_return 200 text/plain "" +} + +proc _ns_remove file { + ns_log notice "fastpath:[ns_conn authuser]:unlink: $file" + ns_unlink $file +} + +# +# _ns_browse -- +# +# Handle the AOLpress BROWSE request to for its file dialog. +# + +proc _ns_browse {} { + set url [ns_conn url] + set dir [ns_url2file $url] + set files "" + foreach f [glob -nocomplain $dir/*] { + set tail [file tail $f] + if [file isdir $f] { + set type "application/x-navidir" + } else { + set type [ns_guesstype $tail] + } + append files "$type $tail\n" + } + ns_return 200 application/x-navibrowse $files +} + + +# +# _ns_mkdir -- +# +# Handle the AOLpress MKDIR request to create a new directory. +# + +proc _ns_mkdir {} { + set url [ns_conn url] + set dir [ns_url2file $url] + if [file exists $dir] { + return [ns_returnbadrequest "File Exists"] + } + + if [catch {ns_mkdir $dir} err] { + ns_log error "fastpath: mkdir $dir failed: $err" + ns_returnbadrequest "Could not create directory" + } + ns_returnok +} + + +# +# _ns_options -- +# +# Handle the AOLpress OPTIONS request to return available functions. +# Note that LOCK and UNLOCK are not yet supported. +# + +proc _ns_options {} { + set hdrs [ns_conn outputheaders] + ns_set put $hdrs Allow "OPTIONS, GET, HEAD, PUT, BROWSE, MKDIR" + ns_returnok +} + + +# +# _ns_delete -- +# +# Handle the AOLpress DELETE request to delete a file +# or empty directory. Note that deleting MiniWebs is +# not yet supported. +# + +proc _ns_delete {} { + set url [ns_conn url] + set file [ns_url2file $url] + if ![file exists $file] { + return [ns_returnbadrequest "No Such File"] + } + if [catch { + if ![file isdir $file] { + _ns_remove $file + } else { + set dir $file + if [_ns_ismw $dir] { + set nvd [_ns_getnvd $dir] + set tail [file tail $nvd] + set files($tail) 1 + set pages 0 + set fp [open $nvd] + while {[gets $fp line] >= 0} { + if [string match Pages:* $line] { + set pages 1 + break + } + } + if $pages { + while {[gets $fp line] >= 0} { + if ![regexp {^"} $line] break + set file [lindex [split $line \"] 1] + set files($file) 0 + } + } + close $fp + foreach file [glob -nocomplain $dir/*] { + set tail [file tail $file] + if ![info exists files($tail)] { + return [ns_returnbadrequest "Directory not empty"] + } + set files($tail) 1 + } + foreach tail [array names files] { + if $files($tail) { + _ns_remove $dir/$tail + } + } + } + ns_rmdir $dir + } + } err] { + ns_log error "fastpath: delete $file failed: $err" + ns_returnbadrequest "Could not delete file" + } + ns_returnok +} + + +# +# _ns_put -- +# +# Handle the AOLpress PUT request to save a file +# or MiniWeb. The MiniWeb code is a bit tricky. +# Also, files are saved to tmp files and renamed +# to ensure half-written files don't become permanent +# + +proc _ns_put {} { + set url [ns_conn url] + set file [ns_url2file $url] + set hdrs [ns_conn headers] + set isdir 0 + set ismw 0 + set exists [file exists $file] + set type [ns_set iget $hdrs content-type] + + if {[ns_set ifind $hdrs x-navicreate] < 0} { + set create 0 + } else { + set create 1 + } + + if {$create && $exists} { + return [ns_returnerror 500 "Already Exists"] + } + if $exists { + set isdir [file isdir $file] + if $isdir { + set ismw [_ns_ismw $file] + } + } + if {$type == "application/x-naviwad"} { + if $exists { + if !$ismw { + return [ns_returnerror 500 "not miniweb"] + } + } + set ismw 1 + } elseif {$exists && $isdir} { + return [ns_returnerror 500 "File is a directory"] + } + + if [catch { + if $ismw { + + # + # Create MiniWeb directory if necessary. + # + + set dir $file + if !$exists { + ns_mkdir $dir + } + + # + # Spool MiniWeb content in a tmp file. + # + + set tmp [ns_tmpnam] + set fp [open $tmp w+] + fconfigure $fp -translation binary + ns_conncptofp $fp + + # + # Read the headers and save the content + # for each included file. + # + + seek $fp 0 + while {[gets $fp line] >= 0} { + set line [string trim $line] + if ![string length $line] { + if {![info exists length] || + ![info exists name]} { + close $fp + return [ns_returnbadrequest] + } + set file $dir/$name + set tmp2 [ns_mktemp $file.putXXXXXX] + set fp2 [open $tmp2 w] + ns_cpfp $fp $fp2 $length + close $fp2 + ns_rename $tmp2 $file + unset name + unset length + } else { + set kv [split $line :] + set k [string trim [lindex $kv 0]] + set v [string trim [lindex $kv 1]] + switch [string tolower $k] { + content-name { + set name $v + } + content-length { + set length $v + } + } + } + } + close $fp + ns_unlink $tmp + } else { + + # + # Save an ordinary file. + # + + set tmp [ns_mktemp $file.putXXXXXX] + set fp [open $tmp w] + ns_conncptofp $fp + close $fp + ns_rename $tmp $file + } + } err] { + ns_log error "put: save $url failed: $err" + return [ns_returnerror 500 "Save failed"] + } + ns_returnok +} Index: mod_nsd/tcl_modules/util.tcl =================================================================== RCS file: /usr/local/cvsroot/mod_nsd/tcl_modules/util.tcl,v diff -u -r1.1 -r1.2 --- mod_nsd/tcl_modules/util.tcl 13 Apr 2001 21:09:32 -0000 1.1 +++ mod_nsd/tcl_modules/util.tcl 6 May 2001 18:54:01 -0000 1.2 @@ -383,3 +383,13 @@ proc ns_updateheader {key value} { ns_set update [ns_conn outputheaders] $key $value } + +proc ns_returnnotice {status msg { longmsg "" } } { + ns_return $status text/html " + +

$msg

+

$longmsg + +" +} +