When to use URLencode
In general, HTTP requires that URLs are properly encoded. This is not a big issue, when just plain ASCII characters without special characters are used in URL paths and query variables. However, when the framework allows the end-user to define also URLs (such as in xowiki and derivatives), one has to be careful when extending the framework. The section below refers to the behavior in OpenACS 5.10, earlier version might differ in some details.
URLs in HTML
When URLs are embedded in HTML (href, src, ...) the URL must be both first urlencoded and then HTML quoted to be on the safe side from the
point of view of HTML. Although most characters problematic for HTML are encoded by ns_urlencode, but the single quote is not (this is not a bug but according to the specs, RFC 3986).
ns_urlencode {<a> 'b' "c" &} # returns: %3ca%3e+'b'+%22c%22+%26
Only, when it can be guaranteed the the URL contains no "funny characters" the URLencoding can be omitted. Note that double encoding with ns_urlencode leads to over-quoting in the same way as double encoding with ns_quotehtml.
Return_urls
In general, return_urls have to be proper URL encoded according to the HTTP specs. Setting these URLs is more complex, since one has to be aware whether or not an URL as encoded before or not before passing it as a return URL.
Here is a short guideline:
1) Query functions return URLs always URLdecoded
- ns_conn url
- ad_conn url
- xo::cc url
2) Output functions return URLs per default URLencoded
- export_vars (input parameter "-base" has to be unencoded)
- ad_return_url
- :pretty_link
3) Redirect operations have to receive encoded input
- ad_returnredirect
- ns_returnredirect
- :returnredirect
4) Query-variables
When setting query variables with URLs, these should be already URL encoded
# # Setting a query variable # set return_url [ad_returnurl] set url [export_vars -base . {return_url}] # # Using query-variable as default value in xo* package # ad_returnredirect [:query_parameter return_url:localurl [ad_return_url]] # # Usage in classical OpenACS # ... # get return_url e.g. via page_contract ... if {[info exists return_url] && $return_url ne ""} { ad_returnredirect $return_url }