# Currently this is for AOLserver 4.0 and later # and requires the am_attributes2set C module # if <%@ Directive ...> syntax is to be used # Warning: defines a proc named just @ # Detailed write up and latest version at: # http://aolserver.am.net/code/modules/masterpages.adpx # Master Pages Operation: # ----------------------- # - Optional: declare start of contentBlock (either fancy tag or just <% am_adp_content start %>) # This would truncate the buffer discarding any content in it - this is useful within the head to # discard the opening html, head, title, etc. tags and after the ) # (the code block can override the idstring - i.e. it can determine where it should be poured into) # This dumps out the current adp buffer (i.e. our content block) into a global array variable with the # idstring as the key and truncates it. Last end declaration should be before closing /body and /html tags. # # - Required: after the closing /body and /html tags but before any client-side script you wish # to be the very last thing to run, declare to output via a particular master page optionally # with whatever parameters that it'll get as args. This would truncate the buffer which would drop # the /body & /html closing tags to keep both master and content pages legal html. # Once all the includes are done, adp processing returns to the original content page, and finishes # parsing any post /html (from the top-most master) <%@ ContentStart%>

Hello, visitor from <%=[ns_conn peerip]%>. Master Pages are cool!

<%@ ContentEnd ContentPlaceHolderId="$mainid"%> <% am_adp_content setcurrentid LastModified # mtime in ns_adp_stats is some date from two years ago set file [file join [ns_adp_dir] [ns_adp_argv 0]] ns_adp_puts "This file was last modified on [clock format [file mtime $file]]" am_adp_content end %> <%@ IncludeInto MasterPageFile="$masterpage"%> <% global pagetitle if {![info exists pagetitle]} {set pagetitle "Master Page"} am_tagAttributes append BODY onload "SiteWideOnloadHandler();" %> My Site | <%=$pagetitle%> <%=[am_adp_content get head]%> >

This is the master page.

Main Content Block goes here <%@ ContentPlaceHolder id="LastModified"%>
My Site | My Page

This is the master page.

Hello, visitor from 206.176.224.5. Master Pages are cool!

This page was last modified on Wed Nov 16 2:48:22 AM Pacific Standard Time 2005
} if {[ns_info version] >= 4.0} { catch {ns_register_adptag adp:includeinto am_adp_directive_includeinto} catch {ns_register_adptag adp:contentstart am_adp_directive_contentstart} catch {ns_register_adptag adp:contentend am_adp_directive_contentend} catch {ns_register_adptag adp:contentplaceholder /adp:contentplaceholder am_adp_directive_contentplaceholder} proc @ {directive args} { # A wrapper that allows fancy tag procs named am_adp_directive_$directive # to be invoked using ASP.NET-style directives: <%@ Directive attribute1=value1 %> # Note that space after @ is required but between <% and @, space is optional. # Fancy tags that take string + arguments (instead of just arguments) # are supported but string will always be "". # set string "" set proc "am_adp_directive_[string tolower $directive]" if {[llength [info args $proc]] > 1} { set string [list ""] } ns_adp_puts -nonewline [eval $proc $string [am_attributes2set [join $args]]] } proc am_adp_directive_includeinto {attributes} { # <%@ IncludeInto MasterPageFile=filename %> OR # If onlycontentid querystring/formfield is present and not blank, # don't pour into master page and output only the requested content block # Use ?onlycontentid=%20& (must have the trailing & when used in a query string) # to reference the unnamed content block. # If you need to manually ns_adp_parse a content page and have it return just # one content block, do this prior to ns_adp_parsing: # am_set iupdate [ns_getform] onlycontentid contentPlaceHolderId # ns_adp_trunc if {[string equal "" [set contentid [ns_queryget onlycontentid]]]} { eval ns_adp_include [list [string trimright [ns_set iget $attributes masterpagefile] /]] [ns_set array $attributes] attributes $attributes return "" } else { return [am_adp_content get [string trim [ns_urldecode $contentid]]] } } proc am_adp_directive_contentstart {attributes} { # <%@ ContentStart ContentPlaceHolderId=id %> OR am_adp_content start [string trimright [ns_set iget $attributes contentplaceholderid] /] return "" } proc am_adp_directive_contentend {attributes} { # <%@ ContentEnd ContentPlaceHolderId=id %> OR am_adp_content end [string trimright [ns_set iget $attributes contentplaceholderid] /] return "" } proc am_adp_directive_contentplaceholder {defaultContent attributes} { # <%@ ContentPlaceHolder id=id %> OR # defaultContent set content [am_adp_content get [string trimright [ns_set iget $attributes id] /]] if {[string equal " " $content]} { set content $defaultContent } return $content } proc am_adp_content {option {contentplaceholderid ""} {content ""}} { # # Last Modified: 2007-07-07 # Last Modified By: Alex Hisen # Original Author: Alex Hisen # # Implements content block handling to enable master pages. # # We allow contentplaceholderid to be blank in am_adp_content start # and for the id to be specified with am_adp_content end or # am_adp_content setcurrentid or not to have an id at all. # contentPlaceHolderId is case-sensitive! # (ids and class names are supposed to be case-sensitive per HTML 4.01 spec) # option is not case-sensitive. # # am_adp_content start ?contentPlaceHolderId? # Truncates/discards the current adp buffer # Also optionally sets the intended contentplaceholderid in # the master page for the content block about to start. # Using start is optional and is only needed to discard # redundant html, body, etc. tags that are in the page # just to keep it as legal html. # # am_adp_content end ?contentPlaceHolderId? # Stores the current adp buffer as a content block, # then truncates the buffer. The supplied id of the content block # (which determines which placeholder it will be placed into) # is used ONLY if the id has not already been set with either # am_adp_content start (or <%@ ContentStart / > # global am_tagAttributes switch $option { set { if {![info exists am_tagAttributes($tag)]} { set am_tagAttributes($tag) [ns_set create $tag] } am_set iupdate [set am_tagAttributes($tag)] $attribute $value } append { if {![info exists am_tagAttributes($tag)]} { set am_tagAttributes($tag) [ns_set create $tag] } return [am_set iappend [set am_tagAttributes($tag)] $attribute $value $separator] } get { if {![info exists am_tagAttributes($tag)]} { return $value } if {[string equal "" $attribute]} { return [am_set2attributes [set am_tagAttributes($tag)] "" quotehtml-nosinglequotes] } else { return [am_set iget [set am_tagAttributes($tag)] $attribute $value] } } default { error "bad option \"$option\": should be append, get or set" "" "" } } } # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Define some helper AM functions in case they are not present: # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if {[string equal "" [info commands am_set]]} { proc am_set {option args} { # # Methods for manipulating ns_set's. # # Last Modified: 2008-04-15 # Last Modified By: Alex Nisenboim # Original Author: Alex Hisen # # Written in TCL for now, it may be worth adding these commands to # ns_set at the C layer later. Might also be nice to have an ns/am_set 'set' command # that uses Ns_SetPutValue (which sets existing key by index) # # am_set fromarray - no such thing - use am_array2set or am_set frommap [array get arrayname] - see below # # am_set fromlist list ?setid? - returns setid in which it creates blank (not same as NULL) # -valued keys from the list (if no setid supplied, creates a new one) # # am_set frommap map | key1 value1 ?key2 value2? ... # Takes a map (i.e. a list in array get format) and returns a setid for a new ns_set # created from the map. Note that map can be in a single parameter or in multiple parameters. # Note that this requires Tcl 7.5+ and we do a simple put for each key-value pair. # For Tcl 7.4 compatibility or for more flexible handling create an array first with # array set $map, then use am_array2set arrayname # # am_set fromprint string - takes the output from [am_printset $setid] and creates a set # This is convenient in debugging - you can easily recreate a set such as formdata # from the print out from an ns_log debugging statement in the server log. # This requires Tcl 8.3+ and is recursive (uses am_set frommap) # # am_set keys setId ?prefix? ?matchPattern? # Returns the list of keys in the ns_set, optionally prefixed with prefix, # optionally narrowed down to the ones matching the case-sensitive glob matchPattern # To make it case-insensitive, run the pattern through am_nocaseGlob first. # # am_set values setId ?keyMatchPattern? ?top? # Returns the list of values in the ns_set, optionally filtered to only # those KEYS that match the case-sensitive glob pattern in keyMatchPattern. # If top (an integer) is specified stops after that many values (like SQL SELECT TOP 1 ...) # # am_set ivalues setId ?keyMatchPattern? ?top? # Case-insensitive version of am_set values # # am_set idelkeys setId key - deletes ALL case-insensitive occurances of $key in ns_set $setid # # am_set iupdate setId key value ?usename? # Does a case-insensitive version of ns_set update. If usename is # non-"", the case version that was in the ns_set is preserved. # Note that both ns_set update and am_set iupdate move the updated # key to the bottom of the ns_set. This means that performing # an ns_set get after an ns_set update may not necessarily return # the value you just updated but instead another instance of this key # which was previously after the updated key and now appears before it! # # am_set iupdateonly setId key value ?usename? # Performs an iupdate ONLY if the key already exists # # am_set iappend setId key value ?separator? # Appends provided string to the current value of the key # (key is matched case-insensitevely, creates key if it doesn't exist). # Optionally, places the specified separator between the two strings. # Smart enough to not put one in, if one already exists at the end # of the current value or if current or specified value is blank. # Always preserves the case version of the key in the ns_set. # Returns the resulting value that is now in the key. # # am_set imerge high low ?prefix? # Does a case-insensitive version of ns_set merge. Any fields in # the low set are appended to the high set if a field with the same # key (case-insensitive) does not already exist in the high set. # Fields are added in a loop, so if there are multiple fields in # the low set whose keys differ only by case, only the first such # field will be included in the high set. # If $prefix is specified, all keys in low are added to high as $prefix$lowkey # # am_set get setId key ?defaultValue? # am_set iget setId key ?defaultValue? # Wrappers to the ns_set get/iget commands that return the defaultValue or "" if not supplied # if setId is "" (instead of throwing error) or the key is "" or does not exist in the ns_set. # # For programming convenience, am_set put and update pass through to ns_set stripping out the 'usename' parameter switch [set option [string tolower $option]] { fromlist { set list [lindex $args 0] set setid [lindex $args 1] if [string match "" $setid] { set setid [ns_set new] } foreach key $list { ns_set put $setid $key "" } return $setid } frommap { if {[llength $args] == 1} { set args [lindex $args 0] } set setid [ns_set new] foreach {key value} $args { ns_set put $setid $key $value } return $setid } fromprint { return [am_set frommap [lrange [split [string map {"\nkey: " \x00 " value: " \x00} "\n[string trim [lindex $args 0]]"] \x00] 1 end]] } keys { set setid [lindex $args 0] if {$setid == ""} {return ""} set prefix [lindex $args 1] set size [ns_set size $setid] set list [list] if {[string match "" [set matchPattern [lindex $args 2]]] || [string match {\*} $matchPattern]} { for {set i 0} {$i < $size} {incr i} { lappend list "$prefix[ns_set key $setid $i]" } } else { for {set i 0} {$i < $size} {incr i} { set key [ns_set key $setid $i] if [string match $matchPattern $key] { lappend list "$prefix$key" } } } return $list } idelkeys { set setid [lindex $args 0] if {$setid == ""} {return ""} set key [lindex $args 1] while {[ns_set iunique $setid $key] == 0} { ns_set idelkey $setid $key } ns_set idelkey $setid $key } iupdate { set setid [lindex $args 0] if {$setid == ""} {return ""} set key [lindex $args 1] set value [lindex $args 2] set usename [lindex $args 3] if {$usename == ""} { ns_set idelkey $setid $key } else { if {[set index [ns_set ifind $setid $key]] != -1} { set key [ns_set key $setid $index] ns_set delete $setid $index } } ns_set put $setid $key $value } iupdateonly { set setid [lindex $args 0] if {$setid == ""} {return ""} set key [lindex $args 1] set value [lindex $args 2] set usename [lindex $args 3] if {[set index [ns_set ifind $setid $key]] == -1} { return "" } if {$usename == ""} { ns_set idelkey $setid $key } else { set key [ns_set key $setid $index] ns_set delete $setid $index } ns_set put $setid $key $value } iappend { set setid [lindex $args 0] if {$setid == ""} {return ""} set key [lindex $args 1] set value [lindex $args 2] if {![string match "" $value]} { set separator [lindex $args 3] } else { set separator "" } if {[set index [ns_set ifind $setid $key]] != -1} { set key [ns_set key $setid $index] set prior [ns_set value $setid $index] ns_set delete $setid $index if {![string match "" $prior]} { set value "[string trimright $prior $separator]$separator$value" } } ns_set put $setid $key $value return $value } imerge { set high [lindex $args 0] set low [lindex $args 1] set prefix [lindex $args 2] if {$high == "" || $low == ""} {return ""} set size [ns_set size $low] for {set i 0} {$i < $size} {incr i} { set key [ns_set key $low $i] if {[ns_set ifind $high "$prefix$key"] == -1} { ns_set put $high "$prefix$key" [ns_set value $low $i] } } } values - ivalues { set setid [lindex $args 0] if {$setid == ""} {return ""} set size [ns_set size $setid] set list [list] set count 0 set top [lindex $args 2] if [string match "" [set keyMatchPattern [lindex $args 1]]] { for {set i 0} {$i < $size} {incr i} { lappend list [ns_set value $setid $i] incr count if {[string match "" $top] == 0 && $count == $top} { return $list } } } else { if [string match "ivalues" $option] { set keyMatchPattern [string tolower $keyMatchPattern] for {set i 0} {$i < $size} {incr i} { if [string match $keyMatchPattern [string tolower [ns_set key $setid $i]]] { lappend list [ns_set value $setid $i] incr count if {[string match "" $top] == 0 && $count == $top} { return $list } } } } else { for {set i 0} {$i < $size} {incr i} { if [string match $keyMatchPattern [ns_set key $setid $i]] { lappend list [ns_set value $setid $i] incr count if {[string match "" $top] == 0 && $count == $top} { return $list } } } } } return $list } get - iget { set setid [lindex $args 0] if [string match "" $setid] { return [lindex $args 2] } if [string match "" [set value [ns_set $option $setid [lindex $args 1]]]] { return [lindex $args 2] } return $value } put { return [ns_set put [lindex $args 0] [lindex $args 1] [lindex $args 2]] } update { return [ns_set update [lindex $args 0] [lindex $args 1] [lindex $args 2]] } default { error "bad option \"$option\": should be fromlist, frommap, fromprint, get, keys, iappend, idelkeys, iget, imerge, iupdate, iupdateonly, ivalues, put, update or values" "" "" } } } } if {[string equal "" [info commands am_set2attributes]]} { proc am_set2attributes {setid {exclude ""} {encode "quotehtml"} {brace 0} {onEmptyKey "bypass"}} { # # Original Author: Jamie Rasmussen # Last Modified By: Jamie Rasmussen # Last Modified: 2004-02-15 # # Thin wrapper to am_dumpset for converting an ns_set to a string of HTML attributes. # For example, if your ns_set contained: # alt "Some \"alt\" text" # height 60 # width 80 # "" "checked" # You would get ==> alt="Some "alt" text" height="60" width="80" checked # # See am_dumpset for more information. return [am_dumpset $setid $exclude " " "" $encode "=" 2 $brace 0 $onEmptyKey] } } if {[string equal "" [info commands am_set2map]]} { proc am_set2map {setid {exclude ""} {encode ""} {unquoteIntegers 0} {addPrefix ""}} { # # Original Author: Jamie Rasmussen # Last Modified By: Jamie Rasmussen # Last Modified: 2004-02-15 # # Thin wrapper to am_dumpset for converting an ns_set to list suitable for Tcl's # string map. # For example, if your ns_set contained: # a b # c d # You would get ==> a b c d # # See am_dumpset for more information. # # Note that under AOLserver 3.x and later, if you don't need the # various advanced processing of am_dumpset, you can just use ns_set array # return [am_dumpset $setid $exclude " " "" $encode " " 0 1 $unquoteIntegers "" $addPrefix] } } if {[string equal "" [info commands am_set2query]]} { proc am_set2query {setid {exclude ""} {fieldsjoin "&"} {separator ","} {encode ""} {onEmptyKey "skip"} {addPrefix ""}} { # # Original Author: Jamie Rasmussen # Last Modified By: Jamie Rasmussen # Last Modified: 2004-02-15 # # Roughly the opposite of ns_parsequery (which takes a query string in # the form key1=value1&key2=value2 and returns an ns_set with those # key-value pairs). The returned query string does NOT have the # initial ? or &. # # Thin wrapper to am_dumpset for converting an ns_set to a URL query string. # For example, if your ns_set contained: # limit 20 # orderby date* # You would get ==> limit=20&orderby=date* # # See am_dumpset for more information. return [am_dumpset $setid $exclude $fieldsjoin $separator $encode "=" 0 0 0 $onEmptyKey $addPrefix] } } if {[string equal "" [info commands am_set2xml]]} { proc am_set2xml {setid {exclude ""} {fieldsjoin ""} {separator ","} {pairjoin ""} {closePair ""} {onEmptyKey "skip"} {addPrefix ""}} { # # Original Author: Alex Hisen # Last Modified By: Alex Hisen # Last Modified: 2007-09-05 # # Thin wrapper to am_dumpset for converting an ns_set to an xml string. # For example, if your ns_set contained: # firstName John "Little" # lastName Doe # email john@domain.com,johndoe@domain.com # You would get: # John "Little"Doejohn@domain.comjohndoe@domain.com # # You can specify \n in fieldsjoin to separate each tag with a newline. # You can also specify \n\t in pairjoin and \n in closePair to get: # # John # # # See am_dumpset for more information. return [am_dumpset $setid $exclude $fieldsjoin $separator "quotehtml" $pairjoin 0 0 0 $onEmptyKey $addPrefix $closePair 1] } } if {[string equal "" [info commands am_dumpset]]} { proc am_dumpset {setid {exclude ""} {fieldsjoin "&"} {separator ","} {encode ""} {pairjoin "="} {quote 0} {brace 0} {unquoteIntegers 0} {onEmptyKey ""} {addPrefix ""} {closePair ""} {xml 0}} { # # Original Author: Alex Hisen and Jamie Rasmussen # Last Modified By: Alex Hisen # Last Modified: 2007-09-13 # # Original name was am_set2query. This function is more general and # is called by am_set2query, am_set2map, am_set2attributes and am_set2xml. # # am_set2query is roughly the opposite of ns_parsequery # (which takes a query string in the form key1=value1&key2=value2 # and returns an ns_set with those key-value pairs). # # The returned query string does NOT have the initial ? or &. # # Now returns "" if setid is "", no longer throws an error. # # All the string defaults are overwritten by blanks, so do not use "" # for an argument to use its default - specify it explicitly # (does not apply to integer/boolean agruments # - "" is equivalent to 0 which is their default). # # Arguments (the number of args in am_dumpset has gotten out of hand and # using wrappers instead calling am_dumpset directly is strongly recommended): # # setid An ns_set to dump # # exclude Specify a tcl list of keys to exclude from being put into the # result. Keys are treated case-insensitively. Note that if you # want to exclude all the ColValue.*, RowID.*, etc. type of keys # and just leave the keys without '.' in them, run your formdata # ns_set through: [ns_findset [ns_set split $formdata]] ""] # # fieldsjoin The string that will be used to join the fields from the # ns_set. Default is '&'. Following new W3C recommendations, # fields in query string may be joined with ';' or even multiple # characters. # # separator This proc automatically expands ns_sets collapsed by # am_uniqueset with $separator (',' by default). # (i.e. key=value1,value2 becomes key=value1&key=value2) If "" is # specified, no expansion will occur. # # encode How to encode the key and value. The default, "", will not # perform any encoding. If encode contains 'quotehtml', HTML quoting # will be performed on both key and value. You can pass directives # to am_quotehtml for not quoting single or double quotes by # including them in this string (i.e. quotehtmlNosinglequotes) # Specifying any other non-blank value will perform an ns_urlencode # on both key and value. Note that ns_parsequery always performs # an ns_urldecode on the string first. This function does not, # both because of its more general purpose and because our source # ns_set is likely to be already encoded form data. # # pairjoin String to join each field's key and value with. Defaults # to '='. # # quote Can be 0/"" (default), 1, or 2. If 1, each field's value will be # always wrapped with quotation marks. If 2, each field's value will be # quoted only they are not already present. Note that unquoteIntegers # has precedence over this argument. # # brace Can be 0/"" (default) or 1. If 1, each field's key and value # will be enclosed in curly braces {} if needed. # # unquoteIntegers Can be 0/"" (default) or 1. If 1, if a field's value # is an integer, any quotes surrounding it will be removed. The # quotes need not be evenly matched - any will be removed. # # onEmptyKey What we should do if the key of the ns_set is "". The # default is no behavior change, and "" is used as the key. If # onEmptyKey is "usevalue", the value of the field will be used. # If onEmptyKey is "bypass", the value will be inserted directly # into the result string as the pair, ignoring any splitting, # encoding, bracing, or quoting options specified for that field. # If onEmptyKey is "skip", we'll pretend the field didn't exist. # # addPrefix - string to prepend to each key. This string is NOT encoded or quoted. # # closePair - string to append after value (this is really only useful # to add newlines/tabs between the value and the closing tag with xml) # # xml Boolean - if True, key is formatted as and each pair is closed with # Note that you must still supply "" (or newlines/tabs) in fieldsjoin and pairjoin if {[string match "" $setid]} {return ""} set encode [string tolower $encode] set exclude [string tolower $exclude] set str "" set size [ns_set size $setid] for {set i 0} {$i < $size} {incr i} { # If we encounter a key we were instructed to exclude, pretend it doesn't exist. if {[lsearch $exclude [string tolower [set key [ns_set key $setid $i]]]] != -1} { continue } # Possibly take special measures for an empty key. if {[string match "" $key]} { if {[string match "usevalue" $onEmptyKey]} { set key [ns_set value $setid $i] } elseif {[string match "bypass" $onEmptyKey]} { if {![string match "" [set value [ns_set value $setid $i]]]} { append str $fieldsjoin $value } continue } elseif {[string match "skip" $onEmptyKey]} { continue } } if {[string match "*quotehtml*" $encode]} { set key "$addPrefix[am_quotehtml $key $encode]" } elseif {![string match "" $encode]} { set key "$addPrefix[ns_urlencode $key]" } else { set key "$addPrefix$key" } set endTag "" if {[am_boolvar $xml]} { set endTag "" set key "<$key>" } # Turn the value into a list, one way or another # guaranteeing an {} list if values is blank set values [ns_set value $setid $i] if {[string match "" $separator]} { set values [list $values] } elseif {[string match "" $values]} { set values [list ""] } else { set values [split $values $separator] } # Loop over values, encoding, quoting, and bracing them # as necessary before adding to our return string # Quoting must happen after encoding or our surrounding # quotes would be encoded. foreach value $values { set integerValue "" regexp {^"*([\d]+)"*$} $value match integerValue if {[string match 2 $quote]} { regexp {^\"([^\"]*)\"$} $value match value } if {[string match "*quotehtml*" $encode]} { set value [am_quotehtml $value $encode] } elseif {![string match "" $encode]} { set value [ns_urlencode $value] } if {[am_boolvar $quote]} { set value \"$value\" } if {[am_boolvar $unquoteIntegers]} { set value $integerValue } if {[am_boolvar $brace]} { set key [list $key] set value [list $value] } append str $fieldsjoin $key $pairjoin $value $closePair $endTag } } # Remove first field joiner (default &) return [string range $str [string length $fieldsjoin] end] } } if {[string equal "" [info commands am_boolvar]]} { proc am_boolvar {value {nullReturn 0}} { # # Under Tcl 8.3+ am_boolvar is essentially just a wrapper to [string is false $value] # # Original Author: Alex Hisen # Last Modified By: Alex Hisen # Last Modified: 2005-01-06 # # This enables use of any variable as a boolean # returns 0 if $value is in (0 f false off no n "") (case insensitive) # 1 otherwise # Note that this proc is somewhat misnamed but for use with various data structures, # it doesn't take the variable name but the variable itself. # i.e. call it [am_boolvar $myvar], or [am_boolvar [ns_set get $setid key]]. # # By default, 0 is returned for a null string in $var but you can override that behavior # by specifying what should be returned in the case of a null string (i.e. 1 or -1 or "") # # Note that am_boolvar's behavior is somewhat different from ns_config -bool, # which will convert a boolean value from # "on", "1", "y", "yes", "t", and "true" to "1", and will convert a boolean value of # "off", "0", "n", "no", "f", and "false" to "0". # If a boolean contains any other value, a warning is logged (and "" is returned). # if [string match "" $value] { return $nullReturn } if [string is false $value] { return 0 } else { return 1 } } } # We now have this as a C command in amattributes2set module if {[string match "" [info commands am_quotehtml]]} { proc am_quotehtml {html args} { # # Last Modified: 2004-12-29 # Last Modified By: Alex Hisen # Original Author: Based on Arsdigita's ad_quotehtml # # Quotes ampersands, double-quotes, and angle brackets in $html. # Analogous to ns_quotehtml except that it quotes double-quotes as " # and single quotes as ' # (ns_quotehtml 2.x does not quote single or double-quotes # at all and 3.x+ uses " for double-quotes). # # Optional args can be either one word or two words/arguments # If $args contains the string "double", double-quotes will NOT be converted # If $args contains the string "single", single-quotes will NOT be converted if [string match "" $html] { return $html } # we have to do & first or we'll hose ourselves with the ones lower down regsub -all & $html \\&\; html if ![string match "*double*" $args] { regsub -all \" $html \\"\; html } if ![string match "*single*" $args] { regsub -all ' $html \\'\; html } regsub -all < $html \\<\; html regsub -all > $html \\>\; html return $html } } }