|
1
|
TH1 Scripts |
|
2
|
=========== |
|
3
|
|
|
4
|
TH1 is a very small scripting language used to help generate web-page |
|
5
|
content in Fossil. |
|
6
|
|
|
7
|
Origins |
|
8
|
------- |
|
9
|
|
|
10
|
TH1 began as a minimalist re-implementation of the Tcl scripting language. |
|
11
|
There was a need to test the SQLite library on Symbian phones, but at that |
|
12
|
time all of the test cases for SQLite were written in Tcl and Tcl could not |
|
13
|
be easily compiled on the SymbianOS. So TH1 was developed as a cut-down |
|
14
|
version of Tcl that would facilitate running the SQLite test scripts on |
|
15
|
SymbianOS. |
|
16
|
|
|
17
|
Fossil was first being designed at about the same time. |
|
18
|
Early prototypes of Fossil were written in pure Tcl. But as the development |
|
19
|
shifted toward the use of C-code, the need arose to have a Tcl-like |
|
20
|
scripting language to help with code generation. TH1 was small and |
|
21
|
light-weight and used minimal resources and seemed ideally suited for the |
|
22
|
task. |
|
23
|
|
|
24
|
The name "TH1" stands for "Test Harness 1", |
|
25
|
since its original purpose was to serve as testing harness |
|
26
|
for SQLite. |
|
27
|
|
|
28
|
Where TH1 Is Used In Fossil |
|
29
|
--------------------------- |
|
30
|
|
|
31
|
* In the header and footer for [skins](./customskin.md) |
|
32
|
text within `<th1>...</th1>` is run as a TH1 script. |
|
33
|
([example](/builtin/skins/default/header.txt)) |
|
34
|
|
|
35
|
* This display of [tickets](./bugtheory.wiki) is controlled by TH1 |
|
36
|
scripts, so that the ticket format can be customized for each |
|
37
|
project. Administrators can visit the <b>/tktsetup</b> page in |
|
38
|
their repositories to view and customize these scripts. |
|
39
|
([example usage](./custom_ticket.wiki)) |
|
40
|
|
|
41
|
Overview Of The Tcl/TH1 Language |
|
42
|
-------------------------------- |
|
43
|
|
|
44
|
TH1 is a string-processing language. All values are strings. Any numerical |
|
45
|
operations are accomplished by converting from string to numeric, performing |
|
46
|
the computation, then converting the result back into a string. (This might |
|
47
|
seem inefficient, but it is faster than people imagine, and numeric |
|
48
|
computations do not come up very often for the kinds of work that TH1 does, |
|
49
|
so it has never been an issue.) |
|
50
|
|
|
51
|
A TH1 script consists of a sequence of commands. |
|
52
|
Each command is terminated by the first *unescaped* newline or ";" character. |
|
53
|
The text of the command (excluding the newline or semicolon terminator) |
|
54
|
is broken into space-separated tokens. The first token is the command |
|
55
|
name and subsequent tokens are the arguments. In this sense, TH1 syntax |
|
56
|
is similar to the familiar command-line shell syntax. |
|
57
|
|
|
58
|
A token is any sequence of characters other than whitespace and semicolons. |
|
59
|
Text inside double-quotes is a single token even if it includes |
|
60
|
whitespace and semicolons. Text within {...} pairs is also a |
|
61
|
single token, which is useful because curly braces are easier to “pair” |
|
62
|
and nest properly than double-quotes. |
|
63
|
|
|
64
|
The nested {...} form of tokens is important because it allows TH1 commands |
|
65
|
to have an appearance similar to C/C++. It is important to remember, though, |
|
66
|
that a TH1 script is really just a list of text commands, not a context-free |
|
67
|
language with a grammar like C/C++. This can be confusing to long-time |
|
68
|
C/C++ programmers because TH1 does look a lot like C/C++, but the semantics |
|
69
|
of TH1 are closer to FORTH or Lisp than they are to C. |
|
70
|
|
|
71
|
Consider the `if` command in TH1. |
|
72
|
|
|
73
|
if {$current eq "dev"} { |
|
74
|
puts "hello" |
|
75
|
} else { |
|
76
|
puts "world" |
|
77
|
} |
|
78
|
|
|
79
|
The example above is a single command. The first token, and the name |
|
80
|
of the command, is `if`. |
|
81
|
The second token is `$current eq "dev"` - an expression. (The outer {...} |
|
82
|
are removed from each token by the command parser.) The third token |
|
83
|
is the `puts "hello"`, with its whitespace and newlines. The fourth token |
|
84
|
is `else` and the fifth and last token is `puts "world"`. |
|
85
|
|
|
86
|
The `if` command evaluates its first argument (the second token) |
|
87
|
as an expression, and if that expression is true, it evaluates its |
|
88
|
second argument (the third token) as a TH1 script. |
|
89
|
If the expression is false and the third argument is `else`, then |
|
90
|
the fourth argument is evaluated as a TH1 expression. |
|
91
|
|
|
92
|
So, you see, even though the example above spans five lines, it is really |
|
93
|
just a single command. |
|
94
|
|
|
95
|
All of this also explains the emphasis on *unescaped* characters above: |
|
96
|
the curly braces `{ }` are string quoting characters in Tcl/TH1, not |
|
97
|
block delimiters as in C. This is how we can have a command that extends |
|
98
|
over multiple lines. It is also why the `else` keyword must be cuddled |
|
99
|
up with the closing brace for the `if` clause's scriptlet. The following |
|
100
|
is invalid Tcl/TH1: |
|
101
|
|
|
102
|
if {$current eq "dev"} { |
|
103
|
puts "hello" |
|
104
|
} |
|
105
|
else { |
|
106
|
puts "world" |
|
107
|
} |
|
108
|
|
|
109
|
If you try to run this under either Tcl or TH1, the interpreter will |
|
110
|
tell you that there is no `else` command, because with the newline on |
|
111
|
the third line, you terminated the `if` command. |
|
112
|
|
|
113
|
Occasionally in Tcl/TH1 scripts, you may need to use a backslash at the |
|
114
|
end of a line to allow a command to extend over multiple lines without |
|
115
|
being considered two separate commands. Here's an example from one of |
|
116
|
Fossil's test scripts: |
|
117
|
|
|
118
|
return [lindex [regexp -line -inline -nocase -- \ |
|
119
|
{^uuid:\s+([0-9A-F]{40}) } [eval [getFossilCommand \ |
|
120
|
$repository "" info trunk]]] end] |
|
121
|
|
|
122
|
Those backslashes allow the command to wrap nicely within a standard |
|
123
|
terminal width while telling the interpreter to consider those three |
|
124
|
lines as a single command. |
|
125
|
|
|
126
|
<a id="taint"></a>Tainted And Untainted Strings |
|
127
|
----------------------------------------------- |
|
128
|
|
|
129
|
Beginning with Fossil version 2.26 (circa 2025), TH1 distinguishes between |
|
130
|
"tainted" and "untainted" strings. Tainted strings are strings that are |
|
131
|
derived from user inputs that might contain text that is designed to subvert |
|
132
|
the script. Untainted strings are known to come from secure sources and |
|
133
|
are assumed to contain no malicious content. |
|
134
|
|
|
135
|
Beginning with Fossil version 2.26, and depending on the value of the |
|
136
|
[vuln-report setting](/help/vuln-report), TH1 will prevent tainted |
|
137
|
strings from being used in ways that might lead to XSS or SQL-injection |
|
138
|
attacks. This feature helps to ensure that XSS and SQL-injection |
|
139
|
vulnerabilities are not *accidentally* added to Fossil when |
|
140
|
custom TH1 scripts for headers or footers or tickets are added to a |
|
141
|
repository. Note that the tainted/untainted distinction in strings does |
|
142
|
not make it impossible to introduce XSS and SQL-injections vulnerabilities |
|
143
|
using poorly-written TH1 scripts; it just makes it more difficult and |
|
144
|
less likely to happen by accident. Developers must still consider the |
|
145
|
security implications of TH1 customizations they add to Fossil, and take |
|
146
|
appropriate precautions when writing custom TH1. Peer review of TH1 |
|
147
|
script changes is encouraged. |
|
148
|
|
|
149
|
In Fossil version 2.26, if the vuln-report setting is set to "block" |
|
150
|
or "fatal", the [html](#html) and [query](#query) TH1 commands will |
|
151
|
fail with an error if their argument is a tainted string. This helps |
|
152
|
to prevent XSS and SQL-injection attacks, respectively. Note that |
|
153
|
the default value of the vuln-report setting is "log", which allows those |
|
154
|
commands to continue working and only writes a warning message into the |
|
155
|
error log. <b>Future versions of Fossil may change the default value |
|
156
|
of the vuln-report setting to "block" or "fatal".</b> Fossil users |
|
157
|
with customized TH1 scripts are encouraged to audit their customizations |
|
158
|
and fix any potential vulnerabilities soon, so as to avoid breakage |
|
159
|
caused by future upgrades. <b>Future versions of Fossil might also |
|
160
|
place additional restrictions on the use of tainted strings.</b> |
|
161
|
For example, it is likely that future versions of Fossil will disallow |
|
162
|
using tainted strings as script, for example as the body of a "for" |
|
163
|
loop or of a "proc". |
|
164
|
|
|
165
|
|
|
166
|
Summary of Core TH1 Commands |
|
167
|
---------------------------- |
|
168
|
|
|
169
|
The original Tcl language (after which TH1 is modeled) has a very rich |
|
170
|
repertoire of commands. TH1, as it is designed to be minimalist and |
|
171
|
embedded has a greatly reduced command set. The following bullets |
|
172
|
summarize the commands available in TH1: |
|
173
|
|
|
174
|
* array exists VARNAME |
|
175
|
* array names VARNAME |
|
176
|
* break |
|
177
|
* catch SCRIPT ?VARIABLE? |
|
178
|
* continue |
|
179
|
* error ?STRING? |
|
180
|
* expr EXPR |
|
181
|
* for INIT-SCRIPT TEST-EXPR NEXT-SCRIPT BODY-SCRIPT |
|
182
|
* foreach VARIABLE-LIST VALUE-LIST BODY-SCRIPT |
|
183
|
* if EXPR SCRIPT (elseif EXPR SCRIPT)* ?else SCRIPT? |
|
184
|
* info commands |
|
185
|
* info exists VARNAME |
|
186
|
* info vars |
|
187
|
* lappend VARIABLE TERM ... |
|
188
|
* lindex LIST INDEX |
|
189
|
* list ARG ... |
|
190
|
* llength LIST |
|
191
|
* lsearch LIST STRING |
|
192
|
* proc NAME ARG-LIST BODY-SCRIPT |
|
193
|
* rename OLD NEW |
|
194
|
* return ?-code CODE? ?VALUE? |
|
195
|
* set VARNAME VALUE |
|
196
|
* string compare STR1 STR2 |
|
197
|
* string first NEEDLE HAYSTACK ?START-INDEX? |
|
198
|
* string index STRING INDEX |
|
199
|
* string is CLASS STRING |
|
200
|
* string last NEEDLE HAYSTACK ?START-INDEX? |
|
201
|
* string match PATTERN STRING |
|
202
|
* string length STRING |
|
203
|
* string range STRING FIRST LAST |
|
204
|
* string repeat STRING COUNT |
|
205
|
* string trim STRING |
|
206
|
* string trimleft STRING |
|
207
|
* string trimright STRING |
|
208
|
* unset VARNAME |
|
209
|
* uplevel ?LEVEL? SCRIPT |
|
210
|
* upvar ?FRAME? OTHERVAR MYVAR ?OTHERVAR MYVAR? |
|
211
|
|
|
212
|
All of the above commands work as in the original Tcl. Refer to the |
|
213
|
<a href="https://www.tcl-lang.org/man/tcl/contents.htm">Tcl documentation</a> |
|
214
|
for details. |
|
215
|
|
|
216
|
Summary of Core TH1 Variables |
|
217
|
----------------------------- |
|
218
|
|
|
219
|
* tcl\_platform(engine) -- _This will always have the value "TH1"._ |
|
220
|
* tcl\_platform(platform) -- _This will have the value "windows" or "unix"._ |
|
221
|
* th\_stack\_trace -- _This will contain error stack information._ |
|
222
|
|
|
223
|
TH1 Extended Commands |
|
224
|
--------------------- |
|
225
|
|
|
226
|
There are many new commands added to TH1 and used to access the special |
|
227
|
features of Fossil. The following is a summary of the extended commands: |
|
228
|
|
|
229
|
* [anoncap](#anoncap) |
|
230
|
* [anycap](#anycap) |
|
231
|
* [artifact](#artifact) |
|
232
|
* [builtin_request_js](#bireqjs) |
|
233
|
* [capexpr](#capexpr) |
|
234
|
* [captureTh1](#captureTh1) |
|
235
|
* [cgiHeaderLine](#cgiHeaderLine) |
|
236
|
* [checkout](#checkout) |
|
237
|
* [combobox](#combobox) |
|
238
|
* [copybtn](#copybtn) |
|
239
|
* [date](#date) |
|
240
|
* [decorate](#decorate) |
|
241
|
* [defHeader](#defHeader) |
|
242
|
* [dir](#dir) |
|
243
|
* [enable\_output](#enable_output) |
|
244
|
* [encode64](#encode64) |
|
245
|
* [getParameter](#getParameter) |
|
246
|
* [glob\_match](#glob_match) |
|
247
|
* [globalState](#globalState) |
|
248
|
* [hascap](#hascap) |
|
249
|
* [hasfeature](#hasfeature) |
|
250
|
* [html](#html) |
|
251
|
* [htmlize](#htmlize) |
|
252
|
* [http](#http) |
|
253
|
* [httpize](#httpize) |
|
254
|
* [insertCsrf](#insertCsrf) |
|
255
|
* [linecount](#linecount) |
|
256
|
* [markdown](#markdown) |
|
257
|
* [nonce](#nonce) |
|
258
|
* [puts](#puts) |
|
259
|
* [query](#query) |
|
260
|
* [randhex](#randhex) |
|
261
|
* [redirect](#redirect) |
|
262
|
* [regexp](#regexp) |
|
263
|
* [reinitialize](#reinitialize) |
|
264
|
* [render](#render) |
|
265
|
* [repository](#repository) |
|
266
|
* [searchable](#searchable) |
|
267
|
* [setParameter](#setParameter) |
|
268
|
* [setting](#setting) |
|
269
|
* [stime](#stime) |
|
270
|
* [styleHeader](#styleHeader) |
|
271
|
* [styleFooter](#styleFooter) |
|
272
|
* [styleScript](#styleScript) |
|
273
|
* [submenu](#submenu) |
|
274
|
* [taint](#taintCmd) |
|
275
|
* [tclEval](#tclEval) |
|
276
|
* [tclExpr](#tclExpr) |
|
277
|
* [tclInvoke](#tclInvoke) |
|
278
|
* [tclIsSafe](#tclIsSafe) |
|
279
|
* [tclMakeSafe](#tclMakeSafe) |
|
280
|
* [tclReady](#tclReady) |
|
281
|
* [trace](#trace) |
|
282
|
* [untaint](#untaintCmd) |
|
283
|
* [unversioned content](#unversioned_content) |
|
284
|
* [unversioned list](#unversioned_list) |
|
285
|
* [utime](#utime) |
|
286
|
* [verifyCsrf](#verifyCsrf) |
|
287
|
* [verifyLogin](#verifyLogin) |
|
288
|
* [wiki](#wiki) |
|
289
|
* [wiki_assoc](#wiki_assoc) |
|
290
|
|
|
291
|
Each of the commands above is documented by a block comment above their |
|
292
|
implementation in the th\_main.c or th\_tcl.c source files. |
|
293
|
|
|
294
|
All commands starting with "tcl", with the exception of "tclReady", |
|
295
|
require the Tcl integration subsystem be included at compile-time. |
|
296
|
Additionally, the "tcl" repository setting must be enabled at runtime |
|
297
|
in order to successfully make use of these commands. |
|
298
|
|
|
299
|
<a id="anoncap"></a>TH1 anoncap Command |
|
300
|
----------------------------------------- |
|
301
|
|
|
302
|
Deprecated: prefer [capexpr](#capexpr) instead. |
|
303
|
|
|
304
|
* anoncap STRING... |
|
305
|
|
|
306
|
Returns true if the anonymous user has all of the capabilities listed |
|
307
|
in STRING. |
|
308
|
|
|
309
|
<a id="anycap"></a>TH1 anycap Command |
|
310
|
--------------------------------------- |
|
311
|
|
|
312
|
Deprecated: prefer [capexpr](#capexpr) instead. |
|
313
|
|
|
314
|
* anycap STRING |
|
315
|
|
|
316
|
Returns true if the current user user has any one of the capabilities |
|
317
|
listed in STRING. |
|
318
|
|
|
319
|
<a id="artifact"></a>TH1 artifact Command |
|
320
|
------------------------------------------- |
|
321
|
|
|
322
|
* artifact ID ?FILENAME? |
|
323
|
|
|
324
|
Attempts to locate the specified artifact and return its contents. An |
|
325
|
error is generated if the repository is not open or the artifact cannot |
|
326
|
be found. |
|
327
|
|
|
328
|
|
|
329
|
<a id="bireqjs"></a>TH1 builtin_request_js Command |
|
330
|
-------------------------------------------------- |
|
331
|
|
|
332
|
* builtin_request_js NAME |
|
333
|
|
|
334
|
NAME must be the name of one of the |
|
335
|
[built-in javascript source files](/dir?ci=trunk&type=flat&name=src&re=js$). |
|
336
|
This command causes that javascript file to be appended to the delivered |
|
337
|
document. |
|
338
|
|
|
339
|
|
|
340
|
|
|
341
|
<a id="capexpr"></a>TH1 capexpr Command |
|
342
|
----------------------------------------------------- |
|
343
|
|
|
344
|
* capexpr CAPABILITY-EXPR |
|
345
|
|
|
346
|
The capability expression is a list. Each term of the list is a |
|
347
|
cluster of [capability letters](./caps/ref.html). |
|
348
|
The overall expression is true if any |
|
349
|
one term is true. A single term is true if all letters within that |
|
350
|
term are true. Or, if the term begins with "!", then the term is true |
|
351
|
if none of the terms are true. Or, if the term begins with "@" then |
|
352
|
the term is true if all of the capability letters in that term are |
|
353
|
available to the "anonymous" user. Or, if the term is "*" then it is |
|
354
|
always true. |
|
355
|
|
|
356
|
Examples: |
|
357
|
|
|
358
|
``` |
|
359
|
capexpr {j o r} True if any one of j, o, or r are available |
|
360
|
capexpr {oh} True if both o and h are available |
|
361
|
capexpr {@2 @3 4 5 6} 2 or 3 available for anonymous or one of |
|
362
|
4, 5 or 6 is available for the user |
|
363
|
capexpr L True if the user is logged in |
|
364
|
capexpr !L True if the user is not logged in |
|
365
|
``` |
|
366
|
|
|
367
|
The `L` pseudo-capability is intended only to be used on its own or with |
|
368
|
the `!` prefix for implementing login/logout menus via the `mainmenu` |
|
369
|
site configuration option: |
|
370
|
|
|
371
|
``` |
|
372
|
Login /login !L {} |
|
373
|
Logout /logout L {} |
|
374
|
``` |
|
375
|
|
|
376
|
i.e. if the user is logged in, show the "Logout" link, else show the |
|
377
|
"Login" link. |
|
378
|
|
|
379
|
<a id="captureTh1"></a>TH1 captureTh1 Command |
|
380
|
----------------------------------------------------- |
|
381
|
|
|
382
|
* captureTh1 STRING |
|
383
|
|
|
384
|
Executes its single argument as TH1 code and captures any |
|
385
|
TH1-generated output as a string, which becomes the result of the |
|
386
|
function call. e.g. any `puts` calls made from that block will not |
|
387
|
generate any output, and instead their output will become part of the |
|
388
|
result string. |
|
389
|
|
|
390
|
|
|
391
|
<a id="cgiHeaderLine"></a>TH1 cgiHeaderLine Command |
|
392
|
----------------------------------------------------- |
|
393
|
|
|
394
|
* cgiHeaderLine line |
|
395
|
|
|
396
|
Adds the specified line to the CGI header. |
|
397
|
|
|
398
|
<a id="checkout"></a>TH1 checkout Command |
|
399
|
------------------------------------------- |
|
400
|
|
|
401
|
* checkout ?BOOLEAN? |
|
402
|
|
|
403
|
Return the fully qualified directory name of the current checkout or an |
|
404
|
empty string if it is not available. Optionally, it will attempt to find |
|
405
|
the current checkout, opening the configuration ("user") database and the |
|
406
|
repository as necessary, if the boolean argument is non-zero. |
|
407
|
|
|
408
|
<a id="combobox"></a>TH1 combobox Command |
|
409
|
------------------------------------------- |
|
410
|
|
|
411
|
* combobox NAME TEXT-LIST NUMLINES |
|
412
|
|
|
413
|
Generates and emits an HTML combobox. NAME is both the name of the |
|
414
|
CGI parameter and the name of a variable that contains the currently |
|
415
|
selected value. TEXT-LIST is a list of possible values for the |
|
416
|
combobox. NUMLINES is 1 for a true combobox. If NUMLINES is greater |
|
417
|
than one then the display is a listbox with the number of lines given. |
|
418
|
|
|
419
|
<a id="copybtn"></a>TH1 copybtn Command |
|
420
|
----------------------------------------- |
|
421
|
|
|
422
|
* copybtn TARGETID FLIPPED TEXT ?COPYLENGTH? |
|
423
|
|
|
424
|
Output TEXT with a click-to-copy button next to it. Loads the copybtn.js |
|
425
|
Javascript module, and generates HTML elements with the following IDs: |
|
426
|
|
|
427
|
* TARGETID: The `<span>` wrapper around TEXT. |
|
428
|
* copy-TARGETID: The `<span>` for the copy button. |
|
429
|
|
|
430
|
If the FLIPPED argument is non-zero, the copy button is displayed after TEXT. |
|
431
|
|
|
432
|
The optional COPYLENGTH argument defines the length of the substring of TEXT |
|
433
|
copied to clipboard: |
|
434
|
|
|
435
|
* <= 0: No limit (default if the argument is omitted). |
|
436
|
* >= 3: Truncate TEXT after COPYLENGTH (single-byte) characters. |
|
437
|
* 1: Use the "hash-digits" setting as the limit. |
|
438
|
* 2: Use the length appropriate for URLs as the limit (defined at |
|
439
|
compile-time by `FOSSIL_HASH_DIGITS_URL`, defaults to 16). |
|
440
|
|
|
441
|
<a id="date"></a>TH1 date Command |
|
442
|
----------------------------------- |
|
443
|
|
|
444
|
* date ?-local? |
|
445
|
|
|
446
|
Return a string which is the current time and date. If the -local |
|
447
|
option is used, the date appears using localtime instead of UTC. |
|
448
|
|
|
449
|
<a id="decorate"></a>TH1 decorate Command |
|
450
|
------------------------------------------- |
|
451
|
|
|
452
|
* decorate STRING |
|
453
|
|
|
454
|
Renders STRING as wiki content; however, only links are handled. No |
|
455
|
other markup is processed. |
|
456
|
|
|
457
|
<a id="defHeader"></a>TH1 defHeader Command |
|
458
|
--------------------------------------------- |
|
459
|
|
|
460
|
* defHeader |
|
461
|
|
|
462
|
Returns the default page header. |
|
463
|
|
|
464
|
<a id="dir"></a>TH1 dir Command |
|
465
|
--------------------------------- |
|
466
|
|
|
467
|
* dir CHECKIN ?GLOB? ?DETAILS? |
|
468
|
|
|
469
|
Returns a list containing all files in CHECKIN. If GLOB is given only |
|
470
|
the files matching the pattern GLOB within CHECKIN will be returned. |
|
471
|
If DETAILS is non-zero, the result will be a list-of-lists, with each |
|
472
|
element containing at least three elements: the file name, the file |
|
473
|
size (in bytes), and the file last modification time (relative to the |
|
474
|
time zone configured for the repository). |
|
475
|
|
|
476
|
<a id="enable_output"></a>TH1 enable\_output Command |
|
477
|
------------------------------------------------------ |
|
478
|
|
|
479
|
* enable\_output BOOLEAN |
|
480
|
|
|
481
|
Enable or disable sending output when the combobox, copybtn, puts, or wiki |
|
482
|
commands are used. |
|
483
|
|
|
484
|
<a id="encode64"></a>TH1 encode64 Command |
|
485
|
------------------------------------------- |
|
486
|
|
|
487
|
* encode64 STRING |
|
488
|
|
|
489
|
Encode the specified string using Base64 and return the result. |
|
490
|
|
|
491
|
<a id="getParameter"></a>TH1 getParameter Command |
|
492
|
--------------------------------------------------- |
|
493
|
|
|
494
|
* getParameter NAME ?DEFAULT? |
|
495
|
|
|
496
|
Returns the value of the specified query parameter or the specified |
|
497
|
default value when there is no matching query parameter. |
|
498
|
|
|
499
|
<a id="glob_match"></a>TH1 glob\_match Command |
|
500
|
------------------------------------------------ |
|
501
|
|
|
502
|
* glob\_match ?-one? ?--? patternList string |
|
503
|
|
|
504
|
Checks the string against the specified glob pattern -OR- list of glob |
|
505
|
patterns and returns non-zero if there is a match. |
|
506
|
|
|
507
|
<a id="globalState"></a>TH1 globalState Command |
|
508
|
------------------------------------------------- |
|
509
|
|
|
510
|
* globalState NAME ?DEFAULT? |
|
511
|
|
|
512
|
Returns a string containing the value of the specified global state |
|
513
|
variable -OR- the specified default value. The supported items are: |
|
514
|
|
|
515
|
1. **checkout** -- _Active local checkout directory, if any._ |
|
516
|
1. **configuration** -- _Active configuration database file name, if any._ |
|
517
|
1. **executable** -- _Fully qualified executable file name._ |
|
518
|
1. **flags** -- _TH1 initialization flags._ |
|
519
|
1. **log** -- _Error log file name, if any._ |
|
520
|
1. **repository** -- _Active local repository file name, if any._ |
|
521
|
1. **top** -- _Base path for the active server instance, if applicable._ |
|
522
|
1. **user** -- _Active user name, if any._ |
|
523
|
1. **vfs** -- _SQLite VFS in use, if overridden._ |
|
524
|
|
|
525
|
Attempts to query for unsupported global state variables will result |
|
526
|
in a script error. Additional global state variables may be exposed |
|
527
|
in the future. |
|
528
|
|
|
529
|
<a id="hascap"></a>TH1 hascap Command |
|
530
|
--------------------------------------- |
|
531
|
|
|
532
|
Deprecated: prefer [capexpr](#capexpr) instead. |
|
533
|
|
|
534
|
* hascap STRING... |
|
535
|
|
|
536
|
Returns true if the current user has all of the capabilities listed |
|
537
|
in STRING. |
|
538
|
|
|
539
|
<a id="hasfeature"></a>TH1 hasfeature Command |
|
540
|
----------------------------------------------- |
|
541
|
|
|
542
|
* hasfeature STRING |
|
543
|
|
|
544
|
Returns true if the binary has the given compile-time feature enabled. |
|
545
|
The possible features are: |
|
546
|
|
|
547
|
1. **ssl** -- _Support for the HTTPS transport._ |
|
548
|
1. **legacyMvRm** -- _Support for legacy mv/rm command behavior._ |
|
549
|
1. **execRelPaths** -- _Use relative paths with external diff/gdiff._ |
|
550
|
1. **th1Docs** -- _Support for TH1 in embedded documentation._ |
|
551
|
1. **th1Hooks** -- _Support for TH1 command and web page hooks._ |
|
552
|
1. **tcl** -- _Support for Tcl integration._ |
|
553
|
1. **useTclStubs** -- _Tcl stubs enabled in the Tcl headers._ |
|
554
|
1. **tclStubs** -- _Uses Tcl stubs (i.e. linking with stubs library)._ |
|
555
|
1. **tclPrivateStubs** -- _Uses Tcl private stubs (i.e. header-only)._ |
|
556
|
1. **json** -- _Support for the JSON APIs._ |
|
557
|
1. **markdown** -- _Support for Markdown documentation format._ |
|
558
|
1. **unicodeCmdLine** -- _The command line arguments are Unicode._ |
|
559
|
1. **dynamicBuild** -- _Dynamically linked to libraries._ |
|
560
|
1. **mman** -- _Uses POSIX memory APIs from "sys/mman.h"._ |
|
561
|
1. **see** -- _Uses the SQLite Encryption Extension._ |
|
562
|
|
|
563
|
Specifying an unknown feature will return a value of false, it will not |
|
564
|
raise a script error. |
|
565
|
|
|
566
|
<a id="html"></a>TH1 html Command |
|
567
|
----------------------------------- |
|
568
|
|
|
569
|
* html STRING |
|
570
|
|
|
571
|
Outputs the STRING literally. It is assumed that STRING contains |
|
572
|
valid HTML, or that if STRING contains any characters that are |
|
573
|
significant to HTML (such as `<`, `>`, `'`, or `&`) have already |
|
574
|
been escaped, perhaps by the [htmlize](#htmlize) command. Use the |
|
575
|
[puts](#puts) command to output text that might contain unescaped |
|
576
|
HTML markup. |
|
577
|
|
|
578
|
**Beware of XSS attacks!** If the STRING value to the html command |
|
579
|
can be controlled by a hostile user, then he might be able to sneak |
|
580
|
in malicious HTML or Javascript which could result in a |
|
581
|
cross-site scripting (XSS) attack. Be careful that all text that |
|
582
|
in STRING that might come from user input has been sanitized by the |
|
583
|
[htmlize](#htmlize) command or similar. In recent versions of Fossil, |
|
584
|
the STRING value must be [untainted](#taint) or else the "html" command |
|
585
|
will fail. |
|
586
|
|
|
587
|
<a id="htmlize"></a>TH1 htmlize Command |
|
588
|
----------------------------------------- |
|
589
|
|
|
590
|
* htmlize STRING |
|
591
|
|
|
592
|
Escape all characters of STRING which have special meaning in HTML. |
|
593
|
Returns the escaped string. |
|
594
|
|
|
595
|
<a id="http"></a>TH1 http Command |
|
596
|
----------------------------------- |
|
597
|
|
|
598
|
* http ?-asynchronous? ?--? url ?payload? |
|
599
|
|
|
600
|
Performs an HTTP or HTTPS request for the specified URL. If a |
|
601
|
payload is present, it will be interpreted as text/plain and |
|
602
|
the POST method will be used; otherwise, the GET method will |
|
603
|
be used. Upon success, if the -asynchronous option is used, an |
|
604
|
empty string is returned as the result; otherwise, the response |
|
605
|
from the server is returned as the result. Synchronous requests |
|
606
|
are not currently implemented. |
|
607
|
|
|
608
|
<a id="httpize"></a>TH1 httpize Command |
|
609
|
----------------------------------------- |
|
610
|
|
|
611
|
* httpize STRING |
|
612
|
|
|
613
|
Escape all characters of STRING which have special meaning in URI |
|
614
|
components. Returns the escaped string. |
|
615
|
|
|
616
|
<a id="insertCsrf"></a>TH1 insertCsrf Command |
|
617
|
----------------------------------------------- |
|
618
|
|
|
619
|
* insertCsrf |
|
620
|
|
|
621
|
While rendering a form, call this command to add the Anti-CSRF token |
|
622
|
as a hidden element of the form. |
|
623
|
|
|
624
|
<a id="linecount"></a>TH1 linecount Command |
|
625
|
--------------------------------------------- |
|
626
|
|
|
627
|
* linecount STRING MAX MIN |
|
628
|
|
|
629
|
Returns one more than the number of `\n` characters in STRING. But |
|
630
|
never returns less than MIN or more than MAX. |
|
631
|
|
|
632
|
<a id="markdown"></a>TH1 markdown Command |
|
633
|
------------------------------------------- |
|
634
|
|
|
635
|
* markdown STRING |
|
636
|
|
|
637
|
Renders the input string as markdown. The result is a two-element list. |
|
638
|
The first element contains the body, rendered as HTML. The second element |
|
639
|
is the text-only title string. |
|
640
|
|
|
641
|
<a id="nonce"></a>TH1 nonce Command |
|
642
|
------------------------------------- |
|
643
|
|
|
644
|
* nonce |
|
645
|
|
|
646
|
Returns the value of the cryptographic nonce for the request being processed. |
|
647
|
|
|
648
|
<a id="puts"></a>TH1 puts Command |
|
649
|
----------------------------------- |
|
650
|
|
|
651
|
* puts STRING |
|
652
|
|
|
653
|
Outputs STRING. Characters within STRING that have special meaning |
|
654
|
in HTML are escaped prior to being output. Thus is it safe for STRING |
|
655
|
to be derived from user inputs. See also the [html](#html) command |
|
656
|
which behaves similarly except does not escape HTML markup. This |
|
657
|
command ("puts") is safe to use on [tainted strings](#taint), but the "html" |
|
658
|
command is not. |
|
659
|
|
|
660
|
<a id="query"></a>TH1 query Command |
|
661
|
------------------------------------- |
|
662
|
|
|
663
|
* query ?-nocomplain? SQL CODE |
|
664
|
|
|
665
|
Runs the SQL query given by the SQL argument. For each row in the result |
|
666
|
set, run CODE. |
|
667
|
|
|
668
|
In SQL, parameters such as $var are filled in using the value of variable |
|
669
|
"var". Result values are stored in variables with the column name prior |
|
670
|
to each invocation of CODE. The names of the variables in which results |
|
671
|
are stored can be controlled using "AS name" clauses in the SQL. As |
|
672
|
the database will often contain content that originates from untrusted |
|
673
|
users, all result values are marked as [tainted](#taint). |
|
674
|
|
|
675
|
**Beware of SQL injections in the `query` command!** |
|
676
|
The SQL argument to the query command should always be literal SQL |
|
677
|
text enclosed in {...}. The SQL argument should never be a double-quoted |
|
678
|
string or the value of a \$variable, as those constructs can lead to |
|
679
|
an SQL Injection attack. If you need to include the values of one or |
|
680
|
more TH1 variables as part of the SQL, then put \$variable inside the |
|
681
|
{...}. The \$variable keyword will then get passed down into the SQLite |
|
682
|
parser which knows to look up the value of \$variable in the TH1 symbol |
|
683
|
table. For example: |
|
684
|
|
|
685
|
~~~ |
|
686
|
query {SELECT res FROM tab1 WHERE key=$mykey} {...} |
|
687
|
~~~ |
|
688
|
|
|
689
|
SQLite will see the \$mykey token in the SQL and will know to resolve it |
|
690
|
to the value of the "mykey" TH1 variable, safely and without the possibility |
|
691
|
of SQL injection. The following is unsafe: |
|
692
|
|
|
693
|
~~~ |
|
694
|
query "SELECT res FROM tab1 WHERE key='$mykey'" {...} ;# <-- UNSAFE! |
|
695
|
~~~ |
|
696
|
|
|
697
|
In this second example, TH1 does the expansion of `$mykey` prior to passing |
|
698
|
the text down into SQLite. So if `$mykey` contains a single-quote character, |
|
699
|
followed by additional hostile text, that will result in an SQL injection. |
|
700
|
|
|
701
|
To help guard against SQL-injections, recent versions of Fossil require |
|
702
|
that the SQL argument be [untainted](#taint) or else the "query" command |
|
703
|
will fail. |
|
704
|
|
|
705
|
<a id="randhex"></a>TH1 randhex Command |
|
706
|
----------------------------------------- |
|
707
|
|
|
708
|
* randhex N |
|
709
|
|
|
710
|
Returns a string of N*2 random hexadecimal digits with N<50. If N is |
|
711
|
omitted, use a value of 10. |
|
712
|
|
|
713
|
<a id="redirect"></a>TH1 redirect Command |
|
714
|
------------------------------------------- |
|
715
|
|
|
716
|
* redirect URL ?withMethod? |
|
717
|
|
|
718
|
Issues an HTTP redirect to the specified URL and then exits the process. |
|
719
|
By default, an HTTP status code of 302 is used. If the optional withMethod |
|
720
|
argument is present and non-zero, an HTTP status code of 307 is used, which |
|
721
|
should force the user agent to preserve the original method for the request |
|
722
|
(e.g. GET, POST) instead of (possibly) forcing the user agent to change the |
|
723
|
method to GET. |
|
724
|
|
|
725
|
<a id="regexp"></a>TH1 regexp Command |
|
726
|
--------------------------------------- |
|
727
|
|
|
728
|
* regexp ?-nocase? ?--? exp string |
|
729
|
|
|
730
|
Checks the string against the specified regular expression and returns |
|
731
|
non-zero if it matches. If the regular expression is invalid or cannot |
|
732
|
be compiled, an error will be generated. |
|
733
|
|
|
734
|
See [fossil grep](./grep.md) for details on the regexp syntax. |
|
735
|
|
|
736
|
<a id="reinitialize"></a>TH1 reinitialize Command |
|
737
|
--------------------------------------------------- |
|
738
|
|
|
739
|
* reinitialize ?FLAGS? |
|
740
|
|
|
741
|
Reinitializes the TH1 interpreter using the specified flags. |
|
742
|
|
|
743
|
<a id="render"></a>TH1 render Command |
|
744
|
--------------------------------------- |
|
745
|
|
|
746
|
* render STRING |
|
747
|
|
|
748
|
Renders the TH1 template and writes the results. |
|
749
|
|
|
750
|
<a id="repository"></a>TH1 repository Command |
|
751
|
----------------------------------------------- |
|
752
|
|
|
753
|
* repository ?BOOLEAN? |
|
754
|
|
|
755
|
Returns the fully qualified file name of the open repository or an empty |
|
756
|
string if one is not currently open. Optionally, it will attempt to open |
|
757
|
the repository if the boolean argument is non-zero. |
|
758
|
|
|
759
|
<a id="searchable"></a>TH1 searchable Command |
|
760
|
----------------------------------------------- |
|
761
|
|
|
762
|
* searchable STRING... |
|
763
|
|
|
764
|
Return true if searching in any of the document classes identified |
|
765
|
by STRING is enabled for the repository and user has the necessary |
|
766
|
capabilities to perform the search. The possible document classes |
|
767
|
are: |
|
768
|
|
|
769
|
1. **c** -- _Check-in comments_ |
|
770
|
1. **d** -- _Embedded documentation_ |
|
771
|
1. **t** -- _Tickets_ |
|
772
|
1. **w** -- _Wiki_ |
|
773
|
|
|
774
|
To be clear, only one of the document classes identified by each STRING |
|
775
|
needs to be searchable in order for that argument to be true. But all |
|
776
|
arguments must be true for this routine to return true. Hence, to see |
|
777
|
if ALL document classes are searchable: |
|
778
|
|
|
779
|
if {[searchable c d t w]} {...} |
|
780
|
|
|
781
|
But to see if ANY document class is searchable: |
|
782
|
|
|
783
|
if {[searchable cdtw]} {...} |
|
784
|
|
|
785
|
This command is useful for enabling or disabling a "Search" entry on the |
|
786
|
menu bar. |
|
787
|
|
|
788
|
<a id="setParameter"></a>TH1 setParameter Command |
|
789
|
--------------------------------------------------- |
|
790
|
|
|
791
|
* setParameter NAME VALUE |
|
792
|
|
|
793
|
Sets the value of the specified query parameter. |
|
794
|
|
|
795
|
<a id="setting"></a>TH1 setting Command |
|
796
|
----------------------------------------- |
|
797
|
|
|
798
|
* setting name |
|
799
|
|
|
800
|
Gets and returns the value of the specified setting. |
|
801
|
|
|
802
|
<a id="stime"></a>TH1 stime Command |
|
803
|
------------------------------------- |
|
804
|
|
|
805
|
* stime |
|
806
|
|
|
807
|
Returns the number of microseconds of CPU time consumed by the current |
|
808
|
process in system space. |
|
809
|
|
|
810
|
<a id="styleHeader"></a>TH1 styleHeader Command |
|
811
|
------------------------------------------------- |
|
812
|
|
|
813
|
* styleHeader TITLE |
|
814
|
|
|
815
|
Render the configured style header for the selected skin. |
|
816
|
|
|
817
|
<a id="styleFooter"></a>TH1 styleFooter Command |
|
818
|
------------------------------------------------- |
|
819
|
|
|
820
|
* styleFooter |
|
821
|
|
|
822
|
Render the configured style footer for the selected skin. |
|
823
|
|
|
824
|
<a id="styleScript"></a>TH1 styleScript Command |
|
825
|
------------------------------------------------- |
|
826
|
|
|
827
|
* styleScript |
|
828
|
|
|
829
|
Render the configured JavaScript for the selected skin. |
|
830
|
|
|
831
|
<a id="submenu"></a>TH1 submenu Command |
|
832
|
----------------------------------------- |
|
833
|
|
|
834
|
* submenu link LABEL URL |
|
835
|
|
|
836
|
Add hyperlink to the submenu of the current page. |
|
837
|
|
|
838
|
<a id="taintCmd"></a>TH1 taint Command |
|
839
|
----------------------------------------- |
|
840
|
|
|
841
|
* taint STRING |
|
842
|
|
|
843
|
This command returns a copy of STRING that has been marked as |
|
844
|
[tainted](#taint). Tainted strings are strings which might be |
|
845
|
controlled by an attacker and might contain hostile inputs and |
|
846
|
are thus unsafe to use in certain contexts. For example, tainted |
|
847
|
strings should not be output as part of a webpage as they might |
|
848
|
contain rogue HTML or Javascript that could lead to an XSS |
|
849
|
vulnerability. Similarly, tainted strings should not be run as |
|
850
|
SQL since they might contain an SQL-injection vulerability. |
|
851
|
|
|
852
|
<a id="tclEval"></a>TH1 tclEval Command |
|
853
|
----------------------------------------- |
|
854
|
|
|
855
|
**This command requires the Tcl integration feature.** |
|
856
|
|
|
857
|
* tclEval arg ?arg ...? |
|
858
|
|
|
859
|
Evaluates the Tcl script and returns its result verbatim. If a Tcl script |
|
860
|
error is generated, it will be transformed into a TH1 script error. The |
|
861
|
Tcl interpreter will be created automatically if it has not been already. |
|
862
|
|
|
863
|
<a id="tclExpr"></a>TH1 tclExpr Command |
|
864
|
----------------------------------------- |
|
865
|
|
|
866
|
**This command requires the Tcl integration feature.** |
|
867
|
|
|
868
|
* tclExpr arg ?arg ...? |
|
869
|
|
|
870
|
Evaluates the Tcl expression and returns its result verbatim. If a Tcl |
|
871
|
script error is generated, it will be transformed into a TH1 script |
|
872
|
error. The Tcl interpreter will be created automatically if it has not |
|
873
|
been already. |
|
874
|
|
|
875
|
<a id="tclInvoke"></a>TH1 tclInvoke Command |
|
876
|
--------------------------------------------- |
|
877
|
|
|
878
|
**This command requires the Tcl integration feature.** |
|
879
|
|
|
880
|
* tclInvoke command ?arg ...? |
|
881
|
|
|
882
|
Invokes the Tcl command using the supplied arguments. No additional |
|
883
|
substitutions are performed on the arguments. The Tcl interpreter |
|
884
|
will be created automatically if it has not been already. |
|
885
|
|
|
886
|
<a id="tclIsSafe"></a>TH1 tclIsSafe Command |
|
887
|
--------------------------------------------- |
|
888
|
|
|
889
|
**This command requires the Tcl integration feature.** |
|
890
|
|
|
891
|
* tclIsSafe |
|
892
|
|
|
893
|
Returns non-zero if the Tcl interpreter is "safe". The Tcl interpreter |
|
894
|
will be created automatically if it has not been already. |
|
895
|
|
|
896
|
<a id="tclMakeSafe"></a>TH1 tclMakeSafe Command |
|
897
|
------------------------------------------------- |
|
898
|
|
|
899
|
**This command requires the Tcl integration feature.** |
|
900
|
|
|
901
|
* tclMakeSafe |
|
902
|
|
|
903
|
Forces the Tcl interpreter into "safe" mode by removing all "unsafe" |
|
904
|
commands and variables. This operation cannot be undone. The Tcl |
|
905
|
interpreter will remain "safe" until the process terminates. The Tcl |
|
906
|
interpreter will be created automatically if it has not been already. |
|
907
|
|
|
908
|
<a id="tclReady"></a>TH1 tclReady Command |
|
909
|
------------------------------------------- |
|
910
|
|
|
911
|
* tclReady |
|
912
|
|
|
913
|
Returns true if the binary has the Tcl integration feature enabled and it |
|
914
|
is currently available for use by TH1 scripts. |
|
915
|
|
|
916
|
<a id="trace"></a>TH1 trace Command |
|
917
|
------------------------------------- |
|
918
|
|
|
919
|
* trace STRING |
|
920
|
|
|
921
|
Generates a TH1 trace message if TH1 tracing is enabled. |
|
922
|
|
|
923
|
<a id="untaintCmd"></a>TH1 untaint Command |
|
924
|
------------------------------------------ |
|
925
|
|
|
926
|
* untaint STRING |
|
927
|
|
|
928
|
This command returns a copy of STRING that has been marked as |
|
929
|
[untainted](#taint). Untainted strings are strings which are |
|
930
|
believed to be free of potentially hostile content. Use this |
|
931
|
command with caution, as it overwrites the tainted-string protection |
|
932
|
mechanisms that are built into TH1. If you do not understand all |
|
933
|
the implications of executing this command, then do not use it. |
|
934
|
|
|
935
|
<a id="unversioned_content"></a>TH1 unversioned content Command |
|
936
|
----------------------------------------------------------------- |
|
937
|
|
|
938
|
* unversioned content FILENAME |
|
939
|
|
|
940
|
Attempts to locate the specified unversioned file and return its contents. |
|
941
|
An error is generated if the repository is not open or the unversioned file |
|
942
|
cannot be found. |
|
943
|
|
|
944
|
<a id="unversioned_list"></a>TH1 unversioned list Command |
|
945
|
----------------------------------------------------------- |
|
946
|
|
|
947
|
* unversioned list |
|
948
|
|
|
949
|
Returns a list of the names of all unversioned files held in the local |
|
950
|
repository. An error is generated if the repository is not open. |
|
951
|
|
|
952
|
<a id="utime"></a>TH1 utime Command |
|
953
|
------------------------------------- |
|
954
|
|
|
955
|
* utime |
|
956
|
|
|
957
|
Returns the number of microseconds of CPU time consumed by the current |
|
958
|
process in user space. |
|
959
|
|
|
960
|
<a id="verifyCsrf"></a>TH1 verifyCsrf Command |
|
961
|
----------------------------------------------- |
|
962
|
|
|
963
|
* verifyCsrf |
|
964
|
|
|
965
|
Before using the results of a form, first call this command to verify |
|
966
|
that the Anti-CSRF token is present and is valid. If the Anti-CSRF token |
|
967
|
is missing or is incorrect, that indicates a cross-site scripting attack. |
|
968
|
If the event of an attack is detected, an error message is generated and |
|
969
|
all further processing is aborted. |
|
970
|
|
|
971
|
<a id="verifyLogin"></a>TH1 verifyLogin Command |
|
972
|
------------------------------------------------- |
|
973
|
|
|
974
|
* verifyLogin |
|
975
|
|
|
976
|
Returns non-zero if the specified user name and password represent a |
|
977
|
valid login for the repository. |
|
978
|
|
|
979
|
<a id="wiki"></a>TH1 wiki Command |
|
980
|
----------------------------------- |
|
981
|
|
|
982
|
* wiki STRING |
|
983
|
|
|
984
|
Renders STRING as wiki content. |
|
985
|
|
|
986
|
<a id="wiki_assoc"></a>TH1 wiki_assoc Command |
|
987
|
----------------------------------- |
|
988
|
|
|
989
|
* wiki_assoc STRING STRING |
|
990
|
|
|
991
|
Renders the special wiki. The first string refers to the namespace |
|
992
|
(checkin, branch, tag, ticket). The second string specifies the |
|
993
|
concrete wiki page to be rendered. |
|
994
|
|
|
995
|
Tcl Integration Commands |
|
996
|
------------------------ |
|
997
|
|
|
998
|
When the Tcl integration subsystem is enabled, several commands are added |
|
999
|
to the Tcl interpreter. They are used to allow Tcl scripts access to the |
|
1000
|
Fossil functionality provided via TH1. The following is a summary of the |
|
1001
|
Tcl commands: |
|
1002
|
|
|
1003
|
* th1Eval |
|
1004
|
* th1Expr |
|
1005
|
|
|
1006
|
<a id="th1Eval"></a>Tcl th1Eval Command |
|
1007
|
----------------------------------------- |
|
1008
|
|
|
1009
|
**This command requires the Tcl integration feature.** |
|
1010
|
|
|
1011
|
* th1Eval arg |
|
1012
|
|
|
1013
|
Evaluates the TH1 script and returns its result verbatim. If a TH1 script |
|
1014
|
error is generated, it will be transformed into a Tcl script error. |
|
1015
|
|
|
1016
|
<a id="th1Expr"></a>Tcl th1Expr Command |
|
1017
|
----------------------------------------- |
|
1018
|
|
|
1019
|
**This command requires the Tcl integration feature.** |
|
1020
|
|
|
1021
|
* th1Expr arg |
|
1022
|
|
|
1023
|
Evaluates the TH1 expression and returns its result verbatim. If a TH1 |
|
1024
|
script error is generated, it will be transformed into a Tcl script error. |
|
1025
|
|