Wapp

Check-in [e17c170f16]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Typos from Andreas. Added the file-upload test to test01.tcl.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: e17c170f16e793a0ddec14755f96cecc534da057b462e073f08e5f29ddada247
User & Date: drh 2018-02-08 12:15:43.530
Context
2018-02-08
12:31
More improvements to test01.tcl. (check-in: cea1360863 user: drh tags: trunk)
12:15
Typos from Andreas. Added the file-upload test to test01.tcl. (check-in: e17c170f16 user: drh tags: trunk)
04:42
Fix minor problems with the two self-scripts. (check-in: b25f6825c5 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to docs/compiling.md.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
How To Compile, Or Not
======================

1.0 Use As Pure Tcl - No Compilation Required
---------------------------------------------

The Wapp framework is pure Tcl contained in a single file calls 
"[wapp.tcl](/file/wapp.tcl)".  That, and a generic "tclsh",
is all you need to run a Wapp application.

For example, when testing Wapp, the developers run the following command from
the root of the source tree:

>
    tclsh tests/test01.tcl

The [test01.tcl](/file/tests/test01.tcl) script does a "source ../wapp.tcl" to
load the Wapp framework.  No special interpreter is required.

The [search function](https://sqlite.org/search) of the SQLite homepage takes
this one step further.  The Tcl script that implements the search function embeds
the wapp.tcl script when the website is begin built.  The "wapp.tcl" is neither
"source"-ed or "package require"-ed.  The wapp.tcl script is embedded into the
"search" script.

2.0 Using A Special Interpreter
-------------------------------

It is sometimes convenient to use the special "wapptclsh" interpreter to run
Wapp applications.  The "wapptclsh" works just like ordinary "tclsh" with the
following minor differences:

  +  Wapptclsh understands "package require wapp" natively, without any extra
     finagling.

  +  Wapptclsh comes with SQLite built-in.  SQLite turns out to be very handy
     for the kinds of small web applications that Wapp  is designed for.

  +  Wapptclsh builds (by default) statically linked, so that it works inside
     chroot jails that lack all the shared libraries needed by generic "tclsh".

To reiterate: "wapptclsh" is not required to run Wapp applications.  But it is
convenient.  The developer of Wapp prefers using "wapptclsh" on his installations.

2.1 Compiling The Special Interpreter
-------------------------------------

To build wapptclsh, make a copy of either Makefile or Makefile.macos in the
top-level directory of the source tree.  Change a few settings.  (This step is
not hard as each Makefile is less than 20 lines long.)  Then run the Makefile.

There is no configure scripts of other automation to help do the build.  Maybe
we will add one someday.  But for now, the Makefile is simple enough to work
stand-alone.






|














|
|















|












|


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
How To Compile, Or Not
======================

1.0 Use As Pure Tcl - No Compilation Required
---------------------------------------------

The Wapp framework is pure Tcl contained in a single file called
"[wapp.tcl](/file/wapp.tcl)".  That, and a generic "tclsh",
is all you need to run a Wapp application.

For example, when testing Wapp, the developers run the following command from
the root of the source tree:

>
    tclsh tests/test01.tcl

The [test01.tcl](/file/tests/test01.tcl) script does a "source ../wapp.tcl" to
load the Wapp framework.  No special interpreter is required.

The [search function](https://sqlite.org/search) of the SQLite homepage takes
this one step further.  The Tcl script that implements the search function embeds
the wapp.tcl script when the website is built.  The "wapp.tcl" is neither
"source"-ed nor "package require"-ed.  The wapp.tcl script is embedded into the
"search" script.

2.0 Using A Special Interpreter
-------------------------------

It is sometimes convenient to use the special "wapptclsh" interpreter to run
Wapp applications.  The "wapptclsh" works just like ordinary "tclsh" with the
following minor differences:

  +  Wapptclsh understands "package require wapp" natively, without any extra
     finagling.

  +  Wapptclsh comes with SQLite built-in.  SQLite turns out to be very handy
     for the kinds of small web applications that Wapp  is designed for.

  +  Wapptclsh builds are (by default) statically linked, so that it works inside
     chroot jails that lack all the shared libraries needed by generic "tclsh".

To reiterate: "wapptclsh" is not required to run Wapp applications.  But it is
convenient.  The developer of Wapp prefers using "wapptclsh" on his installations.

2.1 Compiling The Special Interpreter
-------------------------------------

To build wapptclsh, make a copy of either Makefile or Makefile.macos in the
top-level directory of the source tree.  Change a few settings.  (This step is
not hard as each Makefile is less than 20 lines long.)  Then run the Makefile.

There is no configure scripts or other automation to help do the build.  Maybe
we will add one someday.  But for now, the Makefile is simple enough to work
stand-alone.
Changes to docs/intro.md.
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

To run this same program as a traditional web-server on TCP port 8080, enter:

>
    wapptclsh main.tcl --server 8080

Here the built-in web-server listens on all IP addresses and so the
web page is available on other machines.  But the web-brwser is not
automatically started in this case, so you will have to manually enter
"http://localhost:8080/" into your web-browser in order to see the page.

To run this program as CGI, put the main.tcl script in your web-servers
file hierarchy, in the appropriate place for CGI scripts, and make any
other web-server specific configuration changes so that the web-server
understands that the main.tcl file is a CGI script.  Then point your







|







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

To run this same program as a traditional web-server on TCP port 8080, enter:

>
    wapptclsh main.tcl --server 8080

Here the built-in web-server listens on all IP addresses and so the
web page is available on other machines.  But the web-browser is not
automatically started in this case, so you will have to manually enter
"http://localhost:8080/" into your web-browser in order to see the page.

To run this program as CGI, put the main.tcl script in your web-servers
file hierarchy, in the appropriate place for CGI scripts, and make any
other web-server specific configuration changes so that the web-server
understands that the main.tcl file is a CGI script.  Then point your
Changes to examples/self.tcl.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/wapptclsh
#
# This script demonstrates a Wapp application that can display a copy
# of itself via the /self page.  (See the wapp-page-self procedure for
# how that one page is generated.)
#
# This script also has a homepage and an /env page that show the wapp
# environment.  The header and footer for each page is broken out into
# separate subroutines.
#
# Just for grins, there is also a style-sheet and some cache-control
# lines to show how those things work.
#
package require wapp
proc common-header {} {







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/wapptclsh
#
# This script demonstrates a Wapp application that can display a copy
# of itself via the /self page.  (See the wapp-page-self procedure for
# how that one page is generated.)
#
# This script also has a homepage and an /env page that show the wapp
# environment.  The header and footer for each page are broken out into
# separate subroutines.
#
# Just for grins, there is also a style-sheet and some cache-control
# lines to show how those things work.
#
package require wapp
proc common-header {} {
Changes to examples/self2.tcl.
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  wapp-trim {
    <html>
    <head>
    <link href="%url([wapp-param SCRIPT_NAME]/style.css)" rel="stylesheet">
    <title>Wapp Self-Display Demo</title>
    </head>
    <body>
    <p>In the box below is shown the Wapp script that generated this page.
    Change the foreground color using the color= query parameter.
    Examples:</p>
    <ul>
    <li><a href='%url($self?color=red)'>%html($self?color=red)</a>
    <li><a href='%url($self?color=green)'>%html($self?color=green)</a>
    <li><a href='%url($self?color=blue)'>%html($self?color=blue)</a>
    <li><a href='%url($self)?color=%23003f7f'>%html($self?color=%23003f7f)</a>







|







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  wapp-trim {
    <html>
    <head>
    <link href="%url([wapp-param SCRIPT_NAME]/style.css)" rel="stylesheet">
    <title>Wapp Self-Display Demo</title>
    </head>
    <body>
    <p>The box below shows the Wapp script that generated this page.
    Change the foreground color using the color= query parameter.
    Examples:</p>
    <ul>
    <li><a href='%url($self?color=red)'>%html($self?color=red)</a>
    <li><a href='%url($self?color=green)'>%html($self?color=green)</a>
    <li><a href='%url($self?color=blue)'>%html($self?color=blue)</a>
    <li><a href='%url($self)?color=%23003f7f'>%html($self?color=%23003f7f)</a>
Changes to tests/test01.tcl.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Invoke as "tclsh test01.tcl" and then surf the website that pops up
# to verify the logic in wapp.
#
if {[catch {package require wapp}]} {
  if {[catch {source wapp.tcl}]} {
    source ../wapp.tcl
  }
}
proc wapp-default {} {
  global wapp
  set B [wapp-param BASE_URL]
  set R [wapp-param SCRIPT_NAME]
  wapp-cache-control max-age=15
  wapp "<h1>Hello, World!</h1>\n"




<
|
<







1
2
3
4

5

6
7
8
9
10
11
12
# Invoke as "tclsh test01.tcl" and then surf the website that pops up
# to verify the logic in wapp.
#
if {[catch {package require wapp}]} {

  source [file dir [file dir [info script]]]/wapp.tcl

}
proc wapp-default {} {
  global wapp
  set B [wapp-param BASE_URL]
  set R [wapp-param SCRIPT_NAME]
  wapp-cache-control max-age=15
  wapp "<h1>Hello, World!</h1>\n"
22
23
24
25
26
27
28

29

30
31
32
33
34
35
36
  wapp-trim {
    <li><p><a href='%html($B)/lint'>Lint</a>
    <li><p><a href='%html($B)/errorout'>Deliberate error</a>
    <li><p><a href='%html($B)/encodings'>Encoding checks</a>
    <li><p><a href='%html($B)/redirect'>Redirect to env</a>
    <li><p><a href='globals'>TCL global variables</a>
    <li><p><a href='csptest'>Content Security Policy</a>

    <li><p><a href='fileupload'>File Upload Using multipart/form-data</a>

  }
  set x "%string(...)"
  set v abc'def\"ghi\\jkl
  wapp-subst {<li>%html($x) substitution test: "%string($v)"\n}
  wapp "</ol>"
  if {[dict exists $wapp showenv]} {
    wapp-page-env







>
|
>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
  wapp-trim {
    <li><p><a href='%html($B)/lint'>Lint</a>
    <li><p><a href='%html($B)/errorout'>Deliberate error</a>
    <li><p><a href='%html($B)/encodings'>Encoding checks</a>
    <li><p><a href='%html($B)/redirect'>Redirect to env</a>
    <li><p><a href='globals'>TCL global variables</a>
    <li><p><a href='csptest'>Content Security Policy</a>
    <li><p><a href='%url($B)/fileupload'>File Upload
    Using multipart/form-data</a>
    <li><p><a href='%url($B)/self'>The source code to this script</a>
  }
  set x "%string(...)"
  set v abc'def\"ghi\\jkl
  wapp-subst {<li>%html($x) substitution test: "%string($v)"\n}
  wapp "</ol>"
  if {[dict exists $wapp showenv]} {
    wapp-page-env
208
209
210
211
212
213
214










215
216
217
218
219
220
221
    <h1>Content Security Policy Test Page</h1>
    <p> There is a &lt;script&gt; at the bottom of
    this page that will invoke an alert().  The
    script will be disabled by the default CSP.
    <p>Use the csp= query parameter to change CSP.
    <script>alert("This is the alert");</script>
  }










}
proc wapp-page-drh.jpg {} {
  wapp-mimetype image/jpeg
  wapp-cache-control max-age=3600
  wapp-unsafe [binary decode base64 {
    /9j/4AAQSkZJRgABAQEAlgCWAAD//gAeTEVBRCBUZWNobm9sb2dpZXMgSW5jLiBW
    MS4wMf/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg







>
>
>
>
>
>
>
>
>
>







208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
    <h1>Content Security Policy Test Page</h1>
    <p> There is a &lt;script&gt; at the bottom of
    this page that will invoke an alert().  The
    script will be disabled by the default CSP.
    <p>Use the csp= query parameter to change CSP.
    <script>alert("This is the alert");</script>
  }
}
proc wapp-page-self {} {
  set fd [open [wapp-param SCRIPT_FILENAME] rb]
  set script [read $fd]
  close $fd
  wapp-content-security-policy {default-src 'inline' 'unsafe-inline'}
  wapp-trim {
    <h1>Source code to this script</h1>
    <pre style='border: 1px solid black;'>%html($script)</pre>
  }
}
proc wapp-page-drh.jpg {} {
  wapp-mimetype image/jpeg
  wapp-cache-control max-age=3600
  wapp-unsafe [binary decode base64 {
    /9j/4AAQSkZJRgABAQEAlgCWAAD//gAeTEVBRCBUZWNobm9sb2dpZXMgSW5jLiBW
    MS4wMf/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicg