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.
Commit
1c528d3bb9e07428d1a35a07201ed1aadcb7fd36
Parent
57be4d552ef2ec2…
20 files changed
+6
+6
+1
+36
-7
+36
-7
+119
-10
+18
+18
+238
+238
+56
+4
+88
+10
+10
+10
+10
+8
+8
+5
~
auto.def
~
auto.def
~
src/configure.c
~
src/db.c
~
src/db.c
~
src/main.c
~
src/makemake.tcl
~
src/makemake.tcl
~
src/th_main.c
~
src/th_main.c
~
test/tester.tcl
~
test/th1-hooks-input.txt
~
test/th1-hooks.test
~
win/Makefile.mingw
~
win/Makefile.mingw
~
win/Makefile.mingw.mistachkin
~
win/Makefile.mingw.mistachkin
~
win/Makefile.msc
~
win/Makefile.msc
~
win/fossil.rc
M
auto.def
+6
| --- auto.def | ||
| +++ auto.def | ||
| @@ -4,10 +4,11 @@ | ||
| 4 | 4 | |
| 5 | 5 | options { |
| 6 | 6 | with-openssl:path|auto|none |
| 7 | 7 | => {Look for openssl in the given path, or auto or none} |
| 8 | 8 | with-zlib:path => {Look for zlib in the given path} |
| 9 | + with-th1-hooks=0 => {Enable TH1 hooks for commands and web pages} | |
| 9 | 10 | with-tcl:path => {Enable Tcl integration, with Tcl in the specified path} |
| 10 | 11 | with-tcl-stubs=0 => {Enable Tcl integration via stubs library mechanism} |
| 11 | 12 | with-tcl-private-stubs=0 |
| 12 | 13 | => {Enable Tcl integration via private stubs mechanism} |
| 13 | 14 | internal-sqlite=1 => {Don't use the internal SQLite, use the system one} |
| @@ -80,10 +81,15 @@ | ||
| 80 | 81 | # have #ifdef guards around the whole file without |
| 81 | 82 | # reading config.h first. |
| 82 | 83 | define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_JSON |
| 83 | 84 | define FOSSIL_ENABLE_JSON |
| 84 | 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 | +} | |
| 85 | 91 | |
| 86 | 92 | #if {[opt-bool markdown]} { |
| 87 | 93 | # # no-op. Markdown is now enabled by default. |
| 88 | 94 | #} |
| 89 | 95 | |
| 90 | 96 |
| --- 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 |
M
auto.def
+6
| --- auto.def | ||
| +++ auto.def | ||
| @@ -4,10 +4,11 @@ | ||
| 4 | 4 | |
| 5 | 5 | options { |
| 6 | 6 | with-openssl:path|auto|none |
| 7 | 7 | => {Look for openssl in the given path, or auto or none} |
| 8 | 8 | with-zlib:path => {Look for zlib in the given path} |
| 9 | + with-th1-hooks=0 => {Enable TH1 hooks for commands and web pages} | |
| 9 | 10 | with-tcl:path => {Enable Tcl integration, with Tcl in the specified path} |
| 10 | 11 | with-tcl-stubs=0 => {Enable Tcl integration via stubs library mechanism} |
| 11 | 12 | with-tcl-private-stubs=0 |
| 12 | 13 | => {Enable Tcl integration via private stubs mechanism} |
| 13 | 14 | internal-sqlite=1 => {Don't use the internal SQLite, use the system one} |
| @@ -80,10 +81,15 @@ | ||
| 80 | 81 | # have #ifdef guards around the whole file without |
| 81 | 82 | # reading config.h first. |
| 82 | 83 | define-append EXTRA_CFLAGS -DFOSSIL_ENABLE_JSON |
| 83 | 84 | define FOSSIL_ENABLE_JSON |
| 84 | 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 | +} | |
| 85 | 91 | |
| 86 | 92 | #if {[opt-bool markdown]} { |
| 87 | 93 | # # no-op. Markdown is now enabled by default. |
| 88 | 94 | #} |
| 89 | 95 | |
| 90 | 96 |
| --- 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 |
+1
| --- src/configure.c | ||
| +++ src/configure.c | ||
| @@ -97,10 +97,11 @@ | ||
| 97 | 97 | { "timeline-max-comment", CONFIGSET_SKIN }, |
| 98 | 98 | { "timeline-plaintext", CONFIGSET_SKIN }, |
| 99 | 99 | { "adunit", CONFIGSET_SKIN }, |
| 100 | 100 | { "adunit-omit-if-admin", CONFIGSET_SKIN }, |
| 101 | 101 | { "adunit-omit-if-user", CONFIGSET_SKIN }, |
| 102 | + { "th1-hooks", CONFIGSET_TH1 }, | |
| 102 | 103 | { "th1-setup", CONFIGSET_TH1 }, |
| 103 | 104 | { "th1-uri-regexp", CONFIGSET_TH1 }, |
| 104 | 105 | |
| 105 | 106 | #ifdef FOSSIL_ENABLE_TCL |
| 106 | 107 | { "tcl", CONFIGSET_TH1 }, |
| 107 | 108 |
| --- 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 |
M
src/db.c
+36
-7
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -785,10 +785,31 @@ | ||
| 785 | 785 | assert( g.zMainDbType!=0 ); |
| 786 | 786 | db_attach(zDbName, zLabel); |
| 787 | 787 | if( pWasAttached ) *pWasAttached = 1; |
| 788 | 788 | } |
| 789 | 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 | +} | |
| 790 | 811 | |
| 791 | 812 | /* |
| 792 | 813 | ** Open the user database in "~/.fossil". Create the database anew if |
| 793 | 814 | ** it does not already exist. |
| 794 | 815 | ** |
| @@ -801,11 +822,14 @@ | ||
| 801 | 822 | ** case, invoke this routine with useAttach as 1. |
| 802 | 823 | */ |
| 803 | 824 | void db_open_config(int useAttach){ |
| 804 | 825 | char *zDbName; |
| 805 | 826 | char *zHome; |
| 806 | - if( g.zConfigDbName ) return; | |
| 827 | + if( g.zConfigDbName ){ | |
| 828 | + if( useAttach==g.useAttach ) return; | |
| 829 | + db_close_config(); | |
| 830 | + } | |
| 807 | 831 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 808 | 832 | zHome = fossil_getenv("LOCALAPPDATA"); |
| 809 | 833 | if( zHome==0 ){ |
| 810 | 834 | zHome = fossil_getenv("APPDATA"); |
| 811 | 835 | if( zHome==0 ){ |
| @@ -2169,14 +2193,15 @@ | ||
| 2169 | 2193 | { "ssh-command", 0, 40, 0, 0, "" }, |
| 2170 | 2194 | { "ssl-ca-location", 0, 40, 0, 0, "" }, |
| 2171 | 2195 | { "ssl-identity", 0, 40, 0, 0, "" }, |
| 2172 | 2196 | #ifdef FOSSIL_ENABLE_TCL |
| 2173 | 2197 | { "tcl", 0, 0, 0, 0, "off" }, |
| 2174 | - { "tcl-setup", 0, 40, 0, 1, "" }, | |
| 2198 | + { "tcl-setup", 0, 40, 1, 1, "" }, | |
| 2175 | 2199 | #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, "" }, | |
| 2178 | 2203 | { "web-browser", 0, 32, 0, 0, "" }, |
| 2179 | 2204 | { "white-foreground", 0, 0, 0, 0, "off" }, |
| 2180 | 2205 | { 0,0,0,0,0,0 } |
| 2181 | 2206 | }; |
| 2182 | 2207 | |
| @@ -2375,19 +2400,23 @@ | ||
| 2375 | 2400 | ** scripts to be evaluated from TH1. Additionally, the Tcl |
| 2376 | 2401 | ** interpreter will be able to evaluate arbitrary TH1 |
| 2377 | 2402 | ** expressions and scripts. Default: off. |
| 2378 | 2403 | ** |
| 2379 | 2404 | ** 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 | |
| 2381 | 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. | |
| 2382 | 2411 | ** |
| 2383 | 2412 | ** 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 | |
| 2385 | 2414 | ** is empty and no extra setup is performed. |
| 2386 | 2415 | ** |
| 2387 | 2416 | ** 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 | |
| 2389 | 2418 | ** whatsoever. The default is an empty string. |
| 2390 | 2419 | ** |
| 2391 | 2420 | ** web-browser A shell command used to launch your preferred |
| 2392 | 2421 | ** web browser when given a URL as an argument. |
| 2393 | 2422 | ** Defaults to "start" on windows, "open" on Mac, |
| 2394 | 2423 |
| --- 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 |
M
src/db.c
+36
-7
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -785,10 +785,31 @@ | ||
| 785 | 785 | assert( g.zMainDbType!=0 ); |
| 786 | 786 | db_attach(zDbName, zLabel); |
| 787 | 787 | if( pWasAttached ) *pWasAttached = 1; |
| 788 | 788 | } |
| 789 | 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 | +} | |
| 790 | 811 | |
| 791 | 812 | /* |
| 792 | 813 | ** Open the user database in "~/.fossil". Create the database anew if |
| 793 | 814 | ** it does not already exist. |
| 794 | 815 | ** |
| @@ -801,11 +822,14 @@ | ||
| 801 | 822 | ** case, invoke this routine with useAttach as 1. |
| 802 | 823 | */ |
| 803 | 824 | void db_open_config(int useAttach){ |
| 804 | 825 | char *zDbName; |
| 805 | 826 | char *zHome; |
| 806 | - if( g.zConfigDbName ) return; | |
| 827 | + if( g.zConfigDbName ){ | |
| 828 | + if( useAttach==g.useAttach ) return; | |
| 829 | + db_close_config(); | |
| 830 | + } | |
| 807 | 831 | #if defined(_WIN32) || defined(__CYGWIN__) |
| 808 | 832 | zHome = fossil_getenv("LOCALAPPDATA"); |
| 809 | 833 | if( zHome==0 ){ |
| 810 | 834 | zHome = fossil_getenv("APPDATA"); |
| 811 | 835 | if( zHome==0 ){ |
| @@ -2169,14 +2193,15 @@ | ||
| 2169 | 2193 | { "ssh-command", 0, 40, 0, 0, "" }, |
| 2170 | 2194 | { "ssl-ca-location", 0, 40, 0, 0, "" }, |
| 2171 | 2195 | { "ssl-identity", 0, 40, 0, 0, "" }, |
| 2172 | 2196 | #ifdef FOSSIL_ENABLE_TCL |
| 2173 | 2197 | { "tcl", 0, 0, 0, 0, "off" }, |
| 2174 | - { "tcl-setup", 0, 40, 0, 1, "" }, | |
| 2198 | + { "tcl-setup", 0, 40, 1, 1, "" }, | |
| 2175 | 2199 | #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, "" }, | |
| 2178 | 2203 | { "web-browser", 0, 32, 0, 0, "" }, |
| 2179 | 2204 | { "white-foreground", 0, 0, 0, 0, "off" }, |
| 2180 | 2205 | { 0,0,0,0,0,0 } |
| 2181 | 2206 | }; |
| 2182 | 2207 | |
| @@ -2375,19 +2400,23 @@ | ||
| 2375 | 2400 | ** scripts to be evaluated from TH1. Additionally, the Tcl |
| 2376 | 2401 | ** interpreter will be able to evaluate arbitrary TH1 |
| 2377 | 2402 | ** expressions and scripts. Default: off. |
| 2378 | 2403 | ** |
| 2379 | 2404 | ** 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 | |
| 2381 | 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. | |
| 2382 | 2411 | ** |
| 2383 | 2412 | ** 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 | |
| 2385 | 2414 | ** is empty and no extra setup is performed. |
| 2386 | 2415 | ** |
| 2387 | 2416 | ** 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 | |
| 2389 | 2418 | ** whatsoever. The default is an empty string. |
| 2390 | 2419 | ** |
| 2391 | 2420 | ** web-browser A shell command used to launch your preferred |
| 2392 | 2421 | ** web browser when given a URL as an argument. |
| 2393 | 2422 | ** Defaults to "start" on windows, "open" on Mac, |
| 2394 | 2423 |
| --- 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 @@ | ||
| 194 | 194 | char zCsrfToken[12]; /* Value of the anti-CSRF token */ |
| 195 | 195 | int okCsrf; /* Anti-CSRF token is present and valid */ |
| 196 | 196 | |
| 197 | 197 | int parseCnt[10]; /* Counts of artifacts parsed */ |
| 198 | 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 | |
| 199 | 202 | int thTrace; /* True to enable TH1 debugging output */ |
| 200 | 203 | Blob thLog; /* Text of the TH1 debugging output */ |
| 201 | 204 | |
| 202 | 205 | int isHome; /* True if rendering the "home" page */ |
| 203 | 206 | |
| @@ -620,10 +623,13 @@ | ||
| 620 | 623 | g.fSshClient = 0; |
| 621 | 624 | g.zSshCmd = 0; |
| 622 | 625 | if( g.fSqlTrace ) g.fSqlStats = 1; |
| 623 | 626 | g.fSqlPrint = find_option("sqlprint", 0, 0)!=0; |
| 624 | 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 | |
| 625 | 631 | g.zHttpAuth = 0; |
| 626 | 632 | g.zLogin = find_option("user", "U", 1); |
| 627 | 633 | g.zSSLIdentity = find_option("ssl-identity", 0, 1); |
| 628 | 634 | g.zErrlog = find_option("errorlog", 0, 1); |
| 629 | 635 | if( find_option("utc",0,0) ) g.fTimeFormat = 1; |
| @@ -649,13 +655,30 @@ | ||
| 649 | 655 | if( !is_valid_fd(2) ) fossil_panic("file descriptor 2 not open"); |
| 650 | 656 | /* if( is_valid_fd(3) ) fossil_warning("file descriptor 3 is open"); */ |
| 651 | 657 | #endif |
| 652 | 658 | rc = name_search(zCmdName, aCommand, count(aCommand), &idx); |
| 653 | 659 | 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 | |
| 657 | 680 | }else if( rc==2 ){ |
| 658 | 681 | int i, n; |
| 659 | 682 | Blob couldbe; |
| 660 | 683 | blob_zero(&couldbe); |
| 661 | 684 | n = strlen(zCmdName); |
| @@ -669,11 +692,44 @@ | ||
| 669 | 692 | "%s: use \"help\" for more information\n", |
| 670 | 693 | g.argv[0], zCmdName, g.argv[0], blob_str(&couldbe), g.argv[0]); |
| 671 | 694 | fossil_exit(1); |
| 672 | 695 | } |
| 673 | 696 | 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 | |
| 675 | 731 | fossil_exit(0); |
| 676 | 732 | /*NOT_REACHED*/ |
| 677 | 733 | return 0; |
| 678 | 734 | } |
| 679 | 735 | |
| @@ -861,10 +917,13 @@ | ||
| 861 | 917 | fossil_print("SQLite %s %.30s\n", sqlite3_libversion(), sqlite3_sourceid()); |
| 862 | 918 | fossil_print("Schema version %s\n", AUX_SCHEMA); |
| 863 | 919 | fossil_print("zlib %s, loaded %s\n", ZLIB_VERSION, zlibVersion()); |
| 864 | 920 | #if defined(FOSSIL_ENABLE_SSL) |
| 865 | 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"); | |
| 866 | 925 | #endif |
| 867 | 926 | #if defined(FOSSIL_ENABLE_TCL) |
| 868 | 927 | Th_FossilInit(TH_INIT_DEFAULT | TH_INIT_FORCE_TCL); |
| 869 | 928 | rc = Th_Eval(g.interp, 0, "tclInvoke info patchlevel", -1); |
| 870 | 929 | zRc = Th_ReturnCodeName(rc, 0); |
| @@ -1486,21 +1545,37 @@ | ||
| 1486 | 1545 | } |
| 1487 | 1546 | |
| 1488 | 1547 | /* Locate the method specified by the path and execute the function |
| 1489 | 1548 | ** that implements that method. |
| 1490 | 1549 | */ |
| 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) ){ | |
| 1493 | 1551 | #ifdef FOSSIL_ENABLE_JSON |
| 1494 | 1552 | if(g.json.isJsonMode){ |
| 1495 | 1553 | json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,0); |
| 1496 | 1554 | }else |
| 1497 | 1555 | #endif |
| 1498 | 1556 | { |
| 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 | |
| 1502 | 1577 | } |
| 1503 | 1578 | }else if( aWebpage[idx].xFunc!=page_xfer && db_schema_is_outofdate() ){ |
| 1504 | 1579 | #ifdef FOSSIL_ENABLE_JSON |
| 1505 | 1580 | if(g.json.isJsonMode){ |
| 1506 | 1581 | json_err(FSL_JSON_E_DB_NEEDS_REBUILD,NULL,0); |
| @@ -1510,11 +1585,45 @@ | ||
| 1510 | 1585 | @ <h1>Server Configuration Error</h1> |
| 1511 | 1586 | @ <p>The database schema on the server is out-of-date. Please ask |
| 1512 | 1587 | @ the administrator to run <b>fossil rebuild</b>.</p> |
| 1513 | 1588 | } |
| 1514 | 1589 | }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 | |
| 1516 | 1625 | } |
| 1517 | 1626 | |
| 1518 | 1627 | /* Return the result. |
| 1519 | 1628 | */ |
| 1520 | 1629 | cgi_reply(); |
| 1521 | 1630 |
| --- 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 |
+18
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -409,10 +409,14 @@ | ||
| 409 | 409 | # FOSSIL_ENABLE_JSON = 1 |
| 410 | 410 | |
| 411 | 411 | #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto) |
| 412 | 412 | # |
| 413 | 413 | # FOSSIL_ENABLE_SSL = 1 |
| 414 | + | |
| 415 | +#### Enable hooks for commands and web pages via TH1 | |
| 416 | +# | |
| 417 | +# FOSSIL_ENABLE_TH1_HOOKS = 1 | |
| 414 | 418 | |
| 415 | 419 | #### Enable scripting support via Tcl/Tk |
| 416 | 420 | # |
| 417 | 421 | # FOSSIL_ENABLE_TCL = 1 |
| 418 | 422 | |
| @@ -538,10 +542,16 @@ | ||
| 538 | 542 | # With HTTPS support |
| 539 | 543 | ifdef FOSSIL_ENABLE_SSL |
| 540 | 544 | TCC += -DFOSSIL_ENABLE_SSL=1 |
| 541 | 545 | RCC += -DFOSSIL_ENABLE_SSL=1 |
| 542 | 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 | |
| 543 | 553 | |
| 544 | 554 | # With Tcl support |
| 545 | 555 | ifdef FOSSIL_ENABLE_TCL |
| 546 | 556 | TCC += -DFOSSIL_ENABLE_TCL=1 |
| 547 | 557 | RCC += -DFOSSIL_ENABLE_TCL=1 |
| @@ -1034,10 +1044,13 @@ | ||
| 1034 | 1044 | # Uncomment to enable JSON API |
| 1035 | 1045 | # FOSSIL_ENABLE_JSON = 1 |
| 1036 | 1046 | |
| 1037 | 1047 | # Uncomment to enable SSL support |
| 1038 | 1048 | # FOSSIL_ENABLE_SSL = 1 |
| 1049 | + | |
| 1050 | +# Uncomment to enable TH1 hooks | |
| 1051 | +# FOSSIL_ENABLE_TH1_HOOKS = 1 | |
| 1039 | 1052 | |
| 1040 | 1053 | # Uncomment to enable Tcl support |
| 1041 | 1054 | # FOSSIL_ENABLE_TCL = 1 |
| 1042 | 1055 | |
| 1043 | 1056 | !ifdef FOSSIL_ENABLE_SSL |
| @@ -1092,10 +1105,15 @@ | ||
| 1092 | 1105 | TCC = $(TCC) /DFOSSIL_ENABLE_SSL=1 |
| 1093 | 1106 | RCC = $(RCC) /DFOSSIL_ENABLE_SSL=1 |
| 1094 | 1107 | LIBS = $(LIBS) $(SSLLIB) |
| 1095 | 1108 | LIBDIR = $(LIBDIR) /LIBPATH:$(SSLLIBDIR) |
| 1096 | 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 | |
| 1097 | 1115 | |
| 1098 | 1116 | !ifdef FOSSIL_ENABLE_TCL |
| 1099 | 1117 | TCC = $(TCC) /DFOSSIL_ENABLE_TCL=1 |
| 1100 | 1118 | RCC = $(RCC) /DFOSSIL_ENABLE_TCL=1 |
| 1101 | 1119 | TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1 |
| 1102 | 1120 |
| --- 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 |
+18
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -409,10 +409,14 @@ | ||
| 409 | 409 | # FOSSIL_ENABLE_JSON = 1 |
| 410 | 410 | |
| 411 | 411 | #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto) |
| 412 | 412 | # |
| 413 | 413 | # FOSSIL_ENABLE_SSL = 1 |
| 414 | + | |
| 415 | +#### Enable hooks for commands and web pages via TH1 | |
| 416 | +# | |
| 417 | +# FOSSIL_ENABLE_TH1_HOOKS = 1 | |
| 414 | 418 | |
| 415 | 419 | #### Enable scripting support via Tcl/Tk |
| 416 | 420 | # |
| 417 | 421 | # FOSSIL_ENABLE_TCL = 1 |
| 418 | 422 | |
| @@ -538,10 +542,16 @@ | ||
| 538 | 542 | # With HTTPS support |
| 539 | 543 | ifdef FOSSIL_ENABLE_SSL |
| 540 | 544 | TCC += -DFOSSIL_ENABLE_SSL=1 |
| 541 | 545 | RCC += -DFOSSIL_ENABLE_SSL=1 |
| 542 | 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 | |
| 543 | 553 | |
| 544 | 554 | # With Tcl support |
| 545 | 555 | ifdef FOSSIL_ENABLE_TCL |
| 546 | 556 | TCC += -DFOSSIL_ENABLE_TCL=1 |
| 547 | 557 | RCC += -DFOSSIL_ENABLE_TCL=1 |
| @@ -1034,10 +1044,13 @@ | ||
| 1034 | 1044 | # Uncomment to enable JSON API |
| 1035 | 1045 | # FOSSIL_ENABLE_JSON = 1 |
| 1036 | 1046 | |
| 1037 | 1047 | # Uncomment to enable SSL support |
| 1038 | 1048 | # FOSSIL_ENABLE_SSL = 1 |
| 1049 | + | |
| 1050 | +# Uncomment to enable TH1 hooks | |
| 1051 | +# FOSSIL_ENABLE_TH1_HOOKS = 1 | |
| 1039 | 1052 | |
| 1040 | 1053 | # Uncomment to enable Tcl support |
| 1041 | 1054 | # FOSSIL_ENABLE_TCL = 1 |
| 1042 | 1055 | |
| 1043 | 1056 | !ifdef FOSSIL_ENABLE_SSL |
| @@ -1092,10 +1105,15 @@ | ||
| 1092 | 1105 | TCC = $(TCC) /DFOSSIL_ENABLE_SSL=1 |
| 1093 | 1106 | RCC = $(RCC) /DFOSSIL_ENABLE_SSL=1 |
| 1094 | 1107 | LIBS = $(LIBS) $(SSLLIB) |
| 1095 | 1108 | LIBDIR = $(LIBDIR) /LIBPATH:$(SSLLIBDIR) |
| 1096 | 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 | |
| 1097 | 1115 | |
| 1098 | 1116 | !ifdef FOSSIL_ENABLE_TCL |
| 1099 | 1117 | TCC = $(TCC) /DFOSSIL_ENABLE_TCL=1 |
| 1100 | 1118 | RCC = $(RCC) /DFOSSIL_ENABLE_TCL=1 |
| 1101 | 1119 | TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1 |
| 1102 | 1120 |
| --- 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 @@ | ||
| 31 | 31 | #define TH_INIT_NEED_CONFIG ((u32)0x00000001) /* Open configuration first? */ |
| 32 | 32 | #define TH_INIT_FORCE_TCL ((u32)0x00000002) /* Force Tcl to be enabled? */ |
| 33 | 33 | #define TH_INIT_FORCE_RESET ((u32)0x00000004) /* Force TH1 commands re-added? */ |
| 34 | 34 | #define TH_INIT_FORCE_SETUP ((u32)0x00000008) /* Force eval of setup script? */ |
| 35 | 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" | |
| 36 | 48 | #endif |
| 37 | 49 | |
| 38 | 50 | /* |
| 39 | 51 | ** Global variable counting the number of outstanding calls to malloc() |
| 40 | 52 | ** made by the th1 implementation. This is used to catch memory leaks |
| @@ -327,10 +339,11 @@ | ||
| 327 | 339 | ** |
| 328 | 340 | ** Return true if the fossil binary has the given compile-time feature |
| 329 | 341 | ** enabled. The set of features includes: |
| 330 | 342 | ** |
| 331 | 343 | ** "ssl" = FOSSIL_ENABLE_SSL |
| 344 | +** "th1Hooks" = FOSSIL_ENABLE_TH1_HOOKS | |
| 332 | 345 | ** "tcl" = FOSSIL_ENABLE_TCL |
| 333 | 346 | ** "useTclStubs" = USE_TCL_STUBS |
| 334 | 347 | ** "tclStubs" = FOSSIL_ENABLE_TCL_STUBS |
| 335 | 348 | ** "tclPrivateStubs" = FOSSIL_ENABLE_TCL_PRIVATE_STUBS |
| 336 | 349 | ** "json" = FOSSIL_ENABLE_JSON |
| @@ -355,10 +368,15 @@ | ||
| 355 | 368 | } |
| 356 | 369 | #if defined(FOSSIL_ENABLE_SSL) |
| 357 | 370 | else if( 0 == fossil_strnicmp( zArg, "ssl\0", 4 ) ){ |
| 358 | 371 | rc = 1; |
| 359 | 372 | } |
| 373 | +#endif | |
| 374 | +#if defined(FOSSIL_ENABLE_TH1_HOOKS) | |
| 375 | + else if( 0 == fossil_strnicmp( zArg, "th1Hooks\0", 9 ) ){ | |
| 376 | + rc = 1; | |
| 377 | + } | |
| 360 | 378 | #endif |
| 361 | 379 | #if defined(FOSSIL_ENABLE_TCL) |
| 362 | 380 | else if( 0 == fossil_strnicmp( zArg, "tcl\0", 4 ) ){ |
| 363 | 381 | rc = 1; |
| 364 | 382 | } |
| @@ -1147,10 +1165,23 @@ | ||
| 1147 | 1165 | if( openRepository ){ |
| 1148 | 1166 | db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0); |
| 1149 | 1167 | } |
| 1150 | 1168 | db_open_config(0); |
| 1151 | 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 | +} | |
| 1152 | 1183 | |
| 1153 | 1184 | /* |
| 1154 | 1185 | ** Make sure the interpreter has been initialized. Initialize it if |
| 1155 | 1186 | ** it has not been already. |
| 1156 | 1187 | ** |
| @@ -1265,10 +1296,34 @@ | ||
| 1265 | 1296 | Th_Trace("set %h {%h}<br />\n", zName, zValue); |
| 1266 | 1297 | } |
| 1267 | 1298 | Th_SetVar(g.interp, zName, -1, zValue, strlen(zValue)); |
| 1268 | 1299 | } |
| 1269 | 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 | +} | |
| 1270 | 1325 | |
| 1271 | 1326 | /* |
| 1272 | 1327 | ** Store an integer value in a variable in the interpreter. |
| 1273 | 1328 | */ |
| 1274 | 1329 | void Th_StoreInt(const char *zName, int iValue){ |
| @@ -1362,10 +1417,162 @@ | ||
| 1362 | 1417 | if( z[0]!='>' ) return 0; |
| 1363 | 1418 | i += 2; |
| 1364 | 1419 | } |
| 1365 | 1420 | return i; |
| 1366 | 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 | |
| 1367 | 1574 | |
| 1368 | 1575 | /* |
| 1369 | 1576 | ** The z[] input contains text mixed with TH1 scripts. |
| 1370 | 1577 | ** The TH1 scripts are contained within <th1>...</th1>. |
| 1371 | 1578 | ** TH1 variables are $aaa or $<aaa>. The first form of |
| @@ -1462,5 +1669,36 @@ | ||
| 1462 | 1669 | rc = Th_Eval(g.interp, 0, g.argv[2], -1); |
| 1463 | 1670 | zRc = Th_ReturnCodeName(rc, 1); |
| 1464 | 1671 | fossil_print("%s%s%s\n", zRc, zRc ? ": " : "", Th_GetResult(g.interp, 0)); |
| 1465 | 1672 | Th_PrintTraceLog(); |
| 1466 | 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 | |
| 1467 | 1705 |
| --- 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 @@ | ||
| 31 | 31 | #define TH_INIT_NEED_CONFIG ((u32)0x00000001) /* Open configuration first? */ |
| 32 | 32 | #define TH_INIT_FORCE_TCL ((u32)0x00000002) /* Force Tcl to be enabled? */ |
| 33 | 33 | #define TH_INIT_FORCE_RESET ((u32)0x00000004) /* Force TH1 commands re-added? */ |
| 34 | 34 | #define TH_INIT_FORCE_SETUP ((u32)0x00000008) /* Force eval of setup script? */ |
| 35 | 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" | |
| 36 | 48 | #endif |
| 37 | 49 | |
| 38 | 50 | /* |
| 39 | 51 | ** Global variable counting the number of outstanding calls to malloc() |
| 40 | 52 | ** made by the th1 implementation. This is used to catch memory leaks |
| @@ -327,10 +339,11 @@ | ||
| 327 | 339 | ** |
| 328 | 340 | ** Return true if the fossil binary has the given compile-time feature |
| 329 | 341 | ** enabled. The set of features includes: |
| 330 | 342 | ** |
| 331 | 343 | ** "ssl" = FOSSIL_ENABLE_SSL |
| 344 | +** "th1Hooks" = FOSSIL_ENABLE_TH1_HOOKS | |
| 332 | 345 | ** "tcl" = FOSSIL_ENABLE_TCL |
| 333 | 346 | ** "useTclStubs" = USE_TCL_STUBS |
| 334 | 347 | ** "tclStubs" = FOSSIL_ENABLE_TCL_STUBS |
| 335 | 348 | ** "tclPrivateStubs" = FOSSIL_ENABLE_TCL_PRIVATE_STUBS |
| 336 | 349 | ** "json" = FOSSIL_ENABLE_JSON |
| @@ -355,10 +368,15 @@ | ||
| 355 | 368 | } |
| 356 | 369 | #if defined(FOSSIL_ENABLE_SSL) |
| 357 | 370 | else if( 0 == fossil_strnicmp( zArg, "ssl\0", 4 ) ){ |
| 358 | 371 | rc = 1; |
| 359 | 372 | } |
| 373 | +#endif | |
| 374 | +#if defined(FOSSIL_ENABLE_TH1_HOOKS) | |
| 375 | + else if( 0 == fossil_strnicmp( zArg, "th1Hooks\0", 9 ) ){ | |
| 376 | + rc = 1; | |
| 377 | + } | |
| 360 | 378 | #endif |
| 361 | 379 | #if defined(FOSSIL_ENABLE_TCL) |
| 362 | 380 | else if( 0 == fossil_strnicmp( zArg, "tcl\0", 4 ) ){ |
| 363 | 381 | rc = 1; |
| 364 | 382 | } |
| @@ -1147,10 +1165,23 @@ | ||
| 1147 | 1165 | if( openRepository ){ |
| 1148 | 1166 | db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0); |
| 1149 | 1167 | } |
| 1150 | 1168 | db_open_config(0); |
| 1151 | 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 | +} | |
| 1152 | 1183 | |
| 1153 | 1184 | /* |
| 1154 | 1185 | ** Make sure the interpreter has been initialized. Initialize it if |
| 1155 | 1186 | ** it has not been already. |
| 1156 | 1187 | ** |
| @@ -1265,10 +1296,34 @@ | ||
| 1265 | 1296 | Th_Trace("set %h {%h}<br />\n", zName, zValue); |
| 1266 | 1297 | } |
| 1267 | 1298 | Th_SetVar(g.interp, zName, -1, zValue, strlen(zValue)); |
| 1268 | 1299 | } |
| 1269 | 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 | +} | |
| 1270 | 1325 | |
| 1271 | 1326 | /* |
| 1272 | 1327 | ** Store an integer value in a variable in the interpreter. |
| 1273 | 1328 | */ |
| 1274 | 1329 | void Th_StoreInt(const char *zName, int iValue){ |
| @@ -1362,10 +1417,162 @@ | ||
| 1362 | 1417 | if( z[0]!='>' ) return 0; |
| 1363 | 1418 | i += 2; |
| 1364 | 1419 | } |
| 1365 | 1420 | return i; |
| 1366 | 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 | |
| 1367 | 1574 | |
| 1368 | 1575 | /* |
| 1369 | 1576 | ** The z[] input contains text mixed with TH1 scripts. |
| 1370 | 1577 | ** The TH1 scripts are contained within <th1>...</th1>. |
| 1371 | 1578 | ** TH1 variables are $aaa or $<aaa>. The first form of |
| @@ -1462,5 +1669,36 @@ | ||
| 1462 | 1669 | rc = Th_Eval(g.interp, 0, g.argv[2], -1); |
| 1463 | 1670 | zRc = Th_ReturnCodeName(rc, 1); |
| 1464 | 1671 | fossil_print("%s%s%s\n", zRc, zRc ? ": " : "", Th_GetResult(g.interp, 0)); |
| 1465 | 1672 | Th_PrintTraceLog(); |
| 1466 | 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 | |
| 1467 | 1705 |
| --- 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 |
+56
| --- test/tester.tcl | ||
| +++ test/tester.tcl | ||
| @@ -181,10 +181,66 @@ | ||
| 181 | 181 | # Append all arguments into a single value and then returns it. |
| 182 | 182 | # |
| 183 | 183 | proc appendArgs {args} { |
| 184 | 184 | eval append result $args |
| 185 | 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 | +} | |
| 186 | 242 | |
| 187 | 243 | # Perform a test |
| 188 | 244 | # |
| 189 | 245 | set test_count 0 |
| 190 | 246 | proc test {name expr} { |
| 191 | 247 | |
| 192 | 248 | ADDED test/th1-hooks-input.txt |
| 193 | 249 | 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 |
+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 |
| --- 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 |
+10
| --- win/Makefile.mingw | ||
| +++ win/Makefile.mingw | ||
| @@ -47,10 +47,14 @@ | ||
| 47 | 47 | # FOSSIL_ENABLE_JSON = 1 |
| 48 | 48 | |
| 49 | 49 | #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto) |
| 50 | 50 | # |
| 51 | 51 | # FOSSIL_ENABLE_SSL = 1 |
| 52 | + | |
| 53 | +#### Enable hooks for commands and web pages via TH1 | |
| 54 | +# | |
| 55 | +# FOSSIL_ENABLE_TH1_HOOKS = 1 | |
| 52 | 56 | |
| 53 | 57 | #### Enable scripting support via Tcl/Tk |
| 54 | 58 | # |
| 55 | 59 | # FOSSIL_ENABLE_TCL = 1 |
| 56 | 60 | |
| @@ -176,10 +180,16 @@ | ||
| 176 | 180 | # With HTTPS support |
| 177 | 181 | ifdef FOSSIL_ENABLE_SSL |
| 178 | 182 | TCC += -DFOSSIL_ENABLE_SSL=1 |
| 179 | 183 | RCC += -DFOSSIL_ENABLE_SSL=1 |
| 180 | 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 | |
| 181 | 191 | |
| 182 | 192 | # With Tcl support |
| 183 | 193 | ifdef FOSSIL_ENABLE_TCL |
| 184 | 194 | TCC += -DFOSSIL_ENABLE_TCL=1 |
| 185 | 195 | RCC += -DFOSSIL_ENABLE_TCL=1 |
| 186 | 196 |
| --- 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 |
+10
| --- win/Makefile.mingw | ||
| +++ win/Makefile.mingw | ||
| @@ -47,10 +47,14 @@ | ||
| 47 | 47 | # FOSSIL_ENABLE_JSON = 1 |
| 48 | 48 | |
| 49 | 49 | #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto) |
| 50 | 50 | # |
| 51 | 51 | # FOSSIL_ENABLE_SSL = 1 |
| 52 | + | |
| 53 | +#### Enable hooks for commands and web pages via TH1 | |
| 54 | +# | |
| 55 | +# FOSSIL_ENABLE_TH1_HOOKS = 1 | |
| 52 | 56 | |
| 53 | 57 | #### Enable scripting support via Tcl/Tk |
| 54 | 58 | # |
| 55 | 59 | # FOSSIL_ENABLE_TCL = 1 |
| 56 | 60 | |
| @@ -176,10 +180,16 @@ | ||
| 176 | 180 | # With HTTPS support |
| 177 | 181 | ifdef FOSSIL_ENABLE_SSL |
| 178 | 182 | TCC += -DFOSSIL_ENABLE_SSL=1 |
| 179 | 183 | RCC += -DFOSSIL_ENABLE_SSL=1 |
| 180 | 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 | |
| 181 | 191 | |
| 182 | 192 | # With Tcl support |
| 183 | 193 | ifdef FOSSIL_ENABLE_TCL |
| 184 | 194 | TCC += -DFOSSIL_ENABLE_TCL=1 |
| 185 | 195 | RCC += -DFOSSIL_ENABLE_TCL=1 |
| 186 | 196 |
| --- 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 @@ | ||
| 47 | 47 | FOSSIL_ENABLE_JSON = 1 |
| 48 | 48 | |
| 49 | 49 | #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto) |
| 50 | 50 | # |
| 51 | 51 | FOSSIL_ENABLE_SSL = 1 |
| 52 | + | |
| 53 | +#### Enable hooks for commands and web pages via TH1 | |
| 54 | +# | |
| 55 | +FOSSIL_ENABLE_TH1_HOOKS = 1 | |
| 52 | 56 | |
| 53 | 57 | #### Enable scripting support via Tcl/Tk |
| 54 | 58 | # |
| 55 | 59 | FOSSIL_ENABLE_TCL = 1 |
| 56 | 60 | |
| @@ -176,10 +180,16 @@ | ||
| 176 | 180 | # With HTTPS support |
| 177 | 181 | ifdef FOSSIL_ENABLE_SSL |
| 178 | 182 | TCC += -DFOSSIL_ENABLE_SSL=1 |
| 179 | 183 | RCC += -DFOSSIL_ENABLE_SSL=1 |
| 180 | 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 | |
| 181 | 191 | |
| 182 | 192 | # With Tcl support |
| 183 | 193 | ifdef FOSSIL_ENABLE_TCL |
| 184 | 194 | TCC += -DFOSSIL_ENABLE_TCL=1 |
| 185 | 195 | RCC += -DFOSSIL_ENABLE_TCL=1 |
| 186 | 196 |
| --- 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 @@ | ||
| 47 | 47 | FOSSIL_ENABLE_JSON = 1 |
| 48 | 48 | |
| 49 | 49 | #### Enable HTTPS support via OpenSSL (links to libssl and libcrypto) |
| 50 | 50 | # |
| 51 | 51 | FOSSIL_ENABLE_SSL = 1 |
| 52 | + | |
| 53 | +#### Enable hooks for commands and web pages via TH1 | |
| 54 | +# | |
| 55 | +FOSSIL_ENABLE_TH1_HOOKS = 1 | |
| 52 | 56 | |
| 53 | 57 | #### Enable scripting support via Tcl/Tk |
| 54 | 58 | # |
| 55 | 59 | FOSSIL_ENABLE_TCL = 1 |
| 56 | 60 | |
| @@ -176,10 +180,16 @@ | ||
| 176 | 180 | # With HTTPS support |
| 177 | 181 | ifdef FOSSIL_ENABLE_SSL |
| 178 | 182 | TCC += -DFOSSIL_ENABLE_SSL=1 |
| 179 | 183 | RCC += -DFOSSIL_ENABLE_SSL=1 |
| 180 | 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 | |
| 181 | 191 | |
| 182 | 192 | # With Tcl support |
| 183 | 193 | ifdef FOSSIL_ENABLE_TCL |
| 184 | 194 | TCC += -DFOSSIL_ENABLE_TCL=1 |
| 185 | 195 | RCC += -DFOSSIL_ENABLE_TCL=1 |
| 186 | 196 |
| --- 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 |
+8
| --- win/Makefile.msc | ||
| +++ win/Makefile.msc | ||
| @@ -21,10 +21,13 @@ | ||
| 21 | 21 | # Uncomment to enable JSON API |
| 22 | 22 | # FOSSIL_ENABLE_JSON = 1 |
| 23 | 23 | |
| 24 | 24 | # Uncomment to enable SSL support |
| 25 | 25 | # FOSSIL_ENABLE_SSL = 1 |
| 26 | + | |
| 27 | +# Uncomment to enable TH1 hooks | |
| 28 | +# FOSSIL_ENABLE_TH1_HOOKS = 1 | |
| 26 | 29 | |
| 27 | 30 | # Uncomment to enable Tcl support |
| 28 | 31 | # FOSSIL_ENABLE_TCL = 1 |
| 29 | 32 | |
| 30 | 33 | !ifdef FOSSIL_ENABLE_SSL |
| @@ -79,10 +82,15 @@ | ||
| 79 | 82 | TCC = $(TCC) /DFOSSIL_ENABLE_SSL=1 |
| 80 | 83 | RCC = $(RCC) /DFOSSIL_ENABLE_SSL=1 |
| 81 | 84 | LIBS = $(LIBS) $(SSLLIB) |
| 82 | 85 | LIBDIR = $(LIBDIR) /LIBPATH:$(SSLLIBDIR) |
| 83 | 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 | |
| 84 | 92 | |
| 85 | 93 | !ifdef FOSSIL_ENABLE_TCL |
| 86 | 94 | TCC = $(TCC) /DFOSSIL_ENABLE_TCL=1 |
| 87 | 95 | RCC = $(RCC) /DFOSSIL_ENABLE_TCL=1 |
| 88 | 96 | TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1 |
| 89 | 97 |
| --- 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 |
+8
| --- win/Makefile.msc | ||
| +++ win/Makefile.msc | ||
| @@ -21,10 +21,13 @@ | ||
| 21 | 21 | # Uncomment to enable JSON API |
| 22 | 22 | # FOSSIL_ENABLE_JSON = 1 |
| 23 | 23 | |
| 24 | 24 | # Uncomment to enable SSL support |
| 25 | 25 | # FOSSIL_ENABLE_SSL = 1 |
| 26 | + | |
| 27 | +# Uncomment to enable TH1 hooks | |
| 28 | +# FOSSIL_ENABLE_TH1_HOOKS = 1 | |
| 26 | 29 | |
| 27 | 30 | # Uncomment to enable Tcl support |
| 28 | 31 | # FOSSIL_ENABLE_TCL = 1 |
| 29 | 32 | |
| 30 | 33 | !ifdef FOSSIL_ENABLE_SSL |
| @@ -79,10 +82,15 @@ | ||
| 79 | 82 | TCC = $(TCC) /DFOSSIL_ENABLE_SSL=1 |
| 80 | 83 | RCC = $(RCC) /DFOSSIL_ENABLE_SSL=1 |
| 81 | 84 | LIBS = $(LIBS) $(SSLLIB) |
| 82 | 85 | LIBDIR = $(LIBDIR) /LIBPATH:$(SSLLIBDIR) |
| 83 | 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 | |
| 84 | 92 | |
| 85 | 93 | !ifdef FOSSIL_ENABLE_TCL |
| 86 | 94 | TCC = $(TCC) /DFOSSIL_ENABLE_TCL=1 |
| 87 | 95 | RCC = $(RCC) /DFOSSIL_ENABLE_TCL=1 |
| 88 | 96 | TCC = $(TCC) /DFOSSIL_ENABLE_TCL_STUBS=1 |
| 89 | 97 |
| --- 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 |
+5
| --- win/fossil.rc | ||
| +++ win/fossil.rc | ||
| @@ -101,10 +101,15 @@ | ||
| 101 | 101 | VALUE "CommandLineIsUnicode", "Yes\0" |
| 102 | 102 | #endif /* defined(BROKEN_MINGW_CMDLINE) */ |
| 103 | 103 | #if defined(FOSSIL_ENABLE_SSL) |
| 104 | 104 | VALUE "SslEnabled", "Yes, " OPENSSL_VERSION_TEXT "\0" |
| 105 | 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 | |
| 106 | 111 | #if defined(FOSSIL_ENABLE_TCL) |
| 107 | 112 | VALUE "TclEnabled", "Yes, Tcl " TCL_PATCH_LEVEL "\0" |
| 108 | 113 | #if defined(USE_TCL_STUBS) |
| 109 | 114 | VALUE "UseTclStubsEnabled", "Yes\0" |
| 110 | 115 | #else |
| 111 | 116 |
| --- 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 |