Next: , Previous: User identification, Up: Top

5 TCL evaluation within wiki

It is here assumed that user has some general feeling about what is a wiki. Trac from edgewall and XWiki from have a killer feature of being able to embed computer programs to wikipages but trac is a bit specialized (and good for keeping your sw project) and xwiki supports odd languages.

While schtonk is entirely written in TCL it is jolly good idea to invoke [ interp create -safe i] to do work. Schtonk gives users a safe interpreter (meaning no file system access, a lot of fancy thingies like sockets removed, sorry) but with database access. Look at example

      == Schtonk page for displaying number of pages in DB ==
     Page count is
     return [ mysqlsel "select count(*) from pages" ]

when this page is processed inside backend.tcl the TCL snippet between SCHTONK_TCL_CODE_BEGIN/END will be extracted and fed to TCL interpreter. This particular code happens to return an integer (or possible error message). This integer is put in place of the code snippet so after TCL evaluation the page will look something like this

      == Schtonk page for displaying number of pages in DB ==
     Page count is

this, in turn, is fed to Wiki-formatter that will convert it to HTML and serve the result to client. All TCL code is run before wiki-formatting takes place so by having TCL code inside pages that returns just plain text or (better yet) wiki-formatted text1 formattings and content may be generated on the fly. As mysql may be used from within TCL code, some amount of content may be made available via schtonk.
There may be any number of TCL snippets, length is not limited. Even tough each TCL snippet is evaluated as anonymous script the performance of schtonk doesn't seem that bad. Should you want to deploy schtonk for tens of thousands of concurrent users, modification would be needed as right now there is single instance of backend.tcl and even that is not multithread so there is bottleneck of one CPU.

The things supported by TCL in schtonk are

  1. Everything a safe interpreter supports.
  2. command mysqlsel for doing a select statement. It expects a single string as argument, that is supposed to contain a valid select statement. What is returned is select results as a TCL list. So it may be required to loop over results like this
              set retval {}
              set select_res [ mysqlsel "select a,b from a_table order by a" ]
              	foreach one_line $select_res {
              	    set a [ lindex $one_line 0 ]
              	    set b [ lindex $one_line 1 ]
              	    set retval      "$retval || a is $a || b is $b ||\n"
              return $retval

    where foreach goes for each row, lindex inside loop is used to pick particular table column value from list that represents single column value.

  3. command mysqlexec for doing non-select SQL, like update or delete.
  4. command mysqlescape for escaping strings. It is good idea to feed strings that go between quotation marks in update-statements through this procedure if you don't know what there might be in the strings.

Variables pageid2, lang3, remote_user4, page_param5 and posted_fields6 are given to interpreter with names listed here. Posted fields is an array and if there is no posted fields, the array does not exists, therefore it is usually good idea to condition with
     [ array exists posted_fields ]

The indexes of the array are names of the fields in the posted form. Values then hold the values. If, for instance, there is a form, it may be referenced like this:

     [{FormOpen form='das_form'}]
     a field [{FormTextarea name='field1' rows=1 cols=10}]
     do submit form:
     [{FormInput type='submit' value='do submit' name='s_button'}]
      set retval {}
      if { [ array exists posted_fields ] == 1 } {
        set retval [ format {Value of a field is %s} $posted_fields(field1) ]
      return $retval

This utterly intelligent piece here prints back value from field as user posts it. Array posted_fields may be altered with TCL, when field is given to user the fields do get their values from posted_fields array if one exists ; this may be useful when fetching form content from database. At time of writing, the name of the form is not passed to TCL interpreter so if you're having multiple forms in one page and don't know which to process, it may be good idea to always name the submit button with same name and then condition in value of submit-button (here s_button) but other strategies may exist too.


[1] including forms

[2] integer specifying page

[3] ISO 639 language code

[4] httpd username as identified by httpd

[5] possible string given in braces after pageid

[6] posted form contents