#
# z-security-patch.tcl
#
# collected by dvr@arsdigita.com, July 4, 2000
# code contributed by many.
#
# Changes to old code:
#
#  1) We've added check_for_form_variable_naughtiness, which takes a variable
#     name and value, and returns an error if the value looks like a security 
#     risk.
#
#  2) We've changed ad_page_variables and all the set_form_variable-like 
#     proc to call check_for_form_variable_naughtiness for every variable
#     processed.
#
# New Code:
#
#  3) We've added ad_set_typed_form_variable_filter, which lets you declare
#     the datatype of each form variable (for example, user_id should always
#     be an integer). These rules are followed by 
#     check_for_form_variable_naughtiness
#
#############################################################

util_report_library_entry

proc check_for_form_variable_naughtiness { name value } {
    
    # I'm removing this test because it gets handled by the filter
    # -- dvr, 7/4/2000
    #
    #if { [string compare $name user_id] == 0 } {
    #    if { [string length $value] > 0 && ![regexp {^[0-9]+$} $value] } {
    #        # user_id not null, and not an integer
    #        error "The user_id value must be an integer!"
    #    }
    #}

    # security patch contributed by michael@cleverly.com
    if { [string match "QQ*" $name] } {
        error "Form variables should never begin with QQ!"
    }

    # contributed by michael@cleverly.com
    if { [string match Vform_counter_i $name] } {
        error "Vform_counter_i not an allowed form variable"
    }

    # The statements below make ACS more secure, because it prevents
    # overwrite of variables from something like set_the_usual_form_variables
    # and it will be better if it was in the system. Yet, it is commented
    # out because it will cause an unstable release. To add this security
    # feature, we will need to go through all the code in the ACS and make
    # sure that the code doesn't try to overwrite intentionally and also
    # check to make sure that when tcl files are sourced from another proc,
    # the appropriate variables are unset.  If you want to install this
    # security feature, then you can look in the release notes for more info.
    # 
    # security patch contributed by michael@cleverly.com,
    # fixed by iwashima@arsdigita.com
    #
    # upvar 1 $name name_before
    # if { [info exists name_before] } {
    # The variable was set before the proc was called, and the
    # form attempts to overwrite it
    # error "Setting the variables from the form attempted to overwrite existing variable $name"
    # }
    
    # no naughtiness with uploaded files (discovered by ben@mit.edu)
    # patch by richardl@arsdigita.com, with no thanks to
    # jsc@arsdigita.com.
    if { [string match "*tmpfile" $name] } {
        set tmp_filename [ns_queryget $name]

        # ensure no .. in the path
        ns_normalizepath $tmp_filename

        set passed_check_p 0

        # check to make sure path is to an authorized directory
        set tmpdir_list [ad_parameter_all_values_as_list TmpDir]
        if [empty_string_p $tmpdir_list] {
            set tmpdir_list [list "/var/tmp" "/tmp"]
        }

        foreach tmpdir $tmpdir_list {
            if { [string match "$tmpdir*" $tmp_filename] } {
                set passed_check_p 1
                break
            }
        }

        if { !$passed_check_p } {
            error "You specified a path to a file that is not allowed on the system!"
        }
    
    }

    # integrates with the ad_set_typed_form_variable_filter system
    # written by dvr@arsdigita.com

    # see if this is one of the typed variables
    global ad_typed_form_variables    

    if [info exists ad_typed_form_variables] { 
        foreach typed_var_spec $ad_typed_form_variables {
            set typed_var_name [lindex $typed_var_spec 0]
        
            if ![string match $typed_var_name $name] {
                # no match. Go to the next variable in the list
                continue
            }
        
            # the variable matched the pattern
            set typed_var_type [lindex $typed_var_spec 1]
        
            if [string match "" $typed_var_type] {
                # if they don't specify a type, the default is 'integer'
                set typed_var_type integer
            }
        
            set variable_safe_p [ad_var_type_check_${typed_var_type}_p $value]
        
            if !$variable_safe_p {
                ns_returnerror 500 "variable $name failed '$typed_var_type' type check"
                ns_log Error "[ns_conn url] called with \$$name = $value"
                error "variable $name failed '$typed_var_type' type check"
            }

            # we've found the first element in the list that matches,
            # and we don't want to check against any others
            break
        }
    }
}

#
# Modified old procs
#

proc set_form_variables {{error_if_not_found_p 1}} {
    if { $error_if_not_found_p == 1} {
        uplevel { 
            if { [ns_getform] == "" } {
                ns_returnerror 500 "Missing form data"
                return
            }
        }
     } else {
        uplevel { 
            if { [ns_getform] == "" } {
                # we're not supposed to barf at the user but we want to return
                # from this subroutine anyway because otherwise we'd get an error
                return
            }
        }
    }

    # at this point we know that the form is legal
    # The variable names are prefixed with a V to avoid confusion with the form variables while checking for naughtiness.
    uplevel {
        set Vform [ns_getform] 
        set Vform_size [ns_set size $Vform]
        set Vform_counter_i 0
        while {$Vform_counter_i<$Vform_size} {
            set Vname [ns_set key $Vform $Vform_counter_i]
            set Vvalue [ns_set value $Vform $Vform_counter_i]
            check_for_form_variable_naughtiness $Vname $Vvalue
            set $Vname $Vvalue
            incr Vform_counter_i
        }
    }
}

proc set_form_variables_string_trim_DoubleAposQQ {} {
    # The variable names are prefixed with a V to avoid confusion with the form variables while checking for naughtiness.
    uplevel {
        set Vform [ns_getform] 
        if {$Vform == ""} {
            ns_returnerror 500 "Missing form data"
            return;
        }
        set Vform_size [ns_set size $Vform]
        set Vform_counter_i 0
        while {$Vform_counter_i<$Vform_size} {
            set Vname [ns_set key $Vform $Vform_counter_i]
            set Vvalue [ns_set value $Vform $Vform_counter_i]
            check_for_form_variable_naughtiness $Vname $Vvalue
            set QQ$Vname [DoubleApos [string trim $Vvalue]]
            incr Vform_counter_i
        }
    }
}

# this one does both the regular and the QQ

proc set_the_usual_form_variables {{error_if_not_found_p 1}} {
    if { [ns_getform] == "" } {
        if $error_if_not_found_p {
            uplevel { 
                ns_returnerror 500 "Missing form data"
                return
            }
        } else {
            return
        }
    }

    # The variable names are prefixed with a V to avoid confusion with the form variables while checking for naughtiness.
    uplevel {
        set Vform [ns_getform] 
        set Vform_size [ns_set size $Vform]
        set Vform_counter_i 0
        while {$Vform_counter_i<$Vform_size} {
            set Vname [ns_set key $Vform $Vform_counter_i]
            set Vvalue [ns_set value $Vform $Vform_counter_i]
            check_for_form_variable_naughtiness $Vname $Vvalue
            set QQ$Vname [DoubleApos [string trim $Vvalue]]
            set $Vname $Vvalue
            incr Vform_counter_i
        }
    }
}

proc set_form_variables_string_trim_DoubleApos {} {
    # The variable names are prefixed with a V to avoid confusion with the form variables while checking for naughtiness.
    uplevel {
        set Vform [ns_getform] 
        if {$Vform == ""} {
            ns_returnerror 500 "Missing form data"
            return;
        }
        set Vform_size [ns_set size $Vform]
        set Vform_counter_i 0
        while {$Vform_counter_i<$Vform_size} {
            set Vname [ns_set key $Vform $Vform_counter_i]
            set Vvalue [ns_set value $Vform $Vform_counter_i]
            check_for_form_variable_naughtiness $Vname $Vvalue
            set $Vname [DoubleApos [string trim $Vvalue]]
            incr Vform_counter_i
        }
    }
}

proc set_form_variables_string_trim {} {
    # The variable names are prefixed with a V to avoid confusion with the form variables while checking for naughtiness.
    uplevel {
        set Vform [ns_getform] 
        if {$Vform == ""} {
            ns_returnerror 500 "Missing form data"
            return;
        }
        set Vform_size [ns_set size $Vform]
        set Vform_counter_i 0
        while {$Vform_counter_i<$Vform_size} {
            set Vname [ns_set key $Vform $Vform_counter_i]
            set Vvalue [ns_set value $Vform $Vform_counter_i]
            check_for_form_variable_naughtiness $Vname $Vvalue
            set $Vname [string trim $Vvalue]
            incr Vform_counter_i
        }
    }
}

proc_doc util_GetCheckboxValues {form checkbox_name {default_return 0}} "For getting all the boxes from a set of checkboxes in a form.  This procedure takes the complete ns_conn form and returns a list of checkbox values.  It returns 0 if none are found (or some other default return value if specified)." {

    set i 0
    set size [ns_set size $form]

    while {$i<$size} {

        if { [ns_set key $form $i] == $checkbox_name} {

            set value [ns_set value $form $i]
            check_for_form_variable_naughtiness $checkbox_name $value

            # LIST_TO_RETURN will be created if it doesn't exist
            lappend list_to_return $value
        }
        incr i
    }

    #if no list, you can specify a default return
    #default default is 0

    if { [info exists list_to_return] } { return $list_to_return } else {return $default_return}
}

proc_doc ad_page_variables {variable_specs} {
<pre>
Current syntax:

    ad_page_variables {var_spec1 [varspec2] ... }

    This proc handles translating form inputs into Tcl variables, and checking
    to see that the correct set of inputs was supplied.  Note that this is mostly a
    check on the proper programming of a set of pages.

Here are the recognized var_specs:

    variable				; means it's required
    {variable default-value}
      Optional, with default value.  If the value is supplied but is null, and the
      default-value is present, that value is used.
    {variable -multiple-list}
      The value of the Tcl variable will be a list containing all of the
      values (in order) supplied for that form variable.  Particularly useful
      for collecting checkboxes or select multiples.
      Note that if required or optional variables are specified more than once, the
      first (leftmost) value is used, and the rest are ignored.
    {variable -array}
      This syntax supports the idiom of supplying multiple form variables of the
      same name but ending with a "_[0-9]", e.g., foo_1, foo_2.... Each value will be
      stored in the array variable variable with the index being whatever follows the
      underscore.

QQ variables are automatically created by ad_page_variables.

Other elements of the var_spec are ignored, so a documentation string
describing the variable can be supplied.

Note that the default value form will become the value form in a "set"

Note that the default values are filled in from left to right, and can depend on
values of variables to their left:
ad_page_variables {
    file
    {start 0}
    {end {[expr $start + 20]}}
}
</pre>
} {
    set exception_list [list]
    set form [ns_getform]
    if { $form != "" } {
	set form_size [ns_set size $form]
	set form_counter_i 0

	# first pass -- go through all the variables supplied in the form
	while {$form_counter_i<$form_size} {
	    set variable [ns_set key $form $form_counter_i]
	    set value [ns_set value $form $form_counter_i]
	    check_for_form_variable_naughtiness $variable $value
	    set found "not"
	    # find the matching variable spec, if any
	    foreach variable_spec $variable_specs {
		if { [llength $variable_spec] >= 2 } {
		    switch -- [lindex $variable_spec 1] {
			-multiple-list {
			    if { [lindex $variable_spec 0] == $variable } {
				# variable gets a list of all the values
				upvar 1 $variable var
				lappend var $value
				set found "done"
				break
			    }
			}
			-array {
			    set varname [lindex $variable_spec 0]
			    set pattern "($varname)_(.+)"
			    if { [regexp $pattern $variable match array index] } {
				if { ![empty_string_p $array] } {
				    upvar 1 $array arr
				    set arr($index) [ns_set value $form $form_counter_i]
				}
				set found "done"
				break
			    }
			}
			default {
			    if { [lindex $variable_spec 0] == $variable } {
				set found "set"
				break
			    }
			}
		    }
		} elseif { $variable_spec == $variable } {
		    set found "set"
		    break
		}
	    }
	    if { $found == "set" } {
		upvar 1 $variable var
		if { ![info exists var] } {
		    # take the leftmost value, if there are multiple ones
		    set var $value
		}
	    }
	    incr form_counter_i
	}
    }

    # now make a pass over each variable spec, making sure everything required is there
    # and doing defaulting for unsupplied things that aren't required
    foreach variable_spec $variable_specs {
	set variable [lindex $variable_spec 0]
	upvar 1 $variable var

	if { [llength $variable_spec] >= 2 } {
	    if { ![info exists var] } {
		set default_value_or_flag [lindex $variable_spec 1]
		
		switch -- $default_value_or_flag {
		    -array {
			# don't set anything
		    }
		    -multiple-list {
			set var [list]
		    }
		    default {
			# Needs to be set.
			uplevel [list eval set $variable "\[subst [list $default_value_or_flag]\]"]
			# This used to be:
			#
			#   uplevel [list eval [list set $variable "$default_value_or_flag"]]
			#
			# But it wasn't properly performing substitutions.
		    }
		}
	    }

	    # no longer needed because we QQ everything by default now
	    #	    # if there is a QQ or qq or any variant after the var_spec,
	    #	    # make a "QQ" variable
	    #	    if { [regexp {^[Qq][Qq]$} [lindex $variable_spec 2]] && [info exists var] } {
	    #		upvar QQ$variable QQvar
	    #		set QQvar [DoubleApos $var]
	    #	    }

	} else {
	    if { ![info exists var] } {
		lappend exception_list "\"$variable\" required but not supplied"
	    }
	}

        # modified by rhs@mit.edu on 1/31/2000
	# to QQ everything by default (but not arrays)
        if {[info exists var] && ![array exists var]} {
	    upvar QQ$variable QQvar
	    set QQvar [DoubleApos $var]
	}

    }

    set n_exceptions [llength $exception_list]
    # this is an error in the HTML form
    if { $n_exceptions == 1 } {
	ns_returnerror 500 [lindex $exception_list 0]
	return -code return
    } elseif { $n_exceptions > 1 } {
	ns_returnerror 500 "<li>[join $exception_list "\n<li>"]\n"
	return -code return
    }
}

#
# New procs
#

proc_doc ad_set_typed_form_variable_filter {url_pattern args} {
    <pre>
    #
    # Register special rules for form variables.
    #
    # Example:
    #
    #    ad_set_typed_form_variable_filter /my_module/* {a_id number} {b_id word} {*_id integer}
    #
    # For all pages under /my_module, set_form_variables would set 
    # $a_id only if it was number, and $b_id only if it was a 'word' 
    # (a string that contains only letters, numbers, dashes, and 
    # underscores), and all other variables that match the pattern
    # *_id would be set only if they were integers.
    #
    # Variables not listed have no restrictions on them.
    #
    # By default, the three supported datatypes are 'integer', 'number',
    # and 'word', although you can add your own type by creating
    # functions named ad_var_type_check_${type_name}_p which should
    # return 1 if the value is a valid $type_name, or 0 otherwise.
    #
    # There's also a special datatype named 'nocheck', which will
    # return success regardless of the value. (See the docs for 
    # ad_var_type_check_${type_name}_p to see how this might be
    # useful.)
    #
    # The default data_type is 'integer', which allows you shorten the
    # command above to:
    #
    #    ad_set_typed_form_variable_filter /my_module/* a_id {b_id word}
    #
    </pre>
} {
    ad_register_filter postauth GET  $url_pattern ad_set_typed_form_variables $args
    ad_register_filter postauth POST $url_pattern ad_set_typed_form_variables $args
}

proc ad_set_typed_form_variables {conn args why} {

    global ad_typed_form_variables

    eval lappend ad_typed_form_variables [lindex $args 0]

    return filter_ok
}

#
# All the ad_var_type_check* procs get called from 
# check_for_form_variable_naughtiness. Read the documentation
# for ad_set_typed_form_variable_filter for more details.

proc_doc ad_var_type_check_integer_p {value} {
    <pre>
    #
    # return 1 if $value is an integer, 0 otherwise.
    #
    <pre>
} {

    if [regexp {[^0-9]} $value] {
        return 0
    } else {
        return 1
    }
}

proc_doc ad_var_type_check_safefilename_p {value} {
    <pre>
    #
    # return 0 if the file contains ".."
    #
    <pre>
} {

    if [string match *..* $value] {
        return 0
    } else {
        return 1
    }
}

proc_doc ad_var_type_check_dirname_p {value} {
    <pre>
    #
    # return 0 if $value contains a / or \, 1 otherwise.
    #
    <pre>
} {

    if [regexp {[/\]} $value] {
        return 0
    } else {
        return 1
    }
}

proc_doc ad_var_type_check_number_p {value} {
    <pre>
    #
    # return 1 if $value is a valid number
    #
    <pre>
} {
    if [catch {expr 1.0 * $value}] {
        return 0
    } else {
        return 1
    }
}

proc_doc ad_var_type_check_word_p {value} {
    <pre>
    #
    # return 1 if $value contains only letters, numbers, dashes, 
    # and underscores, otherwise returns 0.
    #
    </pre>
} {

    if [regexp {[^-A-Za-z0-9_]} $value] {
        return 0
    } else {
        return 1
    }
}

proc_doc ad_var_type_check_nocheck_p {{value ""}} {
    <pre>
    #
    # return 1 regardless of the value. This useful if you want to 
    # set a filter over the entire site, then create a few exceptions.
    #
    # For example:
    #
    #   ad_set_typed_form_variable_filter /my-dangerous-page.tcl {user_id nocheck}
    #   ad_set_typed_form_variable_filter /*.tcl user_id
    #
    </pre>
} {
    return 1
}

proc_doc ad_var_type_check_noquote_p {value} {
    <pre>
    #
    # return 1 if $value contains any single-quotes
    #
    <pre>
} {

    if [string match *'* $value] {
        return 0
    } else {
        return 1
    }
}

proc_doc ad_var_type_check_integerlist_p {value} {
    <pre>
    #
    # return 1 if list contains only numbers, spaces, and commas.
    # Example '5, 3, 1'. Note: it doesn't allow negative numbers,
    # because that could let people sneak in numbers that get
    # treated like math expressions like '1, 5-2'
    #
    #
    <pre>
} {

    if [regexp {[^ 0-9,]} $value] {
        return 0
    } else {
        return 1
    }
}

proc_doc ad_var_type_check_fail_p {value} {
    <pre>
    #
    # A check that always returns 0. Useful if you want to disable all access
    # to a page.
    #
    <pre>
} {
    return 0
}

proc_doc ad_var_type_check_third_urlv_integer_p {{args ""}} {
    <pre>
    #
    # Returns 1 if the third path element in the URL is integer.
    #
    <pre>
} {

    set third_url_element [lindex [ns_conn urlv] 3]

    if [regexp {[^0-9]} $third_url_element] {
        return 0
    } else {
        return 1
    }
}

#
# Filters
#
# the following are for registering filters against user-Id being
# passed..sorry for not integrating it with the rest.. - neal
ad_set_typed_form_variable_filter /admin/calendar/item-category-change* {user_id fail}
ad_set_typed_form_variable_filter /admin/calendar/post-edit-2* {user_id fail}
ad_set_typed_form_variable_filter /admin/calendar/post-new-2* {user_id fail}
ad_set_typed_form_variable_filter /admin/calendar/post-new-3* {user_id fail}
ad_set_typed_form_variable_filter /admin/calendar/post-new-4* {user_id fail}
ad_set_typed_form_variable_filter /admin/comments/delete* {user_id fail}
ad_set_typed_form_variable_filter /admin/crm/transition-add-2* {user_id fail}
ad_set_typed_form_variable_filter /admin/crm/transition-add* {user_id fail}
ad_set_typed_form_variable_filter /admin/crm/transition-edit-2* {user_id fail}
ad_set_typed_form_variable_filter /admin/crm/transition-edit* {user_id fail}
ad_set_typed_form_variable_filter /admin/gc/delete-ad-2* {user_id fail}
ad_set_typed_form_variable_filter /admin/gc/delete-ad* {user_id fail}
ad_set_typed_form_variable_filter /admin/gc/delete-ads-from-one-user-2* {user_id fail}
ad_set_typed_form_variable_filter /admin/gc/delete-ads-from-one-user* {user_id fail}
ad_set_typed_form_variable_filter /admin/gc/edit-ad-2* {user_id fail}
ad_set_typed_form_variable_filter /admin/gc/edit-ad* {user_id fail}
ad_set_typed_form_variable_filter /admin/general-comments/edit-2* {user_id fail}
ad_set_typed_form_variable_filter /admin/general-comments/edit* {user_id fail}
ad_set_typed_form_variable_filter /admin/glossary/one* {user_id fail}
ad_set_typed_form_variable_filter /admin/glossary/term-approve* {user_id fail}
ad_set_typed_form_variable_filter /admin/glossary/term-delete* {user_id fail}
ad_set_typed_form_variable_filter /admin/glossary/term-edit-2* {user_id fail}
ad_set_typed_form_variable_filter /admin/glossary/term-edit* {user_id fail}
ad_set_typed_form_variable_filter /admin/glossary/term-new-2* {user_id fail}
ad_set_typed_form_variable_filter /admin/glossary/term-new-3* {user_id fail}
ad_set_typed_form_variable_filter /admin/links/blacklist-2* {user_id fail}
ad_set_typed_form_variable_filter /admin/links/blacklist-remove* {user_id fail}
ad_set_typed_form_variable_filter /admin/links/blacklist* {user_id fail}
ad_set_typed_form_variable_filter /admin/links/delete-2* {user_id fail}
ad_set_typed_form_variable_filter /admin/links/delete* {user_id fail}
ad_set_typed_form_variable_filter /admin/links/restore* {user_id fail}
ad_set_typed_form_variable_filter /admin/users/approve-email* {user_id fail}
ad_set_typed_form_variable_filter /admin/users/approve* {user_id fail}
ad_set_typed_form_variable_filter /admin/users/delete-2* {user_id fail}
ad_set_typed_form_variable_filter /admin/users/reject* {user_id fail}
ad_set_typed_form_variable_filter /bboard/confirm* {user_id fail}
ad_set_typed_form_variable_filter /calendar/admin/post-edit-2* {user_id fail}
ad_set_typed_form_variable_filter /calendar/admin/post-new-3* {user_id fail}
ad_set_typed_form_variable_filter /calendar/admin/post-new-4* {user_id fail}
ad_set_typed_form_variable_filter /calendar/admin/post-new* {user_id fail}
ad_set_typed_form_variable_filter /calendar/post-new-4* {user_id fail}
ad_set_typed_form_variable_filter /download/index* {user_id fail}
ad_set_typed_form_variable_filter /events/admin/activity-add-2* {user_id fail}
ad_set_typed_form_variable_filter /events/admin/activity-edit* {user_id fail}
ad_set_typed_form_variable_filter /events/admin/event-add-3* {user_id fail}
ad_set_typed_form_variable_filter /events/admin/event-edit* {user_id fail}
ad_set_typed_form_variable_filter /events/admin/event-price-ae-2* {user_id fail}
ad_set_typed_form_variable_filter /events/admin/order-history-date* {user_id fail}
ad_set_typed_form_variable_filter /events/admin/order-history-one* {user_id fail}
ad_set_typed_form_variable_filter /events/admin/order-same-person* {user_id fail}
ad_set_typed_form_variable_filter /events/admin/order-search* {user_id fail}
ad_set_typed_form_variable_filter /events/admin/organizer-add* {user_id fail}
ad_set_typed_form_variable_filter /events/admin/reg-approve-2* {user_id fail}
ad_set_typed_form_variable_filter /events/admin/reg-cancel-2* {user_id fail}
ad_set_typed_form_variable_filter /events/admin/reg-wait-list-2* {user_id fail}
ad_set_typed_form_variable_filter /events/admin/spam-selected-events-2* {user_id fail}
ad_set_typed_form_variable_filter /events/admin/venues-ae-2* {user_id fail}
ad_set_typed_form_variable_filter /events/order-cancel-2* {user_id fail}
ad_set_typed_form_variable_filter /events/order-cancel* {user_id fail}
ad_set_typed_form_variable_filter /events/order-check* {user_id fail}
ad_set_typed_form_variable_filter /events/order-one* {user_id fail}
ad_set_typed_form_variable_filter /gc/admin/delete-ad-2* {user_id fail}
ad_set_typed_form_variable_filter /gc/admin/delete-ad* {user_id fail}
ad_set_typed_form_variable_filter /gc/admin/delete-ads-from-one-user-2* {user_id fail}
ad_set_typed_form_variable_filter /gc/admin/delete-ads-from-one-user* {user_id fail}
ad_set_typed_form_variable_filter /gc/admin/domain-top* {user_id fail}
ad_set_typed_form_variable_filter /gc/admin/edit-ad-2* {user_id fail}
ad_set_typed_form_variable_filter /gc/admin/edit-ad* {user_id fail}
ad_set_typed_form_variable_filter /gc/domain-top* {user_id fail}
ad_set_typed_form_variable_filter /glossary/one* {user_id fail}
ad_set_typed_form_variable_filter /glossary/term-edit-2* {user_id fail}
ad_set_typed_form_variable_filter /glossary/term-edit* {user_id fail}
ad_set_typed_form_variable_filter /glossary/term-new-2* {user_id fail}
ad_set_typed_form_variable_filter /glossary/term-new-3* {user_id fail}
ad_set_typed_form_variable_filter /groups/admin/group/spam-item* {user_id fail}
ad_set_typed_form_variable_filter /groups/group-new-3* {user_id fail}
ad_set_typed_form_variable_filter /homepage/index* {user_id fail}
ad_set_typed_form_variable_filter /intranet/customers/ae-2* {user_id fail}
ad_set_typed_form_variable_filter /intranet/customers/ae* {user_id fail}
ad_set_typed_form_variable_filter /intranet/customers/index* {user_id fail}
ad_set_typed_form_variable_filter /intranet/customers/primary-contact-2* {user_id fail}
ad_set_typed_form_variable_filter /intranet/customers/primary-contact-delete* {user_id fail}
ad_set_typed_form_variable_filter /intranet/customers/primary-contact-users-2* {user_id fail}
ad_set_typed_form_variable_filter /intranet/customers/primary-contact-users* {user_id fail}
ad_set_typed_form_variable_filter /intranet/customers/primary-contact* {user_id fail}
ad_set_typed_form_variable_filter /intranet/customers/view* {user_id fail}
ad_set_typed_form_variable_filter /intranet/employees/admin/bulk-edit* {user_id fail}
ad_set_typed_form_variable_filter /intranet/employees/admin/update-supervisor-2* {user_id fail}
ad_set_typed_form_variable_filter /intranet/facilities/ae-2* {user_id fail}
ad_set_typed_form_variable_filter /intranet/facilities/ae* {user_id fail}
ad_set_typed_form_variable_filter /intranet/facilities/primary-contact-2* {user_id fail}
ad_set_typed_form_variable_filter /intranet/facilities/primary-contact-delete* {user_id fail}
ad_set_typed_form_variable_filter /intranet/facilities/primary-contact* {user_id fail}
ad_set_typed_form_variable_filter /intranet/hours/ae-2* {user_id fail}
ad_set_typed_form_variable_filter /intranet/offices/ae-2* {user_id fail}
ad_set_typed_form_variable_filter /intranet/offices/ae* {user_id fail}
ad_set_typed_form_variable_filter /intranet/offices/primary-contact-2* {user_id fail}
ad_set_typed_form_variable_filter /intranet/offices/primary-contact-delete* {user_id fail}
ad_set_typed_form_variable_filter /intranet/offices/primary-contact* {user_id fail}
ad_set_typed_form_variable_filter /intranet/partners/ae-2* {user_id fail}
ad_set_typed_form_variable_filter /intranet/partners/ae* {user_id fail}
ad_set_typed_form_variable_filter /intranet/partners/index* {user_id fail}
ad_set_typed_form_variable_filter /intranet/partners/primary-contact-2* {user_id fail}
ad_set_typed_form_variable_filter /intranet/partners/primary-contact-delete* {user_id fail}
ad_set_typed_form_variable_filter /intranet/partners/primary-contact* {user_id fail}
ad_set_typed_form_variable_filter /intranet/partners/view* {user_id fail}
ad_set_typed_form_variable_filter /intranet/projects/ae-2* {user_id fail}
ad_set_typed_form_variable_filter /intranet/projects/ae* {user_id fail}
ad_set_typed_form_variable_filter /intranet/reports/missing-group-2* {user_id fail}
ad_set_typed_form_variable_filter /intranet/user-search* {user_id fail}
ad_set_typed_form_variable_filter /intranet/users/info-update-2* {user_id fail}
ad_set_typed_form_variable_filter /neighbor/comment-add-2* {user_id fail}
ad_set_typed_form_variable_filter /neighbor/view-one* {user_id fail}
ad_set_typed_form_variable_filter /registry/add-entry* {user_id fail}
ad_set_typed_form_variable_filter /wp/invite-2* {user_id fail}
ad_set_typed_form_variable_filter /wp/presentation-edit-2* {user_id fail}
ad_set_typed_form_variable_filter /wp/style-edit-2* {user_id fail}
ad_set_typed_form_variable_filter /wp/style-image-delete* {user_id fail}


# the filter list for each module
# booleans are filtered as 'word' for lack
# of a more specific filter but this should be fine
# most of the _id are integer values so the datatype
# isn't specified since the filter defaults to integer
# dates are filtered as noquote

ad_set_typed_form_variable_filter /* user_id \
				  user_id_from_search \
				  {first_names_from_search noquote} \
				  {last_name_from_search noquote} \
				  {email_from_search noquote} \
				  {email noquote} \
				  {return_url noquote}

ad_set_typed_form_variable_filter /address-book/* address_book_id

ad_set_typed_form_variable_filter /bannerideas/* idea_id

ad_set_typed_form_variable_filter /admin/bannerideas/*    idea_id

# the msg_id(feature_msg_id,start_msg_id,etc),thread_id,refers_to
# form_refers_to vars
# are actually 6-character strings
# row_id is used to compare w/oracle's internal pointer
ad_set_typed_form_variable_filter /bboard/* \
    upload_id \
    topic_id \
    {msg_id word} \
    {row_id noquote} \
    {form_refers_to word} \
    {refers_to word} \
    bboard_upload_id \
    group_id \
    {start_msg_id word} \
    {thread_id word} \
    {html_p word} \
    {topic noquote} \
    group_id \
    {rowid word} \
    {feature_msg_id word} \
    {start_msg_id word} 

# we nocheck here and in other places because a user should
# be able to enter in quotes - this means that doubleapos'ing
# and/or usage of QQ vars is necessary(this was verified and
# was already done for the vars that are nocheck)
ad_set_typed_form_variable_filter /bboard/admin* {one_line nocheck} \
    n_postings \
    {start_date noquote} \
    {end_date noquote} \
    n_winners \
    {from_address noquote} \
    {subject noquote} 

ad_set_typed_form_variable_filter /bboard/admin-bozo-pattern* \
				  {the_regexp noquote} \
				  {scope noquote} \
				  {message_to_user noquote} \
				  {creation_comment noquote} \
				  {the_regexp_old noquote}

ad_set_typed_form_variable_filter /bboard/admin-bulk* \
				  {deletion_ids noquote} \
				  {msg_ids noquote} 

# these pages are no longer used and should be deleted so
# we fail on any vars passed in
ad_set_typed_form_variable_filter /bboard/admin-authorize* {* fail}

ad_set_typed_form_variable_filter /bboard/admin-bulk-delete* {deletion_ids noquote} \
				  {msg_ids noquote} 

ad_set_typed_form_variable_filter /bboard/admin-q-and-a* {category nocheck}

ad_set_typed_form_variable_filter /bboard/admin-update* \
				  {expiration_days} \
				  {interest_level} \
				  {uploads_anticipated noquote}

ad_set_typed_form_variable_filter /bboard/add-new-alert* \
				  {presentation_type noquote} \
				  {moderation_policy noquote} \
				  {private_p  noquote} \
				  {notify_of_new_postings_p noquote}

ad_set_typed_form_variable_filter /bboard/cc* {key nocheck}

ad_set_typed_form_variable_filter /bboard/confirm* \
				  {notify word} \
				  {q_and_a_p word}

ad_set_typed_form_variable_filter /bboard/custom-q-and-a* {key nocheck}

ad_set_typed_form_variable_filter /bboard/do-delete* \
				  {submit_button noquote} \
				  {explanation nocheck} \
				  {explanation_from noquote} \
				  {explanation_to noquote} \
				  {deletion_list noquote} 

ad_set_typed_form_variable_filter /bboard/insert-msg*
    {file_extension noquote} \
    {local_filename noquote} \
    {tri_id word} \
    {upload_file safefilename}

ad_set_typed_form_variable_filter /bboard/q-and-a* \
				  {category nocheck} \
				  {thread_id word} \
				  {new_category_p word}

ad_set_typed_form_variable_filter /bboard/statistics* {show_total_bytes_p word}

ad_set_typed_form_variable_filter /bboard/threads-one-day* {kickoff_date noquote} \
				  {all_p word} \
				  {julian_date noquote}

ad_set_typed_form_variable_filter /bboard/update* \
				  {q_and_a_categorized_p word} \
				  {q_and_a_solicit_categorized_p word} \
				  {q_and_a_categorization_user_extensible_p word} \
				  {q_and_a_new_days word} \
				  {maintainer_name nocheck} \
				  {maintainer_email noquote} \
				  {admin_password nocheck} 

ad_set_typed_form_variable_filter /bboard/urgent* {archived_p word}

ad_set_typed_form_variable_filter /bboard/usgeospatial* \
    epa_region \
    {usps_abbrev noquote} \
    {tri_id word} \
    {fips_country_code word} \
    {force_p word} \
    {zip_code word} 
    
ad_set_typed_form_variable_filter /bookmarks/* bookmark_id \
	{deleteable_link noquote}

ad_set_typed_form_variable_filter /bookmarks/public-bookmarks-for-one-user* viewed_user_id

ad_set_typed_form_variable_filter /calendar/* comment_id calendar_id

ad_set_typed_form_variable_filter /admin/categories/* category_id \
				  parent_category_id \
				  profiling_weight

ad_set_typed_form_variable_filter /chat/* chat_room_id chat_msg_id

ad_set_typed_form_variable_filter /chat/history-one-day* {the_date noquote}

ad_set_typed_form_variable_filter /admin/chat/* group_id 

ad_set_typed_form_variable_filter /comments/* page_id comment_id

ad_set_typed_form_variable_filter /admin/content-sections/* sort-key \
				  section_id

ad_set_typed_form_variable_filter /admin/contest/* domain_id

ad_set_typed_form_variable_filter /custom-sections/* section_id

ad_set_typed_form_variable_filter /custom-sections/file/* content_file_id

ad_set_typed_form_variable_filter /admin/custom-sections/upload-image-1*  group_id \
                                        on_what_id \
                                        section_id \
                                        content_file_id \
					{upload_file nocheck} \
					{file_name safefilename}

ad_set_typed_form_variable_filter /admin/display/upload-logo-2* {upload_file safefilename} \
			      group_id

ad_set_typed_form_variable_filter /download/* version_id \
					      download_id

ad_set_typed_form_variable_filter /download/admin/* version_id \
						    download_id \
						    {release_date noquote} \
						    {upload_file safefilename} \
						    {pseudo_filename safefilename} \
						    {status word}

ad_set_typed_form_variable_filter /dw/* query_id

ad_set_typed_form_variable_filter /events/* file_id \
					    on_what_id \
					    {upload_file safefilename} \
					    {on_which_table word} \
                                            event_id \
					    activity_id \
					    reg_id \
					    price_id \
					    order_id

ad_set_typed_form_variable_filter /ecommerce/* {file_path safefilename} \
					       category_id \
					       subcategory_id \
					       subsubcategory_id \
					       gift_certificate_id \
					       shipment_id \
					       order_id \
					       product_id \
					       address_id \
                                               comment_id

ad_set_typed_form_variable_filter /admin/ecommerce/* product_id

ad_set_typed_form_variable_filter /admin/ecommerce/products/* {csv_file safefilename} \
				  template_id 

ad_set_typed_form_variable_filter /general-comments/* comment_id


ad_set_typed_form_variable_filter /homepage/* {screen_name noquote} \
					      {upload_file safefilename} \
					      filesystem_node \
					      new_node 

ad_set_typed_form_variable_filter /links/* page_id

ad_set_typed_form_variable_filter /poll/* pole_id choice_id

ad_set_typed_form_variable_filter /pvt/portrait/* {upload_file safefilename}
                                  
ad_set_typed_form_variable_filter /admin/spam/upload-file-2* {path safefilename} \
			   {clientfile safefilename}

ad_set_typed_form_variable_filter /admin/spam/upload-file-to-spam* spam_id \
                                 {clientfile safefilename} \
                                 {data_type word}

ad_set_typed_form_variable_filter /admin/users/view-verbose* {order_by word}
ad_set_typed_form_variable_filter /admin/users/view* {order_by word}

# display is a db column constrained to a few different values
ad_set_typed_form_variable_filter /wp/* attach_id \
					presentation_id \
					{attachment safefilename} \
					slide_id \
					{inline_image_p word} \
					{display noquote} \
					style_id \
					{image safefilename}




