Fossil SCM

merge trunk

jan.nijtmans 2013-02-23 21:35 ticket-d17d6e5b17 merge
Commit f1bb151e6f7a9e572c9e17c69240a4cb2c320f4a
+12 -2
--- src/cgi.c
+++ src/cgi.c
@@ -1272,11 +1272,16 @@
12721272
** The parent never returns from this procedure.
12731273
**
12741274
** Return 0 to each child as it runs. If unable to establish a
12751275
** listening socket, return non-zero.
12761276
*/
1277
-int cgi_http_server(int mnPort, int mxPort, char *zBrowser, int flags){
1277
+int cgi_http_server(
1278
+ int mnPort, int mxPort, /* Range of TCP ports to try */
1279
+ const char *zBrowser, /* Run this browser, if not NULL */
1280
+ const char *zIpAddr, /* Bind to this IP address, if not null */
1281
+ int flags /* HTTP_SERVER_* flags */
1282
+){
12781283
#if defined(_WIN32)
12791284
/* Use win32_http_server() instead */
12801285
fossil_exit(1);
12811286
#else
12821287
int listener = -1; /* The server socket */
@@ -1291,11 +1296,16 @@
12911296
int iPort = mnPort;
12921297
12931298
while( iPort<=mxPort ){
12941299
memset(&inaddr, 0, sizeof(inaddr));
12951300
inaddr.sin_family = AF_INET;
1296
- if( flags & HTTP_SERVER_LOCALHOST ){
1301
+ if( zIpAddr ){
1302
+ inaddr.sin_addr.s_addr = inet_addr(zIpAddr);
1303
+ if( inaddr.sin_addr.s_addr == (-1) ){
1304
+ fossil_fatal("not a valid IP address: %s", zIpAddr);
1305
+ }
1306
+ }else if( flags & HTTP_SERVER_LOCALHOST ){
12971307
inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
12981308
}else{
12991309
inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
13001310
}
13011311
inaddr.sin_port = htons(iPort);
13021312
--- src/cgi.c
+++ src/cgi.c
@@ -1272,11 +1272,16 @@
1272 ** The parent never returns from this procedure.
1273 **
1274 ** Return 0 to each child as it runs. If unable to establish a
1275 ** listening socket, return non-zero.
1276 */
1277 int cgi_http_server(int mnPort, int mxPort, char *zBrowser, int flags){
 
 
 
 
 
1278 #if defined(_WIN32)
1279 /* Use win32_http_server() instead */
1280 fossil_exit(1);
1281 #else
1282 int listener = -1; /* The server socket */
@@ -1291,11 +1296,16 @@
1291 int iPort = mnPort;
1292
1293 while( iPort<=mxPort ){
1294 memset(&inaddr, 0, sizeof(inaddr));
1295 inaddr.sin_family = AF_INET;
1296 if( flags & HTTP_SERVER_LOCALHOST ){
 
 
 
 
 
1297 inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1298 }else{
1299 inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
1300 }
1301 inaddr.sin_port = htons(iPort);
1302
--- src/cgi.c
+++ src/cgi.c
@@ -1272,11 +1272,16 @@
1272 ** The parent never returns from this procedure.
1273 **
1274 ** Return 0 to each child as it runs. If unable to establish a
1275 ** listening socket, return non-zero.
1276 */
1277 int cgi_http_server(
1278 int mnPort, int mxPort, /* Range of TCP ports to try */
1279 const char *zBrowser, /* Run this browser, if not NULL */
1280 const char *zIpAddr, /* Bind to this IP address, if not null */
1281 int flags /* HTTP_SERVER_* flags */
1282 ){
1283 #if defined(_WIN32)
1284 /* Use win32_http_server() instead */
1285 fossil_exit(1);
1286 #else
1287 int listener = -1; /* The server socket */
@@ -1291,11 +1296,16 @@
1296 int iPort = mnPort;
1297
1298 while( iPort<=mxPort ){
1299 memset(&inaddr, 0, sizeof(inaddr));
1300 inaddr.sin_family = AF_INET;
1301 if( zIpAddr ){
1302 inaddr.sin_addr.s_addr = inet_addr(zIpAddr);
1303 if( inaddr.sin_addr.s_addr == (-1) ){
1304 fossil_fatal("not a valid IP address: %s", zIpAddr);
1305 }
1306 }else if( flags & HTTP_SERVER_LOCALHOST ){
1307 inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1308 }else{
1309 inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
1310 }
1311 inaddr.sin_port = htons(iPort);
1312
--- src/checkin.c
+++ src/checkin.c
@@ -174,10 +174,11 @@
174174
if( showHdr && blob_size(&report)>0 ){
175175
fossil_print("Changes for %s at %s:\n", db_get("project-name","???"),
176176
g.zLocalRoot);
177177
}
178178
blob_write_to_file(&report, "-");
179
+ blob_reset(&report);
179180
}
180181
181182
/*
182183
** COMMAND: status
183184
**
184185
--- src/checkin.c
+++ src/checkin.c
@@ -174,10 +174,11 @@
174 if( showHdr && blob_size(&report)>0 ){
175 fossil_print("Changes for %s at %s:\n", db_get("project-name","???"),
176 g.zLocalRoot);
177 }
178 blob_write_to_file(&report, "-");
 
179 }
180
181 /*
182 ** COMMAND: status
183 **
184
--- src/checkin.c
+++ src/checkin.c
@@ -174,10 +174,11 @@
174 if( showHdr && blob_size(&report)>0 ){
175 fossil_print("Changes for %s at %s:\n", db_get("project-name","???"),
176 g.zLocalRoot);
177 }
178 blob_write_to_file(&report, "-");
179 blob_reset(&report);
180 }
181
182 /*
183 ** COMMAND: status
184 **
185
+3 -13
--- src/clone.c
+++ src/clone.c
@@ -99,11 +99,10 @@
9999
** See also: init
100100
*/
101101
void clone_cmd(void){
102102
char *zPassword;
103103
const char *zDefaultUser; /* Optional name of the default user */
104
- const char *zPw; /* The user clone password */
105104
int nErr = 0;
106105
int bPrivate = 0; /* Also clone private branches */
107106
108107
if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
109108
url_proxy_options();
@@ -115,23 +114,17 @@
115114
fossil_panic("file already exists: %s", g.argv[3]);
116115
}
117116
118117
zDefaultUser = find_option("admin-user","A",1);
119118
120
- url_parse(g.argv[2]);
119
+ url_parse(g.argv[2], URL_PROMPT_PW|URL_ASK_REMEMBER_PW);
121120
if( g.urlIsFile ){
122121
file_copy(g.urlName, g.argv[3]);
123122
db_close(1);
124123
db_open_repository(g.argv[3]);
125124
db_record_repository_filename(g.argv[3]);
126
- db_multi_exec(
127
- "REPLACE INTO config(name,value,mtime)"
128
- " VALUES('server-code', lower(hex(randomblob(20))),now());"
129
- "REPLACE INTO config(name,value,mtime)"
130
- " VALUES('last-sync-url', '%q',now());",
131
- g.urlCanonical
132
- );
125
+ url_remember();
133126
if( !bPrivate ) delete_private_content();
134127
shun_artifacts();
135128
db_create_default_users(1, zDefaultUser);
136129
if( zDefaultUser ){
137130
g.zLogin = zDefaultUser;
@@ -146,11 +139,11 @@
146139
db_record_repository_filename(g.argv[3]);
147140
db_initial_setup(0, 0, zDefaultUser, 0);
148141
user_select();
149142
db_set("content-schema", CONTENT_SCHEMA, 0);
150143
db_set("aux-schema", AUX_SCHEMA, 0);
151
- db_set("last-sync-url", g.argv[2], 0);
144
+ url_remember();
152145
if( g.zSSLIdentity!=0 ){
153146
/* If the --ssl-identity option was specified, store it as a setting */
154147
Blob fn;
155148
blob_zero(&fn);
156149
file_canonical_name(g.zSSLIdentity, &fn, 0);
@@ -177,12 +170,9 @@
177170
}
178171
db_begin_transaction();
179172
fossil_print("Rebuilding repository meta-data...\n");
180173
rebuild_db(0, 1, 0);
181174
fossil_print("project-id: %s\n", db_get("project-code", 0));
182
- fossil_print("server-id: %s\n", db_get("server-code", 0));
183175
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
184176
fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
185
- zPw = g.urlPasswd;
186
- if( !g.dontKeepUrl && zPw) db_set("last-sync-pw", obscure(zPw), 0);
187177
db_end_transaction(0);
188178
}
189179
--- src/clone.c
+++ src/clone.c
@@ -99,11 +99,10 @@
99 ** See also: init
100 */
101 void clone_cmd(void){
102 char *zPassword;
103 const char *zDefaultUser; /* Optional name of the default user */
104 const char *zPw; /* The user clone password */
105 int nErr = 0;
106 int bPrivate = 0; /* Also clone private branches */
107
108 if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
109 url_proxy_options();
@@ -115,23 +114,17 @@
115 fossil_panic("file already exists: %s", g.argv[3]);
116 }
117
118 zDefaultUser = find_option("admin-user","A",1);
119
120 url_parse(g.argv[2]);
121 if( g.urlIsFile ){
122 file_copy(g.urlName, g.argv[3]);
123 db_close(1);
124 db_open_repository(g.argv[3]);
125 db_record_repository_filename(g.argv[3]);
126 db_multi_exec(
127 "REPLACE INTO config(name,value,mtime)"
128 " VALUES('server-code', lower(hex(randomblob(20))),now());"
129 "REPLACE INTO config(name,value,mtime)"
130 " VALUES('last-sync-url', '%q',now());",
131 g.urlCanonical
132 );
133 if( !bPrivate ) delete_private_content();
134 shun_artifacts();
135 db_create_default_users(1, zDefaultUser);
136 if( zDefaultUser ){
137 g.zLogin = zDefaultUser;
@@ -146,11 +139,11 @@
146 db_record_repository_filename(g.argv[3]);
147 db_initial_setup(0, 0, zDefaultUser, 0);
148 user_select();
149 db_set("content-schema", CONTENT_SCHEMA, 0);
150 db_set("aux-schema", AUX_SCHEMA, 0);
151 db_set("last-sync-url", g.argv[2], 0);
152 if( g.zSSLIdentity!=0 ){
153 /* If the --ssl-identity option was specified, store it as a setting */
154 Blob fn;
155 blob_zero(&fn);
156 file_canonical_name(g.zSSLIdentity, &fn, 0);
@@ -177,12 +170,9 @@
177 }
178 db_begin_transaction();
179 fossil_print("Rebuilding repository meta-data...\n");
180 rebuild_db(0, 1, 0);
181 fossil_print("project-id: %s\n", db_get("project-code", 0));
182 fossil_print("server-id: %s\n", db_get("server-code", 0));
183 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
184 fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
185 zPw = g.urlPasswd;
186 if( !g.dontKeepUrl && zPw) db_set("last-sync-pw", obscure(zPw), 0);
187 db_end_transaction(0);
188 }
189
--- src/clone.c
+++ src/clone.c
@@ -99,11 +99,10 @@
99 ** See also: init
100 */
101 void clone_cmd(void){
102 char *zPassword;
103 const char *zDefaultUser; /* Optional name of the default user */
 
104 int nErr = 0;
105 int bPrivate = 0; /* Also clone private branches */
106
107 if( find_option("private",0,0)!=0 ) bPrivate = SYNC_PRIVATE;
108 url_proxy_options();
@@ -115,23 +114,17 @@
114 fossil_panic("file already exists: %s", g.argv[3]);
115 }
116
117 zDefaultUser = find_option("admin-user","A",1);
118
119 url_parse(g.argv[2], URL_PROMPT_PW|URL_ASK_REMEMBER_PW);
120 if( g.urlIsFile ){
121 file_copy(g.urlName, g.argv[3]);
122 db_close(1);
123 db_open_repository(g.argv[3]);
124 db_record_repository_filename(g.argv[3]);
125 url_remember();
 
 
 
 
 
 
126 if( !bPrivate ) delete_private_content();
127 shun_artifacts();
128 db_create_default_users(1, zDefaultUser);
129 if( zDefaultUser ){
130 g.zLogin = zDefaultUser;
@@ -146,11 +139,11 @@
139 db_record_repository_filename(g.argv[3]);
140 db_initial_setup(0, 0, zDefaultUser, 0);
141 user_select();
142 db_set("content-schema", CONTENT_SCHEMA, 0);
143 db_set("aux-schema", AUX_SCHEMA, 0);
144 url_remember();
145 if( g.zSSLIdentity!=0 ){
146 /* If the --ssl-identity option was specified, store it as a setting */
147 Blob fn;
148 blob_zero(&fn);
149 file_canonical_name(g.zSSLIdentity, &fn, 0);
@@ -177,12 +170,9 @@
170 }
171 db_begin_transaction();
172 fossil_print("Rebuilding repository meta-data...\n");
173 rebuild_db(0, 1, 0);
174 fossil_print("project-id: %s\n", db_get("project-code", 0));
 
175 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
176 fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword);
 
 
177 db_end_transaction(0);
178 }
179
+5 -13
--- src/configure.c
+++ src/configure.c
@@ -878,14 +878,14 @@
878878
if( strncmp(zMethod, "pull", n)==0
879879
|| strncmp(zMethod, "push", n)==0
880880
|| strncmp(zMethod, "sync", n)==0
881881
){
882882
int mask;
883
- const char *zServer;
884
- const char *zPw;
883
+ const char *zServer = 0;
885884
int legacyFlag = 0;
886885
int overwriteFlag = 0;
886
+
887887
if( zMethod[0]!='s' ) legacyFlag = find_option("legacy",0,0)!=0;
888888
if( strncmp(zMethod,"pull",n)==0 ){
889889
overwriteFlag = find_option("overwrite",0,0)!=0;
890890
}
891891
url_proxy_options();
@@ -893,21 +893,13 @@
893893
usage("pull AREA ?URL?");
894894
}
895895
mask = configure_name_to_mask(g.argv[3], 1);
896896
if( g.argc==5 ){
897897
zServer = g.argv[4];
898
- zPw = 0;
899
- g.dontKeepUrl = 1;
900
- }else{
901
- zServer = db_get("last-sync-url", 0);
902
- if( zServer==0 ){
903
- fossil_fatal("no server specified");
904
- }
905
- zPw = unobscure(db_get("last-sync-pw", 0));
906
- }
907
- url_parse(zServer);
908
- if( g.urlPasswd==0 && zPw ) g.urlPasswd = mprintf("%s", zPw);
898
+ }
899
+ url_parse(zServer, URL_PROMPT_PW);
900
+ if( g.urlProtocol==0 ) fossil_fatal("no server URL specified");
909901
user_select();
910902
url_enable_proxy("via proxy: ");
911903
if( legacyFlag ) mask |= CONFIGSET_OLDFORMAT;
912904
if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE;
913905
if( strncmp(zMethod, "push", n)==0 ){
914906
--- src/configure.c
+++ src/configure.c
@@ -878,14 +878,14 @@
878 if( strncmp(zMethod, "pull", n)==0
879 || strncmp(zMethod, "push", n)==0
880 || strncmp(zMethod, "sync", n)==0
881 ){
882 int mask;
883 const char *zServer;
884 const char *zPw;
885 int legacyFlag = 0;
886 int overwriteFlag = 0;
 
887 if( zMethod[0]!='s' ) legacyFlag = find_option("legacy",0,0)!=0;
888 if( strncmp(zMethod,"pull",n)==0 ){
889 overwriteFlag = find_option("overwrite",0,0)!=0;
890 }
891 url_proxy_options();
@@ -893,21 +893,13 @@
893 usage("pull AREA ?URL?");
894 }
895 mask = configure_name_to_mask(g.argv[3], 1);
896 if( g.argc==5 ){
897 zServer = g.argv[4];
898 zPw = 0;
899 g.dontKeepUrl = 1;
900 }else{
901 zServer = db_get("last-sync-url", 0);
902 if( zServer==0 ){
903 fossil_fatal("no server specified");
904 }
905 zPw = unobscure(db_get("last-sync-pw", 0));
906 }
907 url_parse(zServer);
908 if( g.urlPasswd==0 && zPw ) g.urlPasswd = mprintf("%s", zPw);
909 user_select();
910 url_enable_proxy("via proxy: ");
911 if( legacyFlag ) mask |= CONFIGSET_OLDFORMAT;
912 if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE;
913 if( strncmp(zMethod, "push", n)==0 ){
914
--- src/configure.c
+++ src/configure.c
@@ -878,14 +878,14 @@
878 if( strncmp(zMethod, "pull", n)==0
879 || strncmp(zMethod, "push", n)==0
880 || strncmp(zMethod, "sync", n)==0
881 ){
882 int mask;
883 const char *zServer = 0;
 
884 int legacyFlag = 0;
885 int overwriteFlag = 0;
886
887 if( zMethod[0]!='s' ) legacyFlag = find_option("legacy",0,0)!=0;
888 if( strncmp(zMethod,"pull",n)==0 ){
889 overwriteFlag = find_option("overwrite",0,0)!=0;
890 }
891 url_proxy_options();
@@ -893,21 +893,13 @@
893 usage("pull AREA ?URL?");
894 }
895 mask = configure_name_to_mask(g.argv[3], 1);
896 if( g.argc==5 ){
897 zServer = g.argv[4];
898 }
899 url_parse(zServer, URL_PROMPT_PW);
900 if( g.urlProtocol==0 ) fossil_fatal("no server URL specified");
 
 
 
 
 
 
 
 
901 user_select();
902 url_enable_proxy("via proxy: ");
903 if( legacyFlag ) mask |= CONFIGSET_OLDFORMAT;
904 if( overwriteFlag ) mask |= CONFIGSET_OVERWRITE;
905 if( strncmp(zMethod, "push", n)==0 ){
906
+40 -9
--- src/db.c
+++ src/db.c
@@ -1262,17 +1262,17 @@
12621262
"UPDATE user SET cap='s', pw=lower(hex(randomblob(3)))"
12631263
" WHERE login=%Q", zUser
12641264
);
12651265
if( !setupUserOnly ){
12661266
db_multi_exec(
1267
- "INSERT INTO user(login,pw,cap,info)"
1267
+ "INSERT OR IGNORE INTO user(login,pw,cap,info)"
12681268
" VALUES('anonymous',hex(randomblob(8)),'hmncz','Anon');"
1269
- "INSERT INTO user(login,pw,cap,info)"
1269
+ "INSERT OR IGNORE INTO user(login,pw,cap,info)"
12701270
" VALUES('nobody','','gjor','Nobody');"
1271
- "INSERT INTO user(login,pw,cap,info)"
1271
+ "INSERT OR IGNORE INTO user(login,pw,cap,info)"
12721272
" VALUES('developer','','dei','Dev');"
1273
- "INSERT INTO user(login,pw,cap,info)"
1273
+ "INSERT OR IGNORE INTO user(login,pw,cap,info)"
12741274
" VALUES('reader','','kptw','Reader');"
12751275
);
12761276
}
12771277
}
12781278
@@ -1771,11 +1771,12 @@
17711771
db_swap_connections();
17721772
z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName);
17731773
db_swap_connections();
17741774
}
17751775
if( ctrlSetting!=0 && ctrlSetting->versionable && g.localOpen ){
1776
- /* This is a versionable setting, try and get the info from a checked out file */
1776
+ /* This is a versionable setting, try and get the info from a
1777
+ ** checked out file */
17771778
z = db_get_do_versionable(zName, z);
17781779
}
17791780
if( z==0 ){
17801781
z = zDefault;
17811782
}
@@ -1872,10 +1873,31 @@
18721873
return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName);
18731874
}
18741875
void db_lset_int(const char *zName, int value){
18751876
db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
18761877
}
1878
+
1879
+/*
1880
+** Returns non-0 if the database (which must be open) table identified
1881
+** by zTableName has a column named zColName (case-sensitive), else
1882
+** returns 0.
1883
+*/
1884
+int db_table_has_column( char const *zTableName, char const *zColName ){
1885
+ Stmt q = empty_Stmt;
1886
+ int rc = 0;
1887
+ db_prepare( &q, "PRAGMA table_info(%Q)", zTableName );
1888
+ while(SQLITE_ROW == db_step(&q)){
1889
+ /* Columns: (cid, name, type, notnull, dflt_value, pk) */
1890
+ char const * zCol = db_column_text(&q, 1);
1891
+ if(0==fossil_strcmp(zColName, zCol)){
1892
+ rc = 1;
1893
+ break;
1894
+ }
1895
+ }
1896
+ db_finalize(&q);
1897
+ return rc;
1898
+}
18771899
18781900
/*
18791901
** Record the name of a local repository in the global_config() database.
18801902
** The repository filename %s is recorded as an entry with a "name" field
18811903
** of the following form:
@@ -1963,11 +1985,15 @@
19631985
#if defined(_WIN32)
19641986
# define LOCALDB_NAME "./_FOSSIL_"
19651987
#else
19661988
# define LOCALDB_NAME "./.fslckout"
19671989
#endif
1968
- db_init_database(LOCALDB_NAME, zLocalSchema, (char*)0);
1990
+ db_init_database(LOCALDB_NAME, zLocalSchema,
1991
+#ifdef FOSSIL_LOCAL_WAL
1992
+ "COMMIT; PRAGMA journal_mode=WAL; BEGIN;",
1993
+#endif
1994
+ (char*)0);
19691995
db_delete_on_failure(LOCALDB_NAME);
19701996
db_open_local();
19711997
db_lset("repository", g.argv[2]);
19721998
db_record_repository_filename(blob_str(&path));
19731999
vid = db_int(0, "SELECT pid FROM plink y"
@@ -1996,11 +2022,14 @@
19962022
}
19972023
19982024
/*
19992025
** Print the value of a setting named zName
20002026
*/
2001
-static void print_setting(const struct stControlSettings *ctrlSetting, int localOpen){
2027
+static void print_setting(
2028
+ const struct stControlSettings *ctrlSetting,
2029
+ int localOpen
2030
+){
20022031
Stmt q;
20032032
if( g.repositoryOpen ){
20042033
db_prepare(&q,
20052034
"SELECT '(local)', value FROM config WHERE name=%Q"
20062035
" UNION ALL "
@@ -2021,13 +2050,15 @@
20212050
}
20222051
if( ctrlSetting->versionable && localOpen ){
20232052
/* Check to see if this is overridden by a versionable settings file */
20242053
Blob versionedPathname;
20252054
blob_zero(&versionedPathname);
2026
- blob_appendf(&versionedPathname, "%s/.fossil-settings/%s", g.zLocalRoot, ctrlSetting->name);
2055
+ blob_appendf(&versionedPathname, "%s/.fossil-settings/%s",
2056
+ g.zLocalRoot, ctrlSetting->name);
20272057
if( file_size(blob_str(&versionedPathname))>=0 ){
2028
- fossil_print(" (overridden by contents of file .fossil-settings/%s)\n", ctrlSetting->name);
2058
+ fossil_print(" (overridden by contents of file .fossil-settings/%s)\n",
2059
+ ctrlSetting->name);
20292060
}
20302061
}
20312062
db_finalize(&q);
20322063
}
20332064
20342065
--- src/db.c
+++ src/db.c
@@ -1262,17 +1262,17 @@
1262 "UPDATE user SET cap='s', pw=lower(hex(randomblob(3)))"
1263 " WHERE login=%Q", zUser
1264 );
1265 if( !setupUserOnly ){
1266 db_multi_exec(
1267 "INSERT INTO user(login,pw,cap,info)"
1268 " VALUES('anonymous',hex(randomblob(8)),'hmncz','Anon');"
1269 "INSERT INTO user(login,pw,cap,info)"
1270 " VALUES('nobody','','gjor','Nobody');"
1271 "INSERT INTO user(login,pw,cap,info)"
1272 " VALUES('developer','','dei','Dev');"
1273 "INSERT INTO user(login,pw,cap,info)"
1274 " VALUES('reader','','kptw','Reader');"
1275 );
1276 }
1277 }
1278
@@ -1771,11 +1771,12 @@
1771 db_swap_connections();
1772 z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName);
1773 db_swap_connections();
1774 }
1775 if( ctrlSetting!=0 && ctrlSetting->versionable && g.localOpen ){
1776 /* This is a versionable setting, try and get the info from a checked out file */
 
1777 z = db_get_do_versionable(zName, z);
1778 }
1779 if( z==0 ){
1780 z = zDefault;
1781 }
@@ -1872,10 +1873,31 @@
1872 return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName);
1873 }
1874 void db_lset_int(const char *zName, int value){
1875 db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
1876 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1877
1878 /*
1879 ** Record the name of a local repository in the global_config() database.
1880 ** The repository filename %s is recorded as an entry with a "name" field
1881 ** of the following form:
@@ -1963,11 +1985,15 @@
1963 #if defined(_WIN32)
1964 # define LOCALDB_NAME "./_FOSSIL_"
1965 #else
1966 # define LOCALDB_NAME "./.fslckout"
1967 #endif
1968 db_init_database(LOCALDB_NAME, zLocalSchema, (char*)0);
 
 
 
 
1969 db_delete_on_failure(LOCALDB_NAME);
1970 db_open_local();
1971 db_lset("repository", g.argv[2]);
1972 db_record_repository_filename(blob_str(&path));
1973 vid = db_int(0, "SELECT pid FROM plink y"
@@ -1996,11 +2022,14 @@
1996 }
1997
1998 /*
1999 ** Print the value of a setting named zName
2000 */
2001 static void print_setting(const struct stControlSettings *ctrlSetting, int localOpen){
 
 
 
2002 Stmt q;
2003 if( g.repositoryOpen ){
2004 db_prepare(&q,
2005 "SELECT '(local)', value FROM config WHERE name=%Q"
2006 " UNION ALL "
@@ -2021,13 +2050,15 @@
2021 }
2022 if( ctrlSetting->versionable && localOpen ){
2023 /* Check to see if this is overridden by a versionable settings file */
2024 Blob versionedPathname;
2025 blob_zero(&versionedPathname);
2026 blob_appendf(&versionedPathname, "%s/.fossil-settings/%s", g.zLocalRoot, ctrlSetting->name);
 
2027 if( file_size(blob_str(&versionedPathname))>=0 ){
2028 fossil_print(" (overridden by contents of file .fossil-settings/%s)\n", ctrlSetting->name);
 
2029 }
2030 }
2031 db_finalize(&q);
2032 }
2033
2034
--- src/db.c
+++ src/db.c
@@ -1262,17 +1262,17 @@
1262 "UPDATE user SET cap='s', pw=lower(hex(randomblob(3)))"
1263 " WHERE login=%Q", zUser
1264 );
1265 if( !setupUserOnly ){
1266 db_multi_exec(
1267 "INSERT OR IGNORE INTO user(login,pw,cap,info)"
1268 " VALUES('anonymous',hex(randomblob(8)),'hmncz','Anon');"
1269 "INSERT OR IGNORE INTO user(login,pw,cap,info)"
1270 " VALUES('nobody','','gjor','Nobody');"
1271 "INSERT OR IGNORE INTO user(login,pw,cap,info)"
1272 " VALUES('developer','','dei','Dev');"
1273 "INSERT OR IGNORE INTO user(login,pw,cap,info)"
1274 " VALUES('reader','','kptw','Reader');"
1275 );
1276 }
1277 }
1278
@@ -1771,11 +1771,12 @@
1771 db_swap_connections();
1772 z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName);
1773 db_swap_connections();
1774 }
1775 if( ctrlSetting!=0 && ctrlSetting->versionable && g.localOpen ){
1776 /* This is a versionable setting, try and get the info from a
1777 ** checked out file */
1778 z = db_get_do_versionable(zName, z);
1779 }
1780 if( z==0 ){
1781 z = zDefault;
1782 }
@@ -1872,10 +1873,31 @@
1873 return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName);
1874 }
1875 void db_lset_int(const char *zName, int value){
1876 db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
1877 }
1878
1879 /*
1880 ** Returns non-0 if the database (which must be open) table identified
1881 ** by zTableName has a column named zColName (case-sensitive), else
1882 ** returns 0.
1883 */
1884 int db_table_has_column( char const *zTableName, char const *zColName ){
1885 Stmt q = empty_Stmt;
1886 int rc = 0;
1887 db_prepare( &q, "PRAGMA table_info(%Q)", zTableName );
1888 while(SQLITE_ROW == db_step(&q)){
1889 /* Columns: (cid, name, type, notnull, dflt_value, pk) */
1890 char const * zCol = db_column_text(&q, 1);
1891 if(0==fossil_strcmp(zColName, zCol)){
1892 rc = 1;
1893 break;
1894 }
1895 }
1896 db_finalize(&q);
1897 return rc;
1898 }
1899
1900 /*
1901 ** Record the name of a local repository in the global_config() database.
1902 ** The repository filename %s is recorded as an entry with a "name" field
1903 ** of the following form:
@@ -1963,11 +1985,15 @@
1985 #if defined(_WIN32)
1986 # define LOCALDB_NAME "./_FOSSIL_"
1987 #else
1988 # define LOCALDB_NAME "./.fslckout"
1989 #endif
1990 db_init_database(LOCALDB_NAME, zLocalSchema,
1991 #ifdef FOSSIL_LOCAL_WAL
1992 "COMMIT; PRAGMA journal_mode=WAL; BEGIN;",
1993 #endif
1994 (char*)0);
1995 db_delete_on_failure(LOCALDB_NAME);
1996 db_open_local();
1997 db_lset("repository", g.argv[2]);
1998 db_record_repository_filename(blob_str(&path));
1999 vid = db_int(0, "SELECT pid FROM plink y"
@@ -1996,11 +2022,14 @@
2022 }
2023
2024 /*
2025 ** Print the value of a setting named zName
2026 */
2027 static void print_setting(
2028 const struct stControlSettings *ctrlSetting,
2029 int localOpen
2030 ){
2031 Stmt q;
2032 if( g.repositoryOpen ){
2033 db_prepare(&q,
2034 "SELECT '(local)', value FROM config WHERE name=%Q"
2035 " UNION ALL "
@@ -2021,13 +2050,15 @@
2050 }
2051 if( ctrlSetting->versionable && localOpen ){
2052 /* Check to see if this is overridden by a versionable settings file */
2053 Blob versionedPathname;
2054 blob_zero(&versionedPathname);
2055 blob_appendf(&versionedPathname, "%s/.fossil-settings/%s",
2056 g.zLocalRoot, ctrlSetting->name);
2057 if( file_size(blob_str(&versionedPathname))>=0 ){
2058 fossil_print(" (overridden by contents of file .fossil-settings/%s)\n",
2059 ctrlSetting->name);
2060 }
2061 }
2062 db_finalize(&q);
2063 }
2064
2065
+14 -19
--- src/diff.c
+++ src/diff.c
@@ -363,38 +363,33 @@
363363
}
364364
365365
/*
366366
** This function returns non-zero if the blob starts with a UTF-16
367367
** byte-order-mark (BOM), either in the endianness of the machine
368
-** or in reversed byte order.
368
+** or in reversed byte order. The UTF-32 BOM is ruled out by checking
369
+** if the UTF-16 BOM is not immediately followed by (utf16) 0.
370
+** pnByte and pbReverse are only set when the function returns 1.
369371
*/
370372
int starts_with_utf16_bom(
371373
const Blob *pContent, /* IN: Blob content to perform BOM detection on. */
372374
int *pnByte, /* OUT: The number of bytes used for the BOM. */
373375
int *pbReverse /* OUT: Non-zero for BOM in reverse byte-order. */
374376
){
375
- const char *z = blob_buffer(pContent);
376
- int bomSize = 2;
377
- static const unsigned short bom = 0xfeff;
378
- static const unsigned short bom_reversed = 0xfffe;
379
- static const unsigned short null = 0;
380
- int size;
381
-
382
- if( pnByte ) *pnByte = bomSize;
383
- if( pbReverse ) *pbReverse = -1; /* Unknown. */
384
- size = blob_size(pContent);
385
- if( (size<bomSize) || (size%2) ) return 0;
386
- if( memcmp(z, &bom_reversed, bomSize)==0 ){
377
+ const unsigned short *z = (unsigned short *)blob_buffer(pContent);
378
+ int size = blob_size(pContent);
379
+
380
+ if( (size<2) || (size%2)
381
+ || (size>=4 && z[1]==0) ) return 0;
382
+ if( z[0] == 0xfffe ){
387383
if( pbReverse ) *pbReverse = 1;
388
- if( size<(2*bomSize) ) return 1;
389
- if( memcmp(z+bomSize, &null, bomSize)!=0 ) return 1;
390
- }else if( memcmp(z, &bom, bomSize)==0 ){
384
+ }else if( z[0] == 0xfeff ){
391385
if( pbReverse ) *pbReverse = 0;
392
- if( size<(2*bomSize) ) return 1;
393
- if( memcmp(z+bomSize, &null, bomSize)!=0 ) return 1;
386
+ }else{
387
+ return 0;
394388
}
395
- return 0;
389
+ if( pnByte ) *pnByte = 2;
390
+ return 1;
396391
}
397392
398393
/*
399394
** Return true if two DLine elements are identical.
400395
*/
401396
--- src/diff.c
+++ src/diff.c
@@ -363,38 +363,33 @@
363 }
364
365 /*
366 ** This function returns non-zero if the blob starts with a UTF-16
367 ** byte-order-mark (BOM), either in the endianness of the machine
368 ** or in reversed byte order.
 
 
369 */
370 int starts_with_utf16_bom(
371 const Blob *pContent, /* IN: Blob content to perform BOM detection on. */
372 int *pnByte, /* OUT: The number of bytes used for the BOM. */
373 int *pbReverse /* OUT: Non-zero for BOM in reverse byte-order. */
374 ){
375 const char *z = blob_buffer(pContent);
376 int bomSize = 2;
377 static const unsigned short bom = 0xfeff;
378 static const unsigned short bom_reversed = 0xfffe;
379 static const unsigned short null = 0;
380 int size;
381
382 if( pnByte ) *pnByte = bomSize;
383 if( pbReverse ) *pbReverse = -1; /* Unknown. */
384 size = blob_size(pContent);
385 if( (size<bomSize) || (size%2) ) return 0;
386 if( memcmp(z, &bom_reversed, bomSize)==0 ){
387 if( pbReverse ) *pbReverse = 1;
388 if( size<(2*bomSize) ) return 1;
389 if( memcmp(z+bomSize, &null, bomSize)!=0 ) return 1;
390 }else if( memcmp(z, &bom, bomSize)==0 ){
391 if( pbReverse ) *pbReverse = 0;
392 if( size<(2*bomSize) ) return 1;
393 if( memcmp(z+bomSize, &null, bomSize)!=0 ) return 1;
394 }
395 return 0;
 
396 }
397
398 /*
399 ** Return true if two DLine elements are identical.
400 */
401
--- src/diff.c
+++ src/diff.c
@@ -363,38 +363,33 @@
363 }
364
365 /*
366 ** This function returns non-zero if the blob starts with a UTF-16
367 ** byte-order-mark (BOM), either in the endianness of the machine
368 ** or in reversed byte order. The UTF-32 BOM is ruled out by checking
369 ** if the UTF-16 BOM is not immediately followed by (utf16) 0.
370 ** pnByte and pbReverse are only set when the function returns 1.
371 */
372 int starts_with_utf16_bom(
373 const Blob *pContent, /* IN: Blob content to perform BOM detection on. */
374 int *pnByte, /* OUT: The number of bytes used for the BOM. */
375 int *pbReverse /* OUT: Non-zero for BOM in reverse byte-order. */
376 ){
377 const unsigned short *z = (unsigned short *)blob_buffer(pContent);
378 int size = blob_size(pContent);
379
380 if( (size<2) || (size%2)
381 || (size>=4 && z[1]==0) ) return 0;
382 if( z[0] == 0xfffe ){
 
 
 
 
 
 
383 if( pbReverse ) *pbReverse = 1;
384 }else if( z[0] == 0xfeff ){
 
 
385 if( pbReverse ) *pbReverse = 0;
386 }else{
387 return 0;
388 }
389 if( pnByte ) *pnByte = 2;
390 return 1;
391 }
392
393 /*
394 ** Return true if two DLine elements are identical.
395 */
396
+2 -2
--- src/http.c
+++ src/http.c
@@ -60,11 +60,10 @@
6060
zPw = 0;
6161
}else{
6262
/* Password failure while doing a sync from the command-line interface */
6363
url_prompt_for_password();
6464
zPw = g.urlPasswd;
65
- if( !g.dontKeepUrl ) db_set("last-sync-pw", obscure(zPw), 0);
6665
}
6766
6867
/* If the first character of the password is "#", then that character is
6968
** not really part of the password - it is an indicator that we should
7069
** use Basic Authentication. So skip that character.
@@ -72,10 +71,11 @@
7271
if( zPw && zPw[0]=='#' ) zPw++;
7372
7473
/* The login card wants the SHA1 hash of the password, so convert the
7574
** password to its SHA1 hash it it isn't already a SHA1 hash.
7675
*/
76
+ /* fossil_print("\nzPw=[%s]\n", zPw); // TESTING ONLY */
7777
if( zPw && zPw[0] ) zPw = sha1_shared_secret(zPw, zLogin, 0);
7878
7979
blob_append(&pw, zPw, -1);
8080
sha1sum_blob(&pw, &sig);
8181
blob_appendf(pLogin, "login %F %b %b\n", zLogin, &nonce, &sig);
@@ -243,11 +243,11 @@
243243
while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){
244244
j -= 4;
245245
zLine[j] = 0;
246246
}
247247
fossil_print("redirect to %s\n", &zLine[i]);
248
- url_parse(&zLine[i]);
248
+ url_parse(&zLine[i], 0);
249249
transport_close();
250250
return http_exchange(pSend, pReply, useLogin, maxRedirect);
251251
}else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
252252
if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
253253
isCompressed = 0;
254254
--- src/http.c
+++ src/http.c
@@ -60,11 +60,10 @@
60 zPw = 0;
61 }else{
62 /* Password failure while doing a sync from the command-line interface */
63 url_prompt_for_password();
64 zPw = g.urlPasswd;
65 if( !g.dontKeepUrl ) db_set("last-sync-pw", obscure(zPw), 0);
66 }
67
68 /* If the first character of the password is "#", then that character is
69 ** not really part of the password - it is an indicator that we should
70 ** use Basic Authentication. So skip that character.
@@ -72,10 +71,11 @@
72 if( zPw && zPw[0]=='#' ) zPw++;
73
74 /* The login card wants the SHA1 hash of the password, so convert the
75 ** password to its SHA1 hash it it isn't already a SHA1 hash.
76 */
 
77 if( zPw && zPw[0] ) zPw = sha1_shared_secret(zPw, zLogin, 0);
78
79 blob_append(&pw, zPw, -1);
80 sha1sum_blob(&pw, &sig);
81 blob_appendf(pLogin, "login %F %b %b\n", zLogin, &nonce, &sig);
@@ -243,11 +243,11 @@
243 while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){
244 j -= 4;
245 zLine[j] = 0;
246 }
247 fossil_print("redirect to %s\n", &zLine[i]);
248 url_parse(&zLine[i]);
249 transport_close();
250 return http_exchange(pSend, pReply, useLogin, maxRedirect);
251 }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
252 if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
253 isCompressed = 0;
254
--- src/http.c
+++ src/http.c
@@ -60,11 +60,10 @@
60 zPw = 0;
61 }else{
62 /* Password failure while doing a sync from the command-line interface */
63 url_prompt_for_password();
64 zPw = g.urlPasswd;
 
65 }
66
67 /* If the first character of the password is "#", then that character is
68 ** not really part of the password - it is an indicator that we should
69 ** use Basic Authentication. So skip that character.
@@ -72,10 +71,11 @@
71 if( zPw && zPw[0]=='#' ) zPw++;
72
73 /* The login card wants the SHA1 hash of the password, so convert the
74 ** password to its SHA1 hash it it isn't already a SHA1 hash.
75 */
76 /* fossil_print("\nzPw=[%s]\n", zPw); // TESTING ONLY */
77 if( zPw && zPw[0] ) zPw = sha1_shared_secret(zPw, zLogin, 0);
78
79 blob_append(&pw, zPw, -1);
80 sha1sum_blob(&pw, &sig);
81 blob_appendf(pLogin, "login %F %b %b\n", zLogin, &nonce, &sig);
@@ -243,11 +243,11 @@
243 while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){
244 j -= 4;
245 zLine[j] = 0;
246 }
247 fossil_print("redirect to %s\n", &zLine[i]);
248 url_parse(&zLine[i], 0);
249 transport_close();
250 return http_exchange(pSend, pReply, useLogin, maxRedirect);
251 }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
252 if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
253 isCompressed = 0;
254
+11 -3
--- src/info.c
+++ src/info.c
@@ -209,11 +209,11 @@
209209
vid = g.localOpen ? db_lget_int("checkout", 0) : 0;
210210
if( vid ){
211211
show_common_info(vid, "checkout:", 1, 1);
212212
}
213213
fossil_print("checkins: %d\n",
214
- db_int(-1, "SELECT count(distinct mid) FROM mlink /*scan*/"));
214
+ db_int(-1, "SELECT count(*) FROM event WHERE type='ci' /*scan*/"));
215215
}else{
216216
int rid;
217217
rid = name_to_rid(g.argv[2]);
218218
if( rid==0 ){
219219
fossil_panic("no such object: %s\n", g.argv[2]);
@@ -1665,11 +1665,11 @@
16651665
const char *zUuid;
16661666
char zTktName[UUID_SIZE+1];
16671667
Manifest *pTktChng;
16681668
int modPending;
16691669
const char *zModAction;
1670
-
1670
+ char *zTktTitle;
16711671
login_check_credentials();
16721672
if( !g.perm.RdTkt ){ login_needed(); return; }
16731673
rid = name_to_rid_www("name");
16741674
if( rid==0 ){ fossil_redirect_home(); }
16751675
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
@@ -1694,10 +1694,13 @@
16941694
}
16951695
if( strcmp(zModAction,"approve")==0 ){
16961696
moderation_approve(rid);
16971697
}
16981698
}
1699
+ zTktTitle = db_table_has_column( "ticket", "title" )
1700
+ ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName)
1701
+ : 0;
16991702
style_header("Ticket Change Details");
17001703
style_submenu_element("Raw", "Raw", "%R/artifact/%S", zUuid);
17011704
style_submenu_element("History", "History", "%R/tkthistory/%s", zTktName);
17021705
style_submenu_element("Page", "Page", "%R/tktview/%t", zTktName);
17031706
style_submenu_element("Timeline", "Timeline", "%R/tkttimeline/%t", zTktName);
@@ -1718,17 +1721,22 @@
17181721
modPending = moderation_pending(rid);
17191722
if( modPending ){
17201723
@ <span class="modpending">*** Awaiting Moderator Approval ***</span>
17211724
}
17221725
@ <tr><th>Ticket:</th>
1723
- @ <td>%z(href("%R/tktview/%s",zTktName))%s(zTktName)</a></td></tr>
1726
+ @ <td>%z(href("%R/tktview/%s",zTktName))%s(zTktName)</a>
1727
+ if(zTktTitle){
1728
+ @<br>%h(zTktTitle)
1729
+ }
1730
+ @</td></tr>
17241731
@ <tr><th>Date:</th><td>
17251732
hyperlink_to_date(zDate, "</td></tr>");
17261733
@ <tr><th>User:</th><td>
17271734
hyperlink_to_user(pTktChng->zUser, zDate, "</td></tr>");
17281735
@ </table>
17291736
free(zDate);
1737
+ free(zTktTitle);
17301738
17311739
if( g.perm.ModTkt && modPending ){
17321740
@ <div class="section">Moderation</div>
17331741
@ <blockquote>
17341742
@ <form method="POST" action="%R/tinfo/%s(zUuid)">
17351743
--- src/info.c
+++ src/info.c
@@ -209,11 +209,11 @@
209 vid = g.localOpen ? db_lget_int("checkout", 0) : 0;
210 if( vid ){
211 show_common_info(vid, "checkout:", 1, 1);
212 }
213 fossil_print("checkins: %d\n",
214 db_int(-1, "SELECT count(distinct mid) FROM mlink /*scan*/"));
215 }else{
216 int rid;
217 rid = name_to_rid(g.argv[2]);
218 if( rid==0 ){
219 fossil_panic("no such object: %s\n", g.argv[2]);
@@ -1665,11 +1665,11 @@
1665 const char *zUuid;
1666 char zTktName[UUID_SIZE+1];
1667 Manifest *pTktChng;
1668 int modPending;
1669 const char *zModAction;
1670
1671 login_check_credentials();
1672 if( !g.perm.RdTkt ){ login_needed(); return; }
1673 rid = name_to_rid_www("name");
1674 if( rid==0 ){ fossil_redirect_home(); }
1675 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
@@ -1694,10 +1694,13 @@
1694 }
1695 if( strcmp(zModAction,"approve")==0 ){
1696 moderation_approve(rid);
1697 }
1698 }
 
 
 
1699 style_header("Ticket Change Details");
1700 style_submenu_element("Raw", "Raw", "%R/artifact/%S", zUuid);
1701 style_submenu_element("History", "History", "%R/tkthistory/%s", zTktName);
1702 style_submenu_element("Page", "Page", "%R/tktview/%t", zTktName);
1703 style_submenu_element("Timeline", "Timeline", "%R/tkttimeline/%t", zTktName);
@@ -1718,17 +1721,22 @@
1718 modPending = moderation_pending(rid);
1719 if( modPending ){
1720 @ <span class="modpending">*** Awaiting Moderator Approval ***</span>
1721 }
1722 @ <tr><th>Ticket:</th>
1723 @ <td>%z(href("%R/tktview/%s",zTktName))%s(zTktName)</a></td></tr>
 
 
 
 
1724 @ <tr><th>Date:</th><td>
1725 hyperlink_to_date(zDate, "</td></tr>");
1726 @ <tr><th>User:</th><td>
1727 hyperlink_to_user(pTktChng->zUser, zDate, "</td></tr>");
1728 @ </table>
1729 free(zDate);
 
1730
1731 if( g.perm.ModTkt && modPending ){
1732 @ <div class="section">Moderation</div>
1733 @ <blockquote>
1734 @ <form method="POST" action="%R/tinfo/%s(zUuid)">
1735
--- src/info.c
+++ src/info.c
@@ -209,11 +209,11 @@
209 vid = g.localOpen ? db_lget_int("checkout", 0) : 0;
210 if( vid ){
211 show_common_info(vid, "checkout:", 1, 1);
212 }
213 fossil_print("checkins: %d\n",
214 db_int(-1, "SELECT count(*) FROM event WHERE type='ci' /*scan*/"));
215 }else{
216 int rid;
217 rid = name_to_rid(g.argv[2]);
218 if( rid==0 ){
219 fossil_panic("no such object: %s\n", g.argv[2]);
@@ -1665,11 +1665,11 @@
1665 const char *zUuid;
1666 char zTktName[UUID_SIZE+1];
1667 Manifest *pTktChng;
1668 int modPending;
1669 const char *zModAction;
1670 char *zTktTitle;
1671 login_check_credentials();
1672 if( !g.perm.RdTkt ){ login_needed(); return; }
1673 rid = name_to_rid_www("name");
1674 if( rid==0 ){ fossil_redirect_home(); }
1675 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
@@ -1694,10 +1694,13 @@
1694 }
1695 if( strcmp(zModAction,"approve")==0 ){
1696 moderation_approve(rid);
1697 }
1698 }
1699 zTktTitle = db_table_has_column( "ticket", "title" )
1700 ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName)
1701 : 0;
1702 style_header("Ticket Change Details");
1703 style_submenu_element("Raw", "Raw", "%R/artifact/%S", zUuid);
1704 style_submenu_element("History", "History", "%R/tkthistory/%s", zTktName);
1705 style_submenu_element("Page", "Page", "%R/tktview/%t", zTktName);
1706 style_submenu_element("Timeline", "Timeline", "%R/tkttimeline/%t", zTktName);
@@ -1718,17 +1721,22 @@
1721 modPending = moderation_pending(rid);
1722 if( modPending ){
1723 @ <span class="modpending">*** Awaiting Moderator Approval ***</span>
1724 }
1725 @ <tr><th>Ticket:</th>
1726 @ <td>%z(href("%R/tktview/%s",zTktName))%s(zTktName)</a>
1727 if(zTktTitle){
1728 @<br>%h(zTktTitle)
1729 }
1730 @</td></tr>
1731 @ <tr><th>Date:</th><td>
1732 hyperlink_to_date(zDate, "</td></tr>");
1733 @ <tr><th>User:</th><td>
1734 hyperlink_to_user(pTktChng->zUser, zDate, "</td></tr>");
1735 @ </table>
1736 free(zDate);
1737 free(zTktTitle);
1738
1739 if( g.perm.ModTkt && modPending ){
1740 @ <div class="section">Moderation</div>
1741 @ <blockquote>
1742 @ <form method="POST" action="%R/tinfo/%s(zUuid)">
1743
+13 -6
--- src/json.c
+++ src/json.c
@@ -239,10 +239,11 @@
239239
C(STMT_EXEC,"Statement execution/stepping failed");
240240
C(DB_LOCKED,"Database is locked");
241241
C(DB_NEEDS_REBUILD,"Fossil repository needs to be rebuilt");
242242
C(DB_NOT_FOUND,"Fossil repository db file could not be found.");
243243
C(DB_NOT_VALID, "Fossil repository db file is not valid.");
244
+ C(DB_NEEDS_CHECKOUT, "Command requires a local checkout.");
244245
#undef C
245246
default:
246247
return "Unknown Error";
247248
}
248249
}
@@ -1397,11 +1398,10 @@
13971398
INT(g, urlIsFile);
13981399
INT(g, urlIsHttps);
13991400
INT(g, urlIsSsh);
14001401
INT(g, urlPort);
14011402
INT(g, urlDfltPort);
1402
- INT(g, dontKeepUrl);
14031403
INT(g, useLocalauth);
14041404
INT(g, noPswd);
14051405
INT(g, userUid);
14061406
INT(g, rcvid);
14071407
INT(g, okCsrf);
@@ -2118,18 +2118,22 @@
21182118
** taken from zPages. zPages must be an array of objects
21192119
** whose final entry MUST have a NULL name value or results
21202120
** are undefined.
21212121
**
21222122
** The list is appended to pOut. The number of items (not bytes)
2123
-** appended are returned.
2123
+** appended are returned. If filterByMode is non-0 then the result
2124
+** list will contain only commands which are able to run in the the
2125
+** current run mode (CLI vs. HTTP).
21242126
*/
21252127
static int json_pagedefs_to_string(JsonPageDef const * zPages,
2126
- Blob * pOut){
2128
+ Blob * pOut, int filterByMode){
21272129
int i = 0;
21282130
for( ; zPages->name; ++zPages, ++i ){
2129
- if(g.isHTTP && zPages->runMode < 0) continue;
2130
- else if(zPages->runMode > 0) continue;
2131
+ if(filterByMode){
2132
+ if(g.isHTTP && zPages->runMode < 0) continue;
2133
+ else if(zPages->runMode > 0) continue;
2134
+ }
21312135
blob_appendf(pOut, zPages->name, -1);
21322136
if((zPages+1)->name){
21332137
blob_append(pOut, ", ",2);
21342138
}
21352139
}
@@ -2153,11 +2157,11 @@
21532157
blob_init(&cmdNames,NULL,0);
21542158
if( !zErrPrefix ) {
21552159
zErrPrefix = "Try one of: ";
21562160
}
21572161
blob_append( &cmdNames, zErrPrefix, strlen(zErrPrefix) );
2158
- json_pagedefs_to_string(pCommands, &cmdNames);
2162
+ json_pagedefs_to_string(pCommands, &cmdNames, 1);
21592163
json_set_err(FSL_JSON_E_MISSING_ARGS, "%s",
21602164
blob_str(&cmdNames));
21612165
blob_reset(&cmdNames);
21622166
}
21632167
@@ -2246,10 +2250,12 @@
22462250
cson_value * json_page_user();
22472251
/* Impl in json_config.c. */
22482252
cson_value * json_page_config();
22492253
/* Impl in json_finfo.c. */
22502254
cson_value * json_page_finfo();
2255
+/* Impl in json_status.c. */
2256
+cson_value * json_page_status();
22512257
22522258
/*
22532259
** Mapping of names to JSON pages/commands. Each name is a subpath of
22542260
** /json (in CGI mode) or a subcommand of the json command in CLI mode
22552261
*/
@@ -2270,10 +2276,11 @@
22702276
{"query",json_page_query,0},
22712277
{"rebuild",json_page_rebuild,0},
22722278
{"report", json_page_report, 0},
22732279
{"resultCodes", json_page_resultCodes,0},
22742280
{"stat",json_page_stat,0},
2281
+{"status", json_page_status, 0},
22752282
{"tag", json_page_tag,0},
22762283
/*{"ticket", json_page_nyi,0},*/
22772284
{"timeline", json_page_timeline,0},
22782285
{"user",json_page_user,0},
22792286
{"version",json_page_version,0},
22802287
--- src/json.c
+++ src/json.c
@@ -239,10 +239,11 @@
239 C(STMT_EXEC,"Statement execution/stepping failed");
240 C(DB_LOCKED,"Database is locked");
241 C(DB_NEEDS_REBUILD,"Fossil repository needs to be rebuilt");
242 C(DB_NOT_FOUND,"Fossil repository db file could not be found.");
243 C(DB_NOT_VALID, "Fossil repository db file is not valid.");
 
244 #undef C
245 default:
246 return "Unknown Error";
247 }
248 }
@@ -1397,11 +1398,10 @@
1397 INT(g, urlIsFile);
1398 INT(g, urlIsHttps);
1399 INT(g, urlIsSsh);
1400 INT(g, urlPort);
1401 INT(g, urlDfltPort);
1402 INT(g, dontKeepUrl);
1403 INT(g, useLocalauth);
1404 INT(g, noPswd);
1405 INT(g, userUid);
1406 INT(g, rcvid);
1407 INT(g, okCsrf);
@@ -2118,18 +2118,22 @@
2118 ** taken from zPages. zPages must be an array of objects
2119 ** whose final entry MUST have a NULL name value or results
2120 ** are undefined.
2121 **
2122 ** The list is appended to pOut. The number of items (not bytes)
2123 ** appended are returned.
 
 
2124 */
2125 static int json_pagedefs_to_string(JsonPageDef const * zPages,
2126 Blob * pOut){
2127 int i = 0;
2128 for( ; zPages->name; ++zPages, ++i ){
2129 if(g.isHTTP && zPages->runMode < 0) continue;
2130 else if(zPages->runMode > 0) continue;
 
 
2131 blob_appendf(pOut, zPages->name, -1);
2132 if((zPages+1)->name){
2133 blob_append(pOut, ", ",2);
2134 }
2135 }
@@ -2153,11 +2157,11 @@
2153 blob_init(&cmdNames,NULL,0);
2154 if( !zErrPrefix ) {
2155 zErrPrefix = "Try one of: ";
2156 }
2157 blob_append( &cmdNames, zErrPrefix, strlen(zErrPrefix) );
2158 json_pagedefs_to_string(pCommands, &cmdNames);
2159 json_set_err(FSL_JSON_E_MISSING_ARGS, "%s",
2160 blob_str(&cmdNames));
2161 blob_reset(&cmdNames);
2162 }
2163
@@ -2246,10 +2250,12 @@
2246 cson_value * json_page_user();
2247 /* Impl in json_config.c. */
2248 cson_value * json_page_config();
2249 /* Impl in json_finfo.c. */
2250 cson_value * json_page_finfo();
 
 
2251
2252 /*
2253 ** Mapping of names to JSON pages/commands. Each name is a subpath of
2254 ** /json (in CGI mode) or a subcommand of the json command in CLI mode
2255 */
@@ -2270,10 +2276,11 @@
2270 {"query",json_page_query,0},
2271 {"rebuild",json_page_rebuild,0},
2272 {"report", json_page_report, 0},
2273 {"resultCodes", json_page_resultCodes,0},
2274 {"stat",json_page_stat,0},
 
2275 {"tag", json_page_tag,0},
2276 /*{"ticket", json_page_nyi,0},*/
2277 {"timeline", json_page_timeline,0},
2278 {"user",json_page_user,0},
2279 {"version",json_page_version,0},
2280
--- src/json.c
+++ src/json.c
@@ -239,10 +239,11 @@
239 C(STMT_EXEC,"Statement execution/stepping failed");
240 C(DB_LOCKED,"Database is locked");
241 C(DB_NEEDS_REBUILD,"Fossil repository needs to be rebuilt");
242 C(DB_NOT_FOUND,"Fossil repository db file could not be found.");
243 C(DB_NOT_VALID, "Fossil repository db file is not valid.");
244 C(DB_NEEDS_CHECKOUT, "Command requires a local checkout.");
245 #undef C
246 default:
247 return "Unknown Error";
248 }
249 }
@@ -1397,11 +1398,10 @@
1398 INT(g, urlIsFile);
1399 INT(g, urlIsHttps);
1400 INT(g, urlIsSsh);
1401 INT(g, urlPort);
1402 INT(g, urlDfltPort);
 
1403 INT(g, useLocalauth);
1404 INT(g, noPswd);
1405 INT(g, userUid);
1406 INT(g, rcvid);
1407 INT(g, okCsrf);
@@ -2118,18 +2118,22 @@
2118 ** taken from zPages. zPages must be an array of objects
2119 ** whose final entry MUST have a NULL name value or results
2120 ** are undefined.
2121 **
2122 ** The list is appended to pOut. The number of items (not bytes)
2123 ** appended are returned. If filterByMode is non-0 then the result
2124 ** list will contain only commands which are able to run in the the
2125 ** current run mode (CLI vs. HTTP).
2126 */
2127 static int json_pagedefs_to_string(JsonPageDef const * zPages,
2128 Blob * pOut, int filterByMode){
2129 int i = 0;
2130 for( ; zPages->name; ++zPages, ++i ){
2131 if(filterByMode){
2132 if(g.isHTTP && zPages->runMode < 0) continue;
2133 else if(zPages->runMode > 0) continue;
2134 }
2135 blob_appendf(pOut, zPages->name, -1);
2136 if((zPages+1)->name){
2137 blob_append(pOut, ", ",2);
2138 }
2139 }
@@ -2153,11 +2157,11 @@
2157 blob_init(&cmdNames,NULL,0);
2158 if( !zErrPrefix ) {
2159 zErrPrefix = "Try one of: ";
2160 }
2161 blob_append( &cmdNames, zErrPrefix, strlen(zErrPrefix) );
2162 json_pagedefs_to_string(pCommands, &cmdNames, 1);
2163 json_set_err(FSL_JSON_E_MISSING_ARGS, "%s",
2164 blob_str(&cmdNames));
2165 blob_reset(&cmdNames);
2166 }
2167
@@ -2246,10 +2250,12 @@
2250 cson_value * json_page_user();
2251 /* Impl in json_config.c. */
2252 cson_value * json_page_config();
2253 /* Impl in json_finfo.c. */
2254 cson_value * json_page_finfo();
2255 /* Impl in json_status.c. */
2256 cson_value * json_page_status();
2257
2258 /*
2259 ** Mapping of names to JSON pages/commands. Each name is a subpath of
2260 ** /json (in CGI mode) or a subcommand of the json command in CLI mode
2261 */
@@ -2270,10 +2276,11 @@
2276 {"query",json_page_query,0},
2277 {"rebuild",json_page_rebuild,0},
2278 {"report", json_page_report, 0},
2279 {"resultCodes", json_page_resultCodes,0},
2280 {"stat",json_page_stat,0},
2281 {"status", json_page_status, 0},
2282 {"tag", json_page_tag,0},
2283 /*{"ticket", json_page_nyi,0},*/
2284 {"timeline", json_page_timeline,0},
2285 {"user",json_page_user,0},
2286 {"version",json_page_version,0},
2287
--- src/json_detail.h
+++ src/json_detail.h
@@ -103,12 +103,18 @@
103103
FSL_JSON_E_STMT_EXEC /*+3*/,
104104
FSL_JSON_E_DB_LOCKED /*+4*/,
105105
106106
FSL_JSON_E_DB_NEEDS_REBUILD = FSL_JSON_E_DB + 101,
107107
FSL_JSON_E_DB_NOT_FOUND = FSL_JSON_E_DB + 102,
108
-FSL_JSON_E_DB_NOT_VALID = FSL_JSON_E_DB + 103
109
-
108
+FSL_JSON_E_DB_NOT_VALID = FSL_JSON_E_DB + 103,
109
+/*
110
+** Maintenance reminder: FSL_JSON_E_DB_NOT_FOUND gets triggered in the
111
+** bootstrapping process before we know whether we need to check for
112
+** FSL_JSON_E_DB_NEEDS_CHECKOUT. Thus the former error trumps the
113
+** latter.
114
+*/
115
+FSL_JSON_E_DB_NEEDS_CHECKOUT = FSL_JSON_E_DB + 104
110116
};
111117
112118
113119
/*
114120
** Signature for JSON page/command callbacks. Each callback is
@@ -177,13 +183,10 @@
177183
** <0 = CLI only, >0 = HTTP only, 0==both
178184
**
179185
** Now that we can simulate POST in CLI mode, the distinction
180186
** between them has disappeared in most (or all) cases, so 0 is
181187
** the standard value.
182
- **
183
- ** 201207: this is not needed any more. We can get rid of it. Or
184
- ** keep it around in case it becomes useful again at some point.
185188
*/
186189
char runMode;
187190
} JsonPageDef;
188191
189192
/*
190193
191194
ADDED src/json_status.c
--- src/json_detail.h
+++ src/json_detail.h
@@ -103,12 +103,18 @@
103 FSL_JSON_E_STMT_EXEC /*+3*/,
104 FSL_JSON_E_DB_LOCKED /*+4*/,
105
106 FSL_JSON_E_DB_NEEDS_REBUILD = FSL_JSON_E_DB + 101,
107 FSL_JSON_E_DB_NOT_FOUND = FSL_JSON_E_DB + 102,
108 FSL_JSON_E_DB_NOT_VALID = FSL_JSON_E_DB + 103
109
 
 
 
 
 
 
110 };
111
112
113 /*
114 ** Signature for JSON page/command callbacks. Each callback is
@@ -177,13 +183,10 @@
177 ** <0 = CLI only, >0 = HTTP only, 0==both
178 **
179 ** Now that we can simulate POST in CLI mode, the distinction
180 ** between them has disappeared in most (or all) cases, so 0 is
181 ** the standard value.
182 **
183 ** 201207: this is not needed any more. We can get rid of it. Or
184 ** keep it around in case it becomes useful again at some point.
185 */
186 char runMode;
187 } JsonPageDef;
188
189 /*
190
191 DDED src/json_status.c
--- src/json_detail.h
+++ src/json_detail.h
@@ -103,12 +103,18 @@
103 FSL_JSON_E_STMT_EXEC /*+3*/,
104 FSL_JSON_E_DB_LOCKED /*+4*/,
105
106 FSL_JSON_E_DB_NEEDS_REBUILD = FSL_JSON_E_DB + 101,
107 FSL_JSON_E_DB_NOT_FOUND = FSL_JSON_E_DB + 102,
108 FSL_JSON_E_DB_NOT_VALID = FSL_JSON_E_DB + 103,
109 /*
110 ** Maintenance reminder: FSL_JSON_E_DB_NOT_FOUND gets triggered in the
111 ** bootstrapping process before we know whether we need to check for
112 ** FSL_JSON_E_DB_NEEDS_CHECKOUT. Thus the former error trumps the
113 ** latter.
114 */
115 FSL_JSON_E_DB_NEEDS_CHECKOUT = FSL_JSON_E_DB + 104
116 };
117
118
119 /*
120 ** Signature for JSON page/command callbacks. Each callback is
@@ -177,13 +183,10 @@
183 ** <0 = CLI only, >0 = HTTP only, 0==both
184 **
185 ** Now that we can simulate POST in CLI mode, the distinction
186 ** between them has disappeared in most (or all) cases, so 0 is
187 ** the standard value.
 
 
 
188 */
189 char runMode;
190 } JsonPageDef;
191
192 /*
193
194 DDED src/json_status.c
--- a/src/json_status.c
+++ b/src/json_status.c
@@ -0,0 +1,195 @@
1
+#ifdef FOSSIL_ENABLE_JSON
2
+/*
3
+** Copyright (c) 2013 D. Richard Hipp
4
+**
5
+** This program is free software; you can redistribute it and/or
6
+** modify it under the terms of the Simplified BSD License (also
7
+** known as the "2-Clause License" or "FreeBSD License".)
8
+**
9
+** This program is distributed in the hope that it will be useful,
10
+** but without any warranty; without even the implied warranty of
11
+** merchantability or fitness for a particular purpose.
12
+**
13
+** Author contact information:
14
+** [email protected]
15
+** http://www.hwaci.com/drh/
16
+**
17
+*/
18
+
19
+#include "config.h"
20
+#include "json_status.h"
21
+
22
+#if INTERFACE
23
+#include "json_detail.h"
24
+#endif
25
+
26
+/*
27
+Reminder to check if a column exists:
28
+
29
+PRAGMA table_info(table_name)
30
+
31
+and search for a row where the 'name' field matches.
32
+
33
+That assumes, of course, that table_info()'s output format
34
+is stable.
35
+*/
36
+
37
+/*
38
+** Implementation of the /json/status page.
39
+**
40
+*/
41
+cson_value * json_page_status(){
42
+ char const * zSql = NULL;
43
+ Stmt q = empty_Stmt;
44
+ cson_object * oPay;
45
+ /*cson_object * files;*/
46
+ int vid, nErr = 0;
47
+ cson_object * tmpO;
48
+ char * zTmp;
49
+ i64 iMtime;
50
+ cson_array * aFles;
51
+
52
+ if(!db_o open_local(0)){
53
+ json_set_er,urn NULL;
54
+ }
55
+ oPay = cson_new_object();
56
+ cson_object_set(oPay, "repository",
57
+ json_new_string(db_repository_filename()));
58
+ cson_object_set(oPay, "localRoot",
59
+ json_new_string(g.zLocalRoot));
60
+ vid = db_lget_int("checkout", 0);
61
+ if(!vid){
62
+ json_set_err( FSL_JSON_E_UNKNOWN, "Can this even happen?" );
63
+ return 0;
64
+ }
65
+ vfile_check_signature(vid, 0);
66
+ /* TODO:show_common_info() state */
67
+ tmpO = cson_new_object();
68
+ cson_???object();
69
+ cson_object_set(oPay, "checkout", cson_object_value(tmpO));
70
+
71
+ zTmp = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
72
+ cson_object_set(tmpO, "uuid", json_new_string(zTmp) );
73
+ free(zTmp);
74
+
75
+ cson_object_set( tmpO, "tags", json_tags_for_checkin_rid(vi,wd 0t(0, "Spen_local(0)){
76
+ json_set_erct();
77
+ cson_object_set(oPay, "repository",
78
+ json_new_string(db_repository_filename()));
79
+ cson_object_set(oPay, "localRoot",
80
+ et_int("checkout", 0);
81
+ if(!vid){
82
+ json_set_err( FSL_JSON_E_UNKNOWN, "Can this even happen?" );
83
+ return 0;
84
+ }
85
+ vfile_check_sig#ifdef FOSSIL_ENABLE_JSON
86
+/*
87
+** Copyright (c) 2013 D. Richard Hipp
88
+**
89
+** This program is free software; you can redistribute it and/or
90
+** modify it under the terms of the Simplified BSD License (also
91
+** known as the "2-Clause License" or "FreeBSD License".)
92
+**
93
+** This program is distributed in the hope that it will be useful,
94
+** but without any warranty; without even the implied warranty of
95
+** merchantability or fitness for a particular purpose.
96
+**
97
+** Author contact information:
98
+** [email protected]
99
+** http://www.hwaci.com/drh/
100
+**
101
+*/
102
+
103
+#include "config.h"
104
+#include "json_status.h"
105
+
106
+#if INTERFACE
107
+#include "json_detail.h"
108
+#endif
109
+
110
+/*
111
+Reminder to check if a column exists:
112
+
113
+PRAGMA table_info(table_name)
114
+
115
+and search for a row where the 'name' field matches.
116
+
117
+That assumes, of course, that table_info()'s output format
118
+is stable.
119
+*/
120
+
121
+/*
122
+** Implementation of thelRoot",
123
+ json_new_string(g.zLocalRoot));
124
+ vid = db_lget_int("checkout", 0);
125
+ if(!vid){
126
+ json_set_err( FSL_JSON_E_UNKNOWN, "Can this even happen?" );
127
+ return 0;
128
+ }
129
+ vfile_check_signature(vid, 0);
130
+ /* TODO:show_common_info() state */
131
+ tmpO = cson_new_object();
132
+ cson_???object();
133
+ cson_object_set(oPay, "checkout", cson_object_value(tmpO));
134
+
135
+ zTmp = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
136
+ cson_object_set(tmpO, "uuid", json_new_string(zTmp) );
137
+ free(zTmp);
138
+
139
+ cson_object_set( tmpO, "tags", json_tags_for_checkin_rid(vi,wd 0t(0, "Spen_local(0)){
140
+ json_set_erct();
141
+ cson_object_set(oPay, "repository",
142
+ json_new_string(db_repository_filename()));
143
+ cson_object_set(oPay, "localRoot",
144
+ et_int("checkout", 0);
145
+ if(!vid){
146
+ json_set_err( FSL_JSON_E_UNKNOWN, "Can this even happen?" );
147
+ return 0;
148
+ }
149
+ vfile_check_sig#ifdef FOSSIL_ENABLE_JSON
150
+/*
151
+** Copyright (c) 2013 D. Richard Hipp
152
+**
153
+** This program is free software; you can redistribute it and/or
154
+** modify it under the terms of the Simplified BSD License (also
155
+** known as the "2-Clause License" or "FreeBSD License".)
156
+**
157
+** This program is distributed in the hope that it will be useful,
158
+** but without any warranty; without even the implied warranty of
159
+** merchantability or fitness for a particular purpose.
160
+**
161
+** Author contact information:
162
+** [email protected]
163
+** http://www.hwaci.com/drh/
164
+**
165
+*/
166
+
167
+#include "config.h"
168
+#include "json_status.h"
169
+
170
+#if INTERFACE
171
+#include "json_detail.h"
172
+#endif
173
+
174
+/*
175
+Reminder to check if a column exists:
176
+
177
+PRAGMA table_info(table_name)
178
+
179
+and search for a row where the 'name' field matches.
180
+
181
+That assumes, of course, that table_info()'s output format
182
+is stable.
183
+*/
184
+
185
+/*
186
+** Implementation of the /json/status page.
187
+**
188
+*/
189
+cson_value * json_page_status(){
190
+ Stmt q = empty_Stmt;
191
+ cson_object * oPay;
192
+ /*cson_object * files;*/
193
+ int vid, nErr = 0;
194
+ cson_object * tmpO;
195
+ char * zTC
--- a/src/json_status.c
+++ b/src/json_status.c
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/src/json_status.c
+++ b/src/json_status.c
@@ -0,0 +1,195 @@
1 #ifdef FOSSIL_ENABLE_JSON
2 /*
3 ** Copyright (c) 2013 D. Richard Hipp
4 **
5 ** This program is free software; you can redistribute it and/or
6 ** modify it under the terms of the Simplified BSD License (also
7 ** known as the "2-Clause License" or "FreeBSD License".)
8 **
9 ** This program is distributed in the hope that it will be useful,
10 ** but without any warranty; without even the implied warranty of
11 ** merchantability or fitness for a particular purpose.
12 **
13 ** Author contact information:
14 ** [email protected]
15 ** http://www.hwaci.com/drh/
16 **
17 */
18
19 #include "config.h"
20 #include "json_status.h"
21
22 #if INTERFACE
23 #include "json_detail.h"
24 #endif
25
26 /*
27 Reminder to check if a column exists:
28
29 PRAGMA table_info(table_name)
30
31 and search for a row where the 'name' field matches.
32
33 That assumes, of course, that table_info()'s output format
34 is stable.
35 */
36
37 /*
38 ** Implementation of the /json/status page.
39 **
40 */
41 cson_value * json_page_status(){
42 char const * zSql = NULL;
43 Stmt q = empty_Stmt;
44 cson_object * oPay;
45 /*cson_object * files;*/
46 int vid, nErr = 0;
47 cson_object * tmpO;
48 char * zTmp;
49 i64 iMtime;
50 cson_array * aFles;
51
52 if(!db_o open_local(0)){
53 json_set_er,urn NULL;
54 }
55 oPay = cson_new_object();
56 cson_object_set(oPay, "repository",
57 json_new_string(db_repository_filename()));
58 cson_object_set(oPay, "localRoot",
59 json_new_string(g.zLocalRoot));
60 vid = db_lget_int("checkout", 0);
61 if(!vid){
62 json_set_err( FSL_JSON_E_UNKNOWN, "Can this even happen?" );
63 return 0;
64 }
65 vfile_check_signature(vid, 0);
66 /* TODO:show_common_info() state */
67 tmpO = cson_new_object();
68 cson_???object();
69 cson_object_set(oPay, "checkout", cson_object_value(tmpO));
70
71 zTmp = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
72 cson_object_set(tmpO, "uuid", json_new_string(zTmp) );
73 free(zTmp);
74
75 cson_object_set( tmpO, "tags", json_tags_for_checkin_rid(vi,wd 0t(0, "Spen_local(0)){
76 json_set_erct();
77 cson_object_set(oPay, "repository",
78 json_new_string(db_repository_filename()));
79 cson_object_set(oPay, "localRoot",
80 et_int("checkout", 0);
81 if(!vid){
82 json_set_err( FSL_JSON_E_UNKNOWN, "Can this even happen?" );
83 return 0;
84 }
85 vfile_check_sig#ifdef FOSSIL_ENABLE_JSON
86 /*
87 ** Copyright (c) 2013 D. Richard Hipp
88 **
89 ** This program is free software; you can redistribute it and/or
90 ** modify it under the terms of the Simplified BSD License (also
91 ** known as the "2-Clause License" or "FreeBSD License".)
92 **
93 ** This program is distributed in the hope that it will be useful,
94 ** but without any warranty; without even the implied warranty of
95 ** merchantability or fitness for a particular purpose.
96 **
97 ** Author contact information:
98 ** [email protected]
99 ** http://www.hwaci.com/drh/
100 **
101 */
102
103 #include "config.h"
104 #include "json_status.h"
105
106 #if INTERFACE
107 #include "json_detail.h"
108 #endif
109
110 /*
111 Reminder to check if a column exists:
112
113 PRAGMA table_info(table_name)
114
115 and search for a row where the 'name' field matches.
116
117 That assumes, of course, that table_info()'s output format
118 is stable.
119 */
120
121 /*
122 ** Implementation of thelRoot",
123 json_new_string(g.zLocalRoot));
124 vid = db_lget_int("checkout", 0);
125 if(!vid){
126 json_set_err( FSL_JSON_E_UNKNOWN, "Can this even happen?" );
127 return 0;
128 }
129 vfile_check_signature(vid, 0);
130 /* TODO:show_common_info() state */
131 tmpO = cson_new_object();
132 cson_???object();
133 cson_object_set(oPay, "checkout", cson_object_value(tmpO));
134
135 zTmp = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
136 cson_object_set(tmpO, "uuid", json_new_string(zTmp) );
137 free(zTmp);
138
139 cson_object_set( tmpO, "tags", json_tags_for_checkin_rid(vi,wd 0t(0, "Spen_local(0)){
140 json_set_erct();
141 cson_object_set(oPay, "repository",
142 json_new_string(db_repository_filename()));
143 cson_object_set(oPay, "localRoot",
144 et_int("checkout", 0);
145 if(!vid){
146 json_set_err( FSL_JSON_E_UNKNOWN, "Can this even happen?" );
147 return 0;
148 }
149 vfile_check_sig#ifdef FOSSIL_ENABLE_JSON
150 /*
151 ** Copyright (c) 2013 D. Richard Hipp
152 **
153 ** This program is free software; you can redistribute it and/or
154 ** modify it under the terms of the Simplified BSD License (also
155 ** known as the "2-Clause License" or "FreeBSD License".)
156 **
157 ** This program is distributed in the hope that it will be useful,
158 ** but without any warranty; without even the implied warranty of
159 ** merchantability or fitness for a particular purpose.
160 **
161 ** Author contact information:
162 ** [email protected]
163 ** http://www.hwaci.com/drh/
164 **
165 */
166
167 #include "config.h"
168 #include "json_status.h"
169
170 #if INTERFACE
171 #include "json_detail.h"
172 #endif
173
174 /*
175 Reminder to check if a column exists:
176
177 PRAGMA table_info(table_name)
178
179 and search for a row where the 'name' field matches.
180
181 That assumes, of course, that table_info()'s output format
182 is stable.
183 */
184
185 /*
186 ** Implementation of the /json/status page.
187 **
188 */
189 cson_value * json_page_status(){
190 Stmt q = empty_Stmt;
191 cson_object * oPay;
192 /*cson_object * files;*/
193 int vid, nErr = 0;
194 cson_object * tmpO;
195 char * zTC
+191 -325
--- src/main.c
+++ src/main.c
@@ -31,11 +31,11 @@
3131
#else
3232
# include <errno.h> /* errno global */
3333
#endif
3434
#if INTERFACE
3535
#ifdef FOSSIL_ENABLE_JSON
36
-# include "cson_amalgamation.h" /* JSON API. Needed inside the INTERFACE block! */
36
+# include "cson_amalgamation.h" /* JSON API. */
3737
# include "json_detail.h"
3838
#endif
3939
#ifdef FOSSIL_ENABLE_TCL
4040
#include "tcl.h"
4141
#endif
@@ -172,14 +172,15 @@
172172
char *urlPasswd; /* Password for http: */
173173
char *urlCanonical; /* Canonical representation of the URL */
174174
char *urlProxyAuth; /* Proxy-Authorizer: string */
175175
char *urlFossil; /* The fossil query parameter on ssh: */
176176
char *urlShell; /* The shell query parameter on ssh: */
177
- int dontKeepUrl; /* Do not persist the URL */
177
+ unsigned urlFlags; /* Boolean flags controlling URL processing */
178178
179179
const char *zLogin; /* Login name. "" if not logged in. */
180
- const char *zSSLIdentity; /* Value of --ssl-identity option, filename of SSL client identity */
180
+ const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
181
+ ** SSL client identity */
181182
int useLocalauth; /* No login required if from 127.0.0.1 */
182183
int noPswd; /* Logged in without password (on 127.0.0.1) */
183184
int userUid; /* Integer user id */
184185
185186
/* Information used to populate the RCVFROM table */
@@ -223,11 +224,12 @@
223224
reported. In JSON mode we try to
224225
always output JSON-form error
225226
responses and always exit() with
226227
code 0 to avoid an HTTP 500 error.
227228
*/
228
- int resultCode; /* used for passing back specific codes from /json callbacks. */
229
+ int resultCode; /* used for passing back specific codes
230
+ ** from /json callbacks. */
229231
int errorDetailParanoia; /* 0=full error codes, 1=%10, 2=%100, 3=%1000 */
230232
cson_output_opt outOpt; /* formatting options for JSON mode. */
231233
cson_value * authToken; /* authentication token */
232234
char const * jsonp; /* Name of JSONP function wrapper. */
233235
unsigned char dispatchDepth /* Tells JSON command dispatching
@@ -332,11 +334,11 @@
332334
333335
/*
334336
** atexit() handler which frees up "some" of the resources
335337
** used by fossil.
336338
*/
337
-void fossil_atexit(void) {
339
+static void fossil_atexit(void) {
338340
#ifdef FOSSIL_ENABLE_JSON
339341
cson_value_free(g.json.gc.v);
340342
memset(&g.json, 0, sizeof(g.json));
341343
#endif
342344
free(g.zErrMsg);
@@ -365,11 +367,11 @@
365367
char *z; /* General use string pointer */
366368
char **newArgv; /* New expanded g.argv under construction */
367369
char const * zFileName; /* input file name */
368370
FILE * zInFile; /* input FILE */
369371
#if defined(_WIN32)
370
- WCHAR buf[MAX_PATH];
372
+ wchar_t buf[MAX_PATH];
371373
#endif
372374
373375
g.argc = argc;
374376
g.argv = argv;
375377
sqlite3_initialize();
@@ -453,10 +455,49 @@
453455
}
454456
return zNewArgv;
455457
}
456458
#endif
457459
460
+/*
461
+** Return a name for an SQLite error code
462
+*/
463
+static const char *sqlite_error_code_name(int iCode){
464
+ static char zCode[30];
465
+ switch( iCode & 0xff ){
466
+ case SQLITE_OK: return "SQLITE_OK";
467
+ case SQLITE_ERROR: return "SQLITE_ERROR";
468
+ case SQLITE_PERM: return "SQLITE_PERM";
469
+ case SQLITE_ABORT: return "SQLITE_ABORT";
470
+ case SQLITE_BUSY: return "SQLITE_BUSY";
471
+ case SQLITE_NOMEM: return "SQLITE_NOMEM";
472
+ case SQLITE_READONLY: return "SQLITE_READONLY";
473
+ case SQLITE_INTERRUPT: return "SQLITE_INTERRUPT";
474
+ case SQLITE_IOERR: return "SQLITE_IOERR";
475
+ case SQLITE_CORRUPT: return "SQLITE_CORRUPT";
476
+ case SQLITE_FULL: return "SQLITE_FULL";
477
+ case SQLITE_CANTOPEN: return "SQLITE_CANTOPEN";
478
+ case SQLITE_PROTOCOL: return "SQLITE_PROTOCOL";
479
+ case SQLITE_EMPTY: return "SQLITE_EMPTY";
480
+ case SQLITE_SCHEMA: return "SQLITE_SCHEMA";
481
+ case SQLITE_CONSTRAINT: return "SQLITE_CONSTRAINT";
482
+ case SQLITE_MISMATCH: return "SQLITE_MISMATCH";
483
+ case SQLITE_MISUSE: return "SQLITE_MISUSE";
484
+ case SQLITE_NOLFS: return "SQLITE_NOLFS";
485
+ case SQLITE_FORMAT: return "SQLITE_FORMAT";
486
+ case SQLITE_RANGE: return "SQLITE_RANGE";
487
+ case SQLITE_NOTADB: return "SQLITE_NOTADB";
488
+ default: {
489
+ sqlite3_snprintf(sizeof(zCode),zCode,"error code %d",iCode);
490
+ }
491
+ }
492
+ return zCode;
493
+}
494
+
495
+/* Error logs from SQLite */
496
+static void fossil_sqlite_log(void *notUsed, int iCode, const char *zErrmsg){
497
+ fossil_warning("%s: %s", sqlite_error_code_name(iCode), zErrmsg);
498
+}
458499
459500
/*
460501
** This procedure runs first.
461502
*/
462503
#if defined(_WIN32) && !defined(BROKEN_MINGW_CMDLINE)
@@ -560,252 +601,10 @@
560601
fossil_exit(0);
561602
/*NOT_REACHED*/
562603
return 0;
563604
}
564605
565
-/*
566
-** The following variable becomes true while processing a fatal error
567
-** or a panic. If additional "recursive-fatal" errors occur while
568
-** shutting down, the recursive errors are silently ignored.
569
-*/
570
-static int mainInFatalError = 0;
571
-
572
-/*
573
-** Exit. Take care to close the database first.
574
-*/
575
-NORETURN void fossil_exit(int rc){
576
- db_close(1);
577
- exit(rc);
578
-}
579
-
580
-/*
581
-** Print an error message, rollback all databases, and quit. These
582
-** routines never return.
583
-*/
584
-NORETURN void fossil_panic(const char *zFormat, ...){
585
- char *z;
586
- va_list ap;
587
- int rc = 1;
588
- static int once = 1;
589
- mainInFatalError = 1;
590
- va_start(ap, zFormat);
591
- z = vmprintf(zFormat, ap);
592
- va_end(ap);
593
-#ifdef FOSSIL_ENABLE_JSON
594
- if( g.json.isJsonMode ){
595
- json_err( 0, z, 1 );
596
- if( g.isHTTP ){
597
- rc = 0 /* avoid HTTP 500 */;
598
- }
599
- }
600
- else
601
-#endif
602
- {
603
- if( g.cgiOutput && once ){
604
- once = 0;
605
- cgi_printf("<p class=\"generalError\">%h</p>", z);
606
- cgi_reply();
607
- }else if( !g.fQuiet ){
608
- fossil_trace("%s: %s\n", g.argv[0], z);
609
- }
610
- }
611
- free(z);
612
- db_force_rollback();
613
- fossil_exit(rc);
614
-}
615
-
616
-NORETURN void fossil_fatal(const char *zFormat, ...){
617
- char *z;
618
- int rc = 1;
619
- va_list ap;
620
- mainInFatalError = 1;
621
- va_start(ap, zFormat);
622
- z = vmprintf(zFormat, ap);
623
- va_end(ap);
624
-#ifdef FOSSIL_ENABLE_JSON
625
- if( g.json.isJsonMode ){
626
- json_err( g.json.resultCode, z, 1 );
627
- if( g.isHTTP ){
628
- rc = 0 /* avoid HTTP 500 */;
629
- }
630
- }
631
- else
632
-#endif
633
- {
634
- if( g.cgiOutput ){
635
- g.cgiOutput = 0;
636
- cgi_printf("<p class=\"generalError\">\n%h\n</p>\n", z);
637
- cgi_reply();
638
- }else if( !g.fQuiet ){
639
- fossil_trace("%s: %s\n", g.argv[0], z);
640
- }
641
- }
642
- free(z);
643
- db_force_rollback();
644
- fossil_exit(rc);
645
-}
646
-
647
-/* This routine works like fossil_fatal() except that if called
648
-** recursively, the recursive call is a no-op.
649
-**
650
-** Use this in places where an error might occur while doing
651
-** fatal error shutdown processing. Unlike fossil_panic() and
652
-** fossil_fatal() which never return, this routine might return if
653
-** the fatal error handing is already in process. The caller must
654
-** be prepared for this routine to return.
655
-*/
656
-void fossil_fatal_recursive(const char *zFormat, ...){
657
- char *z;
658
- va_list ap;
659
- int rc = 1;
660
- if( mainInFatalError ) return;
661
- mainInFatalError = 1;
662
- va_start(ap, zFormat);
663
- z = vmprintf(zFormat, ap);
664
- va_end(ap);
665
-#ifdef FOSSIL_ENABLE_JSON
666
- if( g.json.isJsonMode ){
667
- json_err( g.json.resultCode, z, 1 );
668
- if( g.isHTTP ){
669
- rc = 0 /* avoid HTTP 500 */;
670
- }
671
- } else
672
-#endif
673
- {
674
- if( g.cgiOutput ){
675
- g.cgiOutput = 0;
676
- cgi_printf("<p class=\"generalError\">\n%h\n</p>\n", z);
677
- cgi_reply();
678
- }else{
679
- fossil_trace("%s: %s\n", g.argv[0], z);
680
- }
681
- }
682
- db_force_rollback();
683
- fossil_exit(rc);
684
-}
685
-
686
-
687
-/* Print a warning message */
688
-void fossil_warning(const char *zFormat, ...){
689
- char *z;
690
- va_list ap;
691
- va_start(ap, zFormat);
692
- z = vmprintf(zFormat, ap);
693
- va_end(ap);
694
-#ifdef FOSSIL_ENABLE_JSON
695
- if(g.json.isJsonMode){
696
- json_warn( FSL_JSON_W_UNKNOWN, z );
697
- }else
698
-#endif
699
- {
700
- if( g.cgiOutput ){
701
- cgi_printf("<p class=\"generalError\">\n%h\n</p>\n", z);
702
- }else{
703
- fossil_trace("%s: %s\n", g.argv[0], z);
704
- }
705
- }
706
- free(z);
707
-}
708
-
709
-/*
710
-** Malloc and free routines that cannot fail
711
-*/
712
-void *fossil_malloc(size_t n){
713
- void *p = malloc(n==0 ? 1 : n);
714
- if( p==0 ) fossil_panic("out of memory");
715
- return p;
716
-}
717
-void fossil_free(void *p){
718
- free(p);
719
-}
720
-void *fossil_realloc(void *p, size_t n){
721
- p = realloc(p, n);
722
- if( p==0 ) fossil_panic("out of memory");
723
- return p;
724
-}
725
-
726
-/*
727
-** This function implements a cross-platform "system()" interface.
728
-*/
729
-int fossil_system(const char *zOrigCmd){
730
- int rc;
731
-#if defined(_WIN32)
732
- /* On windows, we have to put double-quotes around the entire command.
733
- ** Who knows why - this is just the way windows works.
734
- */
735
- char *zNewCmd = mprintf("\"%s\"", zOrigCmd);
736
- WCHAR *zUnicode = fossil_utf8_to_unicode(zNewCmd);
737
- if( g.fSystemTrace ) {
738
- fossil_trace("SYSTEM: %s\n", zNewCmd);
739
- }
740
- rc = _wsystem(zUnicode);
741
- fossil_unicode_free(zUnicode);
742
- free(zNewCmd);
743
-#else
744
- /* On unix, evaluate the command directly.
745
- */
746
- if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zOrigCmd);
747
- rc = system(zOrigCmd);
748
-#endif
749
- return rc;
750
-}
751
-
752
-/*
753
-** Turn off any NL to CRNL translation on the stream given as an
754
-** argument. This is a no-op on unix but is necessary on windows.
755
-*/
756
-void fossil_binary_mode(FILE *p){
757
-#if defined(_WIN32)
758
- _setmode(_fileno(p), _O_BINARY);
759
-#endif
760
-#ifdef __EMX__ /* OS/2 */
761
- setmode(fileno(p), O_BINARY);
762
-#endif
763
-}
764
-
765
-
766
-
767
-/*
768
-** Return a name for an SQLite error code
769
-*/
770
-static const char *sqlite_error_code_name(int iCode){
771
- static char zCode[30];
772
- switch( iCode & 0xff ){
773
- case SQLITE_OK: return "SQLITE_OK";
774
- case SQLITE_ERROR: return "SQLITE_ERROR";
775
- case SQLITE_PERM: return "SQLITE_PERM";
776
- case SQLITE_ABORT: return "SQLITE_ABORT";
777
- case SQLITE_BUSY: return "SQLITE_BUSY";
778
- case SQLITE_NOMEM: return "SQLITE_NOMEM";
779
- case SQLITE_READONLY: return "SQLITE_READONLY";
780
- case SQLITE_INTERRUPT: return "SQLITE_INTERRUPT";
781
- case SQLITE_IOERR: return "SQLITE_IOERR";
782
- case SQLITE_CORRUPT: return "SQLITE_CORRUPT";
783
- case SQLITE_FULL: return "SQLITE_FULL";
784
- case SQLITE_CANTOPEN: return "SQLITE_CANTOPEN";
785
- case SQLITE_PROTOCOL: return "SQLITE_PROTOCOL";
786
- case SQLITE_EMPTY: return "SQLITE_EMPTY";
787
- case SQLITE_SCHEMA: return "SQLITE_SCHEMA";
788
- case SQLITE_CONSTRAINT: return "SQLITE_CONSTRAINT";
789
- case SQLITE_MISMATCH: return "SQLITE_MISMATCH";
790
- case SQLITE_MISUSE: return "SQLITE_MISUSE";
791
- case SQLITE_NOLFS: return "SQLITE_NOLFS";
792
- case SQLITE_FORMAT: return "SQLITE_FORMAT";
793
- case SQLITE_RANGE: return "SQLITE_RANGE";
794
- case SQLITE_NOTADB: return "SQLITE_NOTADB";
795
- default: {
796
- sqlite3_snprintf(sizeof(zCode),zCode,"error code %d",iCode);
797
- }
798
- }
799
- return zCode;
800
-}
801
-
802
-/* Error logs from SQLite */
803
-void fossil_sqlite_log(void *notUsed, int iCode, const char *zErrmsg){
804
- fossil_warning("%s: %s", sqlite_error_code_name(iCode), zErrmsg);
805
-}
806
-
807606
/*
808607
** Print a usage comment and quit
809608
*/
810609
void usage(const char *zFormat){
811610
fossil_fatal("Usage: %s %s %s\n", g.argv[0], g.argv[1], zFormat);
@@ -812,11 +611,11 @@
812611
}
813612
814613
/*
815614
** Remove n elements from g.argv beginning with the i-th element.
816615
*/
817
-void remove_from_argv(int i, int n){
616
+static void remove_from_argv(int i, int n){
818617
int j;
819618
for(j=i+n; j<g.argc; i++, j++){
820619
g.argv[i] = g.argv[j];
821620
}
822621
g.argc = i;
@@ -931,14 +730,17 @@
931730
**
932731
** List all web pages
933732
*/
934733
void cmd_test_webpage_list(void){
935734
int i, nCmd;
936
- const char *aCmd[count(aWebpage)];
937
- for(i=nCmd=0; i<count(aWebpage); i++){
938
- aCmd[nCmd++] = aWebpage[i].zName;
735
+ const char *aCmd[count(aCommand)];
736
+ for(i=nCmd=0; i<count(aCommand); i++){
737
+ if(0x08 & aCommand[i].cmdFlags){
738
+ aCmd[nCmd++] = aWebpage[i].zName;
739
+ }
939740
}
741
+ assert(nCmd && "page list is empty?");
940742
multi_column_list(aCmd, nCmd);
941743
}
942744
943745
/*
944746
** COMMAND: version
@@ -964,14 +766,17 @@
964766
**
965767
** %fossil help Show common commands
966768
** %fossil help --all Show both common and auxiliary commands
967769
** %fossil help --test Show test commands only
968770
** %fossil help --aux Show auxiliary commands only
771
+** %fossil help --www Show list of WWW pages
969772
*/
970773
void help_cmd(void){
971
- int rc, idx;
774
+ int rc, idx, isPage = 0;
972775
const char *z;
776
+ char const * zCmdOrPage;
777
+ char const * zCmdOrPagePlural;
973778
if( g.argc<3 ){
974779
z = g.argv[0];
975780
fossil_print(
976781
"Usage: %s help COMMAND\n"
977782
"Common COMMANDs: (use \"%s help --all\" for a complete list)\n",
@@ -982,33 +787,46 @@
982787
}
983788
if( find_option("all",0,0) ){
984789
command_list(0, CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER);
985790
return;
986791
}
987
- if( find_option("aux",0,0) ){
792
+ else if( find_option("www",0,0) ){
793
+ command_list(0, CMDFLAG_WEBPAGE);
794
+ return;
795
+ }
796
+ else if( find_option("aux",0,0) ){
988797
command_list(0, CMDFLAG_2ND_TIER);
989798
return;
990799
}
991
- if( find_option("test",0,0) ){
800
+ else if( find_option("test",0,0) ){
992801
command_list(0, CMDFLAG_TEST);
993802
return;
803
+ }
804
+ isPage = ('/' == *g.argv[2]) ? 1 : 0;
805
+ if(isPage){
806
+ zCmdOrPage = "page";
807
+ zCmdOrPagePlural = "pages";
808
+ }else{
809
+ zCmdOrPage = "command";
810
+ zCmdOrPagePlural = "commands";
994811
}
995812
rc = name_search(g.argv[2], aCommand, count(aCommand), &idx);
996813
if( rc==1 ){
997
- fossil_print("unknown command: %s\nAvailable commands:\n", g.argv[2]);
998
- command_list(0, 0xff);
814
+ fossil_print("unknown %s: %s\nAvailable %s:\n",
815
+ zCmdOrPage, g.argv[2], zCmdOrPagePlural);
816
+ command_list(0, isPage ? CMDFLAG_WEBPAGE : (0xff & ~CMDFLAG_WEBPAGE));
999817
fossil_exit(1);
1000818
}else if( rc==2 ){
1001
- fossil_print("ambiguous command prefix: %s\nMatching commands:\n",
1002
- g.argv[2]);
819
+ fossil_print("ambiguous %s prefix: %s\nMatching %s:\n",
820
+ zCmdOrPage, g.argv[2], zCmdOrPagePlural);
1003821
command_list(g.argv[2], 0xff);
1004822
fossil_exit(1);
1005823
}
1006
- z = aCmdHelp[idx];
824
+ z = aCmdHelp[idx].zText;
1007825
if( z==0 ){
1008
- fossil_fatal("no help available for the %s command",
1009
- aCommand[idx].zName);
826
+ fossil_fatal("no help available for the %s %s",
827
+ aCommand[idx].zName, zCmdOrPage);
1010828
}
1011829
while( *z ){
1012830
if( *z=='%' && strncmp(z, "%fossil", 7)==0 ){
1013831
fossil_print("%s", g.argv[0]);
1014832
z += 7;
@@ -1030,20 +848,20 @@
1030848
if( zCmd==0 ) zCmd = P("name");
1031849
style_header("Command-line Help");
1032850
if( zCmd ){
1033851
int rc, idx;
1034852
char *z, *s, *d;
1035
-
853
+ char const * zCmdOrPage = ('/'==*zCmd) ? "page" : "command";
1036854
style_submenu_element("Command-List", "Command-List", "%s/help", g.zTop);
1037
- @ <h1>The "%s(zCmd)" command:</h1>
855
+ @ <h1>The "%s(zCmd)" %s(zCmdOrPage):</h1>
1038856
rc = name_search(zCmd, aCommand, count(aCommand), &idx);
1039857
if( rc==1 ){
1040858
@ unknown command: %s(zCmd)
1041859
}else if( rc==2 ){
1042860
@ ambiguous command prefix: %s(zCmd)
1043861
}else{
1044
- z = (char*)aCmdHelp[idx];
862
+ z = (char*)aCmdHelp[idx].zText;
1045863
if( z==0 ){
1046864
@ no help available for the %s(aCommand[idx].zName) command
1047865
}else{
1048866
z=s=d=mprintf("%s",z);
1049867
while( *s ){
@@ -1065,21 +883,52 @@
1065883
1066884
@ <h1>Available commands:</h1>
1067885
@ <table border="0"><tr>
1068886
for(i=j=0; i<count(aCommand); i++){
1069887
const char *z = aCommand[i].zName;
1070
- if( strncmp(z,"test",4)==0 ) continue;
888
+ if( '/'==*z || strncmp(z,"test",4)==0 ) continue;
1071889
j++;
1072890
}
1073891
n = (j+6)/7;
1074892
for(i=j=0; i<count(aCommand); i++){
1075893
const char *z = aCommand[i].zName;
1076
- if( strncmp(z,"test",4)==0 ) continue;
894
+ if( '/'==*z || strncmp(z,"test",4)==0 ) continue;
895
+ if( j==0 ){
896
+ @ <td valign="top"><ul>
897
+ }
898
+ @ <li><a href="%s(g.zTop)/help?cmd=%s(z)">%s(z)</a></li>
899
+ j++;
900
+ if( j>=n ){
901
+ @ </ul></td>
902
+ j = 0;
903
+ }
904
+ }
905
+ if( j>0 ){
906
+ @ </ul></td>
907
+ }
908
+ @ </tr></table>
909
+
910
+ @ <h1>Available pages:</h1>
911
+ @ (Only pages with help text are linked.)
912
+ @ <table border="0"><tr>
913
+ for(i=j=0; i<count(aCommand); i++){
914
+ const char *z = aCommand[i].zName;
915
+ if( '/'!=*z ) continue;
916
+ j++;
917
+ }
918
+ n = (j+4)/5;
919
+ for(i=j=0; i<count(aCommand); i++){
920
+ const char *z = aCommand[i].zName;
921
+ if( '/'!=*z ) continue;
1077922
if( j==0 ){
1078923
@ <td valign="top"><ul>
1079924
}
1080
- @ <li><a href="%s(g.zTop)/help?cmd=%s(z)">%s(z)</a>
925
+ if( aCmdHelp[i].zText && *aCmdHelp[i].zText ){
926
+ @ <li><a href="%s(g.zTop)/help?cmd=%s(z)">%s(z+1)</a></li>
927
+ }else{
928
+ @ <li>%s(z+1)</li>
929
+ }
1081930
j++;
1082931
if( j>=n ){
1083932
@ </ul></td>
1084933
j = 0;
1085934
}
@@ -1086,10 +935,11 @@
1086935
}
1087936
if( j>0 ){
1088937
@ </ul></td>
1089938
}
1090939
@ </tr></table>
940
+
1091941
}
1092942
style_footer();
1093943
}
1094944
1095945
/*
@@ -1102,11 +952,11 @@
1102952
style_header("Testpage: All Help Text");
1103953
for(i=0; i<count(aCommand); i++){
1104954
if( memcmp(aCommand[i].zName, "test", 4)==0 ) continue;
1105955
@ <h2>%s(aCommand[i].zName):</h2>
1106956
@ <blockquote><pre>
1107
- @ %h(aCmdHelp[i])
957
+ @ %h(aCmdHelp[i].zText)
1108958
@ </pre></blockquote>
1109959
}
1110960
style_footer();
1111961
}
1112962
@@ -1501,10 +1351,61 @@
15011351
15021352
/* Return the result.
15031353
*/
15041354
cgi_reply();
15051355
}
1356
+
1357
+/* If the CGI program contains one or more lines of the form
1358
+**
1359
+** redirect: repository-filename http://hostname/path/%s
1360
+**
1361
+** then control jumps here. Search each repository for an artifact ID
1362
+** that matches the "name" CGI parameter and for the first match,
1363
+** redirect to the corresponding URL with the "name" CGI parameter
1364
+** inserted. Paint an error page if no match is found.
1365
+**
1366
+** If there is a line of the form:
1367
+**
1368
+** redirect: * URL
1369
+**
1370
+** Then a redirect is made to URL if no match is found. Otherwise a
1371
+** very primitive error message is returned.
1372
+*/
1373
+static void redirect_web_page(int nRedirect, char **azRedirect){
1374
+ int i; /* Loop counter */
1375
+ const char *zNotFound = 0; /* Not found URL */
1376
+ const char *zName = P("name");
1377
+ set_base_url(0);
1378
+ if( zName==0 ){
1379
+ zName = P("SCRIPT_NAME");
1380
+ if( zName && zName[0]=='/' ) zName++;
1381
+ }
1382
+ if( zName && validate16(zName, strlen(zName)) ){
1383
+ for(i=0; i<nRedirect; i++){
1384
+ if( fossil_strcmp(azRedirect[i*2],"*")==0 ){
1385
+ zNotFound = azRedirect[i*2+1];
1386
+ continue;
1387
+ }
1388
+ db_open_repository(azRedirect[i*2]);
1389
+ if( db_exists("SELECT 1 FROM blob WHERE uuid GLOB '%s*'", zName) ){
1390
+ cgi_redirectf(azRedirect[i*2+1], zName);
1391
+ return;
1392
+ }
1393
+ db_close(1);
1394
+ }
1395
+ }
1396
+ if( zNotFound ){
1397
+ cgi_redirectf(zNotFound, zName);
1398
+ }else{
1399
+ @ <html>
1400
+ @ <head><title>No Such Object</title></head>
1401
+ @ <body>
1402
+ @ <p>No such object: <b>%h(zName)</b></p>
1403
+ @ </body>
1404
+ cgi_reply();
1405
+ }
1406
+}
15061407
15071408
/*
15081409
** COMMAND: cgi*
15091410
**
15101411
** Usage: %fossil ?cgi? SCRIPT
@@ -1601,61 +1502,10 @@
16011502
}else{
16021503
process_one_web_page(zNotFound, pFileGlob);
16031504
}
16041505
}
16051506
1606
-/* If the CGI program contains one or more lines of the form
1607
-**
1608
-** redirect: repository-filename http://hostname/path/%s
1609
-**
1610
-** then control jumps here. Search each repository for an artifact ID
1611
-** that matches the "name" CGI parameter and for the first match,
1612
-** redirect to the corresponding URL with the "name" CGI parameter
1613
-** inserted. Paint an error page if no match is found.
1614
-**
1615
-** If there is a line of the form:
1616
-**
1617
-** redirect: * URL
1618
-**
1619
-** Then a redirect is made to URL if no match is found. Otherwise a
1620
-** very primitive error message is returned.
1621
-*/
1622
-void redirect_web_page(int nRedirect, char **azRedirect){
1623
- int i; /* Loop counter */
1624
- const char *zNotFound = 0; /* Not found URL */
1625
- const char *zName = P("name");
1626
- set_base_url(0);
1627
- if( zName==0 ){
1628
- zName = P("SCRIPT_NAME");
1629
- if( zName && zName[0]=='/' ) zName++;
1630
- }
1631
- if( zName && validate16(zName, strlen(zName)) ){
1632
- for(i=0; i<nRedirect; i++){
1633
- if( fossil_strcmp(azRedirect[i*2],"*")==0 ){
1634
- zNotFound = azRedirect[i*2+1];
1635
- continue;
1636
- }
1637
- db_open_repository(azRedirect[i*2]);
1638
- if( db_exists("SELECT 1 FROM blob WHERE uuid GLOB '%s*'", zName) ){
1639
- cgi_redirectf(azRedirect[i*2+1], zName);
1640
- return;
1641
- }
1642
- db_close(1);
1643
- }
1644
- }
1645
- if( zNotFound ){
1646
- cgi_redirectf(zNotFound, zName);
1647
- }else{
1648
- @ <html>
1649
- @ <head><title>No Such Object</title></head>
1650
- @ <body>
1651
- @ <p>No such object: <b>%h(zName)</b></p>
1652
- @ </body>
1653
- cgi_reply();
1654
- }
1655
-}
1656
-
16571507
/*
16581508
** If g.argv[2] exists then it is either the name of a repository
16591509
** that will be used by a server, or else it is a directory that
16601510
** contains multiple repositories that can be served. If g.argv[2]
16611511
** is a directory, the repositories it contains must be named
@@ -1888,10 +1738,11 @@
18881738
int isUiCmd; /* True if command is "ui", not "server' */
18891739
const char *zNotFound; /* The --notfound option or NULL */
18901740
int flags = 0; /* Server flags */
18911741
const char *zAltBase; /* Argument to the --baseurl option */
18921742
const char *zFileGlob; /* Static content must match this */
1743
+ char *zIpAddr = 0; /* Bind to this IP address */
18931744
18941745
#if defined(_WIN32)
18951746
const char *zStopperFile; /* Name of file used to terminate server */
18961747
zStopperFile = find_option("stopper", 0, 1);
18971748
#endif
@@ -1914,10 +1765,16 @@
19141765
flags |= HTTP_SERVER_LOCALHOST;
19151766
g.useLocalauth = 1;
19161767
}
19171768
find_server_repository(isUiCmd && zNotFound==0);
19181769
if( zPort ){
1770
+ int i;
1771
+ for(i=strlen(zPort)-1; i>=0 && zPort[i]!=':'; i--){}
1772
+ if( i>0 ){
1773
+ zIpAddr = mprintf("%.*s", i, zPort);
1774
+ zPort += i+1;
1775
+ }
19191776
iPort = mxPort = atoi(zPort);
19201777
}else{
19211778
iPort = db_get_int("http-port", 8080);
19221779
mxPort = iPort+100;
19231780
}
@@ -1925,11 +1782,12 @@
19251782
/* Unix implementation */
19261783
if( isUiCmd ){
19271784
#if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
19281785
zBrowser = db_get("web-browser", 0);
19291786
if( zBrowser==0 ){
1930
- static const char *const azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
1787
+ static const char *const azBrowserProg[] =
1788
+ { "xdg-open", "gnome-open", "firefox", "google-chrome" };
19311789
int i;
19321790
zBrowser = "echo";
19331791
for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
19341792
if( binaryOnPath(azBrowserProg[i]) ){
19351793
zBrowser = azBrowserProg[i];
@@ -1938,14 +1796,18 @@
19381796
}
19391797
}
19401798
#else
19411799
zBrowser = db_get("web-browser", "open");
19421800
#endif
1943
- zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
1801
+ if( zIpAddr ){
1802
+ zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr);
1803
+ }else{
1804
+ zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
1805
+ }
19441806
}
19451807
db_close(1);
1946
- if( cgi_http_server(iPort, mxPort, zBrowserCmd, flags) ){
1808
+ if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
19471809
fossil_fatal("unable to listen on TCP socket %d", iPort);
19481810
}
19491811
g.sslNotAvailable = 1;
19501812
g.httpIn = stdin;
19511813
g.httpOut = stdout;
@@ -1959,16 +1821,20 @@
19591821
process_one_web_page(zNotFound, glob_create(zFileGlob));
19601822
#else
19611823
/* Win32 implementation */
19621824
if( isUiCmd ){
19631825
zBrowser = db_get("web-browser", "start");
1964
- zBrowserCmd = mprintf("%s http://127.0.0.1:%%d/", zBrowser);
1826
+ if( zIpAddr ){
1827
+ zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr);
1828
+ }else{
1829
+ zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
1830
+ }
19651831
}
19661832
db_close(1);
19671833
if( win32_http_service(iPort, zNotFound, zFileGlob, flags) ){
19681834
win32_http_server(iPort, mxPort, zBrowserCmd,
1969
- zStopperFile, zNotFound, zFileGlob, flags);
1835
+ zStopperFile, zNotFound, zFileGlob, zIpAddr, flags);
19701836
}
19711837
#endif
19721838
}
19731839
19741840
/*
19751841
--- src/main.c
+++ src/main.c
@@ -31,11 +31,11 @@
31 #else
32 # include <errno.h> /* errno global */
33 #endif
34 #if INTERFACE
35 #ifdef FOSSIL_ENABLE_JSON
36 # include "cson_amalgamation.h" /* JSON API. Needed inside the INTERFACE block! */
37 # include "json_detail.h"
38 #endif
39 #ifdef FOSSIL_ENABLE_TCL
40 #include "tcl.h"
41 #endif
@@ -172,14 +172,15 @@
172 char *urlPasswd; /* Password for http: */
173 char *urlCanonical; /* Canonical representation of the URL */
174 char *urlProxyAuth; /* Proxy-Authorizer: string */
175 char *urlFossil; /* The fossil query parameter on ssh: */
176 char *urlShell; /* The shell query parameter on ssh: */
177 int dontKeepUrl; /* Do not persist the URL */
178
179 const char *zLogin; /* Login name. "" if not logged in. */
180 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of SSL client identity */
 
181 int useLocalauth; /* No login required if from 127.0.0.1 */
182 int noPswd; /* Logged in without password (on 127.0.0.1) */
183 int userUid; /* Integer user id */
184
185 /* Information used to populate the RCVFROM table */
@@ -223,11 +224,12 @@
223 reported. In JSON mode we try to
224 always output JSON-form error
225 responses and always exit() with
226 code 0 to avoid an HTTP 500 error.
227 */
228 int resultCode; /* used for passing back specific codes from /json callbacks. */
 
229 int errorDetailParanoia; /* 0=full error codes, 1=%10, 2=%100, 3=%1000 */
230 cson_output_opt outOpt; /* formatting options for JSON mode. */
231 cson_value * authToken; /* authentication token */
232 char const * jsonp; /* Name of JSONP function wrapper. */
233 unsigned char dispatchDepth /* Tells JSON command dispatching
@@ -332,11 +334,11 @@
332
333 /*
334 ** atexit() handler which frees up "some" of the resources
335 ** used by fossil.
336 */
337 void fossil_atexit(void) {
338 #ifdef FOSSIL_ENABLE_JSON
339 cson_value_free(g.json.gc.v);
340 memset(&g.json, 0, sizeof(g.json));
341 #endif
342 free(g.zErrMsg);
@@ -365,11 +367,11 @@
365 char *z; /* General use string pointer */
366 char **newArgv; /* New expanded g.argv under construction */
367 char const * zFileName; /* input file name */
368 FILE * zInFile; /* input FILE */
369 #if defined(_WIN32)
370 WCHAR buf[MAX_PATH];
371 #endif
372
373 g.argc = argc;
374 g.argv = argv;
375 sqlite3_initialize();
@@ -453,10 +455,49 @@
453 }
454 return zNewArgv;
455 }
456 #endif
457
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
458
459 /*
460 ** This procedure runs first.
461 */
462 #if defined(_WIN32) && !defined(BROKEN_MINGW_CMDLINE)
@@ -560,252 +601,10 @@
560 fossil_exit(0);
561 /*NOT_REACHED*/
562 return 0;
563 }
564
565 /*
566 ** The following variable becomes true while processing a fatal error
567 ** or a panic. If additional "recursive-fatal" errors occur while
568 ** shutting down, the recursive errors are silently ignored.
569 */
570 static int mainInFatalError = 0;
571
572 /*
573 ** Exit. Take care to close the database first.
574 */
575 NORETURN void fossil_exit(int rc){
576 db_close(1);
577 exit(rc);
578 }
579
580 /*
581 ** Print an error message, rollback all databases, and quit. These
582 ** routines never return.
583 */
584 NORETURN void fossil_panic(const char *zFormat, ...){
585 char *z;
586 va_list ap;
587 int rc = 1;
588 static int once = 1;
589 mainInFatalError = 1;
590 va_start(ap, zFormat);
591 z = vmprintf(zFormat, ap);
592 va_end(ap);
593 #ifdef FOSSIL_ENABLE_JSON
594 if( g.json.isJsonMode ){
595 json_err( 0, z, 1 );
596 if( g.isHTTP ){
597 rc = 0 /* avoid HTTP 500 */;
598 }
599 }
600 else
601 #endif
602 {
603 if( g.cgiOutput && once ){
604 once = 0;
605 cgi_printf("<p class=\"generalError\">%h</p>", z);
606 cgi_reply();
607 }else if( !g.fQuiet ){
608 fossil_trace("%s: %s\n", g.argv[0], z);
609 }
610 }
611 free(z);
612 db_force_rollback();
613 fossil_exit(rc);
614 }
615
616 NORETURN void fossil_fatal(const char *zFormat, ...){
617 char *z;
618 int rc = 1;
619 va_list ap;
620 mainInFatalError = 1;
621 va_start(ap, zFormat);
622 z = vmprintf(zFormat, ap);
623 va_end(ap);
624 #ifdef FOSSIL_ENABLE_JSON
625 if( g.json.isJsonMode ){
626 json_err( g.json.resultCode, z, 1 );
627 if( g.isHTTP ){
628 rc = 0 /* avoid HTTP 500 */;
629 }
630 }
631 else
632 #endif
633 {
634 if( g.cgiOutput ){
635 g.cgiOutput = 0;
636 cgi_printf("<p class=\"generalError\">\n%h\n</p>\n", z);
637 cgi_reply();
638 }else if( !g.fQuiet ){
639 fossil_trace("%s: %s\n", g.argv[0], z);
640 }
641 }
642 free(z);
643 db_force_rollback();
644 fossil_exit(rc);
645 }
646
647 /* This routine works like fossil_fatal() except that if called
648 ** recursively, the recursive call is a no-op.
649 **
650 ** Use this in places where an error might occur while doing
651 ** fatal error shutdown processing. Unlike fossil_panic() and
652 ** fossil_fatal() which never return, this routine might return if
653 ** the fatal error handing is already in process. The caller must
654 ** be prepared for this routine to return.
655 */
656 void fossil_fatal_recursive(const char *zFormat, ...){
657 char *z;
658 va_list ap;
659 int rc = 1;
660 if( mainInFatalError ) return;
661 mainInFatalError = 1;
662 va_start(ap, zFormat);
663 z = vmprintf(zFormat, ap);
664 va_end(ap);
665 #ifdef FOSSIL_ENABLE_JSON
666 if( g.json.isJsonMode ){
667 json_err( g.json.resultCode, z, 1 );
668 if( g.isHTTP ){
669 rc = 0 /* avoid HTTP 500 */;
670 }
671 } else
672 #endif
673 {
674 if( g.cgiOutput ){
675 g.cgiOutput = 0;
676 cgi_printf("<p class=\"generalError\">\n%h\n</p>\n", z);
677 cgi_reply();
678 }else{
679 fossil_trace("%s: %s\n", g.argv[0], z);
680 }
681 }
682 db_force_rollback();
683 fossil_exit(rc);
684 }
685
686
687 /* Print a warning message */
688 void fossil_warning(const char *zFormat, ...){
689 char *z;
690 va_list ap;
691 va_start(ap, zFormat);
692 z = vmprintf(zFormat, ap);
693 va_end(ap);
694 #ifdef FOSSIL_ENABLE_JSON
695 if(g.json.isJsonMode){
696 json_warn( FSL_JSON_W_UNKNOWN, z );
697 }else
698 #endif
699 {
700 if( g.cgiOutput ){
701 cgi_printf("<p class=\"generalError\">\n%h\n</p>\n", z);
702 }else{
703 fossil_trace("%s: %s\n", g.argv[0], z);
704 }
705 }
706 free(z);
707 }
708
709 /*
710 ** Malloc and free routines that cannot fail
711 */
712 void *fossil_malloc(size_t n){
713 void *p = malloc(n==0 ? 1 : n);
714 if( p==0 ) fossil_panic("out of memory");
715 return p;
716 }
717 void fossil_free(void *p){
718 free(p);
719 }
720 void *fossil_realloc(void *p, size_t n){
721 p = realloc(p, n);
722 if( p==0 ) fossil_panic("out of memory");
723 return p;
724 }
725
726 /*
727 ** This function implements a cross-platform "system()" interface.
728 */
729 int fossil_system(const char *zOrigCmd){
730 int rc;
731 #if defined(_WIN32)
732 /* On windows, we have to put double-quotes around the entire command.
733 ** Who knows why - this is just the way windows works.
734 */
735 char *zNewCmd = mprintf("\"%s\"", zOrigCmd);
736 WCHAR *zUnicode = fossil_utf8_to_unicode(zNewCmd);
737 if( g.fSystemTrace ) {
738 fossil_trace("SYSTEM: %s\n", zNewCmd);
739 }
740 rc = _wsystem(zUnicode);
741 fossil_unicode_free(zUnicode);
742 free(zNewCmd);
743 #else
744 /* On unix, evaluate the command directly.
745 */
746 if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zOrigCmd);
747 rc = system(zOrigCmd);
748 #endif
749 return rc;
750 }
751
752 /*
753 ** Turn off any NL to CRNL translation on the stream given as an
754 ** argument. This is a no-op on unix but is necessary on windows.
755 */
756 void fossil_binary_mode(FILE *p){
757 #if defined(_WIN32)
758 _setmode(_fileno(p), _O_BINARY);
759 #endif
760 #ifdef __EMX__ /* OS/2 */
761 setmode(fileno(p), O_BINARY);
762 #endif
763 }
764
765
766
767 /*
768 ** Return a name for an SQLite error code
769 */
770 static const char *sqlite_error_code_name(int iCode){
771 static char zCode[30];
772 switch( iCode & 0xff ){
773 case SQLITE_OK: return "SQLITE_OK";
774 case SQLITE_ERROR: return "SQLITE_ERROR";
775 case SQLITE_PERM: return "SQLITE_PERM";
776 case SQLITE_ABORT: return "SQLITE_ABORT";
777 case SQLITE_BUSY: return "SQLITE_BUSY";
778 case SQLITE_NOMEM: return "SQLITE_NOMEM";
779 case SQLITE_READONLY: return "SQLITE_READONLY";
780 case SQLITE_INTERRUPT: return "SQLITE_INTERRUPT";
781 case SQLITE_IOERR: return "SQLITE_IOERR";
782 case SQLITE_CORRUPT: return "SQLITE_CORRUPT";
783 case SQLITE_FULL: return "SQLITE_FULL";
784 case SQLITE_CANTOPEN: return "SQLITE_CANTOPEN";
785 case SQLITE_PROTOCOL: return "SQLITE_PROTOCOL";
786 case SQLITE_EMPTY: return "SQLITE_EMPTY";
787 case SQLITE_SCHEMA: return "SQLITE_SCHEMA";
788 case SQLITE_CONSTRAINT: return "SQLITE_CONSTRAINT";
789 case SQLITE_MISMATCH: return "SQLITE_MISMATCH";
790 case SQLITE_MISUSE: return "SQLITE_MISUSE";
791 case SQLITE_NOLFS: return "SQLITE_NOLFS";
792 case SQLITE_FORMAT: return "SQLITE_FORMAT";
793 case SQLITE_RANGE: return "SQLITE_RANGE";
794 case SQLITE_NOTADB: return "SQLITE_NOTADB";
795 default: {
796 sqlite3_snprintf(sizeof(zCode),zCode,"error code %d",iCode);
797 }
798 }
799 return zCode;
800 }
801
802 /* Error logs from SQLite */
803 void fossil_sqlite_log(void *notUsed, int iCode, const char *zErrmsg){
804 fossil_warning("%s: %s", sqlite_error_code_name(iCode), zErrmsg);
805 }
806
807 /*
808 ** Print a usage comment and quit
809 */
810 void usage(const char *zFormat){
811 fossil_fatal("Usage: %s %s %s\n", g.argv[0], g.argv[1], zFormat);
@@ -812,11 +611,11 @@
812 }
813
814 /*
815 ** Remove n elements from g.argv beginning with the i-th element.
816 */
817 void remove_from_argv(int i, int n){
818 int j;
819 for(j=i+n; j<g.argc; i++, j++){
820 g.argv[i] = g.argv[j];
821 }
822 g.argc = i;
@@ -931,14 +730,17 @@
931 **
932 ** List all web pages
933 */
934 void cmd_test_webpage_list(void){
935 int i, nCmd;
936 const char *aCmd[count(aWebpage)];
937 for(i=nCmd=0; i<count(aWebpage); i++){
938 aCmd[nCmd++] = aWebpage[i].zName;
 
 
939 }
 
940 multi_column_list(aCmd, nCmd);
941 }
942
943 /*
944 ** COMMAND: version
@@ -964,14 +766,17 @@
964 **
965 ** %fossil help Show common commands
966 ** %fossil help --all Show both common and auxiliary commands
967 ** %fossil help --test Show test commands only
968 ** %fossil help --aux Show auxiliary commands only
 
969 */
970 void help_cmd(void){
971 int rc, idx;
972 const char *z;
 
 
973 if( g.argc<3 ){
974 z = g.argv[0];
975 fossil_print(
976 "Usage: %s help COMMAND\n"
977 "Common COMMANDs: (use \"%s help --all\" for a complete list)\n",
@@ -982,33 +787,46 @@
982 }
983 if( find_option("all",0,0) ){
984 command_list(0, CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER);
985 return;
986 }
987 if( find_option("aux",0,0) ){
 
 
 
 
988 command_list(0, CMDFLAG_2ND_TIER);
989 return;
990 }
991 if( find_option("test",0,0) ){
992 command_list(0, CMDFLAG_TEST);
993 return;
 
 
 
 
 
 
 
 
994 }
995 rc = name_search(g.argv[2], aCommand, count(aCommand), &idx);
996 if( rc==1 ){
997 fossil_print("unknown command: %s\nAvailable commands:\n", g.argv[2]);
998 command_list(0, 0xff);
 
999 fossil_exit(1);
1000 }else if( rc==2 ){
1001 fossil_print("ambiguous command prefix: %s\nMatching commands:\n",
1002 g.argv[2]);
1003 command_list(g.argv[2], 0xff);
1004 fossil_exit(1);
1005 }
1006 z = aCmdHelp[idx];
1007 if( z==0 ){
1008 fossil_fatal("no help available for the %s command",
1009 aCommand[idx].zName);
1010 }
1011 while( *z ){
1012 if( *z=='%' && strncmp(z, "%fossil", 7)==0 ){
1013 fossil_print("%s", g.argv[0]);
1014 z += 7;
@@ -1030,20 +848,20 @@
1030 if( zCmd==0 ) zCmd = P("name");
1031 style_header("Command-line Help");
1032 if( zCmd ){
1033 int rc, idx;
1034 char *z, *s, *d;
1035
1036 style_submenu_element("Command-List", "Command-List", "%s/help", g.zTop);
1037 @ <h1>The "%s(zCmd)" command:</h1>
1038 rc = name_search(zCmd, aCommand, count(aCommand), &idx);
1039 if( rc==1 ){
1040 @ unknown command: %s(zCmd)
1041 }else if( rc==2 ){
1042 @ ambiguous command prefix: %s(zCmd)
1043 }else{
1044 z = (char*)aCmdHelp[idx];
1045 if( z==0 ){
1046 @ no help available for the %s(aCommand[idx].zName) command
1047 }else{
1048 z=s=d=mprintf("%s",z);
1049 while( *s ){
@@ -1065,21 +883,52 @@
1065
1066 @ <h1>Available commands:</h1>
1067 @ <table border="0"><tr>
1068 for(i=j=0; i<count(aCommand); i++){
1069 const char *z = aCommand[i].zName;
1070 if( strncmp(z,"test",4)==0 ) continue;
1071 j++;
1072 }
1073 n = (j+6)/7;
1074 for(i=j=0; i<count(aCommand); i++){
1075 const char *z = aCommand[i].zName;
1076 if( strncmp(z,"test",4)==0 ) continue;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1077 if( j==0 ){
1078 @ <td valign="top"><ul>
1079 }
1080 @ <li><a href="%s(g.zTop)/help?cmd=%s(z)">%s(z)</a>
 
 
 
 
1081 j++;
1082 if( j>=n ){
1083 @ </ul></td>
1084 j = 0;
1085 }
@@ -1086,10 +935,11 @@
1086 }
1087 if( j>0 ){
1088 @ </ul></td>
1089 }
1090 @ </tr></table>
 
1091 }
1092 style_footer();
1093 }
1094
1095 /*
@@ -1102,11 +952,11 @@
1102 style_header("Testpage: All Help Text");
1103 for(i=0; i<count(aCommand); i++){
1104 if( memcmp(aCommand[i].zName, "test", 4)==0 ) continue;
1105 @ <h2>%s(aCommand[i].zName):</h2>
1106 @ <blockquote><pre>
1107 @ %h(aCmdHelp[i])
1108 @ </pre></blockquote>
1109 }
1110 style_footer();
1111 }
1112
@@ -1501,10 +1351,61 @@
1501
1502 /* Return the result.
1503 */
1504 cgi_reply();
1505 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1506
1507 /*
1508 ** COMMAND: cgi*
1509 **
1510 ** Usage: %fossil ?cgi? SCRIPT
@@ -1601,61 +1502,10 @@
1601 }else{
1602 process_one_web_page(zNotFound, pFileGlob);
1603 }
1604 }
1605
1606 /* If the CGI program contains one or more lines of the form
1607 **
1608 ** redirect: repository-filename http://hostname/path/%s
1609 **
1610 ** then control jumps here. Search each repository for an artifact ID
1611 ** that matches the "name" CGI parameter and for the first match,
1612 ** redirect to the corresponding URL with the "name" CGI parameter
1613 ** inserted. Paint an error page if no match is found.
1614 **
1615 ** If there is a line of the form:
1616 **
1617 ** redirect: * URL
1618 **
1619 ** Then a redirect is made to URL if no match is found. Otherwise a
1620 ** very primitive error message is returned.
1621 */
1622 void redirect_web_page(int nRedirect, char **azRedirect){
1623 int i; /* Loop counter */
1624 const char *zNotFound = 0; /* Not found URL */
1625 const char *zName = P("name");
1626 set_base_url(0);
1627 if( zName==0 ){
1628 zName = P("SCRIPT_NAME");
1629 if( zName && zName[0]=='/' ) zName++;
1630 }
1631 if( zName && validate16(zName, strlen(zName)) ){
1632 for(i=0; i<nRedirect; i++){
1633 if( fossil_strcmp(azRedirect[i*2],"*")==0 ){
1634 zNotFound = azRedirect[i*2+1];
1635 continue;
1636 }
1637 db_open_repository(azRedirect[i*2]);
1638 if( db_exists("SELECT 1 FROM blob WHERE uuid GLOB '%s*'", zName) ){
1639 cgi_redirectf(azRedirect[i*2+1], zName);
1640 return;
1641 }
1642 db_close(1);
1643 }
1644 }
1645 if( zNotFound ){
1646 cgi_redirectf(zNotFound, zName);
1647 }else{
1648 @ <html>
1649 @ <head><title>No Such Object</title></head>
1650 @ <body>
1651 @ <p>No such object: <b>%h(zName)</b></p>
1652 @ </body>
1653 cgi_reply();
1654 }
1655 }
1656
1657 /*
1658 ** If g.argv[2] exists then it is either the name of a repository
1659 ** that will be used by a server, or else it is a directory that
1660 ** contains multiple repositories that can be served. If g.argv[2]
1661 ** is a directory, the repositories it contains must be named
@@ -1888,10 +1738,11 @@
1888 int isUiCmd; /* True if command is "ui", not "server' */
1889 const char *zNotFound; /* The --notfound option or NULL */
1890 int flags = 0; /* Server flags */
1891 const char *zAltBase; /* Argument to the --baseurl option */
1892 const char *zFileGlob; /* Static content must match this */
 
1893
1894 #if defined(_WIN32)
1895 const char *zStopperFile; /* Name of file used to terminate server */
1896 zStopperFile = find_option("stopper", 0, 1);
1897 #endif
@@ -1914,10 +1765,16 @@
1914 flags |= HTTP_SERVER_LOCALHOST;
1915 g.useLocalauth = 1;
1916 }
1917 find_server_repository(isUiCmd && zNotFound==0);
1918 if( zPort ){
 
 
 
 
 
 
1919 iPort = mxPort = atoi(zPort);
1920 }else{
1921 iPort = db_get_int("http-port", 8080);
1922 mxPort = iPort+100;
1923 }
@@ -1925,11 +1782,12 @@
1925 /* Unix implementation */
1926 if( isUiCmd ){
1927 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1928 zBrowser = db_get("web-browser", 0);
1929 if( zBrowser==0 ){
1930 static const char *const azBrowserProg[] = { "xdg-open", "gnome-open", "firefox" };
 
1931 int i;
1932 zBrowser = "echo";
1933 for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
1934 if( binaryOnPath(azBrowserProg[i]) ){
1935 zBrowser = azBrowserProg[i];
@@ -1938,14 +1796,18 @@
1938 }
1939 }
1940 #else
1941 zBrowser = db_get("web-browser", "open");
1942 #endif
1943 zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
 
 
 
 
1944 }
1945 db_close(1);
1946 if( cgi_http_server(iPort, mxPort, zBrowserCmd, flags) ){
1947 fossil_fatal("unable to listen on TCP socket %d", iPort);
1948 }
1949 g.sslNotAvailable = 1;
1950 g.httpIn = stdin;
1951 g.httpOut = stdout;
@@ -1959,16 +1821,20 @@
1959 process_one_web_page(zNotFound, glob_create(zFileGlob));
1960 #else
1961 /* Win32 implementation */
1962 if( isUiCmd ){
1963 zBrowser = db_get("web-browser", "start");
1964 zBrowserCmd = mprintf("%s http://127.0.0.1:%%d/", zBrowser);
 
 
 
 
1965 }
1966 db_close(1);
1967 if( win32_http_service(iPort, zNotFound, zFileGlob, flags) ){
1968 win32_http_server(iPort, mxPort, zBrowserCmd,
1969 zStopperFile, zNotFound, zFileGlob, flags);
1970 }
1971 #endif
1972 }
1973
1974 /*
1975
--- src/main.c
+++ src/main.c
@@ -31,11 +31,11 @@
31 #else
32 # include <errno.h> /* errno global */
33 #endif
34 #if INTERFACE
35 #ifdef FOSSIL_ENABLE_JSON
36 # include "cson_amalgamation.h" /* JSON API. */
37 # include "json_detail.h"
38 #endif
39 #ifdef FOSSIL_ENABLE_TCL
40 #include "tcl.h"
41 #endif
@@ -172,14 +172,15 @@
172 char *urlPasswd; /* Password for http: */
173 char *urlCanonical; /* Canonical representation of the URL */
174 char *urlProxyAuth; /* Proxy-Authorizer: string */
175 char *urlFossil; /* The fossil query parameter on ssh: */
176 char *urlShell; /* The shell query parameter on ssh: */
177 unsigned urlFlags; /* Boolean flags controlling URL processing */
178
179 const char *zLogin; /* Login name. "" if not logged in. */
180 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
181 ** SSL client identity */
182 int useLocalauth; /* No login required if from 127.0.0.1 */
183 int noPswd; /* Logged in without password (on 127.0.0.1) */
184 int userUid; /* Integer user id */
185
186 /* Information used to populate the RCVFROM table */
@@ -223,11 +224,12 @@
224 reported. In JSON mode we try to
225 always output JSON-form error
226 responses and always exit() with
227 code 0 to avoid an HTTP 500 error.
228 */
229 int resultCode; /* used for passing back specific codes
230 ** from /json callbacks. */
231 int errorDetailParanoia; /* 0=full error codes, 1=%10, 2=%100, 3=%1000 */
232 cson_output_opt outOpt; /* formatting options for JSON mode. */
233 cson_value * authToken; /* authentication token */
234 char const * jsonp; /* Name of JSONP function wrapper. */
235 unsigned char dispatchDepth /* Tells JSON command dispatching
@@ -332,11 +334,11 @@
334
335 /*
336 ** atexit() handler which frees up "some" of the resources
337 ** used by fossil.
338 */
339 static void fossil_atexit(void) {
340 #ifdef FOSSIL_ENABLE_JSON
341 cson_value_free(g.json.gc.v);
342 memset(&g.json, 0, sizeof(g.json));
343 #endif
344 free(g.zErrMsg);
@@ -365,11 +367,11 @@
367 char *z; /* General use string pointer */
368 char **newArgv; /* New expanded g.argv under construction */
369 char const * zFileName; /* input file name */
370 FILE * zInFile; /* input FILE */
371 #if defined(_WIN32)
372 wchar_t buf[MAX_PATH];
373 #endif
374
375 g.argc = argc;
376 g.argv = argv;
377 sqlite3_initialize();
@@ -453,10 +455,49 @@
455 }
456 return zNewArgv;
457 }
458 #endif
459
460 /*
461 ** Return a name for an SQLite error code
462 */
463 static const char *sqlite_error_code_name(int iCode){
464 static char zCode[30];
465 switch( iCode & 0xff ){
466 case SQLITE_OK: return "SQLITE_OK";
467 case SQLITE_ERROR: return "SQLITE_ERROR";
468 case SQLITE_PERM: return "SQLITE_PERM";
469 case SQLITE_ABORT: return "SQLITE_ABORT";
470 case SQLITE_BUSY: return "SQLITE_BUSY";
471 case SQLITE_NOMEM: return "SQLITE_NOMEM";
472 case SQLITE_READONLY: return "SQLITE_READONLY";
473 case SQLITE_INTERRUPT: return "SQLITE_INTERRUPT";
474 case SQLITE_IOERR: return "SQLITE_IOERR";
475 case SQLITE_CORRUPT: return "SQLITE_CORRUPT";
476 case SQLITE_FULL: return "SQLITE_FULL";
477 case SQLITE_CANTOPEN: return "SQLITE_CANTOPEN";
478 case SQLITE_PROTOCOL: return "SQLITE_PROTOCOL";
479 case SQLITE_EMPTY: return "SQLITE_EMPTY";
480 case SQLITE_SCHEMA: return "SQLITE_SCHEMA";
481 case SQLITE_CONSTRAINT: return "SQLITE_CONSTRAINT";
482 case SQLITE_MISMATCH: return "SQLITE_MISMATCH";
483 case SQLITE_MISUSE: return "SQLITE_MISUSE";
484 case SQLITE_NOLFS: return "SQLITE_NOLFS";
485 case SQLITE_FORMAT: return "SQLITE_FORMAT";
486 case SQLITE_RANGE: return "SQLITE_RANGE";
487 case SQLITE_NOTADB: return "SQLITE_NOTADB";
488 default: {
489 sqlite3_snprintf(sizeof(zCode),zCode,"error code %d",iCode);
490 }
491 }
492 return zCode;
493 }
494
495 /* Error logs from SQLite */
496 static void fossil_sqlite_log(void *notUsed, int iCode, const char *zErrmsg){
497 fossil_warning("%s: %s", sqlite_error_code_name(iCode), zErrmsg);
498 }
499
500 /*
501 ** This procedure runs first.
502 */
503 #if defined(_WIN32) && !defined(BROKEN_MINGW_CMDLINE)
@@ -560,252 +601,10 @@
601 fossil_exit(0);
602 /*NOT_REACHED*/
603 return 0;
604 }
605
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
606 /*
607 ** Print a usage comment and quit
608 */
609 void usage(const char *zFormat){
610 fossil_fatal("Usage: %s %s %s\n", g.argv[0], g.argv[1], zFormat);
@@ -812,11 +611,11 @@
611 }
612
613 /*
614 ** Remove n elements from g.argv beginning with the i-th element.
615 */
616 static void remove_from_argv(int i, int n){
617 int j;
618 for(j=i+n; j<g.argc; i++, j++){
619 g.argv[i] = g.argv[j];
620 }
621 g.argc = i;
@@ -931,14 +730,17 @@
730 **
731 ** List all web pages
732 */
733 void cmd_test_webpage_list(void){
734 int i, nCmd;
735 const char *aCmd[count(aCommand)];
736 for(i=nCmd=0; i<count(aCommand); i++){
737 if(0x08 & aCommand[i].cmdFlags){
738 aCmd[nCmd++] = aWebpage[i].zName;
739 }
740 }
741 assert(nCmd && "page list is empty?");
742 multi_column_list(aCmd, nCmd);
743 }
744
745 /*
746 ** COMMAND: version
@@ -964,14 +766,17 @@
766 **
767 ** %fossil help Show common commands
768 ** %fossil help --all Show both common and auxiliary commands
769 ** %fossil help --test Show test commands only
770 ** %fossil help --aux Show auxiliary commands only
771 ** %fossil help --www Show list of WWW pages
772 */
773 void help_cmd(void){
774 int rc, idx, isPage = 0;
775 const char *z;
776 char const * zCmdOrPage;
777 char const * zCmdOrPagePlural;
778 if( g.argc<3 ){
779 z = g.argv[0];
780 fossil_print(
781 "Usage: %s help COMMAND\n"
782 "Common COMMANDs: (use \"%s help --all\" for a complete list)\n",
@@ -982,33 +787,46 @@
787 }
788 if( find_option("all",0,0) ){
789 command_list(0, CMDFLAG_1ST_TIER | CMDFLAG_2ND_TIER);
790 return;
791 }
792 else if( find_option("www",0,0) ){
793 command_list(0, CMDFLAG_WEBPAGE);
794 return;
795 }
796 else if( find_option("aux",0,0) ){
797 command_list(0, CMDFLAG_2ND_TIER);
798 return;
799 }
800 else if( find_option("test",0,0) ){
801 command_list(0, CMDFLAG_TEST);
802 return;
803 }
804 isPage = ('/' == *g.argv[2]) ? 1 : 0;
805 if(isPage){
806 zCmdOrPage = "page";
807 zCmdOrPagePlural = "pages";
808 }else{
809 zCmdOrPage = "command";
810 zCmdOrPagePlural = "commands";
811 }
812 rc = name_search(g.argv[2], aCommand, count(aCommand), &idx);
813 if( rc==1 ){
814 fossil_print("unknown %s: %s\nAvailable %s:\n",
815 zCmdOrPage, g.argv[2], zCmdOrPagePlural);
816 command_list(0, isPage ? CMDFLAG_WEBPAGE : (0xff & ~CMDFLAG_WEBPAGE));
817 fossil_exit(1);
818 }else if( rc==2 ){
819 fossil_print("ambiguous %s prefix: %s\nMatching %s:\n",
820 zCmdOrPage, g.argv[2], zCmdOrPagePlural);
821 command_list(g.argv[2], 0xff);
822 fossil_exit(1);
823 }
824 z = aCmdHelp[idx].zText;
825 if( z==0 ){
826 fossil_fatal("no help available for the %s %s",
827 aCommand[idx].zName, zCmdOrPage);
828 }
829 while( *z ){
830 if( *z=='%' && strncmp(z, "%fossil", 7)==0 ){
831 fossil_print("%s", g.argv[0]);
832 z += 7;
@@ -1030,20 +848,20 @@
848 if( zCmd==0 ) zCmd = P("name");
849 style_header("Command-line Help");
850 if( zCmd ){
851 int rc, idx;
852 char *z, *s, *d;
853 char const * zCmdOrPage = ('/'==*zCmd) ? "page" : "command";
854 style_submenu_element("Command-List", "Command-List", "%s/help", g.zTop);
855 @ <h1>The "%s(zCmd)" %s(zCmdOrPage):</h1>
856 rc = name_search(zCmd, aCommand, count(aCommand), &idx);
857 if( rc==1 ){
858 @ unknown command: %s(zCmd)
859 }else if( rc==2 ){
860 @ ambiguous command prefix: %s(zCmd)
861 }else{
862 z = (char*)aCmdHelp[idx].zText;
863 if( z==0 ){
864 @ no help available for the %s(aCommand[idx].zName) command
865 }else{
866 z=s=d=mprintf("%s",z);
867 while( *s ){
@@ -1065,21 +883,52 @@
883
884 @ <h1>Available commands:</h1>
885 @ <table border="0"><tr>
886 for(i=j=0; i<count(aCommand); i++){
887 const char *z = aCommand[i].zName;
888 if( '/'==*z || strncmp(z,"test",4)==0 ) continue;
889 j++;
890 }
891 n = (j+6)/7;
892 for(i=j=0; i<count(aCommand); i++){
893 const char *z = aCommand[i].zName;
894 if( '/'==*z || strncmp(z,"test",4)==0 ) continue;
895 if( j==0 ){
896 @ <td valign="top"><ul>
897 }
898 @ <li><a href="%s(g.zTop)/help?cmd=%s(z)">%s(z)</a></li>
899 j++;
900 if( j>=n ){
901 @ </ul></td>
902 j = 0;
903 }
904 }
905 if( j>0 ){
906 @ </ul></td>
907 }
908 @ </tr></table>
909
910 @ <h1>Available pages:</h1>
911 @ (Only pages with help text are linked.)
912 @ <table border="0"><tr>
913 for(i=j=0; i<count(aCommand); i++){
914 const char *z = aCommand[i].zName;
915 if( '/'!=*z ) continue;
916 j++;
917 }
918 n = (j+4)/5;
919 for(i=j=0; i<count(aCommand); i++){
920 const char *z = aCommand[i].zName;
921 if( '/'!=*z ) continue;
922 if( j==0 ){
923 @ <td valign="top"><ul>
924 }
925 if( aCmdHelp[i].zText && *aCmdHelp[i].zText ){
926 @ <li><a href="%s(g.zTop)/help?cmd=%s(z)">%s(z+1)</a></li>
927 }else{
928 @ <li>%s(z+1)</li>
929 }
930 j++;
931 if( j>=n ){
932 @ </ul></td>
933 j = 0;
934 }
@@ -1086,10 +935,11 @@
935 }
936 if( j>0 ){
937 @ </ul></td>
938 }
939 @ </tr></table>
940
941 }
942 style_footer();
943 }
944
945 /*
@@ -1102,11 +952,11 @@
952 style_header("Testpage: All Help Text");
953 for(i=0; i<count(aCommand); i++){
954 if( memcmp(aCommand[i].zName, "test", 4)==0 ) continue;
955 @ <h2>%s(aCommand[i].zName):</h2>
956 @ <blockquote><pre>
957 @ %h(aCmdHelp[i].zText)
958 @ </pre></blockquote>
959 }
960 style_footer();
961 }
962
@@ -1501,10 +1351,61 @@
1351
1352 /* Return the result.
1353 */
1354 cgi_reply();
1355 }
1356
1357 /* If the CGI program contains one or more lines of the form
1358 **
1359 ** redirect: repository-filename http://hostname/path/%s
1360 **
1361 ** then control jumps here. Search each repository for an artifact ID
1362 ** that matches the "name" CGI parameter and for the first match,
1363 ** redirect to the corresponding URL with the "name" CGI parameter
1364 ** inserted. Paint an error page if no match is found.
1365 **
1366 ** If there is a line of the form:
1367 **
1368 ** redirect: * URL
1369 **
1370 ** Then a redirect is made to URL if no match is found. Otherwise a
1371 ** very primitive error message is returned.
1372 */
1373 static void redirect_web_page(int nRedirect, char **azRedirect){
1374 int i; /* Loop counter */
1375 const char *zNotFound = 0; /* Not found URL */
1376 const char *zName = P("name");
1377 set_base_url(0);
1378 if( zName==0 ){
1379 zName = P("SCRIPT_NAME");
1380 if( zName && zName[0]=='/' ) zName++;
1381 }
1382 if( zName && validate16(zName, strlen(zName)) ){
1383 for(i=0; i<nRedirect; i++){
1384 if( fossil_strcmp(azRedirect[i*2],"*")==0 ){
1385 zNotFound = azRedirect[i*2+1];
1386 continue;
1387 }
1388 db_open_repository(azRedirect[i*2]);
1389 if( db_exists("SELECT 1 FROM blob WHERE uuid GLOB '%s*'", zName) ){
1390 cgi_redirectf(azRedirect[i*2+1], zName);
1391 return;
1392 }
1393 db_close(1);
1394 }
1395 }
1396 if( zNotFound ){
1397 cgi_redirectf(zNotFound, zName);
1398 }else{
1399 @ <html>
1400 @ <head><title>No Such Object</title></head>
1401 @ <body>
1402 @ <p>No such object: <b>%h(zName)</b></p>
1403 @ </body>
1404 cgi_reply();
1405 }
1406 }
1407
1408 /*
1409 ** COMMAND: cgi*
1410 **
1411 ** Usage: %fossil ?cgi? SCRIPT
@@ -1601,61 +1502,10 @@
1502 }else{
1503 process_one_web_page(zNotFound, pFileGlob);
1504 }
1505 }
1506
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1507 /*
1508 ** If g.argv[2] exists then it is either the name of a repository
1509 ** that will be used by a server, or else it is a directory that
1510 ** contains multiple repositories that can be served. If g.argv[2]
1511 ** is a directory, the repositories it contains must be named
@@ -1888,10 +1738,11 @@
1738 int isUiCmd; /* True if command is "ui", not "server' */
1739 const char *zNotFound; /* The --notfound option or NULL */
1740 int flags = 0; /* Server flags */
1741 const char *zAltBase; /* Argument to the --baseurl option */
1742 const char *zFileGlob; /* Static content must match this */
1743 char *zIpAddr = 0; /* Bind to this IP address */
1744
1745 #if defined(_WIN32)
1746 const char *zStopperFile; /* Name of file used to terminate server */
1747 zStopperFile = find_option("stopper", 0, 1);
1748 #endif
@@ -1914,10 +1765,16 @@
1765 flags |= HTTP_SERVER_LOCALHOST;
1766 g.useLocalauth = 1;
1767 }
1768 find_server_repository(isUiCmd && zNotFound==0);
1769 if( zPort ){
1770 int i;
1771 for(i=strlen(zPort)-1; i>=0 && zPort[i]!=':'; i--){}
1772 if( i>0 ){
1773 zIpAddr = mprintf("%.*s", i, zPort);
1774 zPort += i+1;
1775 }
1776 iPort = mxPort = atoi(zPort);
1777 }else{
1778 iPort = db_get_int("http-port", 8080);
1779 mxPort = iPort+100;
1780 }
@@ -1925,11 +1782,12 @@
1782 /* Unix implementation */
1783 if( isUiCmd ){
1784 #if !defined(__DARWIN__) && !defined(__APPLE__) && !defined(__HAIKU__)
1785 zBrowser = db_get("web-browser", 0);
1786 if( zBrowser==0 ){
1787 static const char *const azBrowserProg[] =
1788 { "xdg-open", "gnome-open", "firefox", "google-chrome" };
1789 int i;
1790 zBrowser = "echo";
1791 for(i=0; i<sizeof(azBrowserProg)/sizeof(azBrowserProg[0]); i++){
1792 if( binaryOnPath(azBrowserProg[i]) ){
1793 zBrowser = azBrowserProg[i];
@@ -1938,14 +1796,18 @@
1796 }
1797 }
1798 #else
1799 zBrowser = db_get("web-browser", "open");
1800 #endif
1801 if( zIpAddr ){
1802 zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr);
1803 }else{
1804 zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
1805 }
1806 }
1807 db_close(1);
1808 if( cgi_http_server(iPort, mxPort, zBrowserCmd, zIpAddr, flags) ){
1809 fossil_fatal("unable to listen on TCP socket %d", iPort);
1810 }
1811 g.sslNotAvailable = 1;
1812 g.httpIn = stdin;
1813 g.httpOut = stdout;
@@ -1959,16 +1821,20 @@
1821 process_one_web_page(zNotFound, glob_create(zFileGlob));
1822 #else
1823 /* Win32 implementation */
1824 if( isUiCmd ){
1825 zBrowser = db_get("web-browser", "start");
1826 if( zIpAddr ){
1827 zBrowserCmd = mprintf("%s http://%s:%%d/ &", zBrowser, zIpAddr);
1828 }else{
1829 zBrowserCmd = mprintf("%s http://localhost:%%d/ &", zBrowser);
1830 }
1831 }
1832 db_close(1);
1833 if( win32_http_service(iPort, zNotFound, zFileGlob, flags) ){
1834 win32_http_server(iPort, mxPort, zBrowserCmd,
1835 zStopperFile, zNotFound, zFileGlob, zIpAddr, flags);
1836 }
1837 #endif
1838 }
1839
1840 /*
1841
+22 -2
--- src/main.mk
+++ src/main.mk
@@ -60,10 +60,11 @@
6060
$(SRCDIR)/json_dir.c \
6161
$(SRCDIR)/json_finfo.c \
6262
$(SRCDIR)/json_login.c \
6363
$(SRCDIR)/json_query.c \
6464
$(SRCDIR)/json_report.c \
65
+ $(SRCDIR)/json_status.c \
6566
$(SRCDIR)/json_tag.c \
6667
$(SRCDIR)/json_timeline.c \
6768
$(SRCDIR)/json_user.c \
6869
$(SRCDIR)/json_wiki.c \
6970
$(SRCDIR)/leaf.c \
@@ -107,10 +108,11 @@
107108
$(SRCDIR)/unicode.c \
108109
$(SRCDIR)/update.c \
109110
$(SRCDIR)/url.c \
110111
$(SRCDIR)/user.c \
111112
$(SRCDIR)/utf8.c \
113
+ $(SRCDIR)/util.c \
112114
$(SRCDIR)/verify.c \
113115
$(SRCDIR)/vfile.c \
114116
$(SRCDIR)/wiki.c \
115117
$(SRCDIR)/wikiformat.c \
116118
$(SRCDIR)/winhttp.c \
@@ -166,10 +168,11 @@
166168
$(OBJDIR)/json_dir_.c \
167169
$(OBJDIR)/json_finfo_.c \
168170
$(OBJDIR)/json_login_.c \
169171
$(OBJDIR)/json_query_.c \
170172
$(OBJDIR)/json_report_.c \
173
+ $(OBJDIR)/json_status_.c \
171174
$(OBJDIR)/json_tag_.c \
172175
$(OBJDIR)/json_timeline_.c \
173176
$(OBJDIR)/json_user_.c \
174177
$(OBJDIR)/json_wiki_.c \
175178
$(OBJDIR)/leaf_.c \
@@ -213,10 +216,11 @@
213216
$(OBJDIR)/unicode_.c \
214217
$(OBJDIR)/update_.c \
215218
$(OBJDIR)/url_.c \
216219
$(OBJDIR)/user_.c \
217220
$(OBJDIR)/utf8_.c \
221
+ $(OBJDIR)/util_.c \
218222
$(OBJDIR)/verify_.c \
219223
$(OBJDIR)/vfile_.c \
220224
$(OBJDIR)/wiki_.c \
221225
$(OBJDIR)/wikiformat_.c \
222226
$(OBJDIR)/winhttp_.c \
@@ -272,10 +276,11 @@
272276
$(OBJDIR)/json_dir.o \
273277
$(OBJDIR)/json_finfo.o \
274278
$(OBJDIR)/json_login.o \
275279
$(OBJDIR)/json_query.o \
276280
$(OBJDIR)/json_report.o \
281
+ $(OBJDIR)/json_status.o \
277282
$(OBJDIR)/json_tag.o \
278283
$(OBJDIR)/json_timeline.o \
279284
$(OBJDIR)/json_user.o \
280285
$(OBJDIR)/json_wiki.o \
281286
$(OBJDIR)/leaf.o \
@@ -319,10 +324,11 @@
319324
$(OBJDIR)/unicode.o \
320325
$(OBJDIR)/update.o \
321326
$(OBJDIR)/url.o \
322327
$(OBJDIR)/user.o \
323328
$(OBJDIR)/utf8.o \
329
+ $(OBJDIR)/util.o \
324330
$(OBJDIR)/verify.o \
325331
$(OBJDIR)/vfile.o \
326332
$(OBJDIR)/wiki.o \
327333
$(OBJDIR)/wikiformat.o \
328334
$(OBJDIR)/winhttp.o \
@@ -396,14 +402,14 @@
396402
397403
398404
$(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
399405
$(OBJDIR)/mkindex $(TRANS_SRC) >$@
400406
$(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
401
- $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
407
+ $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_status_.c:$(OBJDIR)/json_status.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/util_.c:$(OBJDIR)/util.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
402408
touch $(OBJDIR)/headers
403409
$(OBJDIR)/headers: Makefile
404
-$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/json_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
410
+$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/json_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
405411
Makefile:
406412
$(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
407413
$(OBJDIR)/translate $(SRCDIR)/add.c >$(OBJDIR)/add_.c
408414
409415
$(OBJDIR)/add.o: $(OBJDIR)/add_.c $(OBJDIR)/add.h $(SRCDIR)/config.h
@@ -737,10 +743,17 @@
737743
738744
$(OBJDIR)/json_report.o: $(OBJDIR)/json_report_.c $(OBJDIR)/json_report.h $(SRCDIR)/config.h
739745
$(XTCC) -o $(OBJDIR)/json_report.o -c $(OBJDIR)/json_report_.c
740746
741747
$(OBJDIR)/json_report.h: $(OBJDIR)/headers
748
+$(OBJDIR)/json_status_.c: $(SRCDIR)/json_status.c $(OBJDIR)/translate
749
+ $(OBJDIR)/translate $(SRCDIR)/json_status.c >$(OBJDIR)/json_status_.c
750
+
751
+$(OBJDIR)/json_status.o: $(OBJDIR)/json_status_.c $(OBJDIR)/json_status.h $(SRCDIR)/config.h
752
+ $(XTCC) -o $(OBJDIR)/json_status.o -c $(OBJDIR)/json_status_.c
753
+
754
+$(OBJDIR)/json_status.h: $(OBJDIR)/headers
742755
$(OBJDIR)/json_tag_.c: $(SRCDIR)/json_tag.c $(OBJDIR)/translate
743756
$(OBJDIR)/translate $(SRCDIR)/json_tag.c >$(OBJDIR)/json_tag_.c
744757
745758
$(OBJDIR)/json_tag.o: $(OBJDIR)/json_tag_.c $(OBJDIR)/json_tag.h $(SRCDIR)/config.h
746759
$(XTCC) -o $(OBJDIR)/json_tag.o -c $(OBJDIR)/json_tag_.c
@@ -1066,10 +1079,17 @@
10661079
10671080
$(OBJDIR)/utf8.o: $(OBJDIR)/utf8_.c $(OBJDIR)/utf8.h $(SRCDIR)/config.h
10681081
$(XTCC) -o $(OBJDIR)/utf8.o -c $(OBJDIR)/utf8_.c
10691082
10701083
$(OBJDIR)/utf8.h: $(OBJDIR)/headers
1084
+$(OBJDIR)/util_.c: $(SRCDIR)/util.c $(OBJDIR)/translate
1085
+ $(OBJDIR)/translate $(SRCDIR)/util.c >$(OBJDIR)/util_.c
1086
+
1087
+$(OBJDIR)/util.o: $(OBJDIR)/util_.c $(OBJDIR)/util.h $(SRCDIR)/config.h
1088
+ $(XTCC) -o $(OBJDIR)/util.o -c $(OBJDIR)/util_.c
1089
+
1090
+$(OBJDIR)/util.h: $(OBJDIR)/headers
10711091
$(OBJDIR)/verify_.c: $(SRCDIR)/verify.c $(OBJDIR)/translate
10721092
$(OBJDIR)/translate $(SRCDIR)/verify.c >$(OBJDIR)/verify_.c
10731093
10741094
$(OBJDIR)/verify.o: $(OBJDIR)/verify_.c $(OBJDIR)/verify.h $(SRCDIR)/config.h
10751095
$(XTCC) -o $(OBJDIR)/verify.o -c $(OBJDIR)/verify_.c
10761096
--- src/main.mk
+++ src/main.mk
@@ -60,10 +60,11 @@
60 $(SRCDIR)/json_dir.c \
61 $(SRCDIR)/json_finfo.c \
62 $(SRCDIR)/json_login.c \
63 $(SRCDIR)/json_query.c \
64 $(SRCDIR)/json_report.c \
 
65 $(SRCDIR)/json_tag.c \
66 $(SRCDIR)/json_timeline.c \
67 $(SRCDIR)/json_user.c \
68 $(SRCDIR)/json_wiki.c \
69 $(SRCDIR)/leaf.c \
@@ -107,10 +108,11 @@
107 $(SRCDIR)/unicode.c \
108 $(SRCDIR)/update.c \
109 $(SRCDIR)/url.c \
110 $(SRCDIR)/user.c \
111 $(SRCDIR)/utf8.c \
 
112 $(SRCDIR)/verify.c \
113 $(SRCDIR)/vfile.c \
114 $(SRCDIR)/wiki.c \
115 $(SRCDIR)/wikiformat.c \
116 $(SRCDIR)/winhttp.c \
@@ -166,10 +168,11 @@
166 $(OBJDIR)/json_dir_.c \
167 $(OBJDIR)/json_finfo_.c \
168 $(OBJDIR)/json_login_.c \
169 $(OBJDIR)/json_query_.c \
170 $(OBJDIR)/json_report_.c \
 
171 $(OBJDIR)/json_tag_.c \
172 $(OBJDIR)/json_timeline_.c \
173 $(OBJDIR)/json_user_.c \
174 $(OBJDIR)/json_wiki_.c \
175 $(OBJDIR)/leaf_.c \
@@ -213,10 +216,11 @@
213 $(OBJDIR)/unicode_.c \
214 $(OBJDIR)/update_.c \
215 $(OBJDIR)/url_.c \
216 $(OBJDIR)/user_.c \
217 $(OBJDIR)/utf8_.c \
 
218 $(OBJDIR)/verify_.c \
219 $(OBJDIR)/vfile_.c \
220 $(OBJDIR)/wiki_.c \
221 $(OBJDIR)/wikiformat_.c \
222 $(OBJDIR)/winhttp_.c \
@@ -272,10 +276,11 @@
272 $(OBJDIR)/json_dir.o \
273 $(OBJDIR)/json_finfo.o \
274 $(OBJDIR)/json_login.o \
275 $(OBJDIR)/json_query.o \
276 $(OBJDIR)/json_report.o \
 
277 $(OBJDIR)/json_tag.o \
278 $(OBJDIR)/json_timeline.o \
279 $(OBJDIR)/json_user.o \
280 $(OBJDIR)/json_wiki.o \
281 $(OBJDIR)/leaf.o \
@@ -319,10 +324,11 @@
319 $(OBJDIR)/unicode.o \
320 $(OBJDIR)/update.o \
321 $(OBJDIR)/url.o \
322 $(OBJDIR)/user.o \
323 $(OBJDIR)/utf8.o \
 
324 $(OBJDIR)/verify.o \
325 $(OBJDIR)/vfile.o \
326 $(OBJDIR)/wiki.o \
327 $(OBJDIR)/wikiformat.o \
328 $(OBJDIR)/winhttp.o \
@@ -396,14 +402,14 @@
396
397
398 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
399 $(OBJDIR)/mkindex $(TRANS_SRC) >$@
400 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
401 $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
402 touch $(OBJDIR)/headers
403 $(OBJDIR)/headers: Makefile
404 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/json_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
405 Makefile:
406 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
407 $(OBJDIR)/translate $(SRCDIR)/add.c >$(OBJDIR)/add_.c
408
409 $(OBJDIR)/add.o: $(OBJDIR)/add_.c $(OBJDIR)/add.h $(SRCDIR)/config.h
@@ -737,10 +743,17 @@
737
738 $(OBJDIR)/json_report.o: $(OBJDIR)/json_report_.c $(OBJDIR)/json_report.h $(SRCDIR)/config.h
739 $(XTCC) -o $(OBJDIR)/json_report.o -c $(OBJDIR)/json_report_.c
740
741 $(OBJDIR)/json_report.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
742 $(OBJDIR)/json_tag_.c: $(SRCDIR)/json_tag.c $(OBJDIR)/translate
743 $(OBJDIR)/translate $(SRCDIR)/json_tag.c >$(OBJDIR)/json_tag_.c
744
745 $(OBJDIR)/json_tag.o: $(OBJDIR)/json_tag_.c $(OBJDIR)/json_tag.h $(SRCDIR)/config.h
746 $(XTCC) -o $(OBJDIR)/json_tag.o -c $(OBJDIR)/json_tag_.c
@@ -1066,10 +1079,17 @@
1066
1067 $(OBJDIR)/utf8.o: $(OBJDIR)/utf8_.c $(OBJDIR)/utf8.h $(SRCDIR)/config.h
1068 $(XTCC) -o $(OBJDIR)/utf8.o -c $(OBJDIR)/utf8_.c
1069
1070 $(OBJDIR)/utf8.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
1071 $(OBJDIR)/verify_.c: $(SRCDIR)/verify.c $(OBJDIR)/translate
1072 $(OBJDIR)/translate $(SRCDIR)/verify.c >$(OBJDIR)/verify_.c
1073
1074 $(OBJDIR)/verify.o: $(OBJDIR)/verify_.c $(OBJDIR)/verify.h $(SRCDIR)/config.h
1075 $(XTCC) -o $(OBJDIR)/verify.o -c $(OBJDIR)/verify_.c
1076
--- src/main.mk
+++ src/main.mk
@@ -60,10 +60,11 @@
60 $(SRCDIR)/json_dir.c \
61 $(SRCDIR)/json_finfo.c \
62 $(SRCDIR)/json_login.c \
63 $(SRCDIR)/json_query.c \
64 $(SRCDIR)/json_report.c \
65 $(SRCDIR)/json_status.c \
66 $(SRCDIR)/json_tag.c \
67 $(SRCDIR)/json_timeline.c \
68 $(SRCDIR)/json_user.c \
69 $(SRCDIR)/json_wiki.c \
70 $(SRCDIR)/leaf.c \
@@ -107,10 +108,11 @@
108 $(SRCDIR)/unicode.c \
109 $(SRCDIR)/update.c \
110 $(SRCDIR)/url.c \
111 $(SRCDIR)/user.c \
112 $(SRCDIR)/utf8.c \
113 $(SRCDIR)/util.c \
114 $(SRCDIR)/verify.c \
115 $(SRCDIR)/vfile.c \
116 $(SRCDIR)/wiki.c \
117 $(SRCDIR)/wikiformat.c \
118 $(SRCDIR)/winhttp.c \
@@ -166,10 +168,11 @@
168 $(OBJDIR)/json_dir_.c \
169 $(OBJDIR)/json_finfo_.c \
170 $(OBJDIR)/json_login_.c \
171 $(OBJDIR)/json_query_.c \
172 $(OBJDIR)/json_report_.c \
173 $(OBJDIR)/json_status_.c \
174 $(OBJDIR)/json_tag_.c \
175 $(OBJDIR)/json_timeline_.c \
176 $(OBJDIR)/json_user_.c \
177 $(OBJDIR)/json_wiki_.c \
178 $(OBJDIR)/leaf_.c \
@@ -213,10 +216,11 @@
216 $(OBJDIR)/unicode_.c \
217 $(OBJDIR)/update_.c \
218 $(OBJDIR)/url_.c \
219 $(OBJDIR)/user_.c \
220 $(OBJDIR)/utf8_.c \
221 $(OBJDIR)/util_.c \
222 $(OBJDIR)/verify_.c \
223 $(OBJDIR)/vfile_.c \
224 $(OBJDIR)/wiki_.c \
225 $(OBJDIR)/wikiformat_.c \
226 $(OBJDIR)/winhttp_.c \
@@ -272,10 +276,11 @@
276 $(OBJDIR)/json_dir.o \
277 $(OBJDIR)/json_finfo.o \
278 $(OBJDIR)/json_login.o \
279 $(OBJDIR)/json_query.o \
280 $(OBJDIR)/json_report.o \
281 $(OBJDIR)/json_status.o \
282 $(OBJDIR)/json_tag.o \
283 $(OBJDIR)/json_timeline.o \
284 $(OBJDIR)/json_user.o \
285 $(OBJDIR)/json_wiki.o \
286 $(OBJDIR)/leaf.o \
@@ -319,10 +324,11 @@
324 $(OBJDIR)/unicode.o \
325 $(OBJDIR)/update.o \
326 $(OBJDIR)/url.o \
327 $(OBJDIR)/user.o \
328 $(OBJDIR)/utf8.o \
329 $(OBJDIR)/util.o \
330 $(OBJDIR)/verify.o \
331 $(OBJDIR)/vfile.o \
332 $(OBJDIR)/wiki.o \
333 $(OBJDIR)/wikiformat.o \
334 $(OBJDIR)/winhttp.o \
@@ -396,14 +402,14 @@
402
403
404 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
405 $(OBJDIR)/mkindex $(TRANS_SRC) >$@
406 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
407 $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/glob_.c:$(OBJDIR)/glob.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/json_.c:$(OBJDIR)/json.h $(OBJDIR)/json_artifact_.c:$(OBJDIR)/json_artifact.h $(OBJDIR)/json_branch_.c:$(OBJDIR)/json_branch.h $(OBJDIR)/json_config_.c:$(OBJDIR)/json_config.h $(OBJDIR)/json_diff_.c:$(OBJDIR)/json_diff.h $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h $(OBJDIR)/json_status_.c:$(OBJDIR)/json_status.h $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/markdown_.c:$(OBJDIR)/markdown.h $(OBJDIR)/markdown_html_.c:$(OBJDIR)/markdown_html.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/moderate_.c:$(OBJDIR)/moderate.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/regexp_.c:$(OBJDIR)/regexp.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h $(OBJDIR)/util_.c:$(OBJDIR)/util.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/wysiwyg_.c:$(OBJDIR)/wysiwyg.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/xfersetup_.c:$(OBJDIR)/xfersetup.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
408 touch $(OBJDIR)/headers
409 $(OBJDIR)/headers: Makefile
410 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/json_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
411 Makefile:
412 $(OBJDIR)/add_.c: $(SRCDIR)/add.c $(OBJDIR)/translate
413 $(OBJDIR)/translate $(SRCDIR)/add.c >$(OBJDIR)/add_.c
414
415 $(OBJDIR)/add.o: $(OBJDIR)/add_.c $(OBJDIR)/add.h $(SRCDIR)/config.h
@@ -737,10 +743,17 @@
743
744 $(OBJDIR)/json_report.o: $(OBJDIR)/json_report_.c $(OBJDIR)/json_report.h $(SRCDIR)/config.h
745 $(XTCC) -o $(OBJDIR)/json_report.o -c $(OBJDIR)/json_report_.c
746
747 $(OBJDIR)/json_report.h: $(OBJDIR)/headers
748 $(OBJDIR)/json_status_.c: $(SRCDIR)/json_status.c $(OBJDIR)/translate
749 $(OBJDIR)/translate $(SRCDIR)/json_status.c >$(OBJDIR)/json_status_.c
750
751 $(OBJDIR)/json_status.o: $(OBJDIR)/json_status_.c $(OBJDIR)/json_status.h $(SRCDIR)/config.h
752 $(XTCC) -o $(OBJDIR)/json_status.o -c $(OBJDIR)/json_status_.c
753
754 $(OBJDIR)/json_status.h: $(OBJDIR)/headers
755 $(OBJDIR)/json_tag_.c: $(SRCDIR)/json_tag.c $(OBJDIR)/translate
756 $(OBJDIR)/translate $(SRCDIR)/json_tag.c >$(OBJDIR)/json_tag_.c
757
758 $(OBJDIR)/json_tag.o: $(OBJDIR)/json_tag_.c $(OBJDIR)/json_tag.h $(SRCDIR)/config.h
759 $(XTCC) -o $(OBJDIR)/json_tag.o -c $(OBJDIR)/json_tag_.c
@@ -1066,10 +1079,17 @@
1079
1080 $(OBJDIR)/utf8.o: $(OBJDIR)/utf8_.c $(OBJDIR)/utf8.h $(SRCDIR)/config.h
1081 $(XTCC) -o $(OBJDIR)/utf8.o -c $(OBJDIR)/utf8_.c
1082
1083 $(OBJDIR)/utf8.h: $(OBJDIR)/headers
1084 $(OBJDIR)/util_.c: $(SRCDIR)/util.c $(OBJDIR)/translate
1085 $(OBJDIR)/translate $(SRCDIR)/util.c >$(OBJDIR)/util_.c
1086
1087 $(OBJDIR)/util.o: $(OBJDIR)/util_.c $(OBJDIR)/util.h $(SRCDIR)/config.h
1088 $(XTCC) -o $(OBJDIR)/util.o -c $(OBJDIR)/util_.c
1089
1090 $(OBJDIR)/util.h: $(OBJDIR)/headers
1091 $(OBJDIR)/verify_.c: $(SRCDIR)/verify.c $(OBJDIR)/translate
1092 $(OBJDIR)/translate $(SRCDIR)/verify.c >$(OBJDIR)/verify_.c
1093
1094 $(OBJDIR)/verify.o: $(OBJDIR)/verify_.c $(OBJDIR)/verify.h $(SRCDIR)/config.h
1095 $(XTCC) -o $(OBJDIR)/verify.o -c $(OBJDIR)/verify_.c
1096
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -63,10 +63,11 @@
6363
json_dir
6464
json_finfo
6565
json_login
6666
json_query
6767
json_report
68
+ json_status
6869
json_tag
6970
json_timeline
7071
json_user
7172
json_wiki
7273
leaf
@@ -110,10 +111,11 @@
110111
unicode
111112
update
112113
url
113114
user
114115
utf8
116
+ util
115117
verify
116118
vfile
117119
wiki
118120
wikiformat
119121
winhttp
@@ -268,11 +270,11 @@
268270
writeln "\t\$(OBJDIR)/mkindex \$(TRANS_SRC) >$@"
269271
writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(OBJDIR)/makeheaders \$(OBJDIR)/VERSION.h"
270272
writeln "\t\$(OBJDIR)/makeheaders $mhargs"
271273
writeln "\ttouch \$(OBJDIR)/headers"
272274
writeln "\$(OBJDIR)/headers: Makefile"
273
-writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/json_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h"
275
+writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/json_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_status.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h"
274276
writeln "Makefile:"
275277
set extra_h(main) \$(OBJDIR)/page_index.h
276278
277279
foreach s [lsort $src] {
278280
writeln "\$(OBJDIR)/${s}_.c:\t\$(SRCDIR)/$s.c \$(OBJDIR)/translate"
@@ -418,12 +420,12 @@
418420
#### The directories where the OpenSSL include and library files are located.
419421
# The recommended usage here is to use the Sysinternals junction tool
420422
# to create a hard link between an "openssl-1.x" sub-directory of the
421423
# Fossil source code directory and the target OpenSSL source directory.
422424
#
423
-OPENSSLINCDIR = $(SRCDIR)/../openssl-1.0.1c/include
424
-OPENSSLLIBDIR = $(SRCDIR)/../openssl-1.0.1c
425
+OPENSSLINCDIR = $(SRCDIR)/../openssl-1.0.1e/include
426
+OPENSSLLIBDIR = $(SRCDIR)/../openssl-1.0.1e
425427
426428
#### Either the directory where the Tcl library is installed or the Tcl
427429
# source code directory resides (depending on the value of the macro
428430
# FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
429431
# this directory must have "include" and "lib" sub-directories. If
@@ -752,11 +754,11 @@
752754
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
753755
754756
set opt {}
755757
writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c"
756758
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o\n"
757
-writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/jsos_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h\n"
759
+writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/jsos_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_status.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h\n"
758760
759761
writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
760762
set opt {-Dmain=sqlite3_shell}
761763
append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
762764
writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"
@@ -900,10 +902,11 @@
900902
$(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
901903
$(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
902904
$(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
903905
$(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
904906
$(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
907
+$(OBJDIR)\json_status$O : $(SRCDIR)\json_detail.h
905908
$(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
906909
$(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
907910
$(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
908911
$(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h
909912
@@ -1096,10 +1099,11 @@
10961099
$(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
10971100
$(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
10981101
$(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
10991102
$(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
11001103
$(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
1104
+$(OBJDIR)\json_status$O : $(SRCDIR)\json_detail.h
11011105
$(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
11021106
$(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
11031107
$(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
11041108
$(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h
11051109
11061110
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -63,10 +63,11 @@
63 json_dir
64 json_finfo
65 json_login
66 json_query
67 json_report
 
68 json_tag
69 json_timeline
70 json_user
71 json_wiki
72 leaf
@@ -110,10 +111,11 @@
110 unicode
111 update
112 url
113 user
114 utf8
 
115 verify
116 vfile
117 wiki
118 wikiformat
119 winhttp
@@ -268,11 +270,11 @@
268 writeln "\t\$(OBJDIR)/mkindex \$(TRANS_SRC) >$@"
269 writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(OBJDIR)/makeheaders \$(OBJDIR)/VERSION.h"
270 writeln "\t\$(OBJDIR)/makeheaders $mhargs"
271 writeln "\ttouch \$(OBJDIR)/headers"
272 writeln "\$(OBJDIR)/headers: Makefile"
273 writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/json_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h"
274 writeln "Makefile:"
275 set extra_h(main) \$(OBJDIR)/page_index.h
276
277 foreach s [lsort $src] {
278 writeln "\$(OBJDIR)/${s}_.c:\t\$(SRCDIR)/$s.c \$(OBJDIR)/translate"
@@ -418,12 +420,12 @@
418 #### The directories where the OpenSSL include and library files are located.
419 # The recommended usage here is to use the Sysinternals junction tool
420 # to create a hard link between an "openssl-1.x" sub-directory of the
421 # Fossil source code directory and the target OpenSSL source directory.
422 #
423 OPENSSLINCDIR = $(SRCDIR)/../openssl-1.0.1c/include
424 OPENSSLLIBDIR = $(SRCDIR)/../openssl-1.0.1c
425
426 #### Either the directory where the Tcl library is installed or the Tcl
427 # source code directory resides (depending on the value of the macro
428 # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
429 # this directory must have "include" and "lib" sub-directories. If
@@ -752,11 +754,11 @@
752 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
753
754 set opt {}
755 writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c"
756 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o\n"
757 writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/jsos_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h\n"
758
759 writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
760 set opt {-Dmain=sqlite3_shell}
761 append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
762 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"
@@ -900,10 +902,11 @@
900 $(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
901 $(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
902 $(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
903 $(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
904 $(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
 
905 $(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
906 $(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
907 $(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
908 $(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h
909
@@ -1096,10 +1099,11 @@
1096 $(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
1097 $(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
1098 $(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
1099 $(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
1100 $(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
 
1101 $(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
1102 $(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
1103 $(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
1104 $(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h
1105
1106
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -63,10 +63,11 @@
63 json_dir
64 json_finfo
65 json_login
66 json_query
67 json_report
68 json_status
69 json_tag
70 json_timeline
71 json_user
72 json_wiki
73 leaf
@@ -110,10 +111,11 @@
111 unicode
112 update
113 url
114 user
115 utf8
116 util
117 verify
118 vfile
119 wiki
120 wikiformat
121 winhttp
@@ -268,11 +270,11 @@
270 writeln "\t\$(OBJDIR)/mkindex \$(TRANS_SRC) >$@"
271 writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(OBJDIR)/makeheaders \$(OBJDIR)/VERSION.h"
272 writeln "\t\$(OBJDIR)/makeheaders $mhargs"
273 writeln "\ttouch \$(OBJDIR)/headers"
274 writeln "\$(OBJDIR)/headers: Makefile"
275 writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/json_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_status.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h"
276 writeln "Makefile:"
277 set extra_h(main) \$(OBJDIR)/page_index.h
278
279 foreach s [lsort $src] {
280 writeln "\$(OBJDIR)/${s}_.c:\t\$(SRCDIR)/$s.c \$(OBJDIR)/translate"
@@ -418,12 +420,12 @@
420 #### The directories where the OpenSSL include and library files are located.
421 # The recommended usage here is to use the Sysinternals junction tool
422 # to create a hard link between an "openssl-1.x" sub-directory of the
423 # Fossil source code directory and the target OpenSSL source directory.
424 #
425 OPENSSLINCDIR = $(SRCDIR)/../openssl-1.0.1e/include
426 OPENSSLLIBDIR = $(SRCDIR)/../openssl-1.0.1e
427
428 #### Either the directory where the Tcl library is installed or the Tcl
429 # source code directory resides (depending on the value of the macro
430 # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
431 # this directory must have "include" and "lib" sub-directories. If
@@ -752,11 +754,11 @@
754 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/sqlite3.c -o \$(OBJDIR)/sqlite3.o\n"
755
756 set opt {}
757 writeln "\$(OBJDIR)/cson_amalgamation.o:\t\$(SRCDIR)/cson_amalgamation.c"
758 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/cson_amalgamation.c -o \$(OBJDIR)/cson_amalgamation.o\n"
759 writeln "\$(OBJDIR)/json.o \$(OBJDIR)/json_artifact.o \$(OBJDIR)/json_branch.o \$(OBJDIR)/json_config.o \$(OBJDIR)/json_diff.o \$(OBJDIR)/json_dir.o \$(OBJDIR)/jsos_finfo.o \$(OBJDIR)/json_login.o \$(OBJDIR)/json_query.o \$(OBJDIR)/json_report.o \$(OBJDIR)/json_status.o \$(OBJDIR)/json_tag.o \$(OBJDIR)/json_timeline.o \$(OBJDIR)/json_user.o \$(OBJDIR)/json_wiki.o : \$(SRCDIR)/json_detail.h\n"
760
761 writeln "\$(OBJDIR)/shell.o:\t\$(SRCDIR)/shell.c \$(SRCDIR)/sqlite3.h"
762 set opt {-Dmain=sqlite3_shell}
763 append opt " -DSQLITE_OMIT_LOAD_EXTENSION=1"
764 writeln "\t\$(XTCC) $opt -c \$(SRCDIR)/shell.c -o \$(OBJDIR)/shell.o\n"
@@ -900,10 +902,11 @@
902 $(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
903 $(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
904 $(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
905 $(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
906 $(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
907 $(OBJDIR)\json_status$O : $(SRCDIR)\json_detail.h
908 $(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
909 $(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
910 $(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
911 $(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h
912
@@ -1096,10 +1099,11 @@
1099 $(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
1100 $(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
1101 $(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
1102 $(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
1103 $(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
1104 $(OBJDIR)\json_status$O : $(SRCDIR)\json_detail.h
1105 $(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
1106 $(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
1107 $(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
1108 $(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h
1109
1110
+22 -17
--- src/mkindex.c
+++ src/mkindex.c
@@ -174,10 +174,11 @@
174174
if( strncmp(zLine, "**", 2)==0
175175
&& isspace(zLine[2])
176176
&& strlen(zLine)<sizeof(zHelp)-nHelp-1
177177
&& nUsed>nFixed
178178
&& memcmp(zLine,"** COMMAND:",11)!=0
179
+ && memcmp(zLine,"** WEBPAGE:",11)!=0
179180
){
180181
if( zLine[2]=='\n' ){
181182
zHelp[nHelp++] = '\n';
182183
}else{
183184
if( strncmp(&zLine[3], "Usage: ", 6)==0 ) nHelp = 0;
@@ -242,11 +243,10 @@
242243
/*
243244
** Build the binary search table.
244245
*/
245246
void build_table(void){
246247
int i;
247
- int nType0;
248248
249249
qsort(aEntry, nFixed, sizeof(aEntry[0]), e_compare);
250250
for(i=0; i<nFixed; i++){
251251
if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
252252
printf("extern void %s(void);\n", aEntry[i].zFunc);
@@ -260,10 +260,11 @@
260260
" char cmdFlags;\n"
261261
"};\n"
262262
"#define CMDFLAG_1ST_TIER 0x01\n"
263263
"#define CMDFLAG_2ND_TIER 0x02\n"
264264
"#define CMDFLAG_TEST 0x04\n"
265
+ "#define CMDFLAG_WEBPAGE 0x08\n"
265266
"static const NameMap aWebpage[] = {\n"
266267
);
267268
for(i=0; i<nFixed && aEntry[i].eType==0; i++){
268269
const char *z = aEntry[i].zPath;
269270
int n = strlen(z);
@@ -275,36 +276,38 @@
275276
(int)(35-strlen(aEntry[i].zFunc)), ""
276277
);
277278
if( aEntry[i].zIf ) printf("#endif\n");
278279
}
279280
printf("};\n");
280
- nType0 = i;
281281
printf(
282282
"static const NameMap aCommand[] = {\n"
283283
);
284
- for(i=nType0; i<nFixed && aEntry[i].eType==1; i++){
284
+ for(i=0; i<nFixed /*&& aEntry[i].eType==1*/; i++){
285285
const char *z = aEntry[i].zPath;
286286
int n = strlen(z);
287
- int cmdFlags = 0x01;
288
- if( z[n-1]=='*' ){
289
- n--;
290
- cmdFlags = 0x02;
291
- }else if( memcmp(z, "test-", 5)==0 ){
292
- cmdFlags = 0x04;
287
+ int cmdFlags = (1==aEntry[i].eType) ? 0x01 : 0x08;
288
+ if(0x01==cmdFlags){
289
+ if( z[n-1]=='*' ){
290
+ n--;
291
+ cmdFlags = 0x02;
292
+ }else if( memcmp(z, "test-", 5)==0 ){
293
+ cmdFlags = 0x04;
294
+ }
293295
}
294296
if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
295
- printf(" { \"%.*s\",%*s %s,%*s %d },\n",
297
+ printf(" { \"%s%.*s\",%*s %s,%*s %d },\n",
298
+ (0x08 & cmdFlags) ? "/" : "",
296299
n, z,
297300
25-n, "",
298301
aEntry[i].zFunc,
299302
(int)(35-strlen(aEntry[i].zFunc)), "",
300303
cmdFlags
301304
);
302305
if( aEntry[i].zIf ) printf("#endif\n");
303306
}
304307
printf("};\n");
305
- for(i=nType0; i<nFixed; i++){
308
+ for(i=0; i<nFixed; i++){
306309
char *z = aEntry[i].zHelp;
307310
if( z && z[0] ){
308311
if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
309312
printf("static const char zHelp_%s[] = \n", aEntry[i].zFunc);
310313
printf(" \"");
@@ -321,19 +324,21 @@
321324
printf("\";\n");
322325
if( aEntry[i].zIf ) printf("#endif\n");
323326
aEntry[i].zHelp[0] = 0;
324327
}
325328
}
326
- printf(
327
- "static const char * const aCmdHelp[] = {\n"
328
- );
329
- for(i=nType0; i<nFixed; i++){
329
+ puts("struct CmdHelp {"
330
+ "int eType; "
331
+ "char const * zText;"
332
+ "};");
333
+ puts("static struct CmdHelp aCmdHelp[] = {");
334
+ for(i=0; i<nFixed; i++){
330335
if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
331336
if( aEntry[i].zHelp==0 ){
332
- printf(" 0,\n");
337
+ printf("{%d, 0},\n", aEntry[i].eType);
333338
}else{
334
- printf(" zHelp_%s,\n", aEntry[i].zFunc);
339
+ printf("{%d, zHelp_%s},\n", aEntry[i].eType, aEntry[i].zFunc);
335340
}
336341
if( aEntry[i].zIf ) printf("#endif\n");
337342
}
338343
printf("};\n");
339344
}
340345
--- src/mkindex.c
+++ src/mkindex.c
@@ -174,10 +174,11 @@
174 if( strncmp(zLine, "**", 2)==0
175 && isspace(zLine[2])
176 && strlen(zLine)<sizeof(zHelp)-nHelp-1
177 && nUsed>nFixed
178 && memcmp(zLine,"** COMMAND:",11)!=0
 
179 ){
180 if( zLine[2]=='\n' ){
181 zHelp[nHelp++] = '\n';
182 }else{
183 if( strncmp(&zLine[3], "Usage: ", 6)==0 ) nHelp = 0;
@@ -242,11 +243,10 @@
242 /*
243 ** Build the binary search table.
244 */
245 void build_table(void){
246 int i;
247 int nType0;
248
249 qsort(aEntry, nFixed, sizeof(aEntry[0]), e_compare);
250 for(i=0; i<nFixed; i++){
251 if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
252 printf("extern void %s(void);\n", aEntry[i].zFunc);
@@ -260,10 +260,11 @@
260 " char cmdFlags;\n"
261 "};\n"
262 "#define CMDFLAG_1ST_TIER 0x01\n"
263 "#define CMDFLAG_2ND_TIER 0x02\n"
264 "#define CMDFLAG_TEST 0x04\n"
 
265 "static const NameMap aWebpage[] = {\n"
266 );
267 for(i=0; i<nFixed && aEntry[i].eType==0; i++){
268 const char *z = aEntry[i].zPath;
269 int n = strlen(z);
@@ -275,36 +276,38 @@
275 (int)(35-strlen(aEntry[i].zFunc)), ""
276 );
277 if( aEntry[i].zIf ) printf("#endif\n");
278 }
279 printf("};\n");
280 nType0 = i;
281 printf(
282 "static const NameMap aCommand[] = {\n"
283 );
284 for(i=nType0; i<nFixed && aEntry[i].eType==1; i++){
285 const char *z = aEntry[i].zPath;
286 int n = strlen(z);
287 int cmdFlags = 0x01;
288 if( z[n-1]=='*' ){
289 n--;
290 cmdFlags = 0x02;
291 }else if( memcmp(z, "test-", 5)==0 ){
292 cmdFlags = 0x04;
 
 
293 }
294 if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
295 printf(" { \"%.*s\",%*s %s,%*s %d },\n",
 
296 n, z,
297 25-n, "",
298 aEntry[i].zFunc,
299 (int)(35-strlen(aEntry[i].zFunc)), "",
300 cmdFlags
301 );
302 if( aEntry[i].zIf ) printf("#endif\n");
303 }
304 printf("};\n");
305 for(i=nType0; i<nFixed; i++){
306 char *z = aEntry[i].zHelp;
307 if( z && z[0] ){
308 if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
309 printf("static const char zHelp_%s[] = \n", aEntry[i].zFunc);
310 printf(" \"");
@@ -321,19 +324,21 @@
321 printf("\";\n");
322 if( aEntry[i].zIf ) printf("#endif\n");
323 aEntry[i].zHelp[0] = 0;
324 }
325 }
326 printf(
327 "static const char * const aCmdHelp[] = {\n"
328 );
329 for(i=nType0; i<nFixed; i++){
 
 
330 if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
331 if( aEntry[i].zHelp==0 ){
332 printf(" 0,\n");
333 }else{
334 printf(" zHelp_%s,\n", aEntry[i].zFunc);
335 }
336 if( aEntry[i].zIf ) printf("#endif\n");
337 }
338 printf("};\n");
339 }
340
--- src/mkindex.c
+++ src/mkindex.c
@@ -174,10 +174,11 @@
174 if( strncmp(zLine, "**", 2)==0
175 && isspace(zLine[2])
176 && strlen(zLine)<sizeof(zHelp)-nHelp-1
177 && nUsed>nFixed
178 && memcmp(zLine,"** COMMAND:",11)!=0
179 && memcmp(zLine,"** WEBPAGE:",11)!=0
180 ){
181 if( zLine[2]=='\n' ){
182 zHelp[nHelp++] = '\n';
183 }else{
184 if( strncmp(&zLine[3], "Usage: ", 6)==0 ) nHelp = 0;
@@ -242,11 +243,10 @@
243 /*
244 ** Build the binary search table.
245 */
246 void build_table(void){
247 int i;
 
248
249 qsort(aEntry, nFixed, sizeof(aEntry[0]), e_compare);
250 for(i=0; i<nFixed; i++){
251 if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
252 printf("extern void %s(void);\n", aEntry[i].zFunc);
@@ -260,10 +260,11 @@
260 " char cmdFlags;\n"
261 "};\n"
262 "#define CMDFLAG_1ST_TIER 0x01\n"
263 "#define CMDFLAG_2ND_TIER 0x02\n"
264 "#define CMDFLAG_TEST 0x04\n"
265 "#define CMDFLAG_WEBPAGE 0x08\n"
266 "static const NameMap aWebpage[] = {\n"
267 );
268 for(i=0; i<nFixed && aEntry[i].eType==0; i++){
269 const char *z = aEntry[i].zPath;
270 int n = strlen(z);
@@ -275,36 +276,38 @@
276 (int)(35-strlen(aEntry[i].zFunc)), ""
277 );
278 if( aEntry[i].zIf ) printf("#endif\n");
279 }
280 printf("};\n");
 
281 printf(
282 "static const NameMap aCommand[] = {\n"
283 );
284 for(i=0; i<nFixed /*&& aEntry[i].eType==1*/; i++){
285 const char *z = aEntry[i].zPath;
286 int n = strlen(z);
287 int cmdFlags = (1==aEntry[i].eType) ? 0x01 : 0x08;
288 if(0x01==cmdFlags){
289 if( z[n-1]=='*' ){
290 n--;
291 cmdFlags = 0x02;
292 }else if( memcmp(z, "test-", 5)==0 ){
293 cmdFlags = 0x04;
294 }
295 }
296 if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
297 printf(" { \"%s%.*s\",%*s %s,%*s %d },\n",
298 (0x08 & cmdFlags) ? "/" : "",
299 n, z,
300 25-n, "",
301 aEntry[i].zFunc,
302 (int)(35-strlen(aEntry[i].zFunc)), "",
303 cmdFlags
304 );
305 if( aEntry[i].zIf ) printf("#endif\n");
306 }
307 printf("};\n");
308 for(i=0; i<nFixed; i++){
309 char *z = aEntry[i].zHelp;
310 if( z && z[0] ){
311 if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
312 printf("static const char zHelp_%s[] = \n", aEntry[i].zFunc);
313 printf(" \"");
@@ -321,19 +324,21 @@
324 printf("\";\n");
325 if( aEntry[i].zIf ) printf("#endif\n");
326 aEntry[i].zHelp[0] = 0;
327 }
328 }
329 puts("struct CmdHelp {"
330 "int eType; "
331 "char const * zText;"
332 "};");
333 puts("static struct CmdHelp aCmdHelp[] = {");
334 for(i=0; i<nFixed; i++){
335 if( aEntry[i].zIf ) printf("%s", aEntry[i].zIf);
336 if( aEntry[i].zHelp==0 ){
337 printf("{%d, 0},\n", aEntry[i].eType);
338 }else{
339 printf("{%d, zHelp_%s},\n", aEntry[i].eType, aEntry[i].zFunc);
340 }
341 if( aEntry[i].zIf ) printf("#endif\n");
342 }
343 printf("};\n");
344 }
345
+158 -65
--- src/printf.c
+++ src/printf.c
@@ -13,14 +13,19 @@
1313
** [email protected]
1414
** http://www.hwaci.com/drh/
1515
**
1616
*******************************************************************************
1717
**
18
-** An implementation of printf() with extra conversion fields.
18
+** This file contains implementions of routines for formatting output
19
+** (ex: mprintf()) and for output to the console.
1920
*/
2021
#include "config.h"
2122
#include "printf.h"
23
+#if defined(_WIN32)
24
+# include <io.h>
25
+# include <fcntl.h>
26
+#endif
2227
2328
/*
2429
** Conversion types fall into various categories as defined by the
2530
** following enumeration.
2631
*/
@@ -888,70 +893,158 @@
888893
fossil_puts(blob_str(&b), 1);
889894
blob_reset(&b);
890895
va_end(ap);
891896
}
892897
893
-/*
894
-** Like strcmp() except that it accepts NULL pointers. NULL sorts before
895
-** all non-NULL string pointers. Also, this strcmp() is a binary comparison
896
-** that does not consider locale.
897
-*/
898
-int fossil_strcmp(const char *zA, const char *zB){
899
- if( zA==0 ){
900
- if( zB==0 ) return 0;
901
- return -1;
902
- }else if( zB==0 ){
903
- return +1;
904
- }else{
905
- int a, b;
906
- do{
907
- a = *zA++;
908
- b = *zB++;
909
- }while( a==b && a!=0 );
910
- return ((unsigned char)a) - (unsigned char)b;
911
- }
912
-}
913
-int fossil_strncmp(const char *zA, const char *zB, int nByte){
914
- if( zA==0 ){
915
- if( zB==0 ) return 0;
916
- return -1;
917
- }else if( zB==0 ){
918
- return +1;
919
- }else if( nByte>0 ){
920
- int a, b;
921
- do{
922
- a = *zA++;
923
- b = *zB++;
924
- }while( a==b && a!=0 && (--nByte)>0 );
925
- return ((unsigned char)a) - (unsigned char)b;
926
- }else{
927
- return 0;
928
- }
929
-}
930
-
931
-/*
932
-** Case insensitive string comparison.
933
-*/
934
-int fossil_strnicmp(const char *zA, const char *zB, int nByte){
935
- if( zA==0 ){
936
- if( zB==0 ) return 0;
937
- return -1;
938
- }else if( zB==0 ){
939
- return +1;
940
- }
941
- if( nByte<0 ) nByte = strlen(zB);
942
- return sqlite3_strnicmp(zA, zB, nByte);
943
-}
944
-int fossil_stricmp(const char *zA, const char *zB){
945
- int nByte;
946
- int rc;
947
- if( zA==0 ){
948
- if( zB==0 ) return 0;
949
- return -1;
950
- }else if( zB==0 ){
951
- return +1;
952
- }
953
- nByte = strlen(zB);
954
- rc = sqlite3_strnicmp(zA, zB, nByte);
955
- if( rc==0 && zA[nByte] ) rc = 1;
956
- return rc;
898
+
899
+/*
900
+** The following variable becomes true while processing a fatal error
901
+** or a panic. If additional "recursive-fatal" errors occur while
902
+** shutting down, the recursive errors are silently ignored.
903
+*/
904
+static int mainInFatalError = 0;
905
+
906
+/*
907
+** Print an error message, rollback all databases, and quit. These
908
+** routines never return.
909
+*/
910
+NORETURN void fossil_panic(const char *zFormat, ...){
911
+ char *z;
912
+ va_list ap;
913
+ int rc = 1;
914
+ static int once = 1;
915
+ mainInFatalError = 1;
916
+ va_start(ap, zFormat);
917
+ z = vmprintf(zFormat, ap);
918
+ va_end(ap);
919
+#ifdef FOSSIL_ENABLE_JSON
920
+ if( g.json.isJsonMode ){
921
+ json_err( 0, z, 1 );
922
+ if( g.isHTTP ){
923
+ rc = 0 /* avoid HTTP 500 */;
924
+ }
925
+ }
926
+ else
927
+#endif
928
+ {
929
+ if( g.cgiOutput && once ){
930
+ once = 0;
931
+ cgi_printf("<p class=\"generalError\">%h</p>", z);
932
+ cgi_reply();
933
+ }else if( !g.fQuiet ){
934
+ fossil_force_newline();
935
+ fossil_trace("Fossil internal error: %s\n", z);
936
+ }
937
+ }
938
+ free(z);
939
+ db_force_rollback();
940
+ fossil_exit(rc);
941
+}
942
+
943
+NORETURN void fossil_fatal(const char *zFormat, ...){
944
+ char *z;
945
+ int rc = 1;
946
+ va_list ap;
947
+ mainInFatalError = 1;
948
+ va_start(ap, zFormat);
949
+ z = vmprintf(zFormat, ap);
950
+ va_end(ap);
951
+#ifdef FOSSIL_ENABLE_JSON
952
+ if( g.json.isJsonMode ){
953
+ json_err( g.json.resultCode, z, 1 );
954
+ if( g.isHTTP ){
955
+ rc = 0 /* avoid HTTP 500 */;
956
+ }
957
+ }
958
+ else
959
+#endif
960
+ {
961
+ if( g.cgiOutput ){
962
+ g.cgiOutput = 0;
963
+ cgi_printf("<p class=\"generalError\">\n%h\n</p>\n", z);
964
+ cgi_reply();
965
+ }else if( !g.fQuiet ){
966
+ fossil_force_newline();
967
+ fossil_trace("%s\n", z);
968
+ }
969
+ }
970
+ free(z);
971
+ db_force_rollback();
972
+ fossil_exit(rc);
973
+}
974
+
975
+/* This routine works like fossil_fatal() except that if called
976
+** recursively, the recursive call is a no-op.
977
+**
978
+** Use this in places where an error might occur while doing
979
+** fatal error shutdown processing. Unlike fossil_panic() and
980
+** fossil_fatal() which never return, this routine might return if
981
+** the fatal error handing is already in process. The caller must
982
+** be prepared for this routine to return.
983
+*/
984
+void fossil_fatal_recursive(const char *zFormat, ...){
985
+ char *z;
986
+ va_list ap;
987
+ int rc = 1;
988
+ if( mainInFatalError ) return;
989
+ mainInFatalError = 1;
990
+ va_start(ap, zFormat);
991
+ z = vmprintf(zFormat, ap);
992
+ va_end(ap);
993
+#ifdef FOSSIL_ENABLE_JSON
994
+ if( g.json.isJsonMode ){
995
+ json_err( g.json.resultCode, z, 1 );
996
+ if( g.isHTTP ){
997
+ rc = 0 /* avoid HTTP 500 */;
998
+ }
999
+ } else
1000
+#endif
1001
+ {
1002
+ if( g.cgiOutput ){
1003
+ g.cgiOutput = 0;
1004
+ cgi_printf("<p class=\"generalError\">\n%h\n</p>\n", z);
1005
+ cgi_reply();
1006
+ }else{
1007
+ fossil_force_newline();
1008
+ fossil_trace("%s\n", z);
1009
+ }
1010
+ }
1011
+ db_force_rollback();
1012
+ fossil_exit(rc);
1013
+}
1014
+
1015
+
1016
+/* Print a warning message */
1017
+void fossil_warning(const char *zFormat, ...){
1018
+ char *z;
1019
+ va_list ap;
1020
+ va_start(ap, zFormat);
1021
+ z = vmprintf(zFormat, ap);
1022
+ va_end(ap);
1023
+#ifdef FOSSIL_ENABLE_JSON
1024
+ if(g.json.isJsonMode){
1025
+ json_warn( FSL_JSON_W_UNKNOWN, z );
1026
+ }else
1027
+#endif
1028
+ {
1029
+ if( g.cgiOutput ){
1030
+ cgi_printf("<p class=\"generalError\">\n%h\n</p>\n", z);
1031
+ }else{
1032
+ fossil_force_newline();
1033
+ fossil_trace("%s\n", z);
1034
+ }
1035
+ }
1036
+ free(z);
1037
+}
1038
+
1039
+/*
1040
+** Turn off any NL to CRNL translation on the stream given as an
1041
+** argument. This is a no-op on unix but is necessary on windows.
1042
+*/
1043
+void fossil_binary_mode(FILE *p){
1044
+#if defined(_WIN32)
1045
+ _setmode(_fileno(p), _O_BINARY);
1046
+#endif
1047
+#ifdef __EMX__ /* OS/2 */
1048
+ setmode(fileno(p), O_BINARY);
1049
+#endif
9571050
}
9581051
--- src/printf.c
+++ src/printf.c
@@ -13,14 +13,19 @@
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** An implementation of printf() with extra conversion fields.
 
19 */
20 #include "config.h"
21 #include "printf.h"
 
 
 
 
22
23 /*
24 ** Conversion types fall into various categories as defined by the
25 ** following enumeration.
26 */
@@ -888,70 +893,158 @@
888 fossil_puts(blob_str(&b), 1);
889 blob_reset(&b);
890 va_end(ap);
891 }
892
893 /*
894 ** Like strcmp() except that it accepts NULL pointers. NULL sorts before
895 ** all non-NULL string pointers. Also, this strcmp() is a binary comparison
896 ** that does not consider locale.
897 */
898 int fossil_strcmp(const char *zA, const char *zB){
899 if( zA==0 ){
900 if( zB==0 ) return 0;
901 return -1;
902 }else if( zB==0 ){
903 return +1;
904 }else{
905 int a, b;
906 do{
907 a = *zA++;
908 b = *zB++;
909 }while( a==b && a!=0 );
910 return ((unsigned char)a) - (unsigned char)b;
911 }
912 }
913 int fossil_strncmp(const char *zA, const char *zB, int nByte){
914 if( zA==0 ){
915 if( zB==0 ) return 0;
916 return -1;
917 }else if( zB==0 ){
918 return +1;
919 }else if( nByte>0 ){
920 int a, b;
921 do{
922 a = *zA++;
923 b = *zB++;
924 }while( a==b && a!=0 && (--nByte)>0 );
925 return ((unsigned char)a) - (unsigned char)b;
926 }else{
927 return 0;
928 }
929 }
930
931 /*
932 ** Case insensitive string comparison.
933 */
934 int fossil_strnicmp(const char *zA, const char *zB, int nByte){
935 if( zA==0 ){
936 if( zB==0 ) return 0;
937 return -1;
938 }else if( zB==0 ){
939 return +1;
940 }
941 if( nByte<0 ) nByte = strlen(zB);
942 return sqlite3_strnicmp(zA, zB, nByte);
943 }
944 int fossil_stricmp(const char *zA, const char *zB){
945 int nByte;
946 int rc;
947 if( zA==0 ){
948 if( zB==0 ) return 0;
949 return -1;
950 }else if( zB==0 ){
951 return +1;
952 }
953 nByte = strlen(zB);
954 rc = sqlite3_strnicmp(zA, zB, nByte);
955 if( rc==0 && zA[nByte] ) rc = 1;
956 return rc;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
957 }
958
--- src/printf.c
+++ src/printf.c
@@ -13,14 +13,19 @@
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains implementions of routines for formatting output
19 ** (ex: mprintf()) and for output to the console.
20 */
21 #include "config.h"
22 #include "printf.h"
23 #if defined(_WIN32)
24 # include <io.h>
25 # include <fcntl.h>
26 #endif
27
28 /*
29 ** Conversion types fall into various categories as defined by the
30 ** following enumeration.
31 */
@@ -888,70 +893,158 @@
893 fossil_puts(blob_str(&b), 1);
894 blob_reset(&b);
895 va_end(ap);
896 }
897
898
899 /*
900 ** The following variable becomes true while processing a fatal error
901 ** or a panic. If additional "recursive-fatal" errors occur while
902 ** shutting down, the recursive errors are silently ignored.
903 */
904 static int mainInFatalError = 0;
905
906 /*
907 ** Print an error message, rollback all databases, and quit. These
908 ** routines never return.
909 */
910 NORETURN void fossil_panic(const char *zFormat, ...){
911 char *z;
912 va_list ap;
913 int rc = 1;
914 static int once = 1;
915 mainInFatalError = 1;
916 va_start(ap, zFormat);
917 z = vmprintf(zFormat, ap);
918 va_end(ap);
919 #ifdef FOSSIL_ENABLE_JSON
920 if( g.json.isJsonMode ){
921 json_err( 0, z, 1 );
922 if( g.isHTTP ){
923 rc = 0 /* avoid HTTP 500 */;
924 }
925 }
926 else
927 #endif
928 {
929 if( g.cgiOutput && once ){
930 once = 0;
931 cgi_printf("<p class=\"generalError\">%h</p>", z);
932 cgi_reply();
933 }else if( !g.fQuiet ){
934 fossil_force_newline();
935 fossil_trace("Fossil internal error: %s\n", z);
936 }
937 }
938 free(z);
939 db_force_rollback();
940 fossil_exit(rc);
941 }
942
943 NORETURN void fossil_fatal(const char *zFormat, ...){
944 char *z;
945 int rc = 1;
946 va_list ap;
947 mainInFatalError = 1;
948 va_start(ap, zFormat);
949 z = vmprintf(zFormat, ap);
950 va_end(ap);
951 #ifdef FOSSIL_ENABLE_JSON
952 if( g.json.isJsonMode ){
953 json_err( g.json.resultCode, z, 1 );
954 if( g.isHTTP ){
955 rc = 0 /* avoid HTTP 500 */;
956 }
957 }
958 else
959 #endif
960 {
961 if( g.cgiOutput ){
962 g.cgiOutput = 0;
963 cgi_printf("<p class=\"generalError\">\n%h\n</p>\n", z);
964 cgi_reply();
965 }else if( !g.fQuiet ){
966 fossil_force_newline();
967 fossil_trace("%s\n", z);
968 }
969 }
970 free(z);
971 db_force_rollback();
972 fossil_exit(rc);
973 }
974
975 /* This routine works like fossil_fatal() except that if called
976 ** recursively, the recursive call is a no-op.
977 **
978 ** Use this in places where an error might occur while doing
979 ** fatal error shutdown processing. Unlike fossil_panic() and
980 ** fossil_fatal() which never return, this routine might return if
981 ** the fatal error handing is already in process. The caller must
982 ** be prepared for this routine to return.
983 */
984 void fossil_fatal_recursive(const char *zFormat, ...){
985 char *z;
986 va_list ap;
987 int rc = 1;
988 if( mainInFatalError ) return;
989 mainInFatalError = 1;
990 va_start(ap, zFormat);
991 z = vmprintf(zFormat, ap);
992 va_end(ap);
993 #ifdef FOSSIL_ENABLE_JSON
994 if( g.json.isJsonMode ){
995 json_err( g.json.resultCode, z, 1 );
996 if( g.isHTTP ){
997 rc = 0 /* avoid HTTP 500 */;
998 }
999 } else
1000 #endif
1001 {
1002 if( g.cgiOutput ){
1003 g.cgiOutput = 0;
1004 cgi_printf("<p class=\"generalError\">\n%h\n</p>\n", z);
1005 cgi_reply();
1006 }else{
1007 fossil_force_newline();
1008 fossil_trace("%s\n", z);
1009 }
1010 }
1011 db_force_rollback();
1012 fossil_exit(rc);
1013 }
1014
1015
1016 /* Print a warning message */
1017 void fossil_warning(const char *zFormat, ...){
1018 char *z;
1019 va_list ap;
1020 va_start(ap, zFormat);
1021 z = vmprintf(zFormat, ap);
1022 va_end(ap);
1023 #ifdef FOSSIL_ENABLE_JSON
1024 if(g.json.isJsonMode){
1025 json_warn( FSL_JSON_W_UNKNOWN, z );
1026 }else
1027 #endif
1028 {
1029 if( g.cgiOutput ){
1030 cgi_printf("<p class=\"generalError\">\n%h\n</p>\n", z);
1031 }else{
1032 fossil_force_newline();
1033 fossil_trace("%s\n", z);
1034 }
1035 }
1036 free(z);
1037 }
1038
1039 /*
1040 ** Turn off any NL to CRNL translation on the stream given as an
1041 ** argument. This is a no-op on unix but is necessary on windows.
1042 */
1043 void fossil_binary_mode(FILE *p){
1044 #if defined(_WIN32)
1045 _setmode(_fileno(p), _O_BINARY);
1046 #endif
1047 #ifdef __EMX__ /* OS/2 */
1048 setmode(fileno(p), O_BINARY);
1049 #endif
1050 }
1051
+56
--- src/rss.c
+++ src/rss.c
@@ -22,18 +22,37 @@
2222
#include "rss.h"
2323
#include <assert.h>
2424
2525
/*
2626
** WEBPAGE: timeline.rss
27
+** URL: /timeline.rss?y=TYPE&n=LIMIT&tkt=UUID&tag=TAG&wiki=NAME&name=FILENAME
28
+**
29
+** Produce an RSS feed of the timeline.
30
+**
31
+** TYPE may be: all, ci (show checkins only), t (show tickets only),
32
+** w (show wiki only). LIMIT is the number of items to show.
33
+**
34
+** tkt=UUID filters for only those events for the specified ticket. tag=TAG
35
+** filters for a tag, and wiki=NAME for a wiki page. Only one may be used.
36
+**
37
+** In addition, name=FILENAME filters for a specific file. This may be
38
+** combined with one of the other filters (useful for looking at a specific
39
+** branch).
2740
*/
41
+
2842
void page_timeline_rss(void){
2943
Stmt q;
3044
int nLine=0;
3145
char *zPubDate, *zProjectName, *zProjectDescr, *zFreeProjectName=0;
3246
Blob bSQL;
3347
const char *zType = PD("y","all"); /* Type of events. All if NULL */
48
+ const char *zTicketUuid = PD("tkt",NULL);
49
+ const char *zTag = PD("tag",NULL);
50
+ const char *zFilename = PD("name",NULL);
51
+ const char *zWiki = PD("wiki",NULL);
3452
int nLimit = atoi(PD("n","20"));
53
+ int nTagId;
3554
const char zSQL1[] =
3655
@ SELECT
3756
@ blob.rid,
3857
@ uuid,
3958
@ event.mtime,
@@ -62,10 +81,11 @@
6281
if( !g.perm.Read ){
6382
if( g.perm.RdTkt && g.perm.RdWiki ){
6483
blob_append(&bSQL, " AND event.type!='ci'", -1);
6584
}else if( g.perm.RdTkt ){
6685
blob_append(&bSQL, " AND event.type=='t'", -1);
86
+
6787
}else{
6888
blob_append(&bSQL, " AND event.type=='w'", -1);
6989
}
7090
}else if( !g.perm.RdWiki ){
7191
if( g.perm.RdTkt ){
@@ -76,10 +96,46 @@
7696
}else if( !g.perm.RdTkt ){
7797
assert( !g.perm.RdTkt &&& g.perm.Read && g.perm.RdWiki );
7898
blob_append(&bSQL, " AND event.type!='t'", -1);
7999
}
80100
}
101
+
102
+ if( zTicketUuid ){
103
+ nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",
104
+ zTicketUuid);
105
+ if ( nTagId==0 ){
106
+ nTagId = -1;
107
+ }
108
+ }else if( zTag ){
109
+ nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'sym-%q*'",
110
+ zTag);
111
+ if ( nTagId==0 ){
112
+ nTagId = -1;
113
+ }
114
+ }else if( zWiki ){
115
+ nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'wiki-%q*'",
116
+ zWiki);
117
+ if ( nTagId==0 ){
118
+ nTagId = -1;
119
+ }
120
+ }else{
121
+ nTagId = 0;
122
+ }
123
+
124
+ if( nTagId==-1 ){
125
+ blob_appendf(&bSQL, " AND 0");
126
+ }else if( nTagId!=0 ){
127
+ blob_appendf(&bSQL, " AND (EXISTS(SELECT 1 FROM tagxref"
128
+ " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid))", nTagId);
129
+ }
130
+
131
+ if( zFilename ){
132
+ blob_appendf(&bSQL,
133
+ " AND (SELECT mlink.fnid FROM mlink WHERE event.objid=mlink.mid) IN (SELECT fnid FROM filename WHERE name=%Q %s)",
134
+ zFilename, filename_collation()
135
+ );
136
+ }
81137
82138
blob_append( &bSQL, " ORDER BY event.mtime DESC", -1 );
83139
84140
cgi_set_content_type("application/rss+xml");
85141
86142
--- src/rss.c
+++ src/rss.c
@@ -22,18 +22,37 @@
22 #include "rss.h"
23 #include <assert.h>
24
25 /*
26 ** WEBPAGE: timeline.rss
 
 
 
 
 
 
 
 
 
 
 
 
 
27 */
 
28 void page_timeline_rss(void){
29 Stmt q;
30 int nLine=0;
31 char *zPubDate, *zProjectName, *zProjectDescr, *zFreeProjectName=0;
32 Blob bSQL;
33 const char *zType = PD("y","all"); /* Type of events. All if NULL */
 
 
 
 
34 int nLimit = atoi(PD("n","20"));
 
35 const char zSQL1[] =
36 @ SELECT
37 @ blob.rid,
38 @ uuid,
39 @ event.mtime,
@@ -62,10 +81,11 @@
62 if( !g.perm.Read ){
63 if( g.perm.RdTkt && g.perm.RdWiki ){
64 blob_append(&bSQL, " AND event.type!='ci'", -1);
65 }else if( g.perm.RdTkt ){
66 blob_append(&bSQL, " AND event.type=='t'", -1);
 
67 }else{
68 blob_append(&bSQL, " AND event.type=='w'", -1);
69 }
70 }else if( !g.perm.RdWiki ){
71 if( g.perm.RdTkt ){
@@ -76,10 +96,46 @@
76 }else if( !g.perm.RdTkt ){
77 assert( !g.perm.RdTkt &&& g.perm.Read && g.perm.RdWiki );
78 blob_append(&bSQL, " AND event.type!='t'", -1);
79 }
80 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
82 blob_append( &bSQL, " ORDER BY event.mtime DESC", -1 );
83
84 cgi_set_content_type("application/rss+xml");
85
86
--- src/rss.c
+++ src/rss.c
@@ -22,18 +22,37 @@
22 #include "rss.h"
23 #include <assert.h>
24
25 /*
26 ** WEBPAGE: timeline.rss
27 ** URL: /timeline.rss?y=TYPE&n=LIMIT&tkt=UUID&tag=TAG&wiki=NAME&name=FILENAME
28 **
29 ** Produce an RSS feed of the timeline.
30 **
31 ** TYPE may be: all, ci (show checkins only), t (show tickets only),
32 ** w (show wiki only). LIMIT is the number of items to show.
33 **
34 ** tkt=UUID filters for only those events for the specified ticket. tag=TAG
35 ** filters for a tag, and wiki=NAME for a wiki page. Only one may be used.
36 **
37 ** In addition, name=FILENAME filters for a specific file. This may be
38 ** combined with one of the other filters (useful for looking at a specific
39 ** branch).
40 */
41
42 void page_timeline_rss(void){
43 Stmt q;
44 int nLine=0;
45 char *zPubDate, *zProjectName, *zProjectDescr, *zFreeProjectName=0;
46 Blob bSQL;
47 const char *zType = PD("y","all"); /* Type of events. All if NULL */
48 const char *zTicketUuid = PD("tkt",NULL);
49 const char *zTag = PD("tag",NULL);
50 const char *zFilename = PD("name",NULL);
51 const char *zWiki = PD("wiki",NULL);
52 int nLimit = atoi(PD("n","20"));
53 int nTagId;
54 const char zSQL1[] =
55 @ SELECT
56 @ blob.rid,
57 @ uuid,
58 @ event.mtime,
@@ -62,10 +81,11 @@
81 if( !g.perm.Read ){
82 if( g.perm.RdTkt && g.perm.RdWiki ){
83 blob_append(&bSQL, " AND event.type!='ci'", -1);
84 }else if( g.perm.RdTkt ){
85 blob_append(&bSQL, " AND event.type=='t'", -1);
86
87 }else{
88 blob_append(&bSQL, " AND event.type=='w'", -1);
89 }
90 }else if( !g.perm.RdWiki ){
91 if( g.perm.RdTkt ){
@@ -76,10 +96,46 @@
96 }else if( !g.perm.RdTkt ){
97 assert( !g.perm.RdTkt &&& g.perm.Read && g.perm.RdWiki );
98 blob_append(&bSQL, " AND event.type!='t'", -1);
99 }
100 }
101
102 if( zTicketUuid ){
103 nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",
104 zTicketUuid);
105 if ( nTagId==0 ){
106 nTagId = -1;
107 }
108 }else if( zTag ){
109 nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'sym-%q*'",
110 zTag);
111 if ( nTagId==0 ){
112 nTagId = -1;
113 }
114 }else if( zWiki ){
115 nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'wiki-%q*'",
116 zWiki);
117 if ( nTagId==0 ){
118 nTagId = -1;
119 }
120 }else{
121 nTagId = 0;
122 }
123
124 if( nTagId==-1 ){
125 blob_appendf(&bSQL, " AND 0");
126 }else if( nTagId!=0 ){
127 blob_appendf(&bSQL, " AND (EXISTS(SELECT 1 FROM tagxref"
128 " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid))", nTagId);
129 }
130
131 if( zFilename ){
132 blob_appendf(&bSQL,
133 " AND (SELECT mlink.fnid FROM mlink WHERE event.objid=mlink.mid) IN (SELECT fnid FROM filename WHERE name=%Q %s)",
134 zFilename, filename_collation()
135 );
136 }
137
138 blob_append( &bSQL, " ORDER BY event.mtime DESC", -1 );
139
140 cgi_set_content_type("application/rss+xml");
141
142
+16 -43
--- src/sync.c
+++ src/sync.c
@@ -27,13 +27,11 @@
2727
** if the argument is false.
2828
**
2929
** Return the number of errors.
3030
*/
3131
int autosync(int flags){
32
- const char *zUrl;
3332
const char *zAutosync;
34
- const char *zPw;
3533
int rc;
3634
int configSync = 0; /* configuration changes transferred */
3735
if( g.fNoSync ){
3836
return 0;
3937
}
@@ -49,18 +47,14 @@
4947
return 0; /* Autosync is completely off */
5048
}
5149
}else{
5250
/* Autosync defaults on. To make it default off, "return" here. */
5351
}
54
- zUrl = db_get("last-sync-url", 0);
55
- if( zUrl==0 ){
56
- return 0; /* No default server */
57
- }
58
- zPw = unobscure(db_get("last-sync-pw", 0));
59
- url_parse(zUrl);
52
+ url_parse(0, URL_REMEMBER);
53
+ if( g.urlProtocol==0 ) return 0;
6054
if( g.urlUser!=0 && g.urlPasswd==0 ){
61
- g.urlPasswd = mprintf("%s", zPw);
55
+ g.urlPasswd = unobscure(db_get("last-sync-pw", 0));
6256
}
6357
#if 0 /* Disabled for now */
6458
if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){
6559
/* When doing an automatic pull, also automatically pull shuns from
6660
** the server if pull_shuns is enabled.
@@ -86,14 +80,18 @@
8680
** of a server to sync against. If no argument is given, use the
8781
** most recently synced URL. Remember the current URL for next time.
8882
*/
8983
static void process_sync_args(unsigned *pConfigFlags, unsigned *pSyncFlags){
9084
const char *zUrl = 0;
91
- const char *zPw = 0;
9285
unsigned configSync = 0;
93
- int urlOptional = find_option("autourl",0,0)!=0;
94
- g.dontKeepUrl = find_option("once",0,0)!=0;
86
+ unsigned urlFlags = URL_REMEMBER | URL_PROMPT_PW;
87
+ int urlOptional = 0;
88
+ if( find_option("autourl",0,0)!=0 ){
89
+ urlOptional = 1;
90
+ urlFlags = 0;
91
+ }
92
+ if( find_option("once",0,0)!=0 ) urlFlags &= ~URL_REMEMBER;
9593
if( find_option("private",0,0)!=0 ){
9694
*pSyncFlags |= SYNC_PRIVATE;
9795
}
9896
if( find_option("verbose","v",0)!=0 ){
9997
*pSyncFlags |= SYNC_VERBOSE;
@@ -100,32 +98,19 @@
10098
}
10199
url_proxy_options();
102100
db_find_and_open_repository(0, 0);
103101
db_open_config(0);
104102
if( g.argc==2 ){
105
- zUrl = db_get("last-sync-url", 0);
106
- zPw = unobscure(db_get("last-sync-pw", 0));
107103
if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
108104
}else if( g.argc==3 ){
109105
zUrl = g.argv[2];
110106
}
111
- if( zUrl==0 ){
107
+ url_parse(zUrl, urlFlags);
108
+ if( g.urlProtocol==0 ){
112109
if( urlOptional ) fossil_exit(0);
113110
usage("URL");
114111
}
115
- url_parse(zUrl);
116
- if( g.urlUser!=0 && g.urlPasswd==0 && g.urlIsSsh==0 ){
117
- if( zPw==0 ){
118
- url_prompt_for_password();
119
- }else{
120
- g.urlPasswd = mprintf("%s", zPw);
121
- }
122
- }
123
- if( !g.dontKeepUrl ){
124
- db_set("last-sync-url", g.urlCanonical, 0);
125
- if( g.urlPasswd ) db_set("last-sync-pw", obscure(g.urlPasswd), 0);
126
- }
127112
user_select();
128113
if( g.argc==2 ){
129114
if( ((*pSyncFlags) & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL) ){
130115
fossil_print("Sync with %s\n", g.urlCanonical);
131116
}else if( (*pSyncFlags) & SYNC_PUSH ){
@@ -258,30 +243,18 @@
258243
db_find_and_open_repository(0, 0);
259244
if( g.argc!=2 && g.argc!=3 ){
260245
usage("remote-url ?URL|off?");
261246
}
262247
if( g.argc==3 ){
263
- if( fossil_strcmp(g.argv[2],"off")==0 ){
264
- db_unset("last-sync-url", 0);
265
- db_unset("last-sync-pw", 0);
266
- }else{
267
- url_parse(g.argv[2]);
268
- if( g.urlUser && g.urlPasswd==0 && g.urlIsSsh==0 ){
269
- url_prompt_for_password();
270
- }
271
- db_set("last-sync-url", g.urlCanonical, 0);
272
- if( g.urlPasswd ){
273
- db_set("last-sync-pw", obscure(g.urlPasswd), 0);
274
- }else{
275
- db_unset("last-sync-pw", 0);
276
- }
277
- }
248
+ db_unset("last-sync-url", 0);
249
+ db_unset("last-sync-pw", 0);
250
+ url_parse(g.argv[2], URL_REMEMBER|URL_PROMPT_PW);
278251
}
279252
zUrl = db_get("last-sync-url", 0);
280253
if( zUrl==0 ){
281254
fossil_print("off\n");
282255
return;
283256
}else{
284
- url_parse(zUrl);
257
+ url_parse(zUrl, 0);
285258
fossil_print("%s\n", g.urlCanonical);
286259
}
287260
}
288261
--- src/sync.c
+++ src/sync.c
@@ -27,13 +27,11 @@
27 ** if the argument is false.
28 **
29 ** Return the number of errors.
30 */
31 int autosync(int flags){
32 const char *zUrl;
33 const char *zAutosync;
34 const char *zPw;
35 int rc;
36 int configSync = 0; /* configuration changes transferred */
37 if( g.fNoSync ){
38 return 0;
39 }
@@ -49,18 +47,14 @@
49 return 0; /* Autosync is completely off */
50 }
51 }else{
52 /* Autosync defaults on. To make it default off, "return" here. */
53 }
54 zUrl = db_get("last-sync-url", 0);
55 if( zUrl==0 ){
56 return 0; /* No default server */
57 }
58 zPw = unobscure(db_get("last-sync-pw", 0));
59 url_parse(zUrl);
60 if( g.urlUser!=0 && g.urlPasswd==0 ){
61 g.urlPasswd = mprintf("%s", zPw);
62 }
63 #if 0 /* Disabled for now */
64 if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){
65 /* When doing an automatic pull, also automatically pull shuns from
66 ** the server if pull_shuns is enabled.
@@ -86,14 +80,18 @@
86 ** of a server to sync against. If no argument is given, use the
87 ** most recently synced URL. Remember the current URL for next time.
88 */
89 static void process_sync_args(unsigned *pConfigFlags, unsigned *pSyncFlags){
90 const char *zUrl = 0;
91 const char *zPw = 0;
92 unsigned configSync = 0;
93 int urlOptional = find_option("autourl",0,0)!=0;
94 g.dontKeepUrl = find_option("once",0,0)!=0;
 
 
 
 
 
95 if( find_option("private",0,0)!=0 ){
96 *pSyncFlags |= SYNC_PRIVATE;
97 }
98 if( find_option("verbose","v",0)!=0 ){
99 *pSyncFlags |= SYNC_VERBOSE;
@@ -100,32 +98,19 @@
100 }
101 url_proxy_options();
102 db_find_and_open_repository(0, 0);
103 db_open_config(0);
104 if( g.argc==2 ){
105 zUrl = db_get("last-sync-url", 0);
106 zPw = unobscure(db_get("last-sync-pw", 0));
107 if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
108 }else if( g.argc==3 ){
109 zUrl = g.argv[2];
110 }
111 if( zUrl==0 ){
 
112 if( urlOptional ) fossil_exit(0);
113 usage("URL");
114 }
115 url_parse(zUrl);
116 if( g.urlUser!=0 && g.urlPasswd==0 && g.urlIsSsh==0 ){
117 if( zPw==0 ){
118 url_prompt_for_password();
119 }else{
120 g.urlPasswd = mprintf("%s", zPw);
121 }
122 }
123 if( !g.dontKeepUrl ){
124 db_set("last-sync-url", g.urlCanonical, 0);
125 if( g.urlPasswd ) db_set("last-sync-pw", obscure(g.urlPasswd), 0);
126 }
127 user_select();
128 if( g.argc==2 ){
129 if( ((*pSyncFlags) & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL) ){
130 fossil_print("Sync with %s\n", g.urlCanonical);
131 }else if( (*pSyncFlags) & SYNC_PUSH ){
@@ -258,30 +243,18 @@
258 db_find_and_open_repository(0, 0);
259 if( g.argc!=2 && g.argc!=3 ){
260 usage("remote-url ?URL|off?");
261 }
262 if( g.argc==3 ){
263 if( fossil_strcmp(g.argv[2],"off")==0 ){
264 db_unset("last-sync-url", 0);
265 db_unset("last-sync-pw", 0);
266 }else{
267 url_parse(g.argv[2]);
268 if( g.urlUser && g.urlPasswd==0 && g.urlIsSsh==0 ){
269 url_prompt_for_password();
270 }
271 db_set("last-sync-url", g.urlCanonical, 0);
272 if( g.urlPasswd ){
273 db_set("last-sync-pw", obscure(g.urlPasswd), 0);
274 }else{
275 db_unset("last-sync-pw", 0);
276 }
277 }
278 }
279 zUrl = db_get("last-sync-url", 0);
280 if( zUrl==0 ){
281 fossil_print("off\n");
282 return;
283 }else{
284 url_parse(zUrl);
285 fossil_print("%s\n", g.urlCanonical);
286 }
287 }
288
--- src/sync.c
+++ src/sync.c
@@ -27,13 +27,11 @@
27 ** if the argument is false.
28 **
29 ** Return the number of errors.
30 */
31 int autosync(int flags){
 
32 const char *zAutosync;
 
33 int rc;
34 int configSync = 0; /* configuration changes transferred */
35 if( g.fNoSync ){
36 return 0;
37 }
@@ -49,18 +47,14 @@
47 return 0; /* Autosync is completely off */
48 }
49 }else{
50 /* Autosync defaults on. To make it default off, "return" here. */
51 }
52 url_parse(0, URL_REMEMBER);
53 if( g.urlProtocol==0 ) return 0;
 
 
 
 
54 if( g.urlUser!=0 && g.urlPasswd==0 ){
55 g.urlPasswd = unobscure(db_get("last-sync-pw", 0));
56 }
57 #if 0 /* Disabled for now */
58 if( (flags & AUTOSYNC_PULL)!=0 && db_get_boolean("auto-shun",1) ){
59 /* When doing an automatic pull, also automatically pull shuns from
60 ** the server if pull_shuns is enabled.
@@ -86,14 +80,18 @@
80 ** of a server to sync against. If no argument is given, use the
81 ** most recently synced URL. Remember the current URL for next time.
82 */
83 static void process_sync_args(unsigned *pConfigFlags, unsigned *pSyncFlags){
84 const char *zUrl = 0;
 
85 unsigned configSync = 0;
86 unsigned urlFlags = URL_REMEMBER | URL_PROMPT_PW;
87 int urlOptional = 0;
88 if( find_option("autourl",0,0)!=0 ){
89 urlOptional = 1;
90 urlFlags = 0;
91 }
92 if( find_option("once",0,0)!=0 ) urlFlags &= ~URL_REMEMBER;
93 if( find_option("private",0,0)!=0 ){
94 *pSyncFlags |= SYNC_PRIVATE;
95 }
96 if( find_option("verbose","v",0)!=0 ){
97 *pSyncFlags |= SYNC_VERBOSE;
@@ -100,32 +98,19 @@
98 }
99 url_proxy_options();
100 db_find_and_open_repository(0, 0);
101 db_open_config(0);
102 if( g.argc==2 ){
 
 
103 if( db_get_boolean("auto-shun",1) ) configSync = CONFIGSET_SHUN;
104 }else if( g.argc==3 ){
105 zUrl = g.argv[2];
106 }
107 url_parse(zUrl, urlFlags);
108 if( g.urlProtocol==0 ){
109 if( urlOptional ) fossil_exit(0);
110 usage("URL");
111 }
 
 
 
 
 
 
 
 
 
 
 
 
112 user_select();
113 if( g.argc==2 ){
114 if( ((*pSyncFlags) & (SYNC_PUSH|SYNC_PULL))==(SYNC_PUSH|SYNC_PULL) ){
115 fossil_print("Sync with %s\n", g.urlCanonical);
116 }else if( (*pSyncFlags) & SYNC_PUSH ){
@@ -258,30 +243,18 @@
243 db_find_and_open_repository(0, 0);
244 if( g.argc!=2 && g.argc!=3 ){
245 usage("remote-url ?URL|off?");
246 }
247 if( g.argc==3 ){
248 db_unset("last-sync-url", 0);
249 db_unset("last-sync-pw", 0);
250 url_parse(g.argv[2], URL_REMEMBER|URL_PROMPT_PW);
 
 
 
 
 
 
 
 
 
 
 
 
251 }
252 zUrl = db_get("last-sync-url", 0);
253 if( zUrl==0 ){
254 fossil_print("off\n");
255 return;
256 }else{
257 url_parse(zUrl, 0);
258 fossil_print("%s\n", g.urlCanonical);
259 }
260 }
261
+88 -8
--- src/url.c
+++ src/url.c
@@ -17,10 +17,23 @@
1717
**
1818
** This file contains code for parsing URLs that appear on the command-line
1919
*/
2020
#include "config.h"
2121
#include "url.h"
22
+
23
+#if INTERFACE
24
+/*
25
+** Flags for url_parse()
26
+*/
27
+#define URL_PROMPT_PW 0x001 /* Prompt for password if needed */
28
+#define URL_REMEMBER 0x002 /* Remember the url for later reuse */
29
+#define URL_ASK_REMEMBER_PW 0x004 /* Ask whether to remember prompted pw */
30
+#define URL_REMEMBER_PW 0x008 /* Should remember pw */
31
+#define URL_PROMPTED 0x010 /* Prompted for PW already */
32
+
33
+#endif /* INTERFACE */
34
+
2235
2336
/*
2437
** Convert a string to lower-case.
2538
*/
2639
static void url_tolower(char *z){
@@ -29,11 +42,12 @@
2942
z++;
3043
}
3144
}
3245
3346
/*
34
-** Parse the given URL. Populate variables in the global "g" structure.
47
+** Parse the given URL, which describes a sync server. Populate variables
48
+** in the global "g" structure as follows:
3549
**
3650
** g.urlIsFile True if FILE:
3751
** g.urlIsHttps True if HTTPS:
3852
** g.urlIsSsh True if SSH:
3953
** g.urlProtocol "http" or "https" or "file"
@@ -44,22 +58,32 @@
4458
** g.urlUser Userid.
4559
** g.urlPasswd Password.
4660
** g.urlHostname HOST:PORT or just HOST if port is the default.
4761
** g.urlCanonical The URL in canonical form, omitting the password
4862
**
49
-** HTTP url format is:
63
+** HTTP url format as follows (HTTPS is the same with a different scheme):
5064
**
5165
** http://userid:password@host:port/path
5266
**
5367
** SSH url format is:
5468
**
5569
** ssh://userid:password@host:port/path?fossil=path/to/fossil.exe
5670
**
5771
*/
58
-void url_parse(const char *zUrl){
72
+void url_parse(const char *zUrl, unsigned int urlFlags){
5973
int i, j, c;
6074
char *zFile = 0;
75
+ int bPrompted = 0;
76
+ int bSetUrl = 1;
77
+
78
+ if( zUrl==0 ){
79
+ zUrl = db_get("last-sync-url", 0);
80
+ if( zUrl==0 ) return;
81
+ g.urlPasswd = unobscure(db_get("last-sync-pw", 0));
82
+ bSetUrl = 0;
83
+ }
84
+
6185
if( strncmp(zUrl, "http://", 7)==0
6286
|| strncmp(zUrl, "https://", 8)==0
6387
|| strncmp(zUrl, "ssh://", 6)==0
6488
){
6589
int iStart;
@@ -188,15 +212,16 @@
188212
zFile = mprintf("%s/FOSSIL", zUrl);
189213
if( file_isfile(zFile) ){
190214
g.urlIsFile = 1;
191215
}else{
192216
free(zFile);
193
- fossil_panic("unknown repository: %s", zUrl);
217
+ fossil_fatal("unknown repository: %s", zUrl);
194218
}
195219
}else{
196
- fossil_panic("unknown repository: %s", zUrl);
220
+ fossil_fatal("unknown repository: %s", zUrl);
197221
}
222
+ g.urlFlags = urlFlags;
198223
if( g.urlIsFile ){
199224
Blob cfile;
200225
dehttpize(zFile);
201226
file_canonical_name(zFile, &cfile, 0);
202227
free(zFile);
@@ -203,23 +228,45 @@
203228
g.urlProtocol = "file";
204229
g.urlPath = "";
205230
g.urlName = mprintf("%b", &cfile);
206231
g.urlCanonical = mprintf("file://%T", g.urlName);
207232
blob_reset(&cfile);
233
+ }else if( g.urlUser!=0 && g.urlPasswd==0 && (urlFlags & URL_PROMPT_PW) ){
234
+ url_prompt_for_password();
235
+ bPrompted = 1;
236
+ }
237
+ if( urlFlags & URL_REMEMBER ){
238
+ if( bSetUrl ){
239
+ db_set("last-sync-url", g.urlCanonical, 0);
240
+ }
241
+ if( !bPrompted && g.urlPasswd && g.urlUser ){
242
+ db_set("last-sync-pw", obscure(g.urlPasswd), 0);
243
+ }
208244
}
209245
}
210246
211247
/*
212248
** COMMAND: test-urlparser
249
+**
250
+** Usage: %fossil test-urlparser URL ?options?
251
+**
252
+** --remember Store results in last-sync-url
253
+** --prompt-pw Prompt for password if missing
213254
*/
214255
void cmd_test_urlparser(void){
215256
int i;
257
+ unsigned fg = 0;
216258
url_proxy_options();
259
+ if( find_option("remember",0,0) ){
260
+ db_must_be_within_tree();
261
+ fg |= URL_REMEMBER;
262
+ }
263
+ if( find_option("prompt-pw",0,0) ) fg |= URL_PROMPT_PW;
217264
if( g.argc!=3 && g.argc!=4 ){
218265
usage("URL");
219266
}
220
- url_parse(g.argv[2]);
267
+ url_parse(g.argv[2], fg);
221268
for(i=0; i<2; i++){
222269
fossil_print("g.urlIsFile = %d\n", g.urlIsFile);
223270
fossil_print("g.urlIsHttps = %d\n", g.urlIsHttps);
224271
fossil_print("g.urlIsSsh = %d\n", g.urlIsSsh);
225272
fossil_print("g.urlProtocol = %s\n", g.urlProtocol);
@@ -230,10 +277,11 @@
230277
fossil_print("g.urlPath = %s\n", g.urlPath);
231278
fossil_print("g.urlUser = %s\n", g.urlUser);
232279
fossil_print("g.urlPasswd = %s\n", g.urlPasswd);
233280
fossil_print("g.urlCanonical = %s\n", g.urlCanonical);
234281
fossil_print("g.urlFossil = %s\n", g.urlFossil);
282
+ fossil_print("g.urlFlags = 0x%02x\n", g.urlFlags);
235283
if( g.urlIsFile || g.urlIsSsh ) break;
236284
if( i==0 ){
237285
fossil_print("********\n");
238286
url_enable_proxy("Using proxy: ");
239287
}
@@ -282,13 +330,14 @@
282330
if( zProxy && zProxy[0] && !is_false(zProxy) ){
283331
char *zOriginalUrl = g.urlCanonical;
284332
char *zOriginalHost = g.urlHostname;
285333
char *zOriginalUser = g.urlUser;
286334
char *zOriginalPasswd = g.urlPasswd;
335
+ unsigned uOriginalFlags = g.urlFlags;
287336
g.urlUser = 0;
288337
g.urlPasswd = "";
289
- url_parse(zProxy);
338
+ url_parse(zProxy, 0);
290339
if( zMsg ) fossil_print("%s%s\n", zMsg, g.urlCanonical);
291340
g.urlPath = zOriginalUrl;
292341
g.urlHostname = zOriginalHost;
293342
if( g.urlUser ){
294343
char *zCredentials1 = mprintf("%s:%s", g.urlUser, g.urlPasswd);
@@ -296,10 +345,11 @@
296345
g.urlProxyAuth = mprintf("Basic %z", zCredentials2);
297346
free(zCredentials1);
298347
}
299348
g.urlUser = zOriginalUser;
300349
g.urlPasswd = zOriginalPasswd;
350
+ g.urlFlags = uOriginalFlags;
301351
}
302352
}
303353
304354
#if INTERFACE
305355
/*
@@ -379,22 +429,52 @@
379429
/*
380430
** Prompt the user for the password for g.urlUser. Store the result
381431
** in g.urlPasswd.
382432
*/
383433
void url_prompt_for_password(void){
384
- if( isatty(fileno(stdin)) ){
434
+ if( isatty(fileno(stdin))
435
+ && (g.urlFlags & URL_PROMPT_PW)!=0
436
+ && (g.urlFlags & URL_PROMPTED)==0
437
+ ){
385438
char *zPrompt = mprintf("\rpassword for %s: ", g.urlUser);
386439
Blob x;
440
+ fossil_force_newline();
387441
prompt_for_password(zPrompt, &x, 0);
388442
free(zPrompt);
389443
g.urlPasswd = mprintf("%b", &x);
390444
blob_reset(&x);
445
+ g.urlFlags |= URL_PROMPTED;
446
+ if( g.urlPasswd[0]
447
+ && (g.urlFlags & (URL_REMEMBER|URL_ASK_REMEMBER_PW))!=0
448
+ ){
449
+ char c;
450
+ prompt_user("remember password (Y/n)? ", &x);
451
+ c = blob_str(&x)[0];
452
+ blob_reset(&x);
453
+ if( c!='n' && c!='N' ){
454
+ g.urlFlags |= URL_REMEMBER_PW;
455
+ if( g.urlFlags & URL_REMEMBER ){
456
+ db_set("last-sync-pw", obscure(g.urlPasswd), 0);
457
+ }
458
+ }
459
+ }
391460
}else{
392461
fossil_fatal("missing or incorrect password for user \"%s\"",
393462
g.urlUser);
394463
}
395464
}
465
+
466
+/*
467
+** Remember the URL if requested.
468
+*/
469
+void url_remember(void){
470
+ db_set("last-sync-url", g.urlCanonical, 0);
471
+ if( g.urlFlags & URL_REMEMBER_PW ){
472
+ db_set("last-sync-pw", obscure(g.urlPasswd), 0);
473
+ }
474
+ g.urlFlags |= URL_REMEMBER;
475
+}
396476
397477
/* Preemptively prompt for a password if a username is given in the
398478
** URL but no password.
399479
*/
400480
void url_get_password_if_needed(void){
401481
--- src/url.c
+++ src/url.c
@@ -17,10 +17,23 @@
17 **
18 ** This file contains code for parsing URLs that appear on the command-line
19 */
20 #include "config.h"
21 #include "url.h"
 
 
 
 
 
 
 
 
 
 
 
 
 
22
23 /*
24 ** Convert a string to lower-case.
25 */
26 static void url_tolower(char *z){
@@ -29,11 +42,12 @@
29 z++;
30 }
31 }
32
33 /*
34 ** Parse the given URL. Populate variables in the global "g" structure.
 
35 **
36 ** g.urlIsFile True if FILE:
37 ** g.urlIsHttps True if HTTPS:
38 ** g.urlIsSsh True if SSH:
39 ** g.urlProtocol "http" or "https" or "file"
@@ -44,22 +58,32 @@
44 ** g.urlUser Userid.
45 ** g.urlPasswd Password.
46 ** g.urlHostname HOST:PORT or just HOST if port is the default.
47 ** g.urlCanonical The URL in canonical form, omitting the password
48 **
49 ** HTTP url format is:
50 **
51 ** http://userid:password@host:port/path
52 **
53 ** SSH url format is:
54 **
55 ** ssh://userid:password@host:port/path?fossil=path/to/fossil.exe
56 **
57 */
58 void url_parse(const char *zUrl){
59 int i, j, c;
60 char *zFile = 0;
 
 
 
 
 
 
 
 
 
 
61 if( strncmp(zUrl, "http://", 7)==0
62 || strncmp(zUrl, "https://", 8)==0
63 || strncmp(zUrl, "ssh://", 6)==0
64 ){
65 int iStart;
@@ -188,15 +212,16 @@
188 zFile = mprintf("%s/FOSSIL", zUrl);
189 if( file_isfile(zFile) ){
190 g.urlIsFile = 1;
191 }else{
192 free(zFile);
193 fossil_panic("unknown repository: %s", zUrl);
194 }
195 }else{
196 fossil_panic("unknown repository: %s", zUrl);
197 }
 
198 if( g.urlIsFile ){
199 Blob cfile;
200 dehttpize(zFile);
201 file_canonical_name(zFile, &cfile, 0);
202 free(zFile);
@@ -203,23 +228,45 @@
203 g.urlProtocol = "file";
204 g.urlPath = "";
205 g.urlName = mprintf("%b", &cfile);
206 g.urlCanonical = mprintf("file://%T", g.urlName);
207 blob_reset(&cfile);
 
 
 
 
 
 
 
 
 
 
 
208 }
209 }
210
211 /*
212 ** COMMAND: test-urlparser
 
 
 
 
 
213 */
214 void cmd_test_urlparser(void){
215 int i;
 
216 url_proxy_options();
 
 
 
 
 
217 if( g.argc!=3 && g.argc!=4 ){
218 usage("URL");
219 }
220 url_parse(g.argv[2]);
221 for(i=0; i<2; i++){
222 fossil_print("g.urlIsFile = %d\n", g.urlIsFile);
223 fossil_print("g.urlIsHttps = %d\n", g.urlIsHttps);
224 fossil_print("g.urlIsSsh = %d\n", g.urlIsSsh);
225 fossil_print("g.urlProtocol = %s\n", g.urlProtocol);
@@ -230,10 +277,11 @@
230 fossil_print("g.urlPath = %s\n", g.urlPath);
231 fossil_print("g.urlUser = %s\n", g.urlUser);
232 fossil_print("g.urlPasswd = %s\n", g.urlPasswd);
233 fossil_print("g.urlCanonical = %s\n", g.urlCanonical);
234 fossil_print("g.urlFossil = %s\n", g.urlFossil);
 
235 if( g.urlIsFile || g.urlIsSsh ) break;
236 if( i==0 ){
237 fossil_print("********\n");
238 url_enable_proxy("Using proxy: ");
239 }
@@ -282,13 +330,14 @@
282 if( zProxy && zProxy[0] && !is_false(zProxy) ){
283 char *zOriginalUrl = g.urlCanonical;
284 char *zOriginalHost = g.urlHostname;
285 char *zOriginalUser = g.urlUser;
286 char *zOriginalPasswd = g.urlPasswd;
 
287 g.urlUser = 0;
288 g.urlPasswd = "";
289 url_parse(zProxy);
290 if( zMsg ) fossil_print("%s%s\n", zMsg, g.urlCanonical);
291 g.urlPath = zOriginalUrl;
292 g.urlHostname = zOriginalHost;
293 if( g.urlUser ){
294 char *zCredentials1 = mprintf("%s:%s", g.urlUser, g.urlPasswd);
@@ -296,10 +345,11 @@
296 g.urlProxyAuth = mprintf("Basic %z", zCredentials2);
297 free(zCredentials1);
298 }
299 g.urlUser = zOriginalUser;
300 g.urlPasswd = zOriginalPasswd;
 
301 }
302 }
303
304 #if INTERFACE
305 /*
@@ -379,22 +429,52 @@
379 /*
380 ** Prompt the user for the password for g.urlUser. Store the result
381 ** in g.urlPasswd.
382 */
383 void url_prompt_for_password(void){
384 if( isatty(fileno(stdin)) ){
 
 
 
385 char *zPrompt = mprintf("\rpassword for %s: ", g.urlUser);
386 Blob x;
 
387 prompt_for_password(zPrompt, &x, 0);
388 free(zPrompt);
389 g.urlPasswd = mprintf("%b", &x);
390 blob_reset(&x);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
391 }else{
392 fossil_fatal("missing or incorrect password for user \"%s\"",
393 g.urlUser);
394 }
395 }
 
 
 
 
 
 
 
 
 
 
 
396
397 /* Preemptively prompt for a password if a username is given in the
398 ** URL but no password.
399 */
400 void url_get_password_if_needed(void){
401
--- src/url.c
+++ src/url.c
@@ -17,10 +17,23 @@
17 **
18 ** This file contains code for parsing URLs that appear on the command-line
19 */
20 #include "config.h"
21 #include "url.h"
22
23 #if INTERFACE
24 /*
25 ** Flags for url_parse()
26 */
27 #define URL_PROMPT_PW 0x001 /* Prompt for password if needed */
28 #define URL_REMEMBER 0x002 /* Remember the url for later reuse */
29 #define URL_ASK_REMEMBER_PW 0x004 /* Ask whether to remember prompted pw */
30 #define URL_REMEMBER_PW 0x008 /* Should remember pw */
31 #define URL_PROMPTED 0x010 /* Prompted for PW already */
32
33 #endif /* INTERFACE */
34
35
36 /*
37 ** Convert a string to lower-case.
38 */
39 static void url_tolower(char *z){
@@ -29,11 +42,12 @@
42 z++;
43 }
44 }
45
46 /*
47 ** Parse the given URL, which describes a sync server. Populate variables
48 ** in the global "g" structure as follows:
49 **
50 ** g.urlIsFile True if FILE:
51 ** g.urlIsHttps True if HTTPS:
52 ** g.urlIsSsh True if SSH:
53 ** g.urlProtocol "http" or "https" or "file"
@@ -44,22 +58,32 @@
58 ** g.urlUser Userid.
59 ** g.urlPasswd Password.
60 ** g.urlHostname HOST:PORT or just HOST if port is the default.
61 ** g.urlCanonical The URL in canonical form, omitting the password
62 **
63 ** HTTP url format as follows (HTTPS is the same with a different scheme):
64 **
65 ** http://userid:password@host:port/path
66 **
67 ** SSH url format is:
68 **
69 ** ssh://userid:password@host:port/path?fossil=path/to/fossil.exe
70 **
71 */
72 void url_parse(const char *zUrl, unsigned int urlFlags){
73 int i, j, c;
74 char *zFile = 0;
75 int bPrompted = 0;
76 int bSetUrl = 1;
77
78 if( zUrl==0 ){
79 zUrl = db_get("last-sync-url", 0);
80 if( zUrl==0 ) return;
81 g.urlPasswd = unobscure(db_get("last-sync-pw", 0));
82 bSetUrl = 0;
83 }
84
85 if( strncmp(zUrl, "http://", 7)==0
86 || strncmp(zUrl, "https://", 8)==0
87 || strncmp(zUrl, "ssh://", 6)==0
88 ){
89 int iStart;
@@ -188,15 +212,16 @@
212 zFile = mprintf("%s/FOSSIL", zUrl);
213 if( file_isfile(zFile) ){
214 g.urlIsFile = 1;
215 }else{
216 free(zFile);
217 fossil_fatal("unknown repository: %s", zUrl);
218 }
219 }else{
220 fossil_fatal("unknown repository: %s", zUrl);
221 }
222 g.urlFlags = urlFlags;
223 if( g.urlIsFile ){
224 Blob cfile;
225 dehttpize(zFile);
226 file_canonical_name(zFile, &cfile, 0);
227 free(zFile);
@@ -203,23 +228,45 @@
228 g.urlProtocol = "file";
229 g.urlPath = "";
230 g.urlName = mprintf("%b", &cfile);
231 g.urlCanonical = mprintf("file://%T", g.urlName);
232 blob_reset(&cfile);
233 }else if( g.urlUser!=0 && g.urlPasswd==0 && (urlFlags & URL_PROMPT_PW) ){
234 url_prompt_for_password();
235 bPrompted = 1;
236 }
237 if( urlFlags & URL_REMEMBER ){
238 if( bSetUrl ){
239 db_set("last-sync-url", g.urlCanonical, 0);
240 }
241 if( !bPrompted && g.urlPasswd && g.urlUser ){
242 db_set("last-sync-pw", obscure(g.urlPasswd), 0);
243 }
244 }
245 }
246
247 /*
248 ** COMMAND: test-urlparser
249 **
250 ** Usage: %fossil test-urlparser URL ?options?
251 **
252 ** --remember Store results in last-sync-url
253 ** --prompt-pw Prompt for password if missing
254 */
255 void cmd_test_urlparser(void){
256 int i;
257 unsigned fg = 0;
258 url_proxy_options();
259 if( find_option("remember",0,0) ){
260 db_must_be_within_tree();
261 fg |= URL_REMEMBER;
262 }
263 if( find_option("prompt-pw",0,0) ) fg |= URL_PROMPT_PW;
264 if( g.argc!=3 && g.argc!=4 ){
265 usage("URL");
266 }
267 url_parse(g.argv[2], fg);
268 for(i=0; i<2; i++){
269 fossil_print("g.urlIsFile = %d\n", g.urlIsFile);
270 fossil_print("g.urlIsHttps = %d\n", g.urlIsHttps);
271 fossil_print("g.urlIsSsh = %d\n", g.urlIsSsh);
272 fossil_print("g.urlProtocol = %s\n", g.urlProtocol);
@@ -230,10 +277,11 @@
277 fossil_print("g.urlPath = %s\n", g.urlPath);
278 fossil_print("g.urlUser = %s\n", g.urlUser);
279 fossil_print("g.urlPasswd = %s\n", g.urlPasswd);
280 fossil_print("g.urlCanonical = %s\n", g.urlCanonical);
281 fossil_print("g.urlFossil = %s\n", g.urlFossil);
282 fossil_print("g.urlFlags = 0x%02x\n", g.urlFlags);
283 if( g.urlIsFile || g.urlIsSsh ) break;
284 if( i==0 ){
285 fossil_print("********\n");
286 url_enable_proxy("Using proxy: ");
287 }
@@ -282,13 +330,14 @@
330 if( zProxy && zProxy[0] && !is_false(zProxy) ){
331 char *zOriginalUrl = g.urlCanonical;
332 char *zOriginalHost = g.urlHostname;
333 char *zOriginalUser = g.urlUser;
334 char *zOriginalPasswd = g.urlPasswd;
335 unsigned uOriginalFlags = g.urlFlags;
336 g.urlUser = 0;
337 g.urlPasswd = "";
338 url_parse(zProxy, 0);
339 if( zMsg ) fossil_print("%s%s\n", zMsg, g.urlCanonical);
340 g.urlPath = zOriginalUrl;
341 g.urlHostname = zOriginalHost;
342 if( g.urlUser ){
343 char *zCredentials1 = mprintf("%s:%s", g.urlUser, g.urlPasswd);
@@ -296,10 +345,11 @@
345 g.urlProxyAuth = mprintf("Basic %z", zCredentials2);
346 free(zCredentials1);
347 }
348 g.urlUser = zOriginalUser;
349 g.urlPasswd = zOriginalPasswd;
350 g.urlFlags = uOriginalFlags;
351 }
352 }
353
354 #if INTERFACE
355 /*
@@ -379,22 +429,52 @@
429 /*
430 ** Prompt the user for the password for g.urlUser. Store the result
431 ** in g.urlPasswd.
432 */
433 void url_prompt_for_password(void){
434 if( isatty(fileno(stdin))
435 && (g.urlFlags & URL_PROMPT_PW)!=0
436 && (g.urlFlags & URL_PROMPTED)==0
437 ){
438 char *zPrompt = mprintf("\rpassword for %s: ", g.urlUser);
439 Blob x;
440 fossil_force_newline();
441 prompt_for_password(zPrompt, &x, 0);
442 free(zPrompt);
443 g.urlPasswd = mprintf("%b", &x);
444 blob_reset(&x);
445 g.urlFlags |= URL_PROMPTED;
446 if( g.urlPasswd[0]
447 && (g.urlFlags & (URL_REMEMBER|URL_ASK_REMEMBER_PW))!=0
448 ){
449 char c;
450 prompt_user("remember password (Y/n)? ", &x);
451 c = blob_str(&x)[0];
452 blob_reset(&x);
453 if( c!='n' && c!='N' ){
454 g.urlFlags |= URL_REMEMBER_PW;
455 if( g.urlFlags & URL_REMEMBER ){
456 db_set("last-sync-pw", obscure(g.urlPasswd), 0);
457 }
458 }
459 }
460 }else{
461 fossil_fatal("missing or incorrect password for user \"%s\"",
462 g.urlUser);
463 }
464 }
465
466 /*
467 ** Remember the URL if requested.
468 */
469 void url_remember(void){
470 db_set("last-sync-url", g.urlCanonical, 0);
471 if( g.urlFlags & URL_REMEMBER_PW ){
472 db_set("last-sync-pw", obscure(g.urlPasswd), 0);
473 }
474 g.urlFlags |= URL_REMEMBER;
475 }
476
477 /* Preemptively prompt for a password if a username is given in the
478 ** URL but no password.
479 */
480 void url_get_password_if_needed(void){
481
+2 -7
--- src/user.c
+++ src/user.c
@@ -314,12 +314,10 @@
314314
** (7) Check if the user can be extracted from the remote URL.
315315
**
316316
** The user name is stored in g.zLogin. The uid is in g.userUid.
317317
*/
318318
void user_select(void){
319
- char *zUrl;
320
-
321319
if( g.userUid ) return;
322320
if( g.zLogin ){
323321
if( attempt_user(g.zLogin)==0 ){
324322
fossil_fatal("no such user: %s", g.zLogin);
325323
}else{
@@ -335,15 +333,12 @@
335333
336334
if( attempt_user(fossil_getenv("USER")) ) return;
337335
338336
if( attempt_user(fossil_getenv("USERNAME")) ) return;
339337
340
- zUrl = db_get("last-sync-url", 0);
341
- if( zUrl ){
342
- url_parse(zUrl);
343
- if( attempt_user(g.urlUser) ) return;
344
- }
338
+ url_parse(0, 0);
339
+ if( g.urlUser && attempt_user(g.urlUser) ) return;
345340
346341
fossil_print(
347342
"Cannot figure out who you are! Consider using the --user\n"
348343
"command line option, setting your USER environment variable,\n"
349344
"or setting a default user with \"fossil user default USER\".\n"
350345
--- src/user.c
+++ src/user.c
@@ -314,12 +314,10 @@
314 ** (7) Check if the user can be extracted from the remote URL.
315 **
316 ** The user name is stored in g.zLogin. The uid is in g.userUid.
317 */
318 void user_select(void){
319 char *zUrl;
320
321 if( g.userUid ) return;
322 if( g.zLogin ){
323 if( attempt_user(g.zLogin)==0 ){
324 fossil_fatal("no such user: %s", g.zLogin);
325 }else{
@@ -335,15 +333,12 @@
335
336 if( attempt_user(fossil_getenv("USER")) ) return;
337
338 if( attempt_user(fossil_getenv("USERNAME")) ) return;
339
340 zUrl = db_get("last-sync-url", 0);
341 if( zUrl ){
342 url_parse(zUrl);
343 if( attempt_user(g.urlUser) ) return;
344 }
345
346 fossil_print(
347 "Cannot figure out who you are! Consider using the --user\n"
348 "command line option, setting your USER environment variable,\n"
349 "or setting a default user with \"fossil user default USER\".\n"
350
--- src/user.c
+++ src/user.c
@@ -314,12 +314,10 @@
314 ** (7) Check if the user can be extracted from the remote URL.
315 **
316 ** The user name is stored in g.zLogin. The uid is in g.userUid.
317 */
318 void user_select(void){
 
 
319 if( g.userUid ) return;
320 if( g.zLogin ){
321 if( attempt_user(g.zLogin)==0 ){
322 fossil_fatal("no such user: %s", g.zLogin);
323 }else{
@@ -335,15 +333,12 @@
333
334 if( attempt_user(fossil_getenv("USER")) ) return;
335
336 if( attempt_user(fossil_getenv("USERNAME")) ) return;
337
338 url_parse(0, 0);
339 if( g.urlUser && attempt_user(g.urlUser) ) return;
 
 
 
340
341 fossil_print(
342 "Cannot figure out who you are! Consider using the --user\n"
343 "command line option, setting your USER environment variable,\n"
344 "or setting a default user with \"fossil user default USER\".\n"
345
+23 -25
--- src/utf8.c
+++ src/utf8.c
@@ -24,38 +24,31 @@
2424
#include <sqlite3.h>
2525
#ifdef _WIN32
2626
# include <windows.h>
2727
#endif
2828
29
+#ifdef _WIN32
2930
/*
30
-** Translate MBCS to UTF8. Return a pointer to the translated text.
31
+** Translate MBCS to UTF-8. Return a pointer to the translated text.
3132
** Call fossil_mbcs_free() to deallocate any memory used to store the
3233
** returned pointer when done.
3334
*/
3435
char *fossil_mbcs_to_utf8(const char *zMbcs){
35
-#ifdef _WIN32
3636
extern char *sqlite3_win32_mbcs_to_utf8(const char*);
3737
return sqlite3_win32_mbcs_to_utf8(zMbcs);
38
-#else
39
- return (char*)zMbcs; /* No-op on unix */
40
-#endif
4138
}
4239
4340
/*
44
-** After translating from UTF8 to MBCS, invoke this routine to deallocate
41
+** After translating from UTF-8 to MBCS, invoke this routine to deallocate
4542
** any memory used to hold the translation
4643
*/
4744
void fossil_mbcs_free(char *zOld){
48
-#ifdef _WIN32
4945
sqlite3_free(zOld);
50
-#else
51
- /* No-op on unix */
52
-#endif
5346
}
5447
5548
/*
56
-** Translate Unicode text into UTF8.
49
+** Translate Unicode text into UTF-8.
5750
** Return a pointer to the translated text.
5851
** Call fossil_unicode_free() to deallocate any memory used to store the
5952
** returned pointer when done.
6053
*/
6154
char *fossil_unicode_to_utf8(const void *zUnicode){
@@ -66,16 +59,16 @@
6659
return 0;
6760
}
6861
WideCharToMultiByte(CP_UTF8, 0, zUnicode, -1, zUtf, nByte, 0, 0);
6962
return zUtf;
7063
#else
71
- return (char *)zUnicode; /* No-op on unix */
64
+ return fossil_strdup(zUtf8); /* TODO: implement for unix */
7265
#endif
7366
}
7467
7568
/*
76
-** Translate UTF8 to unicode for use in system calls. Return a pointer to the
69
+** Translate UTF-8 to unicode for use in system calls. Return a pointer to the
7770
** translated text.. Call fossil_unicode_free() to deallocate any memory
7871
** used to store the returned pointer when done.
7972
*/
8073
void *fossil_utf8_to_unicode(const char *zUtf8){
8174
#ifdef _WIN32
@@ -85,11 +78,11 @@
8578
return 0;
8679
}
8780
MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nByte);
8881
return zUnicode;
8982
#else
90
- return (void *)zUtf8; /* No-op on unix */
83
+ return fossil_strdup(zUtf8); /* TODO: implement for unix */
9184
#endif
9285
}
9386
9487
/*
9588
** Deallocate any memory that was previously allocated by
@@ -97,32 +90,33 @@
9790
*/
9891
void fossil_unicode_free(void *pOld){
9992
#ifdef _WIN32
10093
sqlite3_free(pOld);
10194
#else
102
- /* No-op on unix */
95
+ fossil_free(pOld);
10396
#endif
10497
}
98
+#endif /* _WIN32 */
10599
106100
#if defined(__APPLE__) && !defined(WITHOUT_ICONV)
107101
# include <iconv.h>
108102
#endif
109103
110104
/*
111
-** Translate text from the filename character set into
112
-** to precomposed UTF8. Return a pointer to the translated text.
105
+** Translate text from the filename character set into UTF-8.
106
+** Return a pointer to the translated text.
113107
** Call fossil_filename_free() to deallocate any memory used to store the
114108
** returned pointer when done.
115109
*/
116110
char *fossil_filename_to_utf8(void *zFilename){
117111
#if defined(_WIN32)
118112
int nByte;
119113
char *zUtf;
120
- WCHAR *wUnicode = zFilename;
114
+ wchar_t *wUnicode = zFilename;
121115
while( *wUnicode != 0 ){
122
- if ( (*wUnicode & 0xFF80) == 0xF000 ){
123
- WCHAR converted = (*wUnicode & 0x7F);
116
+ if ( (*wUnicode & 0xff80) == 0xf000 ){
117
+ wchar_t converted = (*wUnicode & 0x7f);
124118
/* Only really convert it when the resulting char is in the given range*/
125119
if ( (converted < 32) || wcschr(L"\"*<>?|:", converted) ){
126120
*wUnicode = converted;
127121
}
128122
}
@@ -168,11 +162,11 @@
168162
return (char *)zFilename; /* No-op on non-mac unix */
169163
#endif
170164
}
171165
172166
/*
173
-** Translate UTF8 to unicode for use in filename translations.
167
+** Translate UTF-8 to unicode for use in filename translations.
174168
** Return a pointer to the translated text.. Call fossil_filename_free()
175169
** to deallocate any memory used to store the returned pointer when done.
176170
**
177171
** On Windows, characters in the range U+0001 to U+0031 and the
178172
** characters '"', '*', ':', '<', '>', '?' and '|' are invalid
@@ -185,12 +179,17 @@
185179
** See: <http://cygwin.com/cygwin-ug-net/using-specialnames.html>
186180
**
187181
*/
188182
void *fossil_utf8_to_filename(const char *zUtf8){
189183
#ifdef _WIN32
190
- WCHAR *zUnicode = fossil_utf8_to_unicode(zUtf8);
191
- WCHAR *wUnicode = zUnicode;
184
+ int nByte = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0);
185
+ wchar_t *zUnicode = sqlite3_malloc( nByte * 2 );
186
+ wchar_t *wUnicode = zUnicode;
187
+ if( zUnicode==0 ){
188
+ return 0;
189
+ }
190
+ MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nByte);
192191
/* If path starts with "<drive>:/" or "<drive>:\", don't translate the ':' */
193192
if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
194193
&& (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
195194
zUnicode[2] = '\\';
196195
wUnicode += 3;
@@ -201,11 +200,10 @@
201200
}else if( *wUnicode == '/' ){
202201
*wUnicode = '\\';
203202
}
204203
++wUnicode;
205204
}
206
-
207205
return zUnicode;
208206
#elif defined(__CYGWIN__)
209207
char *zPath = fossil_strdup(zUtf8);
210208
char *p = zPath;
211209
while( (*p = *zUtf8++) != 0){
@@ -234,11 +232,11 @@
234232
/* No-op on all other unix */
235233
#endif
236234
}
237235
238236
/*
239
-** Display UTF8 on the console. Return the number of
237
+** Display UTF-8 on the console. Return the number of
240238
** Characters written. If stdout or stderr is redirected
241239
** to a file, -1 is returned and nothing is written
242240
** to the console.
243241
*/
244242
int fossil_utf8_to_console(const char *zUtf8, int nByte, int toStdErr){
245243
246244
ADDED src/util.c
--- src/utf8.c
+++ src/utf8.c
@@ -24,38 +24,31 @@
24 #include <sqlite3.h>
25 #ifdef _WIN32
26 # include <windows.h>
27 #endif
28
 
29 /*
30 ** Translate MBCS to UTF8. Return a pointer to the translated text.
31 ** Call fossil_mbcs_free() to deallocate any memory used to store the
32 ** returned pointer when done.
33 */
34 char *fossil_mbcs_to_utf8(const char *zMbcs){
35 #ifdef _WIN32
36 extern char *sqlite3_win32_mbcs_to_utf8(const char*);
37 return sqlite3_win32_mbcs_to_utf8(zMbcs);
38 #else
39 return (char*)zMbcs; /* No-op on unix */
40 #endif
41 }
42
43 /*
44 ** After translating from UTF8 to MBCS, invoke this routine to deallocate
45 ** any memory used to hold the translation
46 */
47 void fossil_mbcs_free(char *zOld){
48 #ifdef _WIN32
49 sqlite3_free(zOld);
50 #else
51 /* No-op on unix */
52 #endif
53 }
54
55 /*
56 ** Translate Unicode text into UTF8.
57 ** Return a pointer to the translated text.
58 ** Call fossil_unicode_free() to deallocate any memory used to store the
59 ** returned pointer when done.
60 */
61 char *fossil_unicode_to_utf8(const void *zUnicode){
@@ -66,16 +59,16 @@
66 return 0;
67 }
68 WideCharToMultiByte(CP_UTF8, 0, zUnicode, -1, zUtf, nByte, 0, 0);
69 return zUtf;
70 #else
71 return (char *)zUnicode; /* No-op on unix */
72 #endif
73 }
74
75 /*
76 ** Translate UTF8 to unicode for use in system calls. Return a pointer to the
77 ** translated text.. Call fossil_unicode_free() to deallocate any memory
78 ** used to store the returned pointer when done.
79 */
80 void *fossil_utf8_to_unicode(const char *zUtf8){
81 #ifdef _WIN32
@@ -85,11 +78,11 @@
85 return 0;
86 }
87 MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nByte);
88 return zUnicode;
89 #else
90 return (void *)zUtf8; /* No-op on unix */
91 #endif
92 }
93
94 /*
95 ** Deallocate any memory that was previously allocated by
@@ -97,32 +90,33 @@
97 */
98 void fossil_unicode_free(void *pOld){
99 #ifdef _WIN32
100 sqlite3_free(pOld);
101 #else
102 /* No-op on unix */
103 #endif
104 }
 
105
106 #if defined(__APPLE__) && !defined(WITHOUT_ICONV)
107 # include <iconv.h>
108 #endif
109
110 /*
111 ** Translate text from the filename character set into
112 ** to precomposed UTF8. Return a pointer to the translated text.
113 ** Call fossil_filename_free() to deallocate any memory used to store the
114 ** returned pointer when done.
115 */
116 char *fossil_filename_to_utf8(void *zFilename){
117 #if defined(_WIN32)
118 int nByte;
119 char *zUtf;
120 WCHAR *wUnicode = zFilename;
121 while( *wUnicode != 0 ){
122 if ( (*wUnicode & 0xFF80) == 0xF000 ){
123 WCHAR converted = (*wUnicode & 0x7F);
124 /* Only really convert it when the resulting char is in the given range*/
125 if ( (converted < 32) || wcschr(L"\"*<>?|:", converted) ){
126 *wUnicode = converted;
127 }
128 }
@@ -168,11 +162,11 @@
168 return (char *)zFilename; /* No-op on non-mac unix */
169 #endif
170 }
171
172 /*
173 ** Translate UTF8 to unicode for use in filename translations.
174 ** Return a pointer to the translated text.. Call fossil_filename_free()
175 ** to deallocate any memory used to store the returned pointer when done.
176 **
177 ** On Windows, characters in the range U+0001 to U+0031 and the
178 ** characters '"', '*', ':', '<', '>', '?' and '|' are invalid
@@ -185,12 +179,17 @@
185 ** See: <http://cygwin.com/cygwin-ug-net/using-specialnames.html>
186 **
187 */
188 void *fossil_utf8_to_filename(const char *zUtf8){
189 #ifdef _WIN32
190 WCHAR *zUnicode = fossil_utf8_to_unicode(zUtf8);
191 WCHAR *wUnicode = zUnicode;
 
 
 
 
 
192 /* If path starts with "<drive>:/" or "<drive>:\", don't translate the ':' */
193 if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
194 && (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
195 zUnicode[2] = '\\';
196 wUnicode += 3;
@@ -201,11 +200,10 @@
201 }else if( *wUnicode == '/' ){
202 *wUnicode = '\\';
203 }
204 ++wUnicode;
205 }
206
207 return zUnicode;
208 #elif defined(__CYGWIN__)
209 char *zPath = fossil_strdup(zUtf8);
210 char *p = zPath;
211 while( (*p = *zUtf8++) != 0){
@@ -234,11 +232,11 @@
234 /* No-op on all other unix */
235 #endif
236 }
237
238 /*
239 ** Display UTF8 on the console. Return the number of
240 ** Characters written. If stdout or stderr is redirected
241 ** to a file, -1 is returned and nothing is written
242 ** to the console.
243 */
244 int fossil_utf8_to_console(const char *zUtf8, int nByte, int toStdErr){
245
246 DDED src/util.c
--- src/utf8.c
+++ src/utf8.c
@@ -24,38 +24,31 @@
24 #include <sqlite3.h>
25 #ifdef _WIN32
26 # include <windows.h>
27 #endif
28
29 #ifdef _WIN32
30 /*
31 ** Translate MBCS to UTF-8. Return a pointer to the translated text.
32 ** Call fossil_mbcs_free() to deallocate any memory used to store the
33 ** returned pointer when done.
34 */
35 char *fossil_mbcs_to_utf8(const char *zMbcs){
 
36 extern char *sqlite3_win32_mbcs_to_utf8(const char*);
37 return sqlite3_win32_mbcs_to_utf8(zMbcs);
 
 
 
38 }
39
40 /*
41 ** After translating from UTF-8 to MBCS, invoke this routine to deallocate
42 ** any memory used to hold the translation
43 */
44 void fossil_mbcs_free(char *zOld){
 
45 sqlite3_free(zOld);
 
 
 
46 }
47
48 /*
49 ** Translate Unicode text into UTF-8.
50 ** Return a pointer to the translated text.
51 ** Call fossil_unicode_free() to deallocate any memory used to store the
52 ** returned pointer when done.
53 */
54 char *fossil_unicode_to_utf8(const void *zUnicode){
@@ -66,16 +59,16 @@
59 return 0;
60 }
61 WideCharToMultiByte(CP_UTF8, 0, zUnicode, -1, zUtf, nByte, 0, 0);
62 return zUtf;
63 #else
64 return fossil_strdup(zUtf8); /* TODO: implement for unix */
65 #endif
66 }
67
68 /*
69 ** Translate UTF-8 to unicode for use in system calls. Return a pointer to the
70 ** translated text.. Call fossil_unicode_free() to deallocate any memory
71 ** used to store the returned pointer when done.
72 */
73 void *fossil_utf8_to_unicode(const char *zUtf8){
74 #ifdef _WIN32
@@ -85,11 +78,11 @@
78 return 0;
79 }
80 MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nByte);
81 return zUnicode;
82 #else
83 return fossil_strdup(zUtf8); /* TODO: implement for unix */
84 #endif
85 }
86
87 /*
88 ** Deallocate any memory that was previously allocated by
@@ -97,32 +90,33 @@
90 */
91 void fossil_unicode_free(void *pOld){
92 #ifdef _WIN32
93 sqlite3_free(pOld);
94 #else
95 fossil_free(pOld);
96 #endif
97 }
98 #endif /* _WIN32 */
99
100 #if defined(__APPLE__) && !defined(WITHOUT_ICONV)
101 # include <iconv.h>
102 #endif
103
104 /*
105 ** Translate text from the filename character set into UTF-8.
106 ** Return a pointer to the translated text.
107 ** Call fossil_filename_free() to deallocate any memory used to store the
108 ** returned pointer when done.
109 */
110 char *fossil_filename_to_utf8(void *zFilename){
111 #if defined(_WIN32)
112 int nByte;
113 char *zUtf;
114 wchar_t *wUnicode = zFilename;
115 while( *wUnicode != 0 ){
116 if ( (*wUnicode & 0xff80) == 0xf000 ){
117 wchar_t converted = (*wUnicode & 0x7f);
118 /* Only really convert it when the resulting char is in the given range*/
119 if ( (converted < 32) || wcschr(L"\"*<>?|:", converted) ){
120 *wUnicode = converted;
121 }
122 }
@@ -168,11 +162,11 @@
162 return (char *)zFilename; /* No-op on non-mac unix */
163 #endif
164 }
165
166 /*
167 ** Translate UTF-8 to unicode for use in filename translations.
168 ** Return a pointer to the translated text.. Call fossil_filename_free()
169 ** to deallocate any memory used to store the returned pointer when done.
170 **
171 ** On Windows, characters in the range U+0001 to U+0031 and the
172 ** characters '"', '*', ':', '<', '>', '?' and '|' are invalid
@@ -185,12 +179,17 @@
179 ** See: <http://cygwin.com/cygwin-ug-net/using-specialnames.html>
180 **
181 */
182 void *fossil_utf8_to_filename(const char *zUtf8){
183 #ifdef _WIN32
184 int nByte = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0);
185 wchar_t *zUnicode = sqlite3_malloc( nByte * 2 );
186 wchar_t *wUnicode = zUnicode;
187 if( zUnicode==0 ){
188 return 0;
189 }
190 MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nByte);
191 /* If path starts with "<drive>:/" or "<drive>:\", don't translate the ':' */
192 if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
193 && (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
194 zUnicode[2] = '\\';
195 wUnicode += 3;
@@ -201,11 +200,10 @@
200 }else if( *wUnicode == '/' ){
201 *wUnicode = '\\';
202 }
203 ++wUnicode;
204 }
 
205 return zUnicode;
206 #elif defined(__CYGWIN__)
207 char *zPath = fossil_strdup(zUtf8);
208 char *p = zPath;
209 while( (*p = *zUtf8++) != 0){
@@ -234,11 +232,11 @@
232 /* No-op on all other unix */
233 #endif
234 }
235
236 /*
237 ** Display UTF-8 on the console. Return the number of
238 ** Characters written. If stdout or stderr is redirected
239 ** to a file, -1 is returned and nothing is written
240 ** to the console.
241 */
242 int fossil_utf8_to_console(const char *zUtf8, int nByte, int toStdErr){
243
244 DDED src/util.c
+23 -25
--- src/utf8.c
+++ src/utf8.c
@@ -24,38 +24,31 @@
2424
#include <sqlite3.h>
2525
#ifdef _WIN32
2626
# include <windows.h>
2727
#endif
2828
29
+#ifdef _WIN32
2930
/*
30
-** Translate MBCS to UTF8. Return a pointer to the translated text.
31
+** Translate MBCS to UTF-8. Return a pointer to the translated text.
3132
** Call fossil_mbcs_free() to deallocate any memory used to store the
3233
** returned pointer when done.
3334
*/
3435
char *fossil_mbcs_to_utf8(const char *zMbcs){
35
-#ifdef _WIN32
3636
extern char *sqlite3_win32_mbcs_to_utf8(const char*);
3737
return sqlite3_win32_mbcs_to_utf8(zMbcs);
38
-#else
39
- return (char*)zMbcs; /* No-op on unix */
40
-#endif
4138
}
4239
4340
/*
44
-** After translating from UTF8 to MBCS, invoke this routine to deallocate
41
+** After translating from UTF-8 to MBCS, invoke this routine to deallocate
4542
** any memory used to hold the translation
4643
*/
4744
void fossil_mbcs_free(char *zOld){
48
-#ifdef _WIN32
4945
sqlite3_free(zOld);
50
-#else
51
- /* No-op on unix */
52
-#endif
5346
}
5447
5548
/*
56
-** Translate Unicode text into UTF8.
49
+** Translate Unicode text into UTF-8.
5750
** Return a pointer to the translated text.
5851
** Call fossil_unicode_free() to deallocate any memory used to store the
5952
** returned pointer when done.
6053
*/
6154
char *fossil_unicode_to_utf8(const void *zUnicode){
@@ -66,16 +59,16 @@
6659
return 0;
6760
}
6861
WideCharToMultiByte(CP_UTF8, 0, zUnicode, -1, zUtf, nByte, 0, 0);
6962
return zUtf;
7063
#else
71
- return (char *)zUnicode; /* No-op on unix */
64
+ return fossil_strdup(zUtf8); /* TODO: implement for unix */
7265
#endif
7366
}
7467
7568
/*
76
-** Translate UTF8 to unicode for use in system calls. Return a pointer to the
69
+** Translate UTF-8 to unicode for use in system calls. Return a pointer to the
7770
** translated text.. Call fossil_unicode_free() to deallocate any memory
7871
** used to store the returned pointer when done.
7972
*/
8073
void *fossil_utf8_to_unicode(const char *zUtf8){
8174
#ifdef _WIN32
@@ -85,11 +78,11 @@
8578
return 0;
8679
}
8780
MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nByte);
8881
return zUnicode;
8982
#else
90
- return (void *)zUtf8; /* No-op on unix */
83
+ return fossil_strdup(zUtf8); /* TODO: implement for unix */
9184
#endif
9285
}
9386
9487
/*
9588
** Deallocate any memory that was previously allocated by
@@ -97,32 +90,33 @@
9790
*/
9891
void fossil_unicode_free(void *pOld){
9992
#ifdef _WIN32
10093
sqlite3_free(pOld);
10194
#else
102
- /* No-op on unix */
95
+ fossil_free(pOld);
10396
#endif
10497
}
98
+#endif /* _WIN32 */
10599
106100
#if defined(__APPLE__) && !defined(WITHOUT_ICONV)
107101
# include <iconv.h>
108102
#endif
109103
110104
/*
111
-** Translate text from the filename character set into
112
-** to precomposed UTF8. Return a pointer to the translated text.
105
+** Translate text from the filename character set into UTF-8.
106
+** Return a pointer to the translated text.
113107
** Call fossil_filename_free() to deallocate any memory used to store the
114108
** returned pointer when done.
115109
*/
116110
char *fossil_filename_to_utf8(void *zFilename){
117111
#if defined(_WIN32)
118112
int nByte;
119113
char *zUtf;
120
- WCHAR *wUnicode = zFilename;
114
+ wchar_t *wUnicode = zFilename;
121115
while( *wUnicode != 0 ){
122
- if ( (*wUnicode & 0xFF80) == 0xF000 ){
123
- WCHAR converted = (*wUnicode & 0x7F);
116
+ if ( (*wUnicode & 0xff80) == 0xf000 ){
117
+ wchar_t converted = (*wUnicode & 0x7f);
124118
/* Only really convert it when the resulting char is in the given range*/
125119
if ( (converted < 32) || wcschr(L"\"*<>?|:", converted) ){
126120
*wUnicode = converted;
127121
}
128122
}
@@ -168,11 +162,11 @@
168162
return (char *)zFilename; /* No-op on non-mac unix */
169163
#endif
170164
}
171165
172166
/*
173
-** Translate UTF8 to unicode for use in filename translations.
167
+** Translate UTF-8 to unicode for use in filename translations.
174168
** Return a pointer to the translated text.. Call fossil_filename_free()
175169
** to deallocate any memory used to store the returned pointer when done.
176170
**
177171
** On Windows, characters in the range U+0001 to U+0031 and the
178172
** characters '"', '*', ':', '<', '>', '?' and '|' are invalid
@@ -185,12 +179,17 @@
185179
** See: <http://cygwin.com/cygwin-ug-net/using-specialnames.html>
186180
**
187181
*/
188182
void *fossil_utf8_to_filename(const char *zUtf8){
189183
#ifdef _WIN32
190
- WCHAR *zUnicode = fossil_utf8_to_unicode(zUtf8);
191
- WCHAR *wUnicode = zUnicode;
184
+ int nByte = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0);
185
+ wchar_t *zUnicode = sqlite3_malloc( nByte * 2 );
186
+ wchar_t *wUnicode = zUnicode;
187
+ if( zUnicode==0 ){
188
+ return 0;
189
+ }
190
+ MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nByte);
192191
/* If path starts with "<drive>:/" or "<drive>:\", don't translate the ':' */
193192
if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
194193
&& (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
195194
zUnicode[2] = '\\';
196195
wUnicode += 3;
@@ -201,11 +200,10 @@
201200
}else if( *wUnicode == '/' ){
202201
*wUnicode = '\\';
203202
}
204203
++wUnicode;
205204
}
206
-
207205
return zUnicode;
208206
#elif defined(__CYGWIN__)
209207
char *zPath = fossil_strdup(zUtf8);
210208
char *p = zPath;
211209
while( (*p = *zUtf8++) != 0){
@@ -234,11 +232,11 @@
234232
/* No-op on all other unix */
235233
#endif
236234
}
237235
238236
/*
239
-** Display UTF8 on the console. Return the number of
237
+** Display UTF-8 on the console. Return the number of
240238
** Characters written. If stdout or stderr is redirected
241239
** to a file, -1 is returned and nothing is written
242240
** to the console.
243241
*/
244242
int fossil_utf8_to_console(const char *zUtf8, int nByte, int toStdErr){
245243
246244
ADDED src/util.c
--- src/utf8.c
+++ src/utf8.c
@@ -24,38 +24,31 @@
24 #include <sqlite3.h>
25 #ifdef _WIN32
26 # include <windows.h>
27 #endif
28
 
29 /*
30 ** Translate MBCS to UTF8. Return a pointer to the translated text.
31 ** Call fossil_mbcs_free() to deallocate any memory used to store the
32 ** returned pointer when done.
33 */
34 char *fossil_mbcs_to_utf8(const char *zMbcs){
35 #ifdef _WIN32
36 extern char *sqlite3_win32_mbcs_to_utf8(const char*);
37 return sqlite3_win32_mbcs_to_utf8(zMbcs);
38 #else
39 return (char*)zMbcs; /* No-op on unix */
40 #endif
41 }
42
43 /*
44 ** After translating from UTF8 to MBCS, invoke this routine to deallocate
45 ** any memory used to hold the translation
46 */
47 void fossil_mbcs_free(char *zOld){
48 #ifdef _WIN32
49 sqlite3_free(zOld);
50 #else
51 /* No-op on unix */
52 #endif
53 }
54
55 /*
56 ** Translate Unicode text into UTF8.
57 ** Return a pointer to the translated text.
58 ** Call fossil_unicode_free() to deallocate any memory used to store the
59 ** returned pointer when done.
60 */
61 char *fossil_unicode_to_utf8(const void *zUnicode){
@@ -66,16 +59,16 @@
66 return 0;
67 }
68 WideCharToMultiByte(CP_UTF8, 0, zUnicode, -1, zUtf, nByte, 0, 0);
69 return zUtf;
70 #else
71 return (char *)zUnicode; /* No-op on unix */
72 #endif
73 }
74
75 /*
76 ** Translate UTF8 to unicode for use in system calls. Return a pointer to the
77 ** translated text.. Call fossil_unicode_free() to deallocate any memory
78 ** used to store the returned pointer when done.
79 */
80 void *fossil_utf8_to_unicode(const char *zUtf8){
81 #ifdef _WIN32
@@ -85,11 +78,11 @@
85 return 0;
86 }
87 MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nByte);
88 return zUnicode;
89 #else
90 return (void *)zUtf8; /* No-op on unix */
91 #endif
92 }
93
94 /*
95 ** Deallocate any memory that was previously allocated by
@@ -97,32 +90,33 @@
97 */
98 void fossil_unicode_free(void *pOld){
99 #ifdef _WIN32
100 sqlite3_free(pOld);
101 #else
102 /* No-op on unix */
103 #endif
104 }
 
105
106 #if defined(__APPLE__) && !defined(WITHOUT_ICONV)
107 # include <iconv.h>
108 #endif
109
110 /*
111 ** Translate text from the filename character set into
112 ** to precomposed UTF8. Return a pointer to the translated text.
113 ** Call fossil_filename_free() to deallocate any memory used to store the
114 ** returned pointer when done.
115 */
116 char *fossil_filename_to_utf8(void *zFilename){
117 #if defined(_WIN32)
118 int nByte;
119 char *zUtf;
120 WCHAR *wUnicode = zFilename;
121 while( *wUnicode != 0 ){
122 if ( (*wUnicode & 0xFF80) == 0xF000 ){
123 WCHAR converted = (*wUnicode & 0x7F);
124 /* Only really convert it when the resulting char is in the given range*/
125 if ( (converted < 32) || wcschr(L"\"*<>?|:", converted) ){
126 *wUnicode = converted;
127 }
128 }
@@ -168,11 +162,11 @@
168 return (char *)zFilename; /* No-op on non-mac unix */
169 #endif
170 }
171
172 /*
173 ** Translate UTF8 to unicode for use in filename translations.
174 ** Return a pointer to the translated text.. Call fossil_filename_free()
175 ** to deallocate any memory used to store the returned pointer when done.
176 **
177 ** On Windows, characters in the range U+0001 to U+0031 and the
178 ** characters '"', '*', ':', '<', '>', '?' and '|' are invalid
@@ -185,12 +179,17 @@
185 ** See: <http://cygwin.com/cygwin-ug-net/using-specialnames.html>
186 **
187 */
188 void *fossil_utf8_to_filename(const char *zUtf8){
189 #ifdef _WIN32
190 WCHAR *zUnicode = fossil_utf8_to_unicode(zUtf8);
191 WCHAR *wUnicode = zUnicode;
 
 
 
 
 
192 /* If path starts with "<drive>:/" or "<drive>:\", don't translate the ':' */
193 if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
194 && (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
195 zUnicode[2] = '\\';
196 wUnicode += 3;
@@ -201,11 +200,10 @@
201 }else if( *wUnicode == '/' ){
202 *wUnicode = '\\';
203 }
204 ++wUnicode;
205 }
206
207 return zUnicode;
208 #elif defined(__CYGWIN__)
209 char *zPath = fossil_strdup(zUtf8);
210 char *p = zPath;
211 while( (*p = *zUtf8++) != 0){
@@ -234,11 +232,11 @@
234 /* No-op on all other unix */
235 #endif
236 }
237
238 /*
239 ** Display UTF8 on the console. Return the number of
240 ** Characters written. If stdout or stderr is redirected
241 ** to a file, -1 is returned and nothing is written
242 ** to the console.
243 */
244 int fossil_utf8_to_console(const char *zUtf8, int nByte, int toStdErr){
245
246 DDED src/util.c
--- src/utf8.c
+++ src/utf8.c
@@ -24,38 +24,31 @@
24 #include <sqlite3.h>
25 #ifdef _WIN32
26 # include <windows.h>
27 #endif
28
29 #ifdef _WIN32
30 /*
31 ** Translate MBCS to UTF-8. Return a pointer to the translated text.
32 ** Call fossil_mbcs_free() to deallocate any memory used to store the
33 ** returned pointer when done.
34 */
35 char *fossil_mbcs_to_utf8(const char *zMbcs){
 
36 extern char *sqlite3_win32_mbcs_to_utf8(const char*);
37 return sqlite3_win32_mbcs_to_utf8(zMbcs);
 
 
 
38 }
39
40 /*
41 ** After translating from UTF-8 to MBCS, invoke this routine to deallocate
42 ** any memory used to hold the translation
43 */
44 void fossil_mbcs_free(char *zOld){
 
45 sqlite3_free(zOld);
 
 
 
46 }
47
48 /*
49 ** Translate Unicode text into UTF-8.
50 ** Return a pointer to the translated text.
51 ** Call fossil_unicode_free() to deallocate any memory used to store the
52 ** returned pointer when done.
53 */
54 char *fossil_unicode_to_utf8(const void *zUnicode){
@@ -66,16 +59,16 @@
59 return 0;
60 }
61 WideCharToMultiByte(CP_UTF8, 0, zUnicode, -1, zUtf, nByte, 0, 0);
62 return zUtf;
63 #else
64 return fossil_strdup(zUtf8); /* TODO: implement for unix */
65 #endif
66 }
67
68 /*
69 ** Translate UTF-8 to unicode for use in system calls. Return a pointer to the
70 ** translated text.. Call fossil_unicode_free() to deallocate any memory
71 ** used to store the returned pointer when done.
72 */
73 void *fossil_utf8_to_unicode(const char *zUtf8){
74 #ifdef _WIN32
@@ -85,11 +78,11 @@
78 return 0;
79 }
80 MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nByte);
81 return zUnicode;
82 #else
83 return fossil_strdup(zUtf8); /* TODO: implement for unix */
84 #endif
85 }
86
87 /*
88 ** Deallocate any memory that was previously allocated by
@@ -97,32 +90,33 @@
90 */
91 void fossil_unicode_free(void *pOld){
92 #ifdef _WIN32
93 sqlite3_free(pOld);
94 #else
95 fossil_free(pOld);
96 #endif
97 }
98 #endif /* _WIN32 */
99
100 #if defined(__APPLE__) && !defined(WITHOUT_ICONV)
101 # include <iconv.h>
102 #endif
103
104 /*
105 ** Translate text from the filename character set into UTF-8.
106 ** Return a pointer to the translated text.
107 ** Call fossil_filename_free() to deallocate any memory used to store the
108 ** returned pointer when done.
109 */
110 char *fossil_filename_to_utf8(void *zFilename){
111 #if defined(_WIN32)
112 int nByte;
113 char *zUtf;
114 wchar_t *wUnicode = zFilename;
115 while( *wUnicode != 0 ){
116 if ( (*wUnicode & 0xff80) == 0xf000 ){
117 wchar_t converted = (*wUnicode & 0x7f);
118 /* Only really convert it when the resulting char is in the given range*/
119 if ( (converted < 32) || wcschr(L"\"*<>?|:", converted) ){
120 *wUnicode = converted;
121 }
122 }
@@ -168,11 +162,11 @@
162 return (char *)zFilename; /* No-op on non-mac unix */
163 #endif
164 }
165
166 /*
167 ** Translate UTF-8 to unicode for use in filename translations.
168 ** Return a pointer to the translated text.. Call fossil_filename_free()
169 ** to deallocate any memory used to store the returned pointer when done.
170 **
171 ** On Windows, characters in the range U+0001 to U+0031 and the
172 ** characters '"', '*', ':', '<', '>', '?' and '|' are invalid
@@ -185,12 +179,17 @@
179 ** See: <http://cygwin.com/cygwin-ug-net/using-specialnames.html>
180 **
181 */
182 void *fossil_utf8_to_filename(const char *zUtf8){
183 #ifdef _WIN32
184 int nByte = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0);
185 wchar_t *zUnicode = sqlite3_malloc( nByte * 2 );
186 wchar_t *wUnicode = zUnicode;
187 if( zUnicode==0 ){
188 return 0;
189 }
190 MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nByte);
191 /* If path starts with "<drive>:/" or "<drive>:\", don't translate the ':' */
192 if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
193 && (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
194 zUnicode[2] = '\\';
195 wUnicode += 3;
@@ -201,11 +200,10 @@
200 }else if( *wUnicode == '/' ){
201 *wUnicode = '\\';
202 }
203 ++wUnicode;
204 }
 
205 return zUnicode;
206 #elif defined(__CYGWIN__)
207 char *zPath = fossil_strdup(zUtf8);
208 char *p = zPath;
209 while( (*p = *zUtf8++) != 0){
@@ -234,11 +232,11 @@
232 /* No-op on all other unix */
233 #endif
234 }
235
236 /*
237 ** Display UTF-8 on the console. Return the number of
238 ** Characters written. If stdout or stderr is redirected
239 ** to a file, -1 is returned and nothing is written
240 ** to the console.
241 */
242 int fossil_utf8_to_console(const char *zUtf8, int nByte, int toStdErr){
243
244 DDED src/util.c

No diff available

+12 -5
--- src/winhttp.c
+++ src/winhttp.c
@@ -139,19 +139,20 @@
139139
int mnPort, int mxPort, /* Range of allowed TCP port numbers */
140140
const char *zBrowser, /* Command to launch browser. (Or NULL) */
141141
const char *zStopper, /* Stop server when this file is exists (Or NULL) */
142142
const char *zNotFound, /* The --notfound option, or NULL */
143143
const char *zFileGlob, /* The --fileglob option, or NULL */
144
+ const char *zIpAddr, /* Bind to this IP address, if not NULL */
144145
int flags /* One or more HTTP_SERVER_ flags */
145146
){
146147
WSADATA wd;
147148
SOCKET s = INVALID_SOCKET;
148149
SOCKADDR_IN addr;
149150
int idCnt = 0;
150151
int iPort = mnPort;
151152
Blob options;
152
- WCHAR zTmpPath[MAX_PATH];
153
+ wchar_t zTmpPath[MAX_PATH];
153154
154155
if( zStopper ) file_delete(zStopper);
155156
blob_zero(&options);
156157
if( zNotFound ){
157158
blob_appendf(&options, " --notfound %s", zNotFound);
@@ -170,11 +171,16 @@
170171
if( s==INVALID_SOCKET ){
171172
fossil_fatal("unable to create a socket");
172173
}
173174
addr.sin_family = AF_INET;
174175
addr.sin_port = htons(iPort);
175
- if( flags & HTTP_SERVER_LOCALHOST ){
176
+ if( zIpAddr ){
177
+ addr.sin_addr.s_addr = inet_addr(zIpAddr);
178
+ if( addr.sin_addr.s_addr == (-1) ){
179
+ fossil_fatal("not a valid IP address: %s", zIpAddr);
180
+ }
181
+ }else if( flags & HTTP_SERVER_LOCALHOST ){
176182
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
177183
}else{
178184
addr.sin_addr.s_addr = htonl(INADDR_ANY);
179185
}
180186
if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){
@@ -198,11 +204,12 @@
198204
}
199205
}
200206
if( !GetTempPathW(MAX_PATH, zTmpPath) ){
201207
fossil_fatal("unable to get path to the temporary directory.");
202208
}
203
- zTempPrefix = mprintf("%sfossil_server_P%d_", fossil_unicode_to_utf8(zTmpPath), iPort);
209
+ zTempPrefix = mprintf("%sfossil_server_P%d_",
210
+ fossil_unicode_to_utf8(zTmpPath), iPort);
204211
fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
205212
if( zBrowser ){
206213
zBrowser = mprintf(zBrowser, iPort);
207214
fossil_print("Launch webbrowser: %s\n", zBrowser);
208215
fossil_system(zBrowser);
@@ -254,11 +261,11 @@
254261
int port; /* Port on which the http server should run */
255262
const char *zNotFound; /* The --notfound option, or NULL */
256263
const char *zFileGlob; /* The --files option, or NULL */
257264
int flags; /* One or more HTTP_SERVER_ flags */
258265
int isRunningAsService; /* Are we running as a service ? */
259
- const WCHAR *zServiceName;/* Name of the service */
266
+ const wchar_t *zServiceName;/* Name of the service */
260267
SOCKET s; /* Socket on which the http server listens */
261268
};
262269
263270
/*
264271
** Variables used for running as windows service.
@@ -402,11 +409,11 @@
402409
ssStatus.dwServiceSpecificExitCode = 0;
403410
win32_report_service_status(SERVICE_START_PENDING, NO_ERROR, 3000);
404411
405412
/* Execute the http server */
406413
win32_http_server(hsData.port, hsData.port,
407
- NULL, NULL, hsData.zNotFound, hsData.zFileGlob,
414
+ NULL, NULL, hsData.zNotFound, hsData.zFileGlob, 0,
408415
hsData.flags);
409416
410417
/* Service has stopped now. */
411418
win32_report_service_status(SERVICE_STOPPED, NO_ERROR, 0);
412419
return;
413420
--- src/winhttp.c
+++ src/winhttp.c
@@ -139,19 +139,20 @@
139 int mnPort, int mxPort, /* Range of allowed TCP port numbers */
140 const char *zBrowser, /* Command to launch browser. (Or NULL) */
141 const char *zStopper, /* Stop server when this file is exists (Or NULL) */
142 const char *zNotFound, /* The --notfound option, or NULL */
143 const char *zFileGlob, /* The --fileglob option, or NULL */
 
144 int flags /* One or more HTTP_SERVER_ flags */
145 ){
146 WSADATA wd;
147 SOCKET s = INVALID_SOCKET;
148 SOCKADDR_IN addr;
149 int idCnt = 0;
150 int iPort = mnPort;
151 Blob options;
152 WCHAR zTmpPath[MAX_PATH];
153
154 if( zStopper ) file_delete(zStopper);
155 blob_zero(&options);
156 if( zNotFound ){
157 blob_appendf(&options, " --notfound %s", zNotFound);
@@ -170,11 +171,16 @@
170 if( s==INVALID_SOCKET ){
171 fossil_fatal("unable to create a socket");
172 }
173 addr.sin_family = AF_INET;
174 addr.sin_port = htons(iPort);
175 if( flags & HTTP_SERVER_LOCALHOST ){
 
 
 
 
 
176 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
177 }else{
178 addr.sin_addr.s_addr = htonl(INADDR_ANY);
179 }
180 if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){
@@ -198,11 +204,12 @@
198 }
199 }
200 if( !GetTempPathW(MAX_PATH, zTmpPath) ){
201 fossil_fatal("unable to get path to the temporary directory.");
202 }
203 zTempPrefix = mprintf("%sfossil_server_P%d_", fossil_unicode_to_utf8(zTmpPath), iPort);
 
204 fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
205 if( zBrowser ){
206 zBrowser = mprintf(zBrowser, iPort);
207 fossil_print("Launch webbrowser: %s\n", zBrowser);
208 fossil_system(zBrowser);
@@ -254,11 +261,11 @@
254 int port; /* Port on which the http server should run */
255 const char *zNotFound; /* The --notfound option, or NULL */
256 const char *zFileGlob; /* The --files option, or NULL */
257 int flags; /* One or more HTTP_SERVER_ flags */
258 int isRunningAsService; /* Are we running as a service ? */
259 const WCHAR *zServiceName;/* Name of the service */
260 SOCKET s; /* Socket on which the http server listens */
261 };
262
263 /*
264 ** Variables used for running as windows service.
@@ -402,11 +409,11 @@
402 ssStatus.dwServiceSpecificExitCode = 0;
403 win32_report_service_status(SERVICE_START_PENDING, NO_ERROR, 3000);
404
405 /* Execute the http server */
406 win32_http_server(hsData.port, hsData.port,
407 NULL, NULL, hsData.zNotFound, hsData.zFileGlob,
408 hsData.flags);
409
410 /* Service has stopped now. */
411 win32_report_service_status(SERVICE_STOPPED, NO_ERROR, 0);
412 return;
413
--- src/winhttp.c
+++ src/winhttp.c
@@ -139,19 +139,20 @@
139 int mnPort, int mxPort, /* Range of allowed TCP port numbers */
140 const char *zBrowser, /* Command to launch browser. (Or NULL) */
141 const char *zStopper, /* Stop server when this file is exists (Or NULL) */
142 const char *zNotFound, /* The --notfound option, or NULL */
143 const char *zFileGlob, /* The --fileglob option, or NULL */
144 const char *zIpAddr, /* Bind to this IP address, if not NULL */
145 int flags /* One or more HTTP_SERVER_ flags */
146 ){
147 WSADATA wd;
148 SOCKET s = INVALID_SOCKET;
149 SOCKADDR_IN addr;
150 int idCnt = 0;
151 int iPort = mnPort;
152 Blob options;
153 wchar_t zTmpPath[MAX_PATH];
154
155 if( zStopper ) file_delete(zStopper);
156 blob_zero(&options);
157 if( zNotFound ){
158 blob_appendf(&options, " --notfound %s", zNotFound);
@@ -170,11 +171,16 @@
171 if( s==INVALID_SOCKET ){
172 fossil_fatal("unable to create a socket");
173 }
174 addr.sin_family = AF_INET;
175 addr.sin_port = htons(iPort);
176 if( zIpAddr ){
177 addr.sin_addr.s_addr = inet_addr(zIpAddr);
178 if( addr.sin_addr.s_addr == (-1) ){
179 fossil_fatal("not a valid IP address: %s", zIpAddr);
180 }
181 }else if( flags & HTTP_SERVER_LOCALHOST ){
182 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
183 }else{
184 addr.sin_addr.s_addr = htonl(INADDR_ANY);
185 }
186 if( bind(s, (struct sockaddr*)&addr, sizeof(addr))==SOCKET_ERROR ){
@@ -198,11 +204,12 @@
204 }
205 }
206 if( !GetTempPathW(MAX_PATH, zTmpPath) ){
207 fossil_fatal("unable to get path to the temporary directory.");
208 }
209 zTempPrefix = mprintf("%sfossil_server_P%d_",
210 fossil_unicode_to_utf8(zTmpPath), iPort);
211 fossil_print("Listening for HTTP requests on TCP port %d\n", iPort);
212 if( zBrowser ){
213 zBrowser = mprintf(zBrowser, iPort);
214 fossil_print("Launch webbrowser: %s\n", zBrowser);
215 fossil_system(zBrowser);
@@ -254,11 +261,11 @@
261 int port; /* Port on which the http server should run */
262 const char *zNotFound; /* The --notfound option, or NULL */
263 const char *zFileGlob; /* The --files option, or NULL */
264 int flags; /* One or more HTTP_SERVER_ flags */
265 int isRunningAsService; /* Are we running as a service ? */
266 const wchar_t *zServiceName;/* Name of the service */
267 SOCKET s; /* Socket on which the http server listens */
268 };
269
270 /*
271 ** Variables used for running as windows service.
@@ -402,11 +409,11 @@
409 ssStatus.dwServiceSpecificExitCode = 0;
410 win32_report_service_status(SERVICE_START_PENDING, NO_ERROR, 3000);
411
412 /* Execute the http server */
413 win32_http_server(hsData.port, hsData.port,
414 NULL, NULL, hsData.zNotFound, hsData.zFileGlob, 0,
415 hsData.flags);
416
417 /* Service has stopped now. */
418 win32_report_service_status(SERVICE_STOPPED, NO_ERROR, 0);
419 return;
420
+12 -7
--- src/xfer.c
+++ src/xfer.c
@@ -1708,12 +1708,14 @@
17081708
defossilize(zMsg);
17091709
if( (syncFlags & SYNC_PUSH) && zMsg && strglob("pull only *", zMsg) ){
17101710
syncFlags &= ~SYNC_PUSH;
17111711
zMsg = 0;
17121712
}
1713
- fossil_force_newline();
1714
- fossil_print("Server says: %s\n", zMsg);
1713
+ if( zMsg && zMsg[0] ){
1714
+ fossil_force_newline();
1715
+ fossil_print("Server says: %s\n", zMsg);
1716
+ }
17151717
}else
17161718
17171719
/* pragma NAME VALUE...
17181720
**
17191721
** The server can send pragmas to try to convey meta-information to
@@ -1736,20 +1738,22 @@
17361738
*/
17371739
if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){
17381740
if( (syncFlags & SYNC_CLONE)==0 || nCycle>0 ){
17391741
char *zMsg = blob_terminate(&xfer.aToken[1]);
17401742
defossilize(zMsg);
1743
+ fossil_force_newline();
1744
+ fossil_print("Error: %s\n", zMsg);
17411745
if( fossil_strcmp(zMsg, "login failed")==0 ){
17421746
if( nCycle<2 ){
1743
- if( !g.dontKeepUrl ) db_unset("last-sync-pw", 0);
1747
+ g.urlPasswd = 0;
17441748
go = 1;
1749
+ if( g.cgiOutput==0 ) url_prompt_for_password();
17451750
}
17461751
}else{
1747
- blob_appendf(&xfer.err, "\rserver says: %s", zMsg);
1752
+ blob_appendf(&xfer.err, "server says: %s\n", zMsg);
1753
+ nErr++;
17481754
}
1749
- fossil_warning("\rError: %s", zMsg);
1750
- nErr++;
17511755
break;
17521756
}
17531757
}else
17541758
17551759
/* Unknown message */
@@ -1760,14 +1764,15 @@
17601764
&recv
17611765
);
17621766
nErr++;
17631767
break;
17641768
}
1765
- blob_appendf(&xfer.err, "unknown command: [%b]", &xfer.aToken[0]);
1769
+ blob_appendf(&xfer.err, "unknown command: [%b]\n", &xfer.aToken[0]);
17661770
}
17671771
17681772
if( blob_size(&xfer.err) ){
1773
+ fossil_force_newline();
17691774
fossil_warning("%b", &xfer.err);
17701775
nErr++;
17711776
break;
17721777
}
17731778
blobarray_reset(xfer.aToken, xfer.nToken);
17741779
--- src/xfer.c
+++ src/xfer.c
@@ -1708,12 +1708,14 @@
1708 defossilize(zMsg);
1709 if( (syncFlags & SYNC_PUSH) && zMsg && strglob("pull only *", zMsg) ){
1710 syncFlags &= ~SYNC_PUSH;
1711 zMsg = 0;
1712 }
1713 fossil_force_newline();
1714 fossil_print("Server says: %s\n", zMsg);
 
 
1715 }else
1716
1717 /* pragma NAME VALUE...
1718 **
1719 ** The server can send pragmas to try to convey meta-information to
@@ -1736,20 +1738,22 @@
1736 */
1737 if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){
1738 if( (syncFlags & SYNC_CLONE)==0 || nCycle>0 ){
1739 char *zMsg = blob_terminate(&xfer.aToken[1]);
1740 defossilize(zMsg);
 
 
1741 if( fossil_strcmp(zMsg, "login failed")==0 ){
1742 if( nCycle<2 ){
1743 if( !g.dontKeepUrl ) db_unset("last-sync-pw", 0);
1744 go = 1;
 
1745 }
1746 }else{
1747 blob_appendf(&xfer.err, "\rserver says: %s", zMsg);
 
1748 }
1749 fossil_warning("\rError: %s", zMsg);
1750 nErr++;
1751 break;
1752 }
1753 }else
1754
1755 /* Unknown message */
@@ -1760,14 +1764,15 @@
1760 &recv
1761 );
1762 nErr++;
1763 break;
1764 }
1765 blob_appendf(&xfer.err, "unknown command: [%b]", &xfer.aToken[0]);
1766 }
1767
1768 if( blob_size(&xfer.err) ){
 
1769 fossil_warning("%b", &xfer.err);
1770 nErr++;
1771 break;
1772 }
1773 blobarray_reset(xfer.aToken, xfer.nToken);
1774
--- src/xfer.c
+++ src/xfer.c
@@ -1708,12 +1708,14 @@
1708 defossilize(zMsg);
1709 if( (syncFlags & SYNC_PUSH) && zMsg && strglob("pull only *", zMsg) ){
1710 syncFlags &= ~SYNC_PUSH;
1711 zMsg = 0;
1712 }
1713 if( zMsg && zMsg[0] ){
1714 fossil_force_newline();
1715 fossil_print("Server says: %s\n", zMsg);
1716 }
1717 }else
1718
1719 /* pragma NAME VALUE...
1720 **
1721 ** The server can send pragmas to try to convey meta-information to
@@ -1736,20 +1738,22 @@
1738 */
1739 if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){
1740 if( (syncFlags & SYNC_CLONE)==0 || nCycle>0 ){
1741 char *zMsg = blob_terminate(&xfer.aToken[1]);
1742 defossilize(zMsg);
1743 fossil_force_newline();
1744 fossil_print("Error: %s\n", zMsg);
1745 if( fossil_strcmp(zMsg, "login failed")==0 ){
1746 if( nCycle<2 ){
1747 g.urlPasswd = 0;
1748 go = 1;
1749 if( g.cgiOutput==0 ) url_prompt_for_password();
1750 }
1751 }else{
1752 blob_appendf(&xfer.err, "server says: %s\n", zMsg);
1753 nErr++;
1754 }
 
 
1755 break;
1756 }
1757 }else
1758
1759 /* Unknown message */
@@ -1760,14 +1764,15 @@
1764 &recv
1765 );
1766 nErr++;
1767 break;
1768 }
1769 blob_appendf(&xfer.err, "unknown command: [%b]\n", &xfer.aToken[0]);
1770 }
1771
1772 if( blob_size(&xfer.err) ){
1773 fossil_force_newline();
1774 fossil_warning("%b", &xfer.err);
1775 nErr++;
1776 break;
1777 }
1778 blobarray_reset(xfer.aToken, xfer.nToken);
1779
+17 -4
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -26,13 +26,13 @@
2626
TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
2727
LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
2828
2929
SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0
3030
31
-SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
31
+SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
3232
33
-OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
33
+OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
3434
3535
3636
RC=$(DMDIR)\bin\rcc
3737
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
3838
@@ -46,11 +46,11 @@
4646
4747
$(OBJDIR)\fossil.res: $B\win\fossil.rc
4848
$(RC) $(RCFLAGS) -o$@ $**
4949
5050
$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
51
- +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_tag json_timeline json_user json_wiki leaf login main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 verify vfile wiki wikiformat winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
51
+ +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf login main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
5252
+echo fossil >> $@
5353
+echo fossil >> $@
5454
+echo $(LIBS) >> $@
5555
+echo. >> $@
5656
+echo fossil >> $@
@@ -103,10 +103,11 @@
103103
$(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
104104
$(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
105105
$(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
106106
$(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
107107
$(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
108
+$(OBJDIR)\json_status$O : $(SRCDIR)\json_detail.h
108109
$(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
109110
$(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
110111
$(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
111112
$(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h
112113
@@ -397,10 +398,16 @@
397398
$(OBJDIR)\json_report$O : json_report_.c json_report.h
398399
$(TCC) -o$@ -c json_report_.c
399400
400401
json_report_.c : $(SRCDIR)\json_report.c
401402
+translate$E $** > $@
403
+
404
+$(OBJDIR)\json_status$O : json_status_.c json_status.h
405
+ $(TCC) -o$@ -c json_status_.c
406
+
407
+json_status_.c : $(SRCDIR)\json_status.c
408
+ +translate$E $** > $@
402409
403410
$(OBJDIR)\json_tag$O : json_tag_.c json_tag.h
404411
$(TCC) -o$@ -c json_tag_.c
405412
406413
json_tag_.c : $(SRCDIR)\json_tag.c
@@ -679,10 +686,16 @@
679686
$(OBJDIR)\utf8$O : utf8_.c utf8.h
680687
$(TCC) -o$@ -c utf8_.c
681688
682689
utf8_.c : $(SRCDIR)\utf8.c
683690
+translate$E $** > $@
691
+
692
+$(OBJDIR)\util$O : util_.c util.h
693
+ $(TCC) -o$@ -c util_.c
694
+
695
+util_.c : $(SRCDIR)\util.c
696
+ +translate$E $** > $@
684697
685698
$(OBJDIR)\verify$O : verify_.c verify.h
686699
$(TCC) -o$@ -c verify_.c
687700
688701
verify_.c : $(SRCDIR)\verify.c
@@ -735,7 +748,7 @@
735748
736749
zip_.c : $(SRCDIR)\zip.c
737750
+translate$E $** > $@
738751
739752
headers: makeheaders$E page_index.h VERSION.h
740
- +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
753
+ +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
741754
@copy /Y nul: headers
742755
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -26,13 +26,13 @@
26 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
27 LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
28
29 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0
30
31 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
32
33 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
34
35
36 RC=$(DMDIR)\bin\rcc
37 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
38
@@ -46,11 +46,11 @@
46
47 $(OBJDIR)\fossil.res: $B\win\fossil.rc
48 $(RC) $(RCFLAGS) -o$@ $**
49
50 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
51 +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_tag json_timeline json_user json_wiki leaf login main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 verify vfile wiki wikiformat winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
52 +echo fossil >> $@
53 +echo fossil >> $@
54 +echo $(LIBS) >> $@
55 +echo. >> $@
56 +echo fossil >> $@
@@ -103,10 +103,11 @@
103 $(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
104 $(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
105 $(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
106 $(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
107 $(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
 
108 $(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
109 $(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
110 $(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
111 $(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h
112
@@ -397,10 +398,16 @@
397 $(OBJDIR)\json_report$O : json_report_.c json_report.h
398 $(TCC) -o$@ -c json_report_.c
399
400 json_report_.c : $(SRCDIR)\json_report.c
401 +translate$E $** > $@
 
 
 
 
 
 
402
403 $(OBJDIR)\json_tag$O : json_tag_.c json_tag.h
404 $(TCC) -o$@ -c json_tag_.c
405
406 json_tag_.c : $(SRCDIR)\json_tag.c
@@ -679,10 +686,16 @@
679 $(OBJDIR)\utf8$O : utf8_.c utf8.h
680 $(TCC) -o$@ -c utf8_.c
681
682 utf8_.c : $(SRCDIR)\utf8.c
683 +translate$E $** > $@
 
 
 
 
 
 
684
685 $(OBJDIR)\verify$O : verify_.c verify.h
686 $(TCC) -o$@ -c verify_.c
687
688 verify_.c : $(SRCDIR)\verify.c
@@ -735,7 +748,7 @@
735
736 zip_.c : $(SRCDIR)\zip.c
737 +translate$E $** > $@
738
739 headers: makeheaders$E page_index.h VERSION.h
740 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
741 @copy /Y nul: headers
742
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -26,13 +26,13 @@
26 TCC = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(SSL) $(INCL)
27 LIBS = $(DMDIR)\extra\lib\ zlib wsock32 advapi32
28
29 SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0
30
31 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c login_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
32
33 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
34
35
36 RC=$(DMDIR)\bin\rcc
37 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
38
@@ -46,11 +46,11 @@
46
47 $(OBJDIR)\fossil.res: $B\win\fossil.rc
48 $(RC) $(RCFLAGS) -o$@ $**
49
50 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
51 +echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf login main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf rebuild regexp report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
52 +echo fossil >> $@
53 +echo fossil >> $@
54 +echo $(LIBS) >> $@
55 +echo. >> $@
56 +echo fossil >> $@
@@ -103,10 +103,11 @@
103 $(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
104 $(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
105 $(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
106 $(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
107 $(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
108 $(OBJDIR)\json_status$O : $(SRCDIR)\json_detail.h
109 $(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
110 $(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
111 $(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
112 $(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h
113
@@ -397,10 +398,16 @@
398 $(OBJDIR)\json_report$O : json_report_.c json_report.h
399 $(TCC) -o$@ -c json_report_.c
400
401 json_report_.c : $(SRCDIR)\json_report.c
402 +translate$E $** > $@
403
404 $(OBJDIR)\json_status$O : json_status_.c json_status.h
405 $(TCC) -o$@ -c json_status_.c
406
407 json_status_.c : $(SRCDIR)\json_status.c
408 +translate$E $** > $@
409
410 $(OBJDIR)\json_tag$O : json_tag_.c json_tag.h
411 $(TCC) -o$@ -c json_tag_.c
412
413 json_tag_.c : $(SRCDIR)\json_tag.c
@@ -679,10 +686,16 @@
686 $(OBJDIR)\utf8$O : utf8_.c utf8.h
687 $(TCC) -o$@ -c utf8_.c
688
689 utf8_.c : $(SRCDIR)\utf8.c
690 +translate$E $** > $@
691
692 $(OBJDIR)\util$O : util_.c util.h
693 $(TCC) -o$@ -c util_.c
694
695 util_.c : $(SRCDIR)\util.c
696 +translate$E $** > $@
697
698 $(OBJDIR)\verify$O : verify_.c verify.h
699 $(TCC) -o$@ -c verify_.c
700
701 verify_.c : $(SRCDIR)\verify.c
@@ -735,7 +748,7 @@
748
749 zip_.c : $(SRCDIR)\zip.c
750 +translate$E $** > $@
751
752 headers: makeheaders$E page_index.h VERSION.h
753 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
754 @copy /Y nul: headers
755
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -84,12 +84,12 @@
8484
#### The directories where the OpenSSL include and library files are located.
8585
# The recommended usage here is to use the Sysinternals junction tool
8686
# to create a hard link between an "openssl-1.x" sub-directory of the
8787
# Fossil source code directory and the target OpenSSL source directory.
8888
#
89
-OPENSSLINCDIR = $(SRCDIR)/../openssl-1.0.1c/include
90
-OPENSSLLIBDIR = $(SRCDIR)/../openssl-1.0.1c
89
+OPENSSLINCDIR = $(SRCDIR)/../openssl-1.0.1e/include
90
+OPENSSLLIBDIR = $(SRCDIR)/../openssl-1.0.1e
9191
9292
#### Either the directory where the Tcl library is installed or the Tcl
9393
# source code directory resides (depending on the value of the macro
9494
# FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
9595
# this directory must have "include" and "lib" sub-directories. If
@@ -301,10 +301,11 @@
301301
$(SRCDIR)/json_dir.c \
302302
$(SRCDIR)/json_finfo.c \
303303
$(SRCDIR)/json_login.c \
304304
$(SRCDIR)/json_query.c \
305305
$(SRCDIR)/json_report.c \
306
+ $(SRCDIR)/json_status.c \
306307
$(SRCDIR)/json_tag.c \
307308
$(SRCDIR)/json_timeline.c \
308309
$(SRCDIR)/json_user.c \
309310
$(SRCDIR)/json_wiki.c \
310311
$(SRCDIR)/leaf.c \
@@ -348,10 +349,11 @@
348349
$(SRCDIR)/unicode.c \
349350
$(SRCDIR)/update.c \
350351
$(SRCDIR)/url.c \
351352
$(SRCDIR)/user.c \
352353
$(SRCDIR)/utf8.c \
354
+ $(SRCDIR)/util.c \
353355
$(SRCDIR)/verify.c \
354356
$(SRCDIR)/vfile.c \
355357
$(SRCDIR)/wiki.c \
356358
$(SRCDIR)/wikiformat.c \
357359
$(SRCDIR)/winhttp.c \
@@ -407,10 +409,11 @@
407409
$(OBJDIR)/json_dir_.c \
408410
$(OBJDIR)/json_finfo_.c \
409411
$(OBJDIR)/json_login_.c \
410412
$(OBJDIR)/json_query_.c \
411413
$(OBJDIR)/json_report_.c \
414
+ $(OBJDIR)/json_status_.c \
412415
$(OBJDIR)/json_tag_.c \
413416
$(OBJDIR)/json_timeline_.c \
414417
$(OBJDIR)/json_user_.c \
415418
$(OBJDIR)/json_wiki_.c \
416419
$(OBJDIR)/leaf_.c \
@@ -454,10 +457,11 @@
454457
$(OBJDIR)/unicode_.c \
455458
$(OBJDIR)/update_.c \
456459
$(OBJDIR)/url_.c \
457460
$(OBJDIR)/user_.c \
458461
$(OBJDIR)/utf8_.c \
462
+ $(OBJDIR)/util_.c \
459463
$(OBJDIR)/verify_.c \
460464
$(OBJDIR)/vfile_.c \
461465
$(OBJDIR)/wiki_.c \
462466
$(OBJDIR)/wikiformat_.c \
463467
$(OBJDIR)/winhttp_.c \
@@ -513,10 +517,11 @@
513517
$(OBJDIR)/json_dir.o \
514518
$(OBJDIR)/json_finfo.o \
515519
$(OBJDIR)/json_login.o \
516520
$(OBJDIR)/json_query.o \
517521
$(OBJDIR)/json_report.o \
522
+ $(OBJDIR)/json_status.o \
518523
$(OBJDIR)/json_tag.o \
519524
$(OBJDIR)/json_timeline.o \
520525
$(OBJDIR)/json_user.o \
521526
$(OBJDIR)/json_wiki.o \
522527
$(OBJDIR)/leaf.o \
@@ -560,10 +565,11 @@
560565
$(OBJDIR)/unicode.o \
561566
$(OBJDIR)/update.o \
562567
$(OBJDIR)/url.o \
563568
$(OBJDIR)/user.o \
564569
$(OBJDIR)/utf8.o \
570
+ $(OBJDIR)/util.o \
565571
$(OBJDIR)/verify.o \
566572
$(OBJDIR)/vfile.o \
567573
$(OBJDIR)/wiki.o \
568574
$(OBJDIR)/wikiformat.o \
569575
$(OBJDIR)/winhttp.o \
@@ -732,10 +738,11 @@
732738
$(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h \
733739
$(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h \
734740
$(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h \
735741
$(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h \
736742
$(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h \
743
+ $(OBJDIR)/json_status_.c:$(OBJDIR)/json_status.h \
737744
$(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h \
738745
$(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h \
739746
$(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h \
740747
$(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h \
741748
$(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h \
@@ -779,10 +786,11 @@
779786
$(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h \
780787
$(OBJDIR)/update_.c:$(OBJDIR)/update.h \
781788
$(OBJDIR)/url_.c:$(OBJDIR)/url.h \
782789
$(OBJDIR)/user_.c:$(OBJDIR)/user.h \
783790
$(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \
791
+ $(OBJDIR)/util_.c:$(OBJDIR)/util.h \
784792
$(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \
785793
$(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h \
786794
$(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h \
787795
$(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h \
788796
$(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h \
@@ -1180,10 +1188,18 @@
11801188
11811189
$(OBJDIR)/json_report.o: $(OBJDIR)/json_report_.c $(OBJDIR)/json_report.h $(SRCDIR)/config.h
11821190
$(XTCC) -o $(OBJDIR)/json_report.o -c $(OBJDIR)/json_report_.c
11831191
11841192
$(OBJDIR)/json_report.h: $(OBJDIR)/headers
1193
+
1194
+$(OBJDIR)/json_status_.c: $(SRCDIR)/json_status.c $(OBJDIR)/translate
1195
+ $(TRANSLATE) $(SRCDIR)/json_status.c >$(OBJDIR)/json_status_.c
1196
+
1197
+$(OBJDIR)/json_status.o: $(OBJDIR)/json_status_.c $(OBJDIR)/json_status.h $(SRCDIR)/config.h
1198
+ $(XTCC) -o $(OBJDIR)/json_status.o -c $(OBJDIR)/json_status_.c
1199
+
1200
+$(OBJDIR)/json_status.h: $(OBJDIR)/headers
11851201
11861202
$(OBJDIR)/json_tag_.c: $(SRCDIR)/json_tag.c $(OBJDIR)/translate
11871203
$(TRANSLATE) $(SRCDIR)/json_tag.c >$(OBJDIR)/json_tag_.c
11881204
11891205
$(OBJDIR)/json_tag.o: $(OBJDIR)/json_tag_.c $(OBJDIR)/json_tag.h $(SRCDIR)/config.h
@@ -1556,10 +1572,18 @@
15561572
15571573
$(OBJDIR)/utf8.o: $(OBJDIR)/utf8_.c $(OBJDIR)/utf8.h $(SRCDIR)/config.h
15581574
$(XTCC) -o $(OBJDIR)/utf8.o -c $(OBJDIR)/utf8_.c
15591575
15601576
$(OBJDIR)/utf8.h: $(OBJDIR)/headers
1577
+
1578
+$(OBJDIR)/util_.c: $(SRCDIR)/util.c $(OBJDIR)/translate
1579
+ $(TRANSLATE) $(SRCDIR)/util.c >$(OBJDIR)/util_.c
1580
+
1581
+$(OBJDIR)/util.o: $(OBJDIR)/util_.c $(OBJDIR)/util.h $(SRCDIR)/config.h
1582
+ $(XTCC) -o $(OBJDIR)/util.o -c $(OBJDIR)/util_.c
1583
+
1584
+$(OBJDIR)/util.h: $(OBJDIR)/headers
15611585
15621586
$(OBJDIR)/verify_.c: $(SRCDIR)/verify.c $(OBJDIR)/translate
15631587
$(TRANSLATE) $(SRCDIR)/verify.c >$(OBJDIR)/verify_.c
15641588
15651589
$(OBJDIR)/verify.o: $(OBJDIR)/verify_.c $(OBJDIR)/verify.h $(SRCDIR)/config.h
@@ -1635,11 +1659,11 @@
16351659
$(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
16361660
16371661
$(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
16381662
$(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o
16391663
1640
-$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
1664
+$(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
16411665
16421666
$(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
16431667
$(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
16441668
16451669
$(OBJDIR)/th.o: $(SRCDIR)/th.c
16461670
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -84,12 +84,12 @@
84 #### The directories where the OpenSSL include and library files are located.
85 # The recommended usage here is to use the Sysinternals junction tool
86 # to create a hard link between an "openssl-1.x" sub-directory of the
87 # Fossil source code directory and the target OpenSSL source directory.
88 #
89 OPENSSLINCDIR = $(SRCDIR)/../openssl-1.0.1c/include
90 OPENSSLLIBDIR = $(SRCDIR)/../openssl-1.0.1c
91
92 #### Either the directory where the Tcl library is installed or the Tcl
93 # source code directory resides (depending on the value of the macro
94 # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
95 # this directory must have "include" and "lib" sub-directories. If
@@ -301,10 +301,11 @@
301 $(SRCDIR)/json_dir.c \
302 $(SRCDIR)/json_finfo.c \
303 $(SRCDIR)/json_login.c \
304 $(SRCDIR)/json_query.c \
305 $(SRCDIR)/json_report.c \
 
306 $(SRCDIR)/json_tag.c \
307 $(SRCDIR)/json_timeline.c \
308 $(SRCDIR)/json_user.c \
309 $(SRCDIR)/json_wiki.c \
310 $(SRCDIR)/leaf.c \
@@ -348,10 +349,11 @@
348 $(SRCDIR)/unicode.c \
349 $(SRCDIR)/update.c \
350 $(SRCDIR)/url.c \
351 $(SRCDIR)/user.c \
352 $(SRCDIR)/utf8.c \
 
353 $(SRCDIR)/verify.c \
354 $(SRCDIR)/vfile.c \
355 $(SRCDIR)/wiki.c \
356 $(SRCDIR)/wikiformat.c \
357 $(SRCDIR)/winhttp.c \
@@ -407,10 +409,11 @@
407 $(OBJDIR)/json_dir_.c \
408 $(OBJDIR)/json_finfo_.c \
409 $(OBJDIR)/json_login_.c \
410 $(OBJDIR)/json_query_.c \
411 $(OBJDIR)/json_report_.c \
 
412 $(OBJDIR)/json_tag_.c \
413 $(OBJDIR)/json_timeline_.c \
414 $(OBJDIR)/json_user_.c \
415 $(OBJDIR)/json_wiki_.c \
416 $(OBJDIR)/leaf_.c \
@@ -454,10 +457,11 @@
454 $(OBJDIR)/unicode_.c \
455 $(OBJDIR)/update_.c \
456 $(OBJDIR)/url_.c \
457 $(OBJDIR)/user_.c \
458 $(OBJDIR)/utf8_.c \
 
459 $(OBJDIR)/verify_.c \
460 $(OBJDIR)/vfile_.c \
461 $(OBJDIR)/wiki_.c \
462 $(OBJDIR)/wikiformat_.c \
463 $(OBJDIR)/winhttp_.c \
@@ -513,10 +517,11 @@
513 $(OBJDIR)/json_dir.o \
514 $(OBJDIR)/json_finfo.o \
515 $(OBJDIR)/json_login.o \
516 $(OBJDIR)/json_query.o \
517 $(OBJDIR)/json_report.o \
 
518 $(OBJDIR)/json_tag.o \
519 $(OBJDIR)/json_timeline.o \
520 $(OBJDIR)/json_user.o \
521 $(OBJDIR)/json_wiki.o \
522 $(OBJDIR)/leaf.o \
@@ -560,10 +565,11 @@
560 $(OBJDIR)/unicode.o \
561 $(OBJDIR)/update.o \
562 $(OBJDIR)/url.o \
563 $(OBJDIR)/user.o \
564 $(OBJDIR)/utf8.o \
 
565 $(OBJDIR)/verify.o \
566 $(OBJDIR)/vfile.o \
567 $(OBJDIR)/wiki.o \
568 $(OBJDIR)/wikiformat.o \
569 $(OBJDIR)/winhttp.o \
@@ -732,10 +738,11 @@
732 $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h \
733 $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h \
734 $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h \
735 $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h \
736 $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h \
 
737 $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h \
738 $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h \
739 $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h \
740 $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h \
741 $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h \
@@ -779,10 +786,11 @@
779 $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h \
780 $(OBJDIR)/update_.c:$(OBJDIR)/update.h \
781 $(OBJDIR)/url_.c:$(OBJDIR)/url.h \
782 $(OBJDIR)/user_.c:$(OBJDIR)/user.h \
783 $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \
 
784 $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \
785 $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h \
786 $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h \
787 $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h \
788 $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h \
@@ -1180,10 +1188,18 @@
1180
1181 $(OBJDIR)/json_report.o: $(OBJDIR)/json_report_.c $(OBJDIR)/json_report.h $(SRCDIR)/config.h
1182 $(XTCC) -o $(OBJDIR)/json_report.o -c $(OBJDIR)/json_report_.c
1183
1184 $(OBJDIR)/json_report.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1185
1186 $(OBJDIR)/json_tag_.c: $(SRCDIR)/json_tag.c $(OBJDIR)/translate
1187 $(TRANSLATE) $(SRCDIR)/json_tag.c >$(OBJDIR)/json_tag_.c
1188
1189 $(OBJDIR)/json_tag.o: $(OBJDIR)/json_tag_.c $(OBJDIR)/json_tag.h $(SRCDIR)/config.h
@@ -1556,10 +1572,18 @@
1556
1557 $(OBJDIR)/utf8.o: $(OBJDIR)/utf8_.c $(OBJDIR)/utf8.h $(SRCDIR)/config.h
1558 $(XTCC) -o $(OBJDIR)/utf8.o -c $(OBJDIR)/utf8_.c
1559
1560 $(OBJDIR)/utf8.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1561
1562 $(OBJDIR)/verify_.c: $(SRCDIR)/verify.c $(OBJDIR)/translate
1563 $(TRANSLATE) $(SRCDIR)/verify.c >$(OBJDIR)/verify_.c
1564
1565 $(OBJDIR)/verify.o: $(OBJDIR)/verify_.c $(OBJDIR)/verify.h $(SRCDIR)/config.h
@@ -1635,11 +1659,11 @@
1635 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
1636
1637 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1638 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o
1639
1640 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
1641
1642 $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
1643 $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
1644
1645 $(OBJDIR)/th.o: $(SRCDIR)/th.c
1646
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -84,12 +84,12 @@
84 #### The directories where the OpenSSL include and library files are located.
85 # The recommended usage here is to use the Sysinternals junction tool
86 # to create a hard link between an "openssl-1.x" sub-directory of the
87 # Fossil source code directory and the target OpenSSL source directory.
88 #
89 OPENSSLINCDIR = $(SRCDIR)/../openssl-1.0.1e/include
90 OPENSSLLIBDIR = $(SRCDIR)/../openssl-1.0.1e
91
92 #### Either the directory where the Tcl library is installed or the Tcl
93 # source code directory resides (depending on the value of the macro
94 # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
95 # this directory must have "include" and "lib" sub-directories. If
@@ -301,10 +301,11 @@
301 $(SRCDIR)/json_dir.c \
302 $(SRCDIR)/json_finfo.c \
303 $(SRCDIR)/json_login.c \
304 $(SRCDIR)/json_query.c \
305 $(SRCDIR)/json_report.c \
306 $(SRCDIR)/json_status.c \
307 $(SRCDIR)/json_tag.c \
308 $(SRCDIR)/json_timeline.c \
309 $(SRCDIR)/json_user.c \
310 $(SRCDIR)/json_wiki.c \
311 $(SRCDIR)/leaf.c \
@@ -348,10 +349,11 @@
349 $(SRCDIR)/unicode.c \
350 $(SRCDIR)/update.c \
351 $(SRCDIR)/url.c \
352 $(SRCDIR)/user.c \
353 $(SRCDIR)/utf8.c \
354 $(SRCDIR)/util.c \
355 $(SRCDIR)/verify.c \
356 $(SRCDIR)/vfile.c \
357 $(SRCDIR)/wiki.c \
358 $(SRCDIR)/wikiformat.c \
359 $(SRCDIR)/winhttp.c \
@@ -407,10 +409,11 @@
409 $(OBJDIR)/json_dir_.c \
410 $(OBJDIR)/json_finfo_.c \
411 $(OBJDIR)/json_login_.c \
412 $(OBJDIR)/json_query_.c \
413 $(OBJDIR)/json_report_.c \
414 $(OBJDIR)/json_status_.c \
415 $(OBJDIR)/json_tag_.c \
416 $(OBJDIR)/json_timeline_.c \
417 $(OBJDIR)/json_user_.c \
418 $(OBJDIR)/json_wiki_.c \
419 $(OBJDIR)/leaf_.c \
@@ -454,10 +457,11 @@
457 $(OBJDIR)/unicode_.c \
458 $(OBJDIR)/update_.c \
459 $(OBJDIR)/url_.c \
460 $(OBJDIR)/user_.c \
461 $(OBJDIR)/utf8_.c \
462 $(OBJDIR)/util_.c \
463 $(OBJDIR)/verify_.c \
464 $(OBJDIR)/vfile_.c \
465 $(OBJDIR)/wiki_.c \
466 $(OBJDIR)/wikiformat_.c \
467 $(OBJDIR)/winhttp_.c \
@@ -513,10 +517,11 @@
517 $(OBJDIR)/json_dir.o \
518 $(OBJDIR)/json_finfo.o \
519 $(OBJDIR)/json_login.o \
520 $(OBJDIR)/json_query.o \
521 $(OBJDIR)/json_report.o \
522 $(OBJDIR)/json_status.o \
523 $(OBJDIR)/json_tag.o \
524 $(OBJDIR)/json_timeline.o \
525 $(OBJDIR)/json_user.o \
526 $(OBJDIR)/json_wiki.o \
527 $(OBJDIR)/leaf.o \
@@ -560,10 +565,11 @@
565 $(OBJDIR)/unicode.o \
566 $(OBJDIR)/update.o \
567 $(OBJDIR)/url.o \
568 $(OBJDIR)/user.o \
569 $(OBJDIR)/utf8.o \
570 $(OBJDIR)/util.o \
571 $(OBJDIR)/verify.o \
572 $(OBJDIR)/vfile.o \
573 $(OBJDIR)/wiki.o \
574 $(OBJDIR)/wikiformat.o \
575 $(OBJDIR)/winhttp.o \
@@ -732,10 +738,11 @@
738 $(OBJDIR)/json_dir_.c:$(OBJDIR)/json_dir.h \
739 $(OBJDIR)/json_finfo_.c:$(OBJDIR)/json_finfo.h \
740 $(OBJDIR)/json_login_.c:$(OBJDIR)/json_login.h \
741 $(OBJDIR)/json_query_.c:$(OBJDIR)/json_query.h \
742 $(OBJDIR)/json_report_.c:$(OBJDIR)/json_report.h \
743 $(OBJDIR)/json_status_.c:$(OBJDIR)/json_status.h \
744 $(OBJDIR)/json_tag_.c:$(OBJDIR)/json_tag.h \
745 $(OBJDIR)/json_timeline_.c:$(OBJDIR)/json_timeline.h \
746 $(OBJDIR)/json_user_.c:$(OBJDIR)/json_user.h \
747 $(OBJDIR)/json_wiki_.c:$(OBJDIR)/json_wiki.h \
748 $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h \
@@ -779,10 +786,11 @@
786 $(OBJDIR)/unicode_.c:$(OBJDIR)/unicode.h \
787 $(OBJDIR)/update_.c:$(OBJDIR)/update.h \
788 $(OBJDIR)/url_.c:$(OBJDIR)/url.h \
789 $(OBJDIR)/user_.c:$(OBJDIR)/user.h \
790 $(OBJDIR)/utf8_.c:$(OBJDIR)/utf8.h \
791 $(OBJDIR)/util_.c:$(OBJDIR)/util.h \
792 $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h \
793 $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h \
794 $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h \
795 $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h \
796 $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h \
@@ -1180,10 +1188,18 @@
1188
1189 $(OBJDIR)/json_report.o: $(OBJDIR)/json_report_.c $(OBJDIR)/json_report.h $(SRCDIR)/config.h
1190 $(XTCC) -o $(OBJDIR)/json_report.o -c $(OBJDIR)/json_report_.c
1191
1192 $(OBJDIR)/json_report.h: $(OBJDIR)/headers
1193
1194 $(OBJDIR)/json_status_.c: $(SRCDIR)/json_status.c $(OBJDIR)/translate
1195 $(TRANSLATE) $(SRCDIR)/json_status.c >$(OBJDIR)/json_status_.c
1196
1197 $(OBJDIR)/json_status.o: $(OBJDIR)/json_status_.c $(OBJDIR)/json_status.h $(SRCDIR)/config.h
1198 $(XTCC) -o $(OBJDIR)/json_status.o -c $(OBJDIR)/json_status_.c
1199
1200 $(OBJDIR)/json_status.h: $(OBJDIR)/headers
1201
1202 $(OBJDIR)/json_tag_.c: $(SRCDIR)/json_tag.c $(OBJDIR)/translate
1203 $(TRANSLATE) $(SRCDIR)/json_tag.c >$(OBJDIR)/json_tag_.c
1204
1205 $(OBJDIR)/json_tag.o: $(OBJDIR)/json_tag_.c $(OBJDIR)/json_tag.h $(SRCDIR)/config.h
@@ -1556,10 +1572,18 @@
1572
1573 $(OBJDIR)/utf8.o: $(OBJDIR)/utf8_.c $(OBJDIR)/utf8.h $(SRCDIR)/config.h
1574 $(XTCC) -o $(OBJDIR)/utf8.o -c $(OBJDIR)/utf8_.c
1575
1576 $(OBJDIR)/utf8.h: $(OBJDIR)/headers
1577
1578 $(OBJDIR)/util_.c: $(SRCDIR)/util.c $(OBJDIR)/translate
1579 $(TRANSLATE) $(SRCDIR)/util.c >$(OBJDIR)/util_.c
1580
1581 $(OBJDIR)/util.o: $(OBJDIR)/util_.c $(OBJDIR)/util.h $(SRCDIR)/config.h
1582 $(XTCC) -o $(OBJDIR)/util.o -c $(OBJDIR)/util_.c
1583
1584 $(OBJDIR)/util.h: $(OBJDIR)/headers
1585
1586 $(OBJDIR)/verify_.c: $(SRCDIR)/verify.c $(OBJDIR)/translate
1587 $(TRANSLATE) $(SRCDIR)/verify.c >$(OBJDIR)/verify_.c
1588
1589 $(OBJDIR)/verify.o: $(OBJDIR)/verify_.c $(OBJDIR)/verify.h $(SRCDIR)/config.h
@@ -1635,11 +1659,11 @@
1659 $(XTCC) -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT3 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0 -c $(SRCDIR)/sqlite3.c -o $(OBJDIR)/sqlite3.o
1660
1661 $(OBJDIR)/cson_amalgamation.o: $(SRCDIR)/cson_amalgamation.c
1662 $(XTCC) -c $(SRCDIR)/cson_amalgamation.c -o $(OBJDIR)/cson_amalgamation.o
1663
1664 $(OBJDIR)/json.o $(OBJDIR)/json_artifact.o $(OBJDIR)/json_branch.o $(OBJDIR)/json_config.o $(OBJDIR)/json_diff.o $(OBJDIR)/json_dir.o $(OBJDIR)/jsos_finfo.o $(OBJDIR)/json_login.o $(OBJDIR)/json_query.o $(OBJDIR)/json_report.o $(OBJDIR)/json_status.o $(OBJDIR)/json_tag.o $(OBJDIR)/json_timeline.o $(OBJDIR)/json_user.o $(OBJDIR)/json_wiki.o : $(SRCDIR)/json_detail.h
1665
1666 $(OBJDIR)/shell.o: $(SRCDIR)/shell.c $(SRCDIR)/sqlite3.h
1667 $(XTCC) -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -c $(SRCDIR)/shell.c -o $(OBJDIR)/shell.o
1668
1669 $(OBJDIR)/th.o: $(SRCDIR)/th.c
1670
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -84,12 +84,12 @@
8484
#### The directories where the OpenSSL include and library files are located.
8585
# The recommended usage here is to use the Sysinternals junction tool
8686
# to create a hard link between an "openssl-1.x" sub-directory of the
8787
# Fossil source code directory and the target OpenSSL source directory.
8888
#
89
-OPENSSLINCDIR = $(SRCDIR)/../openssl-1.0.1c/include
90
-OPENSSLLIBDIR = $(SRCDIR)/../openssl-1.0.1c
89
+OPENSSLINCDIR = $(SRCDIR)/../openssl-1.0.1e/include
90
+OPENSSLLIBDIR = $(SRCDIR)/../openssl-1.0.1e
9191
9292
#### Either the directory where the Tcl library is installed or the Tcl
9393
# source code directory resides (depending on the value of the macro
9494
# FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
9595
# this directory must have "include" and "lib" sub-directories. If
9696
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -84,12 +84,12 @@
84 #### The directories where the OpenSSL include and library files are located.
85 # The recommended usage here is to use the Sysinternals junction tool
86 # to create a hard link between an "openssl-1.x" sub-directory of the
87 # Fossil source code directory and the target OpenSSL source directory.
88 #
89 OPENSSLINCDIR = $(SRCDIR)/../openssl-1.0.1c/include
90 OPENSSLLIBDIR = $(SRCDIR)/../openssl-1.0.1c
91
92 #### Either the directory where the Tcl library is installed or the Tcl
93 # source code directory resides (depending on the value of the macro
94 # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
95 # this directory must have "include" and "lib" sub-directories. If
96
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -84,12 +84,12 @@
84 #### The directories where the OpenSSL include and library files are located.
85 # The recommended usage here is to use the Sysinternals junction tool
86 # to create a hard link between an "openssl-1.x" sub-directory of the
87 # Fossil source code directory and the target OpenSSL source directory.
88 #
89 OPENSSLINCDIR = $(SRCDIR)/../openssl-1.0.1e/include
90 OPENSSLLIBDIR = $(SRCDIR)/../openssl-1.0.1e
91
92 #### Either the directory where the Tcl library is installed or the Tcl
93 # source code directory resides (depending on the value of the macro
94 # FOSSIL_TCL_SOURCE). If this points to the Tcl install directory,
95 # this directory must have "include" and "lib" sub-directories. If
96
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -103,10 +103,11 @@
103103
json_dir_.c \
104104
json_finfo_.c \
105105
json_login_.c \
106106
json_query_.c \
107107
json_report_.c \
108
+ json_status_.c \
108109
json_tag_.c \
109110
json_timeline_.c \
110111
json_user_.c \
111112
json_wiki_.c \
112113
leaf_.c \
@@ -150,10 +151,11 @@
150151
unicode_.c \
151152
update_.c \
152153
url_.c \
153154
user_.c \
154155
utf8_.c \
156
+ util_.c \
155157
verify_.c \
156158
vfile_.c \
157159
wiki_.c \
158160
wikiformat_.c \
159161
winhttp_.c \
@@ -209,10 +211,11 @@
209211
$(OX)\json_dir$O \
210212
$(OX)\json_finfo$O \
211213
$(OX)\json_login$O \
212214
$(OX)\json_query$O \
213215
$(OX)\json_report$O \
216
+ $(OX)\json_status$O \
214217
$(OX)\json_tag$O \
215218
$(OX)\json_timeline$O \
216219
$(OX)\json_user$O \
217220
$(OX)\json_wiki$O \
218221
$(OX)\leaf$O \
@@ -260,10 +263,11 @@
260263
$(OX)\unicode$O \
261264
$(OX)\update$O \
262265
$(OX)\url$O \
263266
$(OX)\user$O \
264267
$(OX)\utf8$O \
268
+ $(OX)\util$O \
265269
$(OX)\verify$O \
266270
$(OX)\vfile$O \
267271
$(OX)\wiki$O \
268272
$(OX)\wikiformat$O \
269273
$(OX)\winhttp$O \
@@ -333,10 +337,11 @@
333337
echo $(OX)\json_dir.obj >> $@
334338
echo $(OX)\json_finfo.obj >> $@
335339
echo $(OX)\json_login.obj >> $@
336340
echo $(OX)\json_query.obj >> $@
337341
echo $(OX)\json_report.obj >> $@
342
+ echo $(OX)\json_status.obj >> $@
338343
echo $(OX)\json_tag.obj >> $@
339344
echo $(OX)\json_timeline.obj >> $@
340345
echo $(OX)\json_user.obj >> $@
341346
echo $(OX)\json_wiki.obj >> $@
342347
echo $(OX)\leaf.obj >> $@
@@ -384,10 +389,11 @@
384389
echo $(OX)\unicode.obj >> $@
385390
echo $(OX)\update.obj >> $@
386391
echo $(OX)\url.obj >> $@
387392
echo $(OX)\user.obj >> $@
388393
echo $(OX)\utf8.obj >> $@
394
+ echo $(OX)\util.obj >> $@
389395
echo $(OX)\verify.obj >> $@
390396
echo $(OX)\vfile.obj >> $@
391397
echo $(OX)\wiki.obj >> $@
392398
echo $(OX)\wikiformat.obj >> $@
393399
echo $(OX)\winhttp.obj >> $@
@@ -461,10 +467,11 @@
461467
$(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
462468
$(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
463469
$(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
464470
$(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
465471
$(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
472
+$(OBJDIR)\json_status$O : $(SRCDIR)\json_detail.h
466473
$(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
467474
$(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
468475
$(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
469476
$(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h
470477
@@ -754,10 +761,16 @@
754761
$(OX)\json_report$O : json_report_.c json_report.h
755762
$(TCC) /Fo$@ -c json_report_.c
756763
757764
json_report_.c : $(SRCDIR)\json_report.c
758765
translate$E $** > $@
766
+
767
+$(OX)\json_status$O : json_status_.c json_status.h
768
+ $(TCC) /Fo$@ -c json_status_.c
769
+
770
+json_status_.c : $(SRCDIR)\json_status.c
771
+ translate$E $** > $@
759772
760773
$(OX)\json_tag$O : json_tag_.c json_tag.h
761774
$(TCC) /Fo$@ -c json_tag_.c
762775
763776
json_tag_.c : $(SRCDIR)\json_tag.c
@@ -1036,10 +1049,16 @@
10361049
$(OX)\utf8$O : utf8_.c utf8.h
10371050
$(TCC) /Fo$@ -c utf8_.c
10381051
10391052
utf8_.c : $(SRCDIR)\utf8.c
10401053
translate$E $** > $@
1054
+
1055
+$(OX)\util$O : util_.c util.h
1056
+ $(TCC) /Fo$@ -c util_.c
1057
+
1058
+util_.c : $(SRCDIR)\util.c
1059
+ translate$E $** > $@
10411060
10421061
$(OX)\verify$O : verify_.c verify.h
10431062
$(TCC) /Fo$@ -c verify_.c
10441063
10451064
verify_.c : $(SRCDIR)\verify.c
@@ -1142,10 +1161,11 @@
11421161
json_dir_.c:json_dir.h \
11431162
json_finfo_.c:json_finfo.h \
11441163
json_login_.c:json_login.h \
11451164
json_query_.c:json_query.h \
11461165
json_report_.c:json_report.h \
1166
+ json_status_.c:json_status.h \
11471167
json_tag_.c:json_tag.h \
11481168
json_timeline_.c:json_timeline.h \
11491169
json_user_.c:json_user.h \
11501170
json_wiki_.c:json_wiki.h \
11511171
leaf_.c:leaf.h \
@@ -1189,10 +1209,11 @@
11891209
unicode_.c:unicode.h \
11901210
update_.c:update.h \
11911211
url_.c:url.h \
11921212
user_.c:user.h \
11931213
utf8_.c:utf8.h \
1214
+ util_.c:util.h \
11941215
verify_.c:verify.h \
11951216
vfile_.c:vfile.h \
11961217
wiki_.c:wiki.h \
11971218
wikiformat_.c:wikiformat.h \
11981219
winhttp_.c:winhttp.h \
11991220
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -103,10 +103,11 @@
103 json_dir_.c \
104 json_finfo_.c \
105 json_login_.c \
106 json_query_.c \
107 json_report_.c \
 
108 json_tag_.c \
109 json_timeline_.c \
110 json_user_.c \
111 json_wiki_.c \
112 leaf_.c \
@@ -150,10 +151,11 @@
150 unicode_.c \
151 update_.c \
152 url_.c \
153 user_.c \
154 utf8_.c \
 
155 verify_.c \
156 vfile_.c \
157 wiki_.c \
158 wikiformat_.c \
159 winhttp_.c \
@@ -209,10 +211,11 @@
209 $(OX)\json_dir$O \
210 $(OX)\json_finfo$O \
211 $(OX)\json_login$O \
212 $(OX)\json_query$O \
213 $(OX)\json_report$O \
 
214 $(OX)\json_tag$O \
215 $(OX)\json_timeline$O \
216 $(OX)\json_user$O \
217 $(OX)\json_wiki$O \
218 $(OX)\leaf$O \
@@ -260,10 +263,11 @@
260 $(OX)\unicode$O \
261 $(OX)\update$O \
262 $(OX)\url$O \
263 $(OX)\user$O \
264 $(OX)\utf8$O \
 
265 $(OX)\verify$O \
266 $(OX)\vfile$O \
267 $(OX)\wiki$O \
268 $(OX)\wikiformat$O \
269 $(OX)\winhttp$O \
@@ -333,10 +337,11 @@
333 echo $(OX)\json_dir.obj >> $@
334 echo $(OX)\json_finfo.obj >> $@
335 echo $(OX)\json_login.obj >> $@
336 echo $(OX)\json_query.obj >> $@
337 echo $(OX)\json_report.obj >> $@
 
338 echo $(OX)\json_tag.obj >> $@
339 echo $(OX)\json_timeline.obj >> $@
340 echo $(OX)\json_user.obj >> $@
341 echo $(OX)\json_wiki.obj >> $@
342 echo $(OX)\leaf.obj >> $@
@@ -384,10 +389,11 @@
384 echo $(OX)\unicode.obj >> $@
385 echo $(OX)\update.obj >> $@
386 echo $(OX)\url.obj >> $@
387 echo $(OX)\user.obj >> $@
388 echo $(OX)\utf8.obj >> $@
 
389 echo $(OX)\verify.obj >> $@
390 echo $(OX)\vfile.obj >> $@
391 echo $(OX)\wiki.obj >> $@
392 echo $(OX)\wikiformat.obj >> $@
393 echo $(OX)\winhttp.obj >> $@
@@ -461,10 +467,11 @@
461 $(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
462 $(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
463 $(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
464 $(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
465 $(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
 
466 $(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
467 $(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
468 $(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
469 $(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h
470
@@ -754,10 +761,16 @@
754 $(OX)\json_report$O : json_report_.c json_report.h
755 $(TCC) /Fo$@ -c json_report_.c
756
757 json_report_.c : $(SRCDIR)\json_report.c
758 translate$E $** > $@
 
 
 
 
 
 
759
760 $(OX)\json_tag$O : json_tag_.c json_tag.h
761 $(TCC) /Fo$@ -c json_tag_.c
762
763 json_tag_.c : $(SRCDIR)\json_tag.c
@@ -1036,10 +1049,16 @@
1036 $(OX)\utf8$O : utf8_.c utf8.h
1037 $(TCC) /Fo$@ -c utf8_.c
1038
1039 utf8_.c : $(SRCDIR)\utf8.c
1040 translate$E $** > $@
 
 
 
 
 
 
1041
1042 $(OX)\verify$O : verify_.c verify.h
1043 $(TCC) /Fo$@ -c verify_.c
1044
1045 verify_.c : $(SRCDIR)\verify.c
@@ -1142,10 +1161,11 @@
1142 json_dir_.c:json_dir.h \
1143 json_finfo_.c:json_finfo.h \
1144 json_login_.c:json_login.h \
1145 json_query_.c:json_query.h \
1146 json_report_.c:json_report.h \
 
1147 json_tag_.c:json_tag.h \
1148 json_timeline_.c:json_timeline.h \
1149 json_user_.c:json_user.h \
1150 json_wiki_.c:json_wiki.h \
1151 leaf_.c:leaf.h \
@@ -1189,10 +1209,11 @@
1189 unicode_.c:unicode.h \
1190 update_.c:update.h \
1191 url_.c:url.h \
1192 user_.c:user.h \
1193 utf8_.c:utf8.h \
 
1194 verify_.c:verify.h \
1195 vfile_.c:vfile.h \
1196 wiki_.c:wiki.h \
1197 wikiformat_.c:wikiformat.h \
1198 winhttp_.c:winhttp.h \
1199
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -103,10 +103,11 @@
103 json_dir_.c \
104 json_finfo_.c \
105 json_login_.c \
106 json_query_.c \
107 json_report_.c \
108 json_status_.c \
109 json_tag_.c \
110 json_timeline_.c \
111 json_user_.c \
112 json_wiki_.c \
113 leaf_.c \
@@ -150,10 +151,11 @@
151 unicode_.c \
152 update_.c \
153 url_.c \
154 user_.c \
155 utf8_.c \
156 util_.c \
157 verify_.c \
158 vfile_.c \
159 wiki_.c \
160 wikiformat_.c \
161 winhttp_.c \
@@ -209,10 +211,11 @@
211 $(OX)\json_dir$O \
212 $(OX)\json_finfo$O \
213 $(OX)\json_login$O \
214 $(OX)\json_query$O \
215 $(OX)\json_report$O \
216 $(OX)\json_status$O \
217 $(OX)\json_tag$O \
218 $(OX)\json_timeline$O \
219 $(OX)\json_user$O \
220 $(OX)\json_wiki$O \
221 $(OX)\leaf$O \
@@ -260,10 +263,11 @@
263 $(OX)\unicode$O \
264 $(OX)\update$O \
265 $(OX)\url$O \
266 $(OX)\user$O \
267 $(OX)\utf8$O \
268 $(OX)\util$O \
269 $(OX)\verify$O \
270 $(OX)\vfile$O \
271 $(OX)\wiki$O \
272 $(OX)\wikiformat$O \
273 $(OX)\winhttp$O \
@@ -333,10 +337,11 @@
337 echo $(OX)\json_dir.obj >> $@
338 echo $(OX)\json_finfo.obj >> $@
339 echo $(OX)\json_login.obj >> $@
340 echo $(OX)\json_query.obj >> $@
341 echo $(OX)\json_report.obj >> $@
342 echo $(OX)\json_status.obj >> $@
343 echo $(OX)\json_tag.obj >> $@
344 echo $(OX)\json_timeline.obj >> $@
345 echo $(OX)\json_user.obj >> $@
346 echo $(OX)\json_wiki.obj >> $@
347 echo $(OX)\leaf.obj >> $@
@@ -384,10 +389,11 @@
389 echo $(OX)\unicode.obj >> $@
390 echo $(OX)\update.obj >> $@
391 echo $(OX)\url.obj >> $@
392 echo $(OX)\user.obj >> $@
393 echo $(OX)\utf8.obj >> $@
394 echo $(OX)\util.obj >> $@
395 echo $(OX)\verify.obj >> $@
396 echo $(OX)\vfile.obj >> $@
397 echo $(OX)\wiki.obj >> $@
398 echo $(OX)\wikiformat.obj >> $@
399 echo $(OX)\winhttp.obj >> $@
@@ -461,10 +467,11 @@
467 $(OBJDIR)\json_dir$O : $(SRCDIR)\json_detail.h
468 $(OBJDIR)\json_finfo$O : $(SRCDIR)\json_detail.h
469 $(OBJDIR)\json_login$O : $(SRCDIR)\json_detail.h
470 $(OBJDIR)\json_query$O : $(SRCDIR)\json_detail.h
471 $(OBJDIR)\json_report$O : $(SRCDIR)\json_detail.h
472 $(OBJDIR)\json_status$O : $(SRCDIR)\json_detail.h
473 $(OBJDIR)\json_tag$O : $(SRCDIR)\json_detail.h
474 $(OBJDIR)\json_timeline$O : $(SRCDIR)\json_detail.h
475 $(OBJDIR)\json_user$O : $(SRCDIR)\json_detail.h
476 $(OBJDIR)\json_wiki$O : $(SRCDIR)\json_detail.h
477
@@ -754,10 +761,16 @@
761 $(OX)\json_report$O : json_report_.c json_report.h
762 $(TCC) /Fo$@ -c json_report_.c
763
764 json_report_.c : $(SRCDIR)\json_report.c
765 translate$E $** > $@
766
767 $(OX)\json_status$O : json_status_.c json_status.h
768 $(TCC) /Fo$@ -c json_status_.c
769
770 json_status_.c : $(SRCDIR)\json_status.c
771 translate$E $** > $@
772
773 $(OX)\json_tag$O : json_tag_.c json_tag.h
774 $(TCC) /Fo$@ -c json_tag_.c
775
776 json_tag_.c : $(SRCDIR)\json_tag.c
@@ -1036,10 +1049,16 @@
1049 $(OX)\utf8$O : utf8_.c utf8.h
1050 $(TCC) /Fo$@ -c utf8_.c
1051
1052 utf8_.c : $(SRCDIR)\utf8.c
1053 translate$E $** > $@
1054
1055 $(OX)\util$O : util_.c util.h
1056 $(TCC) /Fo$@ -c util_.c
1057
1058 util_.c : $(SRCDIR)\util.c
1059 translate$E $** > $@
1060
1061 $(OX)\verify$O : verify_.c verify.h
1062 $(TCC) /Fo$@ -c verify_.c
1063
1064 verify_.c : $(SRCDIR)\verify.c
@@ -1142,10 +1161,11 @@
1161 json_dir_.c:json_dir.h \
1162 json_finfo_.c:json_finfo.h \
1163 json_login_.c:json_login.h \
1164 json_query_.c:json_query.h \
1165 json_report_.c:json_report.h \
1166 json_status_.c:json_status.h \
1167 json_tag_.c:json_tag.h \
1168 json_timeline_.c:json_timeline.h \
1169 json_user_.c:json_user.h \
1170 json_wiki_.c:json_wiki.h \
1171 leaf_.c:leaf.h \
@@ -1189,10 +1209,11 @@
1209 unicode_.c:unicode.h \
1210 update_.c:update.h \
1211 url_.c:url.h \
1212 user_.c:user.h \
1213 utf8_.c:utf8.h \
1214 util_.c:util.h \
1215 verify_.c:verify.h \
1216 vfile_.c:vfile.h \
1217 wiki_.c:wiki.h \
1218 wikiformat_.c:wikiformat.h \
1219 winhttp_.c:winhttp.h \
1220
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,6 +1,13 @@
11
<title>Change Log</title>
2
+
3
+<h2>Changes For Version 1.26 (as yet unreleased)</h2>
4
+ * Enhancements to /timeline.rss, adding more flags for filtering
5
+ results, including the ability to subscribe to changes made
6
+ to individual tickets. For example: [/timeline.rss?y=t&tkt=12fceeec82].
7
+ * JSON API: added the 'status' command to report local checkout status.
8
+
29
310
<h2>Changes For Version 1.25 (2013-02-16)</h2>
411
* Enhancements to ticket processing. There are now two tables: TICKET and
512
TICKETCHNG. There is one row in TICKETCHNG for each ticket artifact.
613
Fields from ticket artifacts go into either or both of TICKET and
714
815
ADDED www/fossil_prompt.sh
916
ADDED www/fossil_prompt.wiki
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,6 +1,13 @@
1 <title>Change Log</title>
 
 
 
 
 
 
 
2
3 <h2>Changes For Version 1.25 (2013-02-16)</h2>
4 * Enhancements to ticket processing. There are now two tables: TICKET and
5 TICKETCHNG. There is one row in TICKETCHNG for each ticket artifact.
6 Fields from ticket artifacts go into either or both of TICKET and
7
8 DDED www/fossil_prompt.sh
9 DDED www/fossil_prompt.wiki
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,6 +1,13 @@
1 <title>Change Log</title>
2
3 <h2>Changes For Version 1.26 (as yet unreleased)</h2>
4 * Enhancements to /timeline.rss, adding more flags for filtering
5 results, including the ability to subscribe to changes made
6 to individual tickets. For example: [/timeline.rss?y=t&tkt=12fceeec82].
7 * JSON API: added the 'status' command to report local checkout status.
8
9
10 <h2>Changes For Version 1.25 (2013-02-16)</h2>
11 * Enhancements to ticket processing. There are now two tables: TICKET and
12 TICKETCHNG. There is one row in TICKETCHNG for each ticket artifact.
13 Fields from ticket artifacts go into either or both of TICKET and
14
15 DDED www/fossil_prompt.sh
16 DDED www/fossil_prompt.wiki
--- a/www/fossil_prompt.sh
+++ b/www/fossil_prompt.sh
@@ -0,0 +1,3 @@
1
+
2
+#--------------------------------- sed 's/"//g'|grep "^[^ ]*:" |
3
+
--- a/www/fossil_prompt.sh
+++ b/www/fossil_prompt.sh
@@ -0,0 +1,3 @@
 
 
 
--- a/www/fossil_prompt.sh
+++ b/www/fossil_prompt.sh
@@ -0,0 +1,3 @@
1
2 #--------------------------------- sed 's/"//g'|grep "^[^ ]*:" |
3
--- a/www/fossil_prompt.wiki
+++ b/www/fossil_prompt.wiki
@@ -0,0 +1 @@
1
+<title>Fossy
--- a/www/fossil_prompt.wiki
+++ b/www/fossil_prompt.wiki
@@ -0,0 +1 @@
 
--- a/www/fossil_prompt.wiki
+++ b/www/fossil_prompt.wiki
@@ -0,0 +1 @@
1 <title>Fossy

Keyboard Shortcuts

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