<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://panoptic.com/mediawiki/aolserver/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jcr</id>
	<title>AOLserver Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://panoptic.com/mediawiki/aolserver/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jcr"/>
	<link rel="alternate" type="text/html" href="https://panoptic.com/wiki/aolserver/Special:Contributions/Jcr"/>
	<updated>2026-04-25T16:19:42Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.34.2</generator>
	<entry>
		<id>https://panoptic.com/mediawiki/aolserver/index.php?title=Writing_Your_First_ADP&amp;diff=5176</id>
		<title>Writing Your First ADP</title>
		<link rel="alternate" type="text/html" href="https://panoptic.com/mediawiki/aolserver/index.php?title=Writing_Your_First_ADP&amp;diff=5176"/>
		<updated>2008-11-20T00:34:09Z</updated>

		<summary type="html">&lt;p&gt;Jcr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;ADPs are the simplest way to create a dynamic page in AOLserver. They support the use of all Tcl commands - including AOLserver ones and those you create in Tcl libraries - mixed with HTML to create a complete web page. Unlike Tcl libraries, any changes you make to the ADP take effect immediately without having to restart the server.&lt;br /&gt;
&lt;br /&gt;
'''Configuration'''&lt;br /&gt;
&lt;br /&gt;
Before you start trying, make sure you have configured AOLserver correctly to parse ADP pages.&lt;br /&gt;
&lt;br /&gt;
In the configuration file (usually nsd.tcl), make sure that below:&lt;br /&gt;
&lt;br /&gt;
 ns_section &amp;quot;ns/server/${servername}/adp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
but before the next &amp;quot;ns_section&amp;quot;, you have the line: &lt;br /&gt;
&lt;br /&gt;
 ns_param map &amp;quot;/*.adp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
uncommented.&lt;br /&gt;
&lt;br /&gt;
When you start AOLserver, do so by using the &amp;quot;-ft&amp;quot; option; this runs the server in the foreground and shows any Tcl errors on the console.&lt;br /&gt;
&lt;br /&gt;
If you are running AOLserver in the more usual background mode, errors in ADP pages are written to the server log, by default SERVERHOME/log/server.log, or locate it from the value (path and filename) returned by [[ns_info log]].&lt;br /&gt;
&lt;br /&gt;
'''Writing an ADP'''&lt;br /&gt;
&lt;br /&gt;
In the server's pageroot, create a file called ''test.adp'' using your favourite editor and enter the following code:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;%&lt;br /&gt;
    set title &amp;quot;Hello, AOLserver!&amp;quot;&lt;br /&gt;
    ns_adp_puts $title&lt;br /&gt;
 %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now request that page in a web browser.&lt;br /&gt;
&lt;br /&gt;
Another way to display the value of &amp;quot;title&amp;quot; would be:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;%= $title %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using that syntax, you can also display the results of a Tcl command:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;%= [ns_httptime [ns_time]] %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Mixing HTML and Tcl'''&lt;br /&gt;
&lt;br /&gt;
You can mix HTML and Tcl code to make a complete page:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  &amp;lt;%&lt;br /&gt;
    set title &amp;quot;Welcome to my homepage&amp;quot;&lt;br /&gt;
    set body &amp;quot;This is the main text part of the homepage&amp;quot;&lt;br /&gt;
  %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;html&amp;gt;&lt;br /&gt;
    &amp;lt;head&amp;gt;&lt;br /&gt;
      &amp;lt;title&amp;gt;&amp;lt;%= $title %&amp;gt;&amp;lt;/title&amp;gt;&lt;br /&gt;
    &amp;lt;/head&amp;gt;&lt;br /&gt;
    &amp;lt;body&amp;gt;&lt;br /&gt;
      &amp;lt;%= $body %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
      &amp;lt;p&amp;gt;Now let's count to 10!&amp;lt;/p&amp;gt;&lt;br /&gt;
      &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
      &amp;lt;%&lt;br /&gt;
         for {set i 1} {$i &amp;lt;= 10} {incr i} {&lt;br /&gt;
            ns_adp_puts &amp;quot;$i &amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
      %&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/body&amp;gt;&lt;br /&gt;
  &amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Setting ''title'' and ''body'' as variables was pretty pointless in this case. In your real website, however, these values could be taken from the database by one ADP, which in turn uses [[ns_adp_include]] to include another ADP to format the page and which can be re-used by many pages on your site.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[Category Documentation]] - [[Category Tutorial]]&lt;/div&gt;</summary>
		<author><name>Jcr</name></author>
		
	</entry>
	<entry>
		<id>https://panoptic.com/mediawiki/aolserver/index.php?title=Ns_return&amp;diff=5148</id>
		<title>Ns return</title>
		<link rel="alternate" type="text/html" href="https://panoptic.com/mediawiki/aolserver/index.php?title=Ns_return&amp;diff=5148"/>
		<updated>2008-08-18T23:54:51Z</updated>

		<summary type="html">&lt;p&gt;Jcr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;manpage&amp;gt;ns_return&amp;lt;/manpage&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NAME ==&lt;br /&gt;
&lt;br /&gt;
ns_connsendfp, ns_respond, ns_return, ns_returnadminnotice, ns_returnbadrequest, ns_returnerror, ns_returnfile, ns_returnforbidden, ns_returnfp, ns_returnnotfound, ns_returnnotice, ns_returnredirect, ns_returnunauthorized, ns_write - commands&lt;br /&gt;
&lt;br /&gt;
== SYNOPSIS ==&lt;br /&gt;
&lt;br /&gt;
: '''[[ns_connsendfp]]''' ''fp len''&lt;br /&gt;
: '''[[ns_respond]]'''&lt;br /&gt;
: '''ns_return''' ''status type string''&lt;br /&gt;
: '''[[ns_returnadminnotice]]''' ''status msg ?longmsg?''&lt;br /&gt;
: '''[[ns_returnbadrequest]]''' ''reason''&lt;br /&gt;
: '''[[ns_returnerror]]''' ''status msg''&lt;br /&gt;
: '''[[ns_returnfile]]''' ''status type filename''&lt;br /&gt;
: '''[[ns_returnforbidden]]'''&lt;br /&gt;
: '''[[ns_returnfp]]''' ''status type fileid len''&lt;br /&gt;
: '''[[ns_returnnotfound]]'''&lt;br /&gt;
: '''[[ns_returnnotice]]''' ''status msg ?longmsg?''&lt;br /&gt;
: '''[[ns_returnredirect]]''' ''location''&lt;br /&gt;
: '''[[ns_returnunauthorized]]'''&lt;br /&gt;
: '''[[ns_write]]''' ''string''&lt;br /&gt;
&lt;br /&gt;
== DESCRIPTION ==&lt;br /&gt;
&lt;br /&gt;
These procedures provide a simple interface for returning information to the client. They build HTTP/1.0 headers and send the appropriate data out the socket to the client. The script does not end at the time ns_return* is invoked so you can continue processing data after the client has gotten the data and closed the socket.&lt;br /&gt;
&lt;br /&gt;
''type'' should be a MIME type (see [[ns_guesstype]] for a list). ''status'' is a three-digit number fitting the pattern below:&lt;br /&gt;
&lt;br /&gt;
: 1xx Informational - Not used, but reserved for future use.&lt;br /&gt;
: 2xx Success - The action was successfully received, understood, and accepted.&lt;br /&gt;
: 3xx Redirection - Further action must be taken in order to complete the request.&lt;br /&gt;
: 4xx Client Error - The request contains bad syntax or cannot be fulfilled.&lt;br /&gt;
: 5xx Server Error - The server failed to fulfill an apparently valid request.&lt;br /&gt;
&lt;br /&gt;
Some common status values and their meanings are:&lt;br /&gt;
&lt;br /&gt;
: 201 Created&lt;br /&gt;
: 202 Accepted&lt;br /&gt;
: 203 Provisional Information&lt;br /&gt;
: 204 No Content&lt;br /&gt;
: 300 Multiple Choices&lt;br /&gt;
: 301 Moved Permanently&lt;br /&gt;
: 302 Moved Temporarily&lt;br /&gt;
: 303 Method&lt;br /&gt;
: 304 Not Modified&lt;br /&gt;
: 401 Unauthorized&lt;br /&gt;
: 402 Payment Required&lt;br /&gt;
: 403 Forbidden&lt;br /&gt;
: 404 Not Found&lt;br /&gt;
: 405 Method Not Allowed&lt;br /&gt;
: 406 None Acceptable&lt;br /&gt;
: 407 Proxy Authentication Required&lt;br /&gt;
: 408 Request Time-out&lt;br /&gt;
: 409 Conflict&lt;br /&gt;
: 410 Gone&lt;br /&gt;
: 501 Not Implemented&lt;br /&gt;
: 502 Bad Gateway&lt;br /&gt;
: 503 Service Unavailable&lt;br /&gt;
: 504 Gateway Time-out&lt;br /&gt;
&lt;br /&gt;
; ns_connsendfp&lt;br /&gt;
: This function writes len bytes of the specified channel or file to the conn.&lt;br /&gt;
&lt;br /&gt;
; ns_return&lt;br /&gt;
: Sends back both the headers and the string.&lt;br /&gt;
&lt;br /&gt;
; ns_returnadminnotice&lt;br /&gt;
: Wraps the text msg and longmsg in some html, appends a line with a link to &amp;quot;mailto:serveradministrator&amp;quot; based on the virtual server parameter &amp;quot;WebMaster&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
; ns_returnbadrequest&lt;br /&gt;
: Returns a 400 status code and a formatted HTML message containing the reason text.&lt;br /&gt;
&lt;br /&gt;
; ns_returnerror&lt;br /&gt;
: Wraps the text msg in some html and returns that to the client.&lt;br /&gt;
&lt;br /&gt;
; ns_returnfile&lt;br /&gt;
: Sends back the headers and the contents of the file.  ns_returnfile uses fastpath internally, so care should be taken when using it to return dynamically generated files.&lt;br /&gt;
&lt;br /&gt;
; ns_returnforbidden&lt;br /&gt;
: Returns a 403 status code.&lt;br /&gt;
&lt;br /&gt;
; ns_returnfp&lt;br /&gt;
: First sends the appropriate headers. Next, it writes out the contents of file from the current file position until the end of the file.&lt;br /&gt;
&lt;br /&gt;
; ns_returnnotfound&lt;br /&gt;
: Returns a 404 status code.&lt;br /&gt;
&lt;br /&gt;
; ns_returnnotice&lt;br /&gt;
: Wraps the text msg and longmsg in some html and returns that to the client.&lt;br /&gt;
&lt;br /&gt;
; ns_returnredirect&lt;br /&gt;
: Returns a redirect to the passed in location&lt;br /&gt;
&lt;br /&gt;
; ns_returnunauthorized&lt;br /&gt;
: Returns a 401 status code&lt;br /&gt;
&lt;br /&gt;
; ns_write&lt;br /&gt;
: Writes the string out the connection. You can use it instead of the ns_return or ns_respond functions to build HTTP responses. AOLserver will not include the usual headers on the output data. The script does not end at the time ns_write* is invoked so you can continue processing data after the client has gotten the data and closed the socket.&lt;br /&gt;
&lt;br /&gt;
== SEE ALSO ==&lt;br /&gt;
&lt;br /&gt;
: [[ns_connsendfp]], [[ns_respond]], [[ns_returnadminnotice]], [[ns_returnbadrequest]], [[ns_returnerror]], [[ns_returnfile]], [[ns_returnforbidden]], [[ns_returnfp]], [[ns_returnnotfound]], [[ns_returnnotice]], [[ns_returnredirect]], [[ns_returnunauthorized]], [[ns_write]]&lt;br /&gt;
&lt;br /&gt;
__NOTOC__&lt;br /&gt;
[[Category:Documentation]]&lt;br /&gt;
[[Category:Core Tcl API]]&lt;/div&gt;</summary>
		<author><name>Jcr</name></author>
		
	</entry>
	<entry>
		<id>https://panoptic.com/mediawiki/aolserver/index.php?title=Ns_returnfile&amp;diff=5147</id>
		<title>Ns returnfile</title>
		<link rel="alternate" type="text/html" href="https://panoptic.com/mediawiki/aolserver/index.php?title=Ns_returnfile&amp;diff=5147"/>
		<updated>2008-08-18T23:53:57Z</updated>

		<summary type="html">&lt;p&gt;Jcr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; ns_returnfile 200 &amp;quot;application/zip&amp;quot; $filepath&lt;br /&gt;
 ns_returnfile 200 [ns_guesstype $file] $filepath&lt;br /&gt;
&lt;br /&gt;
ns_returnfile uses fastpath internally, so care should be taken when using it to return dynamically generated files.&lt;br /&gt;
&lt;br /&gt;
For now, see [[ns_return]]&lt;br /&gt;
&lt;br /&gt;
Want to name the file?&lt;br /&gt;
&lt;br /&gt;
ns_set update [ns_conn outputheaders] content-disposition &amp;quot;attachment; filename=1.abc&amp;quot;&lt;/div&gt;</summary>
		<author><name>Jcr</name></author>
		
	</entry>
	<entry>
		<id>https://panoptic.com/mediawiki/aolserver/index.php?title=AOLserver_Cookbook&amp;diff=5101</id>
		<title>AOLserver Cookbook</title>
		<link rel="alternate" type="text/html" href="https://panoptic.com/mediawiki/aolserver/index.php?title=AOLserver_Cookbook&amp;diff=5101"/>
		<updated>2007-09-29T21:59:54Z</updated>

		<summary type="html">&lt;p&gt;Jcr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A collection of questions, and code examples to answer them.&lt;br /&gt;
&lt;br /&gt;
Add your questions here.  Answers should be placed below the question.  Place a horizontal line (&amp;quot;----&amp;quot;) between questions.  Please keep this text before the first question.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Limiting bandwidth ==&lt;br /&gt;
&lt;br /&gt;
Is there a simple way to limit bandwidth per connection/ip???&lt;br /&gt;
&lt;br /&gt;
: There's no simple way of doing it, i.e., no configuration option you can set.  If I had to implement this, I'd use NSV's and [[ns_register_filter]] to keep track of bandwidth consumed by each client IP which can act as an all-or-nothing mechanism.  However, what might be interesting to implement in the socket driver is a setting to control the rate at which bytes are written back to the socket, perhaps configurable per request, so that large HTTP responses don't soak up your upstream bandwidth.  We should keep this in mind for a future version of AOLserver. ''-- [[User:Dossy|Dossy]] 20:06, 4 November 2005 (EST)''&lt;br /&gt;
&lt;br /&gt;
One more question... How can I read output buffer inside function registered as postauth filter?&lt;br /&gt;
And how can I stream it? ns_adp_puts cannot be used inside filters... ns_return would return all data at once. I assume that per connection limit would look like this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
proc ..... {&lt;br /&gt;
ns_adp_stream&lt;br /&gt;
set data [get output content buffer]&lt;br /&gt;
set data_length [output buffer size]&lt;br /&gt;
set block_size 4096&lt;br /&gt;
for {set i 0} {$i &amp;lt; $data_length} {incr i $block_size} {&lt;br /&gt;
   send_to_client [string range $data [expr $block_size*$i] [expr $block_size*[expr$i+1]]]&lt;br /&gt;
   sleep 1&lt;br /&gt;
}&lt;br /&gt;
ns_returnok&lt;br /&gt;
return filter_return&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
I want to limit only one vhost so nssock limit would be too much;)&lt;br /&gt;
&lt;br /&gt;
: First, you don't want to turn [[ns_adp_stream]]'ing on.  Getting the size of the ADP output buffer can be done using [[ns_adp_tell]] and getting the contents with [[ns_adp_dump]].  I guess you could [[ns_adp_trunc]] the output buffer to clear it, then slowly write the contents back using [[ns_write]].  You'd also then need to look at [[ns_conn]] '''outputheaders''' to make sure that you wrote the proper HTTP response ... ah, but I don't know if you can get the HTTP response status code somehow.  I still think doing it in nssock is probably the best place, even with vhosts -- I'd make it a preauth or postauth filter that sets the configuration for the response and then have nssock be responsible for ensuring the response is written at that rate. ''-- [[User:Dossy|Dossy]] 07:24, 8 November 2005 (EST)''&lt;br /&gt;
&lt;br /&gt;
ns_adp_tell inside postauth filter:&lt;br /&gt;
   Error: This function cannot be used outside of an ADP&lt;br /&gt;
what's more, i use ns_returnfile inside some adp code and if i use ns_adp_tell after it, it returns 0 (this adp only returns file, no adp_puts or write).&lt;br /&gt;
Unfortunetly i think there is no other solution then implement it inside nssock or implement some tcl code to manipulate all output buffer.&lt;br /&gt;
&lt;br /&gt;
I use this code for big files... some time I'll add per ip limit, now it's for connection.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
proc returnfile { file } {                                                      &lt;br /&gt;
    set filefp [open $file r]                                                   &lt;br /&gt;
    fconfigure $filefp -translation binary                                      &lt;br /&gt;
    set data_length [file size $file]                                           &lt;br /&gt;
    set block_size 4096                                                         &lt;br /&gt;
                                                                                &lt;br /&gt;
    ns_write &amp;quot;HTTP/1.0 200 OK                                                   &lt;br /&gt;
MIME-Version: 1.0                                                               &lt;br /&gt;
Content-Type: [ns_guesstype $file]                                              &lt;br /&gt;
Content-Length: $data_length                                                    &lt;br /&gt;
                                                                                &lt;br /&gt;
&amp;quot;                                                                               &lt;br /&gt;
    while { ! [eof $filefp] } {                                                 &lt;br /&gt;
        ns_writefp $filefp $block_size                                          &lt;br /&gt;
        ns_sleep 1                                                              &lt;br /&gt;
    }                                                                           &lt;br /&gt;
                                                                                &lt;br /&gt;
    ns_conn close                                                               &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Paul Bukowski&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Virtual server configuration ==&lt;br /&gt;
&lt;br /&gt;
Is it possible to use wildcard '*' in domain name inside &amp;quot;ns/module/nssock/servers&amp;quot; section of aolserver4 config file? I would like to map all requests to *.somedomain.org to one virtual host...&lt;br /&gt;
Something like this doesn't work:&lt;br /&gt;
&lt;br /&gt;
 ns_section &amp;quot;ns/module/nssock/servers&amp;quot;&lt;br /&gt;
 ns_param   forum           somedomain.org                                           &lt;br /&gt;
 ns_param   forum           somedomain.org:80                                        &lt;br /&gt;
 ns_param   forum           *.somedomain.org                                       &lt;br /&gt;
 ns_param   forum           *.somedomain.org:80&lt;br /&gt;
 ns_param   forum           &amp;quot;*.somedomain.org&amp;quot;                                       &lt;br /&gt;
 ns_param   forum           &amp;quot;*.somedomain.org:80&amp;quot;&lt;br /&gt;
&lt;br /&gt;
-Paul Bukowski&lt;br /&gt;
&lt;br /&gt;
: ''2005aug15 [[Dossy]]: Unfortunately, no -- you currently can't use wildcards the way you want.  Not yet, at least.''&lt;br /&gt;
&lt;br /&gt;
Why won't you get some code for mass virtual hosts from http://naviserver.sourceforge.net/ ??&lt;br /&gt;
-PB&lt;br /&gt;
&lt;br /&gt;
: Right now, to map a request to its (virtual) server, there's an O(n) search being done, but it's a &amp;quot;cheap&amp;quot; exact string comparison.  To implement glob-style wildcard support, it'll become a more expensive (but possibly still &amp;quot;cheap&amp;quot; by most people's standards) glob-match comparison.  When you're serving &amp;quot;n&amp;quot; requests per second (where &amp;quot;n&amp;quot; is small) the difference in cost is probably immeasurable, but when &amp;quot;n&amp;quot; is large, the cost is additive and possibly significant.  It might be good if someone could benchmark the two and see what the real cost is. ''-- [[User:Dossy|Dossy]] 20:12, 4 November 2005 (EST)''&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Server-side Includes ==&lt;br /&gt;
&lt;br /&gt;
Does anyone have some code to implement apache-compatible SSI (Server-side includes)?  I have some old pages that use SSI that I'd like to move to my aolserver install but I don't have the time to rewrite them as ADPs.&lt;br /&gt;
&lt;br /&gt;
: ''[[User:Dossy|Dossy]] 20:20, 4 November 2005 (EST)'': I make no representations or warranties about the safety (!) or correctness of the code I'm about to share, but it might get folks started on a proper implementation in the future.  In particular, I didn't implement any commands other than &amp;quot;include&amp;quot; and I even implemented it &amp;quot;wrong&amp;quot; (not according to [http://hoohoo.ncsa.uiuc.edu/docs/tutorials/includes.html the specification]).  If there's real interest in having a complete SSI implementation for AOLserver, I'd be willing to improve this code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ns_log Notice &amp;quot;ssi: registering SSI ADP tags&amp;quot;&lt;br /&gt;
&lt;br /&gt;
proc ssi_include_tag {params} {&lt;br /&gt;
        set param_count [ns_set size $params]&lt;br /&gt;
        for {set i 0} {$i &amp;lt; $param_count} {incr i} {&lt;br /&gt;
                set ssi_var_[ns_set key $params $i] [ns_set value $params $i]&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if [info exists ssi_var_file] {&lt;br /&gt;
                if {[ns_adp_argc] &amp;gt; 1} {&lt;br /&gt;
                        set basedir [lindex [ns_adp_argv] 1]&lt;br /&gt;
                } else {&lt;br /&gt;
                        set basedir [ns_adp_dir]&lt;br /&gt;
                }&lt;br /&gt;
                if [regexp {^/} $ssi_var_file] {&lt;br /&gt;
                        set filename $ssi_var_file&lt;br /&gt;
                } else {&lt;br /&gt;
                        set filename $basedir/$ssi_var_file&lt;br /&gt;
                }&lt;br /&gt;
                return [ns_adp_parse -file $filename $basedir]&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ns_register_adptag {!--#include} ssi_include_tag&lt;br /&gt;
&lt;br /&gt;
ns_log Notice &amp;quot;ssi: registering SSI ADP tags done&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
   &lt;br /&gt;
Is there a way to see only the errors (for example - 'variable' xxx not found? I seem to remember 2 logs - servername.log and servername-error.log?  The version I have now - aolserver 3.2/ad1.2 only seems to give us servername.log - and all the error messages are mixed with the normal msgs - its very hard to debug!&lt;br /&gt;
[[dannyl50]]&lt;br /&gt;
&lt;br /&gt;
The default/example config file did not have entries for both logs. The two sections you need look like (in old style notation): &lt;br /&gt;
&lt;br /&gt;
 [ns/parameters]&lt;br /&gt;
 User=nsadmin &lt;br /&gt;
 Group=nsadmin &lt;br /&gt;
 ServerLog=/var/log/aolserver/servername-error.log &lt;br /&gt;
 PidFile=/var/log/aolserver/nspid.servername&lt;br /&gt;
 Home=/usr/bin/aolserver-3.3ad13 &lt;br /&gt;
&lt;br /&gt;
and &lt;br /&gt;
&lt;br /&gt;
 [ns/server/servername/module/nslog]&lt;br /&gt;
 File=/var/log/aolserver/emp.log &lt;br /&gt;
 LogCombined=On &lt;br /&gt;
 MaxBackup=3 &lt;br /&gt;
 RollFmt=%Y-%m-%d-%H:%M &lt;br /&gt;
 RollHour=0 &lt;br /&gt;
 RollOnSignal=On &lt;br /&gt;
 RollLog=On&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Howdy!  Can someone tell me, in general terms, how they have implemented [[nsperm]]?  It looks cool, but I am using a plain old database with names and passwords, and it is very easy.  I would like the allow/deny functionality, can I have that without the username/password part? -- [[Ian Harding]]&lt;br /&gt;
&lt;br /&gt;
''I've implemented [[nsperm]] to restrict access to specific URLs using HTTP authentication (the username/password dialog) and cookie-based (if they have the correct cookie, otherwise URL redirect them to a login page that may set the cookie).''&lt;br /&gt;
''The latter is done using a registered preauth filter.  I chose to use [[nsperm]] over a database since [[nsperm]] (presumably) manages the authentication information in memory better than repeatedly hitting the database with authentication requests, but there's no reason''&lt;br /&gt;
''I couldn't have used a database to store username/password information.  Does this answer your question?'' -- [[Dossy]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pretty much, although I started writing my app before I understood AOLServer, so I have a rather strange design that is good in some ways, bad in others.  Keep in mind that this is a low activity app, no more than 20 concurrent users right now.  &lt;br /&gt;
&lt;br /&gt;
What I did was to create an [[ADP]] that has a big case statement.  It calls functions to generate pages based on the 'task' value it is passed through POST.  I have created a pretty complex app this way, not using [[ns_register_proc]] at all.  I know now I should have.  As I understand it, ns_register_proc lets you create a 'virtual' directory structure that actually just calls certain procedures based on the GET or POST requested URL.  This is far more graceful than hitting my main adp which opens up the form data, looks at the 'task' value, and decides which procedures to call.  &lt;br /&gt;
&lt;br /&gt;
Given this lame structure, each time someone requests the main adp, I just check for a valid cookie and generate a login page if it's not there.  After that, I have to set another cookie that is their 'access rights' which is then checked from within the procs that generate the pages.  If I was doing it right, I could have registered a proc that would fire for all URLs in my virtual tree, checking your rights to the particular URL you reqested, and redirecting you if you are not allowed, right?  &lt;br /&gt;
&lt;br /&gt;
Thanks!!! -- [[Ian Harding]]&lt;br /&gt;
&lt;br /&gt;
''I probably would've created an ADP per task, and then registered a preauth filter that checked for the cookie and redirected the user to the login page (outside the directory that the preauth filter covers''&lt;br /&gt;
''-- avoid funny redirection loops) if the cookie wasn't set properly.''&lt;br /&gt;
''If you don't want to create a separate ADP per task, you could have used ns_register_proc to create what you describe as &amp;quot;virtual pages&amp;quot; and still have the preauth filter kind of &amp;quot;sit in front&amp;quot; and handle the autehntication, keeping that logic seperate from your actual page generation code.'' -- [[Dossy]]&lt;br /&gt;
&lt;br /&gt;
I started with a separate adp for each task, but I thought it would get out of hand quickly.  I do think I will re-work the thing to use ns_register_proc and even do away with the few adp I do have.  It seems far easier to maintain.  In the meantime, I have to re-write all my SQL Server procedures in PostgreSQL PL/Tcl.  That's why I want the [[nsfreetds]] module so badly, it buys me a little time!&lt;br /&gt;
&lt;br /&gt;
Thanks for all your work! -- [[Ian Harding]]&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
''Speaking of [[nsfreetds]], did you try nsfreetds-0.1pre?  Any luck?  Any problems?'' -- [[Dossy]]&lt;br /&gt;
&lt;br /&gt;
I just now tried it.  I installed freetds with no trouble, compiled nsfreetds, modified my nsd.tcl [[config file]], added the datasource to interfaces, and all seems fine, except for that I always get &amp;quot;no access to pool &amp;quot;mypool&amp;quot; while executing &amp;quot;ns_db gethandle mypool&amp;quot; ...&amp;quot;&lt;br /&gt;
&lt;br /&gt;
I must have missed something.  I saw something in the README about setting $env(SYBASE) before starting nsd.  Is this the same as the SYBASE=/usr/pkg/freetds I had to do even before the build of nsfreetds?&lt;br /&gt;
&lt;br /&gt;
Thanks again... I feel like I am close.. -- [[Ian Harding]]&lt;br /&gt;
&lt;br /&gt;
''Yes, the $env(SYBASE) means setting the SYBASE environment variable.  To be safe, you can try this:''&lt;br /&gt;
&lt;br /&gt;
   $ cd /path/to/aolserver/install&lt;br /&gt;
   $ SYBASE=/usr/pkg/freetds; export SYBASE&lt;br /&gt;
   $ bin/nsd ...args...&lt;br /&gt;
&lt;br /&gt;
''Check log/server.log to make sure that the nsfreetds driver is actually loading.  You should see a lines like this at start-up:''&lt;br /&gt;
&lt;br /&gt;
   [30/May/2001:13:42:37][11838.1024][-main-] Notice: modload: loading '/home/aolserver-dev/bin/nsfreetds.so'&lt;br /&gt;
   [30/May/2001:13:42:37][11838.1024][-main-] Notice: Ns_FreeTDS_DriverInit(freetds):  Loaded Panoptic FreeTDS Driver v0.1-pre, built on May 21 2001 at 22:23:01.&lt;br /&gt;
&lt;br /&gt;
''Are you getting an error in the [[server log]] instead?'' -- [[Dossy]]&lt;br /&gt;
&lt;br /&gt;
I don't get an error, it seems to load nicely.  I can post or give you access to whatever files or output you would like to see, or an ssh login... -- [[Ian Harding]]&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Another question:  Global variables ([[nsv]]*).  I am re-writing my app to use the [[ns_register_proc]] functionality versus my kludge where everything goes through an [[ADP]] that acts as a filter and traffic cop.  I have figured out register filter and register proc, but seem not to be able to use [[ns_puts]] from within the procs.  Is this right?  Anyway, I had been using [[ns_adp_include]] in my filter/traffic cop page to put consistent headers/footers on my pages.  I gather the more correct way (and only possible way with registered procs?) is to use global variables.  &lt;br /&gt;
&lt;br /&gt;
When do I initialize them?  How do I use them?  What are the caveats? W&lt;br /&gt;
&lt;br /&gt;
Thanks, -- [[Ian Harding]]&lt;br /&gt;
&lt;br /&gt;
''Have you started by reading the NSV documentation?'' -- [[Dossy]]&lt;br /&gt;
&lt;br /&gt;
Of course not 8^0  That would be too easy!  I will... -- [[Ian Harding]]&lt;br /&gt;
&lt;br /&gt;
OK, I read it.  It's too easy.  I use it for header, footer, and client side script html, which I stuff into html variable before returning it.  I would like the filter option we talked about in the chat which would prepend or append html automatically, but this will do. -- [[Ian Harding]]&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
How hard would it be to add an HTTPS equivalent of Ns_FetchURL?&lt;br /&gt;
&lt;br /&gt;
''If you can build shared libraries on your target platform with OpenSSL, it probably wouldn't be too hard.  The trick would be writing enough stub code that can be loaded via the Tcl &amp;quot;load&amp;quot; proc so that you could access the OpenSSL-based https client from your Tcl code.  Is there a lot of demand for this?  I could probably bang something out as an initial attempt.'' -- [[Dossy]]&lt;br /&gt;
&lt;br /&gt;
[[Scott Goodwin]]'s [[nsopenssl]] now contains client side https functionality.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Am I a brick, or does ns_register_proc just plain not work with more than one argument for the proc?  I have tried the following code on both aolserver 3.2 running on NT4 and aolserver 3.4 on NetBSD 1.5.  It fails to register the proc even once, if I try to register it with more than one argument anywhere else.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 ns_register_proc GET /foo1 foo 1&lt;br /&gt;
 ns_register_proc GET /foo2 foo 1 2&lt;br /&gt;
 ns_register_proc GET /foo3 foo 1 2 3&lt;br /&gt;
&lt;br /&gt;
 proc foo { conn one {two 22} {three 333}} {&lt;br /&gt;
 ns_return 200 text/html &amp;quot;one is $one, two is $two, three is $three&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This must be something simple.  I have already posted to the aolserver list but the listserv seems to have gone mad.&lt;br /&gt;
&lt;br /&gt;
[[Ian Harding]]&lt;br /&gt;
&lt;br /&gt;
''What are you trying to do?  It appears you want to pass constant parameters to your procedures.  If they are constants, why pass them?  Since ns_register_proc calls are generally in the global scope (and sourced when nsd starts) even a parameter that appears to be a variable probably can/will not vary.''&lt;br /&gt;
&lt;br /&gt;
''Presumably you need to get information from one page to another.  That means formvalues unless your page is stateful (usually a bad idea).  Check out the '''[[ns_conn]] form''' command to get yourself started.''  -- [[Jason Kane]]&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
OK, I'm using Windows 2000 SP2 and 3.4.1, and trying in vain to get Perl CGIs (legacy) to work.  The scripts work outside of Aolserver, and work on AOLserver on Linux, but when I try inside the script to GET from myself (eg, GET http://localhost:8000/foo?bar=bas), I'm told &amp;quot;unknown protocol TCP&amp;quot;, which is quite aggravating.&lt;br /&gt;
&lt;br /&gt;
Does anyone have any experience administering AOLServer on Windows?&lt;br /&gt;
&lt;br /&gt;
Thanks in advance!&lt;br /&gt;
&lt;br /&gt;
-Bill&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
This is interesting, wy do you let me change your page?&lt;br /&gt;
I'm trying to find an example of how to get my data using:&lt;br /&gt;
 set formdata [ns_conn form $conn]&lt;br /&gt;
&lt;br /&gt;
-Jason&lt;br /&gt;
&lt;br /&gt;
Because it's a wiki!  A proc that gets posted variables includes the line you wrote there... then when you want to actually get the values, you can use something like &lt;br /&gt;
&lt;br /&gt;
 set myvar [ns_set get $formdata myvar]&lt;br /&gt;
&lt;br /&gt;
where myvar is the name of the variable.  There is also ns_queryget which looks like&lt;br /&gt;
&lt;br /&gt;
 set myvar [ns_queryget myvar defaultval]&lt;br /&gt;
&lt;br /&gt;
This is handy because if there is no value, it will assign a default value.  &lt;br /&gt;
&lt;br /&gt;
Check out aolserver.com, they have extensive (although sometimes misleading) docs.  If something the docs says should work doesn't, ask.  It may be out of date.&lt;br /&gt;
&lt;br /&gt;
[[Ian Harding]]&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
I don't know where else to share my code fragments, so here seems like as good a place as any.  This one implements user public_html directories. It's based on someone else's stuff (I forget whose tho).  It should really do something with unknown mime types, and should do a better job with errors like unknown users.  It does honor directoryFile and adp maps in the config file.&lt;br /&gt;
&lt;br /&gt;
It works by registering a procedure to /users that interprets the username and finds their directory.  ns_register_proc doesn't allow wildcards other than in the last path element, so /~*  wouldn't work.  However that's not a problem for a filter, so there's a filter to take your /~user url and redirect it to /users/user&lt;br /&gt;
&lt;br /&gt;
-JR&lt;br /&gt;
&lt;br /&gt;
 proc homedir { conn ctx } {&lt;br /&gt;
   set url [ns_conn url $conn]&lt;br /&gt;
   set user {}&lt;br /&gt;
   set file {}&lt;br /&gt;
   regexp {^/users/([^/]*)(/.*)?$} $url dummy user file&lt;br /&gt;
   # ns_returnnotice 200 &amp;quot;url is $url user is $user, file is $file&amp;quot;&lt;br /&gt;
   set userfile [getUserFile $user $file]&lt;br /&gt;
   set type [ns_guesstype $userfile]&lt;br /&gt;
   if {[string match &amp;quot;*[ns_config ns/server/[ns_info server]]/adp map]&amp;quot; $userfile]} {&lt;br /&gt;
     # ns_log notice &amp;quot;adp parsing $userfile&amp;quot;&lt;br /&gt;
     set cwd [pwd]&lt;br /&gt;
     cd [file dirname $userfile]&lt;br /&gt;
     # ns_return 200 text/html [ns_adp_parse -file $userfile]&lt;br /&gt;
     set result [catch {ns_adp_parse -file $userfile} error]&lt;br /&gt;
     if {$result} {&lt;br /&gt;
       ns_return 200 text/html $error&lt;br /&gt;
     } else {&lt;br /&gt;
       ns_return 200 text/html $error&lt;br /&gt;
     }&lt;br /&gt;
     cd $cwd&lt;br /&gt;
   } else {&lt;br /&gt;
     switch $type {&lt;br /&gt;
       &amp;quot;*/*&amp;quot; {&lt;br /&gt;
       }&lt;br /&gt;
       default {&lt;br /&gt;
        ns_returnfile 200 $type $userfile&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
       &lt;br /&gt;
   if {[catch {set fp [open $userfile]}]} {&lt;br /&gt;
     ns_returnnotfound&lt;br /&gt;
     return&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 proc getUserFile {user path} {&lt;br /&gt;
   foreach tail [split ,[ns_config ns/server/[ns_info server] directoryfile] ,] {&lt;br /&gt;
     set userfile &amp;quot;[glob ~$user]/public_html$path$tail&amp;quot;&lt;br /&gt;
     if {[file exists $userfile] &amp;amp;&amp;amp; ![file isdirectory $userfile]} {&lt;br /&gt;
       return $userfile&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   ns_returnnotfound&lt;br /&gt;
   # break&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 ns_register_proc GET /users/ homedir&lt;br /&gt;
 ns_register_proc POST /users/ homedir&lt;br /&gt;
 ns_register_proc HEAD /users/ homedir&lt;br /&gt;
 &lt;br /&gt;
 proc userRedir {conn arg why} {&lt;br /&gt;
   set url [ns_conn url]&lt;br /&gt;
   regsub {^/~(.*)} $url {/users/\1} redir&lt;br /&gt;
   ns_log notice &amp;quot;url is $url, redir is $redir&amp;quot;&lt;br /&gt;
   ns_returnredirect $redir&lt;br /&gt;
   return filter_break&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 ns_register_filter preauth GET /~* userRedir&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Hi!&lt;br /&gt;
&lt;br /&gt;
Does anybody know a graphing module for Aolserver/TCL, with e.g. bargraphs, linegraphs,... ?&lt;br /&gt;
&lt;br /&gt;
-[[wiwo]]&lt;br /&gt;
&lt;br /&gt;
''Yes: [[nsgds]], [[nschartdir]].''&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Can I detect if the user pushes the Stop button in their browser in my TCL/ADP page?&lt;br /&gt;
&lt;br /&gt;
Yes, although it's a kludge. ns_write will return zero if it cannot write because the connection has been lost. However, ns_write is not stupid enough to try writing when you give it nothing to write, and so you must send something to the client. To prevent this being rendered use HTML comments, e.g.&lt;br /&gt;
&lt;br /&gt;
 if {[ns_write &amp;quot;&amp;lt;nowiki&amp;gt;&amp;lt;!-- STOP DETECTOR --&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;quot;] == 0} {&lt;br /&gt;
     # user hit the stop button, browser page was closed, or connection to client was lost.&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
[[Ximon Eighteen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Generating random passwords ==&lt;br /&gt;
&lt;br /&gt;
The following method can be useful to generate random passwords and/or password salts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 # desired length of random string&lt;br /&gt;
  set iStringLength 8&lt;br /&gt;
&lt;br /&gt;
 # characters allowed to appear in the string&lt;br /&gt;
  set sAllowableCharacters &amp;quot;0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 # get length one time&lt;br /&gt;
  set iAllowableCharacters [string length $sAllowableCharacters]&lt;br /&gt;
&lt;br /&gt;
 # begin random string as empty&lt;br /&gt;
  set sRandomString &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 # loop until desired length is achieved&lt;br /&gt;
  for {set ii 0} {$ii &amp;lt; $iStringLength} {incr ii} {&lt;br /&gt;
&lt;br /&gt;
   # get next random between 0 and length of allowed characters&lt;br /&gt;
    set iRandomInt [ns_rand $iAllowableCharacters]&lt;br /&gt;
&lt;br /&gt;
   # retrieve this random character&lt;br /&gt;
    set sRandomCharacter [string index $sAllowableCharacters $iRandomInt]&lt;br /&gt;
&lt;br /&gt;
   # append the character to our random string&lt;br /&gt;
    append sRandomString $sRandomCharacter&lt;br /&gt;
&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  ns_adp_puts &amp;quot;sRandomString: $sRandomString&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Customizing error pages ==&lt;br /&gt;
&lt;br /&gt;
Edit your AOLServer's config file, and add the paths to the error pages as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
# Internal redirects&lt;br /&gt;
#&lt;br /&gt;
ns_section &amp;quot;ns/server/${servername}/redirects&amp;quot;&lt;br /&gt;
ns_param   404 &amp;quot;/notfound.html&amp;quot;      ;# Not Found error page&lt;br /&gt;
ns_param   500 &amp;quot;/servererror.html&amp;quot;   ;# Server Error page&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
---&lt;br /&gt;
&lt;br /&gt;
== Fast caching of generated pages ==&lt;br /&gt;
&lt;br /&gt;
You can use an adp page to handle a 404 (not found) error that generated exactly the page it was looking for.  Conceptually this is similar to how tcl's autoloading using unknown works.  From Bas Sheffers, via John Buckman.&lt;br /&gt;
&lt;br /&gt;
from config.tcl:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ns_section &amp;quot;ns/server/$server1/redirects&amp;quot;&lt;br /&gt;
ns_param   404           /404.adp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
404.adp:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;% handle_404 %&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Support procs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
proc handle_404 {} {&lt;br /&gt;
    set myurl [myurl]&lt;br /&gt;
    set parts [split $myurl /]&lt;br /&gt;
    set root [lindex $parts 1]&lt;br /&gt;
&lt;br /&gt;
    if {$root == &amp;quot;photo&amp;quot;} {&lt;br /&gt;
        return [404_photo $parts]&lt;br /&gt;
    } else {&lt;br /&gt;
        ns_returnredirect &amp;quot;[myhost]/&amp;quot;&lt;br /&gt;
        return&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
proc 404_photo {parts} {&lt;br /&gt;
    &lt;br /&gt;
    set userid [file rootname [lindex $parts 2]]&lt;br /&gt;
    set d [user_photo_data $userid]&lt;br /&gt;
    if {$d == &amp;quot;&amp;quot;} {&lt;br /&gt;
        set fn &amp;quot;/b/photo/unknown.jpg&amp;quot;&lt;br /&gt;
    } else {&lt;br /&gt;
        set fn &amp;quot;/b/photo/${userid}.jpg&amp;quot;&lt;br /&gt;
        write_binary_file $fn $d&lt;br /&gt;
    }&lt;br /&gt;
    ns_returnfile 200 &amp;quot;image/jpeg&amp;quot; $fn&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
proc myurl {} {&lt;br /&gt;
    return [lindex [split [ns_conn request]] 1]   &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
proc photo_cache_dirty {userid} {&lt;br /&gt;
    set fn &amp;quot;/b/photo/${userid}.jpg&amp;quot;&lt;br /&gt;
    file delete $fn&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jcr</name></author>
		
	</entry>
	<entry>
		<id>https://panoptic.com/mediawiki/aolserver/index.php?title=Ns_adp_safeeval&amp;diff=5099</id>
		<title>Ns adp safeeval</title>
		<link rel="alternate" type="text/html" href="https://panoptic.com/mediawiki/aolserver/index.php?title=Ns_adp_safeeval&amp;diff=5099"/>
		<updated>2007-09-24T19:33:45Z</updated>

		<summary type="html">&lt;p&gt;Jcr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''NAME'''&lt;br /&gt;
&lt;br /&gt;
:  ns_adp_safeeval - Safely evaluate an ADP block&lt;br /&gt;
&lt;br /&gt;
'''SYNOPSIS'''&lt;br /&gt;
&lt;br /&gt;
: '''ns_adp_safeeval''' ''page ?args ...?''&lt;br /&gt;
&lt;br /&gt;
'''DESCRIPTION'''&lt;br /&gt;
&lt;br /&gt;
: This function evaluates the ADP specified by ''page'' just as [[ns_adp_eval]] does, except that it ignores inline scripts &amp;quot;&amp;lt;% ... %&amp;gt;&amp;quot;;  only adp registered tags are executed.  This is useful for providing a limited execution environment for untrusted code (such as user-created templates) without allowing potentially damaging code to run on the server.&lt;br /&gt;
&lt;br /&gt;
'''EXAMPLES'''&lt;br /&gt;
&lt;br /&gt;
'''SEE ALSO'''&lt;br /&gt;
&lt;br /&gt;
: [[ns_adp_abort]], [[ns_adp_append]], [[ns_adp_argc]], [[ns_adp_argv]], [[ns_adp_bind_args]], [[ns_adp_break]], [[ns_adp_debug]], [[ns_adp_debuginit]], [[ns_adp_dir]], [[ns_adp_dump]], [[ns_adp_exception]], [[ns_adp_include]], [[ns_adp_mime]], [[ns_adp_mimetype]], [[ns_adp_parse]], [[ns_adp_puts]], [[ns_adp_registeradp]], [[ns_adp_registerproc]], [[ns_adp_registertag]], [[ns_adp_return]], [[ns_adp_safeeval]], [[ns_adp_stats]], [[ns_adp_stream]], [[ns_adp_tell]], [[ns_adp_trunc]]&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[Category Documentation]] - [[Category Core Tcl API]]&lt;/div&gt;</summary>
		<author><name>Jcr</name></author>
		
	</entry>
	<entry>
		<id>https://panoptic.com/mediawiki/aolserver/index.php?title=Ns_adp_parse&amp;diff=5098</id>
		<title>Ns adp parse</title>
		<link rel="alternate" type="text/html" href="https://panoptic.com/mediawiki/aolserver/index.php?title=Ns_adp_parse&amp;diff=5098"/>
		<updated>2007-09-24T19:28:18Z</updated>

		<summary type="html">&lt;p&gt;Jcr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Man page: http://aolserver.com/docs/tcl/ns_adp_parse.html&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
'''NAME'''&lt;br /&gt;
&lt;br /&gt;
: ns_adp_parse - Parse an ADP file or string and return its output&lt;br /&gt;
&lt;br /&gt;
'''SYNOPSIS'''&lt;br /&gt;
&lt;br /&gt;
: '''ns_adp_parse''' ''?-file|-string? ?-safe? arg ?arg ...?''&lt;br /&gt;
&lt;br /&gt;
'''DESCRIPTION'''&lt;br /&gt;
&lt;br /&gt;
: This command processes an ADP from either a file or a string, returning the output.  The first ''arg'' specifies the filename or contains the string to parse, depending on ''-file'' or ''-string''.&lt;br /&gt;
&lt;br /&gt;
: If you need to process a second ADP from inside an ADP, it is usually better to use [[ns_adp_include]], because that command resolves relative pathnames passed to it.  Also note that '''ns_adp_parse''' will ignore any directives to turn on streaming.  Tcl_Eval() is used to evaluate the Tcl commands in the ADP. &lt;br /&gt;
&lt;br /&gt;
: If you use the ''-string'' syntax, then ''arg'' is a string containing ADP syntax to be parsed.  Note that when you call this command with the ''-string'' syntax from inside an ADP, the string cannot contain the &amp;quot;&amp;lt;% ... %&amp;gt;&amp;quot; syntax.  The ''-string'' syntax is the default.&lt;br /&gt;
&lt;br /&gt;
: If you use the ''-file'' syntax, then ''arg'' is the absolute path to the file containing the ADP to be parsed.&lt;br /&gt;
&lt;br /&gt;
: If you specify the ''-safe'' flag, then only registered tags are executed; inline scripts using &amp;quot;&amp;lt;% ... %&amp;gt;&amp;quot; or &amp;quot;&amp;lt;%= ... %&amp;gt;&amp;quot; are ignored.  &lt;br /&gt;
&lt;br /&gt;
: You can pass optional arguments to the ADP.  The arguments can be accessed within the ADP using the [[ns_adp_argc]], [[ns_adp_argv]] and [[ns_adp_bind_args]] commands.&lt;br /&gt;
&lt;br /&gt;
: If this call is a nested ADP evaluation (where one ADP calls another), an error will be thrown if the depth exceeds 256, the maximum number of nested ADP evaluations. &lt;br /&gt;
&lt;br /&gt;
'''EXAMPLES'''&lt;br /&gt;
&lt;br /&gt;
    % ns_adp_parse -string {&amp;lt;% return [[expr 2 + 2]] %&amp;gt;}&lt;br /&gt;
    4&lt;br /&gt;
&lt;br /&gt;
    % ns_adp_parse -file [[ns_info pageroot]]/index.adp&lt;br /&gt;
    ... output of index.adp ...&lt;br /&gt;
&lt;br /&gt;
'''SEE ALSO'''&lt;br /&gt;
&lt;br /&gt;
: [[ns_adp_abort]], [[ns_adp_append]], [[ns_adp_argc]], [[ns_adp_argv]], [[ns_adp_bind_args]], [[ns_adp_break]], [[ns_adp_debug]], [[ns_adp_debuginit]], [[ns_adp_dir]], [[ns_adp_dump]], [[ns_adp_eval]], [[ns_adp_exception]], [[ns_adp_include]], [[ns_adp_mime]], [[ns_adp_mimetype]], [[ns_adp_puts]], [[ns_adp_registeradp]], [[ns_adp_registerproc]], [[ns_adp_registertag]], [[ns_adp_return]], [[ns_adp_safeeval]], [[ns_adp_stats]], [[ns_adp_stream]], [[ns_adp_tell]], [[ns_adp_trunc]]&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[Category Documentation]] - [[Category Core Tcl API]]&lt;/div&gt;</summary>
		<author><name>Jcr</name></author>
		
	</entry>
	<entry>
		<id>https://panoptic.com/mediawiki/aolserver/index.php?title=TDOM&amp;diff=5054</id>
		<title>TDOM</title>
		<link rel="alternate" type="text/html" href="https://panoptic.com/mediawiki/aolserver/index.php?title=TDOM&amp;diff=5054"/>
		<updated>2007-03-20T01:45:08Z</updated>

		<summary type="html">&lt;p&gt;Jcr: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Documentation is available at http://www.tdom.org/doc-index.html&lt;br /&gt;
&lt;br /&gt;
A very helpful tutorial is available at http://wiki.tcl.tk/8984&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[Dossy]]: [http://www.mail-archive.com/aolserver@listserv.aol.com/msg06871.html Assigning a prefix to the default namespace when using XPath in tDOM]&lt;br /&gt;
&lt;br /&gt;
I don't know how many folks are using tDOM but I'm sure more and more&lt;br /&gt;
are.  I keep stumbling into this problem of trying to access child nodes&lt;br /&gt;
which are in the default namespace but the parent is in a named&lt;br /&gt;
namespace ... and trying to write XPath expressions start to look really&lt;br /&gt;
dog-awful, like:&lt;br /&gt;
&lt;br /&gt;
    $root selectNodes {/*[local-name()='foo']/*[local-name()='bar']/...}&lt;br /&gt;
&lt;br /&gt;
So, I sat down for a few minutes and thought about the problem, and&lt;br /&gt;
after some head-scratching, it hit me: name the default namespace.  Duh.&lt;br /&gt;
So, here's some sample code:&lt;br /&gt;
&lt;br /&gt;
    ### IMPORTANT: This code lets us get at nodes with a null prefix.&lt;br /&gt;
    if {[$root hasAttribute xmlns]} {&lt;br /&gt;
        $root setAttributeNS &amp;quot;&amp;quot; xmlns:default [$root getAttribute xmlns]&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
So, now, I can rewrite that XPath expression above:&lt;br /&gt;
&lt;br /&gt;
    $root selectNodes /default:foo/default:bar/...&lt;br /&gt;
&lt;br /&gt;
Man.  Life just couldn't get any better.&lt;br /&gt;
&lt;br /&gt;
If any of you are wondering why this matters, here's a sample XML doc&lt;br /&gt;
and some sample code illustrating the beauty:&lt;br /&gt;
&lt;br /&gt;
    set xml {&lt;br /&gt;
        &amp;lt;aaa:duh xmlns=&amp;quot;booboo&amp;quot; xmlns:aaa=&amp;quot;blort&amp;quot;&amp;gt;&lt;br /&gt;
            &amp;lt;foo&amp;gt;&lt;br /&gt;
                &amp;lt;bar&amp;gt;some text&amp;lt;/bar&amp;gt;&lt;br /&gt;
            &amp;lt;/foo&amp;gt;&lt;br /&gt;
        &amp;lt;/aaa:duh&amp;gt;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    $doc [dom parse $xml]&lt;br /&gt;
    set root [$doc documentElement]&lt;br /&gt;
&lt;br /&gt;
Suppose you want to get the text node inside &amp;lt;bar&amp;gt; with an absolute&lt;br /&gt;
XPath expression.  You might think you could write:&lt;br /&gt;
&lt;br /&gt;
    [$root selectNodes /aaa:duh/foo/bar] text&lt;br /&gt;
&lt;br /&gt;
Ah, but XPath *SPANKS* us and tells us we're naughty, that &amp;lt;foo&amp;gt; and&lt;br /&gt;
&amp;lt;bar&amp;gt; have a null prefix and live in the unnamed namespace.  That line&lt;br /&gt;
of code returns an empty string, not &amp;quot;some text&amp;quot; as we might have&lt;br /&gt;
expected.  So, we tell XPath &amp;quot;well, how about you do me a favor and&lt;br /&gt;
pretend like any node in the unnamed namespace really has a name of my&lt;br /&gt;
choosing ...&amp;quot; by doing this:&lt;br /&gt;
&lt;br /&gt;
    $root setAttributeNS &amp;quot;&amp;quot; xmlns:default [$root getAttribute xmlns]&lt;br /&gt;
&lt;br /&gt;
We're telling the processor to name all nodes in the default namespace&lt;br /&gt;
as though they were in the namespace named &amp;quot;default&amp;quot;.  N.B.:  If your&lt;br /&gt;
XML document really *HAS* a namespace named &amp;quot;default&amp;quot;, this code will&lt;br /&gt;
likely CLOBBER it and give you really weird behavior.  Change&lt;br /&gt;
&amp;quot;xmlns:default&amp;quot; in the above line to a namespace that won't ever exist&lt;br /&gt;
in your document, then.&lt;br /&gt;
&lt;br /&gt;
Now that we've done this, lets rewrite that XPath expression and try&lt;br /&gt;
again:&lt;br /&gt;
&lt;br /&gt;
    [$root selectNodes /aaa:duh/default:foo/default:bar] text&lt;br /&gt;
&lt;br /&gt;
Ahh!  It returned the string &amp;quot;some text&amp;quot; -- exactly what we wanted.&lt;br /&gt;
Notice the injection of &amp;quot;default:&amp;quot; above before &amp;quot;foo&amp;quot; and &amp;quot;bar&amp;quot; -- since&lt;br /&gt;
we just told the processor that nodes in the unnamed namespace (i.e.,&lt;br /&gt;
&amp;lt;foo&amp;gt; and &amp;lt;bar&amp;gt;) now live in the namespace named &amp;quot;default&amp;quot;, in order to&lt;br /&gt;
specify them in an XPath expression, we need to say &amp;quot;default:foo&amp;quot; and&lt;br /&gt;
&amp;quot;default:bar&amp;quot;.  But this is a hell of a lot easier to read than&lt;br /&gt;
&amp;quot;*[local-name()='foo']&amp;quot; and &amp;quot;*[local-name()='bar']&amp;quot;, at least on my&lt;br /&gt;
eyes.&lt;br /&gt;
&lt;br /&gt;
If this is all old news, feel free to ignore this email.  I hadn't seen&lt;br /&gt;
it documented anywhere and I know I've puzzled over this for at least an&lt;br /&gt;
hour or two over the past few months, so maybe this write-up might save&lt;br /&gt;
a few people the same agony.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
While the above code generally works, the explanation is slightly incorrect.&lt;br /&gt;
It is not naming the the default namespace, is is binding a known&lt;br /&gt;
prefix to the uri of the default namespace, which it looks up.  An xml namespace&lt;br /&gt;
is not the (possibly null) prefix; is is the uri to which the prefix is bound.&lt;br /&gt;
In particular, to match nodes, the prefixes need not match, but the namespace uris&lt;br /&gt;
must.  Plain xml obscures this to a certain extent, but xpath makes it painfully&lt;br /&gt;
clear.&lt;br /&gt;
&lt;br /&gt;
The right thing to do is to always know what namespace uris are being used&lt;br /&gt;
in the document, and assign known prefixes to all of them rather than to rely on&lt;br /&gt;
the context node having all the needed (and convenient) bindings.&lt;br /&gt;
&lt;br /&gt;
Note too that the above code will be of no help if the null prefix is assigned&lt;br /&gt;
or changed in a child of the context node.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[[Category:Modules]]&lt;/div&gt;</summary>
		<author><name>Jcr</name></author>
		
	</entry>
</feed>