Fossil SCM

Make the 'tcl-setup', 'th1-setup', and 'th1-uri-regexp' settings versionable. Add support for TH1-based hooks for all commands and web pages, disabled by default.

mistachkin 2014-06-14 20:10 trunk merge
Commit 1c528d3bb9e07428d1a35a07201ed1aadcb7fd36
+6
--- auto.def
+++ auto.def
@@ -4,10 +4,11 @@
44
55
options {
66
with-openssl:path|auto|none
77
=> {Look for openssl in the given path, or auto or none}
88
with-zlib:path => {Look for zlib in the given path}
9
+ with-th1-hooks=0 => {Enable TH1 hooks for commands and web pages}
910
with-tcl:path => {Enable Tcl integration, with Tcl in the specified path}
1011
with-tcl-stubs=0 => {Enable Tcl integration via stubs library mechanism}
1112
with-tcl-private-stubs=0
1213
=> {Enable Tcl integration via private stubs mechanism}
1314
internal-sqlite=1 => {Don't use the internal SQLite, use the system one}
@@ -80,10 +81,15 @@
8081
# have #ifdef guards around the whole file without
8182
# reading config.h first.
8283
define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_JSON
8384
define FOSSIL_ENABLE_JSON
8485
}
86
+
87
+if {[opt-bool with-th1-hooks]} {
88
+ define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_TH1_HOOKS
89
+ define FOSSIL_ENABLE_TH1_HOOKS
90
+}
8591
8692
#if {[opt-bool markdown]} {
8793
# # no-op. Markdown is now enabled by default.
8894
#}
8995
9096
--- auto.def
+++ auto.def
@@ -4,10 +4,11 @@
4
5 options {
6 with-openssl:path|auto|none
7 => {Look for openssl in the given path, or auto or none}
8 with-zlib:path => {Look for zlib in the given path}
 
9 with-tcl:path => {Enable Tcl integration, with Tcl in the specified path}
10 with-tcl-stubs=0 => {Enable Tcl integration via stubs library mechanism}
11 with-tcl-private-stubs=0
12 => {Enable Tcl integration via private stubs mechanism}
13 internal-sqlite=1 => {Don't use the internal SQLite, use the system one}
@@ -80,10 +81,15 @@
80 # have #ifdef guards around the whole file without
81 # reading config.h first.
82 define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_JSON
83 define FOSSIL_ENABLE_JSON
84 }
 
 
 
 
 
85
86 #if {[opt-bool markdown]} {
87 # # no-op. Markdown is now enabled by default.
88 #}
89
90
--- auto.def
+++ auto.def
@@ -4,10 +4,11 @@
4
5 options {
6 with-openssl:path|auto|none
7 => {Look for openssl in the given path, or auto or none}
8 with-zlib:path => {Look for zlib in the given path}
9 with-th1-hooks=0 => {Enable TH1 hooks for commands and web pages}
10 with-tcl:path => {Enable Tcl integration, with Tcl in the specified path}
11 with-tcl-stubs=0 => {Enable Tcl integration via stubs library mechanism}
12 with-tcl-private-stubs=0
13 => {Enable Tcl integration via private stubs mechanism}
14 internal-sqlite=1 => {Don't use the internal SQLite, use the system one}
@@ -80,10 +81,15 @@
81 # have #ifdef guards around the whole file without
82 # reading config.h first.
83 define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_JSON
84 define FOSSIL_ENABLE_JSON
85 }
86
87 if {[opt-bool with-th1-hooks]} {
88 define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_TH1_HOOKS
89 define FOSSIL_ENABLE_TH1_HOOKS
90 }
91
92 #if {[opt-bool markdown]} {
93 # # no-op. Markdown is now enabled by default.
94 #}
95
96
+6
--- auto.def
+++ auto.def
@@ -4,10 +4,11 @@
44
55
options {
66
with-openssl:path|auto|none
77
=> {Look for openssl in the given path, or auto or none}
88
with-zlib:path => {Look for zlib in the given path}
9
+ with-th1-hooks=0 => {Enable TH1 hooks for commands and web pages}
910
with-tcl:path => {Enable Tcl integration, with Tcl in the specified path}
1011
with-tcl-stubs=0 => {Enable Tcl integration via stubs library mechanism}
1112
with-tcl-private-stubs=0
1213
=> {Enable Tcl integration via private stubs mechanism}
1314
internal-sqlite=1 => {Don't use the internal SQLite, use the system one}
@@ -80,10 +81,15 @@
8081
# have #ifdef guards around the whole file without
8182
# reading config.h first.
8283
define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_JSON
8384
define FOSSIL_ENABLE_JSON
8485
}
86
+
87
+if {[opt-bool with-th1-hooks]} {
88
+ define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_TH1_HOOKS
89
+ define FOSSIL_ENABLE_TH1_HOOKS
90
+}
8591
8692
#if {[opt-bool markdown]} {
8793
# # no-op. Markdown is now enabled by default.
8894
#}
8995
9096
--- auto.def
+++ auto.def
@@ -4,10 +4,11 @@
4
5 options {
6 with-openssl:path|auto|none
7 => {Look for openssl in the given path, or auto or none}
8 with-zlib:path => {Look for zlib in the given path}
 
9 with-tcl:path => {Enable Tcl integration, with Tcl in the specified path}
10 with-tcl-stubs=0 => {Enable Tcl integration via stubs library mechanism}
11 with-tcl-private-stubs=0
12 => {Enable Tcl integration via private stubs mechanism}
13 internal-sqlite=1 => {Don't use the internal SQLite, use the system one}
@@ -80,10 +81,15 @@
80 # have #ifdef guards around the whole file without
81 # reading config.h first.
82 define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_JSON
83 define FOSSIL_ENABLE_JSON
84 }
 
 
 
 
 
85
86 #if {[opt-bool markdown]} {
87 # # no-op. Markdown is now enabled by default.
88 #}
89
90
--- auto.def
+++ auto.def
@@ -4,10 +4,11 @@
4
5 options {
6 with-openssl:path|auto|none
7 => {Look for openssl in the given path, or auto or none}
8 with-zlib:path => {Look for zlib in the given path}
9 with-th1-hooks=0 => {Enable TH1 hooks for commands and web pages}
10 with-tcl:path => {Enable Tcl integration, with Tcl in the specified path}
11 with-tcl-stubs=0 => {Enable Tcl integration via stubs library mechanism}
12 with-tcl-private-stubs=0
13 => {Enable Tcl integration via private stubs mechanism}
14 internal-sqlite=1 => {Don't use the internal SQLite, use the system one}
@@ -80,10 +81,15 @@
81 # have #ifdef guards around the whole file without
82 # reading config.h first.
83 define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_JSON
84 define FOSSIL_ENABLE_JSON
85 }
86
87 if {[opt-bool with-th1-hooks]} {
88 define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_TH1_HOOKS
89 define FOSSIL_ENABLE_TH1_HOOKS
90 }
91
92 #if {[opt-bool markdown]} {
93 # # no-op. Markdown is now enabled by default.
94 #}
95
96
--- src/configure.c
+++ src/configure.c
@@ -97,10 +97,11 @@
9797
{ "timeline-max-comment", CONFIGSET_SKIN },
9898
{ "timeline-plaintext", CONFIGSET_SKIN },
9999
{ "adunit", CONFIGSET_SKIN },
100100
{ "adunit-omit-if-admin", CONFIGSET_SKIN },
101101
{ "adunit-omit-if-user", CONFIGSET_SKIN },
102
+ { "th1-hooks", CONFIGSET_TH1 },
102103
{ "th1-setup", CONFIGSET_TH1 },
103104
{ "th1-uri-regexp", CONFIGSET_TH1 },
104105
105106
#ifdef FOSSIL_ENABLE_TCL
106107
{ "tcl", CONFIGSET_TH1 },
107108
--- src/configure.c
+++ src/configure.c
@@ -97,10 +97,11 @@
97 { "timeline-max-comment", CONFIGSET_SKIN },
98 { "timeline-plaintext", CONFIGSET_SKIN },
99 { "adunit", CONFIGSET_SKIN },
100 { "adunit-omit-if-admin", CONFIGSET_SKIN },
101 { "adunit-omit-if-user", CONFIGSET_SKIN },
 
102 { "th1-setup", CONFIGSET_TH1 },
103 { "th1-uri-regexp", CONFIGSET_TH1 },
104
105 #ifdef FOSSIL_ENABLE_TCL
106 { "tcl", CONFIGSET_TH1 },
107
--- src/configure.c
+++ src/configure.c
@@ -97,10 +97,11 @@
97 { "timeline-max-comment", CONFIGSET_SKIN },
98 { "timeline-plaintext", CONFIGSET_SKIN },
99 { "adunit", CONFIGSET_SKIN },
100 { "adunit-omit-if-admin", CONFIGSET_SKIN },
101 { "adunit-omit-if-user", CONFIGSET_SKIN },
102 { "th1-hooks", CONFIGSET_TH1 },
103 { "th1-setup", CONFIGSET_TH1 },
104 { "th1-uri-regexp", CONFIGSET_TH1 },
105
106 #ifdef FOSSIL_ENABLE_TCL
107 { "tcl", CONFIGSET_TH1 },
108
+36 -7
--- src/db.c
+++ src/db.c
@@ -785,10 +785,31 @@
785785
assert( g.zMainDbType!=0 );
786786
db_attach(zDbName, zLabel);
787787
if( pWasAttached ) *pWasAttached = 1;
788788
}
789789
}
790
+
791
+/*
792
+** Close the user database.
793
+*/
794
+void db_close_config(){
795
+ if( g.useAttach ){
796
+ db_detach("configdb");
797
+ g.useAttach = 0;
798
+ g.zConfigDbName = 0;
799
+ }else if( g.dbConfig ){
800
+ sqlite3_close(g.dbConfig);
801
+ g.dbConfig = 0;
802
+ g.zConfigDbType = 0;
803
+ g.zConfigDbName = 0;
804
+ }else if( g.db && fossil_strcmp(g.zMainDbType, "configdb")==0 ){
805
+ sqlite3_close(g.db);
806
+ g.db = 0;
807
+ g.zMainDbType = 0;
808
+ g.zConfigDbName = 0;
809
+ }
810
+}
790811
791812
/*
792813
** Open the user database in "~/.fossil". Create the database anew if
793814
** it does not already exist.
794815
**
@@ -801,11 +822,14 @@
801822
** case, invoke this routine with useAttach as 1.
802823
*/
803824
void db_open_config(int useAttach){
804825
char *zDbName;
805826
char *zHome;
806
- if( g.zConfigDbName ) return;
827
+ if( g.zConfigDbName ){
828
+ if( useAttach==g.useAttach ) return;
829
+ db_close_config();
830
+ }
807831
#if defined(_WIN32) || defined(__CYGWIN__)
808832
zHome = fossil_getenv("LOCALAPPDATA");
809833
if( zHome==0 ){
810834
zHome = fossil_getenv("APPDATA");
811835
if( zHome==0 ){
@@ -2169,14 +2193,15 @@
21692193
{ "ssh-command", 0, 40, 0, 0, "" },
21702194
{ "ssl-ca-location", 0, 40, 0, 0, "" },
21712195
{ "ssl-identity", 0, 40, 0, 0, "" },
21722196
#ifdef FOSSIL_ENABLE_TCL
21732197
{ "tcl", 0, 0, 0, 0, "off" },
2174
- { "tcl-setup", 0, 40, 0, 1, "" },
2198
+ { "tcl-setup", 0, 40, 1, 1, "" },
21752199
#endif
2176
- { "th1-setup", 0, 40, 0, 1, "" },
2177
- { "th1-uri-regexp", 0, 40, 0, 0, "" },
2200
+ { "th1-hooks", 0, 0, 0, 0, "off" },
2201
+ { "th1-setup", 0, 40, 1, 1, "" },
2202
+ { "th1-uri-regexp", 0, 40, 1, 0, "" },
21782203
{ "web-browser", 0, 32, 0, 0, "" },
21792204
{ "white-foreground", 0, 0, 0, 0, "off" },
21802205
{ 0,0,0,0,0,0 }
21812206
};
21822207
@@ -2375,19 +2400,23 @@
23752400
** scripts to be evaluated from TH1. Additionally, the Tcl
23762401
** interpreter will be able to evaluate arbitrary TH1
23772402
** expressions and scripts. Default: off.
23782403
**
23792404
** tcl-setup This is the setup script to be evaluated after creating
2380
-** and initializing the Tcl interpreter. By default, this
2405
+** (versionable) and initializing the Tcl interpreter. By default, this
23812406
** is empty and no extra setup is performed.
2407
+**
2408
+** th1-hooks If enabled (and Fossil was compiled with support for TH1
2409
+** hooks), special TH1 commands will be called before and
2410
+** after any Fossil command or web page. Default: off.
23822411
**
23832412
** th1-setup This is the setup script to be evaluated after creating
2384
-** and initializing the TH1 interpreter. By default, this
2413
+** (versionable) and initializing the TH1 interpreter. By default, this
23852414
** is empty and no extra setup is performed.
23862415
**
23872416
** th1-uri-regexp Specify which URI's are allowed in HTTP requests from
2388
-** TH1 scripts. If empty, no HTTP requests are allowed
2417
+** (versionable) TH1 scripts. If empty, no HTTP requests are allowed
23892418
** whatsoever. The default is an empty string.
23902419
**
23912420
** web-browser A shell command used to launch your preferred
23922421
** web browser when given a URL as an argument.
23932422
** Defaults to "start" on windows, "open" on Mac,
23942423
--- src/db.c
+++ src/db.c
@@ -785,10 +785,31 @@
785 assert( g.zMainDbType!=0 );
786 db_attach(zDbName, zLabel);
787 if( pWasAttached ) *pWasAttached = 1;
788 }
789 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
790
791 /*
792 ** Open the user database in "~/.fossil". Create the database anew if
793 ** it does not already exist.
794 **
@@ -801,11 +822,14 @@
801 ** case, invoke this routine with useAttach as 1.
802 */
803 void db_open_config(int useAttach){
804 char *zDbName;
805 char *zHome;
806 if( g.zConfigDbName ) return;
 
 
 
807 #if defined(_WIN32) || defined(__CYGWIN__)
808 zHome = fossil_getenv("LOCALAPPDATA");
809 if( zHome==0 ){
810 zHome = fossil_getenv("APPDATA");
811 if( zHome==0 ){
@@ -2169,14 +2193,15 @@
2169 { "ssh-command", 0, 40, 0, 0, "" },
2170 { "ssl-ca-location", 0, 40, 0, 0, "" },
2171 { "ssl-identity", 0, 40, 0, 0, "" },
2172 #ifdef FOSSIL_ENABLE_TCL
2173 { "tcl", 0, 0, 0, 0, "off" },
2174 { "tcl-setup", 0, 40, 0, 1, "" },
2175 #endif
2176 { "th1-setup", 0, 40, 0, 1, "" },
2177 { "th1-uri-regexp", 0, 40, 0, 0, "" },
 
2178 { "web-browser", 0, 32, 0, 0, "" },
2179 { "white-foreground", 0, 0, 0, 0, "off" },
2180 { 0,0,0,0,0,0 }
2181 };
2182
@@ -2375,19 +2400,23 @@
2375 ** scripts to be evaluated from TH1. Additionally, the Tcl
2376 ** interpreter will be able to evaluate arbitrary TH1
2377 ** expressions and scripts. Default: off.
2378 **
2379 ** tcl-setup This is the setup script to be evaluated after creating
2380 ** and initializing the Tcl interpreter. By default, this
2381 ** is empty and no extra setup is performed.
 
 
 
 
2382 **
2383 ** th1-setup This is the setup script to be evaluated after creating
2384 ** and initializing the TH1 interpreter. By default, this
2385 ** is empty and no extra setup is performed.
2386 **
2387 ** th1-uri-regexp Specify which URI's are allowed in HTTP requests from
2388 ** TH1 scripts. If empty, no HTTP requests are allowed
2389 ** whatsoever. The default is an empty string.
2390 **
2391 ** web-browser A shell command used to launch your preferred
2392 ** web browser when given a URL as an argument.
2393 ** Defaults to "start" on windows, "open" on Mac,
2394
--- src/db.c
+++ src/db.c
@@ -785,10 +785,31 @@
785 assert( g.zMainDbType!=0 );
786 db_attach(zDbName, zLabel);
787 if( pWasAttached ) *pWasAttached = 1;
788 }
789 }
790
791 /*
792 ** Close the user database.
793 */
794 void db_close_config(){
795 if( g.useAttach ){
796 db_detach("configdb");
797 g.useAttach = 0;
798 g.zConfigDbName = 0;
799 }else if( g.dbConfig ){
800 sqlite3_close(g.dbConfig);
801 g.dbConfig = 0;
802 g.zConfigDbType = 0;
803 g.zConfigDbName = 0;
804 }else if( g.db && fossil_strcmp(g.zMainDbType, "configdb")==0 ){
805 sqlite3_close(g.db);
806 g.db = 0;
807 g.zMainDbType = 0;
808 g.zConfigDbName = 0;
809 }
810 }
811
812 /*
813 ** Open the user database in "~/.fossil". Create the database anew if
814 ** it does not already exist.
815 **
@@ -801,11 +822,14 @@
822 ** case, invoke this routine with useAttach as 1.
823 */
824 void db_open_config(int useAttach){
825 char *zDbName;
826 char *zHome;
827 if( g.zConfigDbName ){
828 if( useAttach==g.useAttach ) return;
829 db_close_config();
830 }
831 #if defined(_WIN32) || defined(__CYGWIN__)
832 zHome = fossil_getenv("LOCALAPPDATA");
833 if( zHome==0 ){
834 zHome = fossil_getenv("APPDATA");
835 if( zHome==0 ){
@@ -2169,14 +2193,15 @@
2193 { "ssh-command", 0, 40, 0, 0, "" },
2194 { "ssl-ca-location", 0, 40, 0, 0, "" },
2195 { "ssl-identity", 0, 40, 0, 0, "" },
2196 #ifdef FOSSIL_ENABLE_TCL
2197 { "tcl", 0, 0, 0, 0, "off" },
2198 { "tcl-setup", 0, 40, 1, 1, "" },
2199 #endif
2200 { "th1-hooks", 0, 0, 0, 0, "off" },
2201 { "th1-setup", 0, 40, 1, 1, "" },
2202 { "th1-uri-regexp", 0, 40, 1, 0, "" },
2203 { "web-browser", 0, 32, 0, 0, "" },
2204 { "white-foreground", 0, 0, 0, 0, "off" },
2205 { 0,0,0,0,0,0 }
2206 };
2207
@@ -2375,19 +2400,23 @@
2400 ** scripts to be evaluated from TH1. Additionally, the Tcl
2401 ** interpreter will be able to evaluate arbitrary TH1
2402 ** expressions and scripts. Default: off.
2403 **
2404 ** tcl-setup This is the setup script to be evaluated after creating
2405 ** (versionable) and initializing the Tcl interpreter. By default, this
2406 ** is empty and no extra setup is performed.
2407 **
2408 ** th1-hooks If enabled (and Fossil was compiled with support for TH1
2409 ** hooks), special TH1 commands will be called before and
2410 ** after any Fossil command or web page. Default: off.
2411 **
2412 ** th1-setup This is the setup script to be evaluated after creating
2413 ** (versionable) and initializing the TH1 interpreter. By default, this
2414 ** is empty and no extra setup is performed.
2415 **
2416 ** th1-uri-regexp Specify which URI's are allowed in HTTP requests from
2417 ** (versionable) TH1 scripts. If empty, no HTTP requests are allowed
2418 ** whatsoever. The default is an empty string.
2419 **
2420 ** web-browser A shell command used to launch your preferred
2421 ** web browser when given a URL as an argument.
2422 ** Defaults to "start" on windows, "open" on Mac,
2423
+36 -7
--- src/db.c
+++ src/db.c
@@ -785,10 +785,31 @@
785785
assert( g.zMainDbType!=0 );
786786
db_attach(zDbName, zLabel);
787787
if( pWasAttached ) *pWasAttached = 1;
788788
}
789789
}
790
+
791
+/*
792
+** Close the user database.
793
+*/
794
+void db_close_config(){
795
+ if( g.useAttach ){
796
+ db_detach("configdb");
797
+ g.useAttach = 0;
798
+ g.zConfigDbName = 0;
799
+ }else if( g.dbConfig ){
800
+ sqlite3_close(g.dbConfig);
801
+ g.dbConfig = 0;
802
+ g.zConfigDbType = 0;
803
+ g.zConfigDbName = 0;
804
+ }else if( g.db && fossil_strcmp(g.zMainDbType, "configdb")==0 ){
805
+ sqlite3_close(g.db);
806
+ g.db = 0;
807
+ g.zMainDbType = 0;
808
+ g.zConfigDbName = 0;
809
+ }
810
+}
790811
791812
/*
792813
** Open the user database in "~/.fossil". Create the database anew if
793814
** it does not already exist.
794815
**
@@ -801,11 +822,14 @@
801822
** case, invoke this routine with useAttach as 1.
802823
*/
803824
void db_open_config(int useAttach){
804825
char *zDbName;
805826
char *zHome;
806
- if( g.zConfigDbName ) return;
827
+ if( g.zConfigDbName ){
828
+ if( useAttach==g.useAttach ) return;
829
+ db_close_config();
830
+ }
807831
#if defined(_WIN32) || defined(__CYGWIN__)
808832
zHome = fossil_getenv("LOCALAPPDATA");
809833
if( zHome==0 ){
810834
zHome = fossil_getenv("APPDATA");
811835
if( zHome==0 ){
@@ -2169,14 +2193,15 @@
21692193
{ "ssh-command", 0, 40, 0, 0, "" },
21702194
{ "ssl-ca-location", 0, 40, 0, 0, "" },
21712195
{ "ssl-identity", 0, 40, 0, 0, "" },
21722196
#ifdef FOSSIL_ENABLE_TCL
21732197
{ "tcl", 0, 0, 0, 0, "off" },
2174
- { "tcl-setup", 0, 40, 0, 1, "" },
2198
+ { "tcl-setup", 0, 40, 1, 1, "" },
21752199
#endif
2176
- { "th1-setup", 0, 40, 0, 1, "" },
2177
- { "th1-uri-regexp", 0, 40, 0, 0, "" },
2200
+ { "th1-hooks", 0, 0, 0, 0, "off" },
2201
+ { "th1-setup", 0, 40, 1, 1, "" },
2202
+ { "th1-uri-regexp", 0, 40, 1, 0, "" },
21782203
{ "web-browser", 0, 32, 0, 0, "" },
21792204
{ "white-foreground", 0, 0, 0, 0, "off" },
21802205
{ 0,0,0,0,0,0 }
21812206
};
21822207
@@ -2375,19 +2400,23 @@
23752400
** scripts to be evaluated from TH1. Additionally, the Tcl
23762401
** interpreter will be able to evaluate arbitrary TH1
23772402
** expressions and scripts. Default: off.
23782403
**
23792404
** tcl-setup This is the setup script to be evaluated after creating
2380
-** and initializing the Tcl interpreter. By default, this
2405
+** (versionable) and initializing the Tcl interpreter. By default, this
23812406
** is empty and no extra setup is performed.
2407
+**
2408
+** th1-hooks If enabled (and Fossil was compiled with support for TH1
2409
+** hooks), special TH1 commands will be called before and
2410
+** after any Fossil command or web page. Default: off.
23822411
**
23832412
** th1-setup This is the setup script to be evaluated after creating
2384
-** and initializing the TH1 interpreter. By default, this
2413
+** (versionable) and initializing the TH1 interpreter. By default, this
23852414
** is empty and no extra setup is performed.
23862415
**
23872416
** th1-uri-regexp Specify which URI's are allowed in HTTP requests from
2388
-** TH1 scripts. If empty, no HTTP requests are allowed
2417
+** (versionable) TH1 scripts. If empty, no HTTP requests are allowed
23892418
** whatsoever. The default is an empty string.
23902419
**
23912420
** web-browser A shell command used to launch your preferred
23922421
** web browser when given a URL as an argument.
23932422
** Defaults to "start" on windows, "open" on Mac,
23942423
--- src/db.c
+++ src/db.c
@@ -785,10 +785,31 @@
785 assert( g.zMainDbType!=0 );
786 db_attach(zDbName, zLabel);
787 if( pWasAttached ) *pWasAttached = 1;
788 }
789 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
790
791 /*
792 ** Open the user database in "~/.fossil". Create the database anew if
793 ** it does not already exist.
794 **
@@ -801,11 +822,14 @@
801 ** case, invoke this routine with useAttach as 1.
802 */
803 void db_open_config(int useAttach){
804 char *zDbName;
805 char *zHome;
806 if( g.zConfigDbName ) return;
 
 
 
807 #if defined(_WIN32) || defined(__CYGWIN__)
808 zHome = fossil_getenv("LOCALAPPDATA");
809 if( zHome==0 ){
810 zHome = fossil_getenv("APPDATA");
811 if( zHome==0 ){
@@ -2169,14 +2193,15 @@
2169 { "ssh-command", 0, 40, 0, 0, "" },
2170 { "ssl-ca-location", 0, 40, 0, 0, "" },
2171 { "ssl-identity", 0, 40, 0, 0, "" },
2172 #ifdef FOSSIL_ENABLE_TCL
2173 { "tcl", 0, 0, 0, 0, "off" },
2174 { "tcl-setup", 0, 40, 0, 1, "" },
2175 #endif
2176 { "th1-setup", 0, 40, 0, 1, "" },
2177 { "th1-uri-regexp", 0, 40, 0, 0, "" },
 
2178 { "web-browser", 0, 32, 0, 0, "" },
2179 { "white-foreground", 0, 0, 0, 0, "off" },
2180 { 0,0,0,0,0,0 }
2181 };
2182
@@ -2375,19 +2400,23 @@
2375 ** scripts to be evaluated from TH1. Additionally, the Tcl
2376 ** interpreter will be able to evaluate arbitrary TH1
2377 ** expressions and scripts. Default: off.
2378 **
2379 ** tcl-setup This is the setup script to be evaluated after creating
2380 ** and initializing the Tcl interpreter. By default, this
2381 ** is empty and no extra setup is performed.
 
 
 
 
2382 **
2383 ** th1-setup This is the setup script to be evaluated after creating
2384 ** and initializing the TH1 interpreter. By default, this
2385 ** is empty and no extra setup is performed.
2386 **
2387 ** th1-uri-regexp Specify which URI's are allowed in HTTP requests from
2388 ** TH1 scripts. If empty, no HTTP requests are allowed
2389 ** whatsoever. The default is an empty string.
2390 **
2391 ** web-browser A shell command used to launch your preferred
2392 ** web browser when given a URL as an argument.
2393 ** Defaults to "start" on windows, "open" on Mac,
2394
--- src/db.c
+++ src/db.c
@@ -785,10 +785,31 @@
785 assert( g.zMainDbType!=0 );
786 db_attach(zDbName, zLabel);
787 if( pWasAttached ) *pWasAttached = 1;
788 }
789 }
790
791 /*
792 ** Close the user database.
793 */
794 void db_close_config(){
795 if( g.useAttach ){
796 db_detach("configdb");
797 g.useAttach = 0;
798 g.zConfigDbName = 0;
799 }else if( g.dbConfig ){
800 sqlite3_close(g.dbConfig);
801 g.dbConfig = 0;
802 g.zConfigDbType = 0;
803 g.zConfigDbName = 0;
804 }else if( g.db && fossil_strcmp(g.zMainDbType, "configdb")==0 ){
805 sqlite3_close(g.db);
806 g.db = 0;
807 g.zMainDbType = 0;
808 g.zConfigDbName = 0;
809 }
810 }
811
812 /*
813 ** Open the user database in "~/.fossil". Create the database anew if
814 ** it does not already exist.
815 **
@@ -801,11 +822,14 @@
822 ** case, invoke this routine with useAttach as 1.
823 */
824 void db_open_config(int useAttach){
825 char *zDbName;
826 char *zHome;
827 if( g.zConfigDbName ){
828 if( useAttach==g.useAttach ) return;
829 db_close_config();
830 }
831 #if defined(_WIN32) || defined(__CYGWIN__)
832 zHome = fossil_getenv("LOCALAPPDATA");
833 if( zHome==0 ){
834 zHome = fossil_getenv("APPDATA");
835 if( zHome==0 ){
@@ -2169,14 +2193,15 @@
2193 { "ssh-command", 0, 40, 0, 0, "" },
2194 { "ssl-ca-location", 0, 40, 0, 0, "" },
2195 { "ssl-identity", 0, 40, 0, 0, "" },
2196 #ifdef FOSSIL_ENABLE_TCL
2197 { "tcl", 0, 0, 0, 0, "off" },
2198 { "tcl-setup", 0, 40, 1, 1, "" },
2199 #endif
2200 { "th1-hooks", 0, 0, 0, 0, "off" },
2201 { "th1-setup", 0, 40, 1, 1, "" },
2202 { "th1-uri-regexp", 0, 40, 1, 0, "" },
2203 { "web-browser", 0, 32, 0, 0, "" },
2204 { "white-foreground", 0, 0, 0, 0, "off" },
2205 { 0,0,0,0,0,0 }
2206 };
2207
@@ -2375,19 +2400,23 @@
2400 ** scripts to be evaluated from TH1. Additionally, the Tcl
2401 ** interpreter will be able to evaluate arbitrary TH1
2402 ** expressions and scripts. Default: off.
2403 **
2404 ** tcl-setup This is the setup script to be evaluated after creating
2405 ** (versionable) and initializing the Tcl interpreter. By default, this
2406 ** is empty and no extra setup is performed.
2407 **
2408 ** th1-hooks If enabled (and Fossil was compiled with support for TH1
2409 ** hooks), special TH1 commands will be called before and
2410 ** after any Fossil command or web page. Default: off.
2411 **
2412 ** th1-setup This is the setup script to be evaluated after creating
2413 ** (versionable) and initializing the TH1 interpreter. By default, this
2414 ** is empty and no extra setup is performed.
2415 **
2416 ** th1-uri-regexp Specify which URI's are allowed in HTTP requests from
2417 ** (versionable) TH1 scripts. If empty, no HTTP requests are allowed
2418 ** whatsoever. The default is an empty string.
2419 **
2420 ** web-browser A shell command used to launch your preferred
2421 ** web browser when given a URL as an argument.
2422 ** Defaults to "start" on windows, "open" on Mac,
2423
+119 -10
--- src/main.c
+++ src/main.c
@@ -194,10 +194,13 @@
194194
char zCsrfToken[12]; /* Value of the anti-CSRF token */
195195
int okCsrf; /* Anti-CSRF token is present and valid */
196196
197197
int parseCnt[10]; /* Counts of artifacts parsed */
198198
FILE *fDebug; /* Write debug information here, if the file exists */
199
+#ifdef FOSSIL_ENABLE_TH1_HOOKS
200
+ int fNoThHook; /* Disable all TH1 command/webpage hooks */
201
+#endif
199202
int thTrace; /* True to enable TH1 debugging output */
200203
Blob thLog; /* Text of the TH1 debugging output */
201204
202205
int isHome; /* True if rendering the "home" page */
203206
@@ -620,10 +623,13 @@
620623
g.fSshClient = 0;
621624
g.zSshCmd = 0;
622625
if( g.fSqlTrace ) g.fSqlStats = 1;
623626
g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
624627
g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
628
+#ifdef FOSSIL_ENABLE_TH1_HOOKS
629
+ g.fNoThHook = find_option("no-th-hook", 0, 0)!=0;
630
+#endif
625631
g.zHttpAuth = 0;
626632
g.zLogin = find_option("user", "U", 1);
627633
g.zSSLIdentity = find_option("ssl-identity", 0, 1);
628634
g.zErrlog = find_option("errorlog", 0, 1);
629635
if( find_option("utc",0,0) ) g.fTimeFormat = 1;
@@ -649,13 +655,30 @@
649655
if( !is_valid_fd(2) ) fossil_panic("file descriptor 2 not open");
650656
/* if( is_valid_fd(3) ) fossil_warning("file descriptor 3 is open"); */
651657
#endif
652658
rc = name_search(zCmdName, aCommand, count(aCommand), &idx);
653659
if( rc==1 ){
654
- fossil_fatal("%s: unknown command: %s\n"
655
- "%s: use \"help\" for more information\n",
656
- g.argv[0], zCmdName, g.argv[0]);
660
+#ifdef FOSSIL_ENABLE_TH1_HOOKS
661
+ if( !g.isHTTP && !g.fNoThHook ){
662
+ rc = Th_CommandHook(zCmdName, 0);
663
+ }else{
664
+ rc = TH_OK;
665
+ }
666
+ if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
667
+ if( rc==TH_OK || rc==TH_RETURN ){
668
+#endif
669
+ fossil_fatal("%s: unknown command: %s\n"
670
+ "%s: use \"help\" for more information\n",
671
+ g.argv[0], zCmdName, g.argv[0]);
672
+#ifdef FOSSIL_ENABLE_TH1_HOOKS
673
+ }
674
+ if( !g.isHTTP && !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
675
+ Th_CommandNotify(zCmdName, 0);
676
+ }
677
+ }
678
+ fossil_exit(0);
679
+#endif
657680
}else if( rc==2 ){
658681
int i, n;
659682
Blob couldbe;
660683
blob_zero(&couldbe);
661684
n = strlen(zCmdName);
@@ -669,11 +692,44 @@
669692
"%s: use \"help\" for more information\n",
670693
g.argv[0], zCmdName, g.argv[0], blob_str(&couldbe), g.argv[0]);
671694
fossil_exit(1);
672695
}
673696
atexit( fossil_atexit );
674
- aCommand[idx].xFunc();
697
+#ifdef FOSSIL_ENABLE_TH1_HOOKS
698
+ /*
699
+ ** The TH1 return codes from the hook will be handled as follows:
700
+ **
701
+ ** TH_OK: The xFunc() and the TH1 notification will both be executed.
702
+ **
703
+ ** TH_ERROR: The xFunc() will be executed, the TH1 notification will be
704
+ ** skipped. If the xFunc() is being hooked, the error message
705
+ ** will be emitted.
706
+ **
707
+ ** TH_BREAK: The xFunc() and the TH1 notification will both be skipped.
708
+ **
709
+ ** TH_RETURN: The xFunc() will be executed, the TH1 notification will be
710
+ ** skipped.
711
+ **
712
+ ** TH_CONTINUE: The xFunc() will be skipped, the TH1 notification will be
713
+ ** executed.
714
+ */
715
+ if( !g.isHTTP && !g.fNoThHook ){
716
+ rc = Th_CommandHook(aCommand[idx].zName, aCommand[idx].cmdFlags);
717
+ }else{
718
+ rc = TH_OK;
719
+ }
720
+ if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
721
+ if( rc==TH_OK || rc==TH_RETURN ){
722
+#endif
723
+ aCommand[idx].xFunc();
724
+#ifdef FOSSIL_ENABLE_TH1_HOOKS
725
+ }
726
+ if( !g.isHTTP && !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
727
+ Th_CommandNotify(aCommand[idx].zName, aCommand[idx].cmdFlags);
728
+ }
729
+ }
730
+#endif
675731
fossil_exit(0);
676732
/*NOT_REACHED*/
677733
return 0;
678734
}
679735
@@ -861,10 +917,13 @@
861917
fossil_print("SQLite %s %.30s\n", sqlite3_libversion(), sqlite3_sourceid());
862918
fossil_print("Schema version %s\n", AUX_SCHEMA);
863919
fossil_print("zlib %s, loaded %s\n", ZLIB_VERSION, zlibVersion());
864920
#if defined(FOSSIL_ENABLE_SSL)
865921
fossil_print("SSL (%s)\n", SSLeay_version(SSLEAY_VERSION));
922
+#endif
923
+#if defined(FOSSIL_ENABLE_TH1_HOOKS)
924
+ fossil_print("TH1_HOOKS\n");
866925
#endif
867926
#if defined(FOSSIL_ENABLE_TCL)
868927
Th_FossilInit(TH_INIT_DEFAULT | TH_INIT_FORCE_TCL);
869928
rc = Th_Eval(g.interp, 0, "tclInvoke info patchlevel", -1);
870929
zRc = Th_ReturnCodeName(rc, 0);
@@ -1486,21 +1545,37 @@
14861545
}
14871546
14881547
/* Locate the method specified by the path and execute the function
14891548
** that implements that method.
14901549
*/
1491
- if( name_search(g.zPath, aWebpage, count(aWebpage), &idx) &&
1492
- name_search("not_found", aWebpage, count(aWebpage), &idx) ){
1550
+ if( name_search(g.zPath, aWebpage, count(aWebpage), &idx) ){
14931551
#ifdef FOSSIL_ENABLE_JSON
14941552
if(g.json.isJsonMode){
14951553
json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,0);
14961554
}else
14971555
#endif
14981556
{
1499
- cgi_set_status(404,"Not Found");
1500
- @ <h1>Not Found</h1>
1501
- @ <p>Page not found: %h(g.zPath)</p>
1557
+#ifdef FOSSIL_ENABLE_TH1_HOOKS
1558
+ int rc;
1559
+ if( !g.fNoThHook ){
1560
+ rc = Th_WebpageHook(g.zPath, 0);
1561
+ }else{
1562
+ rc = TH_OK;
1563
+ }
1564
+ if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
1565
+ if( rc==TH_OK || rc==TH_RETURN ){
1566
+#endif
1567
+ cgi_set_status(404,"Not Found");
1568
+ @ <h1>Not Found</h1>
1569
+ @ <p>Page not found: %h(g.zPath)</p>
1570
+#ifdef FOSSIL_ENABLE_TH1_HOOKS
1571
+ }
1572
+ if( !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
1573
+ Th_WebpageNotify(g.zPath, 0);
1574
+ }
1575
+ }
1576
+#endif
15021577
}
15031578
}else if( aWebpage[idx].xFunc!=page_xfer && db_schema_is_outofdate() ){
15041579
#ifdef FOSSIL_ENABLE_JSON
15051580
if(g.json.isJsonMode){
15061581
json_err(FSL_JSON_E_DB_NEEDS_REBUILD,NULL,0);
@@ -1510,11 +1585,45 @@
15101585
@ <h1>Server Configuration Error</h1>
15111586
@ <p>The database schema on the server is out-of-date. Please ask
15121587
@ the administrator to run <b>fossil rebuild</b>.</p>
15131588
}
15141589
}else{
1515
- aWebpage[idx].xFunc();
1590
+#ifdef FOSSIL_ENABLE_TH1_HOOKS
1591
+ /*
1592
+ ** The TH1 return codes from the hook will be handled as follows:
1593
+ **
1594
+ ** TH_OK: The xFunc() and the TH1 notification will both be executed.
1595
+ **
1596
+ ** TH_ERROR: The xFunc() will be executed, the TH1 notification will be
1597
+ ** skipped. If the xFunc() is being hooked, the error message
1598
+ ** will be emitted.
1599
+ **
1600
+ ** TH_BREAK: The xFunc() and the TH1 notification will both be skipped.
1601
+ **
1602
+ ** TH_RETURN: The xFunc() will be executed, the TH1 notification will be
1603
+ ** skipped.
1604
+ **
1605
+ ** TH_CONTINUE: The xFunc() will be skipped, the TH1 notification will be
1606
+ ** executed.
1607
+ */
1608
+ int rc;
1609
+ if( !g.fNoThHook ){
1610
+ rc = Th_WebpageHook(aWebpage[idx].zName, aWebpage[idx].cmdFlags);
1611
+ }else{
1612
+ rc = TH_OK;
1613
+ }
1614
+ if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
1615
+ if( rc==TH_OK || rc==TH_RETURN ){
1616
+#endif
1617
+ aWebpage[idx].xFunc();
1618
+#ifdef FOSSIL_ENABLE_TH1_HOOKS
1619
+ }
1620
+ if( !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
1621
+ Th_WebpageNotify(aWebpage[idx].zName, aWebpage[idx].cmdFlags);
1622
+ }
1623
+ }
1624
+#endif
15161625
}
15171626
15181627
/* Return the result.
15191628
*/
15201629
cgi_reply();
15211630
--- src/main.c
+++ src/main.c
@@ -194,10 +194,13 @@
194 char zCsrfToken[12]; /* Value of the anti-CSRF token */
195 int okCsrf; /* Anti-CSRF token is present and valid */
196
197 int parseCnt[10]; /* Counts of artifacts parsed */
198 FILE *fDebug; /* Write debug information here, if the file exists */
 
 
 
199 int thTrace; /* True to enable TH1 debugging output */
200 Blob thLog; /* Text of the TH1 debugging output */
201
202 int isHome; /* True if rendering the "home" page */
203
@@ -620,10 +623,13 @@
620 g.fSshClient = 0;
621 g.zSshCmd = 0;
622 if( g.fSqlTrace ) g.fSqlStats = 1;
623 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
624 g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
 
 
 
625 g.zHttpAuth = 0;
626 g.zLogin = find_option("user", "U", 1);
627 g.zSSLIdentity = find_option("ssl-identity", 0, 1);
628 g.zErrlog = find_option("errorlog", 0, 1);
629 if( find_option("utc",0,0) ) g.fTimeFormat = 1;
@@ -649,13 +655,30 @@
649 if( !is_valid_fd(2) ) fossil_panic("file descriptor 2 not open");
650 /* if( is_valid_fd(3) ) fossil_warning("file descriptor 3 is open"); */
651 #endif
652 rc = name_search(zCmdName, aCommand, count(aCommand), &idx);
653 if( rc==1 ){
654 fossil_fatal("%s: unknown command: %s\n"
655 "%s: use \"help\" for more information\n",
656 g.argv[0], zCmdName, g.argv[0]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
657 }else if( rc==2 ){
658 int i, n;
659 Blob couldbe;
660 blob_zero(&couldbe);
661 n = strlen(zCmdName);
@@ -669,11 +692,44 @@
669 "%s: use \"help\" for more information\n",
670 g.argv[0], zCmdName, g.argv[0], blob_str(&couldbe), g.argv[0]);
671 fossil_exit(1);
672 }
673 atexit( fossil_atexit );
674 aCommand[idx].xFunc();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
675 fossil_exit(0);
676 /*NOT_REACHED*/
677 return 0;
678 }
679
@@ -861,10 +917,13 @@
861 fossil_print("SQLite %s %.30s\n", sqlite3_libversion(), sqlite3_sourceid());
862 fossil_print("Schema version %s\n", AUX_SCHEMA);
863 fossil_print("zlib %s, loaded %s\n", ZLIB_VERSION, zlibVersion());
864 #if defined(FOSSIL_ENABLE_SSL)
865 fossil_print("SSL (%s)\n", SSLeay_version(SSLEAY_VERSION));
 
 
 
866 #endif
867 #if defined(FOSSIL_ENABLE_TCL)
868 Th_FossilInit(TH_INIT_DEFAULT | TH_INIT_FORCE_TCL);
869 rc = Th_Eval(g.interp, 0, "tclInvoke info patchlevel", -1);
870 zRc = Th_ReturnCodeName(rc, 0);
@@ -1486,21 +1545,37 @@
1486 }
1487
1488 /* Locate the method specified by the path and execute the function
1489 ** that implements that method.
1490 */
1491 if( name_search(g.zPath, aWebpage, count(aWebpage), &idx) &&
1492 name_search("not_found", aWebpage, count(aWebpage), &idx) ){
1493 #ifdef FOSSIL_ENABLE_JSON
1494 if(g.json.isJsonMode){
1495 json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,0);
1496 }else
1497 #endif
1498 {
1499 cgi_set_status(404,"Not Found");
1500 @ <h1>Not Found</h1>
1501 @ <p>Page not found: %h(g.zPath)</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1502 }
1503 }else if( aWebpage[idx].xFunc!=page_xfer && db_schema_is_outofdate() ){
1504 #ifdef FOSSIL_ENABLE_JSON
1505 if(g.json.isJsonMode){
1506 json_err(FSL_JSON_E_DB_NEEDS_REBUILD,NULL,0);
@@ -1510,11 +1585,45 @@
1510 @ <h1>Server Configuration Error</h1>
1511 @ <p>The database schema on the server is out-of-date. Please ask
1512 @ the administrator to run <b>fossil rebuild</b>.</p>
1513 }
1514 }else{
1515 aWebpage[idx].xFunc();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1516 }
1517
1518 /* Return the result.
1519 */
1520 cgi_reply();
1521
--- src/main.c
+++ src/main.c
@@ -194,10 +194,13 @@
194 char zCsrfToken[12]; /* Value of the anti-CSRF token */
195 int okCsrf; /* Anti-CSRF token is present and valid */
196
197 int parseCnt[10]; /* Counts of artifacts parsed */
198 FILE *fDebug; /* Write debug information here, if the file exists */
199 #ifdef FOSSIL_ENABLE_TH1_HOOKS
200 int fNoThHook; /* Disable all TH1 command/webpage hooks */
201 #endif
202 int thTrace; /* True to enable TH1 debugging output */
203 Blob thLog; /* Text of the TH1 debugging output */
204
205 int isHome; /* True if rendering the "home" page */
206
@@ -620,10 +623,13 @@
623 g.fSshClient = 0;
624 g.zSshCmd = 0;
625 if( g.fSqlTrace ) g.fSqlStats = 1;
626 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
627 g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
628 #ifdef FOSSIL_ENABLE_TH1_HOOKS
629 g.fNoThHook = find_option("no-th-hook", 0, 0)!=0;
630 #endif
631 g.zHttpAuth = 0;
632 g.zLogin = find_option("user", "U", 1);
633 g.zSSLIdentity = find_option("ssl-identity", 0, 1);
634 g.zErrlog = find_option("errorlog", 0, 1);
635 if( find_option("utc",0,0) ) g.fTimeFormat = 1;
@@ -649,13 +655,30 @@
655 if( !is_valid_fd(2) ) fossil_panic("file descriptor 2 not open");
656 /* if( is_valid_fd(3) ) fossil_warning("file descriptor 3 is open"); */
657 #endif
658 rc = name_search(zCmdName, aCommand, count(aCommand), &idx);
659 if( rc==1 ){
660 #ifdef FOSSIL_ENABLE_TH1_HOOKS
661 if( !g.isHTTP && !g.fNoThHook ){
662 rc = Th_CommandHook(zCmdName, 0);
663 }else{
664 rc = TH_OK;
665 }
666 if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
667 if( rc==TH_OK || rc==TH_RETURN ){
668 #endif
669 fossil_fatal("%s: unknown command: %s\n"
670 "%s: use \"help\" for more information\n",
671 g.argv[0], zCmdName, g.argv[0]);
672 #ifdef FOSSIL_ENABLE_TH1_HOOKS
673 }
674 if( !g.isHTTP && !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
675 Th_CommandNotify(zCmdName, 0);
676 }
677 }
678 fossil_exit(0);
679 #endif
680 }else if( rc==2 ){
681 int i, n;
682 Blob couldbe;
683 blob_zero(&couldbe);
684 n = strlen(zCmdName);
@@ -669,11 +692,44 @@
692 "%s: use \"help\" for more information\n",
693 g.argv[0], zCmdName, g.argv[0], blob_str(&couldbe), g.argv[0]);
694 fossil_exit(1);
695 }
696 atexit( fossil_atexit );
697 #ifdef FOSSIL_ENABLE_TH1_HOOKS
698 /*
699 ** The TH1 return codes from the hook will be handled as follows:
700 **
701 ** TH_OK: The xFunc() and the TH1 notification will both be executed.
702 **
703 ** TH_ERROR: The xFunc() will be executed, the TH1 notification will be
704 ** skipped. If the xFunc() is being hooked, the error message
705 ** will be emitted.
706 **
707 ** TH_BREAK: The xFunc() and the TH1 notification will both be skipped.
708 **
709 ** TH_RETURN: The xFunc() will be executed, the TH1 notification will be
710 ** skipped.
711 **
712 ** TH_CONTINUE: The xFunc() will be skipped, the TH1 notification will be
713 ** executed.
714 */
715 if( !g.isHTTP && !g.fNoThHook ){
716 rc = Th_CommandHook(aCommand[idx].zName, aCommand[idx].cmdFlags);
717 }else{
718 rc = TH_OK;
719 }
720 if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
721 if( rc==TH_OK || rc==TH_RETURN ){
722 #endif
723 aCommand[idx].xFunc();
724 #ifdef FOSSIL_ENABLE_TH1_HOOKS
725 }
726 if( !g.isHTTP && !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
727 Th_CommandNotify(aCommand[idx].zName, aCommand[idx].cmdFlags);
728 }
729 }
730 #endif
731 fossil_exit(0);
732 /*NOT_REACHED*/
733 return 0;
734 }
735
@@ -861,10 +917,13 @@
917 fossil_print("SQLite %s %.30s\n", sqlite3_libversion(), sqlite3_sourceid());
918 fossil_print("Schema version %s\n", AUX_SCHEMA);
919 fossil_print("zlib %s, loaded %s\n", ZLIB_VERSION, zlibVersion());
920 #if defined(FOSSIL_ENABLE_SSL)
921 fossil_print("SSL (%s)\n", SSLeay_version(SSLEAY_VERSION));
922 #endif
923 #if defined(FOSSIL_ENABLE_TH1_HOOKS)
924 fossil_print("TH1_HOOKS\n");
925 #endif
926 #if defined(FOSSIL_ENABLE_TCL)
927 Th_FossilInit(TH_INIT_DEFAULT | TH_INIT_FORCE_TCL);
928 rc = Th_Eval(g.interp, 0, "tclInvoke info patchlevel", -1);
929 zRc = Th_ReturnCodeName(rc, 0);
@@ -1486,21 +1545,37 @@
1545 }
1546
1547 /* Locate the method specified by the path and execute the function
1548 ** that implements that method.
1549 */
1550 if( name_search(g.zPath, aWebpage, count(aWebpage), &idx) ){
 
1551 #ifdef FOSSIL_ENABLE_JSON
1552 if(g.json.isJsonMode){
1553 json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,0);
1554 }else
1555 #endif
1556 {
1557 #ifdef FOSSIL_ENABLE_TH1_HOOKS
1558 int rc;
1559 if( !g.fNoThHook ){
1560 rc = Th_WebpageHook(g.zPath, 0);
1561 }else{
1562 rc = TH_OK;
1563 }
1564 if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
1565 if( rc==TH_OK || rc==TH_RETURN ){
1566 #endif
1567 cgi_set_status(404,"Not Found");
1568 @ <h1>Not Found</h1>
1569 @ <p>Page not found: %h(g.zPath)</p>
1570 #ifdef FOSSIL_ENABLE_TH1_HOOKS
1571 }
1572 if( !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
1573 Th_WebpageNotify(g.zPath, 0);
1574 }
1575 }
1576 #endif
1577 }
1578 }else if( aWebpage[idx].xFunc!=page_xfer && db_schema_is_outofdate() ){
1579 #ifdef FOSSIL_ENABLE_JSON
1580 if(g.json.isJsonMode){
1581 json_err(FSL_JSON_E_DB_NEEDS_REBUILD,NULL,0);
@@ -1510,11 +1585,45 @@
1585 @ <h1>Server Configuration Error</h1>
1586 @ <p>The database schema on the server is out-of-date. Please ask
1587 @ the administrator to run <b>fossil rebuild</b>.</p>
1588 }
1589 }else{
1590 #ifdef FOSSIL_ENABLE_TH1_HOOKS
1591 /*
1592 ** The TH1 return codes from the hook will be handled as follows:
1593 **
1594 ** TH_OK: The xFunc() and the TH1 notification will both be executed.
1595 **
1596 ** TH_ERROR: The xFunc() will be executed, the TH1 notification will be
1597 ** skipped. If the xFunc() is being hooked, the error message
1598 ** will be emitted.
1599 **
1600 ** TH_BREAK: The xFunc() and the TH1 notification will both be skipped.
1601 **
1602 ** TH_RETURN: The xFunc() will be executed, the TH1 notification will be
1603 ** skipped.
1604 **
1605 ** TH_CONTINUE: The xFunc() will be skipped, the TH1 notification will be
1606 ** executed.
1607 */
1608 int rc;
1609 if( !g.fNoThHook ){
1610 rc = Th_WebpageHook(aWebpage[idx].zName, aWebpage[idx].cmdFlags);
1611 }else{
1612 rc = TH_OK;
1613 }
1614 if( rc==TH_OK || rc==TH_RETURN || rc==TH_CONTINUE ){
1615 if( rc==TH_OK || rc==TH_RETURN ){
1616 #endif
1617 aWebpage[idx].xFunc();
1618 #ifdef FOSSIL_ENABLE_TH1_HOOKS
1619 }
1620 if( !g.fNoThHook && (rc==TH_OK || rc==TH_CONTINUE) ){
1621 Th_WebpageNotify(aWebpage[idx].zName, aWebpage[idx].cmdFlags);
1622 }
1623 }
1624 #endif
1625 }
1626
1627 /* Return the result.
1628 */
1629 cgi_reply();
1630
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -409,10 +409,14 @@
409409
# FOSSIL_ENABLE_JSON = 1
410410
411411
#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
412412
#
413413
# FOSSIL_ENABLE_SSL = 1
414
+
415
+#### Enable hooks for commands and web pages via TH1
416
+#
417
+# FOSSIL_ENABLE_TH1_HOOKS = 1
414418
415419
#### Enable scripting support via Tcl/Tk
416420
#
417421
# FOSSIL_ENABLE_TCL = 1
418422
@@ -538,10 +542,16 @@
538542
# With HTTPS support
539543
ifdef FOSSIL_ENABLE_SSL
540544
TCC += -DFOSSIL_ENABLE_SSL=1
541545
RCC += -DFOSSIL_ENABLE_SSL=1
542546
endif
547
+
548
+# With TH1 hook support
549
+ifdef FOSSIL_ENABLE_TH1_HOOKS
550
+TCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
551
+RCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
552
+endif
543553
544554
# With Tcl support
545555
ifdef FOSSIL_ENABLE_TCL
546556
TCC += -DFOSSIL_ENABLE_TCL=1
547557
RCC += -DFOSSIL_ENABLE_TCL=1
@@ -1034,10 +1044,13 @@
10341044
# Uncomment to enable JSON API
10351045
# FOSSIL_ENABLE_JSON = 1
10361046
10371047
# Uncomment to enable SSL support
10381048
# FOSSIL_ENABLE_SSL = 1
1049
+
1050
+# Uncomment to enable TH1 hooks
1051
+# FOSSIL_ENABLE_TH1_HOOKS = 1
10391052
10401053
# Uncomment to enable Tcl support
10411054
# FOSSIL_ENABLE_TCL = 1
10421055
10431056
!ifdef FOSSIL_ENABLE_SSL
@@ -1092,10 +1105,15 @@
10921105
TCC = $(TCC) /DFOSSIL_ENABLE_SSL=1
10931106
RCC = $(RCC) /DFOSSIL_ENABLE_SSL=1
10941107
LIBS = $(LIBS) $(SSLLIB)
10951108
LIBDIR = $(LIBDIR) /LIBPATH:$(SSLLIBDIR)
10961109
!endif
1110
+
1111
+!ifdef FOSSIL_ENABLE_TH1_HOOKS
1112
+TCC = $(TCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
1113
+RCC = $(RCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
1114
+!endif
10971115
10981116
!ifdef FOSSIL_ENABLE_TCL
10991117
TCC = $(TCC) /DFOSSIL_ENABLE_TCL=1
11001118
RCC = $(RCC) /DFOSSIL_ENABLE_TCL=1
11011119
TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
11021120
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -409,10 +409,14 @@
409 # FOSSIL_ENABLE_JSON = 1
410
411 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
412 #
413 # FOSSIL_ENABLE_SSL = 1
 
 
 
 
414
415 #### Enable scripting support via Tcl/Tk
416 #
417 # FOSSIL_ENABLE_TCL = 1
418
@@ -538,10 +542,16 @@
538 # With HTTPS support
539 ifdef FOSSIL_ENABLE_SSL
540 TCC += -DFOSSIL_ENABLE_SSL=1
541 RCC += -DFOSSIL_ENABLE_SSL=1
542 endif
 
 
 
 
 
 
543
544 # With Tcl support
545 ifdef FOSSIL_ENABLE_TCL
546 TCC += -DFOSSIL_ENABLE_TCL=1
547 RCC += -DFOSSIL_ENABLE_TCL=1
@@ -1034,10 +1044,13 @@
1034 # Uncomment to enable JSON API
1035 # FOSSIL_ENABLE_JSON = 1
1036
1037 # Uncomment to enable SSL support
1038 # FOSSIL_ENABLE_SSL = 1
 
 
 
1039
1040 # Uncomment to enable Tcl support
1041 # FOSSIL_ENABLE_TCL = 1
1042
1043 !ifdef FOSSIL_ENABLE_SSL
@@ -1092,10 +1105,15 @@
1092 TCC = $(TCC) /DFOSSIL_ENABLE_SSL=1
1093 RCC = $(RCC) /DFOSSIL_ENABLE_SSL=1
1094 LIBS = $(LIBS) $(SSLLIB)
1095 LIBDIR = $(LIBDIR) /LIBPATH:$(SSLLIBDIR)
1096 !endif
 
 
 
 
 
1097
1098 !ifdef FOSSIL_ENABLE_TCL
1099 TCC = $(TCC) /DFOSSIL_ENABLE_TCL=1
1100 RCC = $(RCC) /DFOSSIL_ENABLE_TCL=1
1101 TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
1102
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -409,10 +409,14 @@
409 # FOSSIL_ENABLE_JSON = 1
410
411 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
412 #
413 # FOSSIL_ENABLE_SSL = 1
414
415 #### Enable hooks for commands and web pages via TH1
416 #
417 # FOSSIL_ENABLE_TH1_HOOKS = 1
418
419 #### Enable scripting support via Tcl/Tk
420 #
421 # FOSSIL_ENABLE_TCL = 1
422
@@ -538,10 +542,16 @@
542 # With HTTPS support
543 ifdef FOSSIL_ENABLE_SSL
544 TCC += -DFOSSIL_ENABLE_SSL=1
545 RCC += -DFOSSIL_ENABLE_SSL=1
546 endif
547
548 # With TH1 hook support
549 ifdef FOSSIL_ENABLE_TH1_HOOKS
550 TCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
551 RCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
552 endif
553
554 # With Tcl support
555 ifdef FOSSIL_ENABLE_TCL
556 TCC += -DFOSSIL_ENABLE_TCL=1
557 RCC += -DFOSSIL_ENABLE_TCL=1
@@ -1034,10 +1044,13 @@
1044 # Uncomment to enable JSON API
1045 # FOSSIL_ENABLE_JSON = 1
1046
1047 # Uncomment to enable SSL support
1048 # FOSSIL_ENABLE_SSL = 1
1049
1050 # Uncomment to enable TH1 hooks
1051 # FOSSIL_ENABLE_TH1_HOOKS = 1
1052
1053 # Uncomment to enable Tcl support
1054 # FOSSIL_ENABLE_TCL = 1
1055
1056 !ifdef FOSSIL_ENABLE_SSL
@@ -1092,10 +1105,15 @@
1105 TCC = $(TCC) /DFOSSIL_ENABLE_SSL=1
1106 RCC = $(RCC) /DFOSSIL_ENABLE_SSL=1
1107 LIBS = $(LIBS) $(SSLLIB)
1108 LIBDIR = $(LIBDIR) /LIBPATH:$(SSLLIBDIR)
1109 !endif
1110
1111 !ifdef FOSSIL_ENABLE_TH1_HOOKS
1112 TCC = $(TCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
1113 RCC = $(RCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
1114 !endif
1115
1116 !ifdef FOSSIL_ENABLE_TCL
1117 TCC = $(TCC) /DFOSSIL_ENABLE_TCL=1
1118 RCC = $(RCC) /DFOSSIL_ENABLE_TCL=1
1119 TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
1120
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -409,10 +409,14 @@
409409
# FOSSIL_ENABLE_JSON = 1
410410
411411
#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
412412
#
413413
# FOSSIL_ENABLE_SSL = 1
414
+
415
+#### Enable hooks for commands and web pages via TH1
416
+#
417
+# FOSSIL_ENABLE_TH1_HOOKS = 1
414418
415419
#### Enable scripting support via Tcl/Tk
416420
#
417421
# FOSSIL_ENABLE_TCL = 1
418422
@@ -538,10 +542,16 @@
538542
# With HTTPS support
539543
ifdef FOSSIL_ENABLE_SSL
540544
TCC += -DFOSSIL_ENABLE_SSL=1
541545
RCC += -DFOSSIL_ENABLE_SSL=1
542546
endif
547
+
548
+# With TH1 hook support
549
+ifdef FOSSIL_ENABLE_TH1_HOOKS
550
+TCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
551
+RCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
552
+endif
543553
544554
# With Tcl support
545555
ifdef FOSSIL_ENABLE_TCL
546556
TCC += -DFOSSIL_ENABLE_TCL=1
547557
RCC += -DFOSSIL_ENABLE_TCL=1
@@ -1034,10 +1044,13 @@
10341044
# Uncomment to enable JSON API
10351045
# FOSSIL_ENABLE_JSON = 1
10361046
10371047
# Uncomment to enable SSL support
10381048
# FOSSIL_ENABLE_SSL = 1
1049
+
1050
+# Uncomment to enable TH1 hooks
1051
+# FOSSIL_ENABLE_TH1_HOOKS = 1
10391052
10401053
# Uncomment to enable Tcl support
10411054
# FOSSIL_ENABLE_TCL = 1
10421055
10431056
!ifdef FOSSIL_ENABLE_SSL
@@ -1092,10 +1105,15 @@
10921105
TCC = $(TCC) /DFOSSIL_ENABLE_SSL=1
10931106
RCC = $(RCC) /DFOSSIL_ENABLE_SSL=1
10941107
LIBS = $(LIBS) $(SSLLIB)
10951108
LIBDIR = $(LIBDIR) /LIBPATH:$(SSLLIBDIR)
10961109
!endif
1110
+
1111
+!ifdef FOSSIL_ENABLE_TH1_HOOKS
1112
+TCC = $(TCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
1113
+RCC = $(RCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
1114
+!endif
10971115
10981116
!ifdef FOSSIL_ENABLE_TCL
10991117
TCC = $(TCC) /DFOSSIL_ENABLE_TCL=1
11001118
RCC = $(RCC) /DFOSSIL_ENABLE_TCL=1
11011119
TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
11021120
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -409,10 +409,14 @@
409 # FOSSIL_ENABLE_JSON = 1
410
411 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
412 #
413 # FOSSIL_ENABLE_SSL = 1
 
 
 
 
414
415 #### Enable scripting support via Tcl/Tk
416 #
417 # FOSSIL_ENABLE_TCL = 1
418
@@ -538,10 +542,16 @@
538 # With HTTPS support
539 ifdef FOSSIL_ENABLE_SSL
540 TCC += -DFOSSIL_ENABLE_SSL=1
541 RCC += -DFOSSIL_ENABLE_SSL=1
542 endif
 
 
 
 
 
 
543
544 # With Tcl support
545 ifdef FOSSIL_ENABLE_TCL
546 TCC += -DFOSSIL_ENABLE_TCL=1
547 RCC += -DFOSSIL_ENABLE_TCL=1
@@ -1034,10 +1044,13 @@
1034 # Uncomment to enable JSON API
1035 # FOSSIL_ENABLE_JSON = 1
1036
1037 # Uncomment to enable SSL support
1038 # FOSSIL_ENABLE_SSL = 1
 
 
 
1039
1040 # Uncomment to enable Tcl support
1041 # FOSSIL_ENABLE_TCL = 1
1042
1043 !ifdef FOSSIL_ENABLE_SSL
@@ -1092,10 +1105,15 @@
1092 TCC = $(TCC) /DFOSSIL_ENABLE_SSL=1
1093 RCC = $(RCC) /DFOSSIL_ENABLE_SSL=1
1094 LIBS = $(LIBS) $(SSLLIB)
1095 LIBDIR = $(LIBDIR) /LIBPATH:$(SSLLIBDIR)
1096 !endif
 
 
 
 
 
1097
1098 !ifdef FOSSIL_ENABLE_TCL
1099 TCC = $(TCC) /DFOSSIL_ENABLE_TCL=1
1100 RCC = $(RCC) /DFOSSIL_ENABLE_TCL=1
1101 TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
1102
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -409,10 +409,14 @@
409 # FOSSIL_ENABLE_JSON = 1
410
411 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
412 #
413 # FOSSIL_ENABLE_SSL = 1
414
415 #### Enable hooks for commands and web pages via TH1
416 #
417 # FOSSIL_ENABLE_TH1_HOOKS = 1
418
419 #### Enable scripting support via Tcl/Tk
420 #
421 # FOSSIL_ENABLE_TCL = 1
422
@@ -538,10 +542,16 @@
542 # With HTTPS support
543 ifdef FOSSIL_ENABLE_SSL
544 TCC += -DFOSSIL_ENABLE_SSL=1
545 RCC += -DFOSSIL_ENABLE_SSL=1
546 endif
547
548 # With TH1 hook support
549 ifdef FOSSIL_ENABLE_TH1_HOOKS
550 TCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
551 RCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
552 endif
553
554 # With Tcl support
555 ifdef FOSSIL_ENABLE_TCL
556 TCC += -DFOSSIL_ENABLE_TCL=1
557 RCC += -DFOSSIL_ENABLE_TCL=1
@@ -1034,10 +1044,13 @@
1044 # Uncomment to enable JSON API
1045 # FOSSIL_ENABLE_JSON = 1
1046
1047 # Uncomment to enable SSL support
1048 # FOSSIL_ENABLE_SSL = 1
1049
1050 # Uncomment to enable TH1 hooks
1051 # FOSSIL_ENABLE_TH1_HOOKS = 1
1052
1053 # Uncomment to enable Tcl support
1054 # FOSSIL_ENABLE_TCL = 1
1055
1056 !ifdef FOSSIL_ENABLE_SSL
@@ -1092,10 +1105,15 @@
1105 TCC = $(TCC) /DFOSSIL_ENABLE_SSL=1
1106 RCC = $(RCC) /DFOSSIL_ENABLE_SSL=1
1107 LIBS = $(LIBS) $(SSLLIB)
1108 LIBDIR = $(LIBDIR) /LIBPATH:$(SSLLIBDIR)
1109 !endif
1110
1111 !ifdef FOSSIL_ENABLE_TH1_HOOKS
1112 TCC = $(TCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
1113 RCC = $(RCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
1114 !endif
1115
1116 !ifdef FOSSIL_ENABLE_TCL
1117 TCC = $(TCC) /DFOSSIL_ENABLE_TCL=1
1118 RCC = $(RCC) /DFOSSIL_ENABLE_TCL=1
1119 TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
1120
+238
--- src/th_main.c
+++ src/th_main.c
@@ -31,10 +31,22 @@
3131
#define TH_INIT_NEED_CONFIG ((u32)0x00000001) /* Open configuration first? */
3232
#define TH_INIT_FORCE_TCL ((u32)0x00000002) /* Force Tcl to be enabled? */
3333
#define TH_INIT_FORCE_RESET ((u32)0x00000004) /* Force TH1 commands re-added? */
3434
#define TH_INIT_FORCE_SETUP ((u32)0x00000008) /* Force eval of setup script? */
3535
#define TH_INIT_DEFAULT (TH_INIT_NONE) /* Default flags. */
36
+#define TH_INIT_HOOK (TH_INIT_NEED_CONFIG | TH_INIT_FORCE_SETUP)
37
+#endif
38
+
39
+#ifdef FOSSIL_ENABLE_TH1_HOOKS
40
+/*
41
+** These are the "well-known" TH1 error messages that occur when no hook is
42
+** registered to be called prior to executing a command or processing a web
43
+** page, respectively. If one of these errors is seen, it will not be sent
44
+** or displayed to the remote user or local interactive user, respectively.
45
+*/
46
+#define NO_COMMAND_HOOK_ERROR "no such command: command_hook"
47
+#define NO_WEBPAGE_HOOK_ERROR "no such command: webpage_hook"
3648
#endif
3749
3850
/*
3951
** Global variable counting the number of outstanding calls to malloc()
4052
** made by the th1 implementation. This is used to catch memory leaks
@@ -327,10 +339,11 @@
327339
**
328340
** Return true if the fossil binary has the given compile-time feature
329341
** enabled. The set of features includes:
330342
**
331343
** "ssl" = FOSSIL_ENABLE_SSL
344
+** "th1Hooks" = FOSSIL_ENABLE_TH1_HOOKS
332345
** "tcl" = FOSSIL_ENABLE_TCL
333346
** "useTclStubs" = USE_TCL_STUBS
334347
** "tclStubs" = FOSSIL_ENABLE_TCL_STUBS
335348
** "tclPrivateStubs" = FOSSIL_ENABLE_TCL_PRIVATE_STUBS
336349
** "json" = FOSSIL_ENABLE_JSON
@@ -355,10 +368,15 @@
355368
}
356369
#if defined(FOSSIL_ENABLE_SSL)
357370
else if( 0 == fossil_strnicmp( zArg, "ssl\0", 4 ) ){
358371
rc = 1;
359372
}
373
+#endif
374
+#if defined(FOSSIL_ENABLE_TH1_HOOKS)
375
+ else if( 0 == fossil_strnicmp( zArg, "th1Hooks\0", 9 ) ){
376
+ rc = 1;
377
+ }
360378
#endif
361379
#if defined(FOSSIL_ENABLE_TCL)
362380
else if( 0 == fossil_strnicmp( zArg, "tcl\0", 4 ) ){
363381
rc = 1;
364382
}
@@ -1147,10 +1165,23 @@
11471165
if( openRepository ){
11481166
db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0);
11491167
}
11501168
db_open_config(0);
11511169
}
1170
+
1171
+/*
1172
+** Attempts to close the configuration ("user") database. Optionally, also
1173
+** attempts to close the repository.
1174
+*/
1175
+void Th_CloseConfig(
1176
+ int closeRepository
1177
+){
1178
+ db_close_config();
1179
+ if( closeRepository ){
1180
+ db_close(1);
1181
+ }
1182
+}
11521183
11531184
/*
11541185
** Make sure the interpreter has been initialized. Initialize it if
11551186
** it has not been already.
11561187
**
@@ -1265,10 +1296,34 @@
12651296
Th_Trace("set %h {%h}<br />\n", zName, zValue);
12661297
}
12671298
Th_SetVar(g.interp, zName, -1, zValue, strlen(zValue));
12681299
}
12691300
}
1301
+
1302
+/*
1303
+** Store a list value in a variable in the interpreter.
1304
+*/
1305
+void Th_StoreList(
1306
+ const char *zName,
1307
+ char **pzList,
1308
+ int nList
1309
+){
1310
+ Th_FossilInit(TH_INIT_DEFAULT);
1311
+ if( pzList ){
1312
+ char *zValue = 0;
1313
+ int nValue = 0;
1314
+ int i;
1315
+ for(i=0; i<nList; i++){
1316
+ Th_ListAppend(g.interp, &zValue, &nValue, pzList[i], -1);
1317
+ }
1318
+ if( g.thTrace ){
1319
+ Th_Trace("set %h {%h}<br />\n", zName, zValue);
1320
+ }
1321
+ Th_SetVar(g.interp, zName, -1, zValue, nValue);
1322
+ Th_Free(g.interp, zValue);
1323
+ }
1324
+}
12701325
12711326
/*
12721327
** Store an integer value in a variable in the interpreter.
12731328
*/
12741329
void Th_StoreInt(const char *zName, int iValue){
@@ -1362,10 +1417,162 @@
13621417
if( z[0]!='>' ) return 0;
13631418
i += 2;
13641419
}
13651420
return i;
13661421
}
1422
+
1423
+#ifdef FOSSIL_ENABLE_TH1_HOOKS
1424
+/*
1425
+** This function is called by Fossil just prior to dispatching a command.
1426
+** Returning a value other than TH_OK from this function (i.e. via an
1427
+** evaluated script raising an error or calling [break]/[continue]) will
1428
+** cause the actual command execution to be skipped.
1429
+*/
1430
+int Th_CommandHook(
1431
+ const char *zName,
1432
+ char cmdFlags
1433
+){
1434
+ int rc = TH_OK;
1435
+ Th_OpenConfig(1);
1436
+ if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
1437
+ return rc;
1438
+ }
1439
+ Th_CloseConfig(1);
1440
+ Th_FossilInit(TH_INIT_HOOK);
1441
+ Th_Store("cmd_name", zName);
1442
+ Th_StoreList("cmd_args", g.argv, g.argc);
1443
+ Th_StoreInt("cmd_flags", cmdFlags);
1444
+ rc = Th_Eval(g.interp, 0, "command_hook", -1);
1445
+ if( rc==TH_ERROR ){
1446
+ int nResult = 0;
1447
+ char *zResult = (char*)Th_GetResult(g.interp, &nResult);
1448
+ /*
1449
+ ** Make sure that the TH1 script error was not caused by a "missing"
1450
+ ** command hook handler as that is not actually an error condition.
1451
+ */
1452
+ if( memcmp(zResult, NO_COMMAND_HOOK_ERROR, nResult)!=0 ){
1453
+ sendError(zResult, nResult, 0);
1454
+ }
1455
+ }
1456
+ /*
1457
+ ** If the script returned TH_ERROR (e.g. the "command_hook" TH1 command does
1458
+ ** not exist because commands are not being hooked), return TH_OK because we
1459
+ ** do not want to skip executing essential commands unless the called command
1460
+ ** (i.e. "command_hook") explicitly forbids this by successfully returning
1461
+ ** TH_BREAK or TH_CONTINUE.
1462
+ */
1463
+ if( g.thTrace ){
1464
+ Th_Trace("[command_hook {%h}] => %h<br />\n", zName,
1465
+ Th_ReturnCodeName(rc, 0));
1466
+ }
1467
+ return (rc != TH_ERROR) ? rc : TH_OK;
1468
+}
1469
+
1470
+/*
1471
+** This function is called by Fossil just after dispatching a command.
1472
+** Returning a value other than TH_OK from this function (i.e. via an
1473
+** evaluated script raising an error or calling [break]/[continue]) may
1474
+** cause an error message to be displayed to the local interactive user.
1475
+** Currently, TH1 error messages generated by this function are ignored.
1476
+*/
1477
+int Th_CommandNotify(
1478
+ const char *zName,
1479
+ char cmdFlags
1480
+){
1481
+ int rc = TH_OK;
1482
+ Th_OpenConfig(1);
1483
+ if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
1484
+ return rc;
1485
+ }
1486
+ Th_CloseConfig(1);
1487
+ Th_FossilInit(TH_INIT_HOOK);
1488
+ Th_Store("cmd_name", zName);
1489
+ Th_StoreList("cmd_args", g.argv, g.argc);
1490
+ Th_StoreInt("cmd_flags", cmdFlags);
1491
+ rc = Th_Eval(g.interp, 0, "command_notify", -1);
1492
+ if( g.thTrace ){
1493
+ Th_Trace("[command_notify {%h}] => %h<br />\n", zName,
1494
+ Th_ReturnCodeName(rc, 0));
1495
+ }
1496
+ return rc;
1497
+}
1498
+
1499
+/*
1500
+** This function is called by Fossil just prior to processing a web page.
1501
+** Returning a value other than TH_OK from this function (i.e. via an
1502
+** evaluated script raising an error or calling [break]/[continue]) will
1503
+** cause the actual web page processing to be skipped.
1504
+*/
1505
+int Th_WebpageHook(
1506
+ const char *zName,
1507
+ char cmdFlags
1508
+){
1509
+ int rc = TH_OK;
1510
+ Th_OpenConfig(1);
1511
+ if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
1512
+ return rc;
1513
+ }
1514
+ Th_CloseConfig(1);
1515
+ Th_FossilInit(TH_INIT_HOOK);
1516
+ Th_Store("web_name", zName);
1517
+ Th_StoreList("web_args", g.argv, g.argc);
1518
+ Th_StoreInt("web_flags", cmdFlags);
1519
+ rc = Th_Eval(g.interp, 0, "webpage_hook", -1);
1520
+ if( rc==TH_ERROR ){
1521
+ int nResult = 0;
1522
+ char *zResult = (char*)Th_GetResult(g.interp, &nResult);
1523
+ /*
1524
+ ** Make sure that the TH1 script error was not caused by a "missing"
1525
+ ** webpage hook handler as that is not actually an error condition.
1526
+ */
1527
+ if( memcmp(zResult, NO_WEBPAGE_HOOK_ERROR, nResult)!=0 ){
1528
+ sendError(zResult, nResult, 1);
1529
+ }
1530
+ }
1531
+ /*
1532
+ ** If the script returned TH_ERROR (e.g. the "webpage_hook" TH1 command does
1533
+ ** not exist because commands are not being hooked), return TH_OK because we
1534
+ ** do not want to skip processing essential web pages unless the called
1535
+ ** command (i.e. "webpage_hook") explicitly forbids this by successfully
1536
+ ** returning TH_BREAK or TH_CONTINUE.
1537
+ */
1538
+ if( g.thTrace ){
1539
+ Th_Trace("[webpage_hook {%h}] => %h<br />\n", zName,
1540
+ Th_ReturnCodeName(rc, 0));
1541
+ }
1542
+ return (rc != TH_ERROR) ? rc : TH_OK;
1543
+}
1544
+
1545
+/*
1546
+** This function is called by Fossil just after processing a web page.
1547
+** Returning a value other than TH_OK from this function (i.e. via an
1548
+** evaluated script raising an error or calling [break]/[continue]) may
1549
+** cause an error message to be displayed to the remote user.
1550
+** Currently, TH1 error messages generated by this function are ignored.
1551
+*/
1552
+int Th_WebpageNotify(
1553
+ const char *zName,
1554
+ char cmdFlags
1555
+){
1556
+ int rc = TH_OK;
1557
+ Th_OpenConfig(1);
1558
+ if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
1559
+ return rc;
1560
+ }
1561
+ Th_CloseConfig(1);
1562
+ Th_FossilInit(TH_INIT_HOOK);
1563
+ Th_Store("web_name", zName);
1564
+ Th_StoreList("web_args", g.argv, g.argc);
1565
+ Th_StoreInt("web_flags", cmdFlags);
1566
+ rc = Th_Eval(g.interp, 0, "webpage_notify", -1);
1567
+ if( g.thTrace ){
1568
+ Th_Trace("[webpage_notify {%h}] => %h<br />\n", zName,
1569
+ Th_ReturnCodeName(rc, 0));
1570
+ }
1571
+ return rc;
1572
+}
1573
+#endif
13671574
13681575
/*
13691576
** The z[] input contains text mixed with TH1 scripts.
13701577
** The TH1 scripts are contained within <th1>...</th1>.
13711578
** TH1 variables are $aaa or $<aaa>. The first form of
@@ -1462,5 +1669,36 @@
14621669
rc = Th_Eval(g.interp, 0, g.argv[2], -1);
14631670
zRc = Th_ReturnCodeName(rc, 1);
14641671
fossil_print("%s%s%s\n", zRc, zRc ? ": " : "", Th_GetResult(g.interp, 0));
14651672
Th_PrintTraceLog();
14661673
}
1674
+
1675
+#ifdef FOSSIL_ENABLE_TH1_HOOKS
1676
+/*
1677
+** COMMAND: test-th-hook
1678
+*/
1679
+void test_th_hook(void){
1680
+ int rc = TH_OK;
1681
+ int nResult = 0;
1682
+ char *zResult;
1683
+ if( g.argc<5 ){
1684
+ usage("TYPE NAME FLAGS");
1685
+ }
1686
+ if( fossil_stricmp(g.argv[2], "cmdhook")==0 ){
1687
+ rc = Th_CommandHook(g.argv[3], (char)atoi(g.argv[4]));
1688
+ }else if( fossil_stricmp(g.argv[2], "cmdnotify")==0 ){
1689
+ rc = Th_CommandNotify(g.argv[3], (char)atoi(g.argv[4]));
1690
+ }else if( fossil_stricmp(g.argv[2], "webhook")==0 ){
1691
+ rc = Th_WebpageHook(g.argv[3], (char)atoi(g.argv[4]));
1692
+ }else if( fossil_stricmp(g.argv[2], "webnotify")==0 ){
1693
+ rc = Th_WebpageNotify(g.argv[3], (char)atoi(g.argv[4]));
1694
+ }else{
1695
+ fossil_fatal("Unknown TH1 hook %s\n", g.argv[2]);
1696
+ }
1697
+ zResult = (char*)Th_GetResult(g.interp, &nResult);
1698
+ sendText("RESULT (", -1, 0);
1699
+ sendText(Th_ReturnCodeName(rc, 0), -1, 0);
1700
+ sendText("): ", -1, 0);
1701
+ sendText(zResult, nResult, 0);
1702
+ sendText("\n", -1, 0);
1703
+}
1704
+#endif
14671705
--- src/th_main.c
+++ src/th_main.c
@@ -31,10 +31,22 @@
31 #define TH_INIT_NEED_CONFIG ((u32)0x00000001) /* Open configuration first? */
32 #define TH_INIT_FORCE_TCL ((u32)0x00000002) /* Force Tcl to be enabled? */
33 #define TH_INIT_FORCE_RESET ((u32)0x00000004) /* Force TH1 commands re-added? */
34 #define TH_INIT_FORCE_SETUP ((u32)0x00000008) /* Force eval of setup script? */
35 #define TH_INIT_DEFAULT (TH_INIT_NONE) /* Default flags. */
 
 
 
 
 
 
 
 
 
 
 
 
36 #endif
37
38 /*
39 ** Global variable counting the number of outstanding calls to malloc()
40 ** made by the th1 implementation. This is used to catch memory leaks
@@ -327,10 +339,11 @@
327 **
328 ** Return true if the fossil binary has the given compile-time feature
329 ** enabled. The set of features includes:
330 **
331 ** "ssl" = FOSSIL_ENABLE_SSL
 
332 ** "tcl" = FOSSIL_ENABLE_TCL
333 ** "useTclStubs" = USE_TCL_STUBS
334 ** "tclStubs" = FOSSIL_ENABLE_TCL_STUBS
335 ** "tclPrivateStubs" = FOSSIL_ENABLE_TCL_PRIVATE_STUBS
336 ** "json" = FOSSIL_ENABLE_JSON
@@ -355,10 +368,15 @@
355 }
356 #if defined(FOSSIL_ENABLE_SSL)
357 else if( 0 == fossil_strnicmp( zArg, "ssl\0", 4 ) ){
358 rc = 1;
359 }
 
 
 
 
 
360 #endif
361 #if defined(FOSSIL_ENABLE_TCL)
362 else if( 0 == fossil_strnicmp( zArg, "tcl\0", 4 ) ){
363 rc = 1;
364 }
@@ -1147,10 +1165,23 @@
1147 if( openRepository ){
1148 db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0);
1149 }
1150 db_open_config(0);
1151 }
 
 
 
 
 
 
 
 
 
 
 
 
 
1152
1153 /*
1154 ** Make sure the interpreter has been initialized. Initialize it if
1155 ** it has not been already.
1156 **
@@ -1265,10 +1296,34 @@
1265 Th_Trace("set %h {%h}<br />\n", zName, zValue);
1266 }
1267 Th_SetVar(g.interp, zName, -1, zValue, strlen(zValue));
1268 }
1269 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1270
1271 /*
1272 ** Store an integer value in a variable in the interpreter.
1273 */
1274 void Th_StoreInt(const char *zName, int iValue){
@@ -1362,10 +1417,162 @@
1362 if( z[0]!='>' ) return 0;
1363 i += 2;
1364 }
1365 return i;
1366 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1367
1368 /*
1369 ** The z[] input contains text mixed with TH1 scripts.
1370 ** The TH1 scripts are contained within <th1>...</th1>.
1371 ** TH1 variables are $aaa or $<aaa>. The first form of
@@ -1462,5 +1669,36 @@
1462 rc = Th_Eval(g.interp, 0, g.argv[2], -1);
1463 zRc = Th_ReturnCodeName(rc, 1);
1464 fossil_print("%s%s%s\n", zRc, zRc ? ": " : "", Th_GetResult(g.interp, 0));
1465 Th_PrintTraceLog();
1466 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1467
--- src/th_main.c
+++ src/th_main.c
@@ -31,10 +31,22 @@
31 #define TH_INIT_NEED_CONFIG ((u32)0x00000001) /* Open configuration first? */
32 #define TH_INIT_FORCE_TCL ((u32)0x00000002) /* Force Tcl to be enabled? */
33 #define TH_INIT_FORCE_RESET ((u32)0x00000004) /* Force TH1 commands re-added? */
34 #define TH_INIT_FORCE_SETUP ((u32)0x00000008) /* Force eval of setup script? */
35 #define TH_INIT_DEFAULT (TH_INIT_NONE) /* Default flags. */
36 #define TH_INIT_HOOK (TH_INIT_NEED_CONFIG | TH_INIT_FORCE_SETUP)
37 #endif
38
39 #ifdef FOSSIL_ENABLE_TH1_HOOKS
40 /*
41 ** These are the "well-known" TH1 error messages that occur when no hook is
42 ** registered to be called prior to executing a command or processing a web
43 ** page, respectively. If one of these errors is seen, it will not be sent
44 ** or displayed to the remote user or local interactive user, respectively.
45 */
46 #define NO_COMMAND_HOOK_ERROR "no such command: command_hook"
47 #define NO_WEBPAGE_HOOK_ERROR "no such command: webpage_hook"
48 #endif
49
50 /*
51 ** Global variable counting the number of outstanding calls to malloc()
52 ** made by the th1 implementation. This is used to catch memory leaks
@@ -327,10 +339,11 @@
339 **
340 ** Return true if the fossil binary has the given compile-time feature
341 ** enabled. The set of features includes:
342 **
343 ** "ssl" = FOSSIL_ENABLE_SSL
344 ** "th1Hooks" = FOSSIL_ENABLE_TH1_HOOKS
345 ** "tcl" = FOSSIL_ENABLE_TCL
346 ** "useTclStubs" = USE_TCL_STUBS
347 ** "tclStubs" = FOSSIL_ENABLE_TCL_STUBS
348 ** "tclPrivateStubs" = FOSSIL_ENABLE_TCL_PRIVATE_STUBS
349 ** "json" = FOSSIL_ENABLE_JSON
@@ -355,10 +368,15 @@
368 }
369 #if defined(FOSSIL_ENABLE_SSL)
370 else if( 0 == fossil_strnicmp( zArg, "ssl\0", 4 ) ){
371 rc = 1;
372 }
373 #endif
374 #if defined(FOSSIL_ENABLE_TH1_HOOKS)
375 else if( 0 == fossil_strnicmp( zArg, "th1Hooks\0", 9 ) ){
376 rc = 1;
377 }
378 #endif
379 #if defined(FOSSIL_ENABLE_TCL)
380 else if( 0 == fossil_strnicmp( zArg, "tcl\0", 4 ) ){
381 rc = 1;
382 }
@@ -1147,10 +1165,23 @@
1165 if( openRepository ){
1166 db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0);
1167 }
1168 db_open_config(0);
1169 }
1170
1171 /*
1172 ** Attempts to close the configuration ("user") database. Optionally, also
1173 ** attempts to close the repository.
1174 */
1175 void Th_CloseConfig(
1176 int closeRepository
1177 ){
1178 db_close_config();
1179 if( closeRepository ){
1180 db_close(1);
1181 }
1182 }
1183
1184 /*
1185 ** Make sure the interpreter has been initialized. Initialize it if
1186 ** it has not been already.
1187 **
@@ -1265,10 +1296,34 @@
1296 Th_Trace("set %h {%h}<br />\n", zName, zValue);
1297 }
1298 Th_SetVar(g.interp, zName, -1, zValue, strlen(zValue));
1299 }
1300 }
1301
1302 /*
1303 ** Store a list value in a variable in the interpreter.
1304 */
1305 void Th_StoreList(
1306 const char *zName,
1307 char **pzList,
1308 int nList
1309 ){
1310 Th_FossilInit(TH_INIT_DEFAULT);
1311 if( pzList ){
1312 char *zValue = 0;
1313 int nValue = 0;
1314 int i;
1315 for(i=0; i<nList; i++){
1316 Th_ListAppend(g.interp, &zValue, &nValue, pzList[i], -1);
1317 }
1318 if( g.thTrace ){
1319 Th_Trace("set %h {%h}<br />\n", zName, zValue);
1320 }
1321 Th_SetVar(g.interp, zName, -1, zValue, nValue);
1322 Th_Free(g.interp, zValue);
1323 }
1324 }
1325
1326 /*
1327 ** Store an integer value in a variable in the interpreter.
1328 */
1329 void Th_StoreInt(const char *zName, int iValue){
@@ -1362,10 +1417,162 @@
1417 if( z[0]!='>' ) return 0;
1418 i += 2;
1419 }
1420 return i;
1421 }
1422
1423 #ifdef FOSSIL_ENABLE_TH1_HOOKS
1424 /*
1425 ** This function is called by Fossil just prior to dispatching a command.
1426 ** Returning a value other than TH_OK from this function (i.e. via an
1427 ** evaluated script raising an error or calling [break]/[continue]) will
1428 ** cause the actual command execution to be skipped.
1429 */
1430 int Th_CommandHook(
1431 const char *zName,
1432 char cmdFlags
1433 ){
1434 int rc = TH_OK;
1435 Th_OpenConfig(1);
1436 if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
1437 return rc;
1438 }
1439 Th_CloseConfig(1);
1440 Th_FossilInit(TH_INIT_HOOK);
1441 Th_Store("cmd_name", zName);
1442 Th_StoreList("cmd_args", g.argv, g.argc);
1443 Th_StoreInt("cmd_flags", cmdFlags);
1444 rc = Th_Eval(g.interp, 0, "command_hook", -1);
1445 if( rc==TH_ERROR ){
1446 int nResult = 0;
1447 char *zResult = (char*)Th_GetResult(g.interp, &nResult);
1448 /*
1449 ** Make sure that the TH1 script error was not caused by a "missing"
1450 ** command hook handler as that is not actually an error condition.
1451 */
1452 if( memcmp(zResult, NO_COMMAND_HOOK_ERROR, nResult)!=0 ){
1453 sendError(zResult, nResult, 0);
1454 }
1455 }
1456 /*
1457 ** If the script returned TH_ERROR (e.g. the "command_hook" TH1 command does
1458 ** not exist because commands are not being hooked), return TH_OK because we
1459 ** do not want to skip executing essential commands unless the called command
1460 ** (i.e. "command_hook") explicitly forbids this by successfully returning
1461 ** TH_BREAK or TH_CONTINUE.
1462 */
1463 if( g.thTrace ){
1464 Th_Trace("[command_hook {%h}] => %h<br />\n", zName,
1465 Th_ReturnCodeName(rc, 0));
1466 }
1467 return (rc != TH_ERROR) ? rc : TH_OK;
1468 }
1469
1470 /*
1471 ** This function is called by Fossil just after dispatching a command.
1472 ** Returning a value other than TH_OK from this function (i.e. via an
1473 ** evaluated script raising an error or calling [break]/[continue]) may
1474 ** cause an error message to be displayed to the local interactive user.
1475 ** Currently, TH1 error messages generated by this function are ignored.
1476 */
1477 int Th_CommandNotify(
1478 const char *zName,
1479 char cmdFlags
1480 ){
1481 int rc = TH_OK;
1482 Th_OpenConfig(1);
1483 if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
1484 return rc;
1485 }
1486 Th_CloseConfig(1);
1487 Th_FossilInit(TH_INIT_HOOK);
1488 Th_Store("cmd_name", zName);
1489 Th_StoreList("cmd_args", g.argv, g.argc);
1490 Th_StoreInt("cmd_flags", cmdFlags);
1491 rc = Th_Eval(g.interp, 0, "command_notify", -1);
1492 if( g.thTrace ){
1493 Th_Trace("[command_notify {%h}] => %h<br />\n", zName,
1494 Th_ReturnCodeName(rc, 0));
1495 }
1496 return rc;
1497 }
1498
1499 /*
1500 ** This function is called by Fossil just prior to processing a web page.
1501 ** Returning a value other than TH_OK from this function (i.e. via an
1502 ** evaluated script raising an error or calling [break]/[continue]) will
1503 ** cause the actual web page processing to be skipped.
1504 */
1505 int Th_WebpageHook(
1506 const char *zName,
1507 char cmdFlags
1508 ){
1509 int rc = TH_OK;
1510 Th_OpenConfig(1);
1511 if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
1512 return rc;
1513 }
1514 Th_CloseConfig(1);
1515 Th_FossilInit(TH_INIT_HOOK);
1516 Th_Store("web_name", zName);
1517 Th_StoreList("web_args", g.argv, g.argc);
1518 Th_StoreInt("web_flags", cmdFlags);
1519 rc = Th_Eval(g.interp, 0, "webpage_hook", -1);
1520 if( rc==TH_ERROR ){
1521 int nResult = 0;
1522 char *zResult = (char*)Th_GetResult(g.interp, &nResult);
1523 /*
1524 ** Make sure that the TH1 script error was not caused by a "missing"
1525 ** webpage hook handler as that is not actually an error condition.
1526 */
1527 if( memcmp(zResult, NO_WEBPAGE_HOOK_ERROR, nResult)!=0 ){
1528 sendError(zResult, nResult, 1);
1529 }
1530 }
1531 /*
1532 ** If the script returned TH_ERROR (e.g. the "webpage_hook" TH1 command does
1533 ** not exist because commands are not being hooked), return TH_OK because we
1534 ** do not want to skip processing essential web pages unless the called
1535 ** command (i.e. "webpage_hook") explicitly forbids this by successfully
1536 ** returning TH_BREAK or TH_CONTINUE.
1537 */
1538 if( g.thTrace ){
1539 Th_Trace("[webpage_hook {%h}] => %h<br />\n", zName,
1540 Th_ReturnCodeName(rc, 0));
1541 }
1542 return (rc != TH_ERROR) ? rc : TH_OK;
1543 }
1544
1545 /*
1546 ** This function is called by Fossil just after processing a web page.
1547 ** Returning a value other than TH_OK from this function (i.e. via an
1548 ** evaluated script raising an error or calling [break]/[continue]) may
1549 ** cause an error message to be displayed to the remote user.
1550 ** Currently, TH1 error messages generated by this function are ignored.
1551 */
1552 int Th_WebpageNotify(
1553 const char *zName,
1554 char cmdFlags
1555 ){
1556 int rc = TH_OK;
1557 Th_OpenConfig(1);
1558 if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
1559 return rc;
1560 }
1561 Th_CloseConfig(1);
1562 Th_FossilInit(TH_INIT_HOOK);
1563 Th_Store("web_name", zName);
1564 Th_StoreList("web_args", g.argv, g.argc);
1565 Th_StoreInt("web_flags", cmdFlags);
1566 rc = Th_Eval(g.interp, 0, "webpage_notify", -1);
1567 if( g.thTrace ){
1568 Th_Trace("[webpage_notify {%h}] => %h<br />\n", zName,
1569 Th_ReturnCodeName(rc, 0));
1570 }
1571 return rc;
1572 }
1573 #endif
1574
1575 /*
1576 ** The z[] input contains text mixed with TH1 scripts.
1577 ** The TH1 scripts are contained within <th1>...</th1>.
1578 ** TH1 variables are $aaa or $<aaa>. The first form of
@@ -1462,5 +1669,36 @@
1669 rc = Th_Eval(g.interp, 0, g.argv[2], -1);
1670 zRc = Th_ReturnCodeName(rc, 1);
1671 fossil_print("%s%s%s\n", zRc, zRc ? ": " : "", Th_GetResult(g.interp, 0));
1672 Th_PrintTraceLog();
1673 }
1674
1675 #ifdef FOSSIL_ENABLE_TH1_HOOKS
1676 /*
1677 ** COMMAND: test-th-hook
1678 */
1679 void test_th_hook(void){
1680 int rc = TH_OK;
1681 int nResult = 0;
1682 char *zResult;
1683 if( g.argc<5 ){
1684 usage("TYPE NAME FLAGS");
1685 }
1686 if( fossil_stricmp(g.argv[2], "cmdhook")==0 ){
1687 rc = Th_CommandHook(g.argv[3], (char)atoi(g.argv[4]));
1688 }else if( fossil_stricmp(g.argv[2], "cmdnotify")==0 ){
1689 rc = Th_CommandNotify(g.argv[3], (char)atoi(g.argv[4]));
1690 }else if( fossil_stricmp(g.argv[2], "webhook")==0 ){
1691 rc = Th_WebpageHook(g.argv[3], (char)atoi(g.argv[4]));
1692 }else if( fossil_stricmp(g.argv[2], "webnotify")==0 ){
1693 rc = Th_WebpageNotify(g.argv[3], (char)atoi(g.argv[4]));
1694 }else{
1695 fossil_fatal("Unknown TH1 hook %s\n", g.argv[2]);
1696 }
1697 zResult = (char*)Th_GetResult(g.interp, &nResult);
1698 sendText("RESULT (", -1, 0);
1699 sendText(Th_ReturnCodeName(rc, 0), -1, 0);
1700 sendText("): ", -1, 0);
1701 sendText(zResult, nResult, 0);
1702 sendText("\n", -1, 0);
1703 }
1704 #endif
1705
+238
--- src/th_main.c
+++ src/th_main.c
@@ -31,10 +31,22 @@
3131
#define TH_INIT_NEED_CONFIG ((u32)0x00000001) /* Open configuration first? */
3232
#define TH_INIT_FORCE_TCL ((u32)0x00000002) /* Force Tcl to be enabled? */
3333
#define TH_INIT_FORCE_RESET ((u32)0x00000004) /* Force TH1 commands re-added? */
3434
#define TH_INIT_FORCE_SETUP ((u32)0x00000008) /* Force eval of setup script? */
3535
#define TH_INIT_DEFAULT (TH_INIT_NONE) /* Default flags. */
36
+#define TH_INIT_HOOK (TH_INIT_NEED_CONFIG | TH_INIT_FORCE_SETUP)
37
+#endif
38
+
39
+#ifdef FOSSIL_ENABLE_TH1_HOOKS
40
+/*
41
+** These are the "well-known" TH1 error messages that occur when no hook is
42
+** registered to be called prior to executing a command or processing a web
43
+** page, respectively. If one of these errors is seen, it will not be sent
44
+** or displayed to the remote user or local interactive user, respectively.
45
+*/
46
+#define NO_COMMAND_HOOK_ERROR "no such command: command_hook"
47
+#define NO_WEBPAGE_HOOK_ERROR "no such command: webpage_hook"
3648
#endif
3749
3850
/*
3951
** Global variable counting the number of outstanding calls to malloc()
4052
** made by the th1 implementation. This is used to catch memory leaks
@@ -327,10 +339,11 @@
327339
**
328340
** Return true if the fossil binary has the given compile-time feature
329341
** enabled. The set of features includes:
330342
**
331343
** "ssl" = FOSSIL_ENABLE_SSL
344
+** "th1Hooks" = FOSSIL_ENABLE_TH1_HOOKS
332345
** "tcl" = FOSSIL_ENABLE_TCL
333346
** "useTclStubs" = USE_TCL_STUBS
334347
** "tclStubs" = FOSSIL_ENABLE_TCL_STUBS
335348
** "tclPrivateStubs" = FOSSIL_ENABLE_TCL_PRIVATE_STUBS
336349
** "json" = FOSSIL_ENABLE_JSON
@@ -355,10 +368,15 @@
355368
}
356369
#if defined(FOSSIL_ENABLE_SSL)
357370
else if( 0 == fossil_strnicmp( zArg, "ssl\0", 4 ) ){
358371
rc = 1;
359372
}
373
+#endif
374
+#if defined(FOSSIL_ENABLE_TH1_HOOKS)
375
+ else if( 0 == fossil_strnicmp( zArg, "th1Hooks\0", 9 ) ){
376
+ rc = 1;
377
+ }
360378
#endif
361379
#if defined(FOSSIL_ENABLE_TCL)
362380
else if( 0 == fossil_strnicmp( zArg, "tcl\0", 4 ) ){
363381
rc = 1;
364382
}
@@ -1147,10 +1165,23 @@
11471165
if( openRepository ){
11481166
db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0);
11491167
}
11501168
db_open_config(0);
11511169
}
1170
+
1171
+/*
1172
+** Attempts to close the configuration ("user") database. Optionally, also
1173
+** attempts to close the repository.
1174
+*/
1175
+void Th_CloseConfig(
1176
+ int closeRepository
1177
+){
1178
+ db_close_config();
1179
+ if( closeRepository ){
1180
+ db_close(1);
1181
+ }
1182
+}
11521183
11531184
/*
11541185
** Make sure the interpreter has been initialized. Initialize it if
11551186
** it has not been already.
11561187
**
@@ -1265,10 +1296,34 @@
12651296
Th_Trace("set %h {%h}<br />\n", zName, zValue);
12661297
}
12671298
Th_SetVar(g.interp, zName, -1, zValue, strlen(zValue));
12681299
}
12691300
}
1301
+
1302
+/*
1303
+** Store a list value in a variable in the interpreter.
1304
+*/
1305
+void Th_StoreList(
1306
+ const char *zName,
1307
+ char **pzList,
1308
+ int nList
1309
+){
1310
+ Th_FossilInit(TH_INIT_DEFAULT);
1311
+ if( pzList ){
1312
+ char *zValue = 0;
1313
+ int nValue = 0;
1314
+ int i;
1315
+ for(i=0; i<nList; i++){
1316
+ Th_ListAppend(g.interp, &zValue, &nValue, pzList[i], -1);
1317
+ }
1318
+ if( g.thTrace ){
1319
+ Th_Trace("set %h {%h}<br />\n", zName, zValue);
1320
+ }
1321
+ Th_SetVar(g.interp, zName, -1, zValue, nValue);
1322
+ Th_Free(g.interp, zValue);
1323
+ }
1324
+}
12701325
12711326
/*
12721327
** Store an integer value in a variable in the interpreter.
12731328
*/
12741329
void Th_StoreInt(const char *zName, int iValue){
@@ -1362,10 +1417,162 @@
13621417
if( z[0]!='>' ) return 0;
13631418
i += 2;
13641419
}
13651420
return i;
13661421
}
1422
+
1423
+#ifdef FOSSIL_ENABLE_TH1_HOOKS
1424
+/*
1425
+** This function is called by Fossil just prior to dispatching a command.
1426
+** Returning a value other than TH_OK from this function (i.e. via an
1427
+** evaluated script raising an error or calling [break]/[continue]) will
1428
+** cause the actual command execution to be skipped.
1429
+*/
1430
+int Th_CommandHook(
1431
+ const char *zName,
1432
+ char cmdFlags
1433
+){
1434
+ int rc = TH_OK;
1435
+ Th_OpenConfig(1);
1436
+ if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
1437
+ return rc;
1438
+ }
1439
+ Th_CloseConfig(1);
1440
+ Th_FossilInit(TH_INIT_HOOK);
1441
+ Th_Store("cmd_name", zName);
1442
+ Th_StoreList("cmd_args", g.argv, g.argc);
1443
+ Th_StoreInt("cmd_flags", cmdFlags);
1444
+ rc = Th_Eval(g.interp, 0, "command_hook", -1);
1445
+ if( rc==TH_ERROR ){
1446
+ int nResult = 0;
1447
+ char *zResult = (char*)Th_GetResult(g.interp, &nResult);
1448
+ /*
1449
+ ** Make sure that the TH1 script error was not caused by a "missing"
1450
+ ** command hook handler as that is not actually an error condition.
1451
+ */
1452
+ if( memcmp(zResult, NO_COMMAND_HOOK_ERROR, nResult)!=0 ){
1453
+ sendError(zResult, nResult, 0);
1454
+ }
1455
+ }
1456
+ /*
1457
+ ** If the script returned TH_ERROR (e.g. the "command_hook" TH1 command does
1458
+ ** not exist because commands are not being hooked), return TH_OK because we
1459
+ ** do not want to skip executing essential commands unless the called command
1460
+ ** (i.e. "command_hook") explicitly forbids this by successfully returning
1461
+ ** TH_BREAK or TH_CONTINUE.
1462
+ */
1463
+ if( g.thTrace ){
1464
+ Th_Trace("[command_hook {%h}] => %h<br />\n", zName,
1465
+ Th_ReturnCodeName(rc, 0));
1466
+ }
1467
+ return (rc != TH_ERROR) ? rc : TH_OK;
1468
+}
1469
+
1470
+/*
1471
+** This function is called by Fossil just after dispatching a command.
1472
+** Returning a value other than TH_OK from this function (i.e. via an
1473
+** evaluated script raising an error or calling [break]/[continue]) may
1474
+** cause an error message to be displayed to the local interactive user.
1475
+** Currently, TH1 error messages generated by this function are ignored.
1476
+*/
1477
+int Th_CommandNotify(
1478
+ const char *zName,
1479
+ char cmdFlags
1480
+){
1481
+ int rc = TH_OK;
1482
+ Th_OpenConfig(1);
1483
+ if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
1484
+ return rc;
1485
+ }
1486
+ Th_CloseConfig(1);
1487
+ Th_FossilInit(TH_INIT_HOOK);
1488
+ Th_Store("cmd_name", zName);
1489
+ Th_StoreList("cmd_args", g.argv, g.argc);
1490
+ Th_StoreInt("cmd_flags", cmdFlags);
1491
+ rc = Th_Eval(g.interp, 0, "command_notify", -1);
1492
+ if( g.thTrace ){
1493
+ Th_Trace("[command_notify {%h}] => %h<br />\n", zName,
1494
+ Th_ReturnCodeName(rc, 0));
1495
+ }
1496
+ return rc;
1497
+}
1498
+
1499
+/*
1500
+** This function is called by Fossil just prior to processing a web page.
1501
+** Returning a value other than TH_OK from this function (i.e. via an
1502
+** evaluated script raising an error or calling [break]/[continue]) will
1503
+** cause the actual web page processing to be skipped.
1504
+*/
1505
+int Th_WebpageHook(
1506
+ const char *zName,
1507
+ char cmdFlags
1508
+){
1509
+ int rc = TH_OK;
1510
+ Th_OpenConfig(1);
1511
+ if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
1512
+ return rc;
1513
+ }
1514
+ Th_CloseConfig(1);
1515
+ Th_FossilInit(TH_INIT_HOOK);
1516
+ Th_Store("web_name", zName);
1517
+ Th_StoreList("web_args", g.argv, g.argc);
1518
+ Th_StoreInt("web_flags", cmdFlags);
1519
+ rc = Th_Eval(g.interp, 0, "webpage_hook", -1);
1520
+ if( rc==TH_ERROR ){
1521
+ int nResult = 0;
1522
+ char *zResult = (char*)Th_GetResult(g.interp, &nResult);
1523
+ /*
1524
+ ** Make sure that the TH1 script error was not caused by a "missing"
1525
+ ** webpage hook handler as that is not actually an error condition.
1526
+ */
1527
+ if( memcmp(zResult, NO_WEBPAGE_HOOK_ERROR, nResult)!=0 ){
1528
+ sendError(zResult, nResult, 1);
1529
+ }
1530
+ }
1531
+ /*
1532
+ ** If the script returned TH_ERROR (e.g. the "webpage_hook" TH1 command does
1533
+ ** not exist because commands are not being hooked), return TH_OK because we
1534
+ ** do not want to skip processing essential web pages unless the called
1535
+ ** command (i.e. "webpage_hook") explicitly forbids this by successfully
1536
+ ** returning TH_BREAK or TH_CONTINUE.
1537
+ */
1538
+ if( g.thTrace ){
1539
+ Th_Trace("[webpage_hook {%h}] => %h<br />\n", zName,
1540
+ Th_ReturnCodeName(rc, 0));
1541
+ }
1542
+ return (rc != TH_ERROR) ? rc : TH_OK;
1543
+}
1544
+
1545
+/*
1546
+** This function is called by Fossil just after processing a web page.
1547
+** Returning a value other than TH_OK from this function (i.e. via an
1548
+** evaluated script raising an error or calling [break]/[continue]) may
1549
+** cause an error message to be displayed to the remote user.
1550
+** Currently, TH1 error messages generated by this function are ignored.
1551
+*/
1552
+int Th_WebpageNotify(
1553
+ const char *zName,
1554
+ char cmdFlags
1555
+){
1556
+ int rc = TH_OK;
1557
+ Th_OpenConfig(1);
1558
+ if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
1559
+ return rc;
1560
+ }
1561
+ Th_CloseConfig(1);
1562
+ Th_FossilInit(TH_INIT_HOOK);
1563
+ Th_Store("web_name", zName);
1564
+ Th_StoreList("web_args", g.argv, g.argc);
1565
+ Th_StoreInt("web_flags", cmdFlags);
1566
+ rc = Th_Eval(g.interp, 0, "webpage_notify", -1);
1567
+ if( g.thTrace ){
1568
+ Th_Trace("[webpage_notify {%h}] => %h<br />\n", zName,
1569
+ Th_ReturnCodeName(rc, 0));
1570
+ }
1571
+ return rc;
1572
+}
1573
+#endif
13671574
13681575
/*
13691576
** The z[] input contains text mixed with TH1 scripts.
13701577
** The TH1 scripts are contained within <th1>...</th1>.
13711578
** TH1 variables are $aaa or $<aaa>. The first form of
@@ -1462,5 +1669,36 @@
14621669
rc = Th_Eval(g.interp, 0, g.argv[2], -1);
14631670
zRc = Th_ReturnCodeName(rc, 1);
14641671
fossil_print("%s%s%s\n", zRc, zRc ? ": " : "", Th_GetResult(g.interp, 0));
14651672
Th_PrintTraceLog();
14661673
}
1674
+
1675
+#ifdef FOSSIL_ENABLE_TH1_HOOKS
1676
+/*
1677
+** COMMAND: test-th-hook
1678
+*/
1679
+void test_th_hook(void){
1680
+ int rc = TH_OK;
1681
+ int nResult = 0;
1682
+ char *zResult;
1683
+ if( g.argc<5 ){
1684
+ usage("TYPE NAME FLAGS");
1685
+ }
1686
+ if( fossil_stricmp(g.argv[2], "cmdhook")==0 ){
1687
+ rc = Th_CommandHook(g.argv[3], (char)atoi(g.argv[4]));
1688
+ }else if( fossil_stricmp(g.argv[2], "cmdnotify")==0 ){
1689
+ rc = Th_CommandNotify(g.argv[3], (char)atoi(g.argv[4]));
1690
+ }else if( fossil_stricmp(g.argv[2], "webhook")==0 ){
1691
+ rc = Th_WebpageHook(g.argv[3], (char)atoi(g.argv[4]));
1692
+ }else if( fossil_stricmp(g.argv[2], "webnotify")==0 ){
1693
+ rc = Th_WebpageNotify(g.argv[3], (char)atoi(g.argv[4]));
1694
+ }else{
1695
+ fossil_fatal("Unknown TH1 hook %s\n", g.argv[2]);
1696
+ }
1697
+ zResult = (char*)Th_GetResult(g.interp, &nResult);
1698
+ sendText("RESULT (", -1, 0);
1699
+ sendText(Th_ReturnCodeName(rc, 0), -1, 0);
1700
+ sendText("): ", -1, 0);
1701
+ sendText(zResult, nResult, 0);
1702
+ sendText("\n", -1, 0);
1703
+}
1704
+#endif
14671705
--- src/th_main.c
+++ src/th_main.c
@@ -31,10 +31,22 @@
31 #define TH_INIT_NEED_CONFIG ((u32)0x00000001) /* Open configuration first? */
32 #define TH_INIT_FORCE_TCL ((u32)0x00000002) /* Force Tcl to be enabled? */
33 #define TH_INIT_FORCE_RESET ((u32)0x00000004) /* Force TH1 commands re-added? */
34 #define TH_INIT_FORCE_SETUP ((u32)0x00000008) /* Force eval of setup script? */
35 #define TH_INIT_DEFAULT (TH_INIT_NONE) /* Default flags. */
 
 
 
 
 
 
 
 
 
 
 
 
36 #endif
37
38 /*
39 ** Global variable counting the number of outstanding calls to malloc()
40 ** made by the th1 implementation. This is used to catch memory leaks
@@ -327,10 +339,11 @@
327 **
328 ** Return true if the fossil binary has the given compile-time feature
329 ** enabled. The set of features includes:
330 **
331 ** "ssl" = FOSSIL_ENABLE_SSL
 
332 ** "tcl" = FOSSIL_ENABLE_TCL
333 ** "useTclStubs" = USE_TCL_STUBS
334 ** "tclStubs" = FOSSIL_ENABLE_TCL_STUBS
335 ** "tclPrivateStubs" = FOSSIL_ENABLE_TCL_PRIVATE_STUBS
336 ** "json" = FOSSIL_ENABLE_JSON
@@ -355,10 +368,15 @@
355 }
356 #if defined(FOSSIL_ENABLE_SSL)
357 else if( 0 == fossil_strnicmp( zArg, "ssl\0", 4 ) ){
358 rc = 1;
359 }
 
 
 
 
 
360 #endif
361 #if defined(FOSSIL_ENABLE_TCL)
362 else if( 0 == fossil_strnicmp( zArg, "tcl\0", 4 ) ){
363 rc = 1;
364 }
@@ -1147,10 +1165,23 @@
1147 if( openRepository ){
1148 db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0);
1149 }
1150 db_open_config(0);
1151 }
 
 
 
 
 
 
 
 
 
 
 
 
 
1152
1153 /*
1154 ** Make sure the interpreter has been initialized. Initialize it if
1155 ** it has not been already.
1156 **
@@ -1265,10 +1296,34 @@
1265 Th_Trace("set %h {%h}<br />\n", zName, zValue);
1266 }
1267 Th_SetVar(g.interp, zName, -1, zValue, strlen(zValue));
1268 }
1269 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1270
1271 /*
1272 ** Store an integer value in a variable in the interpreter.
1273 */
1274 void Th_StoreInt(const char *zName, int iValue){
@@ -1362,10 +1417,162 @@
1362 if( z[0]!='>' ) return 0;
1363 i += 2;
1364 }
1365 return i;
1366 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1367
1368 /*
1369 ** The z[] input contains text mixed with TH1 scripts.
1370 ** The TH1 scripts are contained within <th1>...</th1>.
1371 ** TH1 variables are $aaa or $<aaa>. The first form of
@@ -1462,5 +1669,36 @@
1462 rc = Th_Eval(g.interp, 0, g.argv[2], -1);
1463 zRc = Th_ReturnCodeName(rc, 1);
1464 fossil_print("%s%s%s\n", zRc, zRc ? ": " : "", Th_GetResult(g.interp, 0));
1465 Th_PrintTraceLog();
1466 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1467
--- src/th_main.c
+++ src/th_main.c
@@ -31,10 +31,22 @@
31 #define TH_INIT_NEED_CONFIG ((u32)0x00000001) /* Open configuration first? */
32 #define TH_INIT_FORCE_TCL ((u32)0x00000002) /* Force Tcl to be enabled? */
33 #define TH_INIT_FORCE_RESET ((u32)0x00000004) /* Force TH1 commands re-added? */
34 #define TH_INIT_FORCE_SETUP ((u32)0x00000008) /* Force eval of setup script? */
35 #define TH_INIT_DEFAULT (TH_INIT_NONE) /* Default flags. */
36 #define TH_INIT_HOOK (TH_INIT_NEED_CONFIG | TH_INIT_FORCE_SETUP)
37 #endif
38
39 #ifdef FOSSIL_ENABLE_TH1_HOOKS
40 /*
41 ** These are the "well-known" TH1 error messages that occur when no hook is
42 ** registered to be called prior to executing a command or processing a web
43 ** page, respectively. If one of these errors is seen, it will not be sent
44 ** or displayed to the remote user or local interactive user, respectively.
45 */
46 #define NO_COMMAND_HOOK_ERROR "no such command: command_hook"
47 #define NO_WEBPAGE_HOOK_ERROR "no such command: webpage_hook"
48 #endif
49
50 /*
51 ** Global variable counting the number of outstanding calls to malloc()
52 ** made by the th1 implementation. This is used to catch memory leaks
@@ -327,10 +339,11 @@
339 **
340 ** Return true if the fossil binary has the given compile-time feature
341 ** enabled. The set of features includes:
342 **
343 ** "ssl" = FOSSIL_ENABLE_SSL
344 ** "th1Hooks" = FOSSIL_ENABLE_TH1_HOOKS
345 ** "tcl" = FOSSIL_ENABLE_TCL
346 ** "useTclStubs" = USE_TCL_STUBS
347 ** "tclStubs" = FOSSIL_ENABLE_TCL_STUBS
348 ** "tclPrivateStubs" = FOSSIL_ENABLE_TCL_PRIVATE_STUBS
349 ** "json" = FOSSIL_ENABLE_JSON
@@ -355,10 +368,15 @@
368 }
369 #if defined(FOSSIL_ENABLE_SSL)
370 else if( 0 == fossil_strnicmp( zArg, "ssl\0", 4 ) ){
371 rc = 1;
372 }
373 #endif
374 #if defined(FOSSIL_ENABLE_TH1_HOOKS)
375 else if( 0 == fossil_strnicmp( zArg, "th1Hooks\0", 9 ) ){
376 rc = 1;
377 }
378 #endif
379 #if defined(FOSSIL_ENABLE_TCL)
380 else if( 0 == fossil_strnicmp( zArg, "tcl\0", 4 ) ){
381 rc = 1;
382 }
@@ -1147,10 +1165,23 @@
1165 if( openRepository ){
1166 db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0);
1167 }
1168 db_open_config(0);
1169 }
1170
1171 /*
1172 ** Attempts to close the configuration ("user") database. Optionally, also
1173 ** attempts to close the repository.
1174 */
1175 void Th_CloseConfig(
1176 int closeRepository
1177 ){
1178 db_close_config();
1179 if( closeRepository ){
1180 db_close(1);
1181 }
1182 }
1183
1184 /*
1185 ** Make sure the interpreter has been initialized. Initialize it if
1186 ** it has not been already.
1187 **
@@ -1265,10 +1296,34 @@
1296 Th_Trace("set %h {%h}<br />\n", zName, zValue);
1297 }
1298 Th_SetVar(g.interp, zName, -1, zValue, strlen(zValue));
1299 }
1300 }
1301
1302 /*
1303 ** Store a list value in a variable in the interpreter.
1304 */
1305 void Th_StoreList(
1306 const char *zName,
1307 char **pzList,
1308 int nList
1309 ){
1310 Th_FossilInit(TH_INIT_DEFAULT);
1311 if( pzList ){
1312 char *zValue = 0;
1313 int nValue = 0;
1314 int i;
1315 for(i=0; i<nList; i++){
1316 Th_ListAppend(g.interp, &zValue, &nValue, pzList[i], -1);
1317 }
1318 if( g.thTrace ){
1319 Th_Trace("set %h {%h}<br />\n", zName, zValue);
1320 }
1321 Th_SetVar(g.interp, zName, -1, zValue, nValue);
1322 Th_Free(g.interp, zValue);
1323 }
1324 }
1325
1326 /*
1327 ** Store an integer value in a variable in the interpreter.
1328 */
1329 void Th_StoreInt(const char *zName, int iValue){
@@ -1362,10 +1417,162 @@
1417 if( z[0]!='>' ) return 0;
1418 i += 2;
1419 }
1420 return i;
1421 }
1422
1423 #ifdef FOSSIL_ENABLE_TH1_HOOKS
1424 /*
1425 ** This function is called by Fossil just prior to dispatching a command.
1426 ** Returning a value other than TH_OK from this function (i.e. via an
1427 ** evaluated script raising an error or calling [break]/[continue]) will
1428 ** cause the actual command execution to be skipped.
1429 */
1430 int Th_CommandHook(
1431 const char *zName,
1432 char cmdFlags
1433 ){
1434 int rc = TH_OK;
1435 Th_OpenConfig(1);
1436 if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
1437 return rc;
1438 }
1439 Th_CloseConfig(1);
1440 Th_FossilInit(TH_INIT_HOOK);
1441 Th_Store("cmd_name", zName);
1442 Th_StoreList("cmd_args", g.argv, g.argc);
1443 Th_StoreInt("cmd_flags", cmdFlags);
1444 rc = Th_Eval(g.interp, 0, "command_hook", -1);
1445 if( rc==TH_ERROR ){
1446 int nResult = 0;
1447 char *zResult = (char*)Th_GetResult(g.interp, &nResult);
1448 /*
1449 ** Make sure that the TH1 script error was not caused by a "missing"
1450 ** command hook handler as that is not actually an error condition.
1451 */
1452 if( memcmp(zResult, NO_COMMAND_HOOK_ERROR, nResult)!=0 ){
1453 sendError(zResult, nResult, 0);
1454 }
1455 }
1456 /*
1457 ** If the script returned TH_ERROR (e.g. the "command_hook" TH1 command does
1458 ** not exist because commands are not being hooked), return TH_OK because we
1459 ** do not want to skip executing essential commands unless the called command
1460 ** (i.e. "command_hook") explicitly forbids this by successfully returning
1461 ** TH_BREAK or TH_CONTINUE.
1462 */
1463 if( g.thTrace ){
1464 Th_Trace("[command_hook {%h}] => %h<br />\n", zName,
1465 Th_ReturnCodeName(rc, 0));
1466 }
1467 return (rc != TH_ERROR) ? rc : TH_OK;
1468 }
1469
1470 /*
1471 ** This function is called by Fossil just after dispatching a command.
1472 ** Returning a value other than TH_OK from this function (i.e. via an
1473 ** evaluated script raising an error or calling [break]/[continue]) may
1474 ** cause an error message to be displayed to the local interactive user.
1475 ** Currently, TH1 error messages generated by this function are ignored.
1476 */
1477 int Th_CommandNotify(
1478 const char *zName,
1479 char cmdFlags
1480 ){
1481 int rc = TH_OK;
1482 Th_OpenConfig(1);
1483 if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
1484 return rc;
1485 }
1486 Th_CloseConfig(1);
1487 Th_FossilInit(TH_INIT_HOOK);
1488 Th_Store("cmd_name", zName);
1489 Th_StoreList("cmd_args", g.argv, g.argc);
1490 Th_StoreInt("cmd_flags", cmdFlags);
1491 rc = Th_Eval(g.interp, 0, "command_notify", -1);
1492 if( g.thTrace ){
1493 Th_Trace("[command_notify {%h}] => %h<br />\n", zName,
1494 Th_ReturnCodeName(rc, 0));
1495 }
1496 return rc;
1497 }
1498
1499 /*
1500 ** This function is called by Fossil just prior to processing a web page.
1501 ** Returning a value other than TH_OK from this function (i.e. via an
1502 ** evaluated script raising an error or calling [break]/[continue]) will
1503 ** cause the actual web page processing to be skipped.
1504 */
1505 int Th_WebpageHook(
1506 const char *zName,
1507 char cmdFlags
1508 ){
1509 int rc = TH_OK;
1510 Th_OpenConfig(1);
1511 if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
1512 return rc;
1513 }
1514 Th_CloseConfig(1);
1515 Th_FossilInit(TH_INIT_HOOK);
1516 Th_Store("web_name", zName);
1517 Th_StoreList("web_args", g.argv, g.argc);
1518 Th_StoreInt("web_flags", cmdFlags);
1519 rc = Th_Eval(g.interp, 0, "webpage_hook", -1);
1520 if( rc==TH_ERROR ){
1521 int nResult = 0;
1522 char *zResult = (char*)Th_GetResult(g.interp, &nResult);
1523 /*
1524 ** Make sure that the TH1 script error was not caused by a "missing"
1525 ** webpage hook handler as that is not actually an error condition.
1526 */
1527 if( memcmp(zResult, NO_WEBPAGE_HOOK_ERROR, nResult)!=0 ){
1528 sendError(zResult, nResult, 1);
1529 }
1530 }
1531 /*
1532 ** If the script returned TH_ERROR (e.g. the "webpage_hook" TH1 command does
1533 ** not exist because commands are not being hooked), return TH_OK because we
1534 ** do not want to skip processing essential web pages unless the called
1535 ** command (i.e. "webpage_hook") explicitly forbids this by successfully
1536 ** returning TH_BREAK or TH_CONTINUE.
1537 */
1538 if( g.thTrace ){
1539 Th_Trace("[webpage_hook {%h}] => %h<br />\n", zName,
1540 Th_ReturnCodeName(rc, 0));
1541 }
1542 return (rc != TH_ERROR) ? rc : TH_OK;
1543 }
1544
1545 /*
1546 ** This function is called by Fossil just after processing a web page.
1547 ** Returning a value other than TH_OK from this function (i.e. via an
1548 ** evaluated script raising an error or calling [break]/[continue]) may
1549 ** cause an error message to be displayed to the remote user.
1550 ** Currently, TH1 error messages generated by this function are ignored.
1551 */
1552 int Th_WebpageNotify(
1553 const char *zName,
1554 char cmdFlags
1555 ){
1556 int rc = TH_OK;
1557 Th_OpenConfig(1);
1558 if( fossil_getenv("TH1_ENABLE_HOOKS")==0 && !db_get_boolean("th1-hooks", 0) ){
1559 return rc;
1560 }
1561 Th_CloseConfig(1);
1562 Th_FossilInit(TH_INIT_HOOK);
1563 Th_Store("web_name", zName);
1564 Th_StoreList("web_args", g.argv, g.argc);
1565 Th_StoreInt("web_flags", cmdFlags);
1566 rc = Th_Eval(g.interp, 0, "webpage_notify", -1);
1567 if( g.thTrace ){
1568 Th_Trace("[webpage_notify {%h}] => %h<br />\n", zName,
1569 Th_ReturnCodeName(rc, 0));
1570 }
1571 return rc;
1572 }
1573 #endif
1574
1575 /*
1576 ** The z[] input contains text mixed with TH1 scripts.
1577 ** The TH1 scripts are contained within <th1>...</th1>.
1578 ** TH1 variables are $aaa or $<aaa>. The first form of
@@ -1462,5 +1669,36 @@
1669 rc = Th_Eval(g.interp, 0, g.argv[2], -1);
1670 zRc = Th_ReturnCodeName(rc, 1);
1671 fossil_print("%s%s%s\n", zRc, zRc ? ": " : "", Th_GetResult(g.interp, 0));
1672 Th_PrintTraceLog();
1673 }
1674
1675 #ifdef FOSSIL_ENABLE_TH1_HOOKS
1676 /*
1677 ** COMMAND: test-th-hook
1678 */
1679 void test_th_hook(void){
1680 int rc = TH_OK;
1681 int nResult = 0;
1682 char *zResult;
1683 if( g.argc<5 ){
1684 usage("TYPE NAME FLAGS");
1685 }
1686 if( fossil_stricmp(g.argv[2], "cmdhook")==0 ){
1687 rc = Th_CommandHook(g.argv[3], (char)atoi(g.argv[4]));
1688 }else if( fossil_stricmp(g.argv[2], "cmdnotify")==0 ){
1689 rc = Th_CommandNotify(g.argv[3], (char)atoi(g.argv[4]));
1690 }else if( fossil_stricmp(g.argv[2], "webhook")==0 ){
1691 rc = Th_WebpageHook(g.argv[3], (char)atoi(g.argv[4]));
1692 }else if( fossil_stricmp(g.argv[2], "webnotify")==0 ){
1693 rc = Th_WebpageNotify(g.argv[3], (char)atoi(g.argv[4]));
1694 }else{
1695 fossil_fatal("Unknown TH1 hook %s\n", g.argv[2]);
1696 }
1697 zResult = (char*)Th_GetResult(g.interp, &nResult);
1698 sendText("RESULT (", -1, 0);
1699 sendText(Th_ReturnCodeName(rc, 0), -1, 0);
1700 sendText("): ", -1, 0);
1701 sendText(zResult, nResult, 0);
1702 sendText("\n", -1, 0);
1703 }
1704 #endif
1705
--- test/tester.tcl
+++ test/tester.tcl
@@ -181,10 +181,66 @@
181181
# Append all arguments into a single value and then returns it.
182182
#
183183
proc appendArgs {args} {
184184
eval append result $args
185185
}
186
+
187
+# Return the name of the versioned settings file containing the TH1
188
+# setup script.
189
+#
190
+proc getTh1SetupFileName {} {
191
+ #
192
+ # NOTE: This uses the "testdir" global variable provided by the
193
+ # test suite; alternatively, the root of the source tree
194
+ # could be obtained directly from Fossil.
195
+ #
196
+ return [file normalize [file join [file dirname $::testdir] \
197
+ .fossil-settings th1-setup]]
198
+}
199
+
200
+# Return the saved name of the versioned settings file containing
201
+# the TH1 setup script.
202
+#
203
+proc getSavedTh1SetupFileName {} {
204
+ return [appendArgs [getTh1SetupFileName] . [pid]]
205
+}
206
+
207
+# Sets the TH1 setup script to the one provided. Prior to calling
208
+# this, the [saveTh1SetupFile] procedure should be called in order to
209
+# preserve the existing TH1 setup script. Prior to completing the test,
210
+# the [restoreTh1SetupFile] procedure should be called to restore the
211
+# original TH1 setup script.
212
+#
213
+proc writeTh1SetupFile { data } {
214
+ return [write_file [getTh1SetupFileName] $data]
215
+}
216
+
217
+# Saves the TH1 setup script file by renaming it, based on the current
218
+# process ID.
219
+#
220
+proc saveTh1SetupFile {} {
221
+ set oldFileName [getTh1SetupFileName]
222
+ if {[file exists $oldFileName]} then {
223
+ set newFileName [getSavedTh1SetupFileName]
224
+ catch {file delete $newFileName}
225
+ file rename $oldFileName $newFileName
226
+ file delete $oldFileName
227
+ }
228
+}
229
+
230
+# Restores the original TH1 setup script file by renaming it back, based
231
+# on the current process ID.
232
+#
233
+proc restoreTh1SetupFile {} {
234
+ set oldFileName [getSavedTh1SetupFileName]
235
+ if {[file exists $oldFileName]} then {
236
+ set newFileName [getTh1SetupFileName]
237
+ catch {file delete $newFileName}
238
+ file rename $oldFileName $newFileName
239
+ file delete $oldFileName
240
+ }
241
+}
186242
187243
# Perform a test
188244
#
189245
set test_count 0
190246
proc test {name expr} {
191247
192248
ADDED test/th1-hooks-input.txt
193249
ADDED test/th1-hooks.test
--- test/tester.tcl
+++ test/tester.tcl
@@ -181,10 +181,66 @@
181 # Append all arguments into a single value and then returns it.
182 #
183 proc appendArgs {args} {
184 eval append result $args
185 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
187 # Perform a test
188 #
189 set test_count 0
190 proc test {name expr} {
191
192 DDED test/th1-hooks-input.txt
193 DDED test/th1-hooks.test
--- test/tester.tcl
+++ test/tester.tcl
@@ -181,10 +181,66 @@
181 # Append all arguments into a single value and then returns it.
182 #
183 proc appendArgs {args} {
184 eval append result $args
185 }
186
187 # Return the name of the versioned settings file containing the TH1
188 # setup script.
189 #
190 proc getTh1SetupFileName {} {
191 #
192 # NOTE: This uses the "testdir" global variable provided by the
193 # test suite; alternatively, the root of the source tree
194 # could be obtained directly from Fossil.
195 #
196 return [file normalize [file join [file dirname $::testdir] \
197 .fossil-settings th1-setup]]
198 }
199
200 # Return the saved name of the versioned settings file containing
201 # the TH1 setup script.
202 #
203 proc getSavedTh1SetupFileName {} {
204 return [appendArgs [getTh1SetupFileName] . [pid]]
205 }
206
207 # Sets the TH1 setup script to the one provided. Prior to calling
208 # this, the [saveTh1SetupFile] procedure should be called in order to
209 # preserve the existing TH1 setup script. Prior to completing the test,
210 # the [restoreTh1SetupFile] procedure should be called to restore the
211 # original TH1 setup script.
212 #
213 proc writeTh1SetupFile { data } {
214 return [write_file [getTh1SetupFileName] $data]
215 }
216
217 # Saves the TH1 setup script file by renaming it, based on the current
218 # process ID.
219 #
220 proc saveTh1SetupFile {} {
221 set oldFileName [getTh1SetupFileName]
222 if {[file exists $oldFileName]} then {
223 set newFileName [getSavedTh1SetupFileName]
224 catch {file delete $newFileName}
225 file rename $oldFileName $newFileName
226 file delete $oldFileName
227 }
228 }
229
230 # Restores the original TH1 setup script file by renaming it back, based
231 # on the current process ID.
232 #
233 proc restoreTh1SetupFile {} {
234 set oldFileName [getSavedTh1SetupFileName]
235 if {[file exists $oldFileName]} then {
236 set newFileName [getTh1SetupFileName]
237 catch {file delete $newFileName}
238 file rename $oldFileName $newFileName
239 file delete $oldFileName
240 }
241 }
242
243 # Perform a test
244 #
245 set test_count 0
246 proc test {name expr} {
247
248 DDED test/th1-hooks-input.txt
249 DDED test/th1-hooks.test
--- a/test/th1-hooks-input.txt
+++ b/test/th1-hooks-input.txt
@@ -0,0 +1,4 @@
1
+GET ${url} HTTP/1.1
2
+Host: localhost
3
+User-Agent: Fossil
4
+
--- a/test/th1-hooks-input.txt
+++ b/test/th1-hooks-input.txt
@@ -0,0 +1,4 @@
 
 
 
 
--- a/test/th1-hooks-input.txt
+++ b/test/th1-hooks-input.txt
@@ -0,0 +1,4 @@
1 GET ${url} HTTP/1.1
2 Host: localhost
3 User-Agent: Fossil
4
--- a/test/th1-hooks.test
+++ b/test/th1-hooks.test
@@ -0,0 +1,88 @@
1
+#
2
+# Co#
3
+# Copyright (c) 2011 D. Richard Hipp
4
+#
5
+# This program is free software; you can redistribute i1 D. Richard Hipp
6
+#
7
+# This program is free software; you can redistribute it and/or
8
+# modify it under the terms of the Simplified BSD License (also
9
+# known as the "2-Clause License" or "FreeBSD License".)
10
+#
11
+# This program is distributed in the hope that it will be useful,
12
+# but without any warranty; without even the implied warranty of
13
+# merchantability or fitness for a particular purpose.
14
+#
15
+# Author contact information:
16
+# [email protected]
17
+# http://www.hwaci.com/drh/
18
+#
19
+#################################$::RESULT
20
+# TH1 Hooks
21
+#
22
+
23
+fossil test-th-eval then "hasfeature th1Hooks"
24
+
25
+if {[normalize_result] ne "1"} {
26
+ ; compiled with TH1 hooks support."
27
+ test_cleanup_then_return
28
+}
29
+
30
+#########################
31
+
32
+set env(TH1_ustom"} {
33
+ append {$::cmd_name eq "test4"} {
34
+ then{<title>Fossilproc fossil_th1_hook_http { repository url } {
35
+ set suffix [appendArgs [pid] - [getSeqNo] - [clmpPath [appendArgs test-hmpPath [appendArgs test-http-ou set data [subst [read_fil]]
36
+
37
+ write_file $inFileName $data
38
+ fossil http $inFileName $outFileName 127.0.0.1 $repository
39
+ set result [expr {[file exists $outFileName] ? [read_file $outFileName] : ""}]
40
+
41
+ if {1} then {
42
+ catch {file delete $inFileName}
43
+ catch {frepository }
44
+
45
+ return $result
46
+}
47
+
48
+proc normat
49
+}
50
+
51
+proc normalize_result {} {
52
+ return [string map [list \r\n \n] [string trim $::RESULT]]
53
+}
54
+
55
+proc first_data_line {}\n] 0]
56
+}
57
+
58
+proc second_data_line {}\n] 1]
59
+}
60
+
61
+proc third_data_line {}\n] 2]
62
+}
63
+
64
+proc lD. Richard Hipp
65
+#\nlit \n] end-1]
66
+}
67
+
68
+proc \rlit \n] end-1]
69
+}
70
+
71
+proc \rlit \n] end-1]
72
+}
73
+
74
+proc \rlit \n] end-1]
75
+}
76
+
77
+proc \rlit \n] end-1]
78
+}
79
+
80
+proc \r\n] end-1]
81
+if {$::cmd_argsc {} {
82
+ return [lindex [split \n] end-1]
83
+}
84
+
85
+proc #
86
+# Co#
87
+# Copyright (c)ght (c) 2lit \n] end-1RESULT]] eq
88
+timeline}}2b {[secondtimeline}}2cthird_data_line]]}2dest3est4web-hooks-1b {[regexp
--- a/test/th1-hooks.test
+++ b/test/th1-hooks.test
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/test/th1-hooks.test
+++ b/test/th1-hooks.test
@@ -0,0 +1,88 @@
1 #
2 # Co#
3 # Copyright (c) 2011 D. Richard Hipp
4 #
5 # This program is free software; you can redistribute i1 D. Richard Hipp
6 #
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the Simplified BSD License (also
9 # known as the "2-Clause License" or "FreeBSD License".)
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but without any warranty; without even the implied warranty of
13 # merchantability or fitness for a particular purpose.
14 #
15 # Author contact information:
16 # [email protected]
17 # http://www.hwaci.com/drh/
18 #
19 #################################$::RESULT
20 # TH1 Hooks
21 #
22
23 fossil test-th-eval then "hasfeature th1Hooks"
24
25 if {[normalize_result] ne "1"} {
26 ; compiled with TH1 hooks support."
27 test_cleanup_then_return
28 }
29
30 #########################
31
32 set env(TH1_ustom"} {
33 append {$::cmd_name eq "test4"} {
34 then{<title>Fossilproc fossil_th1_hook_http { repository url } {
35 set suffix [appendArgs [pid] - [getSeqNo] - [clmpPath [appendArgs test-hmpPath [appendArgs test-http-ou set data [subst [read_fil]]
36
37 write_file $inFileName $data
38 fossil http $inFileName $outFileName 127.0.0.1 $repository
39 set result [expr {[file exists $outFileName] ? [read_file $outFileName] : ""}]
40
41 if {1} then {
42 catch {file delete $inFileName}
43 catch {frepository }
44
45 return $result
46 }
47
48 proc normat
49 }
50
51 proc normalize_result {} {
52 return [string map [list \r\n \n] [string trim $::RESULT]]
53 }
54
55 proc first_data_line {}\n] 0]
56 }
57
58 proc second_data_line {}\n] 1]
59 }
60
61 proc third_data_line {}\n] 2]
62 }
63
64 proc lD. Richard Hipp
65 #\nlit \n] end-1]
66 }
67
68 proc \rlit \n] end-1]
69 }
70
71 proc \rlit \n] end-1]
72 }
73
74 proc \rlit \n] end-1]
75 }
76
77 proc \rlit \n] end-1]
78 }
79
80 proc \r\n] end-1]
81 if {$::cmd_argsc {} {
82 return [lindex [split \n] end-1]
83 }
84
85 proc #
86 # Co#
87 # Copyright (c)ght (c) 2lit \n] end-1RESULT]] eq
88 timeline}}2b {[secondtimeline}}2cthird_data_line]]}2dest3est4web-hooks-1b {[regexp
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -47,10 +47,14 @@
4747
# FOSSIL_ENABLE_JSON = 1
4848
4949
#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
5050
#
5151
# FOSSIL_ENABLE_SSL = 1
52
+
53
+#### Enable hooks for commands and web pages via TH1
54
+#
55
+# FOSSIL_ENABLE_TH1_HOOKS = 1
5256
5357
#### Enable scripting support via Tcl/Tk
5458
#
5559
# FOSSIL_ENABLE_TCL = 1
5660
@@ -176,10 +180,16 @@
176180
# With HTTPS support
177181
ifdef FOSSIL_ENABLE_SSL
178182
TCC += -DFOSSIL_ENABLE_SSL=1
179183
RCC += -DFOSSIL_ENABLE_SSL=1
180184
endif
185
+
186
+# With TH1 hook support
187
+ifdef FOSSIL_ENABLE_TH1_HOOKS
188
+TCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
189
+RCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
190
+endif
181191
182192
# With Tcl support
183193
ifdef FOSSIL_ENABLE_TCL
184194
TCC += -DFOSSIL_ENABLE_TCL=1
185195
RCC += -DFOSSIL_ENABLE_TCL=1
186196
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -47,10 +47,14 @@
47 # FOSSIL_ENABLE_JSON = 1
48
49 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
50 #
51 # FOSSIL_ENABLE_SSL = 1
 
 
 
 
52
53 #### Enable scripting support via Tcl/Tk
54 #
55 # FOSSIL_ENABLE_TCL = 1
56
@@ -176,10 +180,16 @@
176 # With HTTPS support
177 ifdef FOSSIL_ENABLE_SSL
178 TCC += -DFOSSIL_ENABLE_SSL=1
179 RCC += -DFOSSIL_ENABLE_SSL=1
180 endif
 
 
 
 
 
 
181
182 # With Tcl support
183 ifdef FOSSIL_ENABLE_TCL
184 TCC += -DFOSSIL_ENABLE_TCL=1
185 RCC += -DFOSSIL_ENABLE_TCL=1
186
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -47,10 +47,14 @@
47 # FOSSIL_ENABLE_JSON = 1
48
49 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
50 #
51 # FOSSIL_ENABLE_SSL = 1
52
53 #### Enable hooks for commands and web pages via TH1
54 #
55 # FOSSIL_ENABLE_TH1_HOOKS = 1
56
57 #### Enable scripting support via Tcl/Tk
58 #
59 # FOSSIL_ENABLE_TCL = 1
60
@@ -176,10 +180,16 @@
180 # With HTTPS support
181 ifdef FOSSIL_ENABLE_SSL
182 TCC += -DFOSSIL_ENABLE_SSL=1
183 RCC += -DFOSSIL_ENABLE_SSL=1
184 endif
185
186 # With TH1 hook support
187 ifdef FOSSIL_ENABLE_TH1_HOOKS
188 TCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
189 RCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
190 endif
191
192 # With Tcl support
193 ifdef FOSSIL_ENABLE_TCL
194 TCC += -DFOSSIL_ENABLE_TCL=1
195 RCC += -DFOSSIL_ENABLE_TCL=1
196
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -47,10 +47,14 @@
4747
# FOSSIL_ENABLE_JSON = 1
4848
4949
#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
5050
#
5151
# FOSSIL_ENABLE_SSL = 1
52
+
53
+#### Enable hooks for commands and web pages via TH1
54
+#
55
+# FOSSIL_ENABLE_TH1_HOOKS = 1
5256
5357
#### Enable scripting support via Tcl/Tk
5458
#
5559
# FOSSIL_ENABLE_TCL = 1
5660
@@ -176,10 +180,16 @@
176180
# With HTTPS support
177181
ifdef FOSSIL_ENABLE_SSL
178182
TCC += -DFOSSIL_ENABLE_SSL=1
179183
RCC += -DFOSSIL_ENABLE_SSL=1
180184
endif
185
+
186
+# With TH1 hook support
187
+ifdef FOSSIL_ENABLE_TH1_HOOKS
188
+TCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
189
+RCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
190
+endif
181191
182192
# With Tcl support
183193
ifdef FOSSIL_ENABLE_TCL
184194
TCC += -DFOSSIL_ENABLE_TCL=1
185195
RCC += -DFOSSIL_ENABLE_TCL=1
186196
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -47,10 +47,14 @@
47 # FOSSIL_ENABLE_JSON = 1
48
49 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
50 #
51 # FOSSIL_ENABLE_SSL = 1
 
 
 
 
52
53 #### Enable scripting support via Tcl/Tk
54 #
55 # FOSSIL_ENABLE_TCL = 1
56
@@ -176,10 +180,16 @@
176 # With HTTPS support
177 ifdef FOSSIL_ENABLE_SSL
178 TCC += -DFOSSIL_ENABLE_SSL=1
179 RCC += -DFOSSIL_ENABLE_SSL=1
180 endif
 
 
 
 
 
 
181
182 # With Tcl support
183 ifdef FOSSIL_ENABLE_TCL
184 TCC += -DFOSSIL_ENABLE_TCL=1
185 RCC += -DFOSSIL_ENABLE_TCL=1
186
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -47,10 +47,14 @@
47 # FOSSIL_ENABLE_JSON = 1
48
49 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
50 #
51 # FOSSIL_ENABLE_SSL = 1
52
53 #### Enable hooks for commands and web pages via TH1
54 #
55 # FOSSIL_ENABLE_TH1_HOOKS = 1
56
57 #### Enable scripting support via Tcl/Tk
58 #
59 # FOSSIL_ENABLE_TCL = 1
60
@@ -176,10 +180,16 @@
180 # With HTTPS support
181 ifdef FOSSIL_ENABLE_SSL
182 TCC += -DFOSSIL_ENABLE_SSL=1
183 RCC += -DFOSSIL_ENABLE_SSL=1
184 endif
185
186 # With TH1 hook support
187 ifdef FOSSIL_ENABLE_TH1_HOOKS
188 TCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
189 RCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
190 endif
191
192 # With Tcl support
193 ifdef FOSSIL_ENABLE_TCL
194 TCC += -DFOSSIL_ENABLE_TCL=1
195 RCC += -DFOSSIL_ENABLE_TCL=1
196
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -47,10 +47,14 @@
4747
FOSSIL_ENABLE_JSON = 1
4848
4949
#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
5050
#
5151
FOSSIL_ENABLE_SSL = 1
52
+
53
+#### Enable hooks for commands and web pages via TH1
54
+#
55
+FOSSIL_ENABLE_TH1_HOOKS = 1
5256
5357
#### Enable scripting support via Tcl/Tk
5458
#
5559
FOSSIL_ENABLE_TCL = 1
5660
@@ -176,10 +180,16 @@
176180
# With HTTPS support
177181
ifdef FOSSIL_ENABLE_SSL
178182
TCC += -DFOSSIL_ENABLE_SSL=1
179183
RCC += -DFOSSIL_ENABLE_SSL=1
180184
endif
185
+
186
+# With TH1 hook support
187
+ifdef FOSSIL_ENABLE_TH1_HOOKS
188
+TCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
189
+RCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
190
+endif
181191
182192
# With Tcl support
183193
ifdef FOSSIL_ENABLE_TCL
184194
TCC += -DFOSSIL_ENABLE_TCL=1
185195
RCC += -DFOSSIL_ENABLE_TCL=1
186196
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -47,10 +47,14 @@
47 FOSSIL_ENABLE_JSON = 1
48
49 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
50 #
51 FOSSIL_ENABLE_SSL = 1
 
 
 
 
52
53 #### Enable scripting support via Tcl/Tk
54 #
55 FOSSIL_ENABLE_TCL = 1
56
@@ -176,10 +180,16 @@
176 # With HTTPS support
177 ifdef FOSSIL_ENABLE_SSL
178 TCC += -DFOSSIL_ENABLE_SSL=1
179 RCC += -DFOSSIL_ENABLE_SSL=1
180 endif
 
 
 
 
 
 
181
182 # With Tcl support
183 ifdef FOSSIL_ENABLE_TCL
184 TCC += -DFOSSIL_ENABLE_TCL=1
185 RCC += -DFOSSIL_ENABLE_TCL=1
186
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -47,10 +47,14 @@
47 FOSSIL_ENABLE_JSON = 1
48
49 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
50 #
51 FOSSIL_ENABLE_SSL = 1
52
53 #### Enable hooks for commands and web pages via TH1
54 #
55 FOSSIL_ENABLE_TH1_HOOKS = 1
56
57 #### Enable scripting support via Tcl/Tk
58 #
59 FOSSIL_ENABLE_TCL = 1
60
@@ -176,10 +180,16 @@
180 # With HTTPS support
181 ifdef FOSSIL_ENABLE_SSL
182 TCC += -DFOSSIL_ENABLE_SSL=1
183 RCC += -DFOSSIL_ENABLE_SSL=1
184 endif
185
186 # With TH1 hook support
187 ifdef FOSSIL_ENABLE_TH1_HOOKS
188 TCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
189 RCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
190 endif
191
192 # With Tcl support
193 ifdef FOSSIL_ENABLE_TCL
194 TCC += -DFOSSIL_ENABLE_TCL=1
195 RCC += -DFOSSIL_ENABLE_TCL=1
196
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -47,10 +47,14 @@
4747
FOSSIL_ENABLE_JSON = 1
4848
4949
#### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
5050
#
5151
FOSSIL_ENABLE_SSL = 1
52
+
53
+#### Enable hooks for commands and web pages via TH1
54
+#
55
+FOSSIL_ENABLE_TH1_HOOKS = 1
5256
5357
#### Enable scripting support via Tcl/Tk
5458
#
5559
FOSSIL_ENABLE_TCL = 1
5660
@@ -176,10 +180,16 @@
176180
# With HTTPS support
177181
ifdef FOSSIL_ENABLE_SSL
178182
TCC += -DFOSSIL_ENABLE_SSL=1
179183
RCC += -DFOSSIL_ENABLE_SSL=1
180184
endif
185
+
186
+# With TH1 hook support
187
+ifdef FOSSIL_ENABLE_TH1_HOOKS
188
+TCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
189
+RCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
190
+endif
181191
182192
# With Tcl support
183193
ifdef FOSSIL_ENABLE_TCL
184194
TCC += -DFOSSIL_ENABLE_TCL=1
185195
RCC += -DFOSSIL_ENABLE_TCL=1
186196
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -47,10 +47,14 @@
47 FOSSIL_ENABLE_JSON = 1
48
49 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
50 #
51 FOSSIL_ENABLE_SSL = 1
 
 
 
 
52
53 #### Enable scripting support via Tcl/Tk
54 #
55 FOSSIL_ENABLE_TCL = 1
56
@@ -176,10 +180,16 @@
176 # With HTTPS support
177 ifdef FOSSIL_ENABLE_SSL
178 TCC += -DFOSSIL_ENABLE_SSL=1
179 RCC += -DFOSSIL_ENABLE_SSL=1
180 endif
 
 
 
 
 
 
181
182 # With Tcl support
183 ifdef FOSSIL_ENABLE_TCL
184 TCC += -DFOSSIL_ENABLE_TCL=1
185 RCC += -DFOSSIL_ENABLE_TCL=1
186
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -47,10 +47,14 @@
47 FOSSIL_ENABLE_JSON = 1
48
49 #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto)
50 #
51 FOSSIL_ENABLE_SSL = 1
52
53 #### Enable hooks for commands and web pages via TH1
54 #
55 FOSSIL_ENABLE_TH1_HOOKS = 1
56
57 #### Enable scripting support via Tcl/Tk
58 #
59 FOSSIL_ENABLE_TCL = 1
60
@@ -176,10 +180,16 @@
180 # With HTTPS support
181 ifdef FOSSIL_ENABLE_SSL
182 TCC += -DFOSSIL_ENABLE_SSL=1
183 RCC += -DFOSSIL_ENABLE_SSL=1
184 endif
185
186 # With TH1 hook support
187 ifdef FOSSIL_ENABLE_TH1_HOOKS
188 TCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
189 RCC += -DFOSSIL_ENABLE_TH1_HOOKS=1
190 endif
191
192 # With Tcl support
193 ifdef FOSSIL_ENABLE_TCL
194 TCC += -DFOSSIL_ENABLE_TCL=1
195 RCC += -DFOSSIL_ENABLE_TCL=1
196
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -21,10 +21,13 @@
2121
# Uncomment to enable JSON API
2222
# FOSSIL_ENABLE_JSON = 1
2323
2424
# Uncomment to enable SSL support
2525
# FOSSIL_ENABLE_SSL = 1
26
+
27
+# Uncomment to enable TH1 hooks
28
+# FOSSIL_ENABLE_TH1_HOOKS = 1
2629
2730
# Uncomment to enable Tcl support
2831
# FOSSIL_ENABLE_TCL = 1
2932
3033
!ifdef FOSSIL_ENABLE_SSL
@@ -79,10 +82,15 @@
7982
TCC = $(TCC) /DFOSSIL_ENABLE_SSL=1
8083
RCC = $(RCC) /DFOSSIL_ENABLE_SSL=1
8184
LIBS = $(LIBS) $(SSLLIB)
8285
LIBDIR = $(LIBDIR) /LIBPATH:$(SSLLIBDIR)
8386
!endif
87
+
88
+!ifdef FOSSIL_ENABLE_TH1_HOOKS
89
+TCC = $(TCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
90
+RCC = $(RCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
91
+!endif
8492
8593
!ifdef FOSSIL_ENABLE_TCL
8694
TCC = $(TCC) /DFOSSIL_ENABLE_TCL=1
8795
RCC = $(RCC) /DFOSSIL_ENABLE_TCL=1
8896
TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
8997
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -21,10 +21,13 @@
21 # Uncomment to enable JSON API
22 # FOSSIL_ENABLE_JSON = 1
23
24 # Uncomment to enable SSL support
25 # FOSSIL_ENABLE_SSL = 1
 
 
 
26
27 # Uncomment to enable Tcl support
28 # FOSSIL_ENABLE_TCL = 1
29
30 !ifdef FOSSIL_ENABLE_SSL
@@ -79,10 +82,15 @@
79 TCC = $(TCC) /DFOSSIL_ENABLE_SSL=1
80 RCC = $(RCC) /DFOSSIL_ENABLE_SSL=1
81 LIBS = $(LIBS) $(SSLLIB)
82 LIBDIR = $(LIBDIR) /LIBPATH:$(SSLLIBDIR)
83 !endif
 
 
 
 
 
84
85 !ifdef FOSSIL_ENABLE_TCL
86 TCC = $(TCC) /DFOSSIL_ENABLE_TCL=1
87 RCC = $(RCC) /DFOSSIL_ENABLE_TCL=1
88 TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
89
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -21,10 +21,13 @@
21 # Uncomment to enable JSON API
22 # FOSSIL_ENABLE_JSON = 1
23
24 # Uncomment to enable SSL support
25 # FOSSIL_ENABLE_SSL = 1
26
27 # Uncomment to enable TH1 hooks
28 # FOSSIL_ENABLE_TH1_HOOKS = 1
29
30 # Uncomment to enable Tcl support
31 # FOSSIL_ENABLE_TCL = 1
32
33 !ifdef FOSSIL_ENABLE_SSL
@@ -79,10 +82,15 @@
82 TCC = $(TCC) /DFOSSIL_ENABLE_SSL=1
83 RCC = $(RCC) /DFOSSIL_ENABLE_SSL=1
84 LIBS = $(LIBS) $(SSLLIB)
85 LIBDIR = $(LIBDIR) /LIBPATH:$(SSLLIBDIR)
86 !endif
87
88 !ifdef FOSSIL_ENABLE_TH1_HOOKS
89 TCC = $(TCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
90 RCC = $(RCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
91 !endif
92
93 !ifdef FOSSIL_ENABLE_TCL
94 TCC = $(TCC) /DFOSSIL_ENABLE_TCL=1
95 RCC = $(RCC) /DFOSSIL_ENABLE_TCL=1
96 TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
97
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -21,10 +21,13 @@
2121
# Uncomment to enable JSON API
2222
# FOSSIL_ENABLE_JSON = 1
2323
2424
# Uncomment to enable SSL support
2525
# FOSSIL_ENABLE_SSL = 1
26
+
27
+# Uncomment to enable TH1 hooks
28
+# FOSSIL_ENABLE_TH1_HOOKS = 1
2629
2730
# Uncomment to enable Tcl support
2831
# FOSSIL_ENABLE_TCL = 1
2932
3033
!ifdef FOSSIL_ENABLE_SSL
@@ -79,10 +82,15 @@
7982
TCC = $(TCC) /DFOSSIL_ENABLE_SSL=1
8083
RCC = $(RCC) /DFOSSIL_ENABLE_SSL=1
8184
LIBS = $(LIBS) $(SSLLIB)
8285
LIBDIR = $(LIBDIR) /LIBPATH:$(SSLLIBDIR)
8386
!endif
87
+
88
+!ifdef FOSSIL_ENABLE_TH1_HOOKS
89
+TCC = $(TCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
90
+RCC = $(RCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
91
+!endif
8492
8593
!ifdef FOSSIL_ENABLE_TCL
8694
TCC = $(TCC) /DFOSSIL_ENABLE_TCL=1
8795
RCC = $(RCC) /DFOSSIL_ENABLE_TCL=1
8896
TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
8997
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -21,10 +21,13 @@
21 # Uncomment to enable JSON API
22 # FOSSIL_ENABLE_JSON = 1
23
24 # Uncomment to enable SSL support
25 # FOSSIL_ENABLE_SSL = 1
 
 
 
26
27 # Uncomment to enable Tcl support
28 # FOSSIL_ENABLE_TCL = 1
29
30 !ifdef FOSSIL_ENABLE_SSL
@@ -79,10 +82,15 @@
79 TCC = $(TCC) /DFOSSIL_ENABLE_SSL=1
80 RCC = $(RCC) /DFOSSIL_ENABLE_SSL=1
81 LIBS = $(LIBS) $(SSLLIB)
82 LIBDIR = $(LIBDIR) /LIBPATH:$(SSLLIBDIR)
83 !endif
 
 
 
 
 
84
85 !ifdef FOSSIL_ENABLE_TCL
86 TCC = $(TCC) /DFOSSIL_ENABLE_TCL=1
87 RCC = $(RCC) /DFOSSIL_ENABLE_TCL=1
88 TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
89
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -21,10 +21,13 @@
21 # Uncomment to enable JSON API
22 # FOSSIL_ENABLE_JSON = 1
23
24 # Uncomment to enable SSL support
25 # FOSSIL_ENABLE_SSL = 1
26
27 # Uncomment to enable TH1 hooks
28 # FOSSIL_ENABLE_TH1_HOOKS = 1
29
30 # Uncomment to enable Tcl support
31 # FOSSIL_ENABLE_TCL = 1
32
33 !ifdef FOSSIL_ENABLE_SSL
@@ -79,10 +82,15 @@
82 TCC = $(TCC) /DFOSSIL_ENABLE_SSL=1
83 RCC = $(RCC) /DFOSSIL_ENABLE_SSL=1
84 LIBS = $(LIBS) $(SSLLIB)
85 LIBDIR = $(LIBDIR) /LIBPATH:$(SSLLIBDIR)
86 !endif
87
88 !ifdef FOSSIL_ENABLE_TH1_HOOKS
89 TCC = $(TCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
90 RCC = $(RCC) /DFOSSIL_ENABLE_TH1_HOOKS=1
91 !endif
92
93 !ifdef FOSSIL_ENABLE_TCL
94 TCC = $(TCC) /DFOSSIL_ENABLE_TCL=1
95 RCC = $(RCC) /DFOSSIL_ENABLE_TCL=1
96 TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1
97
--- win/fossil.rc
+++ win/fossil.rc
@@ -101,10 +101,15 @@
101101
VALUE "CommandLineIsUnicode", "Yes\0"
102102
#endif /* defined(BROKEN_MINGW_CMDLINE) */
103103
#if defined(FOSSIL_ENABLE_SSL)
104104
VALUE "SslEnabled", "Yes, " OPENSSL_VERSION_TEXT "\0"
105105
#endif /* defined(FOSSIL_ENABLE_SSL) */
106
+#if defined(FOSSIL_ENABLE_TH1_HOOKS)
107
+ VALUE "Th1Hooks", "Yes\0"
108
+#else
109
+ VALUE "Th1Hooks", "No\0"
110
+#endif
106111
#if defined(FOSSIL_ENABLE_TCL)
107112
VALUE "TclEnabled", "Yes, Tcl " TCL_PATCH_LEVEL "\0"
108113
#if defined(USE_TCL_STUBS)
109114
VALUE "UseTclStubsEnabled", "Yes\0"
110115
#else
111116
--- win/fossil.rc
+++ win/fossil.rc
@@ -101,10 +101,15 @@
101 VALUE "CommandLineIsUnicode", "Yes\0"
102 #endif /* defined(BROKEN_MINGW_CMDLINE) */
103 #if defined(FOSSIL_ENABLE_SSL)
104 VALUE "SslEnabled", "Yes, " OPENSSL_VERSION_TEXT "\0"
105 #endif /* defined(FOSSIL_ENABLE_SSL) */
 
 
 
 
 
106 #if defined(FOSSIL_ENABLE_TCL)
107 VALUE "TclEnabled", "Yes, Tcl " TCL_PATCH_LEVEL "\0"
108 #if defined(USE_TCL_STUBS)
109 VALUE "UseTclStubsEnabled", "Yes\0"
110 #else
111
--- win/fossil.rc
+++ win/fossil.rc
@@ -101,10 +101,15 @@
101 VALUE "CommandLineIsUnicode", "Yes\0"
102 #endif /* defined(BROKEN_MINGW_CMDLINE) */
103 #if defined(FOSSIL_ENABLE_SSL)
104 VALUE "SslEnabled", "Yes, " OPENSSL_VERSION_TEXT "\0"
105 #endif /* defined(FOSSIL_ENABLE_SSL) */
106 #if defined(FOSSIL_ENABLE_TH1_HOOKS)
107 VALUE "Th1Hooks", "Yes\0"
108 #else
109 VALUE "Th1Hooks", "No\0"
110 #endif
111 #if defined(FOSSIL_ENABLE_TCL)
112 VALUE "TclEnabled", "Yes, Tcl " TCL_PATCH_LEVEL "\0"
113 #if defined(USE_TCL_STUBS)
114 VALUE "UseTclStubsEnabled", "Yes\0"
115 #else
116

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button