Index: openacs.org-dev/packages/acs-tcl/tcl/request-processor-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs.org-dev/packages/acs-tcl/tcl/request-processor-procs.tcl,v diff -u -N -r1.1 -r1.2 --- openacs.org-dev/packages/acs-tcl/tcl/request-processor-procs.tcl 9 Jul 2002 17:34:59 -0000 1.1 +++ openacs.org-dev/packages/acs-tcl/tcl/request-processor-procs.tcl 12 Dec 2002 12:21:34 -0000 1.2 @@ -4,7 +4,7 @@ single HTTP request to an ACS server. @author Jon Salz (jsalz@arsdigita.com) - @date 15 May 2000 + @creation-date 15 May 2000 @cvs-id $Id$ } @@ -14,6 +14,117 @@ # ##### +ad_proc -public rp_internal_redirect { + -absolute_path:boolean + path +} { + + Tell the request processor to return some other page. + + The path can either be relative to the current directory (e.g. "some-template") + relative to the server root (e.g. "/packages/my-package/www/some-template"), or + an absolute path (e.g. "/home/donb/openacs-4/templates/some-cms-template"). + + When there is no extension then the request processor will choose the + matching file according to the extension preferences. + + Parameters will stay the same as in the initial request. + + Keep in mind that if you do an internal redirect to something other than + the current directory that relative links returned to the clients + browser may be broken (since the client will have the original URL). + + @param absolute_path If set the path is an absolute path within the host filesystem + @param path path to the file to serve + +} { + + # protect from circular redirects + global __rp_internal_redirect_recursion_counter + if { ![info exists __rp_internal_redirect_recursion_counter] } { + set __rp_internal_redirect_recursion_counter 0 + } elseif { $__rp_internal_redirect_recursion_counter > 10 } { + error "rp_internal_redirect: Recursion limit exceeded." + } else { + incr __rp_internal_redirect_recursion_counter + } + + if { [string is false $absolute_path_p] } { + if { [string index $path 0] != "/" } { + # it's a relative path, prepend the current location + set path "[file dirname [ad_conn file]]/$path" + } else { + set path "[acs_root_dir]$path" + } + } + + # save the current file setting + set saved_file [ad_conn file] + + rp_serve_abstract_file $path + + # restore the file setting. we need to do this because + # rp_serve_abstract_file sets it to the path we internally + # redirected to, and rp_handler will cache the file setting + # internally in the tcl_url2file variable when PerformanceModeP is + # switched on. This way it caches the location that was originally + # requested, not the path that we redirected to. + ad_conn -set file $saved_file +} + +ad_proc rp_getform {} { + + This proc is a simple wrapper around AOLserver's standard ns_getform + proc, that will create the form if it doesn't exist, so that you + can then add values to that form. This is useful in conjunction + with rp_internal_redirect to redirect to a different page with + certain query variables set. + + @author Lars Pind (lars@pinds.com) + @creation-date August 20, 2002 + + @return the form ns_set, just like ns_getform, except it will + always be non-empty. + +} { + # The form may not exist, if there's nothing in it + if { ![empty_string_p [ns_getform]] } { + # It's there + return [ns_getform] + } { + # It doesn't exist, create a new one + + # This is the magic global Tcl variable that AOLserver uses + # to store the ns_set that contains the query args or form. + global _ns_form + + # Simply create a new ns_set and store it in the global _ns_set variable + set _ns_form [ns_set create] + return $_ns_form + } +} + +ad_proc rp_form_put { name value } { + + This proc adds a query variable to AOLserver's internal ns_getform + form, so that it'll be picked up by ad_page_contract and other procs + that look at the query variables or form supplied. This is useful + when you do an rp_internal_redirect to a new page, and you want to + feed that page with certain query variables. + + @author Lars Pind (lars@pinds.com) + @creation-date August 20, 2002 + + @return the form ns_set, in case you're interested. Mostly you'll + probably want to discard the result. + + } { + set form [rp_getform] + ns_set put $form $name $value + return $form +} + + ad_proc ad_return { args } { Works like the "return" Tcl command, with one difference. Where @@ -389,6 +500,28 @@ # End of patch "hostname-based subsites" # ------------------------------------------------------------------------- + # Force the URL to look like [ns_conn location], if desired... + + # JCD: Only do this if ForceHostP set and root is {} + # if root non empty then we had a hostname based subsite and + # should not redirect since we got a hostname we know about. + + set acs_kernel_id [util_memoize ad_acs_kernel_id] + if { [empty_string_p $root] + && [ad_parameter -package_id $acs_kernel_id ForceHostP request-processor 0] } { + set host_header [ns_set iget [ns_conn headers] "Host"] + regexp {^([^:]*)} $host_header "" host_no_port + regexp {^https?://([^:]+)} [ns_conn location] "" desired_host_no_port + if { $host_header != "" && [string compare $host_no_port $desired_host_no_port] } { + set query [ns_getform] + if { $query != "" } { + set query "?[export_entire_form_as_url_vars]" + } + ad_returnredirect "[ns_conn location][ns_conn url]$query" + return "filter_return" + } + } + # DRB: a bug in ns_conn causes urlc to be set to one and urlv to be set to # {} if you hit the site with the host name alone. This confuses code that # expects urlc to be set to zero and the empty list. This bug is probably due @@ -425,6 +558,7 @@ ad_conn -set package_id $node(object_id) ad_conn -set package_key $node(package_key) ad_conn -set package_url $node(url) + ad_conn -set instance_name $node(instance_name) ad_conn -set extra_url [string range [ad_conn url] [string length $node(url)] end] } @@ -466,9 +600,9 @@ if { ![empty_string_p [ad_conn object_id]]} { ad_try { if {[string match "admin/*" [ad_conn extra_url]]} { - ad_require_permission [ad_conn object_id] admin + permission::require_permission -object_id [ad_conn object_id] -privilege admin } else { - ad_require_permission [ad_conn object_id] read + permission::require_permission -object_id [ad_conn object_id] -privilege read } } ad_script_abort val { rp_finish_serving_page @@ -520,11 +654,11 @@ set error_url [ad_conn url] if { [llength [info procs ds_collection_enabled_p]] == 1 && [ds_collection_enabled_p] } { - ds_add conn error $message + ad_call_proc_if_exists ds_add conn error $message } if {![ad_parameter -package_id [ad_acs_kernel_id] "RestrictErrorsToAdminsP" dummy 0] || \ - [ad_permission_p [ad_conn package_id] admin] } { + [permission::permission_p -object_id [ad_conn package_id] -privilege admin] } { if { [ad_parameter -package_id [ad_acs_kernel_id] "AutomaticErrorReportingP" "rp" 0] } { set error_info $message set report_url [ad_parameter -package_id [ad_acs_kernel_id] "ErrorReportURL" "rp" ""] @@ -533,11 +667,11 @@ } else { set auto_report 1 ns_returnerror 200 " -
+ [export_form_vars error_url error_info] This file has generated an error. - -

+ +
[ns_quotehtml $error_info]
[ad_footer]" } } else { @@ -552,7 +686,11 @@ programmers. " } - ns_log Error "[ns_conn method] $error_url [ns_conn query] $message" + set headers [ns_conn headers] + ns_log "Error" "[ns_conn method] http://[ns_set iget $headers host][ns_conn url]?[ns_conn query] +referred by \"[ns_set iget $headers referer]\" +$message" + } ad_proc -private rp_path_prefixes {path} { @@ -712,14 +850,18 @@ {-extension_pattern ".*"} path } { + Serves up a file given the abstract path. Raises the following + exceptions in the obvious cases: + - Serves up a file given the abstract path. Raises the following - exceptions in the obvious cases: + Should not be used in .vuh files or elsewhere, instead + use the public function rp_internal_redirect. - notfound (passes back an empty value) - redirect (passes back the url to which it wants to redirect) - directory (passes back the path of the directory) - + @see rp_internal_redirect } { if { [string equal [string index $path end] "/"] } { if { [file isdirectory $path] } { @@ -872,6 +1014,7 @@ You probably want ad_acs_kernel_id, that is what has all the useful parameters. + @see ad_acs_kernel_id } { return [db_string acs_admin_id_get { select package_id from apm_packages @@ -882,7 +1025,7 @@ ad_proc -public ad_conn {args} { Returns a property about the connection. See the request + href="/doc/request-processor.html">request processor documentation for a list of allowable values. If -set is passed then it sets a property. @@ -931,6 +1074,7 @@ object_type "" package_id "" package_url "" + instance_name "" package_key "" extra_url "" file "" @@ -942,11 +1086,23 @@ } -get { - if { [info exists ad_conn($var)] } { - return $ad_conn($var) - } else { - return [ns_conn $var] - } + # Special handling for the form, because "ns_conn form" can + # cause the server to hang until the socket times out. This + # happens on pages handling multipart form data, where + # ad_page_contract already has called ns_getform and has + # retrieved all data from the client. ns_getform has its + # own caching, so calling it instead of [ns_conn form] + # is OK. + + if { $var == "form" } { + return [ns_getform] + } + + if { [info exists ad_conn($var)] } { + return $ad_conn($var) + } else { + return [ns_conn $var] + } } default {