[html::author "Colin McCormack"]
[mypage::header "Access Control Editor"]
<style>
BODY {
}
TABLE.group {
  background: #CCFFFF;
}

TH.group {
}
TD.group {
}
</style>
[
 proc get_AllowDeny {op} {
     foreach {v1 v2} [split [ncgi::value order_$op] ,] {break}
     return "[string totitle $v1],[string totitle $v2]"
 }
 
 proc MyAuthParseHtaccess {sock file {infoName ""}} {
     if {$infoName == ""} {
	 upvar #0 auth$file info
	 set infoName auth$file
     } else {
	 upvar #0 $infoName info
     }
     
     set mtime [file mtime $file]
     if {![info exists info] || ($mtime > $info(htaccessp,mtime))} {
	 # Parse .htaccess file
	 foreach i [array names info "htaccessp*"] {
	     unset info($i)
	 }
	 set info(htaccessp,mtime) $mtime
	 set info(htaccessp,userfile) {}
	 set info(htaccessp,groupfile) {}
	 if {[catch {open $file} in]} {
	     return 1
	 }
	 set state [list vars]
	 foreach line [split [read $in] \n] {
	     #puts stderr "$state $line"
	     if {[regexp {^#} $line] || [string length [string trim $line]] == 0} {
		 continue
	     }
	     if {[regexp <(.+)> $line x tag]} {
		 #puts stderr "var tag $tag"
		 set line $tag
	     }
                     set words [split $line]
	     set cmd [string tolower [lindex $words 0]]
	     if {[catch {
		 #puts stderr "var eval Ht-$cmd $infoName [lrange $words 1 end]"
		 eval Ht-$cmd $infoName [lrange $words 1 end]
	     } err]} {
		 Log $sock Error $err
	     }
                 }
                 close $in
     }
     return 1
 }
]
[
 # set blank defaults
 ::ncgi::setDefaultValue debug 0	;# set to 1 for debugging output

 ::ncgi::setDefaultValue submit Load
 ::ncgi::setDefaultValue userfile ""
 ::ncgi::setDefaultValue groupfile ""
 ::ncgi::setDefaultValue name webmaster
 ::ncgi::setDefaultValue type Digest

 ::ncgi::setDefaultValue order_GET allow,deny
 ::ncgi::setDefaultValue network_allow_GET ""
 ::ncgi::setDefaultValue network_deny_GET ""
 ::ncgi::setDefaultValue require_GET_group ""
 ::ncgi::setDefaultValue require_GET_user ""

 ::ncgi::setDefaultValue order_POST allow,deny
 ::ncgi::setDefaultValue network_allow_POST ""
 ::ncgi::setDefaultValue network_deny_POST ""
 ::ncgi::setDefaultValue require_POST_group ""
 ::ncgi::setDefaultValue require_POST_user ""

 set directory [ncgi::value directory]
 set submit [ncgi::value submit]
 set groupfile [ncgi::value groupfile]
 set userfile [ncgi::value userfile]

 if {![string match /* $directory]} { 
     set full_dir [file join $Config(docRoot) $directory]
 } else {
     set full_dir $directory
 }

 # Save the file if necessary
 if {[::ncgi::value submit] == "Update"} {

     # sanity check - prevent someone making /htaccess depend on
     # a non existent user or group file, which would lock them out
     global page
     if {[file dirname $page(template)] == $full_dir} {
	 if {($groupfile != "") && ![file exists $groupfile]} {
	     ::ncgi::setValue groupfile ""
	     return "<h2>Refused to save: group file $groupfile doesn't exist</h2>"
	 } elseif {($userfile != "") && ![file exists $userfile]} {
	     ::ncgi::setValue userfile ""
	     return "<h2>Refused to save: user file $userfile doesn't exist</h2>"
	 }
     }

     set content "# Generated by $page(url)\n"
     foreach {tag keyword} {userfile AuthUserFile
	 groupfile AuthGroupFile
	 name AuthName
	 type AuthType
     } {
	 if {[ncgi::value $tag] != ""} {
	     append content "$keyword [string map {" " ""} [ncgi::value $tag]]\n"
	 }
     }

     foreach op {GET POST} {
	 append content "\n<Limit $op>\n"
	 foreach {tag keyword} [subst {
	     order_${op} order
	     network_deny_${op} "deny from"
	     network_allow_${op} "allow from"
	     require_${op}_group "require group"
	     require_${op}_user "require user"
	 }] {
	     set val [ncgi::value $tag]
	     if {$val != ""} {
		 append content "$keyword $val\n"
	     }
	 }
	 
	 append content "</Limit>\n"
     }
     
     # write the file out if necessary
     catch {
	 file copy -force [file join $full_dir .htaccess] [file join $full_dir .htaccess-bak]
     }

     set fd [open [file join $full_dir .htaccess] w]
     puts $fd $content
     close $fd
 }

 global Httpd
 upvar #0 htaccess$Httpd(currentSocket) htaccess
 catch {unset htaccess}

 return ""
]

[
 if {$directory == ""} {
     # we have not been given a directory - use default
     global Config
     ::ncgi::setDefaultValue directory [file join $Config(docRoot) htaccess]
     set submit "Load"
     return [subst {
	 <p>With this utility, the administrator may create and edit group and user files, and .htaccess files in any directory.</p>
	 <p>You may wish to refer to the <a href='/access/htman.html'>documentation</a> and an <a href='/access/htaccess.html'>explanation of .htacess files</a> before proceeding.</p>
	 <ul>
	 <li><form action='$page(url)' method='POST'>
	 <input type='hidden' value='Load'>
	 Edit the .htaccess file in directory [html::textInput directory [::ncgi::value directory]]
	 </form></li>
	 <li><form action='./group.html' method='POST'>
	 Or edit Group file [html::textInput file [::ncgi::value groupfile]]
	 </form></li>
	 <li><form action='./user.html' method='POST'>
	 Or edit User file [html::textInput file [::ncgi::value userfile]]
	 </form></li>
	 </ul>
     }]
 } else {
     return ""
 }
]

[
 if {$directory != ""} {
     # Output the top part of the form
     if {[file exists [file join $directory .htaccess]]} {
	 # we have been given a directory - fetch and parse its contents
	 if {[catch {
	     MyAuthParseHtaccess $Httpd(currentSocket) \
		 [file join $full_dir .htaccess] \
		 htaccess$Httpd(currentSocket)} err]} {
	     global errorInfo
	     return [::html::row $err][::html::row $errorInfo]
	 }

	 foreach tag {userfile groupfile name type
	     order_GET network_deny_GET network_allow_GET
	     require_GET_group require_GET_user
	     order_POST network_deny_POST network_allow_POST
	     require_POST_group require_POST_user
	 } {
	     set ttag "htaccessp,[string map {_ ,} $tag]"
	     if {[info exists htaccess($ttag)]} {
		 ::ncgi::setValue $tag $htaccess($ttag)
	     }
	 }
	 set submit "Update"
     } else {
	 # new file - use defaults
	 set submit "Create"
     }

     set html "<p>See this utility's <a href='/access/htman.html'>documentation</a> and an <a href='/access/htaccess.html'>explanation of .htacess files</a> for the meaning of these fields.</p>"
     append html "<br><form action='$page(url)' method='POST'>"
     append html "<input type='hidden' name=directory value='$directory'>"
     append html "<table align='center' class='group'>\n"

     if {[file exists [file join $full_dir .tclaccess]]} {
	 append html "<h2>$full_dir contains a .tclaccess - .htaccess will be overriden!</h2>"
     }
     
     append html "<tr><th colspan=3>Header</th></tr>"
     append html [::html::foreach {tag var comment} [subst {
	 "Directory" directory "Directory containing .htaccess file"
	 "Realm" name "Security realm"
	 "<a href='user.html?file=[::html::quoteFormValue [ncgi::value userfile]]'>User File</a>" userfile "Click on label to edit User File."
	 "<a href='group.html?file=[::html::quoteFormValue [ncgi::value groupfile]]'>Group File</a>" groupfile "Click on label to edit Group File."

     }] {
	 <tr>
	 <th>$tag</th>
	 <td>[html::textInput $var [::ncgi::value $var]]</td>
	 <td>$comment</td>
	 </tr>
     }]
     append html [subst {
	 <tr>
	 <th>Type</th>
	 <td>[html::radioSet type {&nbsp;} {
		  digest Digest
		  basic Basic
	 } [ncgi::value type]]</td><td>Digest is more secure than Basic</td>
	 </tr>
     }]
    return "$html</table>"
 } else {
     return ""
 }
 ]
<br>
[
 if {($submit != "Load") && ($submit != "")} {
     # Output the detailed File form
     set html "<table class='group' align='center'>\n<tr>"
     append html [::html::foreach op {GET POST} {
	 <td><table class='group'>
	 <tr><th colspan='2'>$op Authorization</th></tr>
	 <tr><th>Require User</th><td>[html::textInput require_${op}_user [::ncgi::value require_${op}_user]]</td></tr>
	 <tr><th>Require Group</th><td>[html::textInput require_${op}_group [::ncgi::value require_${op}_group]]</td></tr>
	 <tr><th>Order</th>
	 <td>[html::radioSet order_$op {&nbsp;} {
	     "Deny,Allow" deny,allow
	     "Allow,Deny" allow,deny
	 } [get_AllowDeny $op]]</td></tr>
	 <tr><th>Allow $op From</th><td>[html::textInput network_allow_$op [::ncgi::value network_allow_$op]]</td></tr>
	 <tr><th>Deny $op From</th><td>[html::textInput network_deny_$op [::ncgi::value network_deny_$op]]</td></tr>
	 </table></td>
     }]
     append html "</tr></table></table><br>"
     append html [::html::submit "$submit"]
     append html "</form>"
     append html "<p><a href='index.html'>Return to htaccess editor</a></p>"

     return $html
 } else {
     return ""
 }
]

[if {[ncgi::value debug] == 1} {
    # debugging output
    return [subst {
	<p><b>htaccess Values</b><br>
	[html::tableFromArray htaccess "border=1"]
	<p><b>CGI Values</b><br>
	[html::tableFromList [ncgi::nvlist] "border=1"]
	<p>
	<b>Environment</b><br>
	[html::tableFromArray ::env "border=1" *]
    }]
}]
<p>
[mypage::footer]

<!--
### Local Variables: ###
### mode:tcl ###
### End: ###
-->
