Fossil SCM

Merge in updates from trunk.

andybradford 2014-02-14 07:16 http-auth merge
Commit 99744084fb3e8be63a87d957b889708e429eed21
-12
--- src/branch.c
+++ src/branch.c
@@ -368,16 +368,10 @@
368368
}
369369
if( cnt ){
370370
@ </ul>
371371
}
372372
db_finalize(&q);
373
- @ <script type="text/JavaScript">
374
- @ function xin(id){
375
- @ }
376
- @ function xout(id){
377
- @ }
378
- @ </script>
379373
style_footer();
380374
}
381375
382376
/*
383377
** This routine is called while for each check-in that is rendered by
@@ -423,13 +417,7 @@
423417
" ORDER BY event.mtime DESC",
424418
timeline_query_for_www(), TAG_BRANCH
425419
);
426420
www_print_timeline(&q, 0, 0, 0, brtimeline_extra);
427421
db_finalize(&q);
428
- @ <script type="text/JavaScript">
429
- @ function xin(id){
430
- @ }
431
- @ function xout(id){
432
- @ }
433
- @ </script>
434422
style_footer();
435423
}
436424
--- src/branch.c
+++ src/branch.c
@@ -368,16 +368,10 @@
368 }
369 if( cnt ){
370 @ </ul>
371 }
372 db_finalize(&q);
373 @ <script type="text/JavaScript">
374 @ function xin(id){
375 @ }
376 @ function xout(id){
377 @ }
378 @ </script>
379 style_footer();
380 }
381
382 /*
383 ** This routine is called while for each check-in that is rendered by
@@ -423,13 +417,7 @@
423 " ORDER BY event.mtime DESC",
424 timeline_query_for_www(), TAG_BRANCH
425 );
426 www_print_timeline(&q, 0, 0, 0, brtimeline_extra);
427 db_finalize(&q);
428 @ <script type="text/JavaScript">
429 @ function xin(id){
430 @ }
431 @ function xout(id){
432 @ }
433 @ </script>
434 style_footer();
435 }
436
--- src/branch.c
+++ src/branch.c
@@ -368,16 +368,10 @@
368 }
369 if( cnt ){
370 @ </ul>
371 }
372 db_finalize(&q);
 
 
 
 
 
 
373 style_footer();
374 }
375
376 /*
377 ** This routine is called while for each check-in that is rendered by
@@ -423,13 +417,7 @@
417 " ORDER BY event.mtime DESC",
418 timeline_query_for_www(), TAG_BRANCH
419 );
420 www_print_timeline(&q, 0, 0, 0, brtimeline_extra);
421 db_finalize(&q);
 
 
 
 
 
 
422 style_footer();
423 }
424
+3 -5
--- src/cgi.c
+++ src/cgi.c
@@ -1706,15 +1706,13 @@
17061706
" port in the range %d..%d", mnPort, mxPort);
17071707
}
17081708
}
17091709
if( iPort>mxPort ) return 1;
17101710
listen(listener,10);
1711
- if( iPort>mnPort ){
1712
- fossil_print("Listening for %s requests on TCP port %d\n",
1713
- (flags & HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP", iPort);
1714
- fflush(stdout);
1715
- }
1711
+ fossil_print("Listening for %s requests on TCP port %d\n",
1712
+ (flags & HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP", iPort);
1713
+ fflush(stdout);
17161714
if( zBrowser ){
17171715
zBrowser = mprintf(zBrowser, iPort);
17181716
#if defined(__CYGWIN__)
17191717
/* On Cygwin, we can do better than "echo" */
17201718
if( memcmp(zBrowser, "echo ", 5)==0 ){
17211719
--- src/cgi.c
+++ src/cgi.c
@@ -1706,15 +1706,13 @@
1706 " port in the range %d..%d", mnPort, mxPort);
1707 }
1708 }
1709 if( iPort>mxPort ) return 1;
1710 listen(listener,10);
1711 if( iPort>mnPort ){
1712 fossil_print("Listening for %s requests on TCP port %d\n",
1713 (flags & HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP", iPort);
1714 fflush(stdout);
1715 }
1716 if( zBrowser ){
1717 zBrowser = mprintf(zBrowser, iPort);
1718 #if defined(__CYGWIN__)
1719 /* On Cygwin, we can do better than "echo" */
1720 if( memcmp(zBrowser, "echo ", 5)==0 ){
1721
--- src/cgi.c
+++ src/cgi.c
@@ -1706,15 +1706,13 @@
1706 " port in the range %d..%d", mnPort, mxPort);
1707 }
1708 }
1709 if( iPort>mxPort ) return 1;
1710 listen(listener,10);
1711 fossil_print("Listening for %s requests on TCP port %d\n",
1712 (flags & HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP", iPort);
1713 fflush(stdout);
 
 
1714 if( zBrowser ){
1715 zBrowser = mprintf(zBrowser, iPort);
1716 #if defined(__CYGWIN__)
1717 /* On Cygwin, we can do better than "echo" */
1718 if( memcmp(zBrowser, "echo ", 5)==0 ){
1719
+2 -2
--- src/db.c
+++ src/db.c
@@ -44,11 +44,11 @@
4444
** An single SQL statement is represented as an instance of the following
4545
** structure.
4646
*/
4747
struct Stmt {
4848
Blob sql; /* The SQL for this statement */
49
- sqlite3_stmt *pStmt; /* The results of sqlite3_prepare() */
49
+ sqlite3_stmt *pStmt; /* The results of sqlite3_prepare_v2() */
5050
Stmt *pNext, *pPrev; /* List of all unfinalized statements */
5151
int nStep; /* Number of sqlite3_step() calls */
5252
};
5353
5454
/*
@@ -108,11 +108,11 @@
108108
static struct DbLocalData {
109109
int nBegin; /* Nesting depth of BEGIN */
110110
int doRollback; /* True to force a rollback */
111111
int nCommitHook; /* Number of commit hooks */
112112
Stmt *pAllStmt; /* List of all unfinalized statements */
113
- int nPrepare; /* Number of calls to sqlite3_prepare() */
113
+ int nPrepare; /* Number of calls to sqlite3_prepare_v2() */
114114
int nDeleteOnFail; /* Number of entries in azDeleteOnFail[] */
115115
struct sCommitHook {
116116
int (*xHook)(void); /* Functions to call at db_end_transaction() */
117117
int sequence; /* Call functions in sequence order */
118118
} aHook[5];
119119
--- src/db.c
+++ src/db.c
@@ -44,11 +44,11 @@
44 ** An single SQL statement is represented as an instance of the following
45 ** structure.
46 */
47 struct Stmt {
48 Blob sql; /* The SQL for this statement */
49 sqlite3_stmt *pStmt; /* The results of sqlite3_prepare() */
50 Stmt *pNext, *pPrev; /* List of all unfinalized statements */
51 int nStep; /* Number of sqlite3_step() calls */
52 };
53
54 /*
@@ -108,11 +108,11 @@
108 static struct DbLocalData {
109 int nBegin; /* Nesting depth of BEGIN */
110 int doRollback; /* True to force a rollback */
111 int nCommitHook; /* Number of commit hooks */
112 Stmt *pAllStmt; /* List of all unfinalized statements */
113 int nPrepare; /* Number of calls to sqlite3_prepare() */
114 int nDeleteOnFail; /* Number of entries in azDeleteOnFail[] */
115 struct sCommitHook {
116 int (*xHook)(void); /* Functions to call at db_end_transaction() */
117 int sequence; /* Call functions in sequence order */
118 } aHook[5];
119
--- src/db.c
+++ src/db.c
@@ -44,11 +44,11 @@
44 ** An single SQL statement is represented as an instance of the following
45 ** structure.
46 */
47 struct Stmt {
48 Blob sql; /* The SQL for this statement */
49 sqlite3_stmt *pStmt; /* The results of sqlite3_prepare_v2() */
50 Stmt *pNext, *pPrev; /* List of all unfinalized statements */
51 int nStep; /* Number of sqlite3_step() calls */
52 };
53
54 /*
@@ -108,11 +108,11 @@
108 static struct DbLocalData {
109 int nBegin; /* Nesting depth of BEGIN */
110 int doRollback; /* True to force a rollback */
111 int nCommitHook; /* Number of commit hooks */
112 Stmt *pAllStmt; /* List of all unfinalized statements */
113 int nPrepare; /* Number of calls to sqlite3_prepare_v2() */
114 int nDeleteOnFail; /* Number of entries in azDeleteOnFail[] */
115 struct sCommitHook {
116 int (*xHook)(void); /* Functions to call at db_end_transaction() */
117 int sequence; /* Call functions in sequence order */
118 } aHook[5];
119
--- src/descendants.c
+++ src/descendants.c
@@ -447,16 +447,10 @@
447447
db_prepare(&q, "%s ORDER BY event.mtime DESC", blob_str(&sql));
448448
blob_reset(&sql);
449449
www_print_timeline(&q, TIMELINE_LEAFONLY, 0, 0, 0);
450450
db_finalize(&q);
451451
@ <br />
452
- @ <script type="text/JavaScript">
453
- @ function xin(id){
454
- @ }
455
- @ function xout(id){
456
- @ }
457
- @ </script>
458452
style_footer();
459453
}
460454
461455
#if INTERFACE
462456
/* Flag parameters to compute_uses_file() */
463457
--- src/descendants.c
+++ src/descendants.c
@@ -447,16 +447,10 @@
447 db_prepare(&q, "%s ORDER BY event.mtime DESC", blob_str(&sql));
448 blob_reset(&sql);
449 www_print_timeline(&q, TIMELINE_LEAFONLY, 0, 0, 0);
450 db_finalize(&q);
451 @ <br />
452 @ <script type="text/JavaScript">
453 @ function xin(id){
454 @ }
455 @ function xout(id){
456 @ }
457 @ </script>
458 style_footer();
459 }
460
461 #if INTERFACE
462 /* Flag parameters to compute_uses_file() */
463
--- src/descendants.c
+++ src/descendants.c
@@ -447,16 +447,10 @@
447 db_prepare(&q, "%s ORDER BY event.mtime DESC", blob_str(&sql));
448 blob_reset(&sql);
449 www_print_timeline(&q, TIMELINE_LEAFONLY, 0, 0, 0);
450 db_finalize(&q);
451 @ <br />
 
 
 
 
 
 
452 style_footer();
453 }
454
455 #if INTERFACE
456 /* Flag parameters to compute_uses_file() */
457
+20 -3
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -774,11 +774,11 @@
774774
@ grid remove $sb
775775
@ }
776776
@ }
777777
@ enableSync x
778778
@ }
779
-@
779
+@
780780
@ proc sync-y {first last} {
781781
@ disableSync y
782782
@ foreach c [cols] {
783783
@ $c yview moveto $first
784784
@ }
@@ -793,10 +793,11 @@
793793
@
794794
@ wm withdraw .
795795
@ wm title . $CFG(TITLE)
796796
@ wm iconname . $CFG(TITLE)
797797
@ bind . <q> exit
798
+@ bind . <Destroy> {after 0 exit}
798799
@ bind . <Tab> {cycleDiffs; break}
799800
@ bind . <<PrevWindow>> {cycleDiffs 1; break}
800801
@ bind . <Return> {
801802
@ event generate .files <1>
802803
@ event generate .files <ButtonRelease-1>
@@ -907,13 +908,15 @@
907908
908909
/*
909910
** Show diff output in a Tcl/Tk window, in response to the --tk option
910911
** to the diff command.
911912
**
912
-** Steps:
913
+** If fossil has direct access to a Tcl interpreter (either loaded
914
+** dynamically through stubs or linked in statically), we can use it
915
+** directly. Otherwise:
913916
** (1) Write the Tcl/Tk script used for rendering into a temp file.
914
-** (2) Invoke "wish" on the temp file using fossil_system().
917
+** (2) Invoke "tclsh" on the temp file using fossil_system().
915918
** (3) Delete the temp file.
916919
*/
917920
void diff_tk(const char *zSubCmd, int firstArg){
918921
int i;
919922
Blob script;
@@ -943,10 +946,24 @@
943946
blob_appendf(&script, "}\n%s", zDiffScript);
944947
if( zTempFile ){
945948
blob_write_to_file(&script, zTempFile);
946949
fossil_print("To see diff, run: tclsh \"%s\"\n", zTempFile);
947950
}else{
951
+#if defined(FOSSIL_ENABLE_TCL)
952
+ Th_FossilInit(TH_INIT_DEFAULT);
953
+ if( evaluateTclWithEvents(g.interp, &g.tcl, blob_str(&script),
954
+ blob_size(&script), 1)==TCL_OK ){
955
+ blob_reset(&script);
956
+ return;
957
+ }
958
+ /*
959
+ * If evaluation of the Tcl script fails, the reason may be that Tk
960
+ * could not be found by the loaded Tcl, or that Tcl cannot be loaded
961
+ * dynamically (e.g. x64 Tcl with x86 Fossil). Therefore, fallback
962
+ * to using the external "tclsh", if available.
963
+ */
964
+#endif
948965
zTempFile = write_blob_to_temp_file(&script);
949966
zCmd = mprintf("tclsh \"%s\"", zTempFile);
950967
fossil_system(zCmd);
951968
file_delete(zTempFile);
952969
fossil_free(zCmd);
953970
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -774,11 +774,11 @@
774 @ grid remove $sb
775 @ }
776 @ }
777 @ enableSync x
778 @ }
779 @
780 @ proc sync-y {first last} {
781 @ disableSync y
782 @ foreach c [cols] {
783 @ $c yview moveto $first
784 @ }
@@ -793,10 +793,11 @@
793 @
794 @ wm withdraw .
795 @ wm title . $CFG(TITLE)
796 @ wm iconname . $CFG(TITLE)
797 @ bind . <q> exit
 
798 @ bind . <Tab> {cycleDiffs; break}
799 @ bind . <<PrevWindow>> {cycleDiffs 1; break}
800 @ bind . <Return> {
801 @ event generate .files <1>
802 @ event generate .files <ButtonRelease-1>
@@ -907,13 +908,15 @@
907
908 /*
909 ** Show diff output in a Tcl/Tk window, in response to the --tk option
910 ** to the diff command.
911 **
912 ** Steps:
 
 
913 ** (1) Write the Tcl/Tk script used for rendering into a temp file.
914 ** (2) Invoke "wish" on the temp file using fossil_system().
915 ** (3) Delete the temp file.
916 */
917 void diff_tk(const char *zSubCmd, int firstArg){
918 int i;
919 Blob script;
@@ -943,10 +946,24 @@
943 blob_appendf(&script, "}\n%s", zDiffScript);
944 if( zTempFile ){
945 blob_write_to_file(&script, zTempFile);
946 fossil_print("To see diff, run: tclsh \"%s\"\n", zTempFile);
947 }else{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
948 zTempFile = write_blob_to_temp_file(&script);
949 zCmd = mprintf("tclsh \"%s\"", zTempFile);
950 fossil_system(zCmd);
951 file_delete(zTempFile);
952 fossil_free(zCmd);
953
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -774,11 +774,11 @@
774 @ grid remove $sb
775 @ }
776 @ }
777 @ enableSync x
778 @ }
779 @
780 @ proc sync-y {first last} {
781 @ disableSync y
782 @ foreach c [cols] {
783 @ $c yview moveto $first
784 @ }
@@ -793,10 +793,11 @@
793 @
794 @ wm withdraw .
795 @ wm title . $CFG(TITLE)
796 @ wm iconname . $CFG(TITLE)
797 @ bind . <q> exit
798 @ bind . <Destroy> {after 0 exit}
799 @ bind . <Tab> {cycleDiffs; break}
800 @ bind . <<PrevWindow>> {cycleDiffs 1; break}
801 @ bind . <Return> {
802 @ event generate .files <1>
803 @ event generate .files <ButtonRelease-1>
@@ -907,13 +908,15 @@
908
909 /*
910 ** Show diff output in a Tcl/Tk window, in response to the --tk option
911 ** to the diff command.
912 **
913 ** If fossil has direct access to a Tcl interpreter (either loaded
914 ** dynamically through stubs or linked in statically), we can use it
915 ** directly. Otherwise:
916 ** (1) Write the Tcl/Tk script used for rendering into a temp file.
917 ** (2) Invoke "tclsh" on the temp file using fossil_system().
918 ** (3) Delete the temp file.
919 */
920 void diff_tk(const char *zSubCmd, int firstArg){
921 int i;
922 Blob script;
@@ -943,10 +946,24 @@
946 blob_appendf(&script, "}\n%s", zDiffScript);
947 if( zTempFile ){
948 blob_write_to_file(&script, zTempFile);
949 fossil_print("To see diff, run: tclsh \"%s\"\n", zTempFile);
950 }else{
951 #if defined(FOSSIL_ENABLE_TCL)
952 Th_FossilInit(TH_INIT_DEFAULT);
953 if( evaluateTclWithEvents(g.interp, &g.tcl, blob_str(&script),
954 blob_size(&script), 1)==TCL_OK ){
955 blob_reset(&script);
956 return;
957 }
958 /*
959 * If evaluation of the Tcl script fails, the reason may be that Tk
960 * could not be found by the loaded Tcl, or that Tcl cannot be loaded
961 * dynamically (e.g. x64 Tcl with x86 Fossil). Therefore, fallback
962 * to using the external "tclsh", if available.
963 */
964 #endif
965 zTempFile = write_blob_to_temp_file(&script);
966 zCmd = mprintf("tclsh \"%s\"", zTempFile);
967 fossil_system(zCmd);
968 file_delete(zTempFile);
969 fossil_free(zCmd);
970
+97 -23
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -173,10 +173,58 @@
173173
if( iBio!=NULL ){
174174
(void)BIO_reset(iBio);
175175
BIO_free_all(iBio);
176176
}
177177
}
178
+
179
+/* See RFC2817 for details */
180
+static int establish_proxy_tunnel(UrlData *pUrlData, BIO *bio){
181
+ int rc, httpVerMin;
182
+ char *bbuf;
183
+ Blob snd, reply;
184
+ int done=0,end=0;
185
+ blob_zero(&snd);
186
+ blob_appendf(&snd, "CONNECT %s:%d HTTP/1.1\r\n", pUrlData->hostname,
187
+ pUrlData->proxyOrigPort);
188
+ blob_appendf(&snd, "Host: %s:%d\r\n", pUrlData->hostname, pUrlData->proxyOrigPort);
189
+ if( pUrlData->proxyAuth ){
190
+ blob_appendf(&snd, "Proxy-Authorization: %s\r\n", pUrlData->proxyAuth);
191
+ }
192
+ blob_append(&snd, "Proxy-Connection: keep-alive\r\n", -1);
193
+ blob_appendf(&snd, "User-Agent: %s\r\n", get_user_agent());
194
+ blob_append(&snd, "\r\n", 2);
195
+ BIO_write(bio, blob_buffer(&snd), blob_size(&snd));
196
+ blob_reset(&snd);
197
+
198
+ /* Wait for end of reply */
199
+ blob_zero(&reply);
200
+ do{
201
+ int len;
202
+ char buf[256];
203
+ len = BIO_read(bio, buf, sizeof(buf));
204
+ blob_append(&reply, buf, len);
205
+
206
+ bbuf = blob_buffer(&reply);
207
+ len = blob_size(&reply);
208
+ while(end < len) {
209
+ if(bbuf[end] == '\r') {
210
+ if(len - end < 4) {
211
+ /* need more data */
212
+ break;
213
+ }
214
+ if(memcmp(&bbuf[end], "\r\n\r\n", 4) == 0) {
215
+ done = 1;
216
+ break;
217
+ }
218
+ }
219
+ end++;
220
+ }
221
+ }while(!done);
222
+ sscanf(bbuf, "HTTP/1.%d %d", &httpVerMin, &rc);
223
+ blob_reset(&reply);
224
+ return rc;
225
+}
178226
179227
/*
180228
** Open an SSL connection. The identify of the server is determined
181229
** by variables that are set using url_parse():
182230
**
@@ -201,41 +249,67 @@
201249
X509_STORE_add_cert(SSL_CTX_get_cert_store(sslCtx), cert);
202250
X509_free(cert);
203251
hasSavedCertificate = 1;
204252
}
205253
206
- iBio = BIO_new_ssl_connect(sslCtx);
254
+ if( pUrlData->useProxy ){
255
+ int rc;
256
+ BIO *sBio;
257
+ char *connStr;
258
+ connStr = mprintf("%s:%d", g.urlName, pUrlData->port);
259
+ sBio = BIO_new_connect(connStr);
260
+ free(connStr);
261
+ if( BIO_do_connect(sBio)<=0 ){
262
+ ssl_set_errmsg("SSL: cannot connect to proxy %s:%d (%s)",
263
+ pUrlData->name, pUrlData->port, ERR_reason_error_string(ERR_get_error()));
264
+ ssl_close();
265
+ return 1;
266
+ }
267
+ rc = establish_proxy_tunnel(pUrlData, sBio);
268
+ if( rc<200||rc>299 ){
269
+ ssl_set_errmsg("SSL: proxy connect failed with HTTP status code %d", rc);
270
+ return 1;
271
+ }
272
+
273
+ pUrlData->path = pUrlData->proxyUrlPath;
274
+
275
+ iBio = BIO_new_ssl(sslCtx, 1);
276
+ BIO_push(iBio, sBio);
277
+ }else{
278
+ iBio = BIO_new_ssl_connect(sslCtx);
279
+ }
280
+ if( iBio==NULL ) {
281
+ ssl_set_errmsg("SSL: cannot open SSL (%s)",
282
+ ERR_reason_error_string(ERR_get_error()));
283
+ return 1;
284
+ }
207285
BIO_get_ssl(iBio, &ssl);
208286
209287
#if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT)
210
- if( !SSL_set_tlsext_host_name(ssl, pUrlData->name) ){
288
+ if( !SSL_set_tlsext_host_name(ssl, (pUrlData->useProxy?pUrlData->hostname:pUrlData->name)) ){
211289
fossil_warning("WARNING: failed to set server name indication (SNI), "
212290
"continuing without it.\n");
213291
}
214292
#endif
215293
216294
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
217
- if( iBio==NULL ) {
218
- ssl_set_errmsg("SSL: cannot open SSL (%s)",
219
- ERR_reason_error_string(ERR_get_error()));
220
- return 1;
221
- }
222
-
223
- BIO_set_conn_hostname(iBio, pUrlData->name);
224
- BIO_set_conn_int_port(iBio, &pUrlData->port);
225
-
226
- if( BIO_do_connect(iBio)<=0 ){
227
- ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)",
228
- pUrlData->name, pUrlData->port,
229
- ERR_reason_error_string(ERR_get_error()));
230
- ssl_close();
231
- return 1;
295
+
296
+ if( !pUrlData->useProxy ){
297
+ BIO_set_conn_hostname(iBio, pUrlData->name);
298
+ BIO_set_conn_int_port(iBio, &pUrlData->port);
299
+ if( BIO_do_connect(iBio)<=0 ){
300
+ ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)",
301
+ pUrlData->name, pUrlData->port, ERR_reason_error_string(ERR_get_error()));
302
+ ssl_close();
303
+ return 1;
304
+ }
232305
}
233306
234307
if( BIO_do_handshake(iBio)<=0 ) {
235308
ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)",
236
- pUrlData->name, pUrlData->port,
309
+ pUrlData->useProxy?pUrlData->hostname:pUrlData->name,
310
+ pUrlData->useProxy?pUrlData->proxyOrigPort:pUrlData->port,
237311
ERR_reason_error_string(ERR_get_error()));
238312
ssl_close();
239313
return 1;
240314
}
241315
/* Check if certificate is valid */
@@ -283,11 +357,11 @@
283357
" certificates list\n\n"
284358
"If you are not expecting this message, answer no and "
285359
"contact your server\nadministrator.\n\n"
286360
"Accept certificate for host %s (a=always/y/N)? ",
287361
X509_verify_cert_error_string(e), desc, warning,
288
- pUrlData->name);
362
+ pUrlData->useProxy?pUrlData->hostname:pUrlData->name);
289363
BIO_free(mem);
290364
291365
prompt_user(prompt, &ans);
292366
free(prompt);
293367
cReply = blob_str(&ans)[0];
@@ -333,14 +407,14 @@
333407
334408
mem = BIO_new(BIO_s_mem());
335409
PEM_write_bio_X509(mem, cert);
336410
BIO_write(mem, "", 1); /* nul-terminate mem buffer */
337411
BIO_get_mem_data(mem, &zCert);
338
- zHost = mprintf("cert:%s", pUrlData->name);
412
+ zHost = mprintf("cert:%s", pUrlData->useProxy?pUrlData->hostname:pUrlData->name);
339413
db_set(zHost, zCert, 1);
340414
free(zHost);
341
- zHost = mprintf("trusted:%s", pUrlData->name);
415
+ zHost = mprintf("trusted:%s", pUrlData->useProxy?pUrlData->hostname:pUrlData->name);
342416
db_set_int(zHost, trusted, 1);
343417
free(zHost);
344418
BIO_free(mem);
345419
}
346420
@@ -351,18 +425,18 @@
351425
X509 *ssl_get_certificate(UrlData *pUrlData, int *pTrusted){
352426
char *zHost, *zCert;
353427
BIO *mem;
354428
X509 *cert;
355429
356
- zHost = mprintf("cert:%s", pUrlData->name);
430
+ zHost = mprintf("cert:%s", pUrlData->useProxy?pUrlData->hostname:pUrlData->name);
357431
zCert = db_get(zHost, NULL);
358432
free(zHost);
359433
if ( zCert==NULL )
360434
return NULL;
361435
362436
if ( pTrusted!=0 ){
363
- zHost = mprintf("trusted:%s", pUrlData->name);
437
+ zHost = mprintf("trusted:%s", pUrlData->useProxy?pUrlData->hostname:pUrlData->name);
364438
*pTrusted = db_get_int(zHost, 0);
365439
free(zHost);
366440
}
367441
368442
mem = BIO_new(BIO_s_mem());
369443
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -173,10 +173,58 @@
173 if( iBio!=NULL ){
174 (void)BIO_reset(iBio);
175 BIO_free_all(iBio);
176 }
177 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
179 /*
180 ** Open an SSL connection. The identify of the server is determined
181 ** by variables that are set using url_parse():
182 **
@@ -201,41 +249,67 @@
201 X509_STORE_add_cert(SSL_CTX_get_cert_store(sslCtx), cert);
202 X509_free(cert);
203 hasSavedCertificate = 1;
204 }
205
206 iBio = BIO_new_ssl_connect(sslCtx);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207 BIO_get_ssl(iBio, &ssl);
208
209 #if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT)
210 if( !SSL_set_tlsext_host_name(ssl, pUrlData->name) ){
211 fossil_warning("WARNING: failed to set server name indication (SNI), "
212 "continuing without it.\n");
213 }
214 #endif
215
216 SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
217 if( iBio==NULL ) {
218 ssl_set_errmsg("SSL: cannot open SSL (%s)",
219 ERR_reason_error_string(ERR_get_error()));
220 return 1;
221 }
222
223 BIO_set_conn_hostname(iBio, pUrlData->name);
224 BIO_set_conn_int_port(iBio, &pUrlData->port);
225
226 if( BIO_do_connect(iBio)<=0 ){
227 ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)",
228 pUrlData->name, pUrlData->port,
229 ERR_reason_error_string(ERR_get_error()));
230 ssl_close();
231 return 1;
232 }
233
234 if( BIO_do_handshake(iBio)<=0 ) {
235 ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)",
236 pUrlData->name, pUrlData->port,
 
237 ERR_reason_error_string(ERR_get_error()));
238 ssl_close();
239 return 1;
240 }
241 /* Check if certificate is valid */
@@ -283,11 +357,11 @@
283 " certificates list\n\n"
284 "If you are not expecting this message, answer no and "
285 "contact your server\nadministrator.\n\n"
286 "Accept certificate for host %s (a=always/y/N)? ",
287 X509_verify_cert_error_string(e), desc, warning,
288 pUrlData->name);
289 BIO_free(mem);
290
291 prompt_user(prompt, &ans);
292 free(prompt);
293 cReply = blob_str(&ans)[0];
@@ -333,14 +407,14 @@
333
334 mem = BIO_new(BIO_s_mem());
335 PEM_write_bio_X509(mem, cert);
336 BIO_write(mem, "", 1); /* nul-terminate mem buffer */
337 BIO_get_mem_data(mem, &zCert);
338 zHost = mprintf("cert:%s", pUrlData->name);
339 db_set(zHost, zCert, 1);
340 free(zHost);
341 zHost = mprintf("trusted:%s", pUrlData->name);
342 db_set_int(zHost, trusted, 1);
343 free(zHost);
344 BIO_free(mem);
345 }
346
@@ -351,18 +425,18 @@
351 X509 *ssl_get_certificate(UrlData *pUrlData, int *pTrusted){
352 char *zHost, *zCert;
353 BIO *mem;
354 X509 *cert;
355
356 zHost = mprintf("cert:%s", pUrlData->name);
357 zCert = db_get(zHost, NULL);
358 free(zHost);
359 if ( zCert==NULL )
360 return NULL;
361
362 if ( pTrusted!=0 ){
363 zHost = mprintf("trusted:%s", pUrlData->name);
364 *pTrusted = db_get_int(zHost, 0);
365 free(zHost);
366 }
367
368 mem = BIO_new(BIO_s_mem());
369
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -173,10 +173,58 @@
173 if( iBio!=NULL ){
174 (void)BIO_reset(iBio);
175 BIO_free_all(iBio);
176 }
177 }
178
179 /* See RFC2817 for details */
180 static int establish_proxy_tunnel(UrlData *pUrlData, BIO *bio){
181 int rc, httpVerMin;
182 char *bbuf;
183 Blob snd, reply;
184 int done=0,end=0;
185 blob_zero(&snd);
186 blob_appendf(&snd, "CONNECT %s:%d HTTP/1.1\r\n", pUrlData->hostname,
187 pUrlData->proxyOrigPort);
188 blob_appendf(&snd, "Host: %s:%d\r\n", pUrlData->hostname, pUrlData->proxyOrigPort);
189 if( pUrlData->proxyAuth ){
190 blob_appendf(&snd, "Proxy-Authorization: %s\r\n", pUrlData->proxyAuth);
191 }
192 blob_append(&snd, "Proxy-Connection: keep-alive\r\n", -1);
193 blob_appendf(&snd, "User-Agent: %s\r\n", get_user_agent());
194 blob_append(&snd, "\r\n", 2);
195 BIO_write(bio, blob_buffer(&snd), blob_size(&snd));
196 blob_reset(&snd);
197
198 /* Wait for end of reply */
199 blob_zero(&reply);
200 do{
201 int len;
202 char buf[256];
203 len = BIO_read(bio, buf, sizeof(buf));
204 blob_append(&reply, buf, len);
205
206 bbuf = blob_buffer(&reply);
207 len = blob_size(&reply);
208 while(end < len) {
209 if(bbuf[end] == '\r') {
210 if(len - end < 4) {
211 /* need more data */
212 break;
213 }
214 if(memcmp(&bbuf[end], "\r\n\r\n", 4) == 0) {
215 done = 1;
216 break;
217 }
218 }
219 end++;
220 }
221 }while(!done);
222 sscanf(bbuf, "HTTP/1.%d %d", &httpVerMin, &rc);
223 blob_reset(&reply);
224 return rc;
225 }
226
227 /*
228 ** Open an SSL connection. The identify of the server is determined
229 ** by variables that are set using url_parse():
230 **
@@ -201,41 +249,67 @@
249 X509_STORE_add_cert(SSL_CTX_get_cert_store(sslCtx), cert);
250 X509_free(cert);
251 hasSavedCertificate = 1;
252 }
253
254 if( pUrlData->useProxy ){
255 int rc;
256 BIO *sBio;
257 char *connStr;
258 connStr = mprintf("%s:%d", g.urlName, pUrlData->port);
259 sBio = BIO_new_connect(connStr);
260 free(connStr);
261 if( BIO_do_connect(sBio)<=0 ){
262 ssl_set_errmsg("SSL: cannot connect to proxy %s:%d (%s)",
263 pUrlData->name, pUrlData->port, ERR_reason_error_string(ERR_get_error()));
264 ssl_close();
265 return 1;
266 }
267 rc = establish_proxy_tunnel(pUrlData, sBio);
268 if( rc<200||rc>299 ){
269 ssl_set_errmsg("SSL: proxy connect failed with HTTP status code %d", rc);
270 return 1;
271 }
272
273 pUrlData->path = pUrlData->proxyUrlPath;
274
275 iBio = BIO_new_ssl(sslCtx, 1);
276 BIO_push(iBio, sBio);
277 }else{
278 iBio = BIO_new_ssl_connect(sslCtx);
279 }
280 if( iBio==NULL ) {
281 ssl_set_errmsg("SSL: cannot open SSL (%s)",
282 ERR_reason_error_string(ERR_get_error()));
283 return 1;
284 }
285 BIO_get_ssl(iBio, &ssl);
286
287 #if (SSLEAY_VERSION_NUMBER >= 0x00908070) && !defined(OPENSSL_NO_TLSEXT)
288 if( !SSL_set_tlsext_host_name(ssl, (pUrlData->useProxy?pUrlData->hostname:pUrlData->name)) ){
289 fossil_warning("WARNING: failed to set server name indication (SNI), "
290 "continuing without it.\n");
291 }
292 #endif
293
294 SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
295
296 if( !pUrlData->useProxy ){
297 BIO_set_conn_hostname(iBio, pUrlData->name);
298 BIO_set_conn_int_port(iBio, &pUrlData->port);
299 if( BIO_do_connect(iBio)<=0 ){
300 ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)",
301 pUrlData->name, pUrlData->port, ERR_reason_error_string(ERR_get_error()));
302 ssl_close();
303 return 1;
304 }
 
 
 
 
 
305 }
306
307 if( BIO_do_handshake(iBio)<=0 ) {
308 ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)",
309 pUrlData->useProxy?pUrlData->hostname:pUrlData->name,
310 pUrlData->useProxy?pUrlData->proxyOrigPort:pUrlData->port,
311 ERR_reason_error_string(ERR_get_error()));
312 ssl_close();
313 return 1;
314 }
315 /* Check if certificate is valid */
@@ -283,11 +357,11 @@
357 " certificates list\n\n"
358 "If you are not expecting this message, answer no and "
359 "contact your server\nadministrator.\n\n"
360 "Accept certificate for host %s (a=always/y/N)? ",
361 X509_verify_cert_error_string(e), desc, warning,
362 pUrlData->useProxy?pUrlData->hostname:pUrlData->name);
363 BIO_free(mem);
364
365 prompt_user(prompt, &ans);
366 free(prompt);
367 cReply = blob_str(&ans)[0];
@@ -333,14 +407,14 @@
407
408 mem = BIO_new(BIO_s_mem());
409 PEM_write_bio_X509(mem, cert);
410 BIO_write(mem, "", 1); /* nul-terminate mem buffer */
411 BIO_get_mem_data(mem, &zCert);
412 zHost = mprintf("cert:%s", pUrlData->useProxy?pUrlData->hostname:pUrlData->name);
413 db_set(zHost, zCert, 1);
414 free(zHost);
415 zHost = mprintf("trusted:%s", pUrlData->useProxy?pUrlData->hostname:pUrlData->name);
416 db_set_int(zHost, trusted, 1);
417 free(zHost);
418 BIO_free(mem);
419 }
420
@@ -351,18 +425,18 @@
425 X509 *ssl_get_certificate(UrlData *pUrlData, int *pTrusted){
426 char *zHost, *zCert;
427 BIO *mem;
428 X509 *cert;
429
430 zHost = mprintf("cert:%s", pUrlData->useProxy?pUrlData->hostname:pUrlData->name);
431 zCert = db_get(zHost, NULL);
432 free(zHost);
433 if ( zCert==NULL )
434 return NULL;
435
436 if ( pTrusted!=0 ){
437 zHost = mprintf("trusted:%s", pUrlData->useProxy?pUrlData->hostname:pUrlData->name);
438 *pTrusted = db_get_int(zHost, 0);
439 free(zHost);
440 }
441
442 mem = BIO_new(BIO_s_mem());
443
+9 -6
--- src/info.c
+++ src/info.c
@@ -933,16 +933,16 @@
933933
** WEBPAGE: vdiff
934934
** URL: /vdiff
935935
**
936936
** Query parameters:
937937
**
938
-** from=TAG
939
-** to=TAG
940
-** branch=TAG
941
-** v=BOOLEAN
942
-** sbs=BOOLEAN
943
-** glob=STRING only diff files matching this glob
938
+** from=TAG Left side of the comparison
939
+** to=TAG Right side of the comparison
940
+** branch=TAG Show all changes on a particular branch
941
+** v=BOOLEAN Default true. If false, only list files that have changed
942
+** sbs=BOOLEAN Side-by-side diff if true. Unified diff if false
943
+** glob=STRING only diff files matching this glob
944944
**
945945
**
946946
** Show all differences between two checkins.
947947
*/
948948
void vdiff_page(void){
@@ -1013,10 +1013,13 @@
10131013
zGlob ? "&glob=" : "", zGlob ? zGlob : "");
10141014
if( zGlob ){
10151015
style_submenu_element("Clear glob", "clearglob",
10161016
"%R/vdiff?from=%T&to=%T&sbs=%d%s", zFrom, zTo,
10171017
sideBySide, (verboseFlag && !sideBySide)?"&v":"");
1018
+ }else{
1019
+ style_submenu_element("Patch", "patch",
1020
+ "%R/vpatch?from=%T&to=%T", zFrom, zTo);
10181021
}
10191022
style_header("Check-in Differences");
10201023
@ <h2>Difference From:</h2><blockquote>
10211024
checkin_description(ridFrom);
10221025
@ </blockquote><h2>To:</h2><blockquote>
10231026
--- src/info.c
+++ src/info.c
@@ -933,16 +933,16 @@
933 ** WEBPAGE: vdiff
934 ** URL: /vdiff
935 **
936 ** Query parameters:
937 **
938 ** from=TAG
939 ** to=TAG
940 ** branch=TAG
941 ** v=BOOLEAN
942 ** sbs=BOOLEAN
943 ** glob=STRING only diff files matching this glob
944 **
945 **
946 ** Show all differences between two checkins.
947 */
948 void vdiff_page(void){
@@ -1013,10 +1013,13 @@
1013 zGlob ? "&glob=" : "", zGlob ? zGlob : "");
1014 if( zGlob ){
1015 style_submenu_element("Clear glob", "clearglob",
1016 "%R/vdiff?from=%T&to=%T&sbs=%d%s", zFrom, zTo,
1017 sideBySide, (verboseFlag && !sideBySide)?"&v":"");
 
 
 
1018 }
1019 style_header("Check-in Differences");
1020 @ <h2>Difference From:</h2><blockquote>
1021 checkin_description(ridFrom);
1022 @ </blockquote><h2>To:</h2><blockquote>
1023
--- src/info.c
+++ src/info.c
@@ -933,16 +933,16 @@
933 ** WEBPAGE: vdiff
934 ** URL: /vdiff
935 **
936 ** Query parameters:
937 **
938 ** from=TAG Left side of the comparison
939 ** to=TAG Right side of the comparison
940 ** branch=TAG Show all changes on a particular branch
941 ** v=BOOLEAN Default true. If false, only list files that have changed
942 ** sbs=BOOLEAN Side-by-side diff if true. Unified diff if false
943 ** glob=STRING only diff files matching this glob
944 **
945 **
946 ** Show all differences between two checkins.
947 */
948 void vdiff_page(void){
@@ -1013,10 +1013,13 @@
1013 zGlob ? "&glob=" : "", zGlob ? zGlob : "");
1014 if( zGlob ){
1015 style_submenu_element("Clear glob", "clearglob",
1016 "%R/vdiff?from=%T&to=%T&sbs=%d%s", zFrom, zTo,
1017 sideBySide, (verboseFlag && !sideBySide)?"&v":"");
1018 }else{
1019 style_submenu_element("Patch", "patch",
1020 "%R/vpatch?from=%T&to=%T", zFrom, zTo);
1021 }
1022 style_header("Check-in Differences");
1023 @ <h2>Difference From:</h2><blockquote>
1024 checkin_description(ridFrom);
1025 @ </blockquote><h2>To:</h2><blockquote>
1026
+1 -1
--- src/login.c
+++ src/login.c
@@ -599,11 +599,11 @@
599599
@ <td></td>
600600
@ <td><input type="submit" name="in" value="Login"
601601
@ onClick="chngAction(this.form)" /></td>
602602
@ </tr>
603603
@ </table>
604
- @ <script type="text/JavaScript">
604
+ @ <script>
605605
@ gebi('u').focus()
606606
@ function chngAction(form){
607607
if( g.sslNotAvailable==0
608608
&& strncmp(g.zBaseURL,"https:",6)!=0
609609
&& db_get_boolean("https-login",0)
610610
--- src/login.c
+++ src/login.c
@@ -599,11 +599,11 @@
599 @ <td></td>
600 @ <td><input type="submit" name="in" value="Login"
601 @ onClick="chngAction(this.form)" /></td>
602 @ </tr>
603 @ </table>
604 @ <script type="text/JavaScript">
605 @ gebi('u').focus()
606 @ function chngAction(form){
607 if( g.sslNotAvailable==0
608 && strncmp(g.zBaseURL,"https:",6)!=0
609 && db_get_boolean("https-login",0)
610
--- src/login.c
+++ src/login.c
@@ -599,11 +599,11 @@
599 @ <td></td>
600 @ <td><input type="submit" name="in" value="Login"
601 @ onClick="chngAction(this.form)" /></td>
602 @ </tr>
603 @ </table>
604 @ <script>
605 @ gebi('u').focus()
606 @ function chngAction(form){
607 if( g.sslNotAvailable==0
608 && strncmp(g.zBaseURL,"https:",6)!=0
609 && db_get_boolean("https-login",0)
610
+3 -1
--- src/main.c
+++ src/main.c
@@ -190,11 +190,13 @@
190190
char *urlPasswd; /* Password for http: */
191191
char *urlCanonical; /* Canonical representation of the URL */
192192
char *urlProxyAuth; /* Proxy-Authorizer: string */
193193
char *urlFossil; /* The fossil query parameter on ssh: */
194194
unsigned urlFlags; /* Boolean flags controlling URL processing */
195
-
195
+ int useProxy; /* Used to remember that a proxy is in use */
196
+ char *proxyUrlPath;
197
+ int proxyOrigPort; /* Tunneled port number for https through proxy */
196198
const char *zLogin; /* Login name. "" if not logged in. */
197199
const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
198200
** SSL client identity */
199201
int useLocalauth; /* No login required if from 127.0.0.1 */
200202
int noPswd; /* Logged in without password (on 127.0.0.1) */
201203
--- src/main.c
+++ src/main.c
@@ -190,11 +190,13 @@
190 char *urlPasswd; /* Password for http: */
191 char *urlCanonical; /* Canonical representation of the URL */
192 char *urlProxyAuth; /* Proxy-Authorizer: string */
193 char *urlFossil; /* The fossil query parameter on ssh: */
194 unsigned urlFlags; /* Boolean flags controlling URL processing */
195
 
 
196 const char *zLogin; /* Login name. "" if not logged in. */
197 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
198 ** SSL client identity */
199 int useLocalauth; /* No login required if from 127.0.0.1 */
200 int noPswd; /* Logged in without password (on 127.0.0.1) */
201
--- src/main.c
+++ src/main.c
@@ -190,11 +190,13 @@
190 char *urlPasswd; /* Password for http: */
191 char *urlCanonical; /* Canonical representation of the URL */
192 char *urlProxyAuth; /* Proxy-Authorizer: string */
193 char *urlFossil; /* The fossil query parameter on ssh: */
194 unsigned urlFlags; /* Boolean flags controlling URL processing */
195 int useProxy; /* Used to remember that a proxy is in use */
196 char *proxyUrlPath;
197 int proxyOrigPort; /* Tunneled port number for https through proxy */
198 const char *zLogin; /* Login name. "" if not logged in. */
199 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
200 ** SSL client identity */
201 int useLocalauth; /* No login required if from 127.0.0.1 */
202 int noPswd; /* Logged in without password (on 127.0.0.1) */
203
+3 -1
--- src/main.c
+++ src/main.c
@@ -190,11 +190,13 @@
190190
char *urlPasswd; /* Password for http: */
191191
char *urlCanonical; /* Canonical representation of the URL */
192192
char *urlProxyAuth; /* Proxy-Authorizer: string */
193193
char *urlFossil; /* The fossil query parameter on ssh: */
194194
unsigned urlFlags; /* Boolean flags controlling URL processing */
195
-
195
+ int useProxy; /* Used to remember that a proxy is in use */
196
+ char *proxyUrlPath;
197
+ int proxyOrigPort; /* Tunneled port number for https through proxy */
196198
const char *zLogin; /* Login name. "" if not logged in. */
197199
const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
198200
** SSL client identity */
199201
int useLocalauth; /* No login required if from 127.0.0.1 */
200202
int noPswd; /* Logged in without password (on 127.0.0.1) */
201203
--- src/main.c
+++ src/main.c
@@ -190,11 +190,13 @@
190 char *urlPasswd; /* Password for http: */
191 char *urlCanonical; /* Canonical representation of the URL */
192 char *urlProxyAuth; /* Proxy-Authorizer: string */
193 char *urlFossil; /* The fossil query parameter on ssh: */
194 unsigned urlFlags; /* Boolean flags controlling URL processing */
195
 
 
196 const char *zLogin; /* Login name. "" if not logged in. */
197 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
198 ** SSL client identity */
199 int useLocalauth; /* No login required if from 127.0.0.1 */
200 int noPswd; /* Logged in without password (on 127.0.0.1) */
201
--- src/main.c
+++ src/main.c
@@ -190,11 +190,13 @@
190 char *urlPasswd; /* Password for http: */
191 char *urlCanonical; /* Canonical representation of the URL */
192 char *urlProxyAuth; /* Proxy-Authorizer: string */
193 char *urlFossil; /* The fossil query parameter on ssh: */
194 unsigned urlFlags; /* Boolean flags controlling URL processing */
195 int useProxy; /* Used to remember that a proxy is in use */
196 char *proxyUrlPath;
197 int proxyOrigPort; /* Tunneled port number for https through proxy */
198 const char *zLogin; /* Login name. "" if not logged in. */
199 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
200 ** SSL client identity */
201 int useLocalauth; /* No login required if from 127.0.0.1 */
202 int noPswd; /* Logged in without password (on 127.0.0.1) */
203
+15 -15
--- src/name.c
+++ src/name.c
@@ -17,11 +17,11 @@
1717
**
1818
** This file contains code used to convert user-supplied object names into
1919
** canonical UUIDs.
2020
**
2121
** A user-supplied object name is any unique prefix of a valid UUID but
22
-** not necessarily in canonical form.
22
+** not necessarily in canonical form.
2323
*/
2424
#include "config.h"
2525
#include "name.h"
2626
#include <assert.h>
2727
@@ -50,11 +50,11 @@
5050
**
5151
** * SHA1 hash
5252
** * SHA1 hash prefix of at least 4 characters
5353
** * Symbolic Name
5454
** * "tag:" + symbolic name
55
-** * Date or date-time
55
+** * Date or date-time
5656
** * "date:" + Date or date-time
5757
** * symbolic-name ":" date-time
5858
** * "tip"
5959
**
6060
** The following additional forms are available in local checkouts:
@@ -64,11 +64,11 @@
6464
** * "next"
6565
**
6666
** Return the RID of the matching artifact. Or return 0 if the name does not
6767
** match any known object. Or return -1 if the name is ambiguous.
6868
**
69
-** The zType parameter specifies the type of artifact: ci, t, w, e, g.
69
+** The zType parameter specifies the type of artifact: ci, t, w, e, g.
7070
** If zType is NULL or "" or "*" then any type of artifact will serve.
7171
** zType is "ci" in most use cases since we are usually searching for
7272
** a check-in.
7373
*/
7474
int symbolic_name_to_rid(const char *zTag, const char *zType){
@@ -93,11 +93,11 @@
9393
9494
/* special keywords: "prev", "previous", "current", and "next" */
9595
if( g.localOpen && (vid=db_lget_int("checkout",0))!=0 ){
9696
if( fossil_strcmp(zTag, "current")==0 ){
9797
rid = vid;
98
- }else if( fossil_strcmp(zTag, "prev")==0
98
+ }else if( fossil_strcmp(zTag, "prev")==0
9999
|| fossil_strcmp(zTag, "previous")==0 ){
100100
rid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", vid);
101101
}else if( fossil_strcmp(zTag, "next")==0 ){
102102
rid = db_int(0, "SELECT cid FROM plink WHERE pid=%d"
103103
" ORDER BY isprim DESC, mtime DESC", vid);
@@ -105,19 +105,19 @@
105105
if( rid ) return rid;
106106
}
107107
108108
/* Date and times */
109109
if( memcmp(zTag, "date:", 5)==0 ){
110
- rid = db_int(0,
110
+ rid = db_int(0,
111111
"SELECT objid FROM event"
112112
" WHERE mtime<=julianday(%Q,'utc') AND type GLOB '%q'"
113113
" ORDER BY mtime DESC LIMIT 1",
114114
&zTag[5], zType);
115115
return rid;
116116
}
117117
if( fossil_isdate(zTag) ){
118
- rid = db_int(0,
118
+ rid = db_int(0,
119119
"SELECT objid FROM event"
120120
" WHERE mtime<=julianday(%Q,'utc') AND type GLOB '%q'"
121121
" ORDER BY mtime DESC LIMIT 1",
122122
zTag, zType);
123123
if( rid) return rid;
@@ -124,19 +124,19 @@
124124
}
125125
126126
/* Deprecated date & time formats: "local:" + date-time and
127127
** "utc:" + date-time */
128128
if( memcmp(zTag, "local:", 6)==0 ){
129
- rid = db_int(0,
129
+ rid = db_int(0,
130130
"SELECT objid FROM event"
131131
" WHERE mtime<=julianday(%Q) AND type GLOB '%q'"
132132
" ORDER BY mtime DESC LIMIT 1",
133133
&zTag[6], zType);
134134
return rid;
135135
}
136136
if( memcmp(zTag, "utc:", 4)==0 ){
137
- rid = db_int(0,
137
+ rid = db_int(0,
138138
"SELECT objid FROM event"
139139
" WHERE mtime<=julianday('%qz') AND type GLOB '%q'"
140140
" ORDER BY mtime DESC LIMIT 1",
141141
&zTag[4], zType);
142142
return rid;
@@ -153,11 +153,11 @@
153153
" AND event.type GLOB '%q'",
154154
&zTag[4], zType
155155
);
156156
return rid;
157157
}
158
-
158
+
159159
/* root:TAG -> The origin of the branch */
160160
if( memcmp(zTag, "root:", 5)==0 ){
161161
Stmt q;
162162
int rc;
163163
char *zBr;
@@ -255,11 +255,11 @@
255255
for(i=0; fossil_isdigit(zTag[i]); i++){}
256256
if( zTag[i]==0 ){
257257
if( strcmp(zType,"*")==0 ){
258258
rid = atoi(zTag);
259259
}else{
260
- rid = db_int(0,
260
+ rid = db_int(0,
261261
"SELECT event.objid"
262262
" FROM event"
263263
" WHERE event.objid=%s"
264264
" AND event.type GLOB '%q'", zTag, zType);
265265
}
@@ -278,12 +278,12 @@
278278
** the name as a tag. If multiple tags match, pick the latest.
279279
** If the input name matches "tag:*" then always resolve as a tag.
280280
**
281281
** If the input is not a tag, then try to match it as an ISO-8601 date
282282
** string YYYY-MM-DD HH:MM:SS and pick the nearest check-in to that date.
283
-** If the input is of the form "date:*" or "localtime:*" or "utc:*" then
284
-** always resolve the name as a date.
283
+** If the input is of the form "date:*" then always resolve the name as
284
+** a date. The forms "utc:*" and "local:" are deprecated.
285285
**
286286
** Return 0 on success. Return 1 if the name cannot be resolved.
287287
** Return 2 name is ambiguous.
288288
*/
289289
int name_to_uuid(Blob *pName, int iErrPriority, const char *zType){
@@ -379,20 +379,20 @@
379379
}
380380
381381
/*
382382
** WEBPAGE: ambiguous
383383
** URL: /ambiguous?name=UUID&src=WEBPAGE
384
-**
384
+**
385385
** The UUID given by the name parameter is ambiguous. Display a page
386386
** that shows all possible choices and let the user select between them.
387387
*/
388388
void ambiguous_page(void){
389389
Stmt q;
390
- const char *zName = P("name");
390
+ const char *zName = P("name");
391391
const char *zSrc = P("src");
392392
char *z;
393
-
393
+
394394
if( zName==0 || zName[0]==0 || zSrc==0 || zSrc[0]==0 ){
395395
fossil_redirect_home();
396396
}
397397
style_header("Ambiguous Artifact ID");
398398
@ <p>The artifact id <b>%h(zName)</b> is ambiguous and might
399399
--- src/name.c
+++ src/name.c
@@ -17,11 +17,11 @@
17 **
18 ** This file contains code used to convert user-supplied object names into
19 ** canonical UUIDs.
20 **
21 ** A user-supplied object name is any unique prefix of a valid UUID but
22 ** not necessarily in canonical form.
23 */
24 #include "config.h"
25 #include "name.h"
26 #include <assert.h>
27
@@ -50,11 +50,11 @@
50 **
51 ** * SHA1 hash
52 ** * SHA1 hash prefix of at least 4 characters
53 ** * Symbolic Name
54 ** * "tag:" + symbolic name
55 ** * Date or date-time
56 ** * "date:" + Date or date-time
57 ** * symbolic-name ":" date-time
58 ** * "tip"
59 **
60 ** The following additional forms are available in local checkouts:
@@ -64,11 +64,11 @@
64 ** * "next"
65 **
66 ** Return the RID of the matching artifact. Or return 0 if the name does not
67 ** match any known object. Or return -1 if the name is ambiguous.
68 **
69 ** The zType parameter specifies the type of artifact: ci, t, w, e, g.
70 ** If zType is NULL or "" or "*" then any type of artifact will serve.
71 ** zType is "ci" in most use cases since we are usually searching for
72 ** a check-in.
73 */
74 int symbolic_name_to_rid(const char *zTag, const char *zType){
@@ -93,11 +93,11 @@
93
94 /* special keywords: "prev", "previous", "current", and "next" */
95 if( g.localOpen && (vid=db_lget_int("checkout",0))!=0 ){
96 if( fossil_strcmp(zTag, "current")==0 ){
97 rid = vid;
98 }else if( fossil_strcmp(zTag, "prev")==0
99 || fossil_strcmp(zTag, "previous")==0 ){
100 rid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", vid);
101 }else if( fossil_strcmp(zTag, "next")==0 ){
102 rid = db_int(0, "SELECT cid FROM plink WHERE pid=%d"
103 " ORDER BY isprim DESC, mtime DESC", vid);
@@ -105,19 +105,19 @@
105 if( rid ) return rid;
106 }
107
108 /* Date and times */
109 if( memcmp(zTag, "date:", 5)==0 ){
110 rid = db_int(0,
111 "SELECT objid FROM event"
112 " WHERE mtime<=julianday(%Q,'utc') AND type GLOB '%q'"
113 " ORDER BY mtime DESC LIMIT 1",
114 &zTag[5], zType);
115 return rid;
116 }
117 if( fossil_isdate(zTag) ){
118 rid = db_int(0,
119 "SELECT objid FROM event"
120 " WHERE mtime<=julianday(%Q,'utc') AND type GLOB '%q'"
121 " ORDER BY mtime DESC LIMIT 1",
122 zTag, zType);
123 if( rid) return rid;
@@ -124,19 +124,19 @@
124 }
125
126 /* Deprecated date & time formats: "local:" + date-time and
127 ** "utc:" + date-time */
128 if( memcmp(zTag, "local:", 6)==0 ){
129 rid = db_int(0,
130 "SELECT objid FROM event"
131 " WHERE mtime<=julianday(%Q) AND type GLOB '%q'"
132 " ORDER BY mtime DESC LIMIT 1",
133 &zTag[6], zType);
134 return rid;
135 }
136 if( memcmp(zTag, "utc:", 4)==0 ){
137 rid = db_int(0,
138 "SELECT objid FROM event"
139 " WHERE mtime<=julianday('%qz') AND type GLOB '%q'"
140 " ORDER BY mtime DESC LIMIT 1",
141 &zTag[4], zType);
142 return rid;
@@ -153,11 +153,11 @@
153 " AND event.type GLOB '%q'",
154 &zTag[4], zType
155 );
156 return rid;
157 }
158
159 /* root:TAG -> The origin of the branch */
160 if( memcmp(zTag, "root:", 5)==0 ){
161 Stmt q;
162 int rc;
163 char *zBr;
@@ -255,11 +255,11 @@
255 for(i=0; fossil_isdigit(zTag[i]); i++){}
256 if( zTag[i]==0 ){
257 if( strcmp(zType,"*")==0 ){
258 rid = atoi(zTag);
259 }else{
260 rid = db_int(0,
261 "SELECT event.objid"
262 " FROM event"
263 " WHERE event.objid=%s"
264 " AND event.type GLOB '%q'", zTag, zType);
265 }
@@ -278,12 +278,12 @@
278 ** the name as a tag. If multiple tags match, pick the latest.
279 ** If the input name matches "tag:*" then always resolve as a tag.
280 **
281 ** If the input is not a tag, then try to match it as an ISO-8601 date
282 ** string YYYY-MM-DD HH:MM:SS and pick the nearest check-in to that date.
283 ** If the input is of the form "date:*" or "localtime:*" or "utc:*" then
284 ** always resolve the name as a date.
285 **
286 ** Return 0 on success. Return 1 if the name cannot be resolved.
287 ** Return 2 name is ambiguous.
288 */
289 int name_to_uuid(Blob *pName, int iErrPriority, const char *zType){
@@ -379,20 +379,20 @@
379 }
380
381 /*
382 ** WEBPAGE: ambiguous
383 ** URL: /ambiguous?name=UUID&src=WEBPAGE
384 **
385 ** The UUID given by the name parameter is ambiguous. Display a page
386 ** that shows all possible choices and let the user select between them.
387 */
388 void ambiguous_page(void){
389 Stmt q;
390 const char *zName = P("name");
391 const char *zSrc = P("src");
392 char *z;
393
394 if( zName==0 || zName[0]==0 || zSrc==0 || zSrc[0]==0 ){
395 fossil_redirect_home();
396 }
397 style_header("Ambiguous Artifact ID");
398 @ <p>The artifact id <b>%h(zName)</b> is ambiguous and might
399
--- src/name.c
+++ src/name.c
@@ -17,11 +17,11 @@
17 **
18 ** This file contains code used to convert user-supplied object names into
19 ** canonical UUIDs.
20 **
21 ** A user-supplied object name is any unique prefix of a valid UUID but
22 ** not necessarily in canonical form.
23 */
24 #include "config.h"
25 #include "name.h"
26 #include <assert.h>
27
@@ -50,11 +50,11 @@
50 **
51 ** * SHA1 hash
52 ** * SHA1 hash prefix of at least 4 characters
53 ** * Symbolic Name
54 ** * "tag:" + symbolic name
55 ** * Date or date-time
56 ** * "date:" + Date or date-time
57 ** * symbolic-name ":" date-time
58 ** * "tip"
59 **
60 ** The following additional forms are available in local checkouts:
@@ -64,11 +64,11 @@
64 ** * "next"
65 **
66 ** Return the RID of the matching artifact. Or return 0 if the name does not
67 ** match any known object. Or return -1 if the name is ambiguous.
68 **
69 ** The zType parameter specifies the type of artifact: ci, t, w, e, g.
70 ** If zType is NULL or "" or "*" then any type of artifact will serve.
71 ** zType is "ci" in most use cases since we are usually searching for
72 ** a check-in.
73 */
74 int symbolic_name_to_rid(const char *zTag, const char *zType){
@@ -93,11 +93,11 @@
93
94 /* special keywords: "prev", "previous", "current", and "next" */
95 if( g.localOpen && (vid=db_lget_int("checkout",0))!=0 ){
96 if( fossil_strcmp(zTag, "current")==0 ){
97 rid = vid;
98 }else if( fossil_strcmp(zTag, "prev")==0
99 || fossil_strcmp(zTag, "previous")==0 ){
100 rid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", vid);
101 }else if( fossil_strcmp(zTag, "next")==0 ){
102 rid = db_int(0, "SELECT cid FROM plink WHERE pid=%d"
103 " ORDER BY isprim DESC, mtime DESC", vid);
@@ -105,19 +105,19 @@
105 if( rid ) return rid;
106 }
107
108 /* Date and times */
109 if( memcmp(zTag, "date:", 5)==0 ){
110 rid = db_int(0,
111 "SELECT objid FROM event"
112 " WHERE mtime<=julianday(%Q,'utc') AND type GLOB '%q'"
113 " ORDER BY mtime DESC LIMIT 1",
114 &zTag[5], zType);
115 return rid;
116 }
117 if( fossil_isdate(zTag) ){
118 rid = db_int(0,
119 "SELECT objid FROM event"
120 " WHERE mtime<=julianday(%Q,'utc') AND type GLOB '%q'"
121 " ORDER BY mtime DESC LIMIT 1",
122 zTag, zType);
123 if( rid) return rid;
@@ -124,19 +124,19 @@
124 }
125
126 /* Deprecated date & time formats: "local:" + date-time and
127 ** "utc:" + date-time */
128 if( memcmp(zTag, "local:", 6)==0 ){
129 rid = db_int(0,
130 "SELECT objid FROM event"
131 " WHERE mtime<=julianday(%Q) AND type GLOB '%q'"
132 " ORDER BY mtime DESC LIMIT 1",
133 &zTag[6], zType);
134 return rid;
135 }
136 if( memcmp(zTag, "utc:", 4)==0 ){
137 rid = db_int(0,
138 "SELECT objid FROM event"
139 " WHERE mtime<=julianday('%qz') AND type GLOB '%q'"
140 " ORDER BY mtime DESC LIMIT 1",
141 &zTag[4], zType);
142 return rid;
@@ -153,11 +153,11 @@
153 " AND event.type GLOB '%q'",
154 &zTag[4], zType
155 );
156 return rid;
157 }
158
159 /* root:TAG -> The origin of the branch */
160 if( memcmp(zTag, "root:", 5)==0 ){
161 Stmt q;
162 int rc;
163 char *zBr;
@@ -255,11 +255,11 @@
255 for(i=0; fossil_isdigit(zTag[i]); i++){}
256 if( zTag[i]==0 ){
257 if( strcmp(zType,"*")==0 ){
258 rid = atoi(zTag);
259 }else{
260 rid = db_int(0,
261 "SELECT event.objid"
262 " FROM event"
263 " WHERE event.objid=%s"
264 " AND event.type GLOB '%q'", zTag, zType);
265 }
@@ -278,12 +278,12 @@
278 ** the name as a tag. If multiple tags match, pick the latest.
279 ** If the input name matches "tag:*" then always resolve as a tag.
280 **
281 ** If the input is not a tag, then try to match it as an ISO-8601 date
282 ** string YYYY-MM-DD HH:MM:SS and pick the nearest check-in to that date.
283 ** If the input is of the form "date:*" then always resolve the name as
284 ** a date. The forms "utc:*" and "local:" are deprecated.
285 **
286 ** Return 0 on success. Return 1 if the name cannot be resolved.
287 ** Return 2 name is ambiguous.
288 */
289 int name_to_uuid(Blob *pName, int iErrPriority, const char *zType){
@@ -379,20 +379,20 @@
379 }
380
381 /*
382 ** WEBPAGE: ambiguous
383 ** URL: /ambiguous?name=UUID&src=WEBPAGE
384 **
385 ** The UUID given by the name parameter is ambiguous. Display a page
386 ** that shows all possible choices and let the user select between them.
387 */
388 void ambiguous_page(void){
389 Stmt q;
390 const char *zName = P("name");
391 const char *zSrc = P("src");
392 char *z;
393
394 if( zName==0 || zName[0]==0 || zSrc==0 || zSrc[0]==0 ){
395 fossil_redirect_home();
396 }
397 style_header("Ambiguous Artifact ID");
398 @ <p>The artifact id <b>%h(zName)</b> is ambiguous and might
399
+14 -13
--- src/rebuild.c
+++ src/rebuild.c
@@ -861,23 +861,24 @@
861861
zUtf8Name = fossil_filename_to_utf8(pEntry->d_name);
862862
zSubpath = mprintf("%s/%s", zPath, zUtf8Name);
863863
fossil_filename_free(zUtf8Name);
864864
if( file_isdir(zSubpath)==1 ){
865865
recon_read_dir(zSubpath);
866
- }
867
- blob_init(&path, 0, 0);
868
- blob_appendf(&path, "%s", zSubpath);
869
- if( blob_read_from_file(&aContent, blob_str(&path))==-1 ){
870
- fossil_fatal("some unknown error occurred while reading \"%s\"",
871
- blob_str(&path));
872
- }
873
- content_put(&aContent);
874
- blob_reset(&path);
875
- blob_reset(&aContent);
876
- free(zSubpath);
877
- fossil_print("\r%d", ++nFileRead);
878
- fflush(stdout);
866
+ }else{
867
+ blob_init(&path, 0, 0);
868
+ blob_appendf(&path, "%s", zSubpath);
869
+ if( blob_read_from_file(&aContent, blob_str(&path))==-1 ){
870
+ fossil_fatal("some unknown error occurred while reading \"%s\"",
871
+ blob_str(&path));
872
+ }
873
+ content_put(&aContent);
874
+ blob_reset(&path);
875
+ blob_reset(&aContent);
876
+ fossil_print("\r%d", ++nFileRead);
877
+ fflush(stdout);
878
+ }
879
+ free(zSubpath);
879880
}
880881
closedir(d);
881882
}else {
882883
fossil_fatal("encountered error %d while trying to open \"%s\".",
883884
errno, g.argv[3]);
884885
--- src/rebuild.c
+++ src/rebuild.c
@@ -861,23 +861,24 @@
861 zUtf8Name = fossil_filename_to_utf8(pEntry->d_name);
862 zSubpath = mprintf("%s/%s", zPath, zUtf8Name);
863 fossil_filename_free(zUtf8Name);
864 if( file_isdir(zSubpath)==1 ){
865 recon_read_dir(zSubpath);
866 }
867 blob_init(&path, 0, 0);
868 blob_appendf(&path, "%s", zSubpath);
869 if( blob_read_from_file(&aContent, blob_str(&path))==-1 ){
870 fossil_fatal("some unknown error occurred while reading \"%s\"",
871 blob_str(&path));
872 }
873 content_put(&aContent);
874 blob_reset(&path);
875 blob_reset(&aContent);
876 free(zSubpath);
877 fossil_print("\r%d", ++nFileRead);
878 fflush(stdout);
 
879 }
880 closedir(d);
881 }else {
882 fossil_fatal("encountered error %d while trying to open \"%s\".",
883 errno, g.argv[3]);
884
--- src/rebuild.c
+++ src/rebuild.c
@@ -861,23 +861,24 @@
861 zUtf8Name = fossil_filename_to_utf8(pEntry->d_name);
862 zSubpath = mprintf("%s/%s", zPath, zUtf8Name);
863 fossil_filename_free(zUtf8Name);
864 if( file_isdir(zSubpath)==1 ){
865 recon_read_dir(zSubpath);
866 }else{
867 blob_init(&path, 0, 0);
868 blob_appendf(&path, "%s", zSubpath);
869 if( blob_read_from_file(&aContent, blob_str(&path))==-1 ){
870 fossil_fatal("some unknown error occurred while reading \"%s\"",
871 blob_str(&path));
872 }
873 content_put(&aContent);
874 blob_reset(&path);
875 blob_reset(&aContent);
876 fossil_print("\r%d", ++nFileRead);
877 fflush(stdout);
878 }
879 free(zSubpath);
880 }
881 closedir(d);
882 }else {
883 fossil_fatal("encountered error %d while trying to open \"%s\".",
884 errno, g.argv[3]);
885
+1 -1
--- src/report.c
+++ src/report.c
@@ -265,11 +265,11 @@
265265
}
266266
}
267267
268268
/* Compile the statement and check for illegal accesses or syntax errors. */
269269
report_restrict_sql(&zErr);
270
- rc = sqlite3_prepare(g.db, zSql, -1, &pStmt, &zTail);
270
+ rc = sqlite3_prepare_v2(g.db, zSql, -1, &pStmt, &zTail);
271271
if( rc!=SQLITE_OK ){
272272
zErr = mprintf("Syntax error: %s", sqlite3_errmsg(g.db));
273273
}
274274
if( !sqlite3_stmt_readonly(pStmt) ){
275275
zErr = mprintf("SQL must not modify the database");
276276
--- src/report.c
+++ src/report.c
@@ -265,11 +265,11 @@
265 }
266 }
267
268 /* Compile the statement and check for illegal accesses or syntax errors. */
269 report_restrict_sql(&zErr);
270 rc = sqlite3_prepare(g.db, zSql, -1, &pStmt, &zTail);
271 if( rc!=SQLITE_OK ){
272 zErr = mprintf("Syntax error: %s", sqlite3_errmsg(g.db));
273 }
274 if( !sqlite3_stmt_readonly(pStmt) ){
275 zErr = mprintf("SQL must not modify the database");
276
--- src/report.c
+++ src/report.c
@@ -265,11 +265,11 @@
265 }
266 }
267
268 /* Compile the statement and check for illegal accesses or syntax errors. */
269 report_restrict_sql(&zErr);
270 rc = sqlite3_prepare_v2(g.db, zSql, -1, &pStmt, &zTail);
271 if( rc!=SQLITE_OK ){
272 zErr = mprintf("Syntax error: %s", sqlite3_errmsg(g.db));
273 }
274 if( !sqlite3_stmt_readonly(pStmt) ){
275 zErr = mprintf("SQL must not modify the database");
276
+3 -2
--- src/setup.c
+++ src/setup.c
@@ -871,11 +871,11 @@
871871
@ <select size="1" name="%s(zQP)" id="id%s(zQP)">
872872
for(i=0; i<nChoice*2; i+=2){
873873
const char *zSel = fossil_strcmp(azChoice[i],z)==0 ? " selected" : "";
874874
@ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
875875
}
876
- @ </select>
876
+ @ </select> <b>%h(zLabel)</b>
877877
}
878878
879879
880880
/*
881881
** WEBPAGE: setup_access
@@ -1174,11 +1174,12 @@
11741174
11751175
@ <hr />
11761176
onoff_attribute("Plaintext comments on timelines",
11771177
"timeline-plaintext", "tpt", 0, 0);
11781178
@ <p>In timeline displays, check-in comments are displayed literally,
1179
- @ without any wiki or HTML interpretation.</p>
1179
+ @ without any wiki or HTML interpretation. (Note: Use CSS to change
1180
+ @ display formatting features such as fonts and line-wrapping behavior.)</p>
11801181
11811182
@ <hr />
11821183
onoff_attribute("Use Universal Coordinated Time (UTC)",
11831184
"timeline-utc", "utc", 1, 0);
11841185
@ <p>Show times as UTC (also sometimes called Greenwich Mean Time (GMT) or
11851186
--- src/setup.c
+++ src/setup.c
@@ -871,11 +871,11 @@
871 @ <select size="1" name="%s(zQP)" id="id%s(zQP)">
872 for(i=0; i<nChoice*2; i+=2){
873 const char *zSel = fossil_strcmp(azChoice[i],z)==0 ? " selected" : "";
874 @ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
875 }
876 @ </select>
877 }
878
879
880 /*
881 ** WEBPAGE: setup_access
@@ -1174,11 +1174,12 @@
1174
1175 @ <hr />
1176 onoff_attribute("Plaintext comments on timelines",
1177 "timeline-plaintext", "tpt", 0, 0);
1178 @ <p>In timeline displays, check-in comments are displayed literally,
1179 @ without any wiki or HTML interpretation.</p>
 
1180
1181 @ <hr />
1182 onoff_attribute("Use Universal Coordinated Time (UTC)",
1183 "timeline-utc", "utc", 1, 0);
1184 @ <p>Show times as UTC (also sometimes called Greenwich Mean Time (GMT) or
1185
--- src/setup.c
+++ src/setup.c
@@ -871,11 +871,11 @@
871 @ <select size="1" name="%s(zQP)" id="id%s(zQP)">
872 for(i=0; i<nChoice*2; i+=2){
873 const char *zSel = fossil_strcmp(azChoice[i],z)==0 ? " selected" : "";
874 @ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
875 }
876 @ </select> <b>%h(zLabel)</b>
877 }
878
879
880 /*
881 ** WEBPAGE: setup_access
@@ -1174,11 +1174,12 @@
1174
1175 @ <hr />
1176 onoff_attribute("Plaintext comments on timelines",
1177 "timeline-plaintext", "tpt", 0, 0);
1178 @ <p>In timeline displays, check-in comments are displayed literally,
1179 @ without any wiki or HTML interpretation. (Note: Use CSS to change
1180 @ display formatting features such as fonts and line-wrapping behavior.)</p>
1181
1182 @ <hr />
1183 onoff_attribute("Use Universal Coordinated Time (UTC)",
1184 "timeline-utc", "utc", 1, 0);
1185 @ <p>Show times as UTC (also sometimes called Greenwich Mean Time (GMT) or
1186
+267 -15
--- src/shell.c
+++ src/shell.c
@@ -43,18 +43,21 @@
4343
# endif
4444
# include <unistd.h>
4545
# include <sys/types.h>
4646
#endif
4747
48
-#ifdef HAVE_EDITLINE
49
-# include <editline/editline.h>
50
-#endif
51
-#if defined(HAVE_READLINE) && HAVE_READLINE==1
48
+#if defined(HAVE_READLINE) && HAVE_READLINE!=0
5249
# include <readline/readline.h>
5350
# include <readline/history.h>
51
+#else
52
+# undef HAVE_READLINE
53
+#endif
54
+#if defined(HAVE_EDITLINE) && !defined(HAVE_READLINE)
55
+# define HAVE_READLINE 1
56
+# include <editline/readline.h>
5457
#endif
55
-#if !defined(HAVE_EDITLINE) && (!defined(HAVE_READLINE) || HAVE_READLINE!=1)
58
+#if !defined(HAVE_READLINE)
5659
# define add_history(X)
5760
# define read_history(X)
5861
# define write_history(X)
5962
# define stifle_history(X)
6063
#endif
@@ -411,11 +414,11 @@
411414
char *zResult;
412415
if( in!=0 ){
413416
zResult = local_getline(zPrior, in);
414417
}else{
415418
zPrompt = isContinuation ? continuePrompt : mainPrompt;
416
-#if defined(HAVE_READLINE) && HAVE_READLINE==1
419
+#if defined(HAVE_READLINE)
417420
free(zPrior);
418421
zResult = readline(zPrompt);
419422
if( zResult && *zResult ) add_history(zResult);
420423
#else
421424
printf("%s", zPrompt);
@@ -1003,11 +1006,11 @@
10031006
sqlite3_stmt *pSelect;
10041007
int rc;
10051008
int nResult;
10061009
int i;
10071010
const char *z;
1008
- rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0);
1011
+ rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
10091012
if( rc!=SQLITE_OK || !pSelect ){
10101013
fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
10111014
if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
10121015
return rc;
10131016
}
@@ -1451,11 +1454,11 @@
14511454
14521455
zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0);
14531456
zTableInfo = appendText(zTableInfo, zTable, '"');
14541457
zTableInfo = appendText(zTableInfo, ");", 0);
14551458
1456
- rc = sqlite3_prepare(p->db, zTableInfo, -1, &pTableInfo, 0);
1459
+ rc = sqlite3_prepare_v2(p->db, zTableInfo, -1, &pTableInfo, 0);
14571460
free(zTableInfo);
14581461
if( rc!=SQLITE_OK || !pTableInfo ){
14591462
return 1;
14601463
}
14611464
@@ -1541,10 +1544,11 @@
15411544
** Text of a help message
15421545
*/
15431546
static char zHelp[] =
15441547
".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
15451548
".bail ON|OFF Stop after hitting an error. Default OFF\n"
1549
+ ".clone NEWDB Clone data into NEWDB from the existing database\n"
15461550
".databases List names and files of attached databases\n"
15471551
".dump ?TABLE? ... Dump the database in an SQL text format\n"
15481552
" If TABLE specified, only dump tables matching\n"
15491553
" LIKE pattern TABLE.\n"
15501554
".echo ON|OFF Turn command echo on or off\n"
@@ -1580,10 +1584,11 @@
15801584
".print STRING... Print literal STRING\n"
15811585
".prompt MAIN CONTINUE Replace the standard prompts\n"
15821586
".quit Exit this program\n"
15831587
".read FILENAME Execute SQL in FILENAME\n"
15841588
".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
1589
+ ".save FILE Write in-memory database into FILE\n"
15851590
".schema ?TABLE? Show the CREATE statements\n"
15861591
" If TABLE specified, only show tables matching\n"
15871592
" LIKE pattern TABLE.\n"
15881593
".separator STRING Change separator used by output mode and .import\n"
15891594
".show Show the current values for various settings\n"
@@ -1893,10 +1898,223 @@
18931898
p->cTerm = c;
18941899
}
18951900
if( p->z ) p->z[p->n] = 0;
18961901
return p->z;
18971902
}
1903
+
1904
+/*
1905
+** Try to transfer data for table zTable. If an error is seen while
1906
+** moving forward, try to go backwards. The backwards movement won't
1907
+** work for WITHOUT ROWID tables.
1908
+*/
1909
+static void tryToCloneData(
1910
+ struct callback_data *p,
1911
+ sqlite3 *newDb,
1912
+ const char *zTable
1913
+){
1914
+ sqlite3_stmt *pQuery = 0;
1915
+ sqlite3_stmt *pInsert = 0;
1916
+ char *zQuery = 0;
1917
+ char *zInsert = 0;
1918
+ int rc;
1919
+ int i, j, n;
1920
+ int nTable = (int)strlen(zTable);
1921
+ int k = 0;
1922
+ int cnt = 0;
1923
+ const int spinRate = 10000;
1924
+
1925
+ zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
1926
+ rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
1927
+ if( rc ){
1928
+ fprintf(stderr, "Error %d: %s on [%s]\n",
1929
+ sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
1930
+ zQuery);
1931
+ goto end_data_xfer;
1932
+ }
1933
+ n = sqlite3_column_count(pQuery);
1934
+ zInsert = sqlite3_malloc(200 + nTable + n*3);
1935
+ if( zInsert==0 ){
1936
+ fprintf(stderr, "out of memory\n");
1937
+ goto end_data_xfer;
1938
+ }
1939
+ sqlite3_snprintf(200+nTable,zInsert,
1940
+ "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
1941
+ i = (int)strlen(zInsert);
1942
+ for(j=1; j<n; j++){
1943
+ memcpy(zInsert+i, ",?", 2);
1944
+ i += 2;
1945
+ }
1946
+ memcpy(zInsert+i, ");", 3);
1947
+ rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
1948
+ if( rc ){
1949
+ fprintf(stderr, "Error %d: %s on [%s]\n",
1950
+ sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
1951
+ zQuery);
1952
+ goto end_data_xfer;
1953
+ }
1954
+ for(k=0; k<2; k++){
1955
+ while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
1956
+ for(i=0; i<n; i++){
1957
+ switch( sqlite3_column_type(pQuery, i) ){
1958
+ case SQLITE_NULL: {
1959
+ sqlite3_bind_null(pInsert, i+1);
1960
+ break;
1961
+ }
1962
+ case SQLITE_INTEGER: {
1963
+ sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
1964
+ break;
1965
+ }
1966
+ case SQLITE_FLOAT: {
1967
+ sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
1968
+ break;
1969
+ }
1970
+ case SQLITE_TEXT: {
1971
+ sqlite3_bind_text(pInsert, i+1,
1972
+ (const char*)sqlite3_column_text(pQuery,i),
1973
+ -1, SQLITE_STATIC);
1974
+ break;
1975
+ }
1976
+ case SQLITE_BLOB: {
1977
+ sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
1978
+ sqlite3_column_bytes(pQuery,i),
1979
+ SQLITE_STATIC);
1980
+ break;
1981
+ }
1982
+ }
1983
+ } /* End for */
1984
+ rc = sqlite3_step(pInsert);
1985
+ if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
1986
+ fprintf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
1987
+ sqlite3_errmsg(newDb));
1988
+ }
1989
+ sqlite3_reset(pInsert);
1990
+ cnt++;
1991
+ if( (cnt%spinRate)==0 ){
1992
+ printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
1993
+ fflush(stdout);
1994
+ }
1995
+ } /* End while */
1996
+ if( rc==SQLITE_DONE ) break;
1997
+ sqlite3_finalize(pQuery);
1998
+ sqlite3_free(zQuery);
1999
+ zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
2000
+ zTable);
2001
+ rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
2002
+ if( rc ){
2003
+ fprintf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
2004
+ break;
2005
+ }
2006
+ } /* End for(k=0...) */
2007
+
2008
+end_data_xfer:
2009
+ sqlite3_finalize(pQuery);
2010
+ sqlite3_finalize(pInsert);
2011
+ sqlite3_free(zQuery);
2012
+ sqlite3_free(zInsert);
2013
+}
2014
+
2015
+
2016
+/*
2017
+** Try to transfer all rows of the schema that match zWhere. For
2018
+** each row, invoke xForEach() on the object defined by that row.
2019
+** If an error is encountered while moving forward through the
2020
+** sqlite_master table, try again moving backwards.
2021
+*/
2022
+static void tryToCloneSchema(
2023
+ struct callback_data *p,
2024
+ sqlite3 *newDb,
2025
+ const char *zWhere,
2026
+ void (*xForEach)(struct callback_data*,sqlite3*,const char*)
2027
+){
2028
+ sqlite3_stmt *pQuery = 0;
2029
+ char *zQuery = 0;
2030
+ int rc;
2031
+ const unsigned char *zName;
2032
+ const unsigned char *zSql;
2033
+ char *zErrMsg = 0;
2034
+
2035
+ zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
2036
+ " WHERE %s", zWhere);
2037
+ rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
2038
+ if( rc ){
2039
+ fprintf(stderr, "Error: (%d) %s on [%s]\n",
2040
+ sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
2041
+ zQuery);
2042
+ goto end_schema_xfer;
2043
+ }
2044
+ while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
2045
+ zName = sqlite3_column_text(pQuery, 0);
2046
+ zSql = sqlite3_column_text(pQuery, 1);
2047
+ printf("%s... ", zName); fflush(stdout);
2048
+ sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
2049
+ if( zErrMsg ){
2050
+ fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
2051
+ sqlite3_free(zErrMsg);
2052
+ zErrMsg = 0;
2053
+ }
2054
+ if( xForEach ){
2055
+ xForEach(p, newDb, (const char*)zName);
2056
+ }
2057
+ printf("done\n");
2058
+ }
2059
+ if( rc!=SQLITE_DONE ){
2060
+ sqlite3_finalize(pQuery);
2061
+ sqlite3_free(zQuery);
2062
+ zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
2063
+ " WHERE %s ORDER BY rowid DESC", zWhere);
2064
+ rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
2065
+ if( rc ){
2066
+ fprintf(stderr, "Error: (%d) %s on [%s]\n",
2067
+ sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
2068
+ zQuery);
2069
+ goto end_schema_xfer;
2070
+ }
2071
+ while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
2072
+ zName = sqlite3_column_text(pQuery, 0);
2073
+ zSql = sqlite3_column_text(pQuery, 1);
2074
+ printf("%s... ", zName); fflush(stdout);
2075
+ sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
2076
+ if( zErrMsg ){
2077
+ fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
2078
+ sqlite3_free(zErrMsg);
2079
+ zErrMsg = 0;
2080
+ }
2081
+ if( xForEach ){
2082
+ xForEach(p, newDb, (const char*)zName);
2083
+ }
2084
+ printf("done\n");
2085
+ }
2086
+ }
2087
+end_schema_xfer:
2088
+ sqlite3_finalize(pQuery);
2089
+ sqlite3_free(zQuery);
2090
+}
2091
+
2092
+/*
2093
+** Open a new database file named "zNewDb". Try to recover as much information
2094
+** as possible out of the main database (which might be corrupt) and write it
2095
+** into zNewDb.
2096
+*/
2097
+static void tryToClone(struct callback_data *p, const char *zNewDb){
2098
+ int rc;
2099
+ sqlite3 *newDb = 0;
2100
+ if( access(zNewDb,0)==0 ){
2101
+ fprintf(stderr, "File \"%s\" already exists.\n", zNewDb);
2102
+ return;
2103
+ }
2104
+ rc = sqlite3_open(zNewDb, &newDb);
2105
+ if( rc ){
2106
+ fprintf(stderr, "Cannot create output database: %s\n",
2107
+ sqlite3_errmsg(newDb));
2108
+ }else{
2109
+ sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
2110
+ tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
2111
+ tryToCloneSchema(p, newDb, "type!='table'", 0);
2112
+ sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
2113
+ }
2114
+ sqlite3_close(newDb);
2115
+}
18982116
18992117
/*
19002118
** If an input line begins with "." then invoke this routine to
19012119
** process that line.
19022120
**
@@ -1936,11 +2154,13 @@
19362154
/* Process the input line.
19372155
*/
19382156
if( nArg==0 ) return 0; /* no tokens, no error */
19392157
n = strlen30(azArg[0]);
19402158
c = azArg[0][0];
1941
- if( c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0 ){
2159
+ if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
2160
+ || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
2161
+ ){
19422162
const char *zDestFile = 0;
19432163
const char *zDb = 0;
19442164
sqlite3 *pDest;
19452165
sqlite3_backup *pBackup;
19462166
int j;
@@ -2000,10 +2220,14 @@
20002220
** routine named test_breakpoint().
20012221
*/
20022222
if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
20032223
test_breakpoint();
20042224
}else
2225
+
2226
+ if( c=='c' && strncmp(azArg[0], "clone", n)==0 && nArg>1 && nArg<3 ){
2227
+ tryToClone(p, azArg[1]);
2228
+ }else
20052229
20062230
if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 && nArg==1 ){
20072231
struct callback_data data;
20082232
char *zErrMsg = 0;
20092233
open_db(p, 0);
@@ -2173,11 +2397,11 @@
21732397
fprintf(stderr, "Error: out of memory\n");
21742398
xCloser(sCsv.in);
21752399
return 1;
21762400
}
21772401
nByte = strlen30(zSql);
2178
- rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
2402
+ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
21792403
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){
21802404
char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
21812405
char cSep = '(';
21822406
while( csv_read_one_field(&sCsv) ){
21832407
zCreate = sqlite3_mprintf("%z%c\n \"%s\" TEXT", zCreate, cSep, sCsv.z);
@@ -2199,11 +2423,11 @@
21992423
sqlite3_errmsg(db));
22002424
sqlite3_free(sCsv.z);
22012425
xCloser(sCsv.in);
22022426
return 1;
22032427
}
2204
- rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
2428
+ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
22052429
}
22062430
sqlite3_free(zSql);
22072431
if( rc ){
22082432
if (pStmt) sqlite3_finalize(pStmt);
22092433
fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
@@ -2226,11 +2450,11 @@
22262450
zSql[j++] = ',';
22272451
zSql[j++] = '?';
22282452
}
22292453
zSql[j++] = ')';
22302454
zSql[j] = 0;
2231
- rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
2455
+ rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
22322456
sqlite3_free(zSql);
22332457
if( rc ){
22342458
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
22352459
if (pStmt) sqlite3_finalize(pStmt);
22362460
xCloser(sCsv.in);
@@ -3280,10 +3504,30 @@
32803504
sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
32813505
sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
32823506
sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
32833507
}
32843508
3509
+/*
3510
+** Output text to the console in a font that attracts extra attention.
3511
+*/
3512
+#ifdef _WIN32
3513
+static void printBold(const char *zText){
3514
+ HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
3515
+ CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
3516
+ GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
3517
+ SetConsoleTextAttribute(out,
3518
+ FOREGROUND_RED|FOREGROUND_INTENSITY
3519
+ );
3520
+ printf("%s", zText);
3521
+ SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
3522
+}
3523
+#else
3524
+static void printBold(const char *zText){
3525
+ printf("\033[1m%s\033[0m", zText);
3526
+}
3527
+#endif
3528
+
32853529
/*
32863530
** Get the argument to an --option. Throw an error and die if no argument
32873531
** is available.
32883532
*/
32893533
static char *cmdline_option_value(int argc, char **argv, int i){
@@ -3300,10 +3544,11 @@
33003544
struct callback_data data;
33013545
const char *zInitFile = 0;
33023546
char *zFirstCmd = 0;
33033547
int i;
33043548
int rc = 0;
3549
+ int warnInmemoryDb = 0;
33053550
33063551
if( sqlite3_libversion_number()<3008003 ){
33073552
fprintf(stderr, "Unsuitable SQLite version %s, must be at least 3.8.3",
33083553
sqlite3_libversion());
33093554
exit(1);
@@ -3394,18 +3639,20 @@
33943639
}
33953640
}
33963641
if( data.zDbFilename==0 ){
33973642
#ifndef SQLITE_OMIT_MEMORYDB
33983643
data.zDbFilename = ":memory:";
3644
+ warnInmemoryDb = argc==1;
33993645
#else
34003646
fprintf(stderr,"%s: Error: no database filename specified\n", Argv0);
34013647
return 1;
34023648
#endif
34033649
/***** Begin Fossil Patch *****/
34043650
{
34053651
extern void fossil_open(const char **);
34063652
fossil_open(&data.zDbFilename);
3653
+ warnInmemoryDb = 0;
34073654
}
34083655
/***** End Fossil Patch *****/
34093656
}
34103657
data.out = stdout;
34113658
@@ -3536,22 +3783,27 @@
35363783
char *zHome;
35373784
char *zHistory = 0;
35383785
int nHistory;
35393786
printf(
35403787
"SQLite version %s %.19s\n" /*extra-version-info*/
3541
- "Enter \".help\" for instructions\n"
3542
- "Enter SQL statements terminated with a \";\"\n",
3788
+ "Enter \".help\" for usage hints.\n",
35433789
sqlite3_libversion(), sqlite3_sourceid()
35443790
);
3791
+ if( warnInmemoryDb ){
3792
+ printf("Connected to a ");
3793
+ printBold("transient in-memory database.");
3794
+ printf("\nUse \".open FILENAME\" to reopen on a "
3795
+ "persistent database.\n");
3796
+ }
35453797
zHome = find_home_dir();
35463798
if( zHome ){
35473799
nHistory = strlen30(zHome) + 20;
35483800
if( (zHistory = malloc(nHistory))!=0 ){
35493801
sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
35503802
}
35513803
}
3552
-#if defined(HAVE_READLINE) && HAVE_READLINE==1
3804
+#if defined(HAVE_READLINE)
35533805
if( zHistory ) read_history(zHistory);
35543806
#endif
35553807
rc = process_input(&data, 0);
35563808
if( zHistory ){
35573809
stifle_history(100);
35583810
--- src/shell.c
+++ src/shell.c
@@ -43,18 +43,21 @@
43 # endif
44 # include <unistd.h>
45 # include <sys/types.h>
46 #endif
47
48 #ifdef HAVE_EDITLINE
49 # include <editline/editline.h>
50 #endif
51 #if defined(HAVE_READLINE) && HAVE_READLINE==1
52 # include <readline/readline.h>
53 # include <readline/history.h>
 
 
 
 
 
 
54 #endif
55 #if !defined(HAVE_EDITLINE) && (!defined(HAVE_READLINE) || HAVE_READLINE!=1)
56 # define add_history(X)
57 # define read_history(X)
58 # define write_history(X)
59 # define stifle_history(X)
60 #endif
@@ -411,11 +414,11 @@
411 char *zResult;
412 if( in!=0 ){
413 zResult = local_getline(zPrior, in);
414 }else{
415 zPrompt = isContinuation ? continuePrompt : mainPrompt;
416 #if defined(HAVE_READLINE) && HAVE_READLINE==1
417 free(zPrior);
418 zResult = readline(zPrompt);
419 if( zResult && *zResult ) add_history(zResult);
420 #else
421 printf("%s", zPrompt);
@@ -1003,11 +1006,11 @@
1003 sqlite3_stmt *pSelect;
1004 int rc;
1005 int nResult;
1006 int i;
1007 const char *z;
1008 rc = sqlite3_prepare(p->db, zSelect, -1, &pSelect, 0);
1009 if( rc!=SQLITE_OK || !pSelect ){
1010 fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
1011 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
1012 return rc;
1013 }
@@ -1451,11 +1454,11 @@
1451
1452 zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0);
1453 zTableInfo = appendText(zTableInfo, zTable, '"');
1454 zTableInfo = appendText(zTableInfo, ");", 0);
1455
1456 rc = sqlite3_prepare(p->db, zTableInfo, -1, &pTableInfo, 0);
1457 free(zTableInfo);
1458 if( rc!=SQLITE_OK || !pTableInfo ){
1459 return 1;
1460 }
1461
@@ -1541,10 +1544,11 @@
1541 ** Text of a help message
1542 */
1543 static char zHelp[] =
1544 ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
1545 ".bail ON|OFF Stop after hitting an error. Default OFF\n"
 
1546 ".databases List names and files of attached databases\n"
1547 ".dump ?TABLE? ... Dump the database in an SQL text format\n"
1548 " If TABLE specified, only dump tables matching\n"
1549 " LIKE pattern TABLE.\n"
1550 ".echo ON|OFF Turn command echo on or off\n"
@@ -1580,10 +1584,11 @@
1580 ".print STRING... Print literal STRING\n"
1581 ".prompt MAIN CONTINUE Replace the standard prompts\n"
1582 ".quit Exit this program\n"
1583 ".read FILENAME Execute SQL in FILENAME\n"
1584 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
 
1585 ".schema ?TABLE? Show the CREATE statements\n"
1586 " If TABLE specified, only show tables matching\n"
1587 " LIKE pattern TABLE.\n"
1588 ".separator STRING Change separator used by output mode and .import\n"
1589 ".show Show the current values for various settings\n"
@@ -1893,10 +1898,223 @@
1893 p->cTerm = c;
1894 }
1895 if( p->z ) p->z[p->n] = 0;
1896 return p->z;
1897 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1898
1899 /*
1900 ** If an input line begins with "." then invoke this routine to
1901 ** process that line.
1902 **
@@ -1936,11 +2154,13 @@
1936 /* Process the input line.
1937 */
1938 if( nArg==0 ) return 0; /* no tokens, no error */
1939 n = strlen30(azArg[0]);
1940 c = azArg[0][0];
1941 if( c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0 ){
 
 
1942 const char *zDestFile = 0;
1943 const char *zDb = 0;
1944 sqlite3 *pDest;
1945 sqlite3_backup *pBackup;
1946 int j;
@@ -2000,10 +2220,14 @@
2000 ** routine named test_breakpoint().
2001 */
2002 if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
2003 test_breakpoint();
2004 }else
 
 
 
 
2005
2006 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 && nArg==1 ){
2007 struct callback_data data;
2008 char *zErrMsg = 0;
2009 open_db(p, 0);
@@ -2173,11 +2397,11 @@
2173 fprintf(stderr, "Error: out of memory\n");
2174 xCloser(sCsv.in);
2175 return 1;
2176 }
2177 nByte = strlen30(zSql);
2178 rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
2179 if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){
2180 char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
2181 char cSep = '(';
2182 while( csv_read_one_field(&sCsv) ){
2183 zCreate = sqlite3_mprintf("%z%c\n \"%s\" TEXT", zCreate, cSep, sCsv.z);
@@ -2199,11 +2423,11 @@
2199 sqlite3_errmsg(db));
2200 sqlite3_free(sCsv.z);
2201 xCloser(sCsv.in);
2202 return 1;
2203 }
2204 rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
2205 }
2206 sqlite3_free(zSql);
2207 if( rc ){
2208 if (pStmt) sqlite3_finalize(pStmt);
2209 fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
@@ -2226,11 +2450,11 @@
2226 zSql[j++] = ',';
2227 zSql[j++] = '?';
2228 }
2229 zSql[j++] = ')';
2230 zSql[j] = 0;
2231 rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0);
2232 sqlite3_free(zSql);
2233 if( rc ){
2234 fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
2235 if (pStmt) sqlite3_finalize(pStmt);
2236 xCloser(sCsv.in);
@@ -3280,10 +3504,30 @@
3280 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
3281 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
3282 sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
3283 }
3284
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3285 /*
3286 ** Get the argument to an --option. Throw an error and die if no argument
3287 ** is available.
3288 */
3289 static char *cmdline_option_value(int argc, char **argv, int i){
@@ -3300,10 +3544,11 @@
3300 struct callback_data data;
3301 const char *zInitFile = 0;
3302 char *zFirstCmd = 0;
3303 int i;
3304 int rc = 0;
 
3305
3306 if( sqlite3_libversion_number()<3008003 ){
3307 fprintf(stderr, "Unsuitable SQLite version %s, must be at least 3.8.3",
3308 sqlite3_libversion());
3309 exit(1);
@@ -3394,18 +3639,20 @@
3394 }
3395 }
3396 if( data.zDbFilename==0 ){
3397 #ifndef SQLITE_OMIT_MEMORYDB
3398 data.zDbFilename = ":memory:";
 
3399 #else
3400 fprintf(stderr,"%s: Error: no database filename specified\n", Argv0);
3401 return 1;
3402 #endif
3403 /***** Begin Fossil Patch *****/
3404 {
3405 extern void fossil_open(const char **);
3406 fossil_open(&data.zDbFilename);
 
3407 }
3408 /***** End Fossil Patch *****/
3409 }
3410 data.out = stdout;
3411
@@ -3536,22 +3783,27 @@
3536 char *zHome;
3537 char *zHistory = 0;
3538 int nHistory;
3539 printf(
3540 "SQLite version %s %.19s\n" /*extra-version-info*/
3541 "Enter \".help\" for instructions\n"
3542 "Enter SQL statements terminated with a \";\"\n",
3543 sqlite3_libversion(), sqlite3_sourceid()
3544 );
 
 
 
 
 
 
3545 zHome = find_home_dir();
3546 if( zHome ){
3547 nHistory = strlen30(zHome) + 20;
3548 if( (zHistory = malloc(nHistory))!=0 ){
3549 sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
3550 }
3551 }
3552 #if defined(HAVE_READLINE) && HAVE_READLINE==1
3553 if( zHistory ) read_history(zHistory);
3554 #endif
3555 rc = process_input(&data, 0);
3556 if( zHistory ){
3557 stifle_history(100);
3558
--- src/shell.c
+++ src/shell.c
@@ -43,18 +43,21 @@
43 # endif
44 # include <unistd.h>
45 # include <sys/types.h>
46 #endif
47
48 #if defined(HAVE_READLINE) && HAVE_READLINE!=0
 
 
 
49 # include <readline/readline.h>
50 # include <readline/history.h>
51 #else
52 # undef HAVE_READLINE
53 #endif
54 #if defined(HAVE_EDITLINE) && !defined(HAVE_READLINE)
55 # define HAVE_READLINE 1
56 # include <editline/readline.h>
57 #endif
58 #if !defined(HAVE_READLINE)
59 # define add_history(X)
60 # define read_history(X)
61 # define write_history(X)
62 # define stifle_history(X)
63 #endif
@@ -411,11 +414,11 @@
414 char *zResult;
415 if( in!=0 ){
416 zResult = local_getline(zPrior, in);
417 }else{
418 zPrompt = isContinuation ? continuePrompt : mainPrompt;
419 #if defined(HAVE_READLINE)
420 free(zPrior);
421 zResult = readline(zPrompt);
422 if( zResult && *zResult ) add_history(zResult);
423 #else
424 printf("%s", zPrompt);
@@ -1003,11 +1006,11 @@
1006 sqlite3_stmt *pSelect;
1007 int rc;
1008 int nResult;
1009 int i;
1010 const char *z;
1011 rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
1012 if( rc!=SQLITE_OK || !pSelect ){
1013 fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db));
1014 if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
1015 return rc;
1016 }
@@ -1451,11 +1454,11 @@
1454
1455 zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0);
1456 zTableInfo = appendText(zTableInfo, zTable, '"');
1457 zTableInfo = appendText(zTableInfo, ");", 0);
1458
1459 rc = sqlite3_prepare_v2(p->db, zTableInfo, -1, &pTableInfo, 0);
1460 free(zTableInfo);
1461 if( rc!=SQLITE_OK || !pTableInfo ){
1462 return 1;
1463 }
1464
@@ -1541,10 +1544,11 @@
1544 ** Text of a help message
1545 */
1546 static char zHelp[] =
1547 ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
1548 ".bail ON|OFF Stop after hitting an error. Default OFF\n"
1549 ".clone NEWDB Clone data into NEWDB from the existing database\n"
1550 ".databases List names and files of attached databases\n"
1551 ".dump ?TABLE? ... Dump the database in an SQL text format\n"
1552 " If TABLE specified, only dump tables matching\n"
1553 " LIKE pattern TABLE.\n"
1554 ".echo ON|OFF Turn command echo on or off\n"
@@ -1580,10 +1584,11 @@
1584 ".print STRING... Print literal STRING\n"
1585 ".prompt MAIN CONTINUE Replace the standard prompts\n"
1586 ".quit Exit this program\n"
1587 ".read FILENAME Execute SQL in FILENAME\n"
1588 ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
1589 ".save FILE Write in-memory database into FILE\n"
1590 ".schema ?TABLE? Show the CREATE statements\n"
1591 " If TABLE specified, only show tables matching\n"
1592 " LIKE pattern TABLE.\n"
1593 ".separator STRING Change separator used by output mode and .import\n"
1594 ".show Show the current values for various settings\n"
@@ -1893,10 +1898,223 @@
1898 p->cTerm = c;
1899 }
1900 if( p->z ) p->z[p->n] = 0;
1901 return p->z;
1902 }
1903
1904 /*
1905 ** Try to transfer data for table zTable. If an error is seen while
1906 ** moving forward, try to go backwards. The backwards movement won't
1907 ** work for WITHOUT ROWID tables.
1908 */
1909 static void tryToCloneData(
1910 struct callback_data *p,
1911 sqlite3 *newDb,
1912 const char *zTable
1913 ){
1914 sqlite3_stmt *pQuery = 0;
1915 sqlite3_stmt *pInsert = 0;
1916 char *zQuery = 0;
1917 char *zInsert = 0;
1918 int rc;
1919 int i, j, n;
1920 int nTable = (int)strlen(zTable);
1921 int k = 0;
1922 int cnt = 0;
1923 const int spinRate = 10000;
1924
1925 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
1926 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
1927 if( rc ){
1928 fprintf(stderr, "Error %d: %s on [%s]\n",
1929 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
1930 zQuery);
1931 goto end_data_xfer;
1932 }
1933 n = sqlite3_column_count(pQuery);
1934 zInsert = sqlite3_malloc(200 + nTable + n*3);
1935 if( zInsert==0 ){
1936 fprintf(stderr, "out of memory\n");
1937 goto end_data_xfer;
1938 }
1939 sqlite3_snprintf(200+nTable,zInsert,
1940 "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
1941 i = (int)strlen(zInsert);
1942 for(j=1; j<n; j++){
1943 memcpy(zInsert+i, ",?", 2);
1944 i += 2;
1945 }
1946 memcpy(zInsert+i, ");", 3);
1947 rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
1948 if( rc ){
1949 fprintf(stderr, "Error %d: %s on [%s]\n",
1950 sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
1951 zQuery);
1952 goto end_data_xfer;
1953 }
1954 for(k=0; k<2; k++){
1955 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
1956 for(i=0; i<n; i++){
1957 switch( sqlite3_column_type(pQuery, i) ){
1958 case SQLITE_NULL: {
1959 sqlite3_bind_null(pInsert, i+1);
1960 break;
1961 }
1962 case SQLITE_INTEGER: {
1963 sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
1964 break;
1965 }
1966 case SQLITE_FLOAT: {
1967 sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
1968 break;
1969 }
1970 case SQLITE_TEXT: {
1971 sqlite3_bind_text(pInsert, i+1,
1972 (const char*)sqlite3_column_text(pQuery,i),
1973 -1, SQLITE_STATIC);
1974 break;
1975 }
1976 case SQLITE_BLOB: {
1977 sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
1978 sqlite3_column_bytes(pQuery,i),
1979 SQLITE_STATIC);
1980 break;
1981 }
1982 }
1983 } /* End for */
1984 rc = sqlite3_step(pInsert);
1985 if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
1986 fprintf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
1987 sqlite3_errmsg(newDb));
1988 }
1989 sqlite3_reset(pInsert);
1990 cnt++;
1991 if( (cnt%spinRate)==0 ){
1992 printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
1993 fflush(stdout);
1994 }
1995 } /* End while */
1996 if( rc==SQLITE_DONE ) break;
1997 sqlite3_finalize(pQuery);
1998 sqlite3_free(zQuery);
1999 zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
2000 zTable);
2001 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
2002 if( rc ){
2003 fprintf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
2004 break;
2005 }
2006 } /* End for(k=0...) */
2007
2008 end_data_xfer:
2009 sqlite3_finalize(pQuery);
2010 sqlite3_finalize(pInsert);
2011 sqlite3_free(zQuery);
2012 sqlite3_free(zInsert);
2013 }
2014
2015
2016 /*
2017 ** Try to transfer all rows of the schema that match zWhere. For
2018 ** each row, invoke xForEach() on the object defined by that row.
2019 ** If an error is encountered while moving forward through the
2020 ** sqlite_master table, try again moving backwards.
2021 */
2022 static void tryToCloneSchema(
2023 struct callback_data *p,
2024 sqlite3 *newDb,
2025 const char *zWhere,
2026 void (*xForEach)(struct callback_data*,sqlite3*,const char*)
2027 ){
2028 sqlite3_stmt *pQuery = 0;
2029 char *zQuery = 0;
2030 int rc;
2031 const unsigned char *zName;
2032 const unsigned char *zSql;
2033 char *zErrMsg = 0;
2034
2035 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
2036 " WHERE %s", zWhere);
2037 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
2038 if( rc ){
2039 fprintf(stderr, "Error: (%d) %s on [%s]\n",
2040 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
2041 zQuery);
2042 goto end_schema_xfer;
2043 }
2044 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
2045 zName = sqlite3_column_text(pQuery, 0);
2046 zSql = sqlite3_column_text(pQuery, 1);
2047 printf("%s... ", zName); fflush(stdout);
2048 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
2049 if( zErrMsg ){
2050 fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
2051 sqlite3_free(zErrMsg);
2052 zErrMsg = 0;
2053 }
2054 if( xForEach ){
2055 xForEach(p, newDb, (const char*)zName);
2056 }
2057 printf("done\n");
2058 }
2059 if( rc!=SQLITE_DONE ){
2060 sqlite3_finalize(pQuery);
2061 sqlite3_free(zQuery);
2062 zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
2063 " WHERE %s ORDER BY rowid DESC", zWhere);
2064 rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
2065 if( rc ){
2066 fprintf(stderr, "Error: (%d) %s on [%s]\n",
2067 sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
2068 zQuery);
2069 goto end_schema_xfer;
2070 }
2071 while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
2072 zName = sqlite3_column_text(pQuery, 0);
2073 zSql = sqlite3_column_text(pQuery, 1);
2074 printf("%s... ", zName); fflush(stdout);
2075 sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
2076 if( zErrMsg ){
2077 fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
2078 sqlite3_free(zErrMsg);
2079 zErrMsg = 0;
2080 }
2081 if( xForEach ){
2082 xForEach(p, newDb, (const char*)zName);
2083 }
2084 printf("done\n");
2085 }
2086 }
2087 end_schema_xfer:
2088 sqlite3_finalize(pQuery);
2089 sqlite3_free(zQuery);
2090 }
2091
2092 /*
2093 ** Open a new database file named "zNewDb". Try to recover as much information
2094 ** as possible out of the main database (which might be corrupt) and write it
2095 ** into zNewDb.
2096 */
2097 static void tryToClone(struct callback_data *p, const char *zNewDb){
2098 int rc;
2099 sqlite3 *newDb = 0;
2100 if( access(zNewDb,0)==0 ){
2101 fprintf(stderr, "File \"%s\" already exists.\n", zNewDb);
2102 return;
2103 }
2104 rc = sqlite3_open(zNewDb, &newDb);
2105 if( rc ){
2106 fprintf(stderr, "Cannot create output database: %s\n",
2107 sqlite3_errmsg(newDb));
2108 }else{
2109 sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
2110 tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
2111 tryToCloneSchema(p, newDb, "type!='table'", 0);
2112 sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
2113 }
2114 sqlite3_close(newDb);
2115 }
2116
2117 /*
2118 ** If an input line begins with "." then invoke this routine to
2119 ** process that line.
2120 **
@@ -1936,11 +2154,13 @@
2154 /* Process the input line.
2155 */
2156 if( nArg==0 ) return 0; /* no tokens, no error */
2157 n = strlen30(azArg[0]);
2158 c = azArg[0][0];
2159 if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
2160 || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
2161 ){
2162 const char *zDestFile = 0;
2163 const char *zDb = 0;
2164 sqlite3 *pDest;
2165 sqlite3_backup *pBackup;
2166 int j;
@@ -2000,10 +2220,14 @@
2220 ** routine named test_breakpoint().
2221 */
2222 if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
2223 test_breakpoint();
2224 }else
2225
2226 if( c=='c' && strncmp(azArg[0], "clone", n)==0 && nArg>1 && nArg<3 ){
2227 tryToClone(p, azArg[1]);
2228 }else
2229
2230 if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 && nArg==1 ){
2231 struct callback_data data;
2232 char *zErrMsg = 0;
2233 open_db(p, 0);
@@ -2173,11 +2397,11 @@
2397 fprintf(stderr, "Error: out of memory\n");
2398 xCloser(sCsv.in);
2399 return 1;
2400 }
2401 nByte = strlen30(zSql);
2402 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
2403 if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){
2404 char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
2405 char cSep = '(';
2406 while( csv_read_one_field(&sCsv) ){
2407 zCreate = sqlite3_mprintf("%z%c\n \"%s\" TEXT", zCreate, cSep, sCsv.z);
@@ -2199,11 +2423,11 @@
2423 sqlite3_errmsg(db));
2424 sqlite3_free(sCsv.z);
2425 xCloser(sCsv.in);
2426 return 1;
2427 }
2428 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
2429 }
2430 sqlite3_free(zSql);
2431 if( rc ){
2432 if (pStmt) sqlite3_finalize(pStmt);
2433 fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
@@ -2226,11 +2450,11 @@
2450 zSql[j++] = ',';
2451 zSql[j++] = '?';
2452 }
2453 zSql[j++] = ')';
2454 zSql[j] = 0;
2455 rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
2456 sqlite3_free(zSql);
2457 if( rc ){
2458 fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
2459 if (pStmt) sqlite3_finalize(pStmt);
2460 xCloser(sCsv.in);
@@ -3280,10 +3504,30 @@
3504 sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
3505 sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
3506 sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
3507 }
3508
3509 /*
3510 ** Output text to the console in a font that attracts extra attention.
3511 */
3512 #ifdef _WIN32
3513 static void printBold(const char *zText){
3514 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
3515 CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
3516 GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
3517 SetConsoleTextAttribute(out,
3518 FOREGROUND_RED|FOREGROUND_INTENSITY
3519 );
3520 printf("%s", zText);
3521 SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
3522 }
3523 #else
3524 static void printBold(const char *zText){
3525 printf("\033[1m%s\033[0m", zText);
3526 }
3527 #endif
3528
3529 /*
3530 ** Get the argument to an --option. Throw an error and die if no argument
3531 ** is available.
3532 */
3533 static char *cmdline_option_value(int argc, char **argv, int i){
@@ -3300,10 +3544,11 @@
3544 struct callback_data data;
3545 const char *zInitFile = 0;
3546 char *zFirstCmd = 0;
3547 int i;
3548 int rc = 0;
3549 int warnInmemoryDb = 0;
3550
3551 if( sqlite3_libversion_number()<3008003 ){
3552 fprintf(stderr, "Unsuitable SQLite version %s, must be at least 3.8.3",
3553 sqlite3_libversion());
3554 exit(1);
@@ -3394,18 +3639,20 @@
3639 }
3640 }
3641 if( data.zDbFilename==0 ){
3642 #ifndef SQLITE_OMIT_MEMORYDB
3643 data.zDbFilename = ":memory:";
3644 warnInmemoryDb = argc==1;
3645 #else
3646 fprintf(stderr,"%s: Error: no database filename specified\n", Argv0);
3647 return 1;
3648 #endif
3649 /***** Begin Fossil Patch *****/
3650 {
3651 extern void fossil_open(const char **);
3652 fossil_open(&data.zDbFilename);
3653 warnInmemoryDb = 0;
3654 }
3655 /***** End Fossil Patch *****/
3656 }
3657 data.out = stdout;
3658
@@ -3536,22 +3783,27 @@
3783 char *zHome;
3784 char *zHistory = 0;
3785 int nHistory;
3786 printf(
3787 "SQLite version %s %.19s\n" /*extra-version-info*/
3788 "Enter \".help\" for usage hints.\n",
 
3789 sqlite3_libversion(), sqlite3_sourceid()
3790 );
3791 if( warnInmemoryDb ){
3792 printf("Connected to a ");
3793 printBold("transient in-memory database.");
3794 printf("\nUse \".open FILENAME\" to reopen on a "
3795 "persistent database.\n");
3796 }
3797 zHome = find_home_dir();
3798 if( zHome ){
3799 nHistory = strlen30(zHome) + 20;
3800 if( (zHistory = malloc(nHistory))!=0 ){
3801 sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
3802 }
3803 }
3804 #if defined(HAVE_READLINE)
3805 if( zHistory ) read_history(zHistory);
3806 #endif
3807 rc = process_input(&data, 0);
3808 if( zHistory ){
3809 stifle_history(100);
3810
+11 -7
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
11
/******************************************************************************
22
** This file is an amalgamation of many separate C source files from SQLite
3
-** version 3.8.3. By combining all the individual C code files into this
3
+** version 3.8.3.1. By combining all the individual C code files into this
44
** single large file, the entire code can be compiled as a single translation
55
** unit. This allows many compilers to do optimizations that would not be
66
** possible if the files were compiled separately. Performance improvements
77
** of 5% or more are commonly seen when SQLite is compiled as a single
88
** translation unit.
@@ -133,13 +133,13 @@
133133
**
134134
** See also: [sqlite3_libversion()],
135135
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
136136
** [sqlite_version()] and [sqlite_source_id()].
137137
*/
138
-#define SQLITE_VERSION "3.8.3"
138
+#define SQLITE_VERSION "3.8.3.1"
139139
#define SQLITE_VERSION_NUMBER 3008003
140
-#define SQLITE_SOURCE_ID "2014-01-27 15:02:07 be1acb610f7e594b417dd8409b7a7aa8f3af5f77"
140
+#define SQLITE_SOURCE_ID "2014-02-11 14:52:19 ea3317a4803d71d88183b29f1d3086f46d68a00e"
141141
142142
/*
143143
** CAPI3REF: Run-Time Library Version Numbers
144144
** KEYWORDS: sqlite3_version, sqlite3_sourceid
145145
**
@@ -41074,11 +41074,11 @@
4107441074
** Find a page in the hash table given its page number. Return
4107541075
** a pointer to the page or NULL if the requested page is not
4107641076
** already in memory.
4107741077
*/
4107841078
static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
41079
- PgHdr *p; /* Return value */
41079
+ PgHdr *p = 0; /* Return value */
4108041080
4108141081
/* It is not possible for a call to PcacheFetch() with createFlag==0 to
4108241082
** fail, since no attempt to allocate dynamic memory will be made.
4108341083
*/
4108441084
(void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);
@@ -77453,10 +77453,11 @@
7745377453
pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
7745477454
pNew->pRightmost = 0;
7745577455
pNew->addrOpenEphm[0] = -1;
7745677456
pNew->addrOpenEphm[1] = -1;
7745777457
pNew->addrOpenEphm[2] = -1;
77458
+ pNew->nSelectRow = p->nSelectRow;
7745877459
pNew->pWith = withDup(db, p->pWith);
7745977460
return pNew;
7746077461
}
7746177462
#else
7746277463
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
@@ -89483,11 +89484,12 @@
8948389484
/* Populate the OLD.* pseudo-table register array. These values will be
8948489485
** used by any BEFORE and AFTER triggers that exist. */
8948589486
sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld);
8948689487
for(iCol=0; iCol<pTab->nCol; iCol++){
8948789488
testcase( mask!=0xffffffff && iCol==31 );
89488
- if( mask==0xffffffff || (mask & MASKBIT32(iCol))!=0 ){
89489
+ testcase( mask!=0xffffffff && iCol==32 );
89490
+ if( mask==0xffffffff || (iCol<=31 && (mask & MASKBIT32(iCol))!=0) ){
8948989491
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1);
8949089492
}
8949189493
}
8949289494
8949389495
/* Invoke BEFORE DELETE trigger programs. */
@@ -112137,11 +112139,13 @@
112137112139
int iTerm;
112138112140
for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
112139112141
Expr *pExpr = pWC->a[iTerm].pExpr;
112140112142
if( &pWC->a[iTerm] == pTerm ) continue;
112141112143
if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
112142
- if( pWC->a[iTerm].wtFlags & (TERM_ORINFO) ) continue;
112144
+ testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO );
112145
+ testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL );
112146
+ if( pWC->a[iTerm].wtFlags & (TERM_ORINFO|TERM_VIRTUAL) ) continue;
112143112147
if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
112144112148
pExpr = sqlite3ExprDup(db, pExpr, 0);
112145112149
pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
112146112150
}
112147112151
if( pAndExpr ){
@@ -122703,11 +122707,11 @@
122703122707
** database files might have arbitrary corruption. Setting the flag during
122704122708
** testing causes certain assert() statements in the code to be activated
122705122709
** that demonstrat invariants on well-formed database files.
122706122710
*/
122707122711
case SQLITE_TESTCTRL_NEVER_CORRUPT: {
122708
- sqlite3Config.neverCorrupt = va_arg(ap, int);
122712
+ sqlite3GlobalConfig.neverCorrupt = va_arg(ap, int);
122709122713
break;
122710122714
}
122711122715
122712122716
}
122713122717
va_end(ap);
122714122718
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
1 /******************************************************************************
2 ** This file is an amalgamation of many separate C source files from SQLite
3 ** version 3.8.3. By combining all the individual C code files into this
4 ** single large file, the entire code can be compiled as a single translation
5 ** unit. This allows many compilers to do optimizations that would not be
6 ** possible if the files were compiled separately. Performance improvements
7 ** of 5% or more are commonly seen when SQLite is compiled as a single
8 ** translation unit.
@@ -133,13 +133,13 @@
133 **
134 ** See also: [sqlite3_libversion()],
135 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
136 ** [sqlite_version()] and [sqlite_source_id()].
137 */
138 #define SQLITE_VERSION "3.8.3"
139 #define SQLITE_VERSION_NUMBER 3008003
140 #define SQLITE_SOURCE_ID "2014-01-27 15:02:07 be1acb610f7e594b417dd8409b7a7aa8f3af5f77"
141
142 /*
143 ** CAPI3REF: Run-Time Library Version Numbers
144 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
145 **
@@ -41074,11 +41074,11 @@
41074 ** Find a page in the hash table given its page number. Return
41075 ** a pointer to the page or NULL if the requested page is not
41076 ** already in memory.
41077 */
41078 static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
41079 PgHdr *p; /* Return value */
41080
41081 /* It is not possible for a call to PcacheFetch() with createFlag==0 to
41082 ** fail, since no attempt to allocate dynamic memory will be made.
41083 */
41084 (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);
@@ -77453,10 +77453,11 @@
77453 pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
77454 pNew->pRightmost = 0;
77455 pNew->addrOpenEphm[0] = -1;
77456 pNew->addrOpenEphm[1] = -1;
77457 pNew->addrOpenEphm[2] = -1;
 
77458 pNew->pWith = withDup(db, p->pWith);
77459 return pNew;
77460 }
77461 #else
77462 SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
@@ -89483,11 +89484,12 @@
89483 /* Populate the OLD.* pseudo-table register array. These values will be
89484 ** used by any BEFORE and AFTER triggers that exist. */
89485 sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld);
89486 for(iCol=0; iCol<pTab->nCol; iCol++){
89487 testcase( mask!=0xffffffff && iCol==31 );
89488 if( mask==0xffffffff || (mask & MASKBIT32(iCol))!=0 ){
 
89489 sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1);
89490 }
89491 }
89492
89493 /* Invoke BEFORE DELETE trigger programs. */
@@ -112137,11 +112139,13 @@
112137 int iTerm;
112138 for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
112139 Expr *pExpr = pWC->a[iTerm].pExpr;
112140 if( &pWC->a[iTerm] == pTerm ) continue;
112141 if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
112142 if( pWC->a[iTerm].wtFlags & (TERM_ORINFO) ) continue;
 
 
112143 if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
112144 pExpr = sqlite3ExprDup(db, pExpr, 0);
112145 pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
112146 }
112147 if( pAndExpr ){
@@ -122703,11 +122707,11 @@
122703 ** database files might have arbitrary corruption. Setting the flag during
122704 ** testing causes certain assert() statements in the code to be activated
122705 ** that demonstrat invariants on well-formed database files.
122706 */
122707 case SQLITE_TESTCTRL_NEVER_CORRUPT: {
122708 sqlite3Config.neverCorrupt = va_arg(ap, int);
122709 break;
122710 }
122711
122712 }
122713 va_end(ap);
122714
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
1 /******************************************************************************
2 ** This file is an amalgamation of many separate C source files from SQLite
3 ** version 3.8.3.1. By combining all the individual C code files into this
4 ** single large file, the entire code can be compiled as a single translation
5 ** unit. This allows many compilers to do optimizations that would not be
6 ** possible if the files were compiled separately. Performance improvements
7 ** of 5% or more are commonly seen when SQLite is compiled as a single
8 ** translation unit.
@@ -133,13 +133,13 @@
133 **
134 ** See also: [sqlite3_libversion()],
135 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
136 ** [sqlite_version()] and [sqlite_source_id()].
137 */
138 #define SQLITE_VERSION "3.8.3.1"
139 #define SQLITE_VERSION_NUMBER 3008003
140 #define SQLITE_SOURCE_ID "2014-02-11 14:52:19 ea3317a4803d71d88183b29f1d3086f46d68a00e"
141
142 /*
143 ** CAPI3REF: Run-Time Library Version Numbers
144 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
145 **
@@ -41074,11 +41074,11 @@
41074 ** Find a page in the hash table given its page number. Return
41075 ** a pointer to the page or NULL if the requested page is not
41076 ** already in memory.
41077 */
41078 static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
41079 PgHdr *p = 0; /* Return value */
41080
41081 /* It is not possible for a call to PcacheFetch() with createFlag==0 to
41082 ** fail, since no attempt to allocate dynamic memory will be made.
41083 */
41084 (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);
@@ -77453,10 +77453,11 @@
77453 pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
77454 pNew->pRightmost = 0;
77455 pNew->addrOpenEphm[0] = -1;
77456 pNew->addrOpenEphm[1] = -1;
77457 pNew->addrOpenEphm[2] = -1;
77458 pNew->nSelectRow = p->nSelectRow;
77459 pNew->pWith = withDup(db, p->pWith);
77460 return pNew;
77461 }
77462 #else
77463 SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
@@ -89483,11 +89484,12 @@
89484 /* Populate the OLD.* pseudo-table register array. These values will be
89485 ** used by any BEFORE and AFTER triggers that exist. */
89486 sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld);
89487 for(iCol=0; iCol<pTab->nCol; iCol++){
89488 testcase( mask!=0xffffffff && iCol==31 );
89489 testcase( mask!=0xffffffff && iCol==32 );
89490 if( mask==0xffffffff || (iCol<=31 && (mask & MASKBIT32(iCol))!=0) ){
89491 sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1);
89492 }
89493 }
89494
89495 /* Invoke BEFORE DELETE trigger programs. */
@@ -112137,11 +112139,13 @@
112139 int iTerm;
112140 for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
112141 Expr *pExpr = pWC->a[iTerm].pExpr;
112142 if( &pWC->a[iTerm] == pTerm ) continue;
112143 if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
112144 testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO );
112145 testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL );
112146 if( pWC->a[iTerm].wtFlags & (TERM_ORINFO|TERM_VIRTUAL) ) continue;
112147 if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
112148 pExpr = sqlite3ExprDup(db, pExpr, 0);
112149 pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
112150 }
112151 if( pAndExpr ){
@@ -122703,11 +122707,11 @@
122707 ** database files might have arbitrary corruption. Setting the flag during
122708 ** testing causes certain assert() statements in the code to be activated
122709 ** that demonstrat invariants on well-formed database files.
122710 */
122711 case SQLITE_TESTCTRL_NEVER_CORRUPT: {
122712 sqlite3GlobalConfig.neverCorrupt = va_arg(ap, int);
122713 break;
122714 }
122715
122716 }
122717 va_end(ap);
122718
+2 -2
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -105,13 +105,13 @@
105105
**
106106
** See also: [sqlite3_libversion()],
107107
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108108
** [sqlite_version()] and [sqlite_source_id()].
109109
*/
110
-#define SQLITE_VERSION "3.8.3"
110
+#define SQLITE_VERSION "3.8.3.1"
111111
#define SQLITE_VERSION_NUMBER 3008003
112
-#define SQLITE_SOURCE_ID "2014-01-27 15:02:07 be1acb610f7e594b417dd8409b7a7aa8f3af5f77"
112
+#define SQLITE_SOURCE_ID "2014-02-11 14:52:19 ea3317a4803d71d88183b29f1d3086f46d68a00e"
113113
114114
/*
115115
** CAPI3REF: Run-Time Library Version Numbers
116116
** KEYWORDS: sqlite3_version, sqlite3_sourceid
117117
**
118118
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -105,13 +105,13 @@
105 **
106 ** See also: [sqlite3_libversion()],
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.8.3"
111 #define SQLITE_VERSION_NUMBER 3008003
112 #define SQLITE_SOURCE_ID "2014-01-27 15:02:07 be1acb610f7e594b417dd8409b7a7aa8f3af5f77"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
118
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -105,13 +105,13 @@
105 **
106 ** See also: [sqlite3_libversion()],
107 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
108 ** [sqlite_version()] and [sqlite_source_id()].
109 */
110 #define SQLITE_VERSION "3.8.3.1"
111 #define SQLITE_VERSION_NUMBER 3008003
112 #define SQLITE_SOURCE_ID "2014-02-11 14:52:19 ea3317a4803d71d88183b29f1d3086f46d68a00e"
113
114 /*
115 ** CAPI3REF: Run-Time Library Version Numbers
116 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
117 **
118
+1 -1
--- src/stash.c
+++ src/stash.c
@@ -168,11 +168,11 @@
168168
blob_zero(&prompt);
169169
#endif
170170
blob_append(&prompt,
171171
"\n"
172172
"# Enter a description of what is being stashed. Lines beginning\n"
173
- "# with \"#\" are ignored. Stash comments are plain text except.\n"
173
+ "# with \"#\" are ignored. Stash comments are plain text except\n"
174174
"# newlines are not preserved.\n",
175175
-1);
176176
prompt_for_user_comment(&comment, &prompt);
177177
blob_reset(&prompt);
178178
zComment = blob_str(&comment);
179179
--- src/stash.c
+++ src/stash.c
@@ -168,11 +168,11 @@
168 blob_zero(&prompt);
169 #endif
170 blob_append(&prompt,
171 "\n"
172 "# Enter a description of what is being stashed. Lines beginning\n"
173 "# with \"#\" are ignored. Stash comments are plain text except.\n"
174 "# newlines are not preserved.\n",
175 -1);
176 prompt_for_user_comment(&comment, &prompt);
177 blob_reset(&prompt);
178 zComment = blob_str(&comment);
179
--- src/stash.c
+++ src/stash.c
@@ -168,11 +168,11 @@
168 blob_zero(&prompt);
169 #endif
170 blob_append(&prompt,
171 "\n"
172 "# Enter a description of what is being stashed. Lines beginning\n"
173 "# with \"#\" are ignored. Stash comments are plain text except\n"
174 "# newlines are not preserved.\n",
175 -1);
176 prompt_for_user_comment(&comment, &prompt);
177 blob_reset(&prompt);
178 zComment = blob_str(&comment);
179
+4 -8
--- src/style.c
+++ src/style.c
@@ -163,12 +163,11 @@
163163
void style_resolve_href(void){
164164
int i;
165165
int nDelay = db_get_int("auto-hyperlink-delay",10);
166166
if( !g.perm.Hyperlink ) return;
167167
if( nHref==0 && nFormAction==0 ) return;
168
- @ <script type="text/JavaScript">
169
- @ /* <![CDATA[ */
168
+ @ <script>
170169
@ function setAllHrefs(){
171170
if( g.javascriptHyperlink ){
172171
for(i=0; i<nHref; i++){
173172
@ gebi("a%d(i+1)").href="%s(aHref[i])";
174173
}
@@ -192,11 +191,10 @@
192191
@ }
193192
}else{
194193
/* Active hyperlinks right away */
195194
@ setTimeout("setAllHrefs();",%d(nDelay));
196195
}
197
- @ /* ]]> */
198196
@ </script>
199197
}
200198
201199
/*
202200
** Add a new element to the submenu
@@ -794,10 +792,12 @@
794792
@ margin: 0 0 0 21px;
795793
},
796794
{ ".filetree li",
797795
"tree-view lists items",
798796
@ position: relative;
797
+ @ margin: 0;
798
+ @ padding: 0;
799799
},
800800
{ ".filetree li li:before",
801801
"tree-view node lines",
802802
@ content: '';
803803
@ position: absolute;
@@ -1156,11 +1156,11 @@
11561156
@ vertical-align: top;
11571157
@ text-align: right;
11581158
@ padding: 0.2ex 2ex;
11591159
},
11601160
{ ".statistics-report-graph-line",
1161
- "for the /stats_report views",
1161
+ "for the /reports views",
11621162
@ background-color: #446979;
11631163
},
11641164
{ ".statistics-report-table-events th",
11651165
"",
11661166
@ padding: 0 1em 0 1em;
@@ -1171,14 +1171,10 @@
11711171
},
11721172
{ ".statistics-report-row-year",
11731173
"",
11741174
@ text-align: left;
11751175
},
1176
- { ".statistics-report-graph-line",
1177
- "for the /stats_report views",
1178
- @ background-color: #446979;
1179
- },
11801176
{ ".statistics-report-week-number-label",
11811177
"for the /stats_report views",
11821178
@ text-align: right;
11831179
@ font-size: 0.8em;
11841180
},
11851181
--- src/style.c
+++ src/style.c
@@ -163,12 +163,11 @@
163 void style_resolve_href(void){
164 int i;
165 int nDelay = db_get_int("auto-hyperlink-delay",10);
166 if( !g.perm.Hyperlink ) return;
167 if( nHref==0 && nFormAction==0 ) return;
168 @ <script type="text/JavaScript">
169 @ /* <![CDATA[ */
170 @ function setAllHrefs(){
171 if( g.javascriptHyperlink ){
172 for(i=0; i<nHref; i++){
173 @ gebi("a%d(i+1)").href="%s(aHref[i])";
174 }
@@ -192,11 +191,10 @@
192 @ }
193 }else{
194 /* Active hyperlinks right away */
195 @ setTimeout("setAllHrefs();",%d(nDelay));
196 }
197 @ /* ]]> */
198 @ </script>
199 }
200
201 /*
202 ** Add a new element to the submenu
@@ -794,10 +792,12 @@
794 @ margin: 0 0 0 21px;
795 },
796 { ".filetree li",
797 "tree-view lists items",
798 @ position: relative;
 
 
799 },
800 { ".filetree li li:before",
801 "tree-view node lines",
802 @ content: '';
803 @ position: absolute;
@@ -1156,11 +1156,11 @@
1156 @ vertical-align: top;
1157 @ text-align: right;
1158 @ padding: 0.2ex 2ex;
1159 },
1160 { ".statistics-report-graph-line",
1161 "for the /stats_report views",
1162 @ background-color: #446979;
1163 },
1164 { ".statistics-report-table-events th",
1165 "",
1166 @ padding: 0 1em 0 1em;
@@ -1171,14 +1171,10 @@
1171 },
1172 { ".statistics-report-row-year",
1173 "",
1174 @ text-align: left;
1175 },
1176 { ".statistics-report-graph-line",
1177 "for the /stats_report views",
1178 @ background-color: #446979;
1179 },
1180 { ".statistics-report-week-number-label",
1181 "for the /stats_report views",
1182 @ text-align: right;
1183 @ font-size: 0.8em;
1184 },
1185
--- src/style.c
+++ src/style.c
@@ -163,12 +163,11 @@
163 void style_resolve_href(void){
164 int i;
165 int nDelay = db_get_int("auto-hyperlink-delay",10);
166 if( !g.perm.Hyperlink ) return;
167 if( nHref==0 && nFormAction==0 ) return;
168 @ <script>
 
169 @ function setAllHrefs(){
170 if( g.javascriptHyperlink ){
171 for(i=0; i<nHref; i++){
172 @ gebi("a%d(i+1)").href="%s(aHref[i])";
173 }
@@ -192,11 +191,10 @@
191 @ }
192 }else{
193 /* Active hyperlinks right away */
194 @ setTimeout("setAllHrefs();",%d(nDelay));
195 }
 
196 @ </script>
197 }
198
199 /*
200 ** Add a new element to the submenu
@@ -794,10 +792,12 @@
792 @ margin: 0 0 0 21px;
793 },
794 { ".filetree li",
795 "tree-view lists items",
796 @ position: relative;
797 @ margin: 0;
798 @ padding: 0;
799 },
800 { ".filetree li li:before",
801 "tree-view node lines",
802 @ content: '';
803 @ position: absolute;
@@ -1156,11 +1156,11 @@
1156 @ vertical-align: top;
1157 @ text-align: right;
1158 @ padding: 0.2ex 2ex;
1159 },
1160 { ".statistics-report-graph-line",
1161 "for the /reports views",
1162 @ background-color: #446979;
1163 },
1164 { ".statistics-report-table-events th",
1165 "",
1166 @ padding: 0 1em 0 1em;
@@ -1171,14 +1171,10 @@
1171 },
1172 { ".statistics-report-row-year",
1173 "",
1174 @ text-align: left;
1175 },
 
 
 
 
1176 { ".statistics-report-week-number-label",
1177 "for the /stats_report views",
1178 @ text-align: right;
1179 @ font-size: 0.8em;
1180 },
1181
-6
--- src/tag.c
+++ src/tag.c
@@ -595,13 +595,7 @@
595595
timeline_query_for_www()
596596
);
597597
www_print_timeline(&q, 0, 0, 0, 0);
598598
db_finalize(&q);
599599
@ <br />
600
- @ <script type="text/JavaScript">
601
- @ function xin(id){
602
- @ }
603
- @ function xout(id){
604
- @ }
605
- @ </script>
606600
style_footer();
607601
}
608602
--- src/tag.c
+++ src/tag.c
@@ -595,13 +595,7 @@
595 timeline_query_for_www()
596 );
597 www_print_timeline(&q, 0, 0, 0, 0);
598 db_finalize(&q);
599 @ <br />
600 @ <script type="text/JavaScript">
601 @ function xin(id){
602 @ }
603 @ function xout(id){
604 @ }
605 @ </script>
606 style_footer();
607 }
608
--- src/tag.c
+++ src/tag.c
@@ -595,13 +595,7 @@
595 timeline_query_for_www()
596 );
597 www_print_timeline(&q, 0, 0, 0, 0);
598 db_finalize(&q);
599 @ <br />
 
 
 
 
 
 
600 style_footer();
601 }
602
+14 -12
--- src/th.c
+++ src/th.c
@@ -2002,27 +2002,29 @@
20022002
default: assert(!"Internal error");
20032003
}
20042004
Th_SetResultInt(interp, iRes);
20052005
}else if( rc==TH_OK && eArgType==ARG_NUMBER ){
20062006
switch( pExpr->pOp->eOp ) {
2007
- case OP_MULTIPLY: Th_SetResultDouble(interp, fLeft*fRight); break;
2007
+ case OP_MULTIPLY: Th_SetResultDouble(interp, fLeft*fRight); break;
20082008
case OP_DIVIDE:
20092009
if( fRight==0.0 ){
20102010
Th_ErrorMessage(interp, "Divide by 0:", zLeft, nLeft);
20112011
rc = TH_ERROR;
20122012
goto finish;
20132013
}
20142014
Th_SetResultDouble(interp, fLeft/fRight);
20152015
break;
2016
- case OP_ADD: Th_SetResultDouble(interp, fLeft+fRight); break;
2017
- case OP_SUBTRACT: Th_SetResultDouble(interp, fLeft-fRight); break;
2018
- case OP_LT: Th_SetResultInt(interp, fLeft<fRight); break;
2019
- case OP_GT: Th_SetResultInt(interp, fLeft>fRight); break;
2020
- case OP_LE: Th_SetResultInt(interp, fLeft<=fRight); break;
2021
- case OP_GE: Th_SetResultInt(interp, fLeft>=fRight); break;
2022
- case OP_EQ: Th_SetResultInt(interp, fLeft==fRight); break;
2023
- case OP_NE: Th_SetResultInt(interp, fLeft!=fRight); break;
2016
+ case OP_ADD: Th_SetResultDouble(interp, fLeft+fRight); break;
2017
+ case OP_SUBTRACT: Th_SetResultDouble(interp, fLeft-fRight); break;
2018
+ case OP_LT: Th_SetResultInt(interp, fLeft<fRight); break;
2019
+ case OP_GT: Th_SetResultInt(interp, fLeft>fRight); break;
2020
+ case OP_LE: Th_SetResultInt(interp, fLeft<=fRight); break;
2021
+ case OP_GE: Th_SetResultInt(interp, fLeft>=fRight); break;
2022
+ case OP_EQ: Th_SetResultInt(interp, fLeft==fRight); break;
2023
+ case OP_NE: Th_SetResultInt(interp, fLeft!=fRight); break;
2024
+ case OP_UNARY_MINUS: Th_SetResultDouble(interp, -fLeft); break;
2025
+ case OP_UNARY_PLUS: Th_SetResultDouble(interp, +fLeft); break;
20242026
default: assert(!"Internal error");
20252027
}
20262028
}else if( rc==TH_OK ){
20272029
int iEqual = 0;
20282030
assert( eArgType==ARG_STRING );
@@ -2629,13 +2631,13 @@
26292631
if( iVal<0 ){
26302632
isNegative = 1;
26312633
iVal = iVal * -1;
26322634
}
26332635
*(--z) = '\0';
2634
- *(--z) = (char)(48+(iVal%10));
2635
- while( (iVal = (iVal/10))>0 ){
2636
- *(--z) = (char)(48+(iVal%10));
2636
+ *(--z) = (char)(48+((unsigned)iVal%10));
2637
+ while( (iVal = ((unsigned)iVal/10))>0 ){
2638
+ *(--z) = (char)(48+((unsigned)iVal%10));
26372639
assert(z>zBuf);
26382640
}
26392641
if( isNegative ){
26402642
*(--z) = '-';
26412643
}
26422644
--- src/th.c
+++ src/th.c
@@ -2002,27 +2002,29 @@
2002 default: assert(!"Internal error");
2003 }
2004 Th_SetResultInt(interp, iRes);
2005 }else if( rc==TH_OK && eArgType==ARG_NUMBER ){
2006 switch( pExpr->pOp->eOp ) {
2007 case OP_MULTIPLY: Th_SetResultDouble(interp, fLeft*fRight); break;
2008 case OP_DIVIDE:
2009 if( fRight==0.0 ){
2010 Th_ErrorMessage(interp, "Divide by 0:", zLeft, nLeft);
2011 rc = TH_ERROR;
2012 goto finish;
2013 }
2014 Th_SetResultDouble(interp, fLeft/fRight);
2015 break;
2016 case OP_ADD: Th_SetResultDouble(interp, fLeft+fRight); break;
2017 case OP_SUBTRACT: Th_SetResultDouble(interp, fLeft-fRight); break;
2018 case OP_LT: Th_SetResultInt(interp, fLeft<fRight); break;
2019 case OP_GT: Th_SetResultInt(interp, fLeft>fRight); break;
2020 case OP_LE: Th_SetResultInt(interp, fLeft<=fRight); break;
2021 case OP_GE: Th_SetResultInt(interp, fLeft>=fRight); break;
2022 case OP_EQ: Th_SetResultInt(interp, fLeft==fRight); break;
2023 case OP_NE: Th_SetResultInt(interp, fLeft!=fRight); break;
 
 
2024 default: assert(!"Internal error");
2025 }
2026 }else if( rc==TH_OK ){
2027 int iEqual = 0;
2028 assert( eArgType==ARG_STRING );
@@ -2629,13 +2631,13 @@
2629 if( iVal<0 ){
2630 isNegative = 1;
2631 iVal = iVal * -1;
2632 }
2633 *(--z) = '\0';
2634 *(--z) = (char)(48+(iVal%10));
2635 while( (iVal = (iVal/10))>0 ){
2636 *(--z) = (char)(48+(iVal%10));
2637 assert(z>zBuf);
2638 }
2639 if( isNegative ){
2640 *(--z) = '-';
2641 }
2642
--- src/th.c
+++ src/th.c
@@ -2002,27 +2002,29 @@
2002 default: assert(!"Internal error");
2003 }
2004 Th_SetResultInt(interp, iRes);
2005 }else if( rc==TH_OK && eArgType==ARG_NUMBER ){
2006 switch( pExpr->pOp->eOp ) {
2007 case OP_MULTIPLY: Th_SetResultDouble(interp, fLeft*fRight); break;
2008 case OP_DIVIDE:
2009 if( fRight==0.0 ){
2010 Th_ErrorMessage(interp, "Divide by 0:", zLeft, nLeft);
2011 rc = TH_ERROR;
2012 goto finish;
2013 }
2014 Th_SetResultDouble(interp, fLeft/fRight);
2015 break;
2016 case OP_ADD: Th_SetResultDouble(interp, fLeft+fRight); break;
2017 case OP_SUBTRACT: Th_SetResultDouble(interp, fLeft-fRight); break;
2018 case OP_LT: Th_SetResultInt(interp, fLeft<fRight); break;
2019 case OP_GT: Th_SetResultInt(interp, fLeft>fRight); break;
2020 case OP_LE: Th_SetResultInt(interp, fLeft<=fRight); break;
2021 case OP_GE: Th_SetResultInt(interp, fLeft>=fRight); break;
2022 case OP_EQ: Th_SetResultInt(interp, fLeft==fRight); break;
2023 case OP_NE: Th_SetResultInt(interp, fLeft!=fRight); break;
2024 case OP_UNARY_MINUS: Th_SetResultDouble(interp, -fLeft); break;
2025 case OP_UNARY_PLUS: Th_SetResultDouble(interp, +fLeft); break;
2026 default: assert(!"Internal error");
2027 }
2028 }else if( rc==TH_OK ){
2029 int iEqual = 0;
2030 assert( eArgType==ARG_STRING );
@@ -2629,13 +2631,13 @@
2631 if( iVal<0 ){
2632 isNegative = 1;
2633 iVal = iVal * -1;
2634 }
2635 *(--z) = '\0';
2636 *(--z) = (char)(48+((unsigned)iVal%10));
2637 while( (iVal = ((unsigned)iVal/10))>0 ){
2638 *(--z) = (char)(48+((unsigned)iVal%10));
2639 assert(z>zBuf);
2640 }
2641 if( isNegative ){
2642 *(--z) = '-';
2643 }
2644
+6 -2
--- src/th.h
+++ src/th.h
@@ -157,12 +157,16 @@
157157
int th_register_sqlite(Th_Interp *interp); /* th_sqlite.c */
158158
int th_register_vfs(Th_Interp *interp); /* th_vfs.c */
159159
int th_register_testvfs(Th_Interp *interp); /* th_testvfs.c */
160160
161161
#ifdef FOSSIL_ENABLE_TCL
162
-int th_register_tcl(Th_Interp *interp, void *pContext); /* th_tcl.c */
163
-int unloadTcl(Th_Interp *interp, void *pContext); /* th_tcl.c */
162
+/*
163
+** Interfaces to the full Tcl core library from "th_tcl.c".
164
+*/
165
+int th_register_tcl(Th_Interp *, void *);
166
+int unloadTcl(Th_Interp *, void *);
167
+int evaluateTclWithEvents(Th_Interp *, void *, const char *, int, int);
164168
#endif
165169
166170
/*
167171
** General purpose hash table from th_lang.c.
168172
*/
169173
--- src/th.h
+++ src/th.h
@@ -157,12 +157,16 @@
157 int th_register_sqlite(Th_Interp *interp); /* th_sqlite.c */
158 int th_register_vfs(Th_Interp *interp); /* th_vfs.c */
159 int th_register_testvfs(Th_Interp *interp); /* th_testvfs.c */
160
161 #ifdef FOSSIL_ENABLE_TCL
162 int th_register_tcl(Th_Interp *interp, void *pContext); /* th_tcl.c */
163 int unloadTcl(Th_Interp *interp, void *pContext); /* th_tcl.c */
 
 
 
 
164 #endif
165
166 /*
167 ** General purpose hash table from th_lang.c.
168 */
169
--- src/th.h
+++ src/th.h
@@ -157,12 +157,16 @@
157 int th_register_sqlite(Th_Interp *interp); /* th_sqlite.c */
158 int th_register_vfs(Th_Interp *interp); /* th_vfs.c */
159 int th_register_testvfs(Th_Interp *interp); /* th_testvfs.c */
160
161 #ifdef FOSSIL_ENABLE_TCL
162 /*
163 ** Interfaces to the full Tcl core library from "th_tcl.c".
164 */
165 int th_register_tcl(Th_Interp *, void *);
166 int unloadTcl(Th_Interp *, void *);
167 int evaluateTclWithEvents(Th_Interp *, void *, const char *, int, int);
168 #endif
169
170 /*
171 ** General purpose hash table from th_lang.c.
172 */
173
--- src/th_main.c
+++ src/th_main.c
@@ -97,10 +97,33 @@
9797
fossil_print("\n------------------ BEGIN TRACE LOG ------------------\n");
9898
fossil_print("%s", blob_str(&g.thLog));
9999
fossil_print("\n------------------- END TRACE LOG -------------------\n");
100100
}
101101
}
102
+
103
+/*
104
+** TH command: httpize STRING
105
+**
106
+** Escape all characters of STRING which have special meaning in URI
107
+** components. Return a new string result.
108
+*/
109
+static int httpizeCmd(
110
+ Th_Interp *interp,
111
+ void *p,
112
+ int argc,
113
+ const char **argv,
114
+ int *argl
115
+){
116
+ char *zOut;
117
+ if( argc!=2 ){
118
+ return Th_WrongNumArgs(interp, "httpize STRING");
119
+ }
120
+ zOut = httpize((char*)argv[1], argl[1]);
121
+ Th_SetResult(interp, zOut, -1);
122
+ free(zOut);
123
+ return TH_OK;
124
+}
102125
103126
/*
104127
** True if output is enabled. False if disabled.
105128
*/
106129
static int enableOutput = 1;
@@ -972,10 +995,11 @@
972995
{"anycap", anycapCmd, 0},
973996
{"combobox", comboboxCmd, 0},
974997
{"date", dateCmd, 0},
975998
{"decorate", wikiCmd, (void*)&aFlags[2]},
976999
{"enable_output", enableOutputCmd, 0},
1000
+ {"httpize", httpizeCmd, 0},
9771001
{"hascap", hascapCmd, 0},
9781002
{"hasfeature", hasfeatureCmd, 0},
9791003
{"html", putsCmd, (void*)&aFlags[0]},
9801004
{"htmlize", htmlizeCmd, 0},
9811005
{"http", httpCmd, 0},
9821006
--- src/th_main.c
+++ src/th_main.c
@@ -97,10 +97,33 @@
97 fossil_print("\n------------------ BEGIN TRACE LOG ------------------\n");
98 fossil_print("%s", blob_str(&g.thLog));
99 fossil_print("\n------------------- END TRACE LOG -------------------\n");
100 }
101 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
103 /*
104 ** True if output is enabled. False if disabled.
105 */
106 static int enableOutput = 1;
@@ -972,10 +995,11 @@
972 {"anycap", anycapCmd, 0},
973 {"combobox", comboboxCmd, 0},
974 {"date", dateCmd, 0},
975 {"decorate", wikiCmd, (void*)&aFlags[2]},
976 {"enable_output", enableOutputCmd, 0},
 
977 {"hascap", hascapCmd, 0},
978 {"hasfeature", hasfeatureCmd, 0},
979 {"html", putsCmd, (void*)&aFlags[0]},
980 {"htmlize", htmlizeCmd, 0},
981 {"http", httpCmd, 0},
982
--- src/th_main.c
+++ src/th_main.c
@@ -97,10 +97,33 @@
97 fossil_print("\n------------------ BEGIN TRACE LOG ------------------\n");
98 fossil_print("%s", blob_str(&g.thLog));
99 fossil_print("\n------------------- END TRACE LOG -------------------\n");
100 }
101 }
102
103 /*
104 ** TH command: httpize STRING
105 **
106 ** Escape all characters of STRING which have special meaning in URI
107 ** components. Return a new string result.
108 */
109 static int httpizeCmd(
110 Th_Interp *interp,
111 void *p,
112 int argc,
113 const char **argv,
114 int *argl
115 ){
116 char *zOut;
117 if( argc!=2 ){
118 return Th_WrongNumArgs(interp, "httpize STRING");
119 }
120 zOut = httpize((char*)argv[1], argl[1]);
121 Th_SetResult(interp, zOut, -1);
122 free(zOut);
123 return TH_OK;
124 }
125
126 /*
127 ** True if output is enabled. False if disabled.
128 */
129 static int enableOutput = 1;
@@ -972,10 +995,11 @@
995 {"anycap", anycapCmd, 0},
996 {"combobox", comboboxCmd, 0},
997 {"date", dateCmd, 0},
998 {"decorate", wikiCmd, (void*)&aFlags[2]},
999 {"enable_output", enableOutputCmd, 0},
1000 {"httpize", httpizeCmd, 0},
1001 {"hascap", hascapCmd, 0},
1002 {"hasfeature", hasfeatureCmd, 0},
1003 {"html", putsCmd, (void*)&aFlags[0]},
1004 {"htmlize", htmlizeCmd, 0},
1005 {"http", httpCmd, 0},
1006
+32
--- src/th_tcl.c
+++ src/th_tcl.c
@@ -766,10 +766,42 @@
766766
}
767767
}
768768
Tcl_DecrRefCount(listPtr);
769769
return rc;
770770
}
771
+
772
+/*
773
+** Evaluate a Tcl script, creating the Tcl interpreter if necessary. If the
774
+** Tcl script succeeds, start a Tcl event loop until there are no more events
775
+** remaining to process -OR- the script calls [exit]. If the bWait argument
776
+** is zero, only process events that are already in the queue; otherwise,
777
+** process events until the script terminates the Tcl event loop.
778
+*/
779
+int evaluateTclWithEvents(
780
+ Th_Interp *interp,
781
+ void *pContext,
782
+ const char *zScript,
783
+ int nScript,
784
+ int bWait
785
+){
786
+ struct TclContext *tclContext = (struct TclContext *)pContext;
787
+ Tcl_Interp *tclInterp;
788
+ int rc;
789
+ int flags = TCL_ALL_EVENTS;
790
+
791
+ if( createTclInterp(interp, pContext)!=TH_OK ){
792
+ return TH_ERROR;
793
+ }
794
+ tclInterp = tclContext->interp;
795
+ rc = Tcl_EvalEx(tclInterp, zScript, nScript, TCL_EVAL_GLOBAL);
796
+ if( rc!=TCL_OK ) return rc;
797
+ if( !bWait ) flags |= TCL_DONT_WAIT;
798
+ while( Tcl_DoOneEvent(flags) ){
799
+ /* do nothing */
800
+ }
801
+ return rc;
802
+}
771803
772804
/*
773805
** Creates and initializes a Tcl interpreter for use with the specified TH1
774806
** interpreter. Stores the created Tcl interpreter in the Tcl context supplied
775807
** by the caller.
776808
--- src/th_tcl.c
+++ src/th_tcl.c
@@ -766,10 +766,42 @@
766 }
767 }
768 Tcl_DecrRefCount(listPtr);
769 return rc;
770 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
771
772 /*
773 ** Creates and initializes a Tcl interpreter for use with the specified TH1
774 ** interpreter. Stores the created Tcl interpreter in the Tcl context supplied
775 ** by the caller.
776
--- src/th_tcl.c
+++ src/th_tcl.c
@@ -766,10 +766,42 @@
766 }
767 }
768 Tcl_DecrRefCount(listPtr);
769 return rc;
770 }
771
772 /*
773 ** Evaluate a Tcl script, creating the Tcl interpreter if necessary. If the
774 ** Tcl script succeeds, start a Tcl event loop until there are no more events
775 ** remaining to process -OR- the script calls [exit]. If the bWait argument
776 ** is zero, only process events that are already in the queue; otherwise,
777 ** process events until the script terminates the Tcl event loop.
778 */
779 int evaluateTclWithEvents(
780 Th_Interp *interp,
781 void *pContext,
782 const char *zScript,
783 int nScript,
784 int bWait
785 ){
786 struct TclContext *tclContext = (struct TclContext *)pContext;
787 Tcl_Interp *tclInterp;
788 int rc;
789 int flags = TCL_ALL_EVENTS;
790
791 if( createTclInterp(interp, pContext)!=TH_OK ){
792 return TH_ERROR;
793 }
794 tclInterp = tclContext->interp;
795 rc = Tcl_EvalEx(tclInterp, zScript, nScript, TCL_EVAL_GLOBAL);
796 if( rc!=TCL_OK ) return rc;
797 if( !bWait ) flags |= TCL_DONT_WAIT;
798 while( Tcl_DoOneEvent(flags) ){
799 /* do nothing */
800 }
801 return rc;
802 }
803
804 /*
805 ** Creates and initializes a Tcl interpreter for use with the specified TH1
806 ** interpreter. Stores the created Tcl interpreter in the Tcl context supplied
807 ** by the caller.
808
+6 -8
--- src/timeline.c
+++ src/timeline.c
@@ -592,12 +592,11 @@
592592
if( pGraph && pGraph->nErr==0 && pGraph->nRow>0 ){
593593
GraphRow *pRow;
594594
int i;
595595
char cSep;
596596
597
- @ <script type="text/JavaScript">
598
- @ /* <![CDATA[ */
597
+ @ <script>
599598
@ var railPitch=%d(pGraph->iRailPitch);
600599
601600
/* the rowinfo[] array contains all the information needed to generate
602601
** the graph. Each entry contains information for a single row:
603602
**
@@ -872,11 +871,10 @@
872871
@ lastY = h;
873872
@ }
874873
@ setTimeout("checkHeight();", 1000);
875874
@ }
876875
@ checkHeight();
877
- @ /* ]]> */
878876
@ </script>
879877
}
880878
}
881879
882880
/*
@@ -2278,12 +2276,12 @@
22782276
cgi_printf("'>%s</a>", zTimeframe);
22792277
}
22802278
@ </td><td>%d(nCount)</td>
22812279
@ <td>
22822280
@ <div class='statistics-report-graph-line'
2283
- @ style='height:16px;width:%d(nSize)%%;'>
2284
- @ </div></td>
2281
+ @ style='width:%d(nSize)%%;'>&nbsp;</div>
2282
+ @ </td>
22852283
@</tr>
22862284
if(includeWeeks){
22872285
/* This part works fine for months but it terribly slow (4.5s on my PC),
22882286
so it's only shown for by-year for now. Suggestions/patches for
22892287
a better/faster layout are welcomed. */
@@ -2373,12 +2371,12 @@
23732371
@ <td>
23742372
@ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a>
23752373
@ </td><td>%d(nCount)</td>
23762374
@ <td>
23772375
@ <div class='statistics-report-graph-line'
2378
- @ style='height:16px;width:%d(nSize)%%;'>
2379
- @ </div></td>
2376
+ @ style='width:%d(nSize)%%;'>&nbsp;</div>
2377
+ @ </td>
23802378
@</tr>
23812379
/*
23822380
Potential improvement: calculate the min/max event counts and
23832381
use percent-based graph bars.
23842382
*/
@@ -2502,11 +2500,11 @@
25022500
25032501
cgi_printf("<td>%d</td>",nCount);
25042502
cgi_printf("<td>");
25052503
if(nCount){
25062504
cgi_printf("<div class='statistics-report-graph-line'"
2507
- "style='height:16px;width:%d%%;'></div>",
2505
+ "style='width:%d%%;'>&nbsp;</div>",
25082506
nSize);
25092507
}
25102508
cgi_printf("</td></tr>");
25112509
}
25122510
db_finalize(&stWeek);
25132511
--- src/timeline.c
+++ src/timeline.c
@@ -592,12 +592,11 @@
592 if( pGraph && pGraph->nErr==0 && pGraph->nRow>0 ){
593 GraphRow *pRow;
594 int i;
595 char cSep;
596
597 @ <script type="text/JavaScript">
598 @ /* <![CDATA[ */
599 @ var railPitch=%d(pGraph->iRailPitch);
600
601 /* the rowinfo[] array contains all the information needed to generate
602 ** the graph. Each entry contains information for a single row:
603 **
@@ -872,11 +871,10 @@
872 @ lastY = h;
873 @ }
874 @ setTimeout("checkHeight();", 1000);
875 @ }
876 @ checkHeight();
877 @ /* ]]> */
878 @ </script>
879 }
880 }
881
882 /*
@@ -2278,12 +2276,12 @@
2278 cgi_printf("'>%s</a>", zTimeframe);
2279 }
2280 @ </td><td>%d(nCount)</td>
2281 @ <td>
2282 @ <div class='statistics-report-graph-line'
2283 @ style='height:16px;width:%d(nSize)%%;'>
2284 @ </div></td>
2285 @</tr>
2286 if(includeWeeks){
2287 /* This part works fine for months but it terribly slow (4.5s on my PC),
2288 so it's only shown for by-year for now. Suggestions/patches for
2289 a better/faster layout are welcomed. */
@@ -2373,12 +2371,12 @@
2373 @ <td>
2374 @ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a>
2375 @ </td><td>%d(nCount)</td>
2376 @ <td>
2377 @ <div class='statistics-report-graph-line'
2378 @ style='height:16px;width:%d(nSize)%%;'>
2379 @ </div></td>
2380 @</tr>
2381 /*
2382 Potential improvement: calculate the min/max event counts and
2383 use percent-based graph bars.
2384 */
@@ -2502,11 +2500,11 @@
2502
2503 cgi_printf("<td>%d</td>",nCount);
2504 cgi_printf("<td>");
2505 if(nCount){
2506 cgi_printf("<div class='statistics-report-graph-line'"
2507 "style='height:16px;width:%d%%;'></div>",
2508 nSize);
2509 }
2510 cgi_printf("</td></tr>");
2511 }
2512 db_finalize(&stWeek);
2513
--- src/timeline.c
+++ src/timeline.c
@@ -592,12 +592,11 @@
592 if( pGraph && pGraph->nErr==0 && pGraph->nRow>0 ){
593 GraphRow *pRow;
594 int i;
595 char cSep;
596
597 @ <script>
 
598 @ var railPitch=%d(pGraph->iRailPitch);
599
600 /* the rowinfo[] array contains all the information needed to generate
601 ** the graph. Each entry contains information for a single row:
602 **
@@ -872,11 +871,10 @@
871 @ lastY = h;
872 @ }
873 @ setTimeout("checkHeight();", 1000);
874 @ }
875 @ checkHeight();
 
876 @ </script>
877 }
878 }
879
880 /*
@@ -2278,12 +2276,12 @@
2276 cgi_printf("'>%s</a>", zTimeframe);
2277 }
2278 @ </td><td>%d(nCount)</td>
2279 @ <td>
2280 @ <div class='statistics-report-graph-line'
2281 @ style='width:%d(nSize)%%;'>&nbsp;</div>
2282 @ </td>
2283 @</tr>
2284 if(includeWeeks){
2285 /* This part works fine for months but it terribly slow (4.5s on my PC),
2286 so it's only shown for by-year for now. Suggestions/patches for
2287 a better/faster layout are welcomed. */
@@ -2373,12 +2371,12 @@
2371 @ <td>
2372 @ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a>
2373 @ </td><td>%d(nCount)</td>
2374 @ <td>
2375 @ <div class='statistics-report-graph-line'
2376 @ style='width:%d(nSize)%%;'>&nbsp;</div>
2377 @ </td>
2378 @</tr>
2379 /*
2380 Potential improvement: calculate the min/max event counts and
2381 use percent-based graph bars.
2382 */
@@ -2502,11 +2500,11 @@
2500
2501 cgi_printf("<td>%d</td>",nCount);
2502 cgi_printf("<td>");
2503 if(nCount){
2504 cgi_printf("<div class='statistics-report-graph-line'"
2505 "style='width:%d%%;'>&nbsp;</div>",
2506 nSize);
2507 }
2508 cgi_printf("</td></tr>");
2509 }
2510 db_finalize(&stWeek);
2511
+11
--- src/url.c
+++ src/url.c
@@ -62,10 +62,13 @@
6262
char *passwd; /* Password for http: */
6363
char *canonical; /* Canonical representation of the URL */
6464
char *proxyAuth; /* Proxy-Authorizer: string */
6565
char *fossil; /* The fossil query parameter on ssh: */
6666
unsigned flags; /* Boolean flags controlling URL processing */
67
+ int useProxy; /* Used to remember that a proxy is in use */
68
+ char *proxyUrlPath;
69
+ int proxyOrigPort; /* Tunneled port number for https through proxy */
6770
};
6871
#endif /* INTERFACE */
6972
7073
7174
/*
@@ -120,10 +123,11 @@
120123
char *zLogin;
121124
char *zExe;
122125
char cQuerySep = '?';
123126
124127
pUrlData->isFile = 0;
128
+ pUrlData->useProxy = 0;
125129
if( zUrl[4]=='s' ){
126130
pUrlData->isHttps = 1;
127131
pUrlData->protocol = "https";
128132
pUrlData->dfltPort = 443;
129133
iStart = 8;
@@ -384,12 +388,15 @@
384388
}
385389
if( zProxy && zProxy[0] && !is_false(zProxy)
386390
&& !g.urlIsSsh && !g.urlIsFile ){
387391
char *zOriginalUrl = g.urlCanonical;
388392
char *zOriginalHost = g.urlHostname;
393
+ int fOriginalIsHttps = g.urlIsHttps;
389394
char *zOriginalUser = g.urlUser;
390395
char *zOriginalPasswd = g.urlPasswd;
396
+ char *zOriginalUrlPath = g.urlPath;
397
+ int iOriginalPort = g.urlPort;
391398
unsigned uOriginalFlags = g.urlFlags;
392399
g.urlUser = 0;
393400
g.urlPasswd = "";
394401
url_parse(zProxy, 0);
395402
if( zMsg ) fossil_print("%s%s\n", zMsg, g.urlCanonical);
@@ -401,10 +408,14 @@
401408
g.urlProxyAuth = mprintf("Basic %z", zCredentials2);
402409
free(zCredentials1);
403410
}
404411
g.urlUser = zOriginalUser;
405412
g.urlPasswd = zOriginalPasswd;
413
+ g.urlIsHttps = fOriginalIsHttps;
414
+ g.useProxy = 1;
415
+ g.proxyUrlPath = zOriginalUrlPath;
416
+ g.proxyOrigPort = iOriginalPort;
406417
g.urlFlags = uOriginalFlags;
407418
}
408419
}
409420
410421
#if INTERFACE
411422
--- src/url.c
+++ src/url.c
@@ -62,10 +62,13 @@
62 char *passwd; /* Password for http: */
63 char *canonical; /* Canonical representation of the URL */
64 char *proxyAuth; /* Proxy-Authorizer: string */
65 char *fossil; /* The fossil query parameter on ssh: */
66 unsigned flags; /* Boolean flags controlling URL processing */
 
 
 
67 };
68 #endif /* INTERFACE */
69
70
71 /*
@@ -120,10 +123,11 @@
120 char *zLogin;
121 char *zExe;
122 char cQuerySep = '?';
123
124 pUrlData->isFile = 0;
 
125 if( zUrl[4]=='s' ){
126 pUrlData->isHttps = 1;
127 pUrlData->protocol = "https";
128 pUrlData->dfltPort = 443;
129 iStart = 8;
@@ -384,12 +388,15 @@
384 }
385 if( zProxy && zProxy[0] && !is_false(zProxy)
386 && !g.urlIsSsh && !g.urlIsFile ){
387 char *zOriginalUrl = g.urlCanonical;
388 char *zOriginalHost = g.urlHostname;
 
389 char *zOriginalUser = g.urlUser;
390 char *zOriginalPasswd = g.urlPasswd;
 
 
391 unsigned uOriginalFlags = g.urlFlags;
392 g.urlUser = 0;
393 g.urlPasswd = "";
394 url_parse(zProxy, 0);
395 if( zMsg ) fossil_print("%s%s\n", zMsg, g.urlCanonical);
@@ -401,10 +408,14 @@
401 g.urlProxyAuth = mprintf("Basic %z", zCredentials2);
402 free(zCredentials1);
403 }
404 g.urlUser = zOriginalUser;
405 g.urlPasswd = zOriginalPasswd;
 
 
 
 
406 g.urlFlags = uOriginalFlags;
407 }
408 }
409
410 #if INTERFACE
411
--- src/url.c
+++ src/url.c
@@ -62,10 +62,13 @@
62 char *passwd; /* Password for http: */
63 char *canonical; /* Canonical representation of the URL */
64 char *proxyAuth; /* Proxy-Authorizer: string */
65 char *fossil; /* The fossil query parameter on ssh: */
66 unsigned flags; /* Boolean flags controlling URL processing */
67 int useProxy; /* Used to remember that a proxy is in use */
68 char *proxyUrlPath;
69 int proxyOrigPort; /* Tunneled port number for https through proxy */
70 };
71 #endif /* INTERFACE */
72
73
74 /*
@@ -120,10 +123,11 @@
123 char *zLogin;
124 char *zExe;
125 char cQuerySep = '?';
126
127 pUrlData->isFile = 0;
128 pUrlData->useProxy = 0;
129 if( zUrl[4]=='s' ){
130 pUrlData->isHttps = 1;
131 pUrlData->protocol = "https";
132 pUrlData->dfltPort = 443;
133 iStart = 8;
@@ -384,12 +388,15 @@
388 }
389 if( zProxy && zProxy[0] && !is_false(zProxy)
390 && !g.urlIsSsh && !g.urlIsFile ){
391 char *zOriginalUrl = g.urlCanonical;
392 char *zOriginalHost = g.urlHostname;
393 int fOriginalIsHttps = g.urlIsHttps;
394 char *zOriginalUser = g.urlUser;
395 char *zOriginalPasswd = g.urlPasswd;
396 char *zOriginalUrlPath = g.urlPath;
397 int iOriginalPort = g.urlPort;
398 unsigned uOriginalFlags = g.urlFlags;
399 g.urlUser = 0;
400 g.urlPasswd = "";
401 url_parse(zProxy, 0);
402 if( zMsg ) fossil_print("%s%s\n", zMsg, g.urlCanonical);
@@ -401,10 +408,14 @@
408 g.urlProxyAuth = mprintf("Basic %z", zCredentials2);
409 free(zCredentials1);
410 }
411 g.urlUser = zOriginalUser;
412 g.urlPasswd = zOriginalPasswd;
413 g.urlIsHttps = fOriginalIsHttps;
414 g.useProxy = 1;
415 g.proxyUrlPath = zOriginalUrlPath;
416 g.proxyOrigPort = iOriginalPort;
417 g.urlFlags = uOriginalFlags;
418 }
419 }
420
421 #if INTERFACE
422
+23 -3
--- src/utf8.c
+++ src/utf8.c
@@ -177,11 +177,12 @@
177177
** Call fossil_filename_free() to deallocate any memory used to store the
178178
** returned pointer when done.
179179
**
180180
** On Windows, characters in the range U+0001 to U+0031 and the
181181
** characters '"', '*', ':', '<', '>', '?' and '|' are invalid
182
-** to be used. Therefore, translate those to characters in the
182
+** to be used, except in the 'extended path' prefix ('?') and
183
+** as drive specifier (':'). Therefore, translate those to characters
183184
** in the range U+F001 - U+F07F (private use area), so those
184185
** characters never arrive in any Windows API. The filenames might
185186
** look strange in Windows explorer, but in the cygwin shell
186187
** everything looks as expected.
187188
**
@@ -195,16 +196,35 @@
195196
wchar_t *wUnicode = zUnicode;
196197
if( zUnicode==0 ){
197198
return 0;
198199
}
199200
MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
200
- /* If path starts with "<drive>:/" or "<drive>:\", don't translate the ':' */
201
+ /*
202
+ ** If path starts with "//?/" or "\\?\" (extended path), translate
203
+ ** any slashes to backslashes but leave the '?' intact
204
+ */
205
+ if( (zUtf8[0]=='\\' || zUtf8[0]=='/') && (zUtf8[1]=='\\' || zUtf8[1]=='/')
206
+ && zUtf8[2]=='?' && (zUtf8[3]=='\\' || zUtf8[3]=='/')) {
207
+ wUnicode[0] = wUnicode[1] = wUnicode[3] = '\\';
208
+ zUtf8 += 4;
209
+ wUnicode += 4;
210
+ }
211
+ /*
212
+ ** If (remainder of) path starts with "<drive>:/" or "<drive>:\",
213
+ ** leave the ':' intact
214
+ */
201215
if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
202216
&& (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
203
- zUnicode[2] = '\\';
217
+ wUnicode[2] = '\\';
204218
wUnicode += 3;
205219
}
220
+ /*
221
+ ** In the remainder of the path, translate invalid characters to
222
+ ** characters in the Unicode private use area. This is what makes
223
+ ** Win32 fossil.exe work well in a Cygwin environment even when a
224
+ ** filename contains characters which are invalid for Win32.
225
+ */
206226
while( *wUnicode != '\0' ){
207227
if ( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){
208228
*wUnicode |= 0xF000;
209229
}else if( *wUnicode == '/' ){
210230
*wUnicode = '\\';
211231
--- src/utf8.c
+++ src/utf8.c
@@ -177,11 +177,12 @@
177 ** Call fossil_filename_free() to deallocate any memory used to store the
178 ** returned pointer when done.
179 **
180 ** On Windows, characters in the range U+0001 to U+0031 and the
181 ** characters '"', '*', ':', '<', '>', '?' and '|' are invalid
182 ** to be used. Therefore, translate those to characters in the
 
183 ** in the range U+F001 - U+F07F (private use area), so those
184 ** characters never arrive in any Windows API. The filenames might
185 ** look strange in Windows explorer, but in the cygwin shell
186 ** everything looks as expected.
187 **
@@ -195,16 +196,35 @@
195 wchar_t *wUnicode = zUnicode;
196 if( zUnicode==0 ){
197 return 0;
198 }
199 MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
200 /* If path starts with "<drive>:/" or "<drive>:\", don't translate the ':' */
 
 
 
 
 
 
 
 
 
 
 
 
 
201 if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
202 && (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
203 zUnicode[2] = '\\';
204 wUnicode += 3;
205 }
 
 
 
 
 
 
206 while( *wUnicode != '\0' ){
207 if ( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){
208 *wUnicode |= 0xF000;
209 }else if( *wUnicode == '/' ){
210 *wUnicode = '\\';
211
--- src/utf8.c
+++ src/utf8.c
@@ -177,11 +177,12 @@
177 ** Call fossil_filename_free() to deallocate any memory used to store the
178 ** returned pointer when done.
179 **
180 ** On Windows, characters in the range U+0001 to U+0031 and the
181 ** characters '"', '*', ':', '<', '>', '?' and '|' are invalid
182 ** to be used, except in the 'extended path' prefix ('?') and
183 ** as drive specifier (':'). Therefore, translate those to characters
184 ** in the range U+F001 - U+F07F (private use area), so those
185 ** characters never arrive in any Windows API. The filenames might
186 ** look strange in Windows explorer, but in the cygwin shell
187 ** everything looks as expected.
188 **
@@ -195,16 +196,35 @@
196 wchar_t *wUnicode = zUnicode;
197 if( zUnicode==0 ){
198 return 0;
199 }
200 MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
201 /*
202 ** If path starts with "//?/" or "\\?\" (extended path), translate
203 ** any slashes to backslashes but leave the '?' intact
204 */
205 if( (zUtf8[0]=='\\' || zUtf8[0]=='/') && (zUtf8[1]=='\\' || zUtf8[1]=='/')
206 && zUtf8[2]=='?' && (zUtf8[3]=='\\' || zUtf8[3]=='/')) {
207 wUnicode[0] = wUnicode[1] = wUnicode[3] = '\\';
208 zUtf8 += 4;
209 wUnicode += 4;
210 }
211 /*
212 ** If (remainder of) path starts with "<drive>:/" or "<drive>:\",
213 ** leave the ':' intact
214 */
215 if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
216 && (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
217 wUnicode[2] = '\\';
218 wUnicode += 3;
219 }
220 /*
221 ** In the remainder of the path, translate invalid characters to
222 ** characters in the Unicode private use area. This is what makes
223 ** Win32 fossil.exe work well in a Cygwin environment even when a
224 ** filename contains characters which are invalid for Win32.
225 */
226 while( *wUnicode != '\0' ){
227 if ( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){
228 *wUnicode |= 0xF000;
229 }else if( *wUnicode == '/' ){
230 *wUnicode = '\\';
231
+15 -3
--- src/winhttp.c
+++ src/winhttp.c
@@ -67,15 +67,18 @@
6767
HttpRequest *p = (HttpRequest*)pAppData;
6868
FILE *in = 0, *out = 0;
6969
int amt, got;
7070
int wanted = 0;
7171
char *z;
72
+ char zCmdFName[MAX_PATH];
7273
char zRequestFName[MAX_PATH];
7374
char zReplyFName[MAX_PATH];
7475
char zCmd[2000]; /* Command-line to process the request */
7576
char zHdr[2000]; /* The HTTP request header */
7677
78
+ sqlite3_snprintf(MAX_PATH, zCmdFName,
79
+ "%s_cmd%d.txt", zTempPrefix, p->id);
7780
sqlite3_snprintf(MAX_PATH, zRequestFName,
7881
"%s_in%d.txt", zTempPrefix, p->id);
7982
sqlite3_snprintf(MAX_PATH, zReplyFName,
8083
"%s_out%d.txt", zTempPrefix, p->id);
8184
amt = 0;
@@ -108,13 +111,21 @@
108111
}
109112
wanted -= got;
110113
}
111114
fclose(out);
112115
out = 0;
113
- sqlite3_snprintf(sizeof(zCmd), zCmd, "\"%s\" http \"%s\" %s %s %s --nossl%s",
114
- g.nameOfExe, g.zRepositoryName, zRequestFName, zReplyFName,
115
- inet_ntoa(p->addr.sin_addr), p->zOptions
116
+ sqlite3_snprintf(sizeof(zCmd), zCmd, "%s%s\n%s\n%s\n%s",
117
+ get_utf8_bom(0), g.zRepositoryName, zRequestFName, zReplyFName,
118
+ inet_ntoa(p->addr.sin_addr)
119
+ );
120
+ out = fossil_fopen(zCmdFName, "wb");
121
+ if( out==0 ) goto end_request;
122
+ fwrite(zCmd, 1, strlen(zCmd), out);
123
+ fclose(out);
124
+
125
+ sqlite3_snprintf(sizeof(zCmd), zCmd, "\"%s\" http -args \"%s\" --nossl%s",
126
+ g.nameOfExe, zCmdFName, p->zOptions
116127
);
117128
fossil_system(zCmd);
118129
in = fossil_fopen(zReplyFName, "rb");
119130
if( in ){
120131
while( (got = fread(zHdr, 1, sizeof(zHdr), in))>0 ){
@@ -126,10 +137,11 @@
126137
if( out ) fclose(out);
127138
if( in ) fclose(in);
128139
closesocket(p->s);
129140
file_delete(zRequestFName);
130141
file_delete(zReplyFName);
142
+ file_delete(zCmdFName);
131143
free(p);
132144
}
133145
134146
/*
135147
** Process a single incoming SCGI request.
136148
--- src/winhttp.c
+++ src/winhttp.c
@@ -67,15 +67,18 @@
67 HttpRequest *p = (HttpRequest*)pAppData;
68 FILE *in = 0, *out = 0;
69 int amt, got;
70 int wanted = 0;
71 char *z;
 
72 char zRequestFName[MAX_PATH];
73 char zReplyFName[MAX_PATH];
74 char zCmd[2000]; /* Command-line to process the request */
75 char zHdr[2000]; /* The HTTP request header */
76
 
 
77 sqlite3_snprintf(MAX_PATH, zRequestFName,
78 "%s_in%d.txt", zTempPrefix, p->id);
79 sqlite3_snprintf(MAX_PATH, zReplyFName,
80 "%s_out%d.txt", zTempPrefix, p->id);
81 amt = 0;
@@ -108,13 +111,21 @@
108 }
109 wanted -= got;
110 }
111 fclose(out);
112 out = 0;
113 sqlite3_snprintf(sizeof(zCmd), zCmd, "\"%s\" http \"%s\" %s %s %s --nossl%s",
114 g.nameOfExe, g.zRepositoryName, zRequestFName, zReplyFName,
115 inet_ntoa(p->addr.sin_addr), p->zOptions
 
 
 
 
 
 
 
 
116 );
117 fossil_system(zCmd);
118 in = fossil_fopen(zReplyFName, "rb");
119 if( in ){
120 while( (got = fread(zHdr, 1, sizeof(zHdr), in))>0 ){
@@ -126,10 +137,11 @@
126 if( out ) fclose(out);
127 if( in ) fclose(in);
128 closesocket(p->s);
129 file_delete(zRequestFName);
130 file_delete(zReplyFName);
 
131 free(p);
132 }
133
134 /*
135 ** Process a single incoming SCGI request.
136
--- src/winhttp.c
+++ src/winhttp.c
@@ -67,15 +67,18 @@
67 HttpRequest *p = (HttpRequest*)pAppData;
68 FILE *in = 0, *out = 0;
69 int amt, got;
70 int wanted = 0;
71 char *z;
72 char zCmdFName[MAX_PATH];
73 char zRequestFName[MAX_PATH];
74 char zReplyFName[MAX_PATH];
75 char zCmd[2000]; /* Command-line to process the request */
76 char zHdr[2000]; /* The HTTP request header */
77
78 sqlite3_snprintf(MAX_PATH, zCmdFName,
79 "%s_cmd%d.txt", zTempPrefix, p->id);
80 sqlite3_snprintf(MAX_PATH, zRequestFName,
81 "%s_in%d.txt", zTempPrefix, p->id);
82 sqlite3_snprintf(MAX_PATH, zReplyFName,
83 "%s_out%d.txt", zTempPrefix, p->id);
84 amt = 0;
@@ -108,13 +111,21 @@
111 }
112 wanted -= got;
113 }
114 fclose(out);
115 out = 0;
116 sqlite3_snprintf(sizeof(zCmd), zCmd, "%s%s\n%s\n%s\n%s",
117 get_utf8_bom(0), g.zRepositoryName, zRequestFName, zReplyFName,
118 inet_ntoa(p->addr.sin_addr)
119 );
120 out = fossil_fopen(zCmdFName, "wb");
121 if( out==0 ) goto end_request;
122 fwrite(zCmd, 1, strlen(zCmd), out);
123 fclose(out);
124
125 sqlite3_snprintf(sizeof(zCmd), zCmd, "\"%s\" http -args \"%s\" --nossl%s",
126 g.nameOfExe, zCmdFName, p->zOptions
127 );
128 fossil_system(zCmd);
129 in = fossil_fopen(zReplyFName, "rb");
130 if( in ){
131 while( (got = fread(zHdr, 1, sizeof(zHdr), in))>0 ){
@@ -126,10 +137,11 @@
137 if( out ) fclose(out);
138 if( in ) fclose(in);
139 closesocket(p->s);
140 file_delete(zRequestFName);
141 file_delete(zReplyFName);
142 file_delete(zCmdFName);
143 free(p);
144 }
145
146 /*
147 ** Process a single incoming SCGI request.
148
--- test/merge_renames.test
+++ test/merge_renames.test
@@ -44,11 +44,11 @@
4444
write_file f1 "line6"
4545
fossil commit -m "c4"
4646
4747
fossil update pivot
4848
fossil mv f1 f2
49
-exec mv f1 f2
49
+file rename -force f1 f2
5050
fossil commit -b rename -m "c5"
5151
5252
fossil merge trunk
5353
fossil commit -m "trunk merged"
5454
@@ -74,11 +74,11 @@
7474
} else {
7575
test merge_renames-1 1
7676
}
7777
7878
fossil close -f
79
-exec rm rep.fossil
79
+file delete rep.fossil
8080
8181
######################################
8282
# Test 2 #
8383
# Reported: Ticket [74413366fe5067] #
8484
######################################
@@ -94,11 +94,11 @@
9494
write_file f2 "line2"
9595
fossil add f2
9696
fossil commit -m "newfile"
9797
9898
fossil mv f2 f2new
99
-exec mv f2 f2new
99
+file rename -force f2 f2new
100100
fossil commit -m "rename"
101101
102102
fossil update pivot
103103
write_file f1 "line3"
104104
fossil commit -b branch -m "change"
@@ -126,11 +126,11 @@
126126
} else {
127127
test merge_renames-2 1
128128
}
129129
130130
fossil close -f
131
-exec rm rep.fossil
131
+file delete rep.fossil
132132
133133
######################################
134134
# Test 3 #
135135
# Reported: Ticket [30b28cf351] #
136136
######################################
@@ -146,11 +146,11 @@
146146
write_file f2 "line2"
147147
fossil add f2
148148
fossil commit -m "newfile"
149149
150150
fossil mv f2 f2new
151
-exec mv f2 f2new
151
+file rename -force f2 f2new
152152
fossil commit -m "rename"
153153
154154
fossil update pivot
155155
write_file f1 "line3"
156156
fossil commit -b branch -m "change"
@@ -178,11 +178,11 @@
178178
} else {
179179
test merge_renames-2 1
180180
}
181181
182182
fossil close -f
183
-exec rm rep.fossil
183
+file delete rep.fossil
184184
185185
######################################
186186
# Test 4 #
187187
# Reported: Ticket [67176c3aa4] #
188188
######################################
189189
--- test/merge_renames.test
+++ test/merge_renames.test
@@ -44,11 +44,11 @@
44 write_file f1 "line6"
45 fossil commit -m "c4"
46
47 fossil update pivot
48 fossil mv f1 f2
49 exec mv f1 f2
50 fossil commit -b rename -m "c5"
51
52 fossil merge trunk
53 fossil commit -m "trunk merged"
54
@@ -74,11 +74,11 @@
74 } else {
75 test merge_renames-1 1
76 }
77
78 fossil close -f
79 exec rm rep.fossil
80
81 ######################################
82 # Test 2 #
83 # Reported: Ticket [74413366fe5067] #
84 ######################################
@@ -94,11 +94,11 @@
94 write_file f2 "line2"
95 fossil add f2
96 fossil commit -m "newfile"
97
98 fossil mv f2 f2new
99 exec mv f2 f2new
100 fossil commit -m "rename"
101
102 fossil update pivot
103 write_file f1 "line3"
104 fossil commit -b branch -m "change"
@@ -126,11 +126,11 @@
126 } else {
127 test merge_renames-2 1
128 }
129
130 fossil close -f
131 exec rm rep.fossil
132
133 ######################################
134 # Test 3 #
135 # Reported: Ticket [30b28cf351] #
136 ######################################
@@ -146,11 +146,11 @@
146 write_file f2 "line2"
147 fossil add f2
148 fossil commit -m "newfile"
149
150 fossil mv f2 f2new
151 exec mv f2 f2new
152 fossil commit -m "rename"
153
154 fossil update pivot
155 write_file f1 "line3"
156 fossil commit -b branch -m "change"
@@ -178,11 +178,11 @@
178 } else {
179 test merge_renames-2 1
180 }
181
182 fossil close -f
183 exec rm rep.fossil
184
185 ######################################
186 # Test 4 #
187 # Reported: Ticket [67176c3aa4] #
188 ######################################
189
--- test/merge_renames.test
+++ test/merge_renames.test
@@ -44,11 +44,11 @@
44 write_file f1 "line6"
45 fossil commit -m "c4"
46
47 fossil update pivot
48 fossil mv f1 f2
49 file rename -force f1 f2
50 fossil commit -b rename -m "c5"
51
52 fossil merge trunk
53 fossil commit -m "trunk merged"
54
@@ -74,11 +74,11 @@
74 } else {
75 test merge_renames-1 1
76 }
77
78 fossil close -f
79 file delete rep.fossil
80
81 ######################################
82 # Test 2 #
83 # Reported: Ticket [74413366fe5067] #
84 ######################################
@@ -94,11 +94,11 @@
94 write_file f2 "line2"
95 fossil add f2
96 fossil commit -m "newfile"
97
98 fossil mv f2 f2new
99 file rename -force f2 f2new
100 fossil commit -m "rename"
101
102 fossil update pivot
103 write_file f1 "line3"
104 fossil commit -b branch -m "change"
@@ -126,11 +126,11 @@
126 } else {
127 test merge_renames-2 1
128 }
129
130 fossil close -f
131 file delete rep.fossil
132
133 ######################################
134 # Test 3 #
135 # Reported: Ticket [30b28cf351] #
136 ######################################
@@ -146,11 +146,11 @@
146 write_file f2 "line2"
147 fossil add f2
148 fossil commit -m "newfile"
149
150 fossil mv f2 f2new
151 file rename -force f2 f2new
152 fossil commit -m "rename"
153
154 fossil update pivot
155 write_file f1 "line3"
156 fossil commit -b branch -m "change"
@@ -178,11 +178,11 @@
178 } else {
179 test merge_renames-2 1
180 }
181
182 fossil close -f
183 file delete rep.fossil
184
185 ######################################
186 # Test 4 #
187 # Reported: Ticket [67176c3aa4] #
188 ######################################
189
--- test/revert.test
+++ test/revert.test
@@ -91,16 +91,16 @@
9191
#
9292
# Add f0
9393
write_file f0 "f0"
9494
fossil add f0
9595
# Remove f1
96
-exec rm f1
96
+file delete f1
9797
fossil rm f1
9898
# Edit f2
9999
write_file f2 "f2.1"
100100
# Rename f3 to f3n
101
-exec mv f3 f3n
101
+file rename -force f3 f3n
102102
fossil mv f3 f3n
103103
104104
# Test 'fossil revert' with no arguments
105105
#
106106
revert-test 1 -addremove {
107107
--- test/revert.test
+++ test/revert.test
@@ -91,16 +91,16 @@
91 #
92 # Add f0
93 write_file f0 "f0"
94 fossil add f0
95 # Remove f1
96 exec rm f1
97 fossil rm f1
98 # Edit f2
99 write_file f2 "f2.1"
100 # Rename f3 to f3n
101 exec mv f3 f3n
102 fossil mv f3 f3n
103
104 # Test 'fossil revert' with no arguments
105 #
106 revert-test 1 -addremove {
107
--- test/revert.test
+++ test/revert.test
@@ -91,16 +91,16 @@
91 #
92 # Add f0
93 write_file f0 "f0"
94 fossil add f0
95 # Remove f1
96 file delete f1
97 fossil rm f1
98 # Edit f2
99 write_file f2 "f2.1"
100 # Rename f3 to f3n
101 file rename -force f3 f3n
102 fossil mv f3 f3n
103
104 # Test 'fossil revert' with no arguments
105 #
106 revert-test 1 -addremove {
107
--- test/th1.test
+++ test/th1.test
@@ -297,5 +297,70 @@
297297
298298
###############################################################################
299299
300300
fossil test-th-eval "string last {AB} {abc}"
301301
test th1-string-last-9 {$RESULT eq {-1}}
302
+
303
+###############################################################################
304
+
305
+fossil test-th-eval "expr -2147483649.0"
306
+test th1-expr-1 {$RESULT eq {-2147483649.0}}
307
+
308
+###############################################################################
309
+
310
+fossil test-th-eval "expr -2147483649"
311
+test th1-expr-2 {$RESULT eq {2147483647}}
312
+
313
+###############################################################################
314
+
315
+fossil test-th-eval "expr -2147483648"
316
+test th1-expr-3 {$RESULT eq {-2147483648}}
317
+
318
+###############################################################################
319
+
320
+fossil test-th-eval "expr -2147483647"
321
+test th1-expr-4 {$RESULT eq {-2147483647}}
322
+
323
+###############################################################################
324
+
325
+fossil test-th-eval "expr -1"
326
+test th1-expr-5 {$RESULT eq {-1}}
327
+
328
+###############################################################################
329
+
330
+fossil test-th-eval "expr 0"
331
+test th1-expr-6 {$RESULT eq {0}}
332
+
333
+###############################################################################
334
+
335
+fossil test-th-eval "expr 0.0"
336
+test th1-expr-7 {$RESULT eq {0.0}}
337
+
338
+###############################################################################
339
+
340
+fossil test-th-eval "expr 1"
341
+test th1-expr-8 {$RESULT eq {1}}
342
+
343
+###############################################################################
344
+
345
+fossil test-th-eval "expr 2147483647"
346
+test th1-expr-9 {$RESULT eq {2147483647}}
347
+
348
+###############################################################################
349
+
350
+fossil test-th-eval "expr 2147483648"
351
+test th1-expr-10 {$RESULT eq {2147483648}}
352
+
353
+###############################################################################
354
+
355
+fossil test-th-eval "expr 2147483649"
356
+test th1-expr-11 {$RESULT eq {2147483649}}
357
+
358
+###############################################################################
359
+
360
+fossil test-th-eval "expr +2147483649"
361
+test th1-expr-12 {$RESULT eq {-2147483647}}
362
+
363
+###############################################################################
364
+
365
+fossil test-th-eval "expr +2147483649.0"
366
+test th1-expr-13 {$RESULT eq {2147483649.0}}
302367
--- test/th1.test
+++ test/th1.test
@@ -297,5 +297,70 @@
297
298 ###############################################################################
299
300 fossil test-th-eval "string last {AB} {abc}"
301 test th1-string-last-9 {$RESULT eq {-1}}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
--- test/th1.test
+++ test/th1.test
@@ -297,5 +297,70 @@
297
298 ###############################################################################
299
300 fossil test-th-eval "string last {AB} {abc}"
301 test th1-string-last-9 {$RESULT eq {-1}}
302
303 ###############################################################################
304
305 fossil test-th-eval "expr -2147483649.0"
306 test th1-expr-1 {$RESULT eq {-2147483649.0}}
307
308 ###############################################################################
309
310 fossil test-th-eval "expr -2147483649"
311 test th1-expr-2 {$RESULT eq {2147483647}}
312
313 ###############################################################################
314
315 fossil test-th-eval "expr -2147483648"
316 test th1-expr-3 {$RESULT eq {-2147483648}}
317
318 ###############################################################################
319
320 fossil test-th-eval "expr -2147483647"
321 test th1-expr-4 {$RESULT eq {-2147483647}}
322
323 ###############################################################################
324
325 fossil test-th-eval "expr -1"
326 test th1-expr-5 {$RESULT eq {-1}}
327
328 ###############################################################################
329
330 fossil test-th-eval "expr 0"
331 test th1-expr-6 {$RESULT eq {0}}
332
333 ###############################################################################
334
335 fossil test-th-eval "expr 0.0"
336 test th1-expr-7 {$RESULT eq {0.0}}
337
338 ###############################################################################
339
340 fossil test-th-eval "expr 1"
341 test th1-expr-8 {$RESULT eq {1}}
342
343 ###############################################################################
344
345 fossil test-th-eval "expr 2147483647"
346 test th1-expr-9 {$RESULT eq {2147483647}}
347
348 ###############################################################################
349
350 fossil test-th-eval "expr 2147483648"
351 test th1-expr-10 {$RESULT eq {2147483648}}
352
353 ###############################################################################
354
355 fossil test-th-eval "expr 2147483649"
356 test th1-expr-11 {$RESULT eq {2147483649}}
357
358 ###############################################################################
359
360 fossil test-th-eval "expr +2147483649"
361 test th1-expr-12 {$RESULT eq {-2147483647}}
362
363 ###############################################################################
364
365 fossil test-th-eval "expr +2147483649.0"
366 test th1-expr-13 {$RESULT eq {2147483649.0}}
367
--- www/changes.wiki
+++ www/changes.wiki
@@ -6,10 +6,11 @@
66
* Honor timezones in imports from git.
77
* The [/reports] page now requires Read ("o") permissions. The "byweek"
88
report now properly propagates the selected year through the event type
99
filter links.
1010
* The [/help/info | info command] now shows leaf status of the checkout.
11
+ * Add support for tunneling https through a http proxy (Ticket [e854101c4f]).
1112
1213
<h2>Changes For Version 1.28 (2014-01-27)</h2>
1314
* Enhance [/help?cmd=/reports | /reports] to support event type filtering.
1415
* When cloning a repository, the user name passed via the URL (if any)
1516
is now used as the default local admin user's name.
1617
--- www/changes.wiki
+++ www/changes.wiki
@@ -6,10 +6,11 @@
6 * Honor timezones in imports from git.
7 * The [/reports] page now requires Read ("o") permissions. The "byweek"
8 report now properly propagates the selected year through the event type
9 filter links.
10 * The [/help/info | info command] now shows leaf status of the checkout.
 
11
12 <h2>Changes For Version 1.28 (2014-01-27)</h2>
13 * Enhance [/help?cmd=/reports | /reports] to support event type filtering.
14 * When cloning a repository, the user name passed via the URL (if any)
15 is now used as the default local admin user's name.
16
--- www/changes.wiki
+++ www/changes.wiki
@@ -6,10 +6,11 @@
6 * Honor timezones in imports from git.
7 * The [/reports] page now requires Read ("o") permissions. The "byweek"
8 report now properly propagates the selected year through the event type
9 filter links.
10 * The [/help/info | info command] now shows leaf status of the checkout.
11 * Add support for tunneling https through a http proxy (Ticket [e854101c4f]).
12
13 <h2>Changes For Version 1.28 (2014-01-27)</h2>
14 * Enhance [/help?cmd=/reports | /reports] to support event type filtering.
15 * When cloning a repository, the user name passed via the URL (if any)
16 is now used as the default local admin user's name.
17
+3 -1
--- www/sync.wiki
+++ www/sync.wiki
@@ -356,18 +356,20 @@
356356
<li> manifest
357357
<li> index-page
358358
<ul></td><td valign="top"><ul>
359359
<li> timeline-block-markup
360360
<li> timeline-max-comment
361
+<li> timeline-plaintext
361362
<li> ticket-table
362363
<li> ticket-common
364
+<li> ticket-change
363365
<li> ticket-newpage
364366
<li> ticket-viewpage
365367
<li> ticket-editpage
368
+<ul></td><td valign="top"><ul>
366369
<li> ticket-reportlist
367370
<li> ticket-report-template
368
-<ul></td><td valign="top"><ul>
369371
<li> ticket-key-template
370372
<li> ticket-title-expr
371373
<li> ticket-closed-expr
372374
<li> @reportfmt
373375
<li> @user
374376
--- www/sync.wiki
+++ www/sync.wiki
@@ -356,18 +356,20 @@
356 <li> manifest
357 <li> index-page
358 <ul></td><td valign="top"><ul>
359 <li> timeline-block-markup
360 <li> timeline-max-comment
 
361 <li> ticket-table
362 <li> ticket-common
 
363 <li> ticket-newpage
364 <li> ticket-viewpage
365 <li> ticket-editpage
 
366 <li> ticket-reportlist
367 <li> ticket-report-template
368 <ul></td><td valign="top"><ul>
369 <li> ticket-key-template
370 <li> ticket-title-expr
371 <li> ticket-closed-expr
372 <li> @reportfmt
373 <li> @user
374
--- www/sync.wiki
+++ www/sync.wiki
@@ -356,18 +356,20 @@
356 <li> manifest
357 <li> index-page
358 <ul></td><td valign="top"><ul>
359 <li> timeline-block-markup
360 <li> timeline-max-comment
361 <li> timeline-plaintext
362 <li> ticket-table
363 <li> ticket-common
364 <li> ticket-change
365 <li> ticket-newpage
366 <li> ticket-viewpage
367 <li> ticket-editpage
368 <ul></td><td valign="top"><ul>
369 <li> ticket-reportlist
370 <li> ticket-report-template
 
371 <li> ticket-key-template
372 <li> ticket-title-expr
373 <li> ticket-closed-expr
374 <li> @reportfmt
375 <li> @user
376

Keyboard Shortcuts

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