Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add wapp-allow-xorigin-params and SAME_ORIGIN. Update the documentation accordingly. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
e82121be4d2be5fa96cae2b1a610b67b |
User & Date: | drh 2018-01-30 23:46:10.970 |
Context
2018-01-31
| ||
00:19 | Add a restrictive default Content Security Policy and provide the wapp-content-security-policy command to change it if necessary. (check-in: 4022bf292d user: drh tags: trunk) | |
2018-01-30
| ||
23:46 | Add wapp-allow-xorigin-params and SAME_ORIGIN. Update the documentation accordingly. (check-in: e82121be4d user: drh tags: trunk) | |
20:36 | Update example scripts to remove uses of the ::wapp dict. Improvements to the documentation. (check-in: 5d5c1559d7 user: drh tags: trunk) | |
Changes
Changes to README.md.
︙ | ︙ | |||
98 99 100 101 102 103 104 | wapp-trim { <h1>Hello, World!</h1> <p>See the <a href='%html($B)/env'>Wapp Environment</a></p> } } proc wapp-page-env {} { | | | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | wapp-trim { <h1>Hello, World!</h1> <p>See the <a href='%html($B)/env'>Wapp Environment</a></p> } } proc wapp-page-env {} { wapp-allow-xorigin-params wapp-subst {<h1>Wapp Environment</h1>\n<pre>\n} foreach var [lsort [wapp-param-list]] { if {[string index $var 0]=="."} continue wapp-subst {%html($var) = %html([list [wapp-param $var]])\n} } wapp-subst {</pre>\n} } |
︙ | ︙ | |||
129 130 131 132 133 134 135 | The /env page is implemented by the "wapp-page-env" proc. This proc generates HTML that describes all of the query parameters. Parameter names that begin with "." are for internal use by Wapp and are skipped for this display. Notice the use of "wapp-subst" to safely escape text for inclusion in an HTML document. 4.0 Parameters | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < > > > > > | < < < | < < < < | | | < < | < < < < < < > > > > > > > > > > > > | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 | The /env page is implemented by the "wapp-page-env" proc. This proc generates HTML that describes all of the query parameters. Parameter names that begin with "." are for internal use by Wapp and are skipped for this display. Notice the use of "wapp-subst" to safely escape text for inclusion in an HTML document. 4.0 Parameters -------------- To better understand Wapp parameters, try running the previous sample program, but extend the /env URL with extra path elements and query parameters. For example: <http://localhost:8080/env/longer/path?q1=5&title=hello+world%21> Notice how the query parameters in the input URL are decoded and become parameters. The same thing occurs with POST parameters and cookies - they are all converted into parameters accessible using the "wapp-param" interface. 4.1 Security By Default ----------------------- For security reasons, this automatic decoding of GET and POST parameters only occurs if inbound request is from the "same origin" or if the special "wapp-allow-xorigin-params" interface is called. An inbound request is from the same origin if it is in response to clicking on a hyperlink or form on a page that was generated by the same website. Manually typing in a URL does not constitute the "same origin". Hence, in the example above the "wapp-allow-xorigin-params" interface is used so that you can manually extend the URL to add new query parameters. If query parameters can have side effects, then you should omit the wapp-allow-xorigin-params call. Only invoke wapp-allow-xorigin-params for web pages that only query information. Do not invoke wapp-allow-xorigin-params on pages where the parameters can be used to change server-side state. 4.2 Environment Parameters -------------------------- Wapp also provides parameters that describe the execution environment. These parameter look like CGI environment variables. To prevent environment information from overlapping and overwriting query parameters, all the environment information uses upper-case names and all query parameters are required to be lower case. If an input URL contains an upper-case query parameter (or POST parameter or cookie), that parameter is silently omitted. The following environment parameters are always available: + **CONTENT\_LENGTH** The number of bytes of POST data. + **CONTENT\_TYPE** The mimetype of the POST data. Usually this is application/x-www-form-urlencoded. + **HTTP\_COOKIE** The values of all cookies in the HTTP header + **HTTP\_HOST** The hostname (or IP address) and port that the client used to create the current HTTP request. This is the first part of the request URL, right after the "http://" or "https://". The format for this value is "HOST:PORT". Examples: "sqlite.org:80" or "127.0.0.1:32172". + **HTTP\_USER\_AGENT** The name of the web-browser or other client program that generated the current HTTP request. + **HTTPS** If the HTTP request arrived of SSL (via "https://"), then this variable has the value "on". For an unencrypted request ("http://"), this variable does not exist. + **PATH\_INFO** The part of the URL path that follows the SCRIPT\_NAME. For all modes other than CGI, this is exactly the URL pathname, though with the query parameters removed. PATH_INFO begins with a "/". + **REMOTE\_ADDR** The IP address from which the HTTP request originated. + **REMOTE\_PORT** The TCP port from which teh HTTP request originated. + **REQUEST\_METHOD** "GET" or "HEAD" or "POST" + **REQUEST\_URI** The URL for the inbound request, without the initial "http://" or "https://" and without the HTTP\_HOST. This variable is the same as the concatenation of $SCRIPT\_NAME and $PATH\_INFO. + **SCRIPT_NAME** In CGI mode, this is the name of the CGI script in the URL. In other words, this is the initial part of the URL path that identifies the CGI script. For other modes, this variable is an empty string. All of the above are standard CGI environment values. The following are supplemental environment parameters are added by Wapp: + **BASE\_URL** The text of the request URL through the SCRIPT\_NAME. This value can be prepended to hyperlinks to ensure that the correct page is reached by those hyperlinks. + **CONTENT** The raw POST data text. + **PATH\_HEAD** The first element in the PATH\_INFO. The value of PATH\_HEAD is used to select one of the "wapp-page-XXXXX" commands to run in order to generate the output web page. + **PATH\_TAIL** All of PATH\_INFO that follows PATH\_HEAD. + **SAME\_ORIGIN** This value is either "1" or "0" depending on whether the current HTTP request is a follow-on to another request from this same website or not. Query parameters and POST parameters are usually only decoded and added to Wapp's parameter list if SAME\_ORIGIN is 1. If a webpage implemented by Wapp needs access to query parameters for a cross-origin request, then it should invoke the "wapp-allow-xorigin-params" interface to explicitly signal that cross-origin parameters are safe for that page. + **SELF\_URL** The URL for the current page, stripped of query parameter. This is useful for filling in the action= attribute of forms. ### 4.1 URL Parsing Example |
︙ | ︙ | |||
297 298 299 300 301 302 303 304 305 306 307 308 309 310 | currentn request. + **wapp-param-list** _NAME_ Return a TCL list containing the names of all parameters for the current request. Note that there are several parameters that Wapp uses internally. Those internal-use parameters all have names that begin with ".". + **wapp-mimetype** _MIMETYPE_ Set the MIME-type for the generated web page. The default is "text/html". + **wapp-reply-code** _CODE_ Set the reply-code for the HTTP request. The default is "200 Ok". | > > > > > > > > | 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 | currentn request. + **wapp-param-list** _NAME_ Return a TCL list containing the names of all parameters for the current request. Note that there are several parameters that Wapp uses internally. Those internal-use parameters all have names that begin with ".". + **wapp-allow-xorigin-params** Query parameters and POST parameters are usually only parsed and added to the set of parameters available to "wapp-param" for same-origin requests. This restriction helps prevent cross-site request forgery (CSRF) attacks. Query-only web pages for which it is safe to accept cross-site query parameters can invoke this routine to cause query parameters to be decoded. + **wapp-mimetype** _MIMETYPE_ Set the MIME-type for the generated web page. The default is "text/html". + **wapp-reply-code** _CODE_ Set the reply-code for the HTTP request. The default is "200 Ok". |
︙ | ︙ | |||
438 439 440 441 442 443 444 | The POST data parser for Wapp currently only understands application/x-www-form-urlencoded content. Wapp does not (currently) have a decoder for multipart/form-data content. A multipart/form-data decoder might be added in the future. Or, individual applications can implement their own multipart/form-data decoder using the raw POST data held in the CONTENT parameter. | < < < < < < < | 476 477 478 479 480 481 482 483 484 485 486 487 488 | The POST data parser for Wapp currently only understands application/x-www-form-urlencoded content. Wapp does not (currently) have a decoder for multipart/form-data content. A multipart/form-data decoder might be added in the future. Or, individual applications can implement their own multipart/form-data decoder using the raw POST data held in the CONTENT parameter. 8.0 Design Rules ---------------- All global procs and variables used by Wapp begin with the four character prefix "wapp". Procs and variable intended for internal use begin with the seven character prefix "wappInt". |
Changes to examples/env.tcl.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # This script is a template used for testing. # # After making modifications to this script to test out bits of HTML # (or not - the script works fine as it is), invoke the script using # # wapptclsh env.tcl # # All web pages show the Wapp execution environment, which includes # CGI-line environment variables, decoded query and POST parameters, and # decoded cookies. # package require wapp proc wapp-default {} { wapp-trim { <h1>Wapp Environment</h1> <pre>%html([wapp-debug-env])</pre> } } wapp-start $argv | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # This script is a template used for testing. # # After making modifications to this script to test out bits of HTML # (or not - the script works fine as it is), invoke the script using # # wapptclsh env.tcl # # All web pages show the Wapp execution environment, which includes # CGI-line environment variables, decoded query and POST parameters, and # decoded cookies. # package require wapp proc wapp-default {} { wapp-allow-xorigin-params wapp-trim { <h1>Wapp Environment</h1> <pre>%html([wapp-debug-env])</pre> } } wapp-start $argv |
Changes to test01.tcl.
︙ | ︙ | |||
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | foreach vname [lsort [uplevel #0 info vars]] { set val ??? catch {set val [set ::$vname]} wapp-subst {<li>%html($vname = [list $val])</li>\n} } } proc wapp-page-env2 {} { wapp-trim { <h1>Wapp Environment using wapp-debug-env</h1> <pre>%html([wapp-debug-env])</pre> } } proc wapp-page-env {} { global wapp wapp-set-cookie env-cookie simple wapp "<h1>Wapp Environment</h1>\n" | > > > | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | foreach vname [lsort [uplevel #0 info vars]] { set val ??? catch {set val [set ::$vname]} wapp-subst {<li>%html($vname = [list $val])</li>\n} } } proc wapp-page-env2 {} { wapp-allow-xorigin-params wapp-trim { <h1>Wapp Environment using wapp-debug-env</h1> <p>This page uses wapp-allow-xorigin-params so that new query parameters may be added manually to the URL.</p> <pre>%html([wapp-debug-env])</pre> } } proc wapp-page-env {} { global wapp wapp-set-cookie env-cookie simple wapp "<h1>Wapp Environment</h1>\n" |
︙ | ︙ |
Changes to wapp.tcl.
︙ | ︙ | |||
242 243 244 245 246 247 248 249 250 251 252 253 254 255 | # Return all parameter names that match the GLOB pattern, or all # names if the GLOB pattern is omitted. # proc wapp-param-list {{glob {*}}} { global wapp return [dict keys $wapp $glob] } # Examine the bodys of all procedures in this program looking for # unsafe calls to "wapp". Return a text string containing warnings. # Return an empty string if all is ok. # # This routine is advisory only. It misses some constructs that are # dangerous and flags others that are safe. | > > > > > > > > > > > > > > > > > > > > > > > > > | 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 | # Return all parameter names that match the GLOB pattern, or all # names if the GLOB pattern is omitted. # proc wapp-param-list {{glob {*}}} { global wapp return [dict keys $wapp $glob] } # By default, Wapp does not decode query parameters and POST parameters # for cross-origin requests. This is a security restriction, designed to # help prevent cross-site request forgery (CSRF) attacks. # # As a consequence of this restriction, URLs for sites generated by Wapp # that contain query parameters will not work as URLs found in other # websites. You cannot create a link from a second website into a Wapp # website if the link contains query planner, by default. # # Of course, it is sometimes desirable to allow query parameters on external # links. For URLs for which this is safe, the application should invoke # wapp-allow-xorigin-params. This procedure tells Wapp that it is safe to # go ahead and decode the query parameters even for cross-site requests. # # In other words, for Wapp security is the default setting. Individual pages # need to actively disable the cross-site request security if those pages # are safe for cross-site access. # proc wapp-allow-xorigin-params {} { global wapp if {![dict exists $wapp .qp] && ![dict get $wapp SAME_ORIGIN]} { wappInt-decode-query-params } } # Examine the bodys of all procedures in this program looking for # unsafe calls to "wapp". Return a text string containing warnings. # Return an empty string if all is ok. # # This routine is advisory only. It misses some constructs that are # dangerous and flags others that are safe. |
︙ | ︙ | |||
526 527 528 529 530 531 532 533 534 535 536 537 538 539 | ACCEPT-ENCODING {set name HTTP_ACCEPT_ENCODING} default {set name .hdr:$name} } dict set W $name $value } return 0 } # Invoke application-supplied methods to generate a reply to # a single HTTP request. # # This routine always runs within [catch], so handle exceptions by # invoking [error]. # | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 | ACCEPT-ENCODING {set name HTTP_ACCEPT_ENCODING} default {set name .hdr:$name} } dict set W $name $value } return 0 } # Decode the QUERY_STRING parameters from a GET request or the # application/x-www-form-urlencoded CONTENT from a POST request. # # This routine sets the ".qp" element of the ::wapp dict as a signal # that query parameters have already been decoded. # proc wappInt-decode-query-params {} { global wapp dict set wapp .qp 1 if {[dict exists $wapp QUERY_STRING]} { foreach qterm [split [dict get $wapp QUERY_STRING] &] { set qsplit [split $qterm =] set nm [lindex $qsplit 0] if {[regexp {^[a-z][a-z0-9]*$} $nm]} { dict set wapp $nm [wappInt-decode-url [lindex $qsplit 1]] } } } if {[dict exists $wapp CONTENT_TYPE] && [dict get $wapp CONTENT_TYPE]=="application/x-www-form-urlencoded" && [dict exists $wapp CONTENT] } { foreach qterm [split [string trim [dict get $wapp CONTENT]] &] { set qsplit [split $qterm =] set nm [lindex $qsplit 0] if {[regexp {^[a-z][-a-z0-9_]*$} $nm]} { dict set wapp $nm [wappInt-decode-url [lindex $qsplit 1]] } } } # To-Do: Perhaps add support for multipart/form-data decoding. # Alternatively, perhaps multipart/form-data decoding can be done # by application code using a separate helper function, like # "wapp_decode_multipart_formdata" or somesuch. } # Invoke application-supplied methods to generate a reply to # a single HTTP request. # # This routine always runs within [catch], so handle exceptions by # invoking [error]. # |
︙ | ︙ | |||
588 589 590 591 592 593 594 | set qsplit [split [string trim $qterm] =] set nm [lindex $qsplit 0] if {[regexp {^[a-z][-a-z0-9_]*$} $nm]} { dict set wapp $nm [wappInt-decode-url [lindex $qsplit 1]] } } } | < < < < < < < < < < < < | < < < < | | < | | > | > < < < < | 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 | set qsplit [split [string trim $qterm] =] set nm [lindex $qsplit 0] if {[regexp {^[a-z][-a-z0-9_]*$} $nm]} { dict set wapp $nm [wappInt-decode-url [lindex $qsplit 1]] } } } if {[dict exists $wapp HTTP_REFERER] && [string match [dict get $wapp BASE_URL]/* [dict get $wapp HTTP_REFERER]] } { set same_origin 1 } else { set same_origin 0 } dict set wapp SAME_ORIGIN $same_origin if {$same_origin} { wappInt-decode-query-params } # Invoke the application-defined handler procedure for this page # request. If an error occurs while running that procedure, generate # an HTTP reply that contains the error message. # wapp-before-dispatch-hook wappInt-trace |
︙ | ︙ |