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