Fossil SCM

Merge in updates from trunk. Some implementation simplifications and more comments (mainly in the SQLite part).

jan.nijtmans 2014-02-14 10:25 win32-longpath merge
Commit 9cc1c9d6904103f4b89e869ae93eaa8efeaeb2d0
+1 -1
--- src/bag.c
+++ src/bag.c
@@ -75,11 +75,11 @@
7575
/*
7676
** Change the size of the hash table on a bag so that
7777
** it contains N slots
7878
**
7979
** Completely reconstruct the hash table from scratch. Deleted
80
-** entries (indicated by a -1) are removed. When finished, it
80
+** entries (indicated by a -1) are removed. When finished, it
8181
** should be the case that p->cnt==p->used.
8282
*/
8383
static void bag_resize(Bag *p, int newSize){
8484
int i;
8585
Bag old;
8686
--- src/bag.c
+++ src/bag.c
@@ -75,11 +75,11 @@
75 /*
76 ** Change the size of the hash table on a bag so that
77 ** it contains N slots
78 **
79 ** Completely reconstruct the hash table from scratch. Deleted
80 ** entries (indicated by a -1) are removed. When finished, it
81 ** should be the case that p->cnt==p->used.
82 */
83 static void bag_resize(Bag *p, int newSize){
84 int i;
85 Bag old;
86
--- src/bag.c
+++ src/bag.c
@@ -75,11 +75,11 @@
75 /*
76 ** Change the size of the hash table on a bag so that
77 ** it contains N slots
78 **
79 ** Completely reconstruct the hash table from scratch. Deleted
80 ** entries (indicated by a -1) are removed. When finished, it
81 ** should be the case that p->cnt==p->used.
82 */
83 static void bag_resize(Bag *p, int newSize){
84 int i;
85 Bag old;
86
+1 -1
--- src/bisect.c
+++ src/bisect.c
@@ -370,11 +370,11 @@
370370
g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pMid->rid);
371371
g.argc = 3;
372372
g.fNoSync = 1;
373373
update_cmd();
374374
}
375
-
375
+
376376
if( strncmp(zDisplay,"chart",m)==0 ){
377377
bisect_chart(1);
378378
}else if( strncmp(zDisplay, "log", m)==0 ){
379379
bisect_chart(0);
380380
}else if( strncmp(zDisplay, "status", m)==0 ){
381381
--- src/bisect.c
+++ src/bisect.c
@@ -370,11 +370,11 @@
370 g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pMid->rid);
371 g.argc = 3;
372 g.fNoSync = 1;
373 update_cmd();
374 }
375
376 if( strncmp(zDisplay,"chart",m)==0 ){
377 bisect_chart(1);
378 }else if( strncmp(zDisplay, "log", m)==0 ){
379 bisect_chart(0);
380 }else if( strncmp(zDisplay, "status", m)==0 ){
381
--- src/bisect.c
+++ src/bisect.c
@@ -370,11 +370,11 @@
370 g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pMid->rid);
371 g.argc = 3;
372 g.fNoSync = 1;
373 update_cmd();
374 }
375
376 if( strncmp(zDisplay,"chart",m)==0 ){
377 bisect_chart(1);
378 }else if( strncmp(zDisplay, "log", m)==0 ){
379 bisect_chart(0);
380 }else if( strncmp(zDisplay, "status", m)==0 ){
381
+2 -13
--- src/branch.c
+++ src/branch.c
@@ -51,11 +51,12 @@
5151
verify_all_options();
5252
if( g.argc<5 ){
5353
usage("new BRANCH-NAME BASIS ?OPTIONS?");
5454
}
5555
db_find_and_open_repository(0, 0);
56
- noSign = db_get_int("omitsign", 0)|noSign;
56
+ noSign = db_get_boolean("omitsign", 0)|noSign;
57
+ if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
5758
5859
/* fossil branch new name */
5960
zBranch = g.argv[3];
6061
if( zBranch==0 || zBranch[0]==0 ){
6162
fossil_fatal("branch name cannot be empty");
@@ -367,16 +368,10 @@
367368
}
368369
if( cnt ){
369370
@ </ul>
370371
}
371372
db_finalize(&q);
372
- @ <script type="text/JavaScript">
373
- @ function xin(id){
374
- @ }
375
- @ function xout(id){
376
- @ }
377
- @ </script>
378373
style_footer();
379374
}
380375
381376
/*
382377
** This routine is called while for each check-in that is rendered by
@@ -422,13 +417,7 @@
422417
" ORDER BY event.mtime DESC",
423418
timeline_query_for_www(), TAG_BRANCH
424419
);
425420
www_print_timeline(&q, 0, 0, 0, brtimeline_extra);
426421
db_finalize(&q);
427
- @ <script type="text/JavaScript">
428
- @ function xin(id){
429
- @ }
430
- @ function xout(id){
431
- @ }
432
- @ </script>
433422
style_footer();
434423
}
435424
--- src/branch.c
+++ src/branch.c
@@ -51,11 +51,12 @@
51 verify_all_options();
52 if( g.argc<5 ){
53 usage("new BRANCH-NAME BASIS ?OPTIONS?");
54 }
55 db_find_and_open_repository(0, 0);
56 noSign = db_get_int("omitsign", 0)|noSign;
 
57
58 /* fossil branch new name */
59 zBranch = g.argv[3];
60 if( zBranch==0 || zBranch[0]==0 ){
61 fossil_fatal("branch name cannot be empty");
@@ -367,16 +368,10 @@
367 }
368 if( cnt ){
369 @ </ul>
370 }
371 db_finalize(&q);
372 @ <script type="text/JavaScript">
373 @ function xin(id){
374 @ }
375 @ function xout(id){
376 @ }
377 @ </script>
378 style_footer();
379 }
380
381 /*
382 ** This routine is called while for each check-in that is rendered by
@@ -422,13 +417,7 @@
422 " ORDER BY event.mtime DESC",
423 timeline_query_for_www(), TAG_BRANCH
424 );
425 www_print_timeline(&q, 0, 0, 0, brtimeline_extra);
426 db_finalize(&q);
427 @ <script type="text/JavaScript">
428 @ function xin(id){
429 @ }
430 @ function xout(id){
431 @ }
432 @ </script>
433 style_footer();
434 }
435
--- src/branch.c
+++ src/branch.c
@@ -51,11 +51,12 @@
51 verify_all_options();
52 if( g.argc<5 ){
53 usage("new BRANCH-NAME BASIS ?OPTIONS?");
54 }
55 db_find_and_open_repository(0, 0);
56 noSign = db_get_boolean("omitsign", 0)|noSign;
57 if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
58
59 /* fossil branch new name */
60 zBranch = g.argv[3];
61 if( zBranch==0 || zBranch[0]==0 ){
62 fossil_fatal("branch name cannot be empty");
@@ -367,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
@@ -422,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
+20 -20
--- src/captcha.c
+++ src/captcha.c
@@ -92,11 +92,11 @@
9292
z[k++] = ' ';
9393
}
9494
z[k++] = '\n';
9595
}
9696
z[k] = 0;
97
- return z;
97
+ return z;
9898
}
9999
#endif /* CAPTCHA==1 */
100100
101101
102102
#if CAPTCHA==2
@@ -148,11 +148,11 @@
148148
"|__ |",
149149
" / / ",
150150
" /_/ ",
151151
152152
/* 8 */
153
- " ___ ",
153
+ " ___ ",
154154
"( _ )",
155155
"/ _ \\",
156156
"\\___/",
157157
158158
/* 9 */
@@ -218,11 +218,11 @@
218218
}
219219
}
220220
z[k++] = '\n';
221221
}
222222
z[k] = 0;
223
- return z;
223
+ return z;
224224
}
225225
#endif /* CAPTCHA==2 */
226226
227227
#if CAPTCHA==3
228228
static const char *const azFont3[] = {
@@ -231,123 +231,123 @@
231231
" / _ \\ ",
232232
"| | | |",
233233
"| | | |",
234234
"| |_| |",
235235
" \\___/ ",
236
-
236
+
237237
/* 1 */
238238
" __ ",
239239
"/_ |",
240240
" | |",
241241
" | |",
242242
" | |",
243243
" |_|",
244
-
244
+
245245
/* 2 */
246246
" ___ ",
247247
"|__ \\ ",
248248
" ) |",
249249
" / / ",
250250
" / /_ ",
251251
"|____|",
252
-
252
+
253253
/* 3 */
254254
" ____ ",
255255
"|___ \\ ",
256256
" __) |",
257257
" |__ < ",
258258
" ___) |",
259259
"|____/ ",
260
-
260
+
261261
/* 4 */
262262
" _ _ ",
263263
"| || | ",
264264
"| || |_ ",
265265
"|__ _|",
266266
" | | ",
267267
" |_| ",
268
-
268
+
269269
/* 5 */
270270
" _____ ",
271271
"| ____|",
272272
"| |__ ",
273273
"|___ \\ ",
274274
" ___) |",
275275
"|____/ ",
276
-
276
+
277277
/* 6 */
278278
" __ ",
279279
" / / ",
280280
" / /_ ",
281281
"| '_ \\ ",
282282
"| (_) |",
283283
" \\___/ ",
284
-
284
+
285285
/* 7 */
286286
" ______ ",
287287
"|____ |",
288288
" / / ",
289289
" / / ",
290290
" / / ",
291291
" /_/ ",
292
-
292
+
293293
/* 8 */
294294
" ___ ",
295295
" / _ \\ ",
296296
"| (_) |",
297297
" > _ < ",
298298
"| (_) |",
299299
" \\___/ ",
300
-
300
+
301301
/* 9 */
302302
" ___ ",
303303
" / _ \\ ",
304304
"| (_) |",
305305
" \\__, |",
306306
" / / ",
307307
" /_/ ",
308
-
308
+
309309
/* A */
310310
" ",
311311
" /\\ ",
312312
" / \\ ",
313313
" / /\\ \\ ",
314314
" / ____ \\ ",
315315
"/_/ \\_\\",
316
-
316
+
317317
/* B */
318318
" ____ ",
319319
"| _ \\ ",
320320
"| |_) |",
321321
"| _ < ",
322322
"| |_) |",
323323
"|____/ ",
324
-
324
+
325325
/* C */
326326
" _____ ",
327327
" / ____|",
328328
"| | ",
329329
"| | ",
330330
"| |____ ",
331331
" \\_____|",
332
-
332
+
333333
/* D */
334334
" _____ ",
335335
"| __ \\ ",
336336
"| | | |",
337337
"| | | |",
338338
"| |__| |",
339339
"|_____/ ",
340
-
340
+
341341
/* E */
342342
" ______ ",
343343
"| ____|",
344344
"| |__ ",
345345
"| __| ",
346346
"| |____ ",
347347
"|______|",
348
-
348
+
349349
/* F */
350350
" ______ ",
351351
"| ____|",
352352
"| |__ ",
353353
"| __| ",
@@ -408,11 +408,11 @@
408408
}
409409
}
410410
z[k++] = '\n';
411411
}
412412
z[k] = 0;
413
- return z;
413
+ return z;
414414
}
415415
#endif /* CAPTCHA==3 */
416416
417417
/*
418418
** COMMAND: test-captcha
@@ -478,11 +478,11 @@
478478
** Return true if a CAPTCHA is required for editing wiki or tickets or for
479479
** adding attachments.
480480
**
481481
** A CAPTCHA is required in those cases if the user is not logged in (if they
482482
** are user "nobody") and if the "require-captcha" setting is true. The
483
-** "require-captcha" setting is controlled on the Admin/Access page. It
483
+** "require-captcha" setting is controlled on the Admin/Access page. It
484484
** defaults to true.
485485
*/
486486
int captcha_needed(void){
487487
if( g.zLogin!=0 ) return 0;
488488
return db_get_boolean("require-captcha", 1);
489489
--- src/captcha.c
+++ src/captcha.c
@@ -92,11 +92,11 @@
92 z[k++] = ' ';
93 }
94 z[k++] = '\n';
95 }
96 z[k] = 0;
97 return z;
98 }
99 #endif /* CAPTCHA==1 */
100
101
102 #if CAPTCHA==2
@@ -148,11 +148,11 @@
148 "|__ |",
149 " / / ",
150 " /_/ ",
151
152 /* 8 */
153 " ___ ",
154 "( _ )",
155 "/ _ \\",
156 "\\___/",
157
158 /* 9 */
@@ -218,11 +218,11 @@
218 }
219 }
220 z[k++] = '\n';
221 }
222 z[k] = 0;
223 return z;
224 }
225 #endif /* CAPTCHA==2 */
226
227 #if CAPTCHA==3
228 static const char *const azFont3[] = {
@@ -231,123 +231,123 @@
231 " / _ \\ ",
232 "| | | |",
233 "| | | |",
234 "| |_| |",
235 " \\___/ ",
236
237 /* 1 */
238 " __ ",
239 "/_ |",
240 " | |",
241 " | |",
242 " | |",
243 " |_|",
244
245 /* 2 */
246 " ___ ",
247 "|__ \\ ",
248 " ) |",
249 " / / ",
250 " / /_ ",
251 "|____|",
252
253 /* 3 */
254 " ____ ",
255 "|___ \\ ",
256 " __) |",
257 " |__ < ",
258 " ___) |",
259 "|____/ ",
260
261 /* 4 */
262 " _ _ ",
263 "| || | ",
264 "| || |_ ",
265 "|__ _|",
266 " | | ",
267 " |_| ",
268
269 /* 5 */
270 " _____ ",
271 "| ____|",
272 "| |__ ",
273 "|___ \\ ",
274 " ___) |",
275 "|____/ ",
276
277 /* 6 */
278 " __ ",
279 " / / ",
280 " / /_ ",
281 "| '_ \\ ",
282 "| (_) |",
283 " \\___/ ",
284
285 /* 7 */
286 " ______ ",
287 "|____ |",
288 " / / ",
289 " / / ",
290 " / / ",
291 " /_/ ",
292
293 /* 8 */
294 " ___ ",
295 " / _ \\ ",
296 "| (_) |",
297 " > _ < ",
298 "| (_) |",
299 " \\___/ ",
300
301 /* 9 */
302 " ___ ",
303 " / _ \\ ",
304 "| (_) |",
305 " \\__, |",
306 " / / ",
307 " /_/ ",
308
309 /* A */
310 " ",
311 " /\\ ",
312 " / \\ ",
313 " / /\\ \\ ",
314 " / ____ \\ ",
315 "/_/ \\_\\",
316
317 /* B */
318 " ____ ",
319 "| _ \\ ",
320 "| |_) |",
321 "| _ < ",
322 "| |_) |",
323 "|____/ ",
324
325 /* C */
326 " _____ ",
327 " / ____|",
328 "| | ",
329 "| | ",
330 "| |____ ",
331 " \\_____|",
332
333 /* D */
334 " _____ ",
335 "| __ \\ ",
336 "| | | |",
337 "| | | |",
338 "| |__| |",
339 "|_____/ ",
340
341 /* E */
342 " ______ ",
343 "| ____|",
344 "| |__ ",
345 "| __| ",
346 "| |____ ",
347 "|______|",
348
349 /* F */
350 " ______ ",
351 "| ____|",
352 "| |__ ",
353 "| __| ",
@@ -408,11 +408,11 @@
408 }
409 }
410 z[k++] = '\n';
411 }
412 z[k] = 0;
413 return z;
414 }
415 #endif /* CAPTCHA==3 */
416
417 /*
418 ** COMMAND: test-captcha
@@ -478,11 +478,11 @@
478 ** Return true if a CAPTCHA is required for editing wiki or tickets or for
479 ** adding attachments.
480 **
481 ** A CAPTCHA is required in those cases if the user is not logged in (if they
482 ** are user "nobody") and if the "require-captcha" setting is true. The
483 ** "require-captcha" setting is controlled on the Admin/Access page. It
484 ** defaults to true.
485 */
486 int captcha_needed(void){
487 if( g.zLogin!=0 ) return 0;
488 return db_get_boolean("require-captcha", 1);
489
--- src/captcha.c
+++ src/captcha.c
@@ -92,11 +92,11 @@
92 z[k++] = ' ';
93 }
94 z[k++] = '\n';
95 }
96 z[k] = 0;
97 return z;
98 }
99 #endif /* CAPTCHA==1 */
100
101
102 #if CAPTCHA==2
@@ -148,11 +148,11 @@
148 "|__ |",
149 " / / ",
150 " /_/ ",
151
152 /* 8 */
153 " ___ ",
154 "( _ )",
155 "/ _ \\",
156 "\\___/",
157
158 /* 9 */
@@ -218,11 +218,11 @@
218 }
219 }
220 z[k++] = '\n';
221 }
222 z[k] = 0;
223 return z;
224 }
225 #endif /* CAPTCHA==2 */
226
227 #if CAPTCHA==3
228 static const char *const azFont3[] = {
@@ -231,123 +231,123 @@
231 " / _ \\ ",
232 "| | | |",
233 "| | | |",
234 "| |_| |",
235 " \\___/ ",
236
237 /* 1 */
238 " __ ",
239 "/_ |",
240 " | |",
241 " | |",
242 " | |",
243 " |_|",
244
245 /* 2 */
246 " ___ ",
247 "|__ \\ ",
248 " ) |",
249 " / / ",
250 " / /_ ",
251 "|____|",
252
253 /* 3 */
254 " ____ ",
255 "|___ \\ ",
256 " __) |",
257 " |__ < ",
258 " ___) |",
259 "|____/ ",
260
261 /* 4 */
262 " _ _ ",
263 "| || | ",
264 "| || |_ ",
265 "|__ _|",
266 " | | ",
267 " |_| ",
268
269 /* 5 */
270 " _____ ",
271 "| ____|",
272 "| |__ ",
273 "|___ \\ ",
274 " ___) |",
275 "|____/ ",
276
277 /* 6 */
278 " __ ",
279 " / / ",
280 " / /_ ",
281 "| '_ \\ ",
282 "| (_) |",
283 " \\___/ ",
284
285 /* 7 */
286 " ______ ",
287 "|____ |",
288 " / / ",
289 " / / ",
290 " / / ",
291 " /_/ ",
292
293 /* 8 */
294 " ___ ",
295 " / _ \\ ",
296 "| (_) |",
297 " > _ < ",
298 "| (_) |",
299 " \\___/ ",
300
301 /* 9 */
302 " ___ ",
303 " / _ \\ ",
304 "| (_) |",
305 " \\__, |",
306 " / / ",
307 " /_/ ",
308
309 /* A */
310 " ",
311 " /\\ ",
312 " / \\ ",
313 " / /\\ \\ ",
314 " / ____ \\ ",
315 "/_/ \\_\\",
316
317 /* B */
318 " ____ ",
319 "| _ \\ ",
320 "| |_) |",
321 "| _ < ",
322 "| |_) |",
323 "|____/ ",
324
325 /* C */
326 " _____ ",
327 " / ____|",
328 "| | ",
329 "| | ",
330 "| |____ ",
331 " \\_____|",
332
333 /* D */
334 " _____ ",
335 "| __ \\ ",
336 "| | | |",
337 "| | | |",
338 "| |__| |",
339 "|_____/ ",
340
341 /* E */
342 " ______ ",
343 "| ____|",
344 "| |__ ",
345 "| __| ",
346 "| |____ ",
347 "|______|",
348
349 /* F */
350 " ______ ",
351 "| ____|",
352 "| |__ ",
353 "| __| ",
@@ -408,11 +408,11 @@
408 }
409 }
410 z[k++] = '\n';
411 }
412 z[k] = 0;
413 return z;
414 }
415 #endif /* CAPTCHA==3 */
416
417 /*
418 ** COMMAND: test-captcha
@@ -478,11 +478,11 @@
478 ** Return true if a CAPTCHA is required for editing wiki or tickets or for
479 ** adding attachments.
480 **
481 ** A CAPTCHA is required in those cases if the user is not logged in (if they
482 ** are user "nobody") and if the "require-captcha" setting is true. The
483 ** "require-captcha" setting is controlled on the Admin/Access page. It
484 ** defaults to true.
485 */
486 int captcha_needed(void){
487 if( g.zLogin!=0 ) return 0;
488 return db_get_boolean("require-captcha", 1);
489
+19 -23
--- src/cgi.c
+++ src/cgi.c
@@ -266,11 +266,11 @@
266266
zTok = strtok_r(0, ",\"",&zPos)){}
267267
fossil_free(zBuf);
268268
if(zTok) return 1;
269269
}
270270
}
271
-
271
+
272272
return 0;
273273
}
274274
#endif
275275
276276
/*
@@ -497,11 +497,11 @@
497497
** must be made of zValue.
498498
*/
499499
void cgi_setenv(const char *zName, const char *zValue){
500500
cgi_set_parameter_nocopy(zName, mprintf("%s",zValue), 0);
501501
}
502
-
502
+
503503
504504
/*
505505
** Add a list of query parameters or cookies to the parameter set.
506506
**
507507
** Each parameter is of the form NAME=VALUE. Both the NAME and the
@@ -615,11 +615,11 @@
615615
break;
616616
}
617617
}
618618
*pz = &z[i];
619619
get_line_from_string(pz, pLen);
620
- return z;
620
+ return z;
621621
}
622622
623623
/*
624624
** Tokenize a line of text into as many as nArg tokens. Make
625625
** azArg[] point to the start of each token.
@@ -722,11 +722,11 @@
722722
cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z, 1);
723723
}
724724
}
725725
}
726726
}
727
- }
727
+ }
728728
}
729729
730730
731731
#ifdef FOSSIL_ENABLE_JSON
732732
/*
@@ -903,11 +903,11 @@
903903
z = (char*)P("HTTP_COOKIE");
904904
if( z ){
905905
z = mprintf("%s",z);
906906
add_param_list(z, ';');
907907
}
908
-
908
+
909909
z = (char*)P("QUERY_STRING");
910910
if( z ){
911911
z = mprintf("%s",z);
912912
add_param_list(z, '&');
913913
}
@@ -919,11 +919,11 @@
919919
920920
len = atoi(PD("CONTENT_LENGTH", "0"));
921921
g.zContentType = zType = P("CONTENT_TYPE");
922922
blob_zero(&g.cgiIn);
923923
if( len>0 && zType ){
924
- if( fossil_strcmp(zType,"application/x-www-form-urlencoded")==0
924
+ if( fossil_strcmp(zType,"application/x-www-form-urlencoded")==0
925925
|| strncmp(zType,"multipart/form-data",19)==0 ){
926926
z = fossil_malloc( len+1 );
927927
len = fread(z, 1, len, g.httpIn);
928928
z[len] = 0;
929929
cgi_trace(z);
@@ -949,11 +949,11 @@
949949
/* FIXMEs:
950950
951951
- See if fossil really needs g.cgiIn to be set for this purpose
952952
(i don't think it does). If it does then fill g.cgiIn and
953953
refactor to parse the JSON from there.
954
-
954
+
955955
- After parsing POST JSON, copy the "first layer" of keys/values
956956
to cgi_setenv(), honoring the upper-case distinction used
957957
in add_param_list(). However...
958958
959959
- If we do that then we might get a disconnect in precedence of
@@ -1225,11 +1225,11 @@
12251225
** loaded into g.zIpAddr.
12261226
*/
12271227
static const char *cgi_accept_forwarded_for(const char *z){
12281228
int i;
12291229
if( fossil_strcmp(g.zIpAddr, "127.0.0.1")!=0 ) return 0;
1230
-
1230
+
12311231
i = strlen(z)-1;
12321232
while( i>=0 && z[i]!=',' && !fossil_isspace(z[i]) ) i--;
12331233
return &z[++i];
12341234
}
12351235
@@ -1297,20 +1297,20 @@
12971297
for(i=0; zToken[i] && zToken[i]!='?'; i++){}
12981298
if( zToken[i] ) zToken[i++] = 0;
12991299
cgi_setenv("PATH_INFO", zToken);
13001300
cgi_setenv("QUERY_STRING", &zToken[i]);
13011301
if( zIpAddr==0 &&
1302
- getpeername(fileno(g.httpIn), (struct sockaddr*)&remoteName,
1302
+ getpeername(fileno(g.httpIn), (struct sockaddr*)&remoteName,
13031303
&size)>=0
13041304
){
13051305
zIpAddr = inet_ntoa(remoteName.sin_addr);
13061306
}
1307
- if( zIpAddr ){
1307
+ if( zIpAddr ){
13081308
cgi_setenv("REMOTE_ADDR", zIpAddr);
13091309
g.zIpAddr = mprintf("%s", zIpAddr);
13101310
}
1311
-
1311
+
13121312
/* Get all the optional fields that follow the first line.
13131313
*/
13141314
while( fgets(zLine,sizeof(zLine),g.httpIn) ){
13151315
char *zFieldName;
13161316
char *zVal;
@@ -1340,14 +1340,12 @@
13401340
cgi_setenv("HTTP_HOST", zVal);
13411341
}else if( fossil_strcmp(zFieldName,"if-none-match:")==0 ){
13421342
cgi_setenv("HTTP_IF_NONE_MATCH", zVal);
13431343
}else if( fossil_strcmp(zFieldName,"if-modified-since:")==0 ){
13441344
cgi_setenv("HTTP_IF_MODIFIED_SINCE", zVal);
1345
-#if 0
13461345
}else if( fossil_strcmp(zFieldName,"referer:")==0 ){
13471346
cgi_setenv("HTTP_REFERER", zVal);
1348
-#endif
13491347
}else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){
13501348
cgi_setenv("HTTP_USER_AGENT", zVal);
13511349
}else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){
13521350
const char *zIpAddr = cgi_accept_forwarded_for(zVal);
13531351
if( zIpAddr!=0 ){
@@ -1376,11 +1374,11 @@
13761374
const char *zType = 0;
13771375
int i, content_length = 0;
13781376
char zLine[2000]; /* A single line of input. */
13791377
13801378
if( zIpAddr ){
1381
- if( nCycles==0 ){
1379
+ if( nCycles==0 ){
13821380
cgi_setenv("REMOTE_ADDR", zIpAddr);
13831381
g.zIpAddr = mprintf("%s", zIpAddr);
13841382
}
13851383
}else{
13861384
fossil_panic("missing SSH IP address");
@@ -1442,11 +1440,11 @@
14421440
if( nCycles==0 ){
14431441
cgi_setenv("PATH_INFO", zToken);
14441442
}else{
14451443
cgi_replace_parameter("PATH_INFO", mprintf("%s",zToken));
14461444
}
1447
-
1445
+
14481446
/* Get all the optional fields that follow the first line.
14491447
*/
14501448
while( fgets(zLine,sizeof(zLine),g.httpIn) ){
14511449
char *zFieldName;
14521450
char *zVal;
@@ -1623,11 +1621,11 @@
16231621
cgi_init();
16241622
}
16251623
16261624
16271625
#if INTERFACE
1628
-/*
1626
+/*
16291627
** Bitmap values for the flags parameter to cgi_http_server().
16301628
*/
16311629
#define HTTP_SERVER_LOCALHOST 0x0001 /* Bind to 127.0.0.1 only */
16321630
#define HTTP_SERVER_SCGI 0x0002 /* SCGI instead of HTTP */
16331631
@@ -1708,15 +1706,13 @@
17081706
" port in the range %d..%d", mnPort, mxPort);
17091707
}
17101708
}
17111709
if( iPort>mxPort ) return 1;
17121710
listen(listener,10);
1713
- if( iPort>mnPort ){
1714
- fossil_print("Listening for %s requests on TCP port %d\n",
1715
- (flags & HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP", iPort);
1716
- fflush(stdout);
1717
- }
1711
+ fossil_print("Listening for %s requests on TCP port %d\n",
1712
+ (flags & HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP", iPort);
1713
+ fflush(stdout);
17181714
if( zBrowser ){
17191715
zBrowser = mprintf(zBrowser, iPort);
17201716
#if defined(__CYGWIN__)
17211717
/* On Cygwin, we can do better than "echo" */
17221718
if( memcmp(zBrowser, "echo ", 5)==0 ){
@@ -1771,11 +1767,11 @@
17711767
/* Bury dead children */
17721768
while( waitpid(0, 0, WNOHANG)>0 ){
17731769
nchildren--;
17741770
}
17751771
}
1776
- /* NOT REACHED */
1772
+ /* NOT REACHED */
17771773
fossil_exit(1);
17781774
#endif
17791775
/* NOT REACHED */
17801776
return 0;
17811777
}
@@ -1859,11 +1855,11 @@
18591855
p->tm_mon %= 12;
18601856
}
18611857
isLeapYr = p->tm_year%4==0 && (p->tm_year%100!=0 || (p->tm_year+300)%400==0);
18621858
p->tm_yday = priorDays[p->tm_mon] + p->tm_mday - 1;
18631859
if( isLeapYr && p->tm_mon>1 ) p->tm_yday++;
1864
- nDay = (p->tm_year-70)*365 + (p->tm_year-69)/4 -p->tm_year/100 +
1860
+ nDay = (p->tm_year-70)*365 + (p->tm_year-69)/4 -p->tm_year/100 +
18651861
(p->tm_year+300)/400 + p->tm_yday;
18661862
t = ((nDay*24 + p->tm_hour)*60 + p->tm_min)*60 + p->tm_sec;
18671863
return t;
18681864
}
18691865
18701866
--- src/cgi.c
+++ src/cgi.c
@@ -266,11 +266,11 @@
266 zTok = strtok_r(0, ",\"",&zPos)){}
267 fossil_free(zBuf);
268 if(zTok) return 1;
269 }
270 }
271
272 return 0;
273 }
274 #endif
275
276 /*
@@ -497,11 +497,11 @@
497 ** must be made of zValue.
498 */
499 void cgi_setenv(const char *zName, const char *zValue){
500 cgi_set_parameter_nocopy(zName, mprintf("%s",zValue), 0);
501 }
502
503
504 /*
505 ** Add a list of query parameters or cookies to the parameter set.
506 **
507 ** Each parameter is of the form NAME=VALUE. Both the NAME and the
@@ -615,11 +615,11 @@
615 break;
616 }
617 }
618 *pz = &z[i];
619 get_line_from_string(pz, pLen);
620 return z;
621 }
622
623 /*
624 ** Tokenize a line of text into as many as nArg tokens. Make
625 ** azArg[] point to the start of each token.
@@ -722,11 +722,11 @@
722 cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z, 1);
723 }
724 }
725 }
726 }
727 }
728 }
729
730
731 #ifdef FOSSIL_ENABLE_JSON
732 /*
@@ -903,11 +903,11 @@
903 z = (char*)P("HTTP_COOKIE");
904 if( z ){
905 z = mprintf("%s",z);
906 add_param_list(z, ';');
907 }
908
909 z = (char*)P("QUERY_STRING");
910 if( z ){
911 z = mprintf("%s",z);
912 add_param_list(z, '&');
913 }
@@ -919,11 +919,11 @@
919
920 len = atoi(PD("CONTENT_LENGTH", "0"));
921 g.zContentType = zType = P("CONTENT_TYPE");
922 blob_zero(&g.cgiIn);
923 if( len>0 && zType ){
924 if( fossil_strcmp(zType,"application/x-www-form-urlencoded")==0
925 || strncmp(zType,"multipart/form-data",19)==0 ){
926 z = fossil_malloc( len+1 );
927 len = fread(z, 1, len, g.httpIn);
928 z[len] = 0;
929 cgi_trace(z);
@@ -949,11 +949,11 @@
949 /* FIXMEs:
950
951 - See if fossil really needs g.cgiIn to be set for this purpose
952 (i don't think it does). If it does then fill g.cgiIn and
953 refactor to parse the JSON from there.
954
955 - After parsing POST JSON, copy the "first layer" of keys/values
956 to cgi_setenv(), honoring the upper-case distinction used
957 in add_param_list(). However...
958
959 - If we do that then we might get a disconnect in precedence of
@@ -1225,11 +1225,11 @@
1225 ** loaded into g.zIpAddr.
1226 */
1227 static const char *cgi_accept_forwarded_for(const char *z){
1228 int i;
1229 if( fossil_strcmp(g.zIpAddr, "127.0.0.1")!=0 ) return 0;
1230
1231 i = strlen(z)-1;
1232 while( i>=0 && z[i]!=',' && !fossil_isspace(z[i]) ) i--;
1233 return &z[++i];
1234 }
1235
@@ -1297,20 +1297,20 @@
1297 for(i=0; zToken[i] && zToken[i]!='?'; i++){}
1298 if( zToken[i] ) zToken[i++] = 0;
1299 cgi_setenv("PATH_INFO", zToken);
1300 cgi_setenv("QUERY_STRING", &zToken[i]);
1301 if( zIpAddr==0 &&
1302 getpeername(fileno(g.httpIn), (struct sockaddr*)&remoteName,
1303 &size)>=0
1304 ){
1305 zIpAddr = inet_ntoa(remoteName.sin_addr);
1306 }
1307 if( zIpAddr ){
1308 cgi_setenv("REMOTE_ADDR", zIpAddr);
1309 g.zIpAddr = mprintf("%s", zIpAddr);
1310 }
1311
1312 /* Get all the optional fields that follow the first line.
1313 */
1314 while( fgets(zLine,sizeof(zLine),g.httpIn) ){
1315 char *zFieldName;
1316 char *zVal;
@@ -1340,14 +1340,12 @@
1340 cgi_setenv("HTTP_HOST", zVal);
1341 }else if( fossil_strcmp(zFieldName,"if-none-match:")==0 ){
1342 cgi_setenv("HTTP_IF_NONE_MATCH", zVal);
1343 }else if( fossil_strcmp(zFieldName,"if-modified-since:")==0 ){
1344 cgi_setenv("HTTP_IF_MODIFIED_SINCE", zVal);
1345 #if 0
1346 }else if( fossil_strcmp(zFieldName,"referer:")==0 ){
1347 cgi_setenv("HTTP_REFERER", zVal);
1348 #endif
1349 }else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){
1350 cgi_setenv("HTTP_USER_AGENT", zVal);
1351 }else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){
1352 const char *zIpAddr = cgi_accept_forwarded_for(zVal);
1353 if( zIpAddr!=0 ){
@@ -1376,11 +1374,11 @@
1376 const char *zType = 0;
1377 int i, content_length = 0;
1378 char zLine[2000]; /* A single line of input. */
1379
1380 if( zIpAddr ){
1381 if( nCycles==0 ){
1382 cgi_setenv("REMOTE_ADDR", zIpAddr);
1383 g.zIpAddr = mprintf("%s", zIpAddr);
1384 }
1385 }else{
1386 fossil_panic("missing SSH IP address");
@@ -1442,11 +1440,11 @@
1442 if( nCycles==0 ){
1443 cgi_setenv("PATH_INFO", zToken);
1444 }else{
1445 cgi_replace_parameter("PATH_INFO", mprintf("%s",zToken));
1446 }
1447
1448 /* Get all the optional fields that follow the first line.
1449 */
1450 while( fgets(zLine,sizeof(zLine),g.httpIn) ){
1451 char *zFieldName;
1452 char *zVal;
@@ -1623,11 +1621,11 @@
1623 cgi_init();
1624 }
1625
1626
1627 #if INTERFACE
1628 /*
1629 ** Bitmap values for the flags parameter to cgi_http_server().
1630 */
1631 #define HTTP_SERVER_LOCALHOST 0x0001 /* Bind to 127.0.0.1 only */
1632 #define HTTP_SERVER_SCGI 0x0002 /* SCGI instead of HTTP */
1633
@@ -1708,15 +1706,13 @@
1708 " port in the range %d..%d", mnPort, mxPort);
1709 }
1710 }
1711 if( iPort>mxPort ) return 1;
1712 listen(listener,10);
1713 if( iPort>mnPort ){
1714 fossil_print("Listening for %s requests on TCP port %d\n",
1715 (flags & HTTP_SERVER_SCGI)!=0?"SCGI":"HTTP", iPort);
1716 fflush(stdout);
1717 }
1718 if( zBrowser ){
1719 zBrowser = mprintf(zBrowser, iPort);
1720 #if defined(__CYGWIN__)
1721 /* On Cygwin, we can do better than "echo" */
1722 if( memcmp(zBrowser, "echo ", 5)==0 ){
@@ -1771,11 +1767,11 @@
1771 /* Bury dead children */
1772 while( waitpid(0, 0, WNOHANG)>0 ){
1773 nchildren--;
1774 }
1775 }
1776 /* NOT REACHED */
1777 fossil_exit(1);
1778 #endif
1779 /* NOT REACHED */
1780 return 0;
1781 }
@@ -1859,11 +1855,11 @@
1859 p->tm_mon %= 12;
1860 }
1861 isLeapYr = p->tm_year%4==0 && (p->tm_year%100!=0 || (p->tm_year+300)%400==0);
1862 p->tm_yday = priorDays[p->tm_mon] + p->tm_mday - 1;
1863 if( isLeapYr && p->tm_mon>1 ) p->tm_yday++;
1864 nDay = (p->tm_year-70)*365 + (p->tm_year-69)/4 -p->tm_year/100 +
1865 (p->tm_year+300)/400 + p->tm_yday;
1866 t = ((nDay*24 + p->tm_hour)*60 + p->tm_min)*60 + p->tm_sec;
1867 return t;
1868 }
1869
1870
--- src/cgi.c
+++ src/cgi.c
@@ -266,11 +266,11 @@
266 zTok = strtok_r(0, ",\"",&zPos)){}
267 fossil_free(zBuf);
268 if(zTok) return 1;
269 }
270 }
271
272 return 0;
273 }
274 #endif
275
276 /*
@@ -497,11 +497,11 @@
497 ** must be made of zValue.
498 */
499 void cgi_setenv(const char *zName, const char *zValue){
500 cgi_set_parameter_nocopy(zName, mprintf("%s",zValue), 0);
501 }
502
503
504 /*
505 ** Add a list of query parameters or cookies to the parameter set.
506 **
507 ** Each parameter is of the form NAME=VALUE. Both the NAME and the
@@ -615,11 +615,11 @@
615 break;
616 }
617 }
618 *pz = &z[i];
619 get_line_from_string(pz, pLen);
620 return z;
621 }
622
623 /*
624 ** Tokenize a line of text into as many as nArg tokens. Make
625 ** azArg[] point to the start of each token.
@@ -722,11 +722,11 @@
722 cgi_set_parameter_nocopy(mprintf("%s:mimetype",zName), z, 1);
723 }
724 }
725 }
726 }
727 }
728 }
729
730
731 #ifdef FOSSIL_ENABLE_JSON
732 /*
@@ -903,11 +903,11 @@
903 z = (char*)P("HTTP_COOKIE");
904 if( z ){
905 z = mprintf("%s",z);
906 add_param_list(z, ';');
907 }
908
909 z = (char*)P("QUERY_STRING");
910 if( z ){
911 z = mprintf("%s",z);
912 add_param_list(z, '&');
913 }
@@ -919,11 +919,11 @@
919
920 len = atoi(PD("CONTENT_LENGTH", "0"));
921 g.zContentType = zType = P("CONTENT_TYPE");
922 blob_zero(&g.cgiIn);
923 if( len>0 && zType ){
924 if( fossil_strcmp(zType,"application/x-www-form-urlencoded")==0
925 || strncmp(zType,"multipart/form-data",19)==0 ){
926 z = fossil_malloc( len+1 );
927 len = fread(z, 1, len, g.httpIn);
928 z[len] = 0;
929 cgi_trace(z);
@@ -949,11 +949,11 @@
949 /* FIXMEs:
950
951 - See if fossil really needs g.cgiIn to be set for this purpose
952 (i don't think it does). If it does then fill g.cgiIn and
953 refactor to parse the JSON from there.
954
955 - After parsing POST JSON, copy the "first layer" of keys/values
956 to cgi_setenv(), honoring the upper-case distinction used
957 in add_param_list(). However...
958
959 - If we do that then we might get a disconnect in precedence of
@@ -1225,11 +1225,11 @@
1225 ** loaded into g.zIpAddr.
1226 */
1227 static const char *cgi_accept_forwarded_for(const char *z){
1228 int i;
1229 if( fossil_strcmp(g.zIpAddr, "127.0.0.1")!=0 ) return 0;
1230
1231 i = strlen(z)-1;
1232 while( i>=0 && z[i]!=',' && !fossil_isspace(z[i]) ) i--;
1233 return &z[++i];
1234 }
1235
@@ -1297,20 +1297,20 @@
1297 for(i=0; zToken[i] && zToken[i]!='?'; i++){}
1298 if( zToken[i] ) zToken[i++] = 0;
1299 cgi_setenv("PATH_INFO", zToken);
1300 cgi_setenv("QUERY_STRING", &zToken[i]);
1301 if( zIpAddr==0 &&
1302 getpeername(fileno(g.httpIn), (struct sockaddr*)&remoteName,
1303 &size)>=0
1304 ){
1305 zIpAddr = inet_ntoa(remoteName.sin_addr);
1306 }
1307 if( zIpAddr ){
1308 cgi_setenv("REMOTE_ADDR", zIpAddr);
1309 g.zIpAddr = mprintf("%s", zIpAddr);
1310 }
1311
1312 /* Get all the optional fields that follow the first line.
1313 */
1314 while( fgets(zLine,sizeof(zLine),g.httpIn) ){
1315 char *zFieldName;
1316 char *zVal;
@@ -1340,14 +1340,12 @@
1340 cgi_setenv("HTTP_HOST", zVal);
1341 }else if( fossil_strcmp(zFieldName,"if-none-match:")==0 ){
1342 cgi_setenv("HTTP_IF_NONE_MATCH", zVal);
1343 }else if( fossil_strcmp(zFieldName,"if-modified-since:")==0 ){
1344 cgi_setenv("HTTP_IF_MODIFIED_SINCE", zVal);
 
1345 }else if( fossil_strcmp(zFieldName,"referer:")==0 ){
1346 cgi_setenv("HTTP_REFERER", zVal);
 
1347 }else if( fossil_strcmp(zFieldName,"user-agent:")==0 ){
1348 cgi_setenv("HTTP_USER_AGENT", zVal);
1349 }else if( fossil_strcmp(zFieldName,"x-forwarded-for:")==0 ){
1350 const char *zIpAddr = cgi_accept_forwarded_for(zVal);
1351 if( zIpAddr!=0 ){
@@ -1376,11 +1374,11 @@
1374 const char *zType = 0;
1375 int i, content_length = 0;
1376 char zLine[2000]; /* A single line of input. */
1377
1378 if( zIpAddr ){
1379 if( nCycles==0 ){
1380 cgi_setenv("REMOTE_ADDR", zIpAddr);
1381 g.zIpAddr = mprintf("%s", zIpAddr);
1382 }
1383 }else{
1384 fossil_panic("missing SSH IP address");
@@ -1442,11 +1440,11 @@
1440 if( nCycles==0 ){
1441 cgi_setenv("PATH_INFO", zToken);
1442 }else{
1443 cgi_replace_parameter("PATH_INFO", mprintf("%s",zToken));
1444 }
1445
1446 /* Get all the optional fields that follow the first line.
1447 */
1448 while( fgets(zLine,sizeof(zLine),g.httpIn) ){
1449 char *zFieldName;
1450 char *zVal;
@@ -1623,11 +1621,11 @@
1621 cgi_init();
1622 }
1623
1624
1625 #if INTERFACE
1626 /*
1627 ** Bitmap values for the flags parameter to cgi_http_server().
1628 */
1629 #define HTTP_SERVER_LOCALHOST 0x0001 /* Bind to 127.0.0.1 only */
1630 #define HTTP_SERVER_SCGI 0x0002 /* SCGI instead of HTTP */
1631
@@ -1708,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 ){
@@ -1771,11 +1767,11 @@
1767 /* Bury dead children */
1768 while( waitpid(0, 0, WNOHANG)>0 ){
1769 nchildren--;
1770 }
1771 }
1772 /* NOT REACHED */
1773 fossil_exit(1);
1774 #endif
1775 /* NOT REACHED */
1776 return 0;
1777 }
@@ -1859,11 +1855,11 @@
1855 p->tm_mon %= 12;
1856 }
1857 isLeapYr = p->tm_year%4==0 && (p->tm_year%100!=0 || (p->tm_year+300)%400==0);
1858 p->tm_yday = priorDays[p->tm_mon] + p->tm_mday - 1;
1859 if( isLeapYr && p->tm_mon>1 ) p->tm_yday++;
1860 nDay = (p->tm_year-70)*365 + (p->tm_year-69)/4 -p->tm_year/100 +
1861 (p->tm_year+300)/400 + p->tm_yday;
1862 t = ((nDay*24 + p->tm_hour)*60 + p->tm_min)*60 + p->tm_sec;
1863 return t;
1864 }
1865
1866
+1 -1
--- src/comformat.c
+++ src/comformat.c
@@ -34,11 +34,11 @@
3434
int tlen = lineLength - indent;
3535
int si, sk, i, k;
3636
int doIndent = 0;
3737
char *zBuf;
3838
char zBuffer[400];
39
- int lineCnt = 0;
39
+ int lineCnt = 0;
4040
4141
if( tlen<=0 ){
4242
tlen = strlen(zText);
4343
}
4444
if( tlen >= (sizeof(zBuffer)) ){
4545
--- src/comformat.c
+++ src/comformat.c
@@ -34,11 +34,11 @@
34 int tlen = lineLength - indent;
35 int si, sk, i, k;
36 int doIndent = 0;
37 char *zBuf;
38 char zBuffer[400];
39 int lineCnt = 0;
40
41 if( tlen<=0 ){
42 tlen = strlen(zText);
43 }
44 if( tlen >= (sizeof(zBuffer)) ){
45
--- src/comformat.c
+++ src/comformat.c
@@ -34,11 +34,11 @@
34 int tlen = lineLength - indent;
35 int si, sk, i, k;
36 int doIndent = 0;
37 char *zBuf;
38 char zBuffer[400];
39 int lineCnt = 0;
40
41 if( tlen<=0 ){
42 tlen = strlen(zText);
43 }
44 if( tlen >= (sizeof(zBuffer)) ){
45
+17 -17
--- src/content.c
+++ src/content.c
@@ -114,11 +114,11 @@
114114
contentCache.n = 0;
115115
contentCache.szTotal = 0;
116116
}
117117
118118
/*
119
-** Return the srcid associated with rid. Or return 0 if rid is
119
+** Return the srcid associated with rid. Or return 0 if rid is
120120
** original content and not a delta.
121121
*/
122122
static int findSrcid(int rid){
123123
static Stmt q;
124124
int srcid;
@@ -154,11 +154,11 @@
154154
** a phantom.
155155
*/
156156
int content_is_available(int rid){
157157
int srcid;
158158
int depth = 0; /* Limit to recursion depth */
159
- while( depth++ < 10000000 ){
159
+ while( depth++ < 10000000 ){
160160
if( bag_find(&contentCache.missing, rid) ){
161161
return 0;
162162
}
163163
if( bag_find(&contentCache.available, rid) ){
164164
return 1;
@@ -416,11 +416,11 @@
416416
417417
/* Recursively dephantomize all artifacts that are derived by
418418
** delta from artifact rid and which have not already been
419419
** cross-linked. */
420420
nChildUsed = 0;
421
- db_prepare(&q,
421
+ db_prepare(&q,
422422
"SELECT rid FROM delta"
423423
" WHERE srcid=%d"
424424
" AND NOT EXISTS(SELECT 1 FROM mlink WHERE mid=delta.rid)",
425425
rid
426426
);
@@ -455,11 +455,11 @@
455455
/*
456456
** Write content into the database. Return the record ID. If the
457457
** content is already in the database, just return the record ID.
458458
**
459459
** If srcId is specified, then pBlob is delta content from
460
-** the srcId record. srcId might be a phantom.
460
+** the srcId record. srcId might be a phantom.
461461
**
462462
** pBlob is normally uncompressed text. But if nBlob>0 then the
463463
** pBlob value has already been compressed and nBlob is its uncompressed
464464
** size. If nBlob>0 then zUuid must be valid.
465465
**
@@ -486,11 +486,11 @@
486486
Stmt s1;
487487
Blob cmpr;
488488
Blob hash;
489489
int markAsUnclustered = 0;
490490
int isDephantomize = 0;
491
-
491
+
492492
assert( g.repositoryOpen );
493493
assert( pBlob!=0 );
494494
assert( srcId==0 || zUuid!=0 );
495495
if( zUuid==0 ){
496496
assert( nBlob==0 );
@@ -580,18 +580,18 @@
580580
** really a delta. Record this fact in the delta table.
581581
*/
582582
if( srcId ){
583583
db_multi_exec("REPLACE INTO delta(rid,srcid) VALUES(%d,%d)", rid, srcId);
584584
}
585
- if( !isDephantomize && bag_find(&contentCache.missing, rid) &&
585
+ if( !isDephantomize && bag_find(&contentCache.missing, rid) &&
586586
(srcId==0 || content_is_available(srcId)) ){
587587
content_mark_available(rid);
588588
}
589589
if( isDephantomize ){
590590
after_dephantomize(rid, 0);
591591
}
592
-
592
+
593593
/* Add the element to the unclustered table if has never been
594594
** previously seen.
595595
*/
596596
if( markAsUnclustered ){
597597
db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d)", rid);
@@ -628,11 +628,11 @@
628628
** Create a new phantom with the given UUID and return its artifact ID.
629629
*/
630630
int content_new(const char *zUuid, int isPrivate){
631631
int rid;
632632
static Stmt s1, s2, s3;
633
-
633
+
634634
assert( g.repositoryOpen );
635635
db_begin_transaction();
636636
if( uuid_is_shunned(zUuid) ){
637637
db_end_transaction(0);
638638
return 0;
@@ -727,15 +727,15 @@
727727
"SELECT 1 FROM private WHERE rid=:rid"
728728
);
729729
db_bind_int(&s1, ":rid", rid);
730730
rc = db_step(&s1);
731731
db_reset(&s1);
732
- return rc==SQLITE_ROW;
732
+ return rc==SQLITE_ROW;
733733
}
734734
735735
/*
736
-** Make sure an artifact is public.
736
+** Make sure an artifact is public.
737737
*/
738738
void content_make_public(int rid){
739739
static Stmt s1;
740740
db_static_prepare(&s1,
741741
"DELETE FROM private WHERE rid=:rid"
@@ -758,11 +758,11 @@
758758
**
759759
** If srcid is a delta that depends on rid, then srcid is
760760
** converted to undeltaed text.
761761
**
762762
** If either rid or srcid contain less than 50 bytes, or if the
763
-** resulting delta does not achieve a compression of at least 25%
763
+** resulting delta does not achieve a compression of at least 25%
764764
** the rid is left untouched.
765765
**
766766
** Return 1 if a delta is made and 0 if no delta occurs.
767767
*/
768768
int content_deltify(int rid, int srcid, int force){
@@ -883,11 +883,11 @@
883883
zId, rid, zSrc, srcid
884884
);
885885
nErr++;
886886
}
887887
db_finalize(&q);
888
-
888
+
889889
db_prepare(&q, "SELECT rid, uuid, size FROM blob ORDER BY rid");
890890
total = db_int(0, "SELECT max(rid) FROM blob");
891891
while( db_step(&q)==SQLITE_ROW ){
892892
int rid = db_column_int(&q, 0);
893893
const char *zUuid = db_column_text(&q, 1);
@@ -945,12 +945,12 @@
945945
}
946946
db_finalize(&q);
947947
fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n",
948948
n2, n1, nErr);
949949
if( bParse ){
950
- const char *azType[] = { 0, "manifest", "cluster", "control", "wiki",
951
- "ticket", "attachment", "event" };
950
+ static const char *const azType[] = { 0, "manifest", "cluster",
951
+ "control", "wiki", "ticket", "attachment", "event" };
952952
int i;
953953
fossil_print("%d total control artifacts\n", nCA);
954954
for(i=1; i<count(azType); i++){
955955
if( anCA[i] ) fossil_print(" %d %ss\n", anCA[i], azType[i]);
956956
}
@@ -1050,11 +1050,11 @@
10501050
if( zDetail && zDetail[0] ){
10511051
fossil_print(" %s\n", zDetail);
10521052
}
10531053
fossil_free(zSrc);
10541054
fossil_free(zDate);
1055
- rc = 1;
1055
+ rc = 1;
10561056
}
10571057
return rc;
10581058
}
10591059
10601060
/*
@@ -1097,11 +1097,11 @@
10971097
if( p ){
10981098
nArtifact++;
10991099
nErr += check_exists(p->zBaseline, flags, p, "baseline of", 0);
11001100
nErr += check_exists(p->zAttachSrc, flags, p, "file of", 0);
11011101
for(i=0; i<p->nFile; i++){
1102
- nErr += check_exists(p->aFile[i].zUuid, flags, p, "file of",
1102
+ nErr += check_exists(p->aFile[i].zUuid, flags, p, "file of",
11031103
p->aFile[i].zName);
11041104
}
11051105
for(i=0; i<p->nParent; i++){
11061106
nErr += check_exists(p->azParent[i], flags, p, "parent of", 0);
11071107
}
@@ -1115,14 +1115,14 @@
11151115
nErr += check_exists(p->azCChild[i], flags, p, "in", 0);
11161116
}
11171117
for(i=0; i<p->nTag; i++){
11181118
nErr += check_exists(p->aTag[i].zUuid, flags, p, "target of", 0);
11191119
}
1120
- manifest_destroy(p);
1120
+ manifest_destroy(p);
11211121
}
11221122
}
11231123
db_finalize(&q);
11241124
if( nErr>0 || quietFlag==0 ){
11251125
fossil_print("%d missing or shunned references in %d control artifacts\n",
11261126
nErr, nArtifact);
11271127
}
11281128
}
11291129
--- src/content.c
+++ src/content.c
@@ -114,11 +114,11 @@
114 contentCache.n = 0;
115 contentCache.szTotal = 0;
116 }
117
118 /*
119 ** Return the srcid associated with rid. Or return 0 if rid is
120 ** original content and not a delta.
121 */
122 static int findSrcid(int rid){
123 static Stmt q;
124 int srcid;
@@ -154,11 +154,11 @@
154 ** a phantom.
155 */
156 int content_is_available(int rid){
157 int srcid;
158 int depth = 0; /* Limit to recursion depth */
159 while( depth++ < 10000000 ){
160 if( bag_find(&contentCache.missing, rid) ){
161 return 0;
162 }
163 if( bag_find(&contentCache.available, rid) ){
164 return 1;
@@ -416,11 +416,11 @@
416
417 /* Recursively dephantomize all artifacts that are derived by
418 ** delta from artifact rid and which have not already been
419 ** cross-linked. */
420 nChildUsed = 0;
421 db_prepare(&q,
422 "SELECT rid FROM delta"
423 " WHERE srcid=%d"
424 " AND NOT EXISTS(SELECT 1 FROM mlink WHERE mid=delta.rid)",
425 rid
426 );
@@ -455,11 +455,11 @@
455 /*
456 ** Write content into the database. Return the record ID. If the
457 ** content is already in the database, just return the record ID.
458 **
459 ** If srcId is specified, then pBlob is delta content from
460 ** the srcId record. srcId might be a phantom.
461 **
462 ** pBlob is normally uncompressed text. But if nBlob>0 then the
463 ** pBlob value has already been compressed and nBlob is its uncompressed
464 ** size. If nBlob>0 then zUuid must be valid.
465 **
@@ -486,11 +486,11 @@
486 Stmt s1;
487 Blob cmpr;
488 Blob hash;
489 int markAsUnclustered = 0;
490 int isDephantomize = 0;
491
492 assert( g.repositoryOpen );
493 assert( pBlob!=0 );
494 assert( srcId==0 || zUuid!=0 );
495 if( zUuid==0 ){
496 assert( nBlob==0 );
@@ -580,18 +580,18 @@
580 ** really a delta. Record this fact in the delta table.
581 */
582 if( srcId ){
583 db_multi_exec("REPLACE INTO delta(rid,srcid) VALUES(%d,%d)", rid, srcId);
584 }
585 if( !isDephantomize && bag_find(&contentCache.missing, rid) &&
586 (srcId==0 || content_is_available(srcId)) ){
587 content_mark_available(rid);
588 }
589 if( isDephantomize ){
590 after_dephantomize(rid, 0);
591 }
592
593 /* Add the element to the unclustered table if has never been
594 ** previously seen.
595 */
596 if( markAsUnclustered ){
597 db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d)", rid);
@@ -628,11 +628,11 @@
628 ** Create a new phantom with the given UUID and return its artifact ID.
629 */
630 int content_new(const char *zUuid, int isPrivate){
631 int rid;
632 static Stmt s1, s2, s3;
633
634 assert( g.repositoryOpen );
635 db_begin_transaction();
636 if( uuid_is_shunned(zUuid) ){
637 db_end_transaction(0);
638 return 0;
@@ -727,15 +727,15 @@
727 "SELECT 1 FROM private WHERE rid=:rid"
728 );
729 db_bind_int(&s1, ":rid", rid);
730 rc = db_step(&s1);
731 db_reset(&s1);
732 return rc==SQLITE_ROW;
733 }
734
735 /*
736 ** Make sure an artifact is public.
737 */
738 void content_make_public(int rid){
739 static Stmt s1;
740 db_static_prepare(&s1,
741 "DELETE FROM private WHERE rid=:rid"
@@ -758,11 +758,11 @@
758 **
759 ** If srcid is a delta that depends on rid, then srcid is
760 ** converted to undeltaed text.
761 **
762 ** If either rid or srcid contain less than 50 bytes, or if the
763 ** resulting delta does not achieve a compression of at least 25%
764 ** the rid is left untouched.
765 **
766 ** Return 1 if a delta is made and 0 if no delta occurs.
767 */
768 int content_deltify(int rid, int srcid, int force){
@@ -883,11 +883,11 @@
883 zId, rid, zSrc, srcid
884 );
885 nErr++;
886 }
887 db_finalize(&q);
888
889 db_prepare(&q, "SELECT rid, uuid, size FROM blob ORDER BY rid");
890 total = db_int(0, "SELECT max(rid) FROM blob");
891 while( db_step(&q)==SQLITE_ROW ){
892 int rid = db_column_int(&q, 0);
893 const char *zUuid = db_column_text(&q, 1);
@@ -945,12 +945,12 @@
945 }
946 db_finalize(&q);
947 fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n",
948 n2, n1, nErr);
949 if( bParse ){
950 const char *azType[] = { 0, "manifest", "cluster", "control", "wiki",
951 "ticket", "attachment", "event" };
952 int i;
953 fossil_print("%d total control artifacts\n", nCA);
954 for(i=1; i<count(azType); i++){
955 if( anCA[i] ) fossil_print(" %d %ss\n", anCA[i], azType[i]);
956 }
@@ -1050,11 +1050,11 @@
1050 if( zDetail && zDetail[0] ){
1051 fossil_print(" %s\n", zDetail);
1052 }
1053 fossil_free(zSrc);
1054 fossil_free(zDate);
1055 rc = 1;
1056 }
1057 return rc;
1058 }
1059
1060 /*
@@ -1097,11 +1097,11 @@
1097 if( p ){
1098 nArtifact++;
1099 nErr += check_exists(p->zBaseline, flags, p, "baseline of", 0);
1100 nErr += check_exists(p->zAttachSrc, flags, p, "file of", 0);
1101 for(i=0; i<p->nFile; i++){
1102 nErr += check_exists(p->aFile[i].zUuid, flags, p, "file of",
1103 p->aFile[i].zName);
1104 }
1105 for(i=0; i<p->nParent; i++){
1106 nErr += check_exists(p->azParent[i], flags, p, "parent of", 0);
1107 }
@@ -1115,14 +1115,14 @@
1115 nErr += check_exists(p->azCChild[i], flags, p, "in", 0);
1116 }
1117 for(i=0; i<p->nTag; i++){
1118 nErr += check_exists(p->aTag[i].zUuid, flags, p, "target of", 0);
1119 }
1120 manifest_destroy(p);
1121 }
1122 }
1123 db_finalize(&q);
1124 if( nErr>0 || quietFlag==0 ){
1125 fossil_print("%d missing or shunned references in %d control artifacts\n",
1126 nErr, nArtifact);
1127 }
1128 }
1129
--- src/content.c
+++ src/content.c
@@ -114,11 +114,11 @@
114 contentCache.n = 0;
115 contentCache.szTotal = 0;
116 }
117
118 /*
119 ** Return the srcid associated with rid. Or return 0 if rid is
120 ** original content and not a delta.
121 */
122 static int findSrcid(int rid){
123 static Stmt q;
124 int srcid;
@@ -154,11 +154,11 @@
154 ** a phantom.
155 */
156 int content_is_available(int rid){
157 int srcid;
158 int depth = 0; /* Limit to recursion depth */
159 while( depth++ < 10000000 ){
160 if( bag_find(&contentCache.missing, rid) ){
161 return 0;
162 }
163 if( bag_find(&contentCache.available, rid) ){
164 return 1;
@@ -416,11 +416,11 @@
416
417 /* Recursively dephantomize all artifacts that are derived by
418 ** delta from artifact rid and which have not already been
419 ** cross-linked. */
420 nChildUsed = 0;
421 db_prepare(&q,
422 "SELECT rid FROM delta"
423 " WHERE srcid=%d"
424 " AND NOT EXISTS(SELECT 1 FROM mlink WHERE mid=delta.rid)",
425 rid
426 );
@@ -455,11 +455,11 @@
455 /*
456 ** Write content into the database. Return the record ID. If the
457 ** content is already in the database, just return the record ID.
458 **
459 ** If srcId is specified, then pBlob is delta content from
460 ** the srcId record. srcId might be a phantom.
461 **
462 ** pBlob is normally uncompressed text. But if nBlob>0 then the
463 ** pBlob value has already been compressed and nBlob is its uncompressed
464 ** size. If nBlob>0 then zUuid must be valid.
465 **
@@ -486,11 +486,11 @@
486 Stmt s1;
487 Blob cmpr;
488 Blob hash;
489 int markAsUnclustered = 0;
490 int isDephantomize = 0;
491
492 assert( g.repositoryOpen );
493 assert( pBlob!=0 );
494 assert( srcId==0 || zUuid!=0 );
495 if( zUuid==0 ){
496 assert( nBlob==0 );
@@ -580,18 +580,18 @@
580 ** really a delta. Record this fact in the delta table.
581 */
582 if( srcId ){
583 db_multi_exec("REPLACE INTO delta(rid,srcid) VALUES(%d,%d)", rid, srcId);
584 }
585 if( !isDephantomize && bag_find(&contentCache.missing, rid) &&
586 (srcId==0 || content_is_available(srcId)) ){
587 content_mark_available(rid);
588 }
589 if( isDephantomize ){
590 after_dephantomize(rid, 0);
591 }
592
593 /* Add the element to the unclustered table if has never been
594 ** previously seen.
595 */
596 if( markAsUnclustered ){
597 db_multi_exec("INSERT OR IGNORE INTO unclustered VALUES(%d)", rid);
@@ -628,11 +628,11 @@
628 ** Create a new phantom with the given UUID and return its artifact ID.
629 */
630 int content_new(const char *zUuid, int isPrivate){
631 int rid;
632 static Stmt s1, s2, s3;
633
634 assert( g.repositoryOpen );
635 db_begin_transaction();
636 if( uuid_is_shunned(zUuid) ){
637 db_end_transaction(0);
638 return 0;
@@ -727,15 +727,15 @@
727 "SELECT 1 FROM private WHERE rid=:rid"
728 );
729 db_bind_int(&s1, ":rid", rid);
730 rc = db_step(&s1);
731 db_reset(&s1);
732 return rc==SQLITE_ROW;
733 }
734
735 /*
736 ** Make sure an artifact is public.
737 */
738 void content_make_public(int rid){
739 static Stmt s1;
740 db_static_prepare(&s1,
741 "DELETE FROM private WHERE rid=:rid"
@@ -758,11 +758,11 @@
758 **
759 ** If srcid is a delta that depends on rid, then srcid is
760 ** converted to undeltaed text.
761 **
762 ** If either rid or srcid contain less than 50 bytes, or if the
763 ** resulting delta does not achieve a compression of at least 25%
764 ** the rid is left untouched.
765 **
766 ** Return 1 if a delta is made and 0 if no delta occurs.
767 */
768 int content_deltify(int rid, int srcid, int force){
@@ -883,11 +883,11 @@
883 zId, rid, zSrc, srcid
884 );
885 nErr++;
886 }
887 db_finalize(&q);
888
889 db_prepare(&q, "SELECT rid, uuid, size FROM blob ORDER BY rid");
890 total = db_int(0, "SELECT max(rid) FROM blob");
891 while( db_step(&q)==SQLITE_ROW ){
892 int rid = db_column_int(&q, 0);
893 const char *zUuid = db_column_text(&q, 1);
@@ -945,12 +945,12 @@
945 }
946 db_finalize(&q);
947 fossil_print("%d non-phantom blobs (out of %d total) checked: %d errors\n",
948 n2, n1, nErr);
949 if( bParse ){
950 static const char *const azType[] = { 0, "manifest", "cluster",
951 "control", "wiki", "ticket", "attachment", "event" };
952 int i;
953 fossil_print("%d total control artifacts\n", nCA);
954 for(i=1; i<count(azType); i++){
955 if( anCA[i] ) fossil_print(" %d %ss\n", anCA[i], azType[i]);
956 }
@@ -1050,11 +1050,11 @@
1050 if( zDetail && zDetail[0] ){
1051 fossil_print(" %s\n", zDetail);
1052 }
1053 fossil_free(zSrc);
1054 fossil_free(zDate);
1055 rc = 1;
1056 }
1057 return rc;
1058 }
1059
1060 /*
@@ -1097,11 +1097,11 @@
1097 if( p ){
1098 nArtifact++;
1099 nErr += check_exists(p->zBaseline, flags, p, "baseline of", 0);
1100 nErr += check_exists(p->zAttachSrc, flags, p, "file of", 0);
1101 for(i=0; i<p->nFile; i++){
1102 nErr += check_exists(p->aFile[i].zUuid, flags, p, "file of",
1103 p->aFile[i].zName);
1104 }
1105 for(i=0; i<p->nParent; i++){
1106 nErr += check_exists(p->azParent[i], flags, p, "parent of", 0);
1107 }
@@ -1115,14 +1115,14 @@
1115 nErr += check_exists(p->azCChild[i], flags, p, "in", 0);
1116 }
1117 for(i=0; i<p->nTag; i++){
1118 nErr += check_exists(p->aTag[i].zUuid, flags, p, "target of", 0);
1119 }
1120 manifest_destroy(p);
1121 }
1122 }
1123 db_finalize(&q);
1124 if( nErr>0 || quietFlag==0 ){
1125 fossil_print("%d missing or shunned references in %d control artifacts\n",
1126 nErr, nArtifact);
1127 }
1128 }
1129
+2 -8
--- 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];
@@ -716,17 +716,11 @@
716716
LOCAL sqlite3 *db_open(const char *zDbName){
717717
int rc;
718718
sqlite3 *db;
719719
720720
#if defined(__CYGWIN__)
721
- /* Necessary if we want Cygwin fossil to recognize win32 file
722
- * paths, as SQLite doesn't handle that (yet) */
723721
zDbName = fossil_utf8_to_filename(zDbName);
724
-#elif defined(_WIN32)
725
- /* Only necessary when SQLite doesn't handle Extended paths. */
726
- zDbName = fossil_utf8_to_filename(zDbName);
727
- zDbName = fossil_filename_to_utf8(zDbName);
728722
#endif
729723
if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName);
730724
rc = sqlite3_open_v2(
731725
zDbName, &db,
732726
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
733727
--- 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];
@@ -716,17 +716,11 @@
716 LOCAL sqlite3 *db_open(const char *zDbName){
717 int rc;
718 sqlite3 *db;
719
720 #if defined(__CYGWIN__)
721 /* Necessary if we want Cygwin fossil to recognize win32 file
722 * paths, as SQLite doesn't handle that (yet) */
723 zDbName = fossil_utf8_to_filename(zDbName);
724 #elif defined(_WIN32)
725 /* Only necessary when SQLite doesn't handle Extended paths. */
726 zDbName = fossil_utf8_to_filename(zDbName);
727 zDbName = fossil_filename_to_utf8(zDbName);
728 #endif
729 if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName);
730 rc = sqlite3_open_v2(
731 zDbName, &db,
732 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
733
--- 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];
@@ -716,17 +716,11 @@
716 LOCAL sqlite3 *db_open(const char *zDbName){
717 int rc;
718 sqlite3 *db;
719
720 #if defined(__CYGWIN__)
 
 
721 zDbName = fossil_utf8_to_filename(zDbName);
 
 
 
 
722 #endif
723 if( g.fSqlTrace ) fossil_trace("-- sqlite3_open: [%s]\n", zDbName);
724 rc = sqlite3_open_v2(
725 zDbName, &db,
726 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
727
--- 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
+52 -35
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -599,11 +599,11 @@
599599
600600
/* A Tcl/Tk script used to render diff output.
601601
*/
602602
static const char zDiffScript[] =
603603
@ package require Tk
604
-@
604
+@
605605
@ array set CFG {
606606
@ TITLE {Fossil Diff}
607607
@ LN_COL_BG #dddddd
608608
@ LN_COL_FG #444444
609609
@ TXT_COL_BG #ffffff
@@ -622,30 +622,30 @@
622622
@ PADX 5
623623
@ WIDTH 80
624624
@ HEIGHT 45
625625
@ LB_HEIGHT 25
626626
@ }
627
-@
627
+@
628628
@ if {![namespace exists ttk]} {
629629
@ interp alias {} ::ttk::scrollbar {} ::scrollbar
630630
@ interp alias {} ::ttk::menubutton {} ::menubutton
631631
@ }
632
-@
632
+@
633633
@ proc dehtml {x} {
634634
@ set x [regsub -all {<[^>]*>} $x {}]
635635
@ return [string map {&amp; & &lt; < &gt; > &#39; ' &quot; \"} $x]
636636
@ }
637
-@
637
+@
638638
@ proc cols {} {
639639
@ return [list .lnA .txtA .mkr .lnB .txtB]
640640
@ }
641
-@
641
+@
642642
@ proc colType {c} {
643643
@ regexp {[a-z]+} $c type
644644
@ return $type
645645
@ }
646
-@
646
+@
647647
@ proc readDiffs {fossilcmd} {
648648
@ set in [open $fossilcmd r]
649649
@ fconfigure $in -encoding utf-8
650650
@ set nDiffs 0
651651
@ array set widths {txt 0 ln 0 mkr 0}
@@ -657,34 +657,34 @@
657657
@ continue
658658
@ }
659659
@ incr nDiffs
660660
@ set idx [expr {$nDiffs > 1 ? [.txtA index end] : "1.0"}]
661661
@ .wfiles.lb insert end $fn
662
-@
662
+@
663663
@ foreach c [cols] {
664664
@ while {[gets $in] ne "<pre>"} continue
665
-@
665
+@
666666
@ if {$nDiffs > 1} {
667667
@ $c insert end \n -
668668
@ }
669669
@ if {[colType $c] eq "txt"} {
670670
@ $c insert end $fn\n fn
671671
@ } else {
672672
@ $c insert end \n fn
673673
@ }
674674
@ $c insert end \n -
675
-@
675
+@
676676
@ set type [colType $c]
677677
@ set str {}
678678
@ while {[set line [gets $in]] ne "</pre>"} {
679679
@ set len [string length [dehtml $line]]
680680
@ if {$len > $widths($type)} {
681681
@ set widths($type) $len
682682
@ }
683683
@ append str $line\n
684684
@ }
685
-@
685
+@
686686
@ set re {<span class="diff([a-z]+)">([^<]*)</span>}
687687
@ # Use \r as separator since it can't appear in the diff output (it gets
688688
@ # converted to a space).
689689
@ set str [regsub -all $re $str "\r\\1\r\\2\r"]
690690
@ foreach {pre class mid} [split $str \r] {
@@ -695,11 +695,11 @@
695695
@ }
696696
@ }
697697
@ }
698698
@ }
699699
@ close $in
700
-@
700
+@
701701
@ foreach c [cols] {
702702
@ set type [colType $c]
703703
@ if {$type ne "txt"} {
704704
@ $c config -width $widths($type)
705705
@ }
@@ -707,19 +707,19 @@
707707
@ }
708708
@ if {$nDiffs <= [.wfiles.lb cget -height]} {
709709
@ .wfiles.lb config -height $nDiffs
710710
@ grid remove .wfiles.sb
711711
@ }
712
-@
712
+@
713713
@ return $nDiffs
714714
@ }
715
-@
715
+@
716716
@ proc viewDiff {idx} {
717717
@ .txtA yview $idx
718718
@ .txtA xview moveto 0
719719
@ }
720
-@
720
+@
721721
@ proc cycleDiffs {{reverse 0}} {
722722
@ if {$reverse} {
723723
@ set range [.txtA tag prevrange fn @0,0 1.0]
724724
@ if {$range eq ""} {
725725
@ viewDiff {fn.last -1c}
@@ -733,36 +733,36 @@
733733
@ } else {
734734
@ viewDiff [lindex $range 0]
735735
@ }
736736
@ }
737737
@ }
738
-@
738
+@
739739
@ proc xvis {col} {
740740
@ set view [$col xview]
741741
@ return [expr {[lindex $view 1]-[lindex $view 0]}]
742742
@ }
743
-@
743
+@
744744
@ proc scroll-x {args} {
745745
@ set c .txt[expr {[xvis .txtA] < [xvis .txtB] ? "A" : "B"}]
746746
@ eval $c xview $args
747747
@ }
748
-@
748
+@
749749
@ interp alias {} scroll-y {} .txtA yview
750
-@
750
+@
751751
@ proc noop {args} {}
752
-@
752
+@
753753
@ proc enableSync {axis} {
754754
@ update idletasks
755755
@ interp alias {} sync-$axis {}
756756
@ rename _sync-$axis sync-$axis
757757
@ }
758
-@
758
+@
759759
@ proc disableSync {axis} {
760760
@ rename sync-$axis _sync-$axis
761761
@ interp alias {} sync-$axis {} noop
762762
@ }
763
-@
763
+@
764764
@ proc sync-x {col first last} {
765765
@ disableSync x
766766
@ $col xview moveto [expr {$first*[xvis $col]/($last-$first)}]
767767
@ foreach side {A B} {
768768
@ set sb .sbx$side
@@ -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
@ }
@@ -788,15 +788,16 @@
788788
@ } else {
789789
@ grid remove .sby
790790
@ }
791791
@ enableSync y
792792
@ }
793
-@
793
+@
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>
@@ -813,11 +814,11 @@
813814
@ End y {moveto 1}
814815
@ } {
815816
@ bind . <$key> "scroll-$axis $args; break"
816817
@ bind . <Shift-$key> continue
817818
@ }
818
-@
819
+@
819820
@ ::ttk::menubutton .files -text "Files"
820821
@ toplevel .wfiles
821822
@ wm withdraw .wfiles
822823
@ update idletasks
823824
@ wm transient .wfiles .
@@ -847,16 +848,16 @@
847848
@ }
848849
@ bind .wfiles.lb <Motion> {
849850
@ %W selection clear 0 end
850851
@ %W selection set @%x,%y
851852
@ }
852
-@
853
+@
853854
@ foreach {side syncCol} {A .txtB B .txtA} {
854855
@ set ln .ln$side
855856
@ text $ln
856857
@ $ln tag config - -justify right
857
-@
858
+@
858859
@ set txt .txt$side
859860
@ text $txt -width $CFG(WIDTH) -height $CFG(HEIGHT) -wrap none \
860861
@ -xscroll "sync-x $syncCol"
861862
@ catch {$txt config -tabstyle wordprocessor} ;# Required for Tk>=8.5
862863
@ foreach tag {add rm chng} {
@@ -865,11 +866,11 @@
865866
@ }
866867
@ $txt tag config fn -background $CFG(FN_BG) -foreground $CFG(FN_FG) \
867868
@ -justify center
868869
@ }
869870
@ text .mkr
870
-@
871
+@
871872
@ foreach c [cols] {
872873
@ set keyPrefix [string toupper [colType $c]]_COL_
873874
@ if {[tk windowingsystem] eq "win32"} {$c config -font {courier 9}}
874875
@ $c config -bg $CFG(${keyPrefix}BG) -fg $CFG(${keyPrefix}FG) -borderwidth 0 \
875876
@ -padx $CFG(PADX) -yscroll sync-y
@@ -877,22 +878,22 @@
877878
@ -foreground $CFG(HR_FG)
878879
@ $c tag config fn -spacing1 $CFG(FN_PAD) -spacing3 $CFG(FN_PAD)
879880
@ bindtags $c ". $c Text all"
880881
@ bind $c <1> {focus %W}
881882
@ }
882
-@
883
+@
883884
@ ::ttk::scrollbar .sby -command {.txtA yview} -orient vertical
884885
@ ::ttk::scrollbar .sbxA -command {.txtA xview} -orient horizontal
885886
@ ::ttk::scrollbar .sbxB -command {.txtB xview} -orient horizontal
886887
@ frame .spacer
887
-@
888
+@
888889
@ if {[readDiffs $fossilcmd] == 0} {
889890
@ tk_messageBox -type ok -title $CFG(TITLE) -message "No changes"
890891
@ exit
891892
@ }
892893
@ update idletasks
893
-@
894
+@
894895
@ grid rowconfigure . 1 -weight 1
895896
@ grid columnconfigure . 1 -weight 1
896897
@ grid columnconfigure . 4 -weight 1
897898
@ grid .files -row 0 -columnspan 6
898899
@ eval grid [cols] -row 1 -sticky nsew
@@ -906,14 +907,16 @@
906907
;
907908
908909
/*
909910
** Show diff output in a Tcl/Tk window, in response to the --tk option
910911
** to the diff command.
911
-**
912
-** Steps:
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:
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);
@@ -988,11 +1005,11 @@
9881005
** specified (as they exist on disk) and that same file as it was checked
9891006
** out. Or if the FILE arguments are omitted, show the unsaved changed
9901007
** currently in the working check-out.
9911008
**
9921009
** If the "--from VERSION" or "-r VERSION" option is used it specifies
993
-** the source check-in for the diff operation. If not specified, the
1010
+** the source check-in for the diff operation. If not specified, the
9941011
** source check-in is the base check-in for the current check-out.
9951012
**
9961013
** If the "--to VERSION" option appears, it specifies the check-in from
9971014
** which the second version of the file or files is taken. If there is
9981015
** no "--to" option then the (possibly edited) files in the current check-out
@@ -1015,11 +1032,11 @@
10151032
**
10161033
** Options:
10171034
** --binary PATTERN Treat files that match the glob PATTERN as binary
10181035
** --branch BRANCH Show diff of all changes on BRANCH
10191036
** --brief Show filenames only
1020
-** --context|-c N Use N lines of context
1037
+** --context|-c N Use N lines of context
10211038
** --diff-binary BOOL Include binary files when using external commands
10221039
** --from|-r VERSION select VERSION as source for the diff
10231040
** --internal|-i use internal diff logic
10241041
** --side-by-side|-y side-by-side diff
10251042
** --tk Launch a Tcl/Tk GUI for display
10261043
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -599,11 +599,11 @@
599
600 /* A Tcl/Tk script used to render diff output.
601 */
602 static const char zDiffScript[] =
603 @ package require Tk
604 @
605 @ array set CFG {
606 @ TITLE {Fossil Diff}
607 @ LN_COL_BG #dddddd
608 @ LN_COL_FG #444444
609 @ TXT_COL_BG #ffffff
@@ -622,30 +622,30 @@
622 @ PADX 5
623 @ WIDTH 80
624 @ HEIGHT 45
625 @ LB_HEIGHT 25
626 @ }
627 @
628 @ if {![namespace exists ttk]} {
629 @ interp alias {} ::ttk::scrollbar {} ::scrollbar
630 @ interp alias {} ::ttk::menubutton {} ::menubutton
631 @ }
632 @
633 @ proc dehtml {x} {
634 @ set x [regsub -all {<[^>]*>} $x {}]
635 @ return [string map {&amp; & &lt; < &gt; > &#39; ' &quot; \"} $x]
636 @ }
637 @
638 @ proc cols {} {
639 @ return [list .lnA .txtA .mkr .lnB .txtB]
640 @ }
641 @
642 @ proc colType {c} {
643 @ regexp {[a-z]+} $c type
644 @ return $type
645 @ }
646 @
647 @ proc readDiffs {fossilcmd} {
648 @ set in [open $fossilcmd r]
649 @ fconfigure $in -encoding utf-8
650 @ set nDiffs 0
651 @ array set widths {txt 0 ln 0 mkr 0}
@@ -657,34 +657,34 @@
657 @ continue
658 @ }
659 @ incr nDiffs
660 @ set idx [expr {$nDiffs > 1 ? [.txtA index end] : "1.0"}]
661 @ .wfiles.lb insert end $fn
662 @
663 @ foreach c [cols] {
664 @ while {[gets $in] ne "<pre>"} continue
665 @
666 @ if {$nDiffs > 1} {
667 @ $c insert end \n -
668 @ }
669 @ if {[colType $c] eq "txt"} {
670 @ $c insert end $fn\n fn
671 @ } else {
672 @ $c insert end \n fn
673 @ }
674 @ $c insert end \n -
675 @
676 @ set type [colType $c]
677 @ set str {}
678 @ while {[set line [gets $in]] ne "</pre>"} {
679 @ set len [string length [dehtml $line]]
680 @ if {$len > $widths($type)} {
681 @ set widths($type) $len
682 @ }
683 @ append str $line\n
684 @ }
685 @
686 @ set re {<span class="diff([a-z]+)">([^<]*)</span>}
687 @ # Use \r as separator since it can't appear in the diff output (it gets
688 @ # converted to a space).
689 @ set str [regsub -all $re $str "\r\\1\r\\2\r"]
690 @ foreach {pre class mid} [split $str \r] {
@@ -695,11 +695,11 @@
695 @ }
696 @ }
697 @ }
698 @ }
699 @ close $in
700 @
701 @ foreach c [cols] {
702 @ set type [colType $c]
703 @ if {$type ne "txt"} {
704 @ $c config -width $widths($type)
705 @ }
@@ -707,19 +707,19 @@
707 @ }
708 @ if {$nDiffs <= [.wfiles.lb cget -height]} {
709 @ .wfiles.lb config -height $nDiffs
710 @ grid remove .wfiles.sb
711 @ }
712 @
713 @ return $nDiffs
714 @ }
715 @
716 @ proc viewDiff {idx} {
717 @ .txtA yview $idx
718 @ .txtA xview moveto 0
719 @ }
720 @
721 @ proc cycleDiffs {{reverse 0}} {
722 @ if {$reverse} {
723 @ set range [.txtA tag prevrange fn @0,0 1.0]
724 @ if {$range eq ""} {
725 @ viewDiff {fn.last -1c}
@@ -733,36 +733,36 @@
733 @ } else {
734 @ viewDiff [lindex $range 0]
735 @ }
736 @ }
737 @ }
738 @
739 @ proc xvis {col} {
740 @ set view [$col xview]
741 @ return [expr {[lindex $view 1]-[lindex $view 0]}]
742 @ }
743 @
744 @ proc scroll-x {args} {
745 @ set c .txt[expr {[xvis .txtA] < [xvis .txtB] ? "A" : "B"}]
746 @ eval $c xview $args
747 @ }
748 @
749 @ interp alias {} scroll-y {} .txtA yview
750 @
751 @ proc noop {args} {}
752 @
753 @ proc enableSync {axis} {
754 @ update idletasks
755 @ interp alias {} sync-$axis {}
756 @ rename _sync-$axis sync-$axis
757 @ }
758 @
759 @ proc disableSync {axis} {
760 @ rename sync-$axis _sync-$axis
761 @ interp alias {} sync-$axis {} noop
762 @ }
763 @
764 @ proc sync-x {col first last} {
765 @ disableSync x
766 @ $col xview moveto [expr {$first*[xvis $col]/($last-$first)}]
767 @ foreach side {A B} {
768 @ set sb .sbx$side
@@ -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 @ }
@@ -788,15 +788,16 @@
788 @ } else {
789 @ grid remove .sby
790 @ }
791 @ enableSync y
792 @ }
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>
@@ -813,11 +814,11 @@
813 @ End y {moveto 1}
814 @ } {
815 @ bind . <$key> "scroll-$axis $args; break"
816 @ bind . <Shift-$key> continue
817 @ }
818 @
819 @ ::ttk::menubutton .files -text "Files"
820 @ toplevel .wfiles
821 @ wm withdraw .wfiles
822 @ update idletasks
823 @ wm transient .wfiles .
@@ -847,16 +848,16 @@
847 @ }
848 @ bind .wfiles.lb <Motion> {
849 @ %W selection clear 0 end
850 @ %W selection set @%x,%y
851 @ }
852 @
853 @ foreach {side syncCol} {A .txtB B .txtA} {
854 @ set ln .ln$side
855 @ text $ln
856 @ $ln tag config - -justify right
857 @
858 @ set txt .txt$side
859 @ text $txt -width $CFG(WIDTH) -height $CFG(HEIGHT) -wrap none \
860 @ -xscroll "sync-x $syncCol"
861 @ catch {$txt config -tabstyle wordprocessor} ;# Required for Tk>=8.5
862 @ foreach tag {add rm chng} {
@@ -865,11 +866,11 @@
865 @ }
866 @ $txt tag config fn -background $CFG(FN_BG) -foreground $CFG(FN_FG) \
867 @ -justify center
868 @ }
869 @ text .mkr
870 @
871 @ foreach c [cols] {
872 @ set keyPrefix [string toupper [colType $c]]_COL_
873 @ if {[tk windowingsystem] eq "win32"} {$c config -font {courier 9}}
874 @ $c config -bg $CFG(${keyPrefix}BG) -fg $CFG(${keyPrefix}FG) -borderwidth 0 \
875 @ -padx $CFG(PADX) -yscroll sync-y
@@ -877,22 +878,22 @@
877 @ -foreground $CFG(HR_FG)
878 @ $c tag config fn -spacing1 $CFG(FN_PAD) -spacing3 $CFG(FN_PAD)
879 @ bindtags $c ". $c Text all"
880 @ bind $c <1> {focus %W}
881 @ }
882 @
883 @ ::ttk::scrollbar .sby -command {.txtA yview} -orient vertical
884 @ ::ttk::scrollbar .sbxA -command {.txtA xview} -orient horizontal
885 @ ::ttk::scrollbar .sbxB -command {.txtB xview} -orient horizontal
886 @ frame .spacer
887 @
888 @ if {[readDiffs $fossilcmd] == 0} {
889 @ tk_messageBox -type ok -title $CFG(TITLE) -message "No changes"
890 @ exit
891 @ }
892 @ update idletasks
893 @
894 @ grid rowconfigure . 1 -weight 1
895 @ grid columnconfigure . 1 -weight 1
896 @ grid columnconfigure . 4 -weight 1
897 @ grid .files -row 0 -columnspan 6
898 @ eval grid [cols] -row 1 -sticky nsew
@@ -906,14 +907,16 @@
906 ;
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);
@@ -988,11 +1005,11 @@
988 ** specified (as they exist on disk) and that same file as it was checked
989 ** out. Or if the FILE arguments are omitted, show the unsaved changed
990 ** currently in the working check-out.
991 **
992 ** If the "--from VERSION" or "-r VERSION" option is used it specifies
993 ** the source check-in for the diff operation. If not specified, the
994 ** source check-in is the base check-in for the current check-out.
995 **
996 ** If the "--to VERSION" option appears, it specifies the check-in from
997 ** which the second version of the file or files is taken. If there is
998 ** no "--to" option then the (possibly edited) files in the current check-out
@@ -1015,11 +1032,11 @@
1015 **
1016 ** Options:
1017 ** --binary PATTERN Treat files that match the glob PATTERN as binary
1018 ** --branch BRANCH Show diff of all changes on BRANCH
1019 ** --brief Show filenames only
1020 ** --context|-c N Use N lines of context
1021 ** --diff-binary BOOL Include binary files when using external commands
1022 ** --from|-r VERSION select VERSION as source for the diff
1023 ** --internal|-i use internal diff logic
1024 ** --side-by-side|-y side-by-side diff
1025 ** --tk Launch a Tcl/Tk GUI for display
1026
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -599,11 +599,11 @@
599
600 /* A Tcl/Tk script used to render diff output.
601 */
602 static const char zDiffScript[] =
603 @ package require Tk
604 @
605 @ array set CFG {
606 @ TITLE {Fossil Diff}
607 @ LN_COL_BG #dddddd
608 @ LN_COL_FG #444444
609 @ TXT_COL_BG #ffffff
@@ -622,30 +622,30 @@
622 @ PADX 5
623 @ WIDTH 80
624 @ HEIGHT 45
625 @ LB_HEIGHT 25
626 @ }
627 @
628 @ if {![namespace exists ttk]} {
629 @ interp alias {} ::ttk::scrollbar {} ::scrollbar
630 @ interp alias {} ::ttk::menubutton {} ::menubutton
631 @ }
632 @
633 @ proc dehtml {x} {
634 @ set x [regsub -all {<[^>]*>} $x {}]
635 @ return [string map {&amp; & &lt; < &gt; > &#39; ' &quot; \"} $x]
636 @ }
637 @
638 @ proc cols {} {
639 @ return [list .lnA .txtA .mkr .lnB .txtB]
640 @ }
641 @
642 @ proc colType {c} {
643 @ regexp {[a-z]+} $c type
644 @ return $type
645 @ }
646 @
647 @ proc readDiffs {fossilcmd} {
648 @ set in [open $fossilcmd r]
649 @ fconfigure $in -encoding utf-8
650 @ set nDiffs 0
651 @ array set widths {txt 0 ln 0 mkr 0}
@@ -657,34 +657,34 @@
657 @ continue
658 @ }
659 @ incr nDiffs
660 @ set idx [expr {$nDiffs > 1 ? [.txtA index end] : "1.0"}]
661 @ .wfiles.lb insert end $fn
662 @
663 @ foreach c [cols] {
664 @ while {[gets $in] ne "<pre>"} continue
665 @
666 @ if {$nDiffs > 1} {
667 @ $c insert end \n -
668 @ }
669 @ if {[colType $c] eq "txt"} {
670 @ $c insert end $fn\n fn
671 @ } else {
672 @ $c insert end \n fn
673 @ }
674 @ $c insert end \n -
675 @
676 @ set type [colType $c]
677 @ set str {}
678 @ while {[set line [gets $in]] ne "</pre>"} {
679 @ set len [string length [dehtml $line]]
680 @ if {$len > $widths($type)} {
681 @ set widths($type) $len
682 @ }
683 @ append str $line\n
684 @ }
685 @
686 @ set re {<span class="diff([a-z]+)">([^<]*)</span>}
687 @ # Use \r as separator since it can't appear in the diff output (it gets
688 @ # converted to a space).
689 @ set str [regsub -all $re $str "\r\\1\r\\2\r"]
690 @ foreach {pre class mid} [split $str \r] {
@@ -695,11 +695,11 @@
695 @ }
696 @ }
697 @ }
698 @ }
699 @ close $in
700 @
701 @ foreach c [cols] {
702 @ set type [colType $c]
703 @ if {$type ne "txt"} {
704 @ $c config -width $widths($type)
705 @ }
@@ -707,19 +707,19 @@
707 @ }
708 @ if {$nDiffs <= [.wfiles.lb cget -height]} {
709 @ .wfiles.lb config -height $nDiffs
710 @ grid remove .wfiles.sb
711 @ }
712 @
713 @ return $nDiffs
714 @ }
715 @
716 @ proc viewDiff {idx} {
717 @ .txtA yview $idx
718 @ .txtA xview moveto 0
719 @ }
720 @
721 @ proc cycleDiffs {{reverse 0}} {
722 @ if {$reverse} {
723 @ set range [.txtA tag prevrange fn @0,0 1.0]
724 @ if {$range eq ""} {
725 @ viewDiff {fn.last -1c}
@@ -733,36 +733,36 @@
733 @ } else {
734 @ viewDiff [lindex $range 0]
735 @ }
736 @ }
737 @ }
738 @
739 @ proc xvis {col} {
740 @ set view [$col xview]
741 @ return [expr {[lindex $view 1]-[lindex $view 0]}]
742 @ }
743 @
744 @ proc scroll-x {args} {
745 @ set c .txt[expr {[xvis .txtA] < [xvis .txtB] ? "A" : "B"}]
746 @ eval $c xview $args
747 @ }
748 @
749 @ interp alias {} scroll-y {} .txtA yview
750 @
751 @ proc noop {args} {}
752 @
753 @ proc enableSync {axis} {
754 @ update idletasks
755 @ interp alias {} sync-$axis {}
756 @ rename _sync-$axis sync-$axis
757 @ }
758 @
759 @ proc disableSync {axis} {
760 @ rename sync-$axis _sync-$axis
761 @ interp alias {} sync-$axis {} noop
762 @ }
763 @
764 @ proc sync-x {col first last} {
765 @ disableSync x
766 @ $col xview moveto [expr {$first*[xvis $col]/($last-$first)}]
767 @ foreach side {A B} {
768 @ set sb .sbx$side
@@ -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 @ }
@@ -788,15 +788,16 @@
788 @ } else {
789 @ grid remove .sby
790 @ }
791 @ enableSync y
792 @ }
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>
@@ -813,11 +814,11 @@
814 @ End y {moveto 1}
815 @ } {
816 @ bind . <$key> "scroll-$axis $args; break"
817 @ bind . <Shift-$key> continue
818 @ }
819 @
820 @ ::ttk::menubutton .files -text "Files"
821 @ toplevel .wfiles
822 @ wm withdraw .wfiles
823 @ update idletasks
824 @ wm transient .wfiles .
@@ -847,16 +848,16 @@
848 @ }
849 @ bind .wfiles.lb <Motion> {
850 @ %W selection clear 0 end
851 @ %W selection set @%x,%y
852 @ }
853 @
854 @ foreach {side syncCol} {A .txtB B .txtA} {
855 @ set ln .ln$side
856 @ text $ln
857 @ $ln tag config - -justify right
858 @
859 @ set txt .txt$side
860 @ text $txt -width $CFG(WIDTH) -height $CFG(HEIGHT) -wrap none \
861 @ -xscroll "sync-x $syncCol"
862 @ catch {$txt config -tabstyle wordprocessor} ;# Required for Tk>=8.5
863 @ foreach tag {add rm chng} {
@@ -865,11 +866,11 @@
866 @ }
867 @ $txt tag config fn -background $CFG(FN_BG) -foreground $CFG(FN_FG) \
868 @ -justify center
869 @ }
870 @ text .mkr
871 @
872 @ foreach c [cols] {
873 @ set keyPrefix [string toupper [colType $c]]_COL_
874 @ if {[tk windowingsystem] eq "win32"} {$c config -font {courier 9}}
875 @ $c config -bg $CFG(${keyPrefix}BG) -fg $CFG(${keyPrefix}FG) -borderwidth 0 \
876 @ -padx $CFG(PADX) -yscroll sync-y
@@ -877,22 +878,22 @@
878 @ -foreground $CFG(HR_FG)
879 @ $c tag config fn -spacing1 $CFG(FN_PAD) -spacing3 $CFG(FN_PAD)
880 @ bindtags $c ". $c Text all"
881 @ bind $c <1> {focus %W}
882 @ }
883 @
884 @ ::ttk::scrollbar .sby -command {.txtA yview} -orient vertical
885 @ ::ttk::scrollbar .sbxA -command {.txtA xview} -orient horizontal
886 @ ::ttk::scrollbar .sbxB -command {.txtB xview} -orient horizontal
887 @ frame .spacer
888 @
889 @ if {[readDiffs $fossilcmd] == 0} {
890 @ tk_messageBox -type ok -title $CFG(TITLE) -message "No changes"
891 @ exit
892 @ }
893 @ update idletasks
894 @
895 @ grid rowconfigure . 1 -weight 1
896 @ grid columnconfigure . 1 -weight 1
897 @ grid columnconfigure . 4 -weight 1
898 @ grid .files -row 0 -columnspan 6
899 @ eval grid [cols] -row 1 -sticky nsew
@@ -906,14 +907,16 @@
907 ;
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);
@@ -988,11 +1005,11 @@
1005 ** specified (as they exist on disk) and that same file as it was checked
1006 ** out. Or if the FILE arguments are omitted, show the unsaved changed
1007 ** currently in the working check-out.
1008 **
1009 ** If the "--from VERSION" or "-r VERSION" option is used it specifies
1010 ** the source check-in for the diff operation. If not specified, the
1011 ** source check-in is the base check-in for the current check-out.
1012 **
1013 ** If the "--to VERSION" option appears, it specifies the check-in from
1014 ** which the second version of the file or files is taken. If there is
1015 ** no "--to" option then the (possibly edited) files in the current check-out
@@ -1015,11 +1032,11 @@
1032 **
1033 ** Options:
1034 ** --binary PATTERN Treat files that match the glob PATTERN as binary
1035 ** --branch BRANCH Show diff of all changes on BRANCH
1036 ** --brief Show filenames only
1037 ** --context|-c N Use N lines of context
1038 ** --diff-binary BOOL Include binary files when using external commands
1039 ** --from|-r VERSION select VERSION as source for the diff
1040 ** --internal|-i use internal diff logic
1041 ** --side-by-side|-y side-by-side diff
1042 ** --tk Launch a Tcl/Tk GUI for display
1043
+1 -1
--- src/file.c
+++ src/file.c
@@ -996,11 +996,11 @@
996996
}else{
997997
xCmp = fossil_strnicmp;
998998
}
999999
10001000
/* Special case. zOrigName refers to g.zLocalRoot directory. */
1001
- if( (nFull==nLocalRoot-1 && xCmp(zLocalRoot, zFull, nFull)==0)
1001
+ if( (nFull==nLocalRoot-1 && xCmp(zLocalRoot, zFull, nFull)==0)
10021002
|| (nFull==1 && zFull[0]=='/' && nLocalRoot==1 && zLocalRoot[0]=='/') ){
10031003
blob_append(pOut, ".", 1);
10041004
blob_reset(&localRoot);
10051005
blob_reset(&full);
10061006
return 1;
10071007
--- src/file.c
+++ src/file.c
@@ -996,11 +996,11 @@
996 }else{
997 xCmp = fossil_strnicmp;
998 }
999
1000 /* Special case. zOrigName refers to g.zLocalRoot directory. */
1001 if( (nFull==nLocalRoot-1 && xCmp(zLocalRoot, zFull, nFull)==0)
1002 || (nFull==1 && zFull[0]=='/' && nLocalRoot==1 && zLocalRoot[0]=='/') ){
1003 blob_append(pOut, ".", 1);
1004 blob_reset(&localRoot);
1005 blob_reset(&full);
1006 return 1;
1007
--- src/file.c
+++ src/file.c
@@ -996,11 +996,11 @@
996 }else{
997 xCmp = fossil_strnicmp;
998 }
999
1000 /* Special case. zOrigName refers to g.zLocalRoot directory. */
1001 if( (nFull==nLocalRoot-1 && xCmp(zLocalRoot, zFull, nFull)==0)
1002 || (nFull==1 && zFull[0]=='/' && nLocalRoot==1 && zLocalRoot[0]=='/') ){
1003 blob_append(pOut, ".", 1);
1004 blob_reset(&localRoot);
1005 blob_reset(&full);
1006 return 1;
1007
+1 -1
--- src/finfo.c
+++ src/finfo.c
@@ -322,11 +322,11 @@
322322
);
323323
if( firstChngOnly ){
324324
#if 0
325325
blob_appendf(&sql, ", min(event.mtime)");
326326
#else
327
- blob_appendf(&sql,
327
+ blob_appendf(&sql,
328328
", min(CASE (SELECT value FROM tagxref"
329329
" WHERE tagtype>0 AND tagid=%d"
330330
" AND tagxref.rid=mlink.mid)"
331331
" WHEN 'trunk' THEN event.mtime-10000 ELSE event.mtime END)",
332332
TAG_BRANCH);
333333
--- src/finfo.c
+++ src/finfo.c
@@ -322,11 +322,11 @@
322 );
323 if( firstChngOnly ){
324 #if 0
325 blob_appendf(&sql, ", min(event.mtime)");
326 #else
327 blob_appendf(&sql,
328 ", min(CASE (SELECT value FROM tagxref"
329 " WHERE tagtype>0 AND tagid=%d"
330 " AND tagxref.rid=mlink.mid)"
331 " WHEN 'trunk' THEN event.mtime-10000 ELSE event.mtime END)",
332 TAG_BRANCH);
333
--- src/finfo.c
+++ src/finfo.c
@@ -322,11 +322,11 @@
322 );
323 if( firstChngOnly ){
324 #if 0
325 blob_appendf(&sql, ", min(event.mtime)");
326 #else
327 blob_appendf(&sql,
328 ", min(CASE (SELECT value FROM tagxref"
329 " WHERE tagtype>0 AND tagid=%d"
330 " AND tagxref.rid=mlink.mid)"
331 " WHEN 'trunk' THEN event.mtime-10000 ELSE event.mtime END)",
332 TAG_BRANCH);
333
+1 -1
--- src/gzip.c
+++ src/gzip.c
@@ -73,11 +73,11 @@
7373
*/
7474
#define GZIP_BUFSZ 100000
7575
void gzip_step(const char *pIn, int nIn){
7676
char *zOutBuf;
7777
int nOut;
78
-
78
+
7979
nOut = nIn + nIn/10 + 100;
8080
if( nOut<100000 ) nOut = 100000;
8181
zOutBuf = fossil_malloc(nOut);
8282
gzip.stream.avail_in = nIn;
8383
gzip.stream.next_in = (unsigned char*)pIn;
8484
--- src/gzip.c
+++ src/gzip.c
@@ -73,11 +73,11 @@
73 */
74 #define GZIP_BUFSZ 100000
75 void gzip_step(const char *pIn, int nIn){
76 char *zOutBuf;
77 int nOut;
78
79 nOut = nIn + nIn/10 + 100;
80 if( nOut<100000 ) nOut = 100000;
81 zOutBuf = fossil_malloc(nOut);
82 gzip.stream.avail_in = nIn;
83 gzip.stream.next_in = (unsigned char*)pIn;
84
--- src/gzip.c
+++ src/gzip.c
@@ -73,11 +73,11 @@
73 */
74 #define GZIP_BUFSZ 100000
75 void gzip_step(const char *pIn, int nIn){
76 char *zOutBuf;
77 int nOut;
78
79 nOut = nIn + nIn/10 + 100;
80 if( nOut<100000 ) nOut = 100000;
81 zOutBuf = fossil_malloc(nOut);
82 gzip.stream.avail_in = nIn;
83 gzip.stream.next_in = (unsigned char*)pIn;
84
+100 -26
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -173,17 +173,65 @@
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
181
-** by global variables that are set using url_parse():
229
+** by variables that are set using url_parse():
182230
**
183
-** g.urlName Name of the server. Ex: www.fossil-scm.org
184
-** g.urlPort TCP/IP port to use. Ex: 80
231
+** pUrlData->name Name of the server. Ex: www.fossil-scm.org
232
+** pUrlData->port TCP/IP port to use. Ex: 80
185233
**
186234
** Return the number of errors.
187235
*/
188236
int ssl_open(UrlData *pUrlData){
189237
X509 *cert;
@@ -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,17 +173,65 @@
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 global variables that are set using url_parse():
182 **
183 ** g.urlName Name of the server. Ex: www.fossil-scm.org
184 ** g.urlPort TCP/IP port to use. Ex: 80
185 **
186 ** Return the number of errors.
187 */
188 int ssl_open(UrlData *pUrlData){
189 X509 *cert;
@@ -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,17 +173,65 @@
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 **
231 ** pUrlData->name Name of the server. Ex: www.fossil-scm.org
232 ** pUrlData->port TCP/IP port to use. Ex: 80
233 **
234 ** Return the number of errors.
235 */
236 int ssl_open(UrlData *pUrlData){
237 X509 *cert;
@@ -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
+67 -26
--- src/info.c
+++ src/info.c
@@ -108,10 +108,26 @@
108108
);
109109
fossil_print("%-13s %s %s\n", zType, zUuid, zDate);
110110
free(zDate);
111111
}
112112
db_finalize(&q);
113
+ }
114
+ if( zUuid ){
115
+ fossil_print("%-13s ", "leaf:");
116
+ if(is_a_leaf(rid)){
117
+ if(db_int(0, "SELECT 1 FROM tagxref AS tx"
118
+ " WHERE tx.rid=%d"
119
+ " AND tx.tagid=%d"
120
+ " AND tx.tagtype>0",
121
+ rid, TAG_CLOSED)){
122
+ fossil_print("%s\n", "closed");
123
+ }else{
124
+ fossil_print("%s\n", "open");
125
+ }
126
+ }else{
127
+ fossil_print("no\n");
128
+ }
113129
}
114130
zTags = info_tags_of_checkin(rid, 0);
115131
if( zTags && zTags[0] ){
116132
fossil_print("tags: %s\n", zTags);
117133
}
@@ -917,15 +933,16 @@
917933
** WEBPAGE: vdiff
918934
** URL: /vdiff
919935
**
920936
** Query parameters:
921937
**
922
-** from=TAG
923
-** to=TAG
924
-** branch=TAG
925
-** v=BOOLEAN
926
-** sbs=BOOLEAN
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
927944
**
928945
**
929946
** Show all differences between two checkins.
930947
*/
931948
void vdiff_page(void){
@@ -938,16 +955,15 @@
938955
const char *zBranch;
939956
const char *zFrom;
940957
const char *zTo;
941958
const char *zRe;
942959
const char *zVerbose;
960
+ const char *zGlob;
943961
ReCompiled *pRe = 0;
944
-
945962
login_check_credentials();
946963
if( !g.perm.Read ){ login_needed(); return; }
947964
login_anonymous_available();
948
-
949965
zRe = P("regex");
950966
if( zRe ) re_compile(&pRe, zRe, 0);
951967
zBranch = P("branch");
952968
if( zBranch && zBranch[0] ){
953969
cgi_replace_parameter("from", mprintf("root:%s", zBranch));
@@ -965,30 +981,46 @@
965981
if( !zVerbose ){
966982
zVerbose = P("detail"); /* deprecated */
967983
}
968984
verboseFlag = (zVerbose!=0) && !is_false(zVerbose);
969985
if( !verboseFlag && sideBySide ) verboseFlag = 1;
986
+ zGlob = P("glob");
970987
zFrom = P("from");
971988
zTo = P("to");
989
+ if(zGlob && !*zGlob){
990
+ zGlob = NULL;
991
+ }
972992
if( sideBySide || verboseFlag ){
973993
style_submenu_element("Hide Diff", "hidediff",
974
- "%R/vdiff?from=%T&to=%T&sbs=0",
975
- zFrom, zTo);
994
+ "%R/vdiff?from=%T&to=%T&sbs=0%s%T",
995
+ zFrom, zTo,
996
+ zGlob ? "&glob=" : "", zGlob ? zGlob : "");
976997
}
977998
if( !sideBySide ){
978999
style_submenu_element("Side-by-side Diff", "sbsdiff",
979
- "%R/vdiff?from=%T&to=%T&sbs=1",
980
- zFrom, zTo);
1000
+ "%R/vdiff?from=%T&to=%T&sbs=1%s%T",
1001
+ zFrom, zTo,
1002
+ zGlob ? "&glob=" : "", zGlob ? zGlob : "");
9811003
}
9821004
if( sideBySide || !verboseFlag ) {
9831005
style_submenu_element("Unified Diff", "udiff",
984
- "%R/vdiff?from=%T&to=%T&sbs=0&v",
985
- zFrom, zTo);
1006
+ "%R/vdiff?from=%T&to=%T&sbs=0&v%s%T",
1007
+ zFrom, zTo,
1008
+ zGlob ? "&glob=" : "", zGlob ? zGlob : "");
9861009
}
9871010
style_submenu_element("Invert", "invert",
988
- "%R/vdiff?from=%T&to=%T&sbs=%d%s", zTo, zFrom,
989
- sideBySide, (verboseFlag && !sideBySide)?"&v":"");
1011
+ "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T", zTo, zFrom,
1012
+ sideBySide, (verboseFlag && !sideBySide)?"&v":"",
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
+ }
9901022
style_header("Check-in Differences");
9911023
@ <h2>Difference From:</h2><blockquote>
9921024
checkin_description(ridFrom);
9931025
@ </blockquote><h2>To:</h2><blockquote>
9941026
checkin_description(ridTo);
@@ -995,10 +1027,13 @@
9951027
@ </blockquote>
9961028
if( pRe ){
9971029
@ <p><b>Only differences that match regular expression "%h(zRe)"
9981030
@ are shown.</b></p>
9991031
}
1032
+ if( zGlob ){
1033
+ @ <p><b>Only files matching the glob "%h(zGlob)" are shown.</b></p>
1034
+ }
10001035
@<hr /><p>
10011036
10021037
manifest_file_rewind(pFrom);
10031038
pFileFrom = manifest_file_next(pFrom, 0);
10041039
manifest_file_rewind(pTo);
@@ -1012,27 +1047,33 @@
10121047
cmp = -1;
10131048
}else{
10141049
cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
10151050
}
10161051
if( cmp<0 ){
1017
- append_file_change_line(pFileFrom->zName,
1018
- pFileFrom->zUuid, 0, 0, diffFlags, pRe, 0);
1052
+ if(!zGlob || strglob(zGlob, pFileFrom->zName)){
1053
+ append_file_change_line(pFileFrom->zName,
1054
+ pFileFrom->zUuid, 0, 0, diffFlags, pRe, 0);
1055
+ }
10191056
pFileFrom = manifest_file_next(pFrom, 0);
10201057
}else if( cmp>0 ){
1021
- append_file_change_line(pFileTo->zName,
1022
- 0, pFileTo->zUuid, 0, diffFlags, pRe,
1023
- manifest_file_mperm(pFileTo));
1058
+ if(!zGlob || strglob(zGlob, pFileTo->zName)){
1059
+ append_file_change_line(pFileTo->zName,
1060
+ 0, pFileTo->zUuid, 0, diffFlags, pRe,
1061
+ manifest_file_mperm(pFileTo));
1062
+ }
10241063
pFileTo = manifest_file_next(pTo, 0);
10251064
}else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
1026
- /* No changes */
10271065
pFileFrom = manifest_file_next(pFrom, 0);
10281066
pFileTo = manifest_file_next(pTo, 0);
10291067
}else{
1030
- append_file_change_line(pFileFrom->zName,
1031
- pFileFrom->zUuid,
1032
- pFileTo->zUuid, 0, diffFlags, pRe,
1033
- manifest_file_mperm(pFileTo));
1068
+ if(!zGlob || (strglob(zGlob, pFileFrom->zName)
1069
+ || strglob(zGlob, pFileTo->zName))){
1070
+ append_file_change_line(pFileFrom->zName,
1071
+ pFileFrom->zUuid,
1072
+ pFileTo->zUuid, 0, diffFlags, pRe,
1073
+ manifest_file_mperm(pFileTo));
1074
+ }
10341075
pFileFrom = manifest_file_next(pFrom, 0);
10351076
pFileTo = manifest_file_next(pTo, 0);
10361077
}
10371078
}
10381079
manifest_destroy(pFrom);
@@ -2372,11 +2413,11 @@
23722413
@ onkeyup="chgbn(this.value.trim(),'%h(zBranchName)')" /></td></tr>
23732414
if( !fHasHidden ){
23742415
@ <tr><th align="right" valign="top">Branch Hiding:</th>
23752416
@ <td valign="top">
23762417
@ <label><input type="checkbox" id="hidebr" name="hide"%s(zHideFlag) />
2377
- @ Hide branch
2418
+ @ Hide branch
23782419
@ <span style="font-weight:bold" id="hbranch">%h(zBranchName)</span>
23792420
@ from the timeline starting from this check-in</label>
23802421
@ </td></tr>
23812422
}
23822423
if( !fHasClosed ){
23832424
--- src/info.c
+++ src/info.c
@@ -108,10 +108,26 @@
108 );
109 fossil_print("%-13s %s %s\n", zType, zUuid, zDate);
110 free(zDate);
111 }
112 db_finalize(&q);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113 }
114 zTags = info_tags_of_checkin(rid, 0);
115 if( zTags && zTags[0] ){
116 fossil_print("tags: %s\n", zTags);
117 }
@@ -917,15 +933,16 @@
917 ** WEBPAGE: vdiff
918 ** URL: /vdiff
919 **
920 ** Query parameters:
921 **
922 ** from=TAG
923 ** to=TAG
924 ** branch=TAG
925 ** v=BOOLEAN
926 ** sbs=BOOLEAN
 
927 **
928 **
929 ** Show all differences between two checkins.
930 */
931 void vdiff_page(void){
@@ -938,16 +955,15 @@
938 const char *zBranch;
939 const char *zFrom;
940 const char *zTo;
941 const char *zRe;
942 const char *zVerbose;
 
943 ReCompiled *pRe = 0;
944
945 login_check_credentials();
946 if( !g.perm.Read ){ login_needed(); return; }
947 login_anonymous_available();
948
949 zRe = P("regex");
950 if( zRe ) re_compile(&pRe, zRe, 0);
951 zBranch = P("branch");
952 if( zBranch && zBranch[0] ){
953 cgi_replace_parameter("from", mprintf("root:%s", zBranch));
@@ -965,30 +981,46 @@
965 if( !zVerbose ){
966 zVerbose = P("detail"); /* deprecated */
967 }
968 verboseFlag = (zVerbose!=0) && !is_false(zVerbose);
969 if( !verboseFlag && sideBySide ) verboseFlag = 1;
 
970 zFrom = P("from");
971 zTo = P("to");
 
 
 
972 if( sideBySide || verboseFlag ){
973 style_submenu_element("Hide Diff", "hidediff",
974 "%R/vdiff?from=%T&to=%T&sbs=0",
975 zFrom, zTo);
 
976 }
977 if( !sideBySide ){
978 style_submenu_element("Side-by-side Diff", "sbsdiff",
979 "%R/vdiff?from=%T&to=%T&sbs=1",
980 zFrom, zTo);
 
981 }
982 if( sideBySide || !verboseFlag ) {
983 style_submenu_element("Unified Diff", "udiff",
984 "%R/vdiff?from=%T&to=%T&sbs=0&v",
985 zFrom, zTo);
 
986 }
987 style_submenu_element("Invert", "invert",
988 "%R/vdiff?from=%T&to=%T&sbs=%d%s", zTo, zFrom,
989 sideBySide, (verboseFlag && !sideBySide)?"&v":"");
 
 
 
 
 
 
 
 
 
990 style_header("Check-in Differences");
991 @ <h2>Difference From:</h2><blockquote>
992 checkin_description(ridFrom);
993 @ </blockquote><h2>To:</h2><blockquote>
994 checkin_description(ridTo);
@@ -995,10 +1027,13 @@
995 @ </blockquote>
996 if( pRe ){
997 @ <p><b>Only differences that match regular expression "%h(zRe)"
998 @ are shown.</b></p>
999 }
 
 
 
1000 @<hr /><p>
1001
1002 manifest_file_rewind(pFrom);
1003 pFileFrom = manifest_file_next(pFrom, 0);
1004 manifest_file_rewind(pTo);
@@ -1012,27 +1047,33 @@
1012 cmp = -1;
1013 }else{
1014 cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
1015 }
1016 if( cmp<0 ){
1017 append_file_change_line(pFileFrom->zName,
1018 pFileFrom->zUuid, 0, 0, diffFlags, pRe, 0);
 
 
1019 pFileFrom = manifest_file_next(pFrom, 0);
1020 }else if( cmp>0 ){
1021 append_file_change_line(pFileTo->zName,
1022 0, pFileTo->zUuid, 0, diffFlags, pRe,
1023 manifest_file_mperm(pFileTo));
 
 
1024 pFileTo = manifest_file_next(pTo, 0);
1025 }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
1026 /* No changes */
1027 pFileFrom = manifest_file_next(pFrom, 0);
1028 pFileTo = manifest_file_next(pTo, 0);
1029 }else{
1030 append_file_change_line(pFileFrom->zName,
1031 pFileFrom->zUuid,
1032 pFileTo->zUuid, 0, diffFlags, pRe,
1033 manifest_file_mperm(pFileTo));
 
 
 
1034 pFileFrom = manifest_file_next(pFrom, 0);
1035 pFileTo = manifest_file_next(pTo, 0);
1036 }
1037 }
1038 manifest_destroy(pFrom);
@@ -2372,11 +2413,11 @@
2372 @ onkeyup="chgbn(this.value.trim(),'%h(zBranchName)')" /></td></tr>
2373 if( !fHasHidden ){
2374 @ <tr><th align="right" valign="top">Branch Hiding:</th>
2375 @ <td valign="top">
2376 @ <label><input type="checkbox" id="hidebr" name="hide"%s(zHideFlag) />
2377 @ Hide branch
2378 @ <span style="font-weight:bold" id="hbranch">%h(zBranchName)</span>
2379 @ from the timeline starting from this check-in</label>
2380 @ </td></tr>
2381 }
2382 if( !fHasClosed ){
2383
--- src/info.c
+++ src/info.c
@@ -108,10 +108,26 @@
108 );
109 fossil_print("%-13s %s %s\n", zType, zUuid, zDate);
110 free(zDate);
111 }
112 db_finalize(&q);
113 }
114 if( zUuid ){
115 fossil_print("%-13s ", "leaf:");
116 if(is_a_leaf(rid)){
117 if(db_int(0, "SELECT 1 FROM tagxref AS tx"
118 " WHERE tx.rid=%d"
119 " AND tx.tagid=%d"
120 " AND tx.tagtype>0",
121 rid, TAG_CLOSED)){
122 fossil_print("%s\n", "closed");
123 }else{
124 fossil_print("%s\n", "open");
125 }
126 }else{
127 fossil_print("no\n");
128 }
129 }
130 zTags = info_tags_of_checkin(rid, 0);
131 if( zTags && zTags[0] ){
132 fossil_print("tags: %s\n", zTags);
133 }
@@ -917,15 +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){
@@ -938,16 +955,15 @@
955 const char *zBranch;
956 const char *zFrom;
957 const char *zTo;
958 const char *zRe;
959 const char *zVerbose;
960 const char *zGlob;
961 ReCompiled *pRe = 0;
 
962 login_check_credentials();
963 if( !g.perm.Read ){ login_needed(); return; }
964 login_anonymous_available();
 
965 zRe = P("regex");
966 if( zRe ) re_compile(&pRe, zRe, 0);
967 zBranch = P("branch");
968 if( zBranch && zBranch[0] ){
969 cgi_replace_parameter("from", mprintf("root:%s", zBranch));
@@ -965,30 +981,46 @@
981 if( !zVerbose ){
982 zVerbose = P("detail"); /* deprecated */
983 }
984 verboseFlag = (zVerbose!=0) && !is_false(zVerbose);
985 if( !verboseFlag && sideBySide ) verboseFlag = 1;
986 zGlob = P("glob");
987 zFrom = P("from");
988 zTo = P("to");
989 if(zGlob && !*zGlob){
990 zGlob = NULL;
991 }
992 if( sideBySide || verboseFlag ){
993 style_submenu_element("Hide Diff", "hidediff",
994 "%R/vdiff?from=%T&to=%T&sbs=0%s%T",
995 zFrom, zTo,
996 zGlob ? "&glob=" : "", zGlob ? zGlob : "");
997 }
998 if( !sideBySide ){
999 style_submenu_element("Side-by-side Diff", "sbsdiff",
1000 "%R/vdiff?from=%T&to=%T&sbs=1%s%T",
1001 zFrom, zTo,
1002 zGlob ? "&glob=" : "", zGlob ? zGlob : "");
1003 }
1004 if( sideBySide || !verboseFlag ) {
1005 style_submenu_element("Unified Diff", "udiff",
1006 "%R/vdiff?from=%T&to=%T&sbs=0&v%s%T",
1007 zFrom, zTo,
1008 zGlob ? "&glob=" : "", zGlob ? zGlob : "");
1009 }
1010 style_submenu_element("Invert", "invert",
1011 "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T", zTo, zFrom,
1012 sideBySide, (verboseFlag && !sideBySide)?"&v":"",
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 checkin_description(ridTo);
@@ -995,10 +1027,13 @@
1027 @ </blockquote>
1028 if( pRe ){
1029 @ <p><b>Only differences that match regular expression "%h(zRe)"
1030 @ are shown.</b></p>
1031 }
1032 if( zGlob ){
1033 @ <p><b>Only files matching the glob "%h(zGlob)" are shown.</b></p>
1034 }
1035 @<hr /><p>
1036
1037 manifest_file_rewind(pFrom);
1038 pFileFrom = manifest_file_next(pFrom, 0);
1039 manifest_file_rewind(pTo);
@@ -1012,27 +1047,33 @@
1047 cmp = -1;
1048 }else{
1049 cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
1050 }
1051 if( cmp<0 ){
1052 if(!zGlob || strglob(zGlob, pFileFrom->zName)){
1053 append_file_change_line(pFileFrom->zName,
1054 pFileFrom->zUuid, 0, 0, diffFlags, pRe, 0);
1055 }
1056 pFileFrom = manifest_file_next(pFrom, 0);
1057 }else if( cmp>0 ){
1058 if(!zGlob || strglob(zGlob, pFileTo->zName)){
1059 append_file_change_line(pFileTo->zName,
1060 0, pFileTo->zUuid, 0, diffFlags, pRe,
1061 manifest_file_mperm(pFileTo));
1062 }
1063 pFileTo = manifest_file_next(pTo, 0);
1064 }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
 
1065 pFileFrom = manifest_file_next(pFrom, 0);
1066 pFileTo = manifest_file_next(pTo, 0);
1067 }else{
1068 if(!zGlob || (strglob(zGlob, pFileFrom->zName)
1069 || strglob(zGlob, pFileTo->zName))){
1070 append_file_change_line(pFileFrom->zName,
1071 pFileFrom->zUuid,
1072 pFileTo->zUuid, 0, diffFlags, pRe,
1073 manifest_file_mperm(pFileTo));
1074 }
1075 pFileFrom = manifest_file_next(pFrom, 0);
1076 pFileTo = manifest_file_next(pTo, 0);
1077 }
1078 }
1079 manifest_destroy(pFrom);
@@ -2372,11 +2413,11 @@
2413 @ onkeyup="chgbn(this.value.trim(),'%h(zBranchName)')" /></td></tr>
2414 if( !fHasHidden ){
2415 @ <tr><th align="right" valign="top">Branch Hiding:</th>
2416 @ <td valign="top">
2417 @ <label><input type="checkbox" id="hidebr" name="hide"%s(zHideFlag) />
2418 @ Hide branch
2419 @ <span style="font-weight:bold" id="hbranch">%h(zBranchName)</span>
2420 @ from the timeline starting from this check-in</label>
2421 @ </td></tr>
2422 }
2423 if( !fHasClosed ){
2424
+27 -23
--- src/login.c
+++ src/login.c
@@ -41,11 +41,11 @@
4141
** logs and downloading diffs of very version of the archive that
4242
** has ever existed, and things like that.
4343
*/
4444
#include "config.h"
4545
#include "login.h"
46
-#if defined(_WIN32)
46
+#if defined(_WIN32)
4747
# include <windows.h> /* for Sleep */
4848
# if defined(__MINGW32__) || defined(_MSC_VER)
4949
# define sleep Sleep /* windows does not have sleep, but Sleep */
5050
# endif
5151
#endif
@@ -112,13 +112,13 @@
112112
}
113113
}
114114
115115
/*
116116
** The IP address of the client is stored as part of login cookies.
117
-** But some clients are behind firewalls that shift the IP address
118
-** with each HTTP request. To allow such (broken) clients to log in,
119
-** extract just a prefix of the IP address.
117
+** But some clients are behind firewalls that shift the IP address
118
+** with each HTTP request. To allow such (broken) clients to log in,
119
+** extract just a prefix of the IP address.
120120
*/
121121
static char *ipPrefix(const char *zIP){
122122
int i, j;
123123
static int ip_prefix_terms = -1;
124124
if( ip_prefix_terms<0 ){
@@ -344,11 +344,11 @@
344344
*/
345345
void login_clear_login_data(){
346346
if(!g.userUid){
347347
return;
348348
}else{
349
- char const * cookie = login_cookie_name();
349
+ char const * cookie = login_cookie_name();
350350
/* To logout, change the cookie value to an empty string */
351351
cgi_set_cookie(cookie, "",
352352
login_cookie_path(), -86400);
353353
db_multi_exec("UPDATE user SET cookie=NULL, ipaddr=NULL, "
354354
" cexpire=0 WHERE uid=%d"
@@ -472,10 +472,11 @@
472472
int anonFlag;
473473
char *zErrMsg = "";
474474
int uid; /* User id logged in user */
475475
char *zSha1Pw;
476476
const char *zIpAddr; /* IP address of requestor */
477
+ const char *zReferer;
477478
478479
login_check_credentials();
479480
sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0,
480481
constant_time_cmp_function, 0, 0);
481482
zUsername = P("u");
@@ -491,21 +492,21 @@
491492
/* The user requests a password change */
492493
zSha1Pw = sha1_shared_secret(zPasswd, g.zLogin, 0);
493494
if( db_int(1, "SELECT 0 FROM user"
494495
" WHERE uid=%d"
495496
" AND (constant_time_cmp(pw,%Q)=0"
496
- " OR constant_time_cmp(pw,%Q)=0)",
497
+ " OR constant_time_cmp(pw,%Q)=0)",
497498
g.userUid, zSha1Pw, zPasswd) ){
498499
sleep(1);
499
- zErrMsg =
500
+ zErrMsg =
500501
@ <p><span class="loginError">
501502
@ You entered an incorrect old password while attempting to change
502503
@ your password. Your password is unchanged.
503504
@ </span></p>
504505
;
505506
}else if( fossil_strcmp(zNew1,zNew2)!=0 ){
506
- zErrMsg =
507
+ zErrMsg =
507508
@ <p><span class="loginError">
508509
@ The two copies of your new passwords do not match.
509510
@ Your password is unchanged.
510511
@ </span></p>
511512
;
@@ -532,10 +533,11 @@
532533
return;
533534
}
534535
}
535536
}
536537
zIpAddr = PD("REMOTE_ADDR","nil"); /* Complete IP address for logging */
538
+ zReferer = P("HTTP_REFERER");
537539
uid = login_is_valid_anonymous(zUsername, zPasswd, P("cs"));
538540
if( uid>0 ){
539541
login_set_anon_cookie(zIpAddr, NULL);
540542
record_login_attempt("anonymous", zIpAddr, 1);
541543
redirect_to_g();
@@ -544,11 +546,11 @@
544546
/* Attempting to log in as a user other than anonymous.
545547
*/
546548
uid = login_search_uid(zUsername, zPasswd);
547549
if( uid<=0 ){
548550
sleep(1);
549
- zErrMsg =
551
+ zErrMsg =
550552
@ <p><span class="loginError">
551553
@ You entered an unknown user or an incorrect password.
552554
@ </span></p>
553555
;
554556
record_login_attempt(zUsername, zIpAddr, 0);
@@ -570,10 +572,12 @@
570572
@ <p>A login is required for <a href="%h(zGoto)">%h(zGoto)</a>.</p>
571573
}
572574
form_begin(0, "%R/login");
573575
if( zGoto ){
574576
@ <input type="hidden" name="g" value="%h(zGoto)" />
577
+ }else if( zReferer && strncmp(g.zBaseURL, zReferer, strlen(g.zBaseURL))==0 ){
578
+ @ <input type="hidden" name="g" value="%h(zReferer)" />
575579
}
576580
@ <table class="login_out">
577581
@ <tr>
578582
@ <td class="login_out_label">User ID:</td>
579583
if( anonFlag ){
@@ -595,11 +599,11 @@
595599
@ <td></td>
596600
@ <td><input type="submit" name="in" value="Login"
597601
@ onClick="chngAction(this.form)" /></td>
598602
@ </tr>
599603
@ </table>
600
- @ <script type="text/JavaScript">
604
+ @ <script>
601605
@ gebi('u').focus()
602606
@ function chngAction(form){
603607
if( g.sslNotAvailable==0
604608
&& strncmp(g.zBaseURL,"https:",6)!=0
605609
&& db_get_boolean("https-login",0)
@@ -620,11 +624,11 @@
620624
@ your user-id and password at the left and press the
621625
@ "Login" button. Your user name will be stored in a browser cookie.
622626
@ You must configure your web browser to accept cookies in order for
623627
@ the login to take.</p>
624628
if( db_get_boolean("self-register", 0) ){
625
- @ <p>If you do not have an account, you can
629
+ @ <p>If you do not have an account, you can
626630
@ <a href="%s(g.zTop)/register?g=%T(P("G"))">create one</a>.
627631
}
628632
if( zAnonPw ){
629633
unsigned int uSeed = captcha_seed();
630634
char const *zDecoded = captcha_decode(uSeed);
@@ -672,11 +676,11 @@
672676
style_footer();
673677
}
674678
675679
/*
676680
** Attempt to find login credentials for user zLogin on a peer repository
677
-** with project code zCode. Transfer those credentials to the local
681
+** with project code zCode. Transfer those credentials to the local
678682
** repository.
679683
**
680684
** Return true if a transfer was made and false if not.
681685
*/
682686
static int login_transfer_credentials(
@@ -690,11 +694,11 @@
690694
char *zSQL; /* SQL of the query against other repo */
691695
char *zOtherRepo; /* Filename of the other repository */
692696
int rc; /* Result code from SQLite library functions */
693697
int nXfer = 0; /* Number of credentials transferred */
694698
695
- zOtherRepo = db_text(0,
699
+ zOtherRepo = db_text(0,
696700
"SELECT value FROM config WHERE name='peer-repo-%q'",
697701
zCode
698702
);
699703
if( zOtherRepo==0 ) return 0; /* No such peer repository */
700704
@@ -752,11 +756,11 @@
752756
int uid;
753757
if( fossil_strcmp(zLogin, "anonymous")==0 ) return 0;
754758
if( fossil_strcmp(zLogin, "nobody")==0 ) return 0;
755759
if( fossil_strcmp(zLogin, "developer")==0 ) return 0;
756760
if( fossil_strcmp(zLogin, "reader")==0 ) return 0;
757
- uid = db_int(0,
761
+ uid = db_int(0,
758762
"SELECT uid FROM user"
759763
" WHERE login=%Q"
760764
" AND ipaddr=%Q"
761765
" AND cexpire>julianday('now')"
762766
" AND length(cap)>0"
@@ -792,11 +796,11 @@
792796
793797
sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0,
794798
constant_time_cmp_function, 0, 0);
795799
796800
/* If the HTTP connection is coming over 127.0.0.1 and if
797
- ** local login is disabled and if we are using HTTP and not HTTPS,
801
+ ** local login is disabled and if we are using HTTP and not HTTPS,
798802
** then there is no need to check user credentials.
799803
**
800804
** This feature allows the "fossil ui" command to give the user
801805
** full access rights without having to log in.
802806
*/
@@ -847,15 +851,15 @@
847851
** SECRET is the "captcha-secret" value in the repository.
848852
*/
849853
double rTime = atof(zArg);
850854
Blob b;
851855
blob_zero(&b);
852
- blob_appendf(&b, "%s/%s/%s",
856
+ blob_appendf(&b, "%s/%s/%s",
853857
zArg, zRemoteAddr, db_get("captcha-secret",""));
854858
sha1sum_blob(&b, &b);
855859
if( fossil_strcmp(zHash, blob_str(&b))==0 ){
856
- uid = db_int(0,
860
+ uid = db_int(0,
857861
"SELECT uid FROM user WHERE login='anonymous'"
858862
" AND length(cap)>0"
859863
" AND length(pw)>0"
860864
" AND %.17g+0.25>julianday('now')",
861865
rTime
@@ -1002,11 +1006,11 @@
10021006
for(i=0; zCap[i]; i++){
10031007
switch( zCap[i] ){
10041008
case 's': g.perm.Setup = 1; /* Fall thru into Admin */
10051009
case 'a': g.perm.Admin = g.perm.RdTkt = g.perm.WrTkt = g.perm.Zip =
10061010
g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki =
1007
- g.perm.ApndWiki = g.perm.Hyperlink = g.perm.Clone =
1011
+ g.perm.ApndWiki = g.perm.Hyperlink = g.perm.Clone =
10081012
g.perm.NewTkt = g.perm.Password = g.perm.RdAddr =
10091013
g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt =
10101014
g.perm.ModWiki = g.perm.ModTkt = 1;
10111015
/* Fall thru into Read/Write */
10121016
case 'i': g.perm.Read = g.perm.Write = 1; break;
@@ -1025,19 +1029,19 @@
10251029
case 'l': g.perm.ModWiki = 1; break;
10261030
10271031
case 'e': g.perm.RdAddr = 1; break;
10281032
case 'r': g.perm.RdTkt = 1; break;
10291033
case 'n': g.perm.NewTkt = 1; break;
1030
- case 'w': g.perm.WrTkt = g.perm.RdTkt = g.perm.NewTkt =
1034
+ case 'w': g.perm.WrTkt = g.perm.RdTkt = g.perm.NewTkt =
10311035
g.perm.ApndTkt = 1; break;
10321036
case 'c': g.perm.ApndTkt = 1; break;
10331037
case 'q': g.perm.ModTkt = 1; break;
10341038
case 't': g.perm.TktFmt = 1; break;
10351039
case 'b': g.perm.Attach = 1; break;
10361040
case 'x': g.perm.Private = 1; break;
10371041
1038
- /* The "u" privileges is a little different. It recursively
1042
+ /* The "u" privileges is a little different. It recursively
10391043
** inherits all privileges of the user named "reader" */
10401044
case 'u': {
10411045
if( (flags & LOGIN_IGNORE_UV)==0 ){
10421046
const char *zUser;
10431047
zUser = db_text("", "SELECT cap FROM user WHERE login='reader'");
@@ -1044,11 +1048,11 @@
10441048
login_set_capabilities(zUser, flags | LOGIN_IGNORE_UV);
10451049
}
10461050
break;
10471051
}
10481052
1049
- /* The "v" privileges is a little different. It recursively
1053
+ /* The "v" privileges is a little different. It recursively
10501054
** inherits all privileges of the user named "developer" */
10511055
case 'v': {
10521056
if( (flags & LOGIN_IGNORE_UV)==0 ){
10531057
const char *zDev;
10541058
zDev = db_text("", "SELECT cap FROM user WHERE login='developer'");
@@ -1359,11 +1363,11 @@
13591363
if( zPrefix==0 ) zPrefix = "";
13601364
if( zSuffix==0 ) zSuffix = "";
13611365
if( pzErrorMsg ) *pzErrorMsg = 0;
13621366
zSelfCode = abbreviated_project_code(db_get("project-code", "x"));
13631367
blob_zero(&err);
1364
- db_prepare(&q,
1368
+ db_prepare(&q,
13651369
"SELECT name, value FROM config"
13661370
" WHERE name GLOB 'peer-repo-*'"
13671371
" AND name <> 'peer-repo-%q'"
13681372
" ORDER BY +value",
13691373
zSelfCode
@@ -1441,11 +1445,11 @@
14411445
const char *zSelf; /* The ATTACH name of our repository */
14421446
14431447
*pzErrMsg = 0; /* Default to no errors */
14441448
zSelf = db_name("repository");
14451449
1446
- /* Get the full pathname of the other repository */
1450
+ /* Get the full pathname of the other repository */
14471451
file_canonical_name(zRepo, &fullName, 0);
14481452
zRepo = mprintf(blob_str(&fullName));
14491453
blob_reset(&fullName);
14501454
14511455
/* Get the full pathname for our repository. Also the project code
14521456
--- src/login.c
+++ src/login.c
@@ -41,11 +41,11 @@
41 ** logs and downloading diffs of very version of the archive that
42 ** has ever existed, and things like that.
43 */
44 #include "config.h"
45 #include "login.h"
46 #if defined(_WIN32)
47 # include <windows.h> /* for Sleep */
48 # if defined(__MINGW32__) || defined(_MSC_VER)
49 # define sleep Sleep /* windows does not have sleep, but Sleep */
50 # endif
51 #endif
@@ -112,13 +112,13 @@
112 }
113 }
114
115 /*
116 ** The IP address of the client is stored as part of login cookies.
117 ** But some clients are behind firewalls that shift the IP address
118 ** with each HTTP request. To allow such (broken) clients to log in,
119 ** extract just a prefix of the IP address.
120 */
121 static char *ipPrefix(const char *zIP){
122 int i, j;
123 static int ip_prefix_terms = -1;
124 if( ip_prefix_terms<0 ){
@@ -344,11 +344,11 @@
344 */
345 void login_clear_login_data(){
346 if(!g.userUid){
347 return;
348 }else{
349 char const * cookie = login_cookie_name();
350 /* To logout, change the cookie value to an empty string */
351 cgi_set_cookie(cookie, "",
352 login_cookie_path(), -86400);
353 db_multi_exec("UPDATE user SET cookie=NULL, ipaddr=NULL, "
354 " cexpire=0 WHERE uid=%d"
@@ -472,10 +472,11 @@
472 int anonFlag;
473 char *zErrMsg = "";
474 int uid; /* User id logged in user */
475 char *zSha1Pw;
476 const char *zIpAddr; /* IP address of requestor */
 
477
478 login_check_credentials();
479 sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0,
480 constant_time_cmp_function, 0, 0);
481 zUsername = P("u");
@@ -491,21 +492,21 @@
491 /* The user requests a password change */
492 zSha1Pw = sha1_shared_secret(zPasswd, g.zLogin, 0);
493 if( db_int(1, "SELECT 0 FROM user"
494 " WHERE uid=%d"
495 " AND (constant_time_cmp(pw,%Q)=0"
496 " OR constant_time_cmp(pw,%Q)=0)",
497 g.userUid, zSha1Pw, zPasswd) ){
498 sleep(1);
499 zErrMsg =
500 @ <p><span class="loginError">
501 @ You entered an incorrect old password while attempting to change
502 @ your password. Your password is unchanged.
503 @ </span></p>
504 ;
505 }else if( fossil_strcmp(zNew1,zNew2)!=0 ){
506 zErrMsg =
507 @ <p><span class="loginError">
508 @ The two copies of your new passwords do not match.
509 @ Your password is unchanged.
510 @ </span></p>
511 ;
@@ -532,10 +533,11 @@
532 return;
533 }
534 }
535 }
536 zIpAddr = PD("REMOTE_ADDR","nil"); /* Complete IP address for logging */
 
537 uid = login_is_valid_anonymous(zUsername, zPasswd, P("cs"));
538 if( uid>0 ){
539 login_set_anon_cookie(zIpAddr, NULL);
540 record_login_attempt("anonymous", zIpAddr, 1);
541 redirect_to_g();
@@ -544,11 +546,11 @@
544 /* Attempting to log in as a user other than anonymous.
545 */
546 uid = login_search_uid(zUsername, zPasswd);
547 if( uid<=0 ){
548 sleep(1);
549 zErrMsg =
550 @ <p><span class="loginError">
551 @ You entered an unknown user or an incorrect password.
552 @ </span></p>
553 ;
554 record_login_attempt(zUsername, zIpAddr, 0);
@@ -570,10 +572,12 @@
570 @ <p>A login is required for <a href="%h(zGoto)">%h(zGoto)</a>.</p>
571 }
572 form_begin(0, "%R/login");
573 if( zGoto ){
574 @ <input type="hidden" name="g" value="%h(zGoto)" />
 
 
575 }
576 @ <table class="login_out">
577 @ <tr>
578 @ <td class="login_out_label">User ID:</td>
579 if( anonFlag ){
@@ -595,11 +599,11 @@
595 @ <td></td>
596 @ <td><input type="submit" name="in" value="Login"
597 @ onClick="chngAction(this.form)" /></td>
598 @ </tr>
599 @ </table>
600 @ <script type="text/JavaScript">
601 @ gebi('u').focus()
602 @ function chngAction(form){
603 if( g.sslNotAvailable==0
604 && strncmp(g.zBaseURL,"https:",6)!=0
605 && db_get_boolean("https-login",0)
@@ -620,11 +624,11 @@
620 @ your user-id and password at the left and press the
621 @ "Login" button. Your user name will be stored in a browser cookie.
622 @ You must configure your web browser to accept cookies in order for
623 @ the login to take.</p>
624 if( db_get_boolean("self-register", 0) ){
625 @ <p>If you do not have an account, you can
626 @ <a href="%s(g.zTop)/register?g=%T(P("G"))">create one</a>.
627 }
628 if( zAnonPw ){
629 unsigned int uSeed = captcha_seed();
630 char const *zDecoded = captcha_decode(uSeed);
@@ -672,11 +676,11 @@
672 style_footer();
673 }
674
675 /*
676 ** Attempt to find login credentials for user zLogin on a peer repository
677 ** with project code zCode. Transfer those credentials to the local
678 ** repository.
679 **
680 ** Return true if a transfer was made and false if not.
681 */
682 static int login_transfer_credentials(
@@ -690,11 +694,11 @@
690 char *zSQL; /* SQL of the query against other repo */
691 char *zOtherRepo; /* Filename of the other repository */
692 int rc; /* Result code from SQLite library functions */
693 int nXfer = 0; /* Number of credentials transferred */
694
695 zOtherRepo = db_text(0,
696 "SELECT value FROM config WHERE name='peer-repo-%q'",
697 zCode
698 );
699 if( zOtherRepo==0 ) return 0; /* No such peer repository */
700
@@ -752,11 +756,11 @@
752 int uid;
753 if( fossil_strcmp(zLogin, "anonymous")==0 ) return 0;
754 if( fossil_strcmp(zLogin, "nobody")==0 ) return 0;
755 if( fossil_strcmp(zLogin, "developer")==0 ) return 0;
756 if( fossil_strcmp(zLogin, "reader")==0 ) return 0;
757 uid = db_int(0,
758 "SELECT uid FROM user"
759 " WHERE login=%Q"
760 " AND ipaddr=%Q"
761 " AND cexpire>julianday('now')"
762 " AND length(cap)>0"
@@ -792,11 +796,11 @@
792
793 sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0,
794 constant_time_cmp_function, 0, 0);
795
796 /* If the HTTP connection is coming over 127.0.0.1 and if
797 ** local login is disabled and if we are using HTTP and not HTTPS,
798 ** then there is no need to check user credentials.
799 **
800 ** This feature allows the "fossil ui" command to give the user
801 ** full access rights without having to log in.
802 */
@@ -847,15 +851,15 @@
847 ** SECRET is the "captcha-secret" value in the repository.
848 */
849 double rTime = atof(zArg);
850 Blob b;
851 blob_zero(&b);
852 blob_appendf(&b, "%s/%s/%s",
853 zArg, zRemoteAddr, db_get("captcha-secret",""));
854 sha1sum_blob(&b, &b);
855 if( fossil_strcmp(zHash, blob_str(&b))==0 ){
856 uid = db_int(0,
857 "SELECT uid FROM user WHERE login='anonymous'"
858 " AND length(cap)>0"
859 " AND length(pw)>0"
860 " AND %.17g+0.25>julianday('now')",
861 rTime
@@ -1002,11 +1006,11 @@
1002 for(i=0; zCap[i]; i++){
1003 switch( zCap[i] ){
1004 case 's': g.perm.Setup = 1; /* Fall thru into Admin */
1005 case 'a': g.perm.Admin = g.perm.RdTkt = g.perm.WrTkt = g.perm.Zip =
1006 g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki =
1007 g.perm.ApndWiki = g.perm.Hyperlink = g.perm.Clone =
1008 g.perm.NewTkt = g.perm.Password = g.perm.RdAddr =
1009 g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt =
1010 g.perm.ModWiki = g.perm.ModTkt = 1;
1011 /* Fall thru into Read/Write */
1012 case 'i': g.perm.Read = g.perm.Write = 1; break;
@@ -1025,19 +1029,19 @@
1025 case 'l': g.perm.ModWiki = 1; break;
1026
1027 case 'e': g.perm.RdAddr = 1; break;
1028 case 'r': g.perm.RdTkt = 1; break;
1029 case 'n': g.perm.NewTkt = 1; break;
1030 case 'w': g.perm.WrTkt = g.perm.RdTkt = g.perm.NewTkt =
1031 g.perm.ApndTkt = 1; break;
1032 case 'c': g.perm.ApndTkt = 1; break;
1033 case 'q': g.perm.ModTkt = 1; break;
1034 case 't': g.perm.TktFmt = 1; break;
1035 case 'b': g.perm.Attach = 1; break;
1036 case 'x': g.perm.Private = 1; break;
1037
1038 /* The "u" privileges is a little different. It recursively
1039 ** inherits all privileges of the user named "reader" */
1040 case 'u': {
1041 if( (flags & LOGIN_IGNORE_UV)==0 ){
1042 const char *zUser;
1043 zUser = db_text("", "SELECT cap FROM user WHERE login='reader'");
@@ -1044,11 +1048,11 @@
1044 login_set_capabilities(zUser, flags | LOGIN_IGNORE_UV);
1045 }
1046 break;
1047 }
1048
1049 /* The "v" privileges is a little different. It recursively
1050 ** inherits all privileges of the user named "developer" */
1051 case 'v': {
1052 if( (flags & LOGIN_IGNORE_UV)==0 ){
1053 const char *zDev;
1054 zDev = db_text("", "SELECT cap FROM user WHERE login='developer'");
@@ -1359,11 +1363,11 @@
1359 if( zPrefix==0 ) zPrefix = "";
1360 if( zSuffix==0 ) zSuffix = "";
1361 if( pzErrorMsg ) *pzErrorMsg = 0;
1362 zSelfCode = abbreviated_project_code(db_get("project-code", "x"));
1363 blob_zero(&err);
1364 db_prepare(&q,
1365 "SELECT name, value FROM config"
1366 " WHERE name GLOB 'peer-repo-*'"
1367 " AND name <> 'peer-repo-%q'"
1368 " ORDER BY +value",
1369 zSelfCode
@@ -1441,11 +1445,11 @@
1441 const char *zSelf; /* The ATTACH name of our repository */
1442
1443 *pzErrMsg = 0; /* Default to no errors */
1444 zSelf = db_name("repository");
1445
1446 /* Get the full pathname of the other repository */
1447 file_canonical_name(zRepo, &fullName, 0);
1448 zRepo = mprintf(blob_str(&fullName));
1449 blob_reset(&fullName);
1450
1451 /* Get the full pathname for our repository. Also the project code
1452
--- src/login.c
+++ src/login.c
@@ -41,11 +41,11 @@
41 ** logs and downloading diffs of very version of the archive that
42 ** has ever existed, and things like that.
43 */
44 #include "config.h"
45 #include "login.h"
46 #if defined(_WIN32)
47 # include <windows.h> /* for Sleep */
48 # if defined(__MINGW32__) || defined(_MSC_VER)
49 # define sleep Sleep /* windows does not have sleep, but Sleep */
50 # endif
51 #endif
@@ -112,13 +112,13 @@
112 }
113 }
114
115 /*
116 ** The IP address of the client is stored as part of login cookies.
117 ** But some clients are behind firewalls that shift the IP address
118 ** with each HTTP request. To allow such (broken) clients to log in,
119 ** extract just a prefix of the IP address.
120 */
121 static char *ipPrefix(const char *zIP){
122 int i, j;
123 static int ip_prefix_terms = -1;
124 if( ip_prefix_terms<0 ){
@@ -344,11 +344,11 @@
344 */
345 void login_clear_login_data(){
346 if(!g.userUid){
347 return;
348 }else{
349 char const * cookie = login_cookie_name();
350 /* To logout, change the cookie value to an empty string */
351 cgi_set_cookie(cookie, "",
352 login_cookie_path(), -86400);
353 db_multi_exec("UPDATE user SET cookie=NULL, ipaddr=NULL, "
354 " cexpire=0 WHERE uid=%d"
@@ -472,10 +472,11 @@
472 int anonFlag;
473 char *zErrMsg = "";
474 int uid; /* User id logged in user */
475 char *zSha1Pw;
476 const char *zIpAddr; /* IP address of requestor */
477 const char *zReferer;
478
479 login_check_credentials();
480 sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0,
481 constant_time_cmp_function, 0, 0);
482 zUsername = P("u");
@@ -491,21 +492,21 @@
492 /* The user requests a password change */
493 zSha1Pw = sha1_shared_secret(zPasswd, g.zLogin, 0);
494 if( db_int(1, "SELECT 0 FROM user"
495 " WHERE uid=%d"
496 " AND (constant_time_cmp(pw,%Q)=0"
497 " OR constant_time_cmp(pw,%Q)=0)",
498 g.userUid, zSha1Pw, zPasswd) ){
499 sleep(1);
500 zErrMsg =
501 @ <p><span class="loginError">
502 @ You entered an incorrect old password while attempting to change
503 @ your password. Your password is unchanged.
504 @ </span></p>
505 ;
506 }else if( fossil_strcmp(zNew1,zNew2)!=0 ){
507 zErrMsg =
508 @ <p><span class="loginError">
509 @ The two copies of your new passwords do not match.
510 @ Your password is unchanged.
511 @ </span></p>
512 ;
@@ -532,10 +533,11 @@
533 return;
534 }
535 }
536 }
537 zIpAddr = PD("REMOTE_ADDR","nil"); /* Complete IP address for logging */
538 zReferer = P("HTTP_REFERER");
539 uid = login_is_valid_anonymous(zUsername, zPasswd, P("cs"));
540 if( uid>0 ){
541 login_set_anon_cookie(zIpAddr, NULL);
542 record_login_attempt("anonymous", zIpAddr, 1);
543 redirect_to_g();
@@ -544,11 +546,11 @@
546 /* Attempting to log in as a user other than anonymous.
547 */
548 uid = login_search_uid(zUsername, zPasswd);
549 if( uid<=0 ){
550 sleep(1);
551 zErrMsg =
552 @ <p><span class="loginError">
553 @ You entered an unknown user or an incorrect password.
554 @ </span></p>
555 ;
556 record_login_attempt(zUsername, zIpAddr, 0);
@@ -570,10 +572,12 @@
572 @ <p>A login is required for <a href="%h(zGoto)">%h(zGoto)</a>.</p>
573 }
574 form_begin(0, "%R/login");
575 if( zGoto ){
576 @ <input type="hidden" name="g" value="%h(zGoto)" />
577 }else if( zReferer && strncmp(g.zBaseURL, zReferer, strlen(g.zBaseURL))==0 ){
578 @ <input type="hidden" name="g" value="%h(zReferer)" />
579 }
580 @ <table class="login_out">
581 @ <tr>
582 @ <td class="login_out_label">User ID:</td>
583 if( anonFlag ){
@@ -595,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)
@@ -620,11 +624,11 @@
624 @ your user-id and password at the left and press the
625 @ "Login" button. Your user name will be stored in a browser cookie.
626 @ You must configure your web browser to accept cookies in order for
627 @ the login to take.</p>
628 if( db_get_boolean("self-register", 0) ){
629 @ <p>If you do not have an account, you can
630 @ <a href="%s(g.zTop)/register?g=%T(P("G"))">create one</a>.
631 }
632 if( zAnonPw ){
633 unsigned int uSeed = captcha_seed();
634 char const *zDecoded = captcha_decode(uSeed);
@@ -672,11 +676,11 @@
676 style_footer();
677 }
678
679 /*
680 ** Attempt to find login credentials for user zLogin on a peer repository
681 ** with project code zCode. Transfer those credentials to the local
682 ** repository.
683 **
684 ** Return true if a transfer was made and false if not.
685 */
686 static int login_transfer_credentials(
@@ -690,11 +694,11 @@
694 char *zSQL; /* SQL of the query against other repo */
695 char *zOtherRepo; /* Filename of the other repository */
696 int rc; /* Result code from SQLite library functions */
697 int nXfer = 0; /* Number of credentials transferred */
698
699 zOtherRepo = db_text(0,
700 "SELECT value FROM config WHERE name='peer-repo-%q'",
701 zCode
702 );
703 if( zOtherRepo==0 ) return 0; /* No such peer repository */
704
@@ -752,11 +756,11 @@
756 int uid;
757 if( fossil_strcmp(zLogin, "anonymous")==0 ) return 0;
758 if( fossil_strcmp(zLogin, "nobody")==0 ) return 0;
759 if( fossil_strcmp(zLogin, "developer")==0 ) return 0;
760 if( fossil_strcmp(zLogin, "reader")==0 ) return 0;
761 uid = db_int(0,
762 "SELECT uid FROM user"
763 " WHERE login=%Q"
764 " AND ipaddr=%Q"
765 " AND cexpire>julianday('now')"
766 " AND length(cap)>0"
@@ -792,11 +796,11 @@
796
797 sqlite3_create_function(g.db, "constant_time_cmp", 2, SQLITE_UTF8, 0,
798 constant_time_cmp_function, 0, 0);
799
800 /* If the HTTP connection is coming over 127.0.0.1 and if
801 ** local login is disabled and if we are using HTTP and not HTTPS,
802 ** then there is no need to check user credentials.
803 **
804 ** This feature allows the "fossil ui" command to give the user
805 ** full access rights without having to log in.
806 */
@@ -847,15 +851,15 @@
851 ** SECRET is the "captcha-secret" value in the repository.
852 */
853 double rTime = atof(zArg);
854 Blob b;
855 blob_zero(&b);
856 blob_appendf(&b, "%s/%s/%s",
857 zArg, zRemoteAddr, db_get("captcha-secret",""));
858 sha1sum_blob(&b, &b);
859 if( fossil_strcmp(zHash, blob_str(&b))==0 ){
860 uid = db_int(0,
861 "SELECT uid FROM user WHERE login='anonymous'"
862 " AND length(cap)>0"
863 " AND length(pw)>0"
864 " AND %.17g+0.25>julianday('now')",
865 rTime
@@ -1002,11 +1006,11 @@
1006 for(i=0; zCap[i]; i++){
1007 switch( zCap[i] ){
1008 case 's': g.perm.Setup = 1; /* Fall thru into Admin */
1009 case 'a': g.perm.Admin = g.perm.RdTkt = g.perm.WrTkt = g.perm.Zip =
1010 g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki =
1011 g.perm.ApndWiki = g.perm.Hyperlink = g.perm.Clone =
1012 g.perm.NewTkt = g.perm.Password = g.perm.RdAddr =
1013 g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt =
1014 g.perm.ModWiki = g.perm.ModTkt = 1;
1015 /* Fall thru into Read/Write */
1016 case 'i': g.perm.Read = g.perm.Write = 1; break;
@@ -1025,19 +1029,19 @@
1029 case 'l': g.perm.ModWiki = 1; break;
1030
1031 case 'e': g.perm.RdAddr = 1; break;
1032 case 'r': g.perm.RdTkt = 1; break;
1033 case 'n': g.perm.NewTkt = 1; break;
1034 case 'w': g.perm.WrTkt = g.perm.RdTkt = g.perm.NewTkt =
1035 g.perm.ApndTkt = 1; break;
1036 case 'c': g.perm.ApndTkt = 1; break;
1037 case 'q': g.perm.ModTkt = 1; break;
1038 case 't': g.perm.TktFmt = 1; break;
1039 case 'b': g.perm.Attach = 1; break;
1040 case 'x': g.perm.Private = 1; break;
1041
1042 /* The "u" privileges is a little different. It recursively
1043 ** inherits all privileges of the user named "reader" */
1044 case 'u': {
1045 if( (flags & LOGIN_IGNORE_UV)==0 ){
1046 const char *zUser;
1047 zUser = db_text("", "SELECT cap FROM user WHERE login='reader'");
@@ -1044,11 +1048,11 @@
1048 login_set_capabilities(zUser, flags | LOGIN_IGNORE_UV);
1049 }
1050 break;
1051 }
1052
1053 /* The "v" privileges is a little different. It recursively
1054 ** inherits all privileges of the user named "developer" */
1055 case 'v': {
1056 if( (flags & LOGIN_IGNORE_UV)==0 ){
1057 const char *zDev;
1058 zDev = db_text("", "SELECT cap FROM user WHERE login='developer'");
@@ -1359,11 +1363,11 @@
1363 if( zPrefix==0 ) zPrefix = "";
1364 if( zSuffix==0 ) zSuffix = "";
1365 if( pzErrorMsg ) *pzErrorMsg = 0;
1366 zSelfCode = abbreviated_project_code(db_get("project-code", "x"));
1367 blob_zero(&err);
1368 db_prepare(&q,
1369 "SELECT name, value FROM config"
1370 " WHERE name GLOB 'peer-repo-*'"
1371 " AND name <> 'peer-repo-%q'"
1372 " ORDER BY +value",
1373 zSelfCode
@@ -1441,11 +1445,11 @@
1445 const char *zSelf; /* The ATTACH name of our repository */
1446
1447 *pzErrMsg = 0; /* Default to no errors */
1448 zSelf = db_name("repository");
1449
1450 /* Get the full pathname of the other repository */
1451 file_canonical_name(zRepo, &fullName, 0);
1452 zRepo = mprintf(blob_str(&fullName));
1453 blob_reset(&fullName);
1454
1455 /* Get the full pathname for our repository. Also the project code
1456
+4 -2
--- src/main.c
+++ src/main.c
@@ -189,11 +189,13 @@
189189
char *urlPasswd; /* Password for http: */
190190
char *urlCanonical; /* Canonical representation of the URL */
191191
char *urlProxyAuth; /* Proxy-Authorizer: string */
192192
char *urlFossil; /* The fossil query parameter on ssh: */
193193
unsigned urlFlags; /* Boolean flags controlling URL processing */
194
-
194
+ int useProxy; /* Used to remember that a proxy is in use */
195
+ char *proxyUrlPath;
196
+ int proxyOrigPort; /* Tunneled port number for https through proxy */
195197
const char *zLogin; /* Login name. "" if not logged in. */
196198
const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
197199
** SSL client identity */
198200
int useLocalauth; /* No login required if from 127.0.0.1 */
199201
int noPswd; /* Logged in without password (on 127.0.0.1) */
@@ -600,11 +602,11 @@
600602
#endif
601603
g.mainTimerId = fossil_timer_start();
602604
g.zVfsName = find_option("vfs",0,1);
603605
if( g.zVfsName==0 ){
604606
g.zVfsName = fossil_getenv("FOSSIL_VFS");
605
-#if defined(_WIN32) || defined(__CYGWIN__)
607
+#if defined(__CYGWIN__)
606608
if( g.zVfsName==0 ){
607609
g.zVfsName = "win32-longpath";
608610
}
609611
#endif
610612
}
611613
--- src/main.c
+++ src/main.c
@@ -189,11 +189,13 @@
189 char *urlPasswd; /* Password for http: */
190 char *urlCanonical; /* Canonical representation of the URL */
191 char *urlProxyAuth; /* Proxy-Authorizer: string */
192 char *urlFossil; /* The fossil query parameter on ssh: */
193 unsigned urlFlags; /* Boolean flags controlling URL processing */
194
 
 
195 const char *zLogin; /* Login name. "" if not logged in. */
196 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
197 ** SSL client identity */
198 int useLocalauth; /* No login required if from 127.0.0.1 */
199 int noPswd; /* Logged in without password (on 127.0.0.1) */
@@ -600,11 +602,11 @@
600 #endif
601 g.mainTimerId = fossil_timer_start();
602 g.zVfsName = find_option("vfs",0,1);
603 if( g.zVfsName==0 ){
604 g.zVfsName = fossil_getenv("FOSSIL_VFS");
605 #if defined(_WIN32) || defined(__CYGWIN__)
606 if( g.zVfsName==0 ){
607 g.zVfsName = "win32-longpath";
608 }
609 #endif
610 }
611
--- src/main.c
+++ src/main.c
@@ -189,11 +189,13 @@
189 char *urlPasswd; /* Password for http: */
190 char *urlCanonical; /* Canonical representation of the URL */
191 char *urlProxyAuth; /* Proxy-Authorizer: string */
192 char *urlFossil; /* The fossil query parameter on ssh: */
193 unsigned urlFlags; /* Boolean flags controlling URL processing */
194 int useProxy; /* Used to remember that a proxy is in use */
195 char *proxyUrlPath;
196 int proxyOrigPort; /* Tunneled port number for https through proxy */
197 const char *zLogin; /* Login name. "" if not logged in. */
198 const char *zSSLIdentity; /* Value of --ssl-identity option, filename of
199 ** SSL client identity */
200 int useLocalauth; /* No login required if from 127.0.0.1 */
201 int noPswd; /* Logged in without password (on 127.0.0.1) */
@@ -600,11 +602,11 @@
602 #endif
603 g.mainTimerId = fossil_timer_start();
604 g.zVfsName = find_option("vfs",0,1);
605 if( g.zVfsName==0 ){
606 g.zVfsName = fossil_getenv("FOSSIL_VFS");
607 #if defined(__CYGWIN__)
608 if( g.zVfsName==0 ){
609 g.zVfsName = "win32-longpath";
610 }
611 #endif
612 }
613
+25 -25
--- src/manifest.c
+++ src/manifest.c
@@ -51,11 +51,11 @@
5151
#define MC_PERMIT_HOOKS 1 /* permit hooks to execute */
5252
5353
/*
5454
** A single F-card within a manifest
5555
*/
56
-struct ManifestFile {
56
+struct ManifestFile {
5757
char *zName; /* Name of a file */
5858
char *zUuid; /* UUID of the file */
5959
char *zPerm; /* File permissions */
6060
char *zPrior; /* Prior name if the name was changed */
6161
};
@@ -89,11 +89,11 @@
8989
ManifestFile *aFile; /* One entry for each F-card */
9090
int nParent; /* Number of parents. */
9191
int nParentAlloc; /* Slots allocated in azParent[] */
9292
char **azParent; /* UUIDs of parents. One for each P card argument */
9393
int nCherrypick; /* Number of entries in aCherrypick[] */
94
- struct {
94
+ struct {
9595
char *zCPTarget; /* UUID of cherry-picked version w/ +|- prefix */
9696
char *zCPBase; /* UUID of cherry-pick baseline. NULL for singletons */
9797
} *aCherrypick;
9898
int nCChild; /* Number of cluster children */
9999
int nCChildAlloc; /* Number of closts allocated in azCChild[] */
@@ -105,11 +105,11 @@
105105
char *zUuid; /* UUID that the tag is applied to */
106106
char *zValue; /* Value if the tag is really a property */
107107
} *aTag; /* One for each T card */
108108
int nField; /* Number of J cards */
109109
int nFieldAlloc; /* Slots allocated in aField[] */
110
- struct {
110
+ struct {
111111
char *zName; /* Key or field name */
112112
char *zValue; /* Value of the field */
113113
} *aField; /* One for each J card */
114114
};
115115
#endif
@@ -251,11 +251,11 @@
251251
** Verify the Z-card checksum on the artifact, if there is such a
252252
** checksum. Return 0 if there is no Z-card. Return 1 if the Z-card
253253
** exists and is correct. Return 2 if the Z-card exists and has the wrong
254254
** value.
255255
**
256
-** 0123456789 123456789 123456789 123456789
256
+** 0123456789 123456789 123456789 123456789
257257
** Z aea84f4f863865a8d59d0384e4d2a41c
258258
*/
259259
static int verify_z_card(const char *z, int n){
260260
if( n<35 ) return 0;
261261
if( z[n-35]!='Z' || z[n-34]!=' ' ) return 0;
@@ -435,11 +435,11 @@
435435
char *zName, *zTarget, *zSrc;
436436
int nTarget = 0, nSrc = 0;
437437
zName = next_token(&x, 0);
438438
zTarget = next_token(&x, &nTarget);
439439
zSrc = next_token(&x, &nSrc);
440
- if( zName==0 || zTarget==0 ) goto manifest_syntax_error;
440
+ if( zName==0 || zTarget==0 ) goto manifest_syntax_error;
441441
if( p->zAttachName!=0 ) goto manifest_syntax_error;
442442
defossilize(zName);
443443
if( !file_is_simple_pathname(zName, 0) ){
444444
SYNTAX("invalid filename on A-card");
445445
}
@@ -504,11 +504,11 @@
504504
}
505505
506506
/*
507507
** E <timestamp> <uuid>
508508
**
509
- ** An "event" card that contains the timestamp of the event in the
509
+ ** An "event" card that contains the timestamp of the event in the
510510
** format YYYY-MM-DDtHH:MM:SS and a unique identifier for the event.
511511
** The event timestamp is distinct from the D timestamp. The D
512512
** timestamp is when the artifact was created whereas the E timestamp
513513
** is when the specific event is said to occur.
514514
*/
@@ -551,11 +551,11 @@
551551
SYNTAX("F-card old filename is not a simple path");
552552
}
553553
}
554554
if( p->nFile>=p->nFileAlloc ){
555555
p->nFileAlloc = p->nFileAlloc*2 + 10;
556
- p->aFile = fossil_realloc(p->aFile,
556
+ p->aFile = fossil_realloc(p->aFile,
557557
p->nFileAlloc*sizeof(p->aFile[0]) );
558558
}
559559
i = p->nFile++;
560560
p->aFile[i].zName = zName;
561561
p->aFile[i].zUuid = zUuid;
@@ -743,11 +743,11 @@
743743
** singleton tag, "*" to create a propagating tag, or "-" to create
744744
** anti-tag that undoes a prior "+" or blocks propagation of of
745745
** a "*".
746746
**
747747
** The tag is applied to <uuid>. If <uuid> is "*" then the tag is
748
- ** applied to the current manifest. If <value> is provided then
748
+ ** applied to the current manifest. If <value> is provided then
749749
** the tag is really a property with the given value.
750750
**
751751
** Tags are not allowed in clusters. Multiple T lines are allowed.
752752
*/
753753
case 'T': {
@@ -1050,11 +1050,11 @@
10501050
db_multi_exec(
10511051
"INSERT OR IGNORE INTO orphan(rid, baseline) VALUES(%d,%d)",
10521052
p->rid, rid
10531053
);
10541054
return 1;
1055
- }
1055
+ }
10561056
fossil_fatal("cannot access baseline manifest %S", p->zBaseline);
10571057
}
10581058
}
10591059
return 0;
10601060
}
@@ -1075,11 +1075,11 @@
10751075
**
10761076
** Return NULL for end-of-records or if there is an error. If an error
10771077
** occurs and pErr!=0 then store 1 in *pErr.
10781078
*/
10791079
ManifestFile *manifest_file_next(
1080
- Manifest *p,
1080
+ Manifest *p,
10811081
int *pErr
10821082
){
10831083
ManifestFile *pOut = 0;
10841084
if( pErr ) *pErr = 0;
10851085
if( p->pBaseline==0 ){
@@ -1219,11 +1219,11 @@
12191219
content_deltify(pid, fid, 0);
12201220
}
12211221
}
12221222
12231223
/*
1224
-** Do a binary search to find a file in the p->aFile[] array.
1224
+** Do a binary search to find a file in the p->aFile[] array.
12251225
**
12261226
** As an optimization, guess that the file we seek is at index p->iFile.
12271227
** That will usually be the case. If it is not found there, then do the
12281228
** actual binary search.
12291229
**
@@ -1263,18 +1263,18 @@
12631263
/*
12641264
** Locate a file named zName in the aFile[] array of the given manifest.
12651265
** Return a pointer to the appropriate ManifestFile object. Return NULL
12661266
** if not found.
12671267
**
1268
-** This routine works even if p is a delta-manifest. The pointer
1268
+** This routine works even if p is a delta-manifest. The pointer
12691269
** returned might be to the baseline.
12701270
**
12711271
** We assume that filenames are in sorted order and use a binary search.
12721272
*/
12731273
ManifestFile *manifest_file_seek(Manifest *p, const char *zName){
12741274
ManifestFile *pFile;
1275
-
1275
+
12761276
pFile = manifest_file_seek_base(p, zName);
12771277
if( pFile && pFile->zUuid==0 ) return 0;
12781278
if( pFile==0 && p->zBaseline ){
12791279
fetch_baseline(p, 1);
12801280
pFile = manifest_file_seek_base(p->pBaseline, zName);
@@ -1362,15 +1362,15 @@
13621362
return;
13631363
}
13641364
isPublic = !content_is_private(cid);
13651365
13661366
/* Try to make the parent manifest a delta from the child, if that
1367
- ** is an appropriate thing to do. For a new baseline, make the
1367
+ ** is an appropriate thing to do. For a new baseline, make the
13681368
** previous baseline a delta from the current baseline.
13691369
*/
13701370
if( (pParent->zBaseline==0)==(pChild->zBaseline==0) ){
1371
- content_deltify(pid, cid, 0);
1371
+ content_deltify(pid, cid, 0);
13721372
}else if( pChild->zBaseline==0 && pParent->zBaseline!=0 ){
13731373
content_deltify(pParent->pBaseline->rid, cid, 0);
13741374
}
13751375
13761376
/* Remember all children less than a few seconds younger than their parent,
@@ -1385,11 +1385,11 @@
13851385
);
13861386
}
13871387
13881388
/* First look at all files in pChild, ignoring its baseline. This
13891389
** is where most of the changes will be found.
1390
- */
1390
+ */
13911391
for(i=0, pChildFile=pChild->aFile; i<pChild->nFile; i++, pChildFile++){
13921392
int mperm = manifest_file_mperm(pChildFile);
13931393
if( pChildFile->zPrior ){
13941394
pParentFile = manifest_file_seek(pParent, pChildFile->zPrior);
13951395
if( pParentFile ){
@@ -1450,11 +1450,11 @@
14501450
** but are missing from pChild and mark them as having been deleted. */
14511451
manifest_file_rewind(pParent);
14521452
while( (pParentFile = manifest_file_next(pParent,0))!=0 ){
14531453
pChildFile = manifest_file_seek(pChild, pParentFile->zName);
14541454
if( pChildFile==0 && pParentFile->zUuid!=0 ){
1455
- add_one_mlink(cid, pParentFile->zUuid, 0, pParentFile->zName, 0,
1455
+ add_one_mlink(cid, pParentFile->zUuid, 0, pParentFile->zName, 0,
14561456
isPublic, 0);
14571457
}
14581458
}
14591459
}
14601460
manifest_cache_insert(*ppOther);
@@ -1578,11 +1578,11 @@
15781578
if( once ){
15791579
once = 0;
15801580
zTitleExpr = db_get("ticket-title-expr", "title");
15811581
zStatusColumn = db_get("ticket-status-column", "status");
15821582
}
1583
- zTitle = db_text("unknown",
1583
+ zTitle = db_text("unknown",
15841584
"SELECT %s FROM ticket WHERE tkt_uuid='%s'",
15851585
zTitleExpr, pManifest->zTicketUuid
15861586
);
15871587
if( !isNew ){
15881588
for(i=0; i<pManifest->nField; i++){
@@ -1599,11 +1599,11 @@
15991599
pManifest->nField-1, pManifest->nField==2 ? "" : "s");
16001600
}
16011601
blob_appendf(&brief, "%h ticket [%.10s].",
16021602
zNewStatus, pManifest->zTicketUuid);
16031603
}else{
1604
- zNewStatus = db_text("unknown",
1604
+ zNewStatus = db_text("unknown",
16051605
"SELECT %s FROM ticket WHERE tkt_uuid='%s'",
16061606
zStatusColumn, pManifest->zTicketUuid
16071607
);
16081608
blob_appendf(&comment, "Ticket [%.10s] <i>%h</i> status still %h with "
16091609
"%d other change%s",
@@ -1661,11 +1661,11 @@
16611661
**
16621662
** If the input is a control artifact, then make appropriate entries
16631663
** in the auxiliary tables of the database in order to crosslink the
16641664
** artifact.
16651665
**
1666
-** If global variable g.xlinkClusterOnly is true, then ignore all
1666
+** If global variable g.xlinkClusterOnly is true, then ignore all
16671667
** control artifacts other than clusters.
16681668
**
16691669
** This routine always resets the pContent blob before returning.
16701670
**
16711671
** Historical note: This routine original processed manifests only.
@@ -1744,11 +1744,11 @@
17441744
" %d,%Q,%Q,"
17451745
" (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d AND tagtype>0),"
17461746
" (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d),"
17471747
" (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d),%.17g);",
17481748
TAG_DATE, rid, p->rDate,
1749
- rid, p->zUser, p->zComment,
1749
+ rid, p->zUser, p->zComment,
17501750
TAG_BGCOLOR, rid,
17511751
TAG_USER, rid,
17521752
TAG_COMMENT, rid, p->rDate
17531753
);
17541754
zCom = db_text(0, "SELECT coalesce(ecomment, comment) FROM event"
@@ -1802,11 +1802,11 @@
18021802
case '*': type = 2; break; /* Propagate to descendants */
18031803
default:
18041804
fossil_error(1, "unknown tag type in manifest: %s", p->aTag);
18051805
return 0;
18061806
}
1807
- tag_insert(&p->aTag[i].zName[1], type, p->aTag[i].zValue,
1807
+ tag_insert(&p->aTag[i].zName[1], type, p->aTag[i].zValue,
18081808
rid, p->rDate, tid);
18091809
}
18101810
}
18111811
if( parentid ){
18121812
tag_propagate_all(parentid);
@@ -1843,11 +1843,11 @@
18431843
" bgcolor,euser,ecomment)"
18441844
"VALUES('w',%.17g,%d,%Q,%Q,"
18451845
" (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d AND tagtype>1),"
18461846
" (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d),"
18471847
" (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
1848
- p->rDate, rid, p->zUser, zComment,
1848
+ p->rDate, rid, p->zUser, zComment,
18491849
TAG_BGCOLOR, rid,
18501850
TAG_BGCOLOR, rid,
18511851
TAG_USER, rid,
18521852
TAG_COMMENT, rid
18531853
);
@@ -1893,11 +1893,11 @@
18931893
}else{
18941894
db_multi_exec(
18951895
"REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)"
18961896
"VALUES('e',%.17g,%d,%d,%Q,%Q,"
18971897
" (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
1898
- p->rEventDate, rid, tagid, p->zUser, p->zComment,
1898
+ p->rEventDate, rid, tagid, p->zUser, p->zComment,
18991899
TAG_BGCOLOR, rid
19001900
);
19011901
}
19021902
}
19031903
if( p->type==CFTYPE_TICKET ){
@@ -1925,11 +1925,11 @@
19251925
" WHERE target=%Q AND filename=%Q",
19261926
p->zAttachTarget, p->zAttachName,
19271927
p->zAttachTarget, p->zAttachName
19281928
);
19291929
if( strlen(p->zAttachTarget)!=UUID_SIZE
1930
- || !validate16(p->zAttachTarget, UUID_SIZE)
1930
+ || !validate16(p->zAttachTarget, UUID_SIZE)
19311931
){
19321932
char *zComment;
19331933
if( p->zAttachSrc && p->zAttachSrc[0] ){
19341934
zComment = mprintf(
19351935
"Add attachment [/artifact/%S|%h] to wiki page [%h]",
19361936
--- src/manifest.c
+++ src/manifest.c
@@ -51,11 +51,11 @@
51 #define MC_PERMIT_HOOKS 1 /* permit hooks to execute */
52
53 /*
54 ** A single F-card within a manifest
55 */
56 struct ManifestFile {
57 char *zName; /* Name of a file */
58 char *zUuid; /* UUID of the file */
59 char *zPerm; /* File permissions */
60 char *zPrior; /* Prior name if the name was changed */
61 };
@@ -89,11 +89,11 @@
89 ManifestFile *aFile; /* One entry for each F-card */
90 int nParent; /* Number of parents. */
91 int nParentAlloc; /* Slots allocated in azParent[] */
92 char **azParent; /* UUIDs of parents. One for each P card argument */
93 int nCherrypick; /* Number of entries in aCherrypick[] */
94 struct {
95 char *zCPTarget; /* UUID of cherry-picked version w/ +|- prefix */
96 char *zCPBase; /* UUID of cherry-pick baseline. NULL for singletons */
97 } *aCherrypick;
98 int nCChild; /* Number of cluster children */
99 int nCChildAlloc; /* Number of closts allocated in azCChild[] */
@@ -105,11 +105,11 @@
105 char *zUuid; /* UUID that the tag is applied to */
106 char *zValue; /* Value if the tag is really a property */
107 } *aTag; /* One for each T card */
108 int nField; /* Number of J cards */
109 int nFieldAlloc; /* Slots allocated in aField[] */
110 struct {
111 char *zName; /* Key or field name */
112 char *zValue; /* Value of the field */
113 } *aField; /* One for each J card */
114 };
115 #endif
@@ -251,11 +251,11 @@
251 ** Verify the Z-card checksum on the artifact, if there is such a
252 ** checksum. Return 0 if there is no Z-card. Return 1 if the Z-card
253 ** exists and is correct. Return 2 if the Z-card exists and has the wrong
254 ** value.
255 **
256 ** 0123456789 123456789 123456789 123456789
257 ** Z aea84f4f863865a8d59d0384e4d2a41c
258 */
259 static int verify_z_card(const char *z, int n){
260 if( n<35 ) return 0;
261 if( z[n-35]!='Z' || z[n-34]!=' ' ) return 0;
@@ -435,11 +435,11 @@
435 char *zName, *zTarget, *zSrc;
436 int nTarget = 0, nSrc = 0;
437 zName = next_token(&x, 0);
438 zTarget = next_token(&x, &nTarget);
439 zSrc = next_token(&x, &nSrc);
440 if( zName==0 || zTarget==0 ) goto manifest_syntax_error;
441 if( p->zAttachName!=0 ) goto manifest_syntax_error;
442 defossilize(zName);
443 if( !file_is_simple_pathname(zName, 0) ){
444 SYNTAX("invalid filename on A-card");
445 }
@@ -504,11 +504,11 @@
504 }
505
506 /*
507 ** E <timestamp> <uuid>
508 **
509 ** An "event" card that contains the timestamp of the event in the
510 ** format YYYY-MM-DDtHH:MM:SS and a unique identifier for the event.
511 ** The event timestamp is distinct from the D timestamp. The D
512 ** timestamp is when the artifact was created whereas the E timestamp
513 ** is when the specific event is said to occur.
514 */
@@ -551,11 +551,11 @@
551 SYNTAX("F-card old filename is not a simple path");
552 }
553 }
554 if( p->nFile>=p->nFileAlloc ){
555 p->nFileAlloc = p->nFileAlloc*2 + 10;
556 p->aFile = fossil_realloc(p->aFile,
557 p->nFileAlloc*sizeof(p->aFile[0]) );
558 }
559 i = p->nFile++;
560 p->aFile[i].zName = zName;
561 p->aFile[i].zUuid = zUuid;
@@ -743,11 +743,11 @@
743 ** singleton tag, "*" to create a propagating tag, or "-" to create
744 ** anti-tag that undoes a prior "+" or blocks propagation of of
745 ** a "*".
746 **
747 ** The tag is applied to <uuid>. If <uuid> is "*" then the tag is
748 ** applied to the current manifest. If <value> is provided then
749 ** the tag is really a property with the given value.
750 **
751 ** Tags are not allowed in clusters. Multiple T lines are allowed.
752 */
753 case 'T': {
@@ -1050,11 +1050,11 @@
1050 db_multi_exec(
1051 "INSERT OR IGNORE INTO orphan(rid, baseline) VALUES(%d,%d)",
1052 p->rid, rid
1053 );
1054 return 1;
1055 }
1056 fossil_fatal("cannot access baseline manifest %S", p->zBaseline);
1057 }
1058 }
1059 return 0;
1060 }
@@ -1075,11 +1075,11 @@
1075 **
1076 ** Return NULL for end-of-records or if there is an error. If an error
1077 ** occurs and pErr!=0 then store 1 in *pErr.
1078 */
1079 ManifestFile *manifest_file_next(
1080 Manifest *p,
1081 int *pErr
1082 ){
1083 ManifestFile *pOut = 0;
1084 if( pErr ) *pErr = 0;
1085 if( p->pBaseline==0 ){
@@ -1219,11 +1219,11 @@
1219 content_deltify(pid, fid, 0);
1220 }
1221 }
1222
1223 /*
1224 ** Do a binary search to find a file in the p->aFile[] array.
1225 **
1226 ** As an optimization, guess that the file we seek is at index p->iFile.
1227 ** That will usually be the case. If it is not found there, then do the
1228 ** actual binary search.
1229 **
@@ -1263,18 +1263,18 @@
1263 /*
1264 ** Locate a file named zName in the aFile[] array of the given manifest.
1265 ** Return a pointer to the appropriate ManifestFile object. Return NULL
1266 ** if not found.
1267 **
1268 ** This routine works even if p is a delta-manifest. The pointer
1269 ** returned might be to the baseline.
1270 **
1271 ** We assume that filenames are in sorted order and use a binary search.
1272 */
1273 ManifestFile *manifest_file_seek(Manifest *p, const char *zName){
1274 ManifestFile *pFile;
1275
1276 pFile = manifest_file_seek_base(p, zName);
1277 if( pFile && pFile->zUuid==0 ) return 0;
1278 if( pFile==0 && p->zBaseline ){
1279 fetch_baseline(p, 1);
1280 pFile = manifest_file_seek_base(p->pBaseline, zName);
@@ -1362,15 +1362,15 @@
1362 return;
1363 }
1364 isPublic = !content_is_private(cid);
1365
1366 /* Try to make the parent manifest a delta from the child, if that
1367 ** is an appropriate thing to do. For a new baseline, make the
1368 ** previous baseline a delta from the current baseline.
1369 */
1370 if( (pParent->zBaseline==0)==(pChild->zBaseline==0) ){
1371 content_deltify(pid, cid, 0);
1372 }else if( pChild->zBaseline==0 && pParent->zBaseline!=0 ){
1373 content_deltify(pParent->pBaseline->rid, cid, 0);
1374 }
1375
1376 /* Remember all children less than a few seconds younger than their parent,
@@ -1385,11 +1385,11 @@
1385 );
1386 }
1387
1388 /* First look at all files in pChild, ignoring its baseline. This
1389 ** is where most of the changes will be found.
1390 */
1391 for(i=0, pChildFile=pChild->aFile; i<pChild->nFile; i++, pChildFile++){
1392 int mperm = manifest_file_mperm(pChildFile);
1393 if( pChildFile->zPrior ){
1394 pParentFile = manifest_file_seek(pParent, pChildFile->zPrior);
1395 if( pParentFile ){
@@ -1450,11 +1450,11 @@
1450 ** but are missing from pChild and mark them as having been deleted. */
1451 manifest_file_rewind(pParent);
1452 while( (pParentFile = manifest_file_next(pParent,0))!=0 ){
1453 pChildFile = manifest_file_seek(pChild, pParentFile->zName);
1454 if( pChildFile==0 && pParentFile->zUuid!=0 ){
1455 add_one_mlink(cid, pParentFile->zUuid, 0, pParentFile->zName, 0,
1456 isPublic, 0);
1457 }
1458 }
1459 }
1460 manifest_cache_insert(*ppOther);
@@ -1578,11 +1578,11 @@
1578 if( once ){
1579 once = 0;
1580 zTitleExpr = db_get("ticket-title-expr", "title");
1581 zStatusColumn = db_get("ticket-status-column", "status");
1582 }
1583 zTitle = db_text("unknown",
1584 "SELECT %s FROM ticket WHERE tkt_uuid='%s'",
1585 zTitleExpr, pManifest->zTicketUuid
1586 );
1587 if( !isNew ){
1588 for(i=0; i<pManifest->nField; i++){
@@ -1599,11 +1599,11 @@
1599 pManifest->nField-1, pManifest->nField==2 ? "" : "s");
1600 }
1601 blob_appendf(&brief, "%h ticket [%.10s].",
1602 zNewStatus, pManifest->zTicketUuid);
1603 }else{
1604 zNewStatus = db_text("unknown",
1605 "SELECT %s FROM ticket WHERE tkt_uuid='%s'",
1606 zStatusColumn, pManifest->zTicketUuid
1607 );
1608 blob_appendf(&comment, "Ticket [%.10s] <i>%h</i> status still %h with "
1609 "%d other change%s",
@@ -1661,11 +1661,11 @@
1661 **
1662 ** If the input is a control artifact, then make appropriate entries
1663 ** in the auxiliary tables of the database in order to crosslink the
1664 ** artifact.
1665 **
1666 ** If global variable g.xlinkClusterOnly is true, then ignore all
1667 ** control artifacts other than clusters.
1668 **
1669 ** This routine always resets the pContent blob before returning.
1670 **
1671 ** Historical note: This routine original processed manifests only.
@@ -1744,11 +1744,11 @@
1744 " %d,%Q,%Q,"
1745 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d AND tagtype>0),"
1746 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d),"
1747 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d),%.17g);",
1748 TAG_DATE, rid, p->rDate,
1749 rid, p->zUser, p->zComment,
1750 TAG_BGCOLOR, rid,
1751 TAG_USER, rid,
1752 TAG_COMMENT, rid, p->rDate
1753 );
1754 zCom = db_text(0, "SELECT coalesce(ecomment, comment) FROM event"
@@ -1802,11 +1802,11 @@
1802 case '*': type = 2; break; /* Propagate to descendants */
1803 default:
1804 fossil_error(1, "unknown tag type in manifest: %s", p->aTag);
1805 return 0;
1806 }
1807 tag_insert(&p->aTag[i].zName[1], type, p->aTag[i].zValue,
1808 rid, p->rDate, tid);
1809 }
1810 }
1811 if( parentid ){
1812 tag_propagate_all(parentid);
@@ -1843,11 +1843,11 @@
1843 " bgcolor,euser,ecomment)"
1844 "VALUES('w',%.17g,%d,%Q,%Q,"
1845 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d AND tagtype>1),"
1846 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d),"
1847 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
1848 p->rDate, rid, p->zUser, zComment,
1849 TAG_BGCOLOR, rid,
1850 TAG_BGCOLOR, rid,
1851 TAG_USER, rid,
1852 TAG_COMMENT, rid
1853 );
@@ -1893,11 +1893,11 @@
1893 }else{
1894 db_multi_exec(
1895 "REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)"
1896 "VALUES('e',%.17g,%d,%d,%Q,%Q,"
1897 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
1898 p->rEventDate, rid, tagid, p->zUser, p->zComment,
1899 TAG_BGCOLOR, rid
1900 );
1901 }
1902 }
1903 if( p->type==CFTYPE_TICKET ){
@@ -1925,11 +1925,11 @@
1925 " WHERE target=%Q AND filename=%Q",
1926 p->zAttachTarget, p->zAttachName,
1927 p->zAttachTarget, p->zAttachName
1928 );
1929 if( strlen(p->zAttachTarget)!=UUID_SIZE
1930 || !validate16(p->zAttachTarget, UUID_SIZE)
1931 ){
1932 char *zComment;
1933 if( p->zAttachSrc && p->zAttachSrc[0] ){
1934 zComment = mprintf(
1935 "Add attachment [/artifact/%S|%h] to wiki page [%h]",
1936
--- src/manifest.c
+++ src/manifest.c
@@ -51,11 +51,11 @@
51 #define MC_PERMIT_HOOKS 1 /* permit hooks to execute */
52
53 /*
54 ** A single F-card within a manifest
55 */
56 struct ManifestFile {
57 char *zName; /* Name of a file */
58 char *zUuid; /* UUID of the file */
59 char *zPerm; /* File permissions */
60 char *zPrior; /* Prior name if the name was changed */
61 };
@@ -89,11 +89,11 @@
89 ManifestFile *aFile; /* One entry for each F-card */
90 int nParent; /* Number of parents. */
91 int nParentAlloc; /* Slots allocated in azParent[] */
92 char **azParent; /* UUIDs of parents. One for each P card argument */
93 int nCherrypick; /* Number of entries in aCherrypick[] */
94 struct {
95 char *zCPTarget; /* UUID of cherry-picked version w/ +|- prefix */
96 char *zCPBase; /* UUID of cherry-pick baseline. NULL for singletons */
97 } *aCherrypick;
98 int nCChild; /* Number of cluster children */
99 int nCChildAlloc; /* Number of closts allocated in azCChild[] */
@@ -105,11 +105,11 @@
105 char *zUuid; /* UUID that the tag is applied to */
106 char *zValue; /* Value if the tag is really a property */
107 } *aTag; /* One for each T card */
108 int nField; /* Number of J cards */
109 int nFieldAlloc; /* Slots allocated in aField[] */
110 struct {
111 char *zName; /* Key or field name */
112 char *zValue; /* Value of the field */
113 } *aField; /* One for each J card */
114 };
115 #endif
@@ -251,11 +251,11 @@
251 ** Verify the Z-card checksum on the artifact, if there is such a
252 ** checksum. Return 0 if there is no Z-card. Return 1 if the Z-card
253 ** exists and is correct. Return 2 if the Z-card exists and has the wrong
254 ** value.
255 **
256 ** 0123456789 123456789 123456789 123456789
257 ** Z aea84f4f863865a8d59d0384e4d2a41c
258 */
259 static int verify_z_card(const char *z, int n){
260 if( n<35 ) return 0;
261 if( z[n-35]!='Z' || z[n-34]!=' ' ) return 0;
@@ -435,11 +435,11 @@
435 char *zName, *zTarget, *zSrc;
436 int nTarget = 0, nSrc = 0;
437 zName = next_token(&x, 0);
438 zTarget = next_token(&x, &nTarget);
439 zSrc = next_token(&x, &nSrc);
440 if( zName==0 || zTarget==0 ) goto manifest_syntax_error;
441 if( p->zAttachName!=0 ) goto manifest_syntax_error;
442 defossilize(zName);
443 if( !file_is_simple_pathname(zName, 0) ){
444 SYNTAX("invalid filename on A-card");
445 }
@@ -504,11 +504,11 @@
504 }
505
506 /*
507 ** E <timestamp> <uuid>
508 **
509 ** An "event" card that contains the timestamp of the event in the
510 ** format YYYY-MM-DDtHH:MM:SS and a unique identifier for the event.
511 ** The event timestamp is distinct from the D timestamp. The D
512 ** timestamp is when the artifact was created whereas the E timestamp
513 ** is when the specific event is said to occur.
514 */
@@ -551,11 +551,11 @@
551 SYNTAX("F-card old filename is not a simple path");
552 }
553 }
554 if( p->nFile>=p->nFileAlloc ){
555 p->nFileAlloc = p->nFileAlloc*2 + 10;
556 p->aFile = fossil_realloc(p->aFile,
557 p->nFileAlloc*sizeof(p->aFile[0]) );
558 }
559 i = p->nFile++;
560 p->aFile[i].zName = zName;
561 p->aFile[i].zUuid = zUuid;
@@ -743,11 +743,11 @@
743 ** singleton tag, "*" to create a propagating tag, or "-" to create
744 ** anti-tag that undoes a prior "+" or blocks propagation of of
745 ** a "*".
746 **
747 ** The tag is applied to <uuid>. If <uuid> is "*" then the tag is
748 ** applied to the current manifest. If <value> is provided then
749 ** the tag is really a property with the given value.
750 **
751 ** Tags are not allowed in clusters. Multiple T lines are allowed.
752 */
753 case 'T': {
@@ -1050,11 +1050,11 @@
1050 db_multi_exec(
1051 "INSERT OR IGNORE INTO orphan(rid, baseline) VALUES(%d,%d)",
1052 p->rid, rid
1053 );
1054 return 1;
1055 }
1056 fossil_fatal("cannot access baseline manifest %S", p->zBaseline);
1057 }
1058 }
1059 return 0;
1060 }
@@ -1075,11 +1075,11 @@
1075 **
1076 ** Return NULL for end-of-records or if there is an error. If an error
1077 ** occurs and pErr!=0 then store 1 in *pErr.
1078 */
1079 ManifestFile *manifest_file_next(
1080 Manifest *p,
1081 int *pErr
1082 ){
1083 ManifestFile *pOut = 0;
1084 if( pErr ) *pErr = 0;
1085 if( p->pBaseline==0 ){
@@ -1219,11 +1219,11 @@
1219 content_deltify(pid, fid, 0);
1220 }
1221 }
1222
1223 /*
1224 ** Do a binary search to find a file in the p->aFile[] array.
1225 **
1226 ** As an optimization, guess that the file we seek is at index p->iFile.
1227 ** That will usually be the case. If it is not found there, then do the
1228 ** actual binary search.
1229 **
@@ -1263,18 +1263,18 @@
1263 /*
1264 ** Locate a file named zName in the aFile[] array of the given manifest.
1265 ** Return a pointer to the appropriate ManifestFile object. Return NULL
1266 ** if not found.
1267 **
1268 ** This routine works even if p is a delta-manifest. The pointer
1269 ** returned might be to the baseline.
1270 **
1271 ** We assume that filenames are in sorted order and use a binary search.
1272 */
1273 ManifestFile *manifest_file_seek(Manifest *p, const char *zName){
1274 ManifestFile *pFile;
1275
1276 pFile = manifest_file_seek_base(p, zName);
1277 if( pFile && pFile->zUuid==0 ) return 0;
1278 if( pFile==0 && p->zBaseline ){
1279 fetch_baseline(p, 1);
1280 pFile = manifest_file_seek_base(p->pBaseline, zName);
@@ -1362,15 +1362,15 @@
1362 return;
1363 }
1364 isPublic = !content_is_private(cid);
1365
1366 /* Try to make the parent manifest a delta from the child, if that
1367 ** is an appropriate thing to do. For a new baseline, make the
1368 ** previous baseline a delta from the current baseline.
1369 */
1370 if( (pParent->zBaseline==0)==(pChild->zBaseline==0) ){
1371 content_deltify(pid, cid, 0);
1372 }else if( pChild->zBaseline==0 && pParent->zBaseline!=0 ){
1373 content_deltify(pParent->pBaseline->rid, cid, 0);
1374 }
1375
1376 /* Remember all children less than a few seconds younger than their parent,
@@ -1385,11 +1385,11 @@
1385 );
1386 }
1387
1388 /* First look at all files in pChild, ignoring its baseline. This
1389 ** is where most of the changes will be found.
1390 */
1391 for(i=0, pChildFile=pChild->aFile; i<pChild->nFile; i++, pChildFile++){
1392 int mperm = manifest_file_mperm(pChildFile);
1393 if( pChildFile->zPrior ){
1394 pParentFile = manifest_file_seek(pParent, pChildFile->zPrior);
1395 if( pParentFile ){
@@ -1450,11 +1450,11 @@
1450 ** but are missing from pChild and mark them as having been deleted. */
1451 manifest_file_rewind(pParent);
1452 while( (pParentFile = manifest_file_next(pParent,0))!=0 ){
1453 pChildFile = manifest_file_seek(pChild, pParentFile->zName);
1454 if( pChildFile==0 && pParentFile->zUuid!=0 ){
1455 add_one_mlink(cid, pParentFile->zUuid, 0, pParentFile->zName, 0,
1456 isPublic, 0);
1457 }
1458 }
1459 }
1460 manifest_cache_insert(*ppOther);
@@ -1578,11 +1578,11 @@
1578 if( once ){
1579 once = 0;
1580 zTitleExpr = db_get("ticket-title-expr", "title");
1581 zStatusColumn = db_get("ticket-status-column", "status");
1582 }
1583 zTitle = db_text("unknown",
1584 "SELECT %s FROM ticket WHERE tkt_uuid='%s'",
1585 zTitleExpr, pManifest->zTicketUuid
1586 );
1587 if( !isNew ){
1588 for(i=0; i<pManifest->nField; i++){
@@ -1599,11 +1599,11 @@
1599 pManifest->nField-1, pManifest->nField==2 ? "" : "s");
1600 }
1601 blob_appendf(&brief, "%h ticket [%.10s].",
1602 zNewStatus, pManifest->zTicketUuid);
1603 }else{
1604 zNewStatus = db_text("unknown",
1605 "SELECT %s FROM ticket WHERE tkt_uuid='%s'",
1606 zStatusColumn, pManifest->zTicketUuid
1607 );
1608 blob_appendf(&comment, "Ticket [%.10s] <i>%h</i> status still %h with "
1609 "%d other change%s",
@@ -1661,11 +1661,11 @@
1661 **
1662 ** If the input is a control artifact, then make appropriate entries
1663 ** in the auxiliary tables of the database in order to crosslink the
1664 ** artifact.
1665 **
1666 ** If global variable g.xlinkClusterOnly is true, then ignore all
1667 ** control artifacts other than clusters.
1668 **
1669 ** This routine always resets the pContent blob before returning.
1670 **
1671 ** Historical note: This routine original processed manifests only.
@@ -1744,11 +1744,11 @@
1744 " %d,%Q,%Q,"
1745 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d AND tagtype>0),"
1746 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d),"
1747 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d),%.17g);",
1748 TAG_DATE, rid, p->rDate,
1749 rid, p->zUser, p->zComment,
1750 TAG_BGCOLOR, rid,
1751 TAG_USER, rid,
1752 TAG_COMMENT, rid, p->rDate
1753 );
1754 zCom = db_text(0, "SELECT coalesce(ecomment, comment) FROM event"
@@ -1802,11 +1802,11 @@
1802 case '*': type = 2; break; /* Propagate to descendants */
1803 default:
1804 fossil_error(1, "unknown tag type in manifest: %s", p->aTag);
1805 return 0;
1806 }
1807 tag_insert(&p->aTag[i].zName[1], type, p->aTag[i].zValue,
1808 rid, p->rDate, tid);
1809 }
1810 }
1811 if( parentid ){
1812 tag_propagate_all(parentid);
@@ -1843,11 +1843,11 @@
1843 " bgcolor,euser,ecomment)"
1844 "VALUES('w',%.17g,%d,%Q,%Q,"
1845 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d AND tagtype>1),"
1846 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d),"
1847 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
1848 p->rDate, rid, p->zUser, zComment,
1849 TAG_BGCOLOR, rid,
1850 TAG_BGCOLOR, rid,
1851 TAG_USER, rid,
1852 TAG_COMMENT, rid
1853 );
@@ -1893,11 +1893,11 @@
1893 }else{
1894 db_multi_exec(
1895 "REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)"
1896 "VALUES('e',%.17g,%d,%d,%Q,%Q,"
1897 " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));",
1898 p->rEventDate, rid, tagid, p->zUser, p->zComment,
1899 TAG_BGCOLOR, rid
1900 );
1901 }
1902 }
1903 if( p->type==CFTYPE_TICKET ){
@@ -1925,11 +1925,11 @@
1925 " WHERE target=%Q AND filename=%Q",
1926 p->zAttachTarget, p->zAttachName,
1927 p->zAttachTarget, p->zAttachName
1928 );
1929 if( strlen(p->zAttachTarget)!=UUID_SIZE
1930 || !validate16(p->zAttachTarget, UUID_SIZE)
1931 ){
1932 char *zComment;
1933 if( p->zAttachSrc && p->zAttachSrc[0] ){
1934 zComment = mprintf(
1935 "Add attachment [/artifact/%S|%h] to wiki page [%h]",
1936
+6 -6
--- src/markdown.c
+++ src/markdown.c
@@ -161,11 +161,11 @@
161161
};
162162
163163
164164
/* html_tag -- structure for quick HTML tag search (inspired from discount) */
165165
struct html_tag {
166
- char *text;
166
+ const char *text;
167167
int size;
168168
};
169169
170170
171171
@@ -172,11 +172,11 @@
172172
/********************
173173
* GLOBAL VARIABLES *
174174
********************/
175175
176176
/* block_tags -- recognised block tags, sorted by cmp_html_tag */
177
-static struct html_tag block_tags[] = {
177
+static const struct html_tag block_tags[] = {
178178
{ "p", 1 },
179179
{ "dl", 2 },
180180
{ "h1", 2 },
181181
{ "h2", 2 },
182182
{ "h3", 2 },
@@ -276,11 +276,11 @@
276276
return fossil_strnicmp(hta->text, htb->text, hta->size);
277277
}
278278
279279
280280
/* find_block_tag -- returns the current block tag */
281
-static struct html_tag *find_block_tag(char *data, size_t size){
281
+static const struct html_tag *find_block_tag(const char *data, size_t size){
282282
size_t i = 0;
283283
struct html_tag key;
284284
285285
/* looking for the word end */
286286
while( i<size
@@ -1070,11 +1070,11 @@
10701070
/*********************************
10711071
* BLOCK-LEVEL PARSING FUNCTIONS *
10721072
*********************************/
10731073
10741074
/* is_empty -- returns the line length when it is empty, 0 otherwise */
1075
-static size_t is_empty(char *data, size_t size){
1075
+static size_t is_empty(const char *data, size_t size){
10761076
size_t i;
10771077
for(i=0; i<size && data[i]!='\n'; i++){
10781078
if( data[i]!=' ' && data[i]!='\t' ) return 0;
10791079
}
10801080
return i+1;
@@ -1631,11 +1631,11 @@
16311631
}
16321632
16331633
16341634
/* htmlblock_end -- checking end of HTML block : </tag>[ \t]*\n[ \t*]\n */
16351635
/* returns the length on match, 0 otherwise */
1636
-static size_t htmlblock_end(struct html_tag *tag, char *data, size_t size){
1636
+static size_t htmlblock_end(const struct html_tag *tag, const char *data, size_t size){
16371637
size_t i, w;
16381638
16391639
/* assuming data[0]=='<' && data[1]=='/' already tested */
16401640
16411641
/* checking tag is a match */
@@ -1668,11 +1668,11 @@
16681668
struct render *rndr,
16691669
char *data,
16701670
size_t size
16711671
){
16721672
size_t i, j = 0;
1673
- struct html_tag *curtag;
1673
+ const struct html_tag *curtag;
16741674
int found;
16751675
size_t work_size = 0;
16761676
struct Blob work = BLOB_INITIALIZER;
16771677
16781678
/* identification of the opening tag */
16791679
--- src/markdown.c
+++ src/markdown.c
@@ -161,11 +161,11 @@
161 };
162
163
164 /* html_tag -- structure for quick HTML tag search (inspired from discount) */
165 struct html_tag {
166 char *text;
167 int size;
168 };
169
170
171
@@ -172,11 +172,11 @@
172 /********************
173 * GLOBAL VARIABLES *
174 ********************/
175
176 /* block_tags -- recognised block tags, sorted by cmp_html_tag */
177 static struct html_tag block_tags[] = {
178 { "p", 1 },
179 { "dl", 2 },
180 { "h1", 2 },
181 { "h2", 2 },
182 { "h3", 2 },
@@ -276,11 +276,11 @@
276 return fossil_strnicmp(hta->text, htb->text, hta->size);
277 }
278
279
280 /* find_block_tag -- returns the current block tag */
281 static struct html_tag *find_block_tag(char *data, size_t size){
282 size_t i = 0;
283 struct html_tag key;
284
285 /* looking for the word end */
286 while( i<size
@@ -1070,11 +1070,11 @@
1070 /*********************************
1071 * BLOCK-LEVEL PARSING FUNCTIONS *
1072 *********************************/
1073
1074 /* is_empty -- returns the line length when it is empty, 0 otherwise */
1075 static size_t is_empty(char *data, size_t size){
1076 size_t i;
1077 for(i=0; i<size && data[i]!='\n'; i++){
1078 if( data[i]!=' ' && data[i]!='\t' ) return 0;
1079 }
1080 return i+1;
@@ -1631,11 +1631,11 @@
1631 }
1632
1633
1634 /* htmlblock_end -- checking end of HTML block : </tag>[ \t]*\n[ \t*]\n */
1635 /* returns the length on match, 0 otherwise */
1636 static size_t htmlblock_end(struct html_tag *tag, char *data, size_t size){
1637 size_t i, w;
1638
1639 /* assuming data[0]=='<' && data[1]=='/' already tested */
1640
1641 /* checking tag is a match */
@@ -1668,11 +1668,11 @@
1668 struct render *rndr,
1669 char *data,
1670 size_t size
1671 ){
1672 size_t i, j = 0;
1673 struct html_tag *curtag;
1674 int found;
1675 size_t work_size = 0;
1676 struct Blob work = BLOB_INITIALIZER;
1677
1678 /* identification of the opening tag */
1679
--- src/markdown.c
+++ src/markdown.c
@@ -161,11 +161,11 @@
161 };
162
163
164 /* html_tag -- structure for quick HTML tag search (inspired from discount) */
165 struct html_tag {
166 const char *text;
167 int size;
168 };
169
170
171
@@ -172,11 +172,11 @@
172 /********************
173 * GLOBAL VARIABLES *
174 ********************/
175
176 /* block_tags -- recognised block tags, sorted by cmp_html_tag */
177 static const struct html_tag block_tags[] = {
178 { "p", 1 },
179 { "dl", 2 },
180 { "h1", 2 },
181 { "h2", 2 },
182 { "h3", 2 },
@@ -276,11 +276,11 @@
276 return fossil_strnicmp(hta->text, htb->text, hta->size);
277 }
278
279
280 /* find_block_tag -- returns the current block tag */
281 static const struct html_tag *find_block_tag(const char *data, size_t size){
282 size_t i = 0;
283 struct html_tag key;
284
285 /* looking for the word end */
286 while( i<size
@@ -1070,11 +1070,11 @@
1070 /*********************************
1071 * BLOCK-LEVEL PARSING FUNCTIONS *
1072 *********************************/
1073
1074 /* is_empty -- returns the line length when it is empty, 0 otherwise */
1075 static size_t is_empty(const char *data, size_t size){
1076 size_t i;
1077 for(i=0; i<size && data[i]!='\n'; i++){
1078 if( data[i]!=' ' && data[i]!='\t' ) return 0;
1079 }
1080 return i+1;
@@ -1631,11 +1631,11 @@
1631 }
1632
1633
1634 /* htmlblock_end -- checking end of HTML block : </tag>[ \t]*\n[ \t*]\n */
1635 /* returns the length on match, 0 otherwise */
1636 static size_t htmlblock_end(const struct html_tag *tag, const char *data, size_t size){
1637 size_t i, w;
1638
1639 /* assuming data[0]=='<' && data[1]=='/' already tested */
1640
1641 /* checking tag is a match */
@@ -1668,11 +1668,11 @@
1668 struct render *rndr,
1669 char *data,
1670 size_t size
1671 ){
1672 size_t i, j = 0;
1673 const struct html_tag *curtag;
1674 int found;
1675 size_t work_size = 0;
1676 struct Blob work = BLOB_INITIALIZER;
1677
1678 /* identification of the opening tag */
1679
+3 -11
--- src/merge.c
+++ src/merge.c
@@ -258,21 +258,13 @@
258258
if( !forceFlag && mid==pid ){
259259
fossil_print("Merge skipped because it is a no-op. "
260260
" Use --force to override.\n");
261261
return;
262262
}
263
- if( integrateFlag ){
264
- if( db_exists("SELECT 1 FROM vmerge WHERE id=-4")) {
265
- /* Fossil earlier than [55cacfcace] cannot handle this,
266
- * therefore disallow it. */
267
- fossil_fatal("Integration of another branch already in progress."
268
- " Commit or Undo needed first", g.argv[2]);
269
- }
270
- if( !is_a_leaf(mid) ){
271
- fossil_warning("ignoring --integrate: %s is not a leaf", g.argv[2]);
272
- integrateFlag = 0;
273
- }
263
+ if( integrateFlag && !is_a_leaf(mid)){
264
+ fossil_warning("ignoring --integrate: %s is not a leaf", g.argv[2]);
265
+ integrateFlag = 0;
274266
}
275267
if( verboseFlag ){
276268
print_checkin_description(mid, 12, integrateFlag?"integrate:":"merge-from:");
277269
print_checkin_description(pid, 12, "baseline:");
278270
}
279271
--- src/merge.c
+++ src/merge.c
@@ -258,21 +258,13 @@
258 if( !forceFlag && mid==pid ){
259 fossil_print("Merge skipped because it is a no-op. "
260 " Use --force to override.\n");
261 return;
262 }
263 if( integrateFlag ){
264 if( db_exists("SELECT 1 FROM vmerge WHERE id=-4")) {
265 /* Fossil earlier than [55cacfcace] cannot handle this,
266 * therefore disallow it. */
267 fossil_fatal("Integration of another branch already in progress."
268 " Commit or Undo needed first", g.argv[2]);
269 }
270 if( !is_a_leaf(mid) ){
271 fossil_warning("ignoring --integrate: %s is not a leaf", g.argv[2]);
272 integrateFlag = 0;
273 }
274 }
275 if( verboseFlag ){
276 print_checkin_description(mid, 12, integrateFlag?"integrate:":"merge-from:");
277 print_checkin_description(pid, 12, "baseline:");
278 }
279
--- src/merge.c
+++ src/merge.c
@@ -258,21 +258,13 @@
258 if( !forceFlag && mid==pid ){
259 fossil_print("Merge skipped because it is a no-op. "
260 " Use --force to override.\n");
261 return;
262 }
263 if( integrateFlag && !is_a_leaf(mid)){
264 fossil_warning("ignoring --integrate: %s is not a leaf", g.argv[2]);
265 integrateFlag = 0;
 
 
 
 
 
 
 
 
266 }
267 if( verboseFlag ){
268 print_checkin_description(mid, 12, integrateFlag?"integrate:":"merge-from:");
269 print_checkin_description(pid, 12, "baseline:");
270 }
271
+1 -1
--- src/merge3.c
+++ src/merge3.c
@@ -364,11 +364,11 @@
364364
**
365365
** fossil 3-way-merge Xbase.c Xlocal.c Xup.c Xlocal.c
366366
** cp Xup.c Xbase.c
367367
** # Verify that everything still works
368368
** fossil commit
369
-**
369
+**
370370
*/
371371
void delta_3waymerge_cmd(void){
372372
Blob pivot, v1, v2, merged;
373373
if( g.argc!=6 ){
374374
usage("PIVOT V1 V2 MERGED");
375375
--- src/merge3.c
+++ src/merge3.c
@@ -364,11 +364,11 @@
364 **
365 ** fossil 3-way-merge Xbase.c Xlocal.c Xup.c Xlocal.c
366 ** cp Xup.c Xbase.c
367 ** # Verify that everything still works
368 ** fossil commit
369 **
370 */
371 void delta_3waymerge_cmd(void){
372 Blob pivot, v1, v2, merged;
373 if( g.argc!=6 ){
374 usage("PIVOT V1 V2 MERGED");
375
--- src/merge3.c
+++ src/merge3.c
@@ -364,11 +364,11 @@
364 **
365 ** fossil 3-way-merge Xbase.c Xlocal.c Xup.c Xlocal.c
366 ** cp Xup.c Xbase.c
367 ** # Verify that everything still works
368 ** fossil commit
369 **
370 */
371 void delta_3waymerge_cmd(void){
372 Blob pivot, v1, v2, merged;
373 if( g.argc!=6 ){
374 usage("PIVOT V1 V2 MERGED");
375
+1 -1
--- src/moderate.c
+++ src/moderate.c
@@ -64,11 +64,11 @@
6464
6565
/*
6666
** Check to see if the object identified by RID is used for anything.
6767
*/
6868
static int object_used(int rid){
69
- static const char *aTabField[] = {
69
+ static const char *const aTabField[] = {
7070
"modreq", "attachRid",
7171
"mlink", "mid",
7272
"mlink", "fid",
7373
"tagxref", "srcid",
7474
"tagxref", "rid",
7575
--- src/moderate.c
+++ src/moderate.c
@@ -64,11 +64,11 @@
64
65 /*
66 ** Check to see if the object identified by RID is used for anything.
67 */
68 static int object_used(int rid){
69 static const char *aTabField[] = {
70 "modreq", "attachRid",
71 "mlink", "mid",
72 "mlink", "fid",
73 "tagxref", "srcid",
74 "tagxref", "rid",
75
--- src/moderate.c
+++ src/moderate.c
@@ -64,11 +64,11 @@
64
65 /*
66 ** Check to see if the object identified by RID is used for anything.
67 */
68 static int object_used(int rid){
69 static const char *const aTabField[] = {
70 "modreq", "attachRid",
71 "mlink", "mid",
72 "mlink", "fid",
73 "tagxref", "srcid",
74 "tagxref", "rid",
75
+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
+2 -2
--- src/printf.c
+++ src/printf.c
@@ -859,11 +859,11 @@
859859
fwrite(z, 1, n, toStdErr ? stderr : stdout);
860860
fflush(toStdErr ? stderr : stdout);
861861
}
862862
863863
/*
864
-** Force the standard output cursor to move to the beginning
864
+** Force the standard output cursor to move to the beginning
865865
** of a line, if it is not there already.
866866
*/
867867
void fossil_force_newline(void){
868868
if( g.cgiOutput==0 && stdoutAtBOL==0 ) fossil_puts("\n", 0);
869869
}
@@ -918,11 +918,11 @@
918918
time_t now;
919919
FILE *out;
920920
const char *z;
921921
int i;
922922
va_list ap;
923
- static const char *azEnv[] = { "HTTP_HOST", "HTTP_USER_AGENT",
923
+ static const char *const azEnv[] = { "HTTP_HOST", "HTTP_USER_AGENT",
924924
"PATH_INFO", "QUERY_STRING", "REMOTE_ADDR", "REQUEST_METHOD",
925925
"REQUEST_URI", "SCRIPT_NAME" };
926926
if( g.zErrlog==0 ) return;
927927
out = fossil_fopen(g.zErrlog, "a");
928928
if( out==0 ) return;
929929
--- src/printf.c
+++ src/printf.c
@@ -859,11 +859,11 @@
859 fwrite(z, 1, n, toStdErr ? stderr : stdout);
860 fflush(toStdErr ? stderr : stdout);
861 }
862
863 /*
864 ** Force the standard output cursor to move to the beginning
865 ** of a line, if it is not there already.
866 */
867 void fossil_force_newline(void){
868 if( g.cgiOutput==0 && stdoutAtBOL==0 ) fossil_puts("\n", 0);
869 }
@@ -918,11 +918,11 @@
918 time_t now;
919 FILE *out;
920 const char *z;
921 int i;
922 va_list ap;
923 static const char *azEnv[] = { "HTTP_HOST", "HTTP_USER_AGENT",
924 "PATH_INFO", "QUERY_STRING", "REMOTE_ADDR", "REQUEST_METHOD",
925 "REQUEST_URI", "SCRIPT_NAME" };
926 if( g.zErrlog==0 ) return;
927 out = fossil_fopen(g.zErrlog, "a");
928 if( out==0 ) return;
929
--- src/printf.c
+++ src/printf.c
@@ -859,11 +859,11 @@
859 fwrite(z, 1, n, toStdErr ? stderr : stdout);
860 fflush(toStdErr ? stderr : stdout);
861 }
862
863 /*
864 ** Force the standard output cursor to move to the beginning
865 ** of a line, if it is not there already.
866 */
867 void fossil_force_newline(void){
868 if( g.cgiOutput==0 && stdoutAtBOL==0 ) fossil_puts("\n", 0);
869 }
@@ -918,11 +918,11 @@
918 time_t now;
919 FILE *out;
920 const char *z;
921 int i;
922 va_list ap;
923 static const char *const azEnv[] = { "HTTP_HOST", "HTTP_USER_AGENT",
924 "PATH_INFO", "QUERY_STRING", "REMOTE_ADDR", "REQUEST_METHOD",
925 "REQUEST_URI", "SCRIPT_NAME" };
926 if( g.zErrlog==0 ) return;
927 out = fossil_fopen(g.zErrlog, "a");
928 if( out==0 ) return;
929
+26 -25
--- src/rebuild.c
+++ src/rebuild.c
@@ -47,18 +47,18 @@
4747
@ mtime INTEGER, -- When added. Seconds since 1970
4848
@ scom TEXT -- Optional text explaining why the shun occurred
4949
@ );
5050
@
5151
@ -- Artifacts that should not be pushed are stored in the "private"
52
-@ -- table.
52
+@ -- table.
5353
@ --
5454
@ CREATE TABLE IF NOT EXISTS private(rid INTEGER PRIMARY KEY);
5555
@
5656
@ -- Some ticket content (such as the originators email address or contact
5757
@ -- information) needs to be obscured to protect privacy. This is achieved
5858
@ -- by storing an SHA1 hash of the content. For display, the hash is
59
-@ -- mapped back into the original text using this table.
59
+@ -- mapped back into the original text using this table.
6060
@ --
6161
@ -- This table contains sensitive information and should not be shared
6262
@ -- with unauthorized users.
6363
@ --
6464
@ CREATE TABLE IF NOT EXISTS concealed(
@@ -153,11 +153,11 @@
153153
db_multi_exec(
154154
"ALTER TABLE concealed ADD COLUMN mtime INTEGER;"
155155
"UPDATE concealed SET mtime=now();"
156156
);
157157
}
158
-}
158
+}
159159
160160
/*
161161
** Variables used to store state information about an on-going "rebuild"
162162
** or "deconstruct".
163163
*/
@@ -227,11 +227,11 @@
227227
if( size!=blob_size(pBase) ){
228228
db_multi_exec(
229229
"UPDATE blob SET size=%d WHERE rid=%d", blob_size(pBase), rid
230230
);
231231
}
232
-
232
+
233233
/* Find all children of artifact rid */
234234
db_static_prepare(&q1, "SELECT rid FROM delta WHERE srcid=:rid");
235235
db_bind_int(&q1, ":rid", rid);
236236
bag_init(&children);
237237
while( db_step(&q1)==SQLITE_ROW ){
@@ -240,11 +240,11 @@
240240
bag_insert(&children, cid);
241241
}
242242
}
243243
nChild = bag_count(&children);
244244
db_reset(&q1);
245
-
245
+
246246
/* Crosslink the artifact */
247247
if( nChild==0 ){
248248
pUse = pBase;
249249
}else{
250250
blob_copy(&copy, pBase);
@@ -262,11 +262,11 @@
262262
free(zUuid);
263263
blob_reset(pUse);
264264
}
265265
assert( blob_is_reset(pUse) );
266266
rebuild_step_done(rid);
267
-
267
+
268268
/* Call all children recursively */
269269
rid = 0;
270270
for(cid=bag_first(&children), i=1; cid; cid=bag_next(&children, cid), i++){
271271
static Stmt q2;
272272
int sz;
@@ -626,11 +626,11 @@
626626
if( activateWal ){
627627
db_multi_exec("PRAGMA journal_mode=WAL;");
628628
}
629629
}
630630
if( showStats ){
631
- static struct { int idx; const char *zLabel; } aStat[] = {
631
+ static const struct { int idx; const char *zLabel; } aStat[] = {
632632
{ CFTYPE_ANY, "Artifacts:" },
633633
{ CFTYPE_MANIFEST, "Manifests:" },
634634
{ CFTYPE_CLUSTER, "Clusters:" },
635635
{ CFTYPE_CONTROL, "Tags:" },
636636
{ CFTYPE_WIKI, "Wikis:" },
@@ -687,11 +687,11 @@
687687
db_close(1);
688688
db_open_repository(g.zRepositoryName);
689689
}
690690
db_begin_transaction();
691691
create_cluster();
692
- db_end_transaction(0);
692
+ db_end_transaction(0);
693693
}
694694
695695
/*
696696
** COMMAND: test-clusters
697697
**
@@ -700,11 +700,11 @@
700700
*/
701701
void test_clusters_cmd(void){
702702
Bag pending;
703703
Stmt q;
704704
int n;
705
-
705
+
706706
db_find_and_open_repository(0, 2);
707707
bag_init(&pending);
708708
db_multi_exec(
709709
"CREATE TEMP TABLE xdone(x INTEGER PRIMARY KEY);"
710710
"INSERT INTO xdone SELECT rid FROM unclustered;"
@@ -722,11 +722,11 @@
722722
db_finalize(&q);
723723
while( bag_count(&pending)>0 ){
724724
Manifest *p;
725725
int rid = bag_first(&pending);
726726
int i;
727
-
727
+
728728
bag_remove(&pending, rid);
729729
p = manifest_get(rid, CFTYPE_CLUSTER, 0);
730730
if( p==0 ){
731731
fossil_fatal("bad cluster: rid=%d", rid);
732732
}
@@ -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]);
@@ -922,11 +923,11 @@
922923
/* Skip the verify_before_commit() step on a reconstruct. Most artifacts
923924
** will have been changed and verification therefore takes a really, really
924925
** long time.
925926
*/
926927
verify_cancel();
927
-
928
+
928929
db_end_transaction(0);
929930
fossil_print("project-id: %s\n", db_get("project-code", 0));
930931
fossil_print("server-id: %s\n", db_get("server-code", 0));
931932
zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
932933
fossil_print("admin-user: %s (initial password is \"%s\")\n", g.zLogin, zPassword);
@@ -942,11 +943,11 @@
942943
** writes all artifacts to the file system. The DESTINATION directory
943944
** will be populated with subdirectories AA and files AA/BBBBBBBBB.., where
944945
** AABBBBBBBBB.. is the 40 character artifact ID, AA the first 2 characters.
945946
** If -L|--prefixlength is given, the length (default 2) of the directory
946947
** prefix can be set to 0,1,..,9 characters.
947
-**
948
+**
948949
** Options:
949950
** -R|--repository REPOSITORY deconstruct given REPOSITORY
950951
** -L|--prefixlength N set the length of the names of the DESTINATION
951952
** subdirectories to N
952953
** --private Include private artifacts.
953954
--- src/rebuild.c
+++ src/rebuild.c
@@ -47,18 +47,18 @@
47 @ mtime INTEGER, -- When added. Seconds since 1970
48 @ scom TEXT -- Optional text explaining why the shun occurred
49 @ );
50 @
51 @ -- Artifacts that should not be pushed are stored in the "private"
52 @ -- table.
53 @ --
54 @ CREATE TABLE IF NOT EXISTS private(rid INTEGER PRIMARY KEY);
55 @
56 @ -- Some ticket content (such as the originators email address or contact
57 @ -- information) needs to be obscured to protect privacy. This is achieved
58 @ -- by storing an SHA1 hash of the content. For display, the hash is
59 @ -- mapped back into the original text using this table.
60 @ --
61 @ -- This table contains sensitive information and should not be shared
62 @ -- with unauthorized users.
63 @ --
64 @ CREATE TABLE IF NOT EXISTS concealed(
@@ -153,11 +153,11 @@
153 db_multi_exec(
154 "ALTER TABLE concealed ADD COLUMN mtime INTEGER;"
155 "UPDATE concealed SET mtime=now();"
156 );
157 }
158 }
159
160 /*
161 ** Variables used to store state information about an on-going "rebuild"
162 ** or "deconstruct".
163 */
@@ -227,11 +227,11 @@
227 if( size!=blob_size(pBase) ){
228 db_multi_exec(
229 "UPDATE blob SET size=%d WHERE rid=%d", blob_size(pBase), rid
230 );
231 }
232
233 /* Find all children of artifact rid */
234 db_static_prepare(&q1, "SELECT rid FROM delta WHERE srcid=:rid");
235 db_bind_int(&q1, ":rid", rid);
236 bag_init(&children);
237 while( db_step(&q1)==SQLITE_ROW ){
@@ -240,11 +240,11 @@
240 bag_insert(&children, cid);
241 }
242 }
243 nChild = bag_count(&children);
244 db_reset(&q1);
245
246 /* Crosslink the artifact */
247 if( nChild==0 ){
248 pUse = pBase;
249 }else{
250 blob_copy(&copy, pBase);
@@ -262,11 +262,11 @@
262 free(zUuid);
263 blob_reset(pUse);
264 }
265 assert( blob_is_reset(pUse) );
266 rebuild_step_done(rid);
267
268 /* Call all children recursively */
269 rid = 0;
270 for(cid=bag_first(&children), i=1; cid; cid=bag_next(&children, cid), i++){
271 static Stmt q2;
272 int sz;
@@ -626,11 +626,11 @@
626 if( activateWal ){
627 db_multi_exec("PRAGMA journal_mode=WAL;");
628 }
629 }
630 if( showStats ){
631 static struct { int idx; const char *zLabel; } aStat[] = {
632 { CFTYPE_ANY, "Artifacts:" },
633 { CFTYPE_MANIFEST, "Manifests:" },
634 { CFTYPE_CLUSTER, "Clusters:" },
635 { CFTYPE_CONTROL, "Tags:" },
636 { CFTYPE_WIKI, "Wikis:" },
@@ -687,11 +687,11 @@
687 db_close(1);
688 db_open_repository(g.zRepositoryName);
689 }
690 db_begin_transaction();
691 create_cluster();
692 db_end_transaction(0);
693 }
694
695 /*
696 ** COMMAND: test-clusters
697 **
@@ -700,11 +700,11 @@
700 */
701 void test_clusters_cmd(void){
702 Bag pending;
703 Stmt q;
704 int n;
705
706 db_find_and_open_repository(0, 2);
707 bag_init(&pending);
708 db_multi_exec(
709 "CREATE TEMP TABLE xdone(x INTEGER PRIMARY KEY);"
710 "INSERT INTO xdone SELECT rid FROM unclustered;"
@@ -722,11 +722,11 @@
722 db_finalize(&q);
723 while( bag_count(&pending)>0 ){
724 Manifest *p;
725 int rid = bag_first(&pending);
726 int i;
727
728 bag_remove(&pending, rid);
729 p = manifest_get(rid, CFTYPE_CLUSTER, 0);
730 if( p==0 ){
731 fossil_fatal("bad cluster: rid=%d", rid);
732 }
@@ -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]);
@@ -922,11 +923,11 @@
922 /* Skip the verify_before_commit() step on a reconstruct. Most artifacts
923 ** will have been changed and verification therefore takes a really, really
924 ** long time.
925 */
926 verify_cancel();
927
928 db_end_transaction(0);
929 fossil_print("project-id: %s\n", db_get("project-code", 0));
930 fossil_print("server-id: %s\n", db_get("server-code", 0));
931 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
932 fossil_print("admin-user: %s (initial password is \"%s\")\n", g.zLogin, zPassword);
@@ -942,11 +943,11 @@
942 ** writes all artifacts to the file system. The DESTINATION directory
943 ** will be populated with subdirectories AA and files AA/BBBBBBBBB.., where
944 ** AABBBBBBBBB.. is the 40 character artifact ID, AA the first 2 characters.
945 ** If -L|--prefixlength is given, the length (default 2) of the directory
946 ** prefix can be set to 0,1,..,9 characters.
947 **
948 ** Options:
949 ** -R|--repository REPOSITORY deconstruct given REPOSITORY
950 ** -L|--prefixlength N set the length of the names of the DESTINATION
951 ** subdirectories to N
952 ** --private Include private artifacts.
953
--- src/rebuild.c
+++ src/rebuild.c
@@ -47,18 +47,18 @@
47 @ mtime INTEGER, -- When added. Seconds since 1970
48 @ scom TEXT -- Optional text explaining why the shun occurred
49 @ );
50 @
51 @ -- Artifacts that should not be pushed are stored in the "private"
52 @ -- table.
53 @ --
54 @ CREATE TABLE IF NOT EXISTS private(rid INTEGER PRIMARY KEY);
55 @
56 @ -- Some ticket content (such as the originators email address or contact
57 @ -- information) needs to be obscured to protect privacy. This is achieved
58 @ -- by storing an SHA1 hash of the content. For display, the hash is
59 @ -- mapped back into the original text using this table.
60 @ --
61 @ -- This table contains sensitive information and should not be shared
62 @ -- with unauthorized users.
63 @ --
64 @ CREATE TABLE IF NOT EXISTS concealed(
@@ -153,11 +153,11 @@
153 db_multi_exec(
154 "ALTER TABLE concealed ADD COLUMN mtime INTEGER;"
155 "UPDATE concealed SET mtime=now();"
156 );
157 }
158 }
159
160 /*
161 ** Variables used to store state information about an on-going "rebuild"
162 ** or "deconstruct".
163 */
@@ -227,11 +227,11 @@
227 if( size!=blob_size(pBase) ){
228 db_multi_exec(
229 "UPDATE blob SET size=%d WHERE rid=%d", blob_size(pBase), rid
230 );
231 }
232
233 /* Find all children of artifact rid */
234 db_static_prepare(&q1, "SELECT rid FROM delta WHERE srcid=:rid");
235 db_bind_int(&q1, ":rid", rid);
236 bag_init(&children);
237 while( db_step(&q1)==SQLITE_ROW ){
@@ -240,11 +240,11 @@
240 bag_insert(&children, cid);
241 }
242 }
243 nChild = bag_count(&children);
244 db_reset(&q1);
245
246 /* Crosslink the artifact */
247 if( nChild==0 ){
248 pUse = pBase;
249 }else{
250 blob_copy(&copy, pBase);
@@ -262,11 +262,11 @@
262 free(zUuid);
263 blob_reset(pUse);
264 }
265 assert( blob_is_reset(pUse) );
266 rebuild_step_done(rid);
267
268 /* Call all children recursively */
269 rid = 0;
270 for(cid=bag_first(&children), i=1; cid; cid=bag_next(&children, cid), i++){
271 static Stmt q2;
272 int sz;
@@ -626,11 +626,11 @@
626 if( activateWal ){
627 db_multi_exec("PRAGMA journal_mode=WAL;");
628 }
629 }
630 if( showStats ){
631 static const struct { int idx; const char *zLabel; } aStat[] = {
632 { CFTYPE_ANY, "Artifacts:" },
633 { CFTYPE_MANIFEST, "Manifests:" },
634 { CFTYPE_CLUSTER, "Clusters:" },
635 { CFTYPE_CONTROL, "Tags:" },
636 { CFTYPE_WIKI, "Wikis:" },
@@ -687,11 +687,11 @@
687 db_close(1);
688 db_open_repository(g.zRepositoryName);
689 }
690 db_begin_transaction();
691 create_cluster();
692 db_end_transaction(0);
693 }
694
695 /*
696 ** COMMAND: test-clusters
697 **
@@ -700,11 +700,11 @@
700 */
701 void test_clusters_cmd(void){
702 Bag pending;
703 Stmt q;
704 int n;
705
706 db_find_and_open_repository(0, 2);
707 bag_init(&pending);
708 db_multi_exec(
709 "CREATE TEMP TABLE xdone(x INTEGER PRIMARY KEY);"
710 "INSERT INTO xdone SELECT rid FROM unclustered;"
@@ -722,11 +722,11 @@
722 db_finalize(&q);
723 while( bag_count(&pending)>0 ){
724 Manifest *p;
725 int rid = bag_first(&pending);
726 int i;
727
728 bag_remove(&pending, rid);
729 p = manifest_get(rid, CFTYPE_CLUSTER, 0);
730 if( p==0 ){
731 fossil_fatal("bad cluster: rid=%d", rid);
732 }
@@ -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]);
@@ -922,11 +923,11 @@
923 /* Skip the verify_before_commit() step on a reconstruct. Most artifacts
924 ** will have been changed and verification therefore takes a really, really
925 ** long time.
926 */
927 verify_cancel();
928
929 db_end_transaction(0);
930 fossil_print("project-id: %s\n", db_get("project-code", 0));
931 fossil_print("server-id: %s\n", db_get("server-code", 0));
932 zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin);
933 fossil_print("admin-user: %s (initial password is \"%s\")\n", g.zLogin, zPassword);
@@ -942,11 +943,11 @@
943 ** writes all artifacts to the file system. The DESTINATION directory
944 ** will be populated with subdirectories AA and files AA/BBBBBBBBB.., where
945 ** AABBBBBBBBB.. is the 40 character artifact ID, AA the first 2 characters.
946 ** If -L|--prefixlength is given, the length (default 2) of the directory
947 ** prefix can be set to 0,1,..,9 characters.
948 **
949 ** Options:
950 ** -R|--repository REPOSITORY deconstruct given REPOSITORY
951 ** -L|--prefixlength N set the length of the names of the DESTINATION
952 ** subdirectories to N
953 ** --private Include private artifacts.
954
+37 -35
--- src/report.c
+++ src/report.c
@@ -12,11 +12,11 @@
1212
** Author contact information:
1313
** [email protected]
1414
** http://www.hwaci.com/drh/
1515
**
1616
*******************************************************************************
17
-**
17
+**
1818
** Code to generate the ticket listings
1919
*/
2020
#include "config.h"
2121
#include <time.h>
2222
#include "report.h"
@@ -43,11 +43,11 @@
4343
if( !g.perm.RdTkt && !g.perm.NewTkt ){ login_needed(); return; }
4444
style_header("Ticket Main Menu");
4545
if( g.thTrace ) Th_Trace("BEGIN_REPORTLIST<br />\n", -1);
4646
zScript = ticket_reportlist_code();
4747
if( g.thTrace ) Th_Trace("BEGIN_REPORTLIST_SCRIPT<br />\n", -1);
48
-
48
+
4949
blob_zero(&ril);
5050
ticket_init();
5151
5252
db_prepare(&q, "SELECT rn, title, owner FROM reportfmt ORDER BY title");
5353
while( db_step(&q)==SQLITE_ROW ){
@@ -70,14 +70,14 @@
7070
}
7171
if( g.perm.TktFmt ){
7272
blob_appendf(&ril, "[%zcopy</a>] ",
7373
href("%R/rptedit?rn=%d&copy=1", rn));
7474
}
75
- if( g.perm.Admin
75
+ if( g.perm.Admin
7676
|| (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0)
7777
){
78
- blob_appendf(&ril, "[%zedit</a>]",
78
+ blob_appendf(&ril, "[%zedit</a>]",
7979
href("%R/rptedit?rn=%d", rn));
8080
}
8181
if( g.perm.TktFmt ){
8282
blob_appendf(&ril, "[%zsql</a>]",
8383
href("%R/rptsql?rn=%d", rn));
@@ -85,13 +85,13 @@
8585
blob_appendf(&ril, "</li>\n");
8686
}
8787
db_finalize(&q);
8888
8989
Th_Store("report_items", blob_str(&ril));
90
-
90
+
9191
Th_Render(zScript);
92
-
92
+
9393
blob_reset(&ril);
9494
if( g.thTrace ) Th_Trace("END_REPORTLIST<br />\n", -1);
9595
9696
style_footer();
9797
}
@@ -205,11 +205,11 @@
205205
}
206206
case SQLITE_RECURSIVE: {
207207
*(char**)pError = mprintf("recursive queries are not allowed");
208208
rc = SQLITE_DENY;
209209
break;
210
- }
210
+ }
211211
default: {
212212
*(char**)pError = mprintf("only SELECT statements are allowed");
213213
rc = SQLITE_DENY;
214214
break;
215215
}
@@ -262,14 +262,14 @@
262262
return mprintf("Semi-colon detected! "
263263
"Only a single SQL statement is allowed");
264264
}
265265
}
266266
}
267
-
267
+
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");
@@ -383,11 +383,11 @@
383383
}
384384
if( zTitle && zSQL ){
385385
if( zSQL[0]==0 ){
386386
zErr = "Please supply an SQL query statement";
387387
}else if( (zTitle = trim_string(zTitle))[0]==0 ){
388
- zErr = "Please supply a title";
388
+ zErr = "Please supply a title";
389389
}else{
390390
zErr = verify_sql_statement(zSQL);
391391
}
392392
if( zErr==0
393393
&& db_exists("SELECT 1 FROM reportfmt WHERE title=%Q and rn<>%d",
@@ -650,17 +650,17 @@
650650
** The callback function for db_query
651651
*/
652652
static int generate_html(
653653
void *pUser, /* Pointer to output state */
654654
int nArg, /* Number of columns in this result row */
655
- char **azArg, /* Text of data in all columns */
656
- char **azName /* Names of the columns */
655
+ const char **azArg, /* Text of data in all columns */
656
+ const char **azName /* Names of the columns */
657657
){
658658
struct GenerateHTML *pState = (struct GenerateHTML*)pUser;
659659
int i;
660660
const char *zTid; /* Ticket UUID. (value of column named '#') */
661
- char *zBg = 0; /* Use this background color */
661
+ const char *zBg = 0; /* Use this background color */
662662
663663
/* Do initialization
664664
*/
665665
if( pState->nCount==0 ){
666666
/* Turn off the authorizer. It is no longer doing anything since the
@@ -710,11 +710,11 @@
710710
/* The first time this routine is called, output a table header
711711
*/
712712
@ <thead><tr>
713713
zTid = 0;
714714
for(i=0; i<nArg; i++){
715
- char *zName = azName[i];
715
+ const char *zName = azName[i];
716716
if( i==pState->iBg ) continue;
717717
if( pState->iNewRow>=0 && i>=pState->iNewRow ){
718718
if( g.perm.Write && zTid ){
719719
@ <th>&nbsp;</th>
720720
zTid = 0;
@@ -753,11 +753,11 @@
753753
zBg = pState->iBg>=0 ? azArg[pState->iBg] : 0;
754754
if( zBg==0 ) zBg = "white";
755755
@ <tr style="background-color:%h(zBg)">
756756
zTid = 0;
757757
for(i=0; i<nArg; i++){
758
- char *zData;
758
+ const char *zData;
759759
if( i==pState->iBg ) continue;
760760
zData = azArg[i];
761761
if( zData==0 ) zData = "";
762762
if( pState->iNewRow>=0 && i>=pState->iNewRow ){
763763
if( zTid && g.perm.Write ){
@@ -815,12 +815,12 @@
815815
** Output a row as a tab-separated line of text.
816816
*/
817817
static int output_tab_separated(
818818
void *pUser, /* Pointer to row-count integer */
819819
int nArg, /* Number of columns in this result row */
820
- char **azArg, /* Text of data in all columns */
821
- char **azName /* Names of the columns */
820
+ const char **azArg, /* Text of data in all columns */
821
+ const char **azName /* Names of the columns */
822822
){
823823
int *pCount = (int*)pUser;
824824
int i;
825825
826826
if( *pCount==0 ){
@@ -840,18 +840,19 @@
840840
/*
841841
** Generate HTML that describes a color key.
842842
*/
843843
void output_color_key(const char *zClrKey, int horiz, char *zTabArgs){
844844
int i, j, k;
845
- char *zSafeKey, *zToFree;
845
+ const char *zSafeKey;
846
+ char *zToFree;
846847
while( fossil_isspace(*zClrKey) ) zClrKey++;
847848
if( zClrKey[0]==0 ) return;
848849
@ <table %s(zTabArgs)>
849850
if( horiz ){
850851
@ <tr>
851852
}
852
- zToFree = zSafeKey = mprintf("%h", zClrKey);
853
+ zSafeKey = zToFree = mprintf("%h", zClrKey);
853854
while( zSafeKey[0] ){
854855
while( fossil_isspace(*zSafeKey) ) zSafeKey++;
855856
for(i=0; zSafeKey[i] && !fossil_isspace(zSafeKey[i]); i++){}
856857
for(j=i; fossil_isspace(zSafeKey[j]); j++){}
857858
for(k=j; zSafeKey[k] && zSafeKey[k]!='\n' && zSafeKey[k]!='\r'; k++){}
@@ -873,23 +874,24 @@
873874
874875
/*
875876
** Execute a single read-only SQL statement. Invoke xCallback() on each
876877
** row.
877878
*/
878
-int sqlite3_exec_readonly(
879
+static int db_exec_readonly(
879880
sqlite3 *db, /* The database on which the SQL executes */
880881
const char *zSql, /* The SQL to be executed */
881
- sqlite3_callback xCallback, /* Invoke this callback routine */
882
+ int (*xCallback)(void*,int,const char**, const char**),
883
+ /* Invoke this callback routine */
882884
void *pArg, /* First argument to xCallback() */
883885
char **pzErrMsg /* Write error messages here */
884886
){
885887
int rc = SQLITE_OK; /* Return code */
886888
const char *zLeftover; /* Tail of unprocessed SQL */
887889
sqlite3_stmt *pStmt = 0; /* The current SQL statement */
888
- char **azCols = 0; /* Names of result columns */
890
+ const char **azCols = 0; /* Names of result columns */
889891
int nCol; /* Number of columns of output */
890
- char **azVals = 0; /* Text of all output columns */
892
+ const char **azVals = 0; /* Text of all output columns */
891893
int i; /* Loop counter */
892894
893895
pStmt = 0;
894896
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
895897
assert( rc==SQLITE_OK || pStmt==0 );
@@ -912,15 +914,15 @@
912914
azVals = fossil_malloc(2*nCol*sizeof(const char*) + 1);
913915
while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
914916
if( azCols==0 ){
915917
azCols = &azVals[nCol];
916918
for(i=0; i<nCol; i++){
917
- azCols[i] = (char *)sqlite3_column_name(pStmt, i);
919
+ azCols[i] = sqlite3_column_name(pStmt, i);
918920
}
919921
}
920922
for(i=0; i<nCol; i++){
921
- azVals[i] = (char *)sqlite3_column_text(pStmt, i);
923
+ azVals[i] = (const char *)sqlite3_column_text(pStmt, i);
922924
}
923925
if( xCallback(pArg, nCol, azVals, azCols) ){
924926
break;
925927
}
926928
}
@@ -1065,13 +1067,13 @@
10651067
count = 0;
10661068
if( !tabs ){
10671069
struct GenerateHTML sState;
10681070
10691071
db_multi_exec("PRAGMA empty_result_callbacks=ON");
1070
- style_submenu_element("Raw", "Raw",
1072
+ style_submenu_element("Raw", "Raw",
10711073
"rptview?tablist=1&%h", PD("QUERY_STRING",""));
1072
- if( g.perm.Admin
1074
+ if( g.perm.Admin
10731075
|| (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
10741076
style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn);
10751077
}
10761078
if( g.perm.TktFmt ){
10771079
style_submenu_element("SQL", "SQL", "rptsql?rn=%d",rn);
@@ -1079,18 +1081,18 @@
10791081
if( g.perm.NewTkt ){
10801082
style_submenu_element("New Ticket", "Create a new ticket",
10811083
"%s/tktnew", g.zTop);
10821084
}
10831085
style_header(zTitle);
1084
- output_color_key(zClrKey, 1,
1086
+ output_color_key(zClrKey, 1,
10851087
"border=\"0\" cellpadding=\"3\" cellspacing=\"0\" class=\"report\"");
10861088
@ <table border="1" cellpadding="2" cellspacing="0" class="report"
10871089
@ id="reportTable">
10881090
sState.rn = rn;
10891091
sState.nCount = 0;
10901092
report_restrict_sql(&zErr1);
1091
- sqlite3_exec_readonly(g.db, zSql, generate_html, &sState, &zErr2);
1093
+ db_exec_readonly(g.db, zSql, generate_html, &sState, &zErr2);
10921094
report_unrestrict_sql();
10931095
@ </tbody></table>
10941096
if( zErr1 ){
10951097
@ <p class="reportError">Error: %h(zErr1)</p>
10961098
}else if( zErr2 ){
@@ -1098,11 +1100,11 @@
10981100
}
10991101
output_table_sorting_javascript("reportTable","");
11001102
style_footer();
11011103
}else{
11021104
report_restrict_sql(&zErr1);
1103
- sqlite3_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2);
1105
+ db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2);
11041106
report_unrestrict_sql();
11051107
cgi_set_content_type("text/plain");
11061108
}
11071109
}
11081110
@@ -1177,22 +1179,22 @@
11771179
if( j>i ){
11781180
fossil_print("%*s", j-i, "");
11791181
}
11801182
z += j;
11811183
}
1182
- break;
1184
+ break;
11831185
}
11841186
}
11851187
11861188
/*
11871189
** Output a row as a tab-separated line of text.
11881190
*/
11891191
int output_separated_file(
11901192
void *pUser, /* Pointer to row-count integer */
11911193
int nArg, /* Number of columns in this result row */
1192
- char **azArg, /* Text of data in all columns */
1193
- char **azName /* Names of the columns */
1194
+ const char **azArg, /* Text of data in all columns */
1195
+ const char **azName /* Names of the columns */
11941196
){
11951197
int *pCount = (int*)pUser;
11961198
int i;
11971199
11981200
if( *pCount==0 ){
@@ -1212,11 +1214,11 @@
12121214
/*
12131215
** Generate a report. The rn query parameter is the report number.
12141216
** The output is written to stdout as flat file. The zFilter parameter
12151217
** is a full WHERE-condition.
12161218
*/
1217
-void rptshow(
1219
+void rptshow(
12181220
const char *zRep,
12191221
const char *zSepIn,
12201222
const char *zFilter,
12211223
tTktShowEncoding enc
12221224
){
@@ -1251,11 +1253,11 @@
12511253
}
12521254
count = 0;
12531255
tktEncode = enc;
12541256
zSep = zSepIn;
12551257
report_restrict_sql(&zErr1);
1256
- sqlite3_exec_readonly(g.db, zSql, output_separated_file, &count, &zErr2);
1258
+ db_exec_readonly(g.db, zSql, output_separated_file, &count, &zErr2);
12571259
report_unrestrict_sql();
12581260
if( zFilter ){
12591261
free(zSql);
12601262
}
12611263
}
12621264
--- src/report.c
+++ src/report.c
@@ -12,11 +12,11 @@
12 ** Author contact information:
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** Code to generate the ticket listings
19 */
20 #include "config.h"
21 #include <time.h>
22 #include "report.h"
@@ -43,11 +43,11 @@
43 if( !g.perm.RdTkt && !g.perm.NewTkt ){ login_needed(); return; }
44 style_header("Ticket Main Menu");
45 if( g.thTrace ) Th_Trace("BEGIN_REPORTLIST<br />\n", -1);
46 zScript = ticket_reportlist_code();
47 if( g.thTrace ) Th_Trace("BEGIN_REPORTLIST_SCRIPT<br />\n", -1);
48
49 blob_zero(&ril);
50 ticket_init();
51
52 db_prepare(&q, "SELECT rn, title, owner FROM reportfmt ORDER BY title");
53 while( db_step(&q)==SQLITE_ROW ){
@@ -70,14 +70,14 @@
70 }
71 if( g.perm.TktFmt ){
72 blob_appendf(&ril, "[%zcopy</a>] ",
73 href("%R/rptedit?rn=%d&copy=1", rn));
74 }
75 if( g.perm.Admin
76 || (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0)
77 ){
78 blob_appendf(&ril, "[%zedit</a>]",
79 href("%R/rptedit?rn=%d", rn));
80 }
81 if( g.perm.TktFmt ){
82 blob_appendf(&ril, "[%zsql</a>]",
83 href("%R/rptsql?rn=%d", rn));
@@ -85,13 +85,13 @@
85 blob_appendf(&ril, "</li>\n");
86 }
87 db_finalize(&q);
88
89 Th_Store("report_items", blob_str(&ril));
90
91 Th_Render(zScript);
92
93 blob_reset(&ril);
94 if( g.thTrace ) Th_Trace("END_REPORTLIST<br />\n", -1);
95
96 style_footer();
97 }
@@ -205,11 +205,11 @@
205 }
206 case SQLITE_RECURSIVE: {
207 *(char**)pError = mprintf("recursive queries are not allowed");
208 rc = SQLITE_DENY;
209 break;
210 }
211 default: {
212 *(char**)pError = mprintf("only SELECT statements are allowed");
213 rc = SQLITE_DENY;
214 break;
215 }
@@ -262,14 +262,14 @@
262 return mprintf("Semi-colon detected! "
263 "Only a single SQL statement is allowed");
264 }
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");
@@ -383,11 +383,11 @@
383 }
384 if( zTitle && zSQL ){
385 if( zSQL[0]==0 ){
386 zErr = "Please supply an SQL query statement";
387 }else if( (zTitle = trim_string(zTitle))[0]==0 ){
388 zErr = "Please supply a title";
389 }else{
390 zErr = verify_sql_statement(zSQL);
391 }
392 if( zErr==0
393 && db_exists("SELECT 1 FROM reportfmt WHERE title=%Q and rn<>%d",
@@ -650,17 +650,17 @@
650 ** The callback function for db_query
651 */
652 static int generate_html(
653 void *pUser, /* Pointer to output state */
654 int nArg, /* Number of columns in this result row */
655 char **azArg, /* Text of data in all columns */
656 char **azName /* Names of the columns */
657 ){
658 struct GenerateHTML *pState = (struct GenerateHTML*)pUser;
659 int i;
660 const char *zTid; /* Ticket UUID. (value of column named '#') */
661 char *zBg = 0; /* Use this background color */
662
663 /* Do initialization
664 */
665 if( pState->nCount==0 ){
666 /* Turn off the authorizer. It is no longer doing anything since the
@@ -710,11 +710,11 @@
710 /* The first time this routine is called, output a table header
711 */
712 @ <thead><tr>
713 zTid = 0;
714 for(i=0; i<nArg; i++){
715 char *zName = azName[i];
716 if( i==pState->iBg ) continue;
717 if( pState->iNewRow>=0 && i>=pState->iNewRow ){
718 if( g.perm.Write && zTid ){
719 @ <th>&nbsp;</th>
720 zTid = 0;
@@ -753,11 +753,11 @@
753 zBg = pState->iBg>=0 ? azArg[pState->iBg] : 0;
754 if( zBg==0 ) zBg = "white";
755 @ <tr style="background-color:%h(zBg)">
756 zTid = 0;
757 for(i=0; i<nArg; i++){
758 char *zData;
759 if( i==pState->iBg ) continue;
760 zData = azArg[i];
761 if( zData==0 ) zData = "";
762 if( pState->iNewRow>=0 && i>=pState->iNewRow ){
763 if( zTid && g.perm.Write ){
@@ -815,12 +815,12 @@
815 ** Output a row as a tab-separated line of text.
816 */
817 static int output_tab_separated(
818 void *pUser, /* Pointer to row-count integer */
819 int nArg, /* Number of columns in this result row */
820 char **azArg, /* Text of data in all columns */
821 char **azName /* Names of the columns */
822 ){
823 int *pCount = (int*)pUser;
824 int i;
825
826 if( *pCount==0 ){
@@ -840,18 +840,19 @@
840 /*
841 ** Generate HTML that describes a color key.
842 */
843 void output_color_key(const char *zClrKey, int horiz, char *zTabArgs){
844 int i, j, k;
845 char *zSafeKey, *zToFree;
 
846 while( fossil_isspace(*zClrKey) ) zClrKey++;
847 if( zClrKey[0]==0 ) return;
848 @ <table %s(zTabArgs)>
849 if( horiz ){
850 @ <tr>
851 }
852 zToFree = zSafeKey = mprintf("%h", zClrKey);
853 while( zSafeKey[0] ){
854 while( fossil_isspace(*zSafeKey) ) zSafeKey++;
855 for(i=0; zSafeKey[i] && !fossil_isspace(zSafeKey[i]); i++){}
856 for(j=i; fossil_isspace(zSafeKey[j]); j++){}
857 for(k=j; zSafeKey[k] && zSafeKey[k]!='\n' && zSafeKey[k]!='\r'; k++){}
@@ -873,23 +874,24 @@
873
874 /*
875 ** Execute a single read-only SQL statement. Invoke xCallback() on each
876 ** row.
877 */
878 int sqlite3_exec_readonly(
879 sqlite3 *db, /* The database on which the SQL executes */
880 const char *zSql, /* The SQL to be executed */
881 sqlite3_callback xCallback, /* Invoke this callback routine */
 
882 void *pArg, /* First argument to xCallback() */
883 char **pzErrMsg /* Write error messages here */
884 ){
885 int rc = SQLITE_OK; /* Return code */
886 const char *zLeftover; /* Tail of unprocessed SQL */
887 sqlite3_stmt *pStmt = 0; /* The current SQL statement */
888 char **azCols = 0; /* Names of result columns */
889 int nCol; /* Number of columns of output */
890 char **azVals = 0; /* Text of all output columns */
891 int i; /* Loop counter */
892
893 pStmt = 0;
894 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
895 assert( rc==SQLITE_OK || pStmt==0 );
@@ -912,15 +914,15 @@
912 azVals = fossil_malloc(2*nCol*sizeof(const char*) + 1);
913 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
914 if( azCols==0 ){
915 azCols = &azVals[nCol];
916 for(i=0; i<nCol; i++){
917 azCols[i] = (char *)sqlite3_column_name(pStmt, i);
918 }
919 }
920 for(i=0; i<nCol; i++){
921 azVals[i] = (char *)sqlite3_column_text(pStmt, i);
922 }
923 if( xCallback(pArg, nCol, azVals, azCols) ){
924 break;
925 }
926 }
@@ -1065,13 +1067,13 @@
1065 count = 0;
1066 if( !tabs ){
1067 struct GenerateHTML sState;
1068
1069 db_multi_exec("PRAGMA empty_result_callbacks=ON");
1070 style_submenu_element("Raw", "Raw",
1071 "rptview?tablist=1&%h", PD("QUERY_STRING",""));
1072 if( g.perm.Admin
1073 || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
1074 style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn);
1075 }
1076 if( g.perm.TktFmt ){
1077 style_submenu_element("SQL", "SQL", "rptsql?rn=%d",rn);
@@ -1079,18 +1081,18 @@
1079 if( g.perm.NewTkt ){
1080 style_submenu_element("New Ticket", "Create a new ticket",
1081 "%s/tktnew", g.zTop);
1082 }
1083 style_header(zTitle);
1084 output_color_key(zClrKey, 1,
1085 "border=\"0\" cellpadding=\"3\" cellspacing=\"0\" class=\"report\"");
1086 @ <table border="1" cellpadding="2" cellspacing="0" class="report"
1087 @ id="reportTable">
1088 sState.rn = rn;
1089 sState.nCount = 0;
1090 report_restrict_sql(&zErr1);
1091 sqlite3_exec_readonly(g.db, zSql, generate_html, &sState, &zErr2);
1092 report_unrestrict_sql();
1093 @ </tbody></table>
1094 if( zErr1 ){
1095 @ <p class="reportError">Error: %h(zErr1)</p>
1096 }else if( zErr2 ){
@@ -1098,11 +1100,11 @@
1098 }
1099 output_table_sorting_javascript("reportTable","");
1100 style_footer();
1101 }else{
1102 report_restrict_sql(&zErr1);
1103 sqlite3_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2);
1104 report_unrestrict_sql();
1105 cgi_set_content_type("text/plain");
1106 }
1107 }
1108
@@ -1177,22 +1179,22 @@
1177 if( j>i ){
1178 fossil_print("%*s", j-i, "");
1179 }
1180 z += j;
1181 }
1182 break;
1183 }
1184 }
1185
1186 /*
1187 ** Output a row as a tab-separated line of text.
1188 */
1189 int output_separated_file(
1190 void *pUser, /* Pointer to row-count integer */
1191 int nArg, /* Number of columns in this result row */
1192 char **azArg, /* Text of data in all columns */
1193 char **azName /* Names of the columns */
1194 ){
1195 int *pCount = (int*)pUser;
1196 int i;
1197
1198 if( *pCount==0 ){
@@ -1212,11 +1214,11 @@
1212 /*
1213 ** Generate a report. The rn query parameter is the report number.
1214 ** The output is written to stdout as flat file. The zFilter parameter
1215 ** is a full WHERE-condition.
1216 */
1217 void rptshow(
1218 const char *zRep,
1219 const char *zSepIn,
1220 const char *zFilter,
1221 tTktShowEncoding enc
1222 ){
@@ -1251,11 +1253,11 @@
1251 }
1252 count = 0;
1253 tktEncode = enc;
1254 zSep = zSepIn;
1255 report_restrict_sql(&zErr1);
1256 sqlite3_exec_readonly(g.db, zSql, output_separated_file, &count, &zErr2);
1257 report_unrestrict_sql();
1258 if( zFilter ){
1259 free(zSql);
1260 }
1261 }
1262
--- src/report.c
+++ src/report.c
@@ -12,11 +12,11 @@
12 ** Author contact information:
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** Code to generate the ticket listings
19 */
20 #include "config.h"
21 #include <time.h>
22 #include "report.h"
@@ -43,11 +43,11 @@
43 if( !g.perm.RdTkt && !g.perm.NewTkt ){ login_needed(); return; }
44 style_header("Ticket Main Menu");
45 if( g.thTrace ) Th_Trace("BEGIN_REPORTLIST<br />\n", -1);
46 zScript = ticket_reportlist_code();
47 if( g.thTrace ) Th_Trace("BEGIN_REPORTLIST_SCRIPT<br />\n", -1);
48
49 blob_zero(&ril);
50 ticket_init();
51
52 db_prepare(&q, "SELECT rn, title, owner FROM reportfmt ORDER BY title");
53 while( db_step(&q)==SQLITE_ROW ){
@@ -70,14 +70,14 @@
70 }
71 if( g.perm.TktFmt ){
72 blob_appendf(&ril, "[%zcopy</a>] ",
73 href("%R/rptedit?rn=%d&copy=1", rn));
74 }
75 if( g.perm.Admin
76 || (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0)
77 ){
78 blob_appendf(&ril, "[%zedit</a>]",
79 href("%R/rptedit?rn=%d", rn));
80 }
81 if( g.perm.TktFmt ){
82 blob_appendf(&ril, "[%zsql</a>]",
83 href("%R/rptsql?rn=%d", rn));
@@ -85,13 +85,13 @@
85 blob_appendf(&ril, "</li>\n");
86 }
87 db_finalize(&q);
88
89 Th_Store("report_items", blob_str(&ril));
90
91 Th_Render(zScript);
92
93 blob_reset(&ril);
94 if( g.thTrace ) Th_Trace("END_REPORTLIST<br />\n", -1);
95
96 style_footer();
97 }
@@ -205,11 +205,11 @@
205 }
206 case SQLITE_RECURSIVE: {
207 *(char**)pError = mprintf("recursive queries are not allowed");
208 rc = SQLITE_DENY;
209 break;
210 }
211 default: {
212 *(char**)pError = mprintf("only SELECT statements are allowed");
213 rc = SQLITE_DENY;
214 break;
215 }
@@ -262,14 +262,14 @@
262 return mprintf("Semi-colon detected! "
263 "Only a single SQL statement is allowed");
264 }
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");
@@ -383,11 +383,11 @@
383 }
384 if( zTitle && zSQL ){
385 if( zSQL[0]==0 ){
386 zErr = "Please supply an SQL query statement";
387 }else if( (zTitle = trim_string(zTitle))[0]==0 ){
388 zErr = "Please supply a title";
389 }else{
390 zErr = verify_sql_statement(zSQL);
391 }
392 if( zErr==0
393 && db_exists("SELECT 1 FROM reportfmt WHERE title=%Q and rn<>%d",
@@ -650,17 +650,17 @@
650 ** The callback function for db_query
651 */
652 static int generate_html(
653 void *pUser, /* Pointer to output state */
654 int nArg, /* Number of columns in this result row */
655 const char **azArg, /* Text of data in all columns */
656 const char **azName /* Names of the columns */
657 ){
658 struct GenerateHTML *pState = (struct GenerateHTML*)pUser;
659 int i;
660 const char *zTid; /* Ticket UUID. (value of column named '#') */
661 const char *zBg = 0; /* Use this background color */
662
663 /* Do initialization
664 */
665 if( pState->nCount==0 ){
666 /* Turn off the authorizer. It is no longer doing anything since the
@@ -710,11 +710,11 @@
710 /* The first time this routine is called, output a table header
711 */
712 @ <thead><tr>
713 zTid = 0;
714 for(i=0; i<nArg; i++){
715 const char *zName = azName[i];
716 if( i==pState->iBg ) continue;
717 if( pState->iNewRow>=0 && i>=pState->iNewRow ){
718 if( g.perm.Write && zTid ){
719 @ <th>&nbsp;</th>
720 zTid = 0;
@@ -753,11 +753,11 @@
753 zBg = pState->iBg>=0 ? azArg[pState->iBg] : 0;
754 if( zBg==0 ) zBg = "white";
755 @ <tr style="background-color:%h(zBg)">
756 zTid = 0;
757 for(i=0; i<nArg; i++){
758 const char *zData;
759 if( i==pState->iBg ) continue;
760 zData = azArg[i];
761 if( zData==0 ) zData = "";
762 if( pState->iNewRow>=0 && i>=pState->iNewRow ){
763 if( zTid && g.perm.Write ){
@@ -815,12 +815,12 @@
815 ** Output a row as a tab-separated line of text.
816 */
817 static int output_tab_separated(
818 void *pUser, /* Pointer to row-count integer */
819 int nArg, /* Number of columns in this result row */
820 const char **azArg, /* Text of data in all columns */
821 const char **azName /* Names of the columns */
822 ){
823 int *pCount = (int*)pUser;
824 int i;
825
826 if( *pCount==0 ){
@@ -840,18 +840,19 @@
840 /*
841 ** Generate HTML that describes a color key.
842 */
843 void output_color_key(const char *zClrKey, int horiz, char *zTabArgs){
844 int i, j, k;
845 const char *zSafeKey;
846 char *zToFree;
847 while( fossil_isspace(*zClrKey) ) zClrKey++;
848 if( zClrKey[0]==0 ) return;
849 @ <table %s(zTabArgs)>
850 if( horiz ){
851 @ <tr>
852 }
853 zSafeKey = zToFree = mprintf("%h", zClrKey);
854 while( zSafeKey[0] ){
855 while( fossil_isspace(*zSafeKey) ) zSafeKey++;
856 for(i=0; zSafeKey[i] && !fossil_isspace(zSafeKey[i]); i++){}
857 for(j=i; fossil_isspace(zSafeKey[j]); j++){}
858 for(k=j; zSafeKey[k] && zSafeKey[k]!='\n' && zSafeKey[k]!='\r'; k++){}
@@ -873,23 +874,24 @@
874
875 /*
876 ** Execute a single read-only SQL statement. Invoke xCallback() on each
877 ** row.
878 */
879 static int db_exec_readonly(
880 sqlite3 *db, /* The database on which the SQL executes */
881 const char *zSql, /* The SQL to be executed */
882 int (*xCallback)(void*,int,const char**, const char**),
883 /* Invoke this callback routine */
884 void *pArg, /* First argument to xCallback() */
885 char **pzErrMsg /* Write error messages here */
886 ){
887 int rc = SQLITE_OK; /* Return code */
888 const char *zLeftover; /* Tail of unprocessed SQL */
889 sqlite3_stmt *pStmt = 0; /* The current SQL statement */
890 const char **azCols = 0; /* Names of result columns */
891 int nCol; /* Number of columns of output */
892 const char **azVals = 0; /* Text of all output columns */
893 int i; /* Loop counter */
894
895 pStmt = 0;
896 rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
897 assert( rc==SQLITE_OK || pStmt==0 );
@@ -912,15 +914,15 @@
914 azVals = fossil_malloc(2*nCol*sizeof(const char*) + 1);
915 while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){
916 if( azCols==0 ){
917 azCols = &azVals[nCol];
918 for(i=0; i<nCol; i++){
919 azCols[i] = sqlite3_column_name(pStmt, i);
920 }
921 }
922 for(i=0; i<nCol; i++){
923 azVals[i] = (const char *)sqlite3_column_text(pStmt, i);
924 }
925 if( xCallback(pArg, nCol, azVals, azCols) ){
926 break;
927 }
928 }
@@ -1065,13 +1067,13 @@
1067 count = 0;
1068 if( !tabs ){
1069 struct GenerateHTML sState;
1070
1071 db_multi_exec("PRAGMA empty_result_callbacks=ON");
1072 style_submenu_element("Raw", "Raw",
1073 "rptview?tablist=1&%h", PD("QUERY_STRING",""));
1074 if( g.perm.Admin
1075 || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
1076 style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn);
1077 }
1078 if( g.perm.TktFmt ){
1079 style_submenu_element("SQL", "SQL", "rptsql?rn=%d",rn);
@@ -1079,18 +1081,18 @@
1081 if( g.perm.NewTkt ){
1082 style_submenu_element("New Ticket", "Create a new ticket",
1083 "%s/tktnew", g.zTop);
1084 }
1085 style_header(zTitle);
1086 output_color_key(zClrKey, 1,
1087 "border=\"0\" cellpadding=\"3\" cellspacing=\"0\" class=\"report\"");
1088 @ <table border="1" cellpadding="2" cellspacing="0" class="report"
1089 @ id="reportTable">
1090 sState.rn = rn;
1091 sState.nCount = 0;
1092 report_restrict_sql(&zErr1);
1093 db_exec_readonly(g.db, zSql, generate_html, &sState, &zErr2);
1094 report_unrestrict_sql();
1095 @ </tbody></table>
1096 if( zErr1 ){
1097 @ <p class="reportError">Error: %h(zErr1)</p>
1098 }else if( zErr2 ){
@@ -1098,11 +1100,11 @@
1100 }
1101 output_table_sorting_javascript("reportTable","");
1102 style_footer();
1103 }else{
1104 report_restrict_sql(&zErr1);
1105 db_exec_readonly(g.db, zSql, output_tab_separated, &count, &zErr2);
1106 report_unrestrict_sql();
1107 cgi_set_content_type("text/plain");
1108 }
1109 }
1110
@@ -1177,22 +1179,22 @@
1179 if( j>i ){
1180 fossil_print("%*s", j-i, "");
1181 }
1182 z += j;
1183 }
1184 break;
1185 }
1186 }
1187
1188 /*
1189 ** Output a row as a tab-separated line of text.
1190 */
1191 int output_separated_file(
1192 void *pUser, /* Pointer to row-count integer */
1193 int nArg, /* Number of columns in this result row */
1194 const char **azArg, /* Text of data in all columns */
1195 const char **azName /* Names of the columns */
1196 ){
1197 int *pCount = (int*)pUser;
1198 int i;
1199
1200 if( *pCount==0 ){
@@ -1212,11 +1214,11 @@
1214 /*
1215 ** Generate a report. The rn query parameter is the report number.
1216 ** The output is written to stdout as flat file. The zFilter parameter
1217 ** is a full WHERE-condition.
1218 */
1219 void rptshow(
1220 const char *zRep,
1221 const char *zSepIn,
1222 const char *zFilter,
1223 tTktShowEncoding enc
1224 ){
@@ -1251,11 +1253,11 @@
1253 }
1254 count = 0;
1255 tktEncode = enc;
1256 zSep = zSepIn;
1257 report_restrict_sql(&zErr1);
1258 db_exec_readonly(g.db, zSql, output_separated_file, &count, &zErr2);
1259 report_unrestrict_sql();
1260 if( zFilter ){
1261 free(zSql);
1262 }
1263 }
1264
+1 -1
--- src/search.c
+++ src/search.c
@@ -135,11 +135,11 @@
135135
136136
/* Every term must be seen or else the score is zero */
137137
for(j=0; j<p->nTerm; j++){
138138
if( !seen[j] ) return 0;
139139
}
140
-
140
+
141141
return score;
142142
}
143143
144144
/*
145145
** This is an SQLite function that scores its input using
146146
--- src/search.c
+++ src/search.c
@@ -135,11 +135,11 @@
135
136 /* Every term must be seen or else the score is zero */
137 for(j=0; j<p->nTerm; j++){
138 if( !seen[j] ) return 0;
139 }
140
141 return score;
142 }
143
144 /*
145 ** This is an SQLite function that scores its input using
146
--- src/search.c
+++ src/search.c
@@ -135,11 +135,11 @@
135
136 /* Every term must be seen or else the score is zero */
137 for(j=0; j<p->nTerm; j++){
138 if( !seen[j] ) return 0;
139 }
140
141 return score;
142 }
143
144 /*
145 ** This is an SQLite function that scores its input using
146
+8 -10
--- src/setup.c
+++ src/setup.c
@@ -249,14 +249,11 @@
249249
@ <tr><th valign="top">w</th>
250250
@ <td><i>Write-Tkt:</i> Edit tickets</td></tr>
251251
@ <tr><th valign="top">x</th>
252252
@ <td><i>Private:</i> Push and/or pull private branches</td></tr>
253253
@ <tr><th valign="top">z</th>
254
- @ <td><i>Zip download:</i> Download a baseline via the
255
- @ <tt>/zip</tt> URL even without
256
- @ check<span class="capability">o</span>ut
257
- @ and <span class="capability">h</span>istory permissions</td></tr>
254
+ @ <td><i>Zip download:</i> Download a ZIP archive or tarball</td></tr>
258255
@ </table>
259256
@ </li>
260257
@
261258
@ <li><p>
262259
@ Every user, logged in or not, inherits the privileges of
@@ -859,11 +856,11 @@
859856
const char *zLabel, /* The text label on the menu */
860857
const char *zVar, /* The corresponding row in the VAR table */
861858
const char *zQP, /* The query parameter */
862859
const char *zDflt, /* Default value if VAR table entry does not exist */
863860
int nChoice, /* Number of choices */
864
- const char **azChoice /* Choices. 2 per choice: (VAR value, Display) */
861
+ const char *const *azChoice /* Choices. 2 per choice: (VAR value, Display) */
865862
){
866863
const char *z = db_get(zVar, (char*)zDflt);
867864
const char *zQ = P(zQP);
868865
int i;
869866
if( zQ && fossil_strcmp(zQ,z)!=0){
@@ -874,11 +871,11 @@
874871
@ <select size="1" name="%s(zQP)" id="id%s(zQP)">
875872
for(i=0; i<nChoice*2; i+=2){
876873
const char *zSel = fossil_strcmp(azChoice[i],z)==0 ? " selected" : "";
877874
@ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
878875
}
879
- @ </select>
876
+ @ </select> <b>%h(zLabel)</b>
880877
}
881878
882879
883880
/*
884881
** WEBPAGE: setup_access
@@ -975,19 +972,19 @@
975972
@ including user "nobody", as long as (1) the User-Agent string in the
976973
@ HTTP header indicates that the request is coming from an actual human
977974
@ being and not a a robot or spider and (2) the user agent is able to
978975
@ run Javascript in order to set the href= attribute of hyperlinks. Bots
979976
@ and spiders can forge a User-Agent string that makes them seem to be a
980
- @ normal browser and they can run javascript just like browsers. But most
977
+ @ normal browser and they can run javascript just like browsers. But most
981978
@ bots do not go to that much trouble so this is normally an effective defense.</p>
982979
@
983980
@ <p>You do not normally want a bot to walk your entire repository because
984981
@ if it does, your server will end up computing diffs and annotations for
985982
@ every historical version of every file and creating ZIPs and tarballs of
986983
@ every historical check-in, which can use a lot of CPU and bandwidth
987984
@ even for relatively small projects.</p>
988
- @
985
+ @
989986
@ <p>Additional parameters that control this behavior:</p>
990987
@ <blockquote>
991988
onoff_attribute("Require mouse movement before enabling hyperlinks",
992989
"auto-hyperlink-mouseover", "ahmo", 0, 0);
993990
@ <br>
@@ -1151,11 +1148,11 @@
11511148
** WEBPAGE: setup_timeline
11521149
*/
11531150
void setup_timeline(void){
11541151
double tmDiff;
11551152
char zTmDiff[20];
1156
- static const char *azTimeFormats[] = {
1153
+ static const char *const azTimeFormats[] = {
11571154
"0", "HH:MM",
11581155
"1", "HH:MM:SS",
11591156
"2", "YYYY-MM-DD HH:MM",
11601157
"3", "YYMMDD HH:MM"
11611158
};
@@ -1177,11 +1174,12 @@
11771174
11781175
@ <hr />
11791176
onoff_attribute("Plaintext comments on timelines",
11801177
"timeline-plaintext", "tpt", 0, 0);
11811178
@ <p>In timeline displays, check-in comments are displayed literally,
1182
- @ 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>
11831181
11841182
@ <hr />
11851183
onoff_attribute("Use Universal Coordinated Time (UTC)",
11861184
"timeline-utc", "utc", 1, 0);
11871185
@ <p>Show times as UTC (also sometimes called Greenwich Mean Time (GMT) or
11881186
--- src/setup.c
+++ src/setup.c
@@ -249,14 +249,11 @@
249 @ <tr><th valign="top">w</th>
250 @ <td><i>Write-Tkt:</i> Edit tickets</td></tr>
251 @ <tr><th valign="top">x</th>
252 @ <td><i>Private:</i> Push and/or pull private branches</td></tr>
253 @ <tr><th valign="top">z</th>
254 @ <td><i>Zip download:</i> Download a baseline via the
255 @ <tt>/zip</tt> URL even without
256 @ check<span class="capability">o</span>ut
257 @ and <span class="capability">h</span>istory permissions</td></tr>
258 @ </table>
259 @ </li>
260 @
261 @ <li><p>
262 @ Every user, logged in or not, inherits the privileges of
@@ -859,11 +856,11 @@
859 const char *zLabel, /* The text label on the menu */
860 const char *zVar, /* The corresponding row in the VAR table */
861 const char *zQP, /* The query parameter */
862 const char *zDflt, /* Default value if VAR table entry does not exist */
863 int nChoice, /* Number of choices */
864 const char **azChoice /* Choices. 2 per choice: (VAR value, Display) */
865 ){
866 const char *z = db_get(zVar, (char*)zDflt);
867 const char *zQ = P(zQP);
868 int i;
869 if( zQ && fossil_strcmp(zQ,z)!=0){
@@ -874,11 +871,11 @@
874 @ <select size="1" name="%s(zQP)" id="id%s(zQP)">
875 for(i=0; i<nChoice*2; i+=2){
876 const char *zSel = fossil_strcmp(azChoice[i],z)==0 ? " selected" : "";
877 @ <option value="%h(azChoice[i])"%s(zSel)>%h(azChoice[i+1])</option>
878 }
879 @ </select>
880 }
881
882
883 /*
884 ** WEBPAGE: setup_access
@@ -975,19 +972,19 @@
975 @ including user "nobody", as long as (1) the User-Agent string in the
976 @ HTTP header indicates that the request is coming from an actual human
977 @ being and not a a robot or spider and (2) the user agent is able to
978 @ run Javascript in order to set the href= attribute of hyperlinks. Bots
979 @ and spiders can forge a User-Agent string that makes them seem to be a
980 @ normal browser and they can run javascript just like browsers. But most
981 @ bots do not go to that much trouble so this is normally an effective defense.</p>
982 @
983 @ <p>You do not normally want a bot to walk your entire repository because
984 @ if it does, your server will end up computing diffs and annotations for
985 @ every historical version of every file and creating ZIPs and tarballs of
986 @ every historical check-in, which can use a lot of CPU and bandwidth
987 @ even for relatively small projects.</p>
988 @
989 @ <p>Additional parameters that control this behavior:</p>
990 @ <blockquote>
991 onoff_attribute("Require mouse movement before enabling hyperlinks",
992 "auto-hyperlink-mouseover", "ahmo", 0, 0);
993 @ <br>
@@ -1151,11 +1148,11 @@
1151 ** WEBPAGE: setup_timeline
1152 */
1153 void setup_timeline(void){
1154 double tmDiff;
1155 char zTmDiff[20];
1156 static const char *azTimeFormats[] = {
1157 "0", "HH:MM",
1158 "1", "HH:MM:SS",
1159 "2", "YYYY-MM-DD HH:MM",
1160 "3", "YYMMDD HH:MM"
1161 };
@@ -1177,11 +1174,12 @@
1177
1178 @ <hr />
1179 onoff_attribute("Plaintext comments on timelines",
1180 "timeline-plaintext", "tpt", 0, 0);
1181 @ <p>In timeline displays, check-in comments are displayed literally,
1182 @ without any wiki or HTML interpretation.</p>
 
1183
1184 @ <hr />
1185 onoff_attribute("Use Universal Coordinated Time (UTC)",
1186 "timeline-utc", "utc", 1, 0);
1187 @ <p>Show times as UTC (also sometimes called Greenwich Mean Time (GMT) or
1188
--- src/setup.c
+++ src/setup.c
@@ -249,14 +249,11 @@
249 @ <tr><th valign="top">w</th>
250 @ <td><i>Write-Tkt:</i> Edit tickets</td></tr>
251 @ <tr><th valign="top">x</th>
252 @ <td><i>Private:</i> Push and/or pull private branches</td></tr>
253 @ <tr><th valign="top">z</th>
254 @ <td><i>Zip download:</i> Download a ZIP archive or tarball</td></tr>
 
 
 
255 @ </table>
256 @ </li>
257 @
258 @ <li><p>
259 @ Every user, logged in or not, inherits the privileges of
@@ -859,11 +856,11 @@
856 const char *zLabel, /* The text label on the menu */
857 const char *zVar, /* The corresponding row in the VAR table */
858 const char *zQP, /* The query parameter */
859 const char *zDflt, /* Default value if VAR table entry does not exist */
860 int nChoice, /* Number of choices */
861 const char *const *azChoice /* Choices. 2 per choice: (VAR value, Display) */
862 ){
863 const char *z = db_get(zVar, (char*)zDflt);
864 const char *zQ = P(zQP);
865 int i;
866 if( zQ && fossil_strcmp(zQ,z)!=0){
@@ -874,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
@@ -975,19 +972,19 @@
972 @ including user "nobody", as long as (1) the User-Agent string in the
973 @ HTTP header indicates that the request is coming from an actual human
974 @ being and not a a robot or spider and (2) the user agent is able to
975 @ run Javascript in order to set the href= attribute of hyperlinks. Bots
976 @ and spiders can forge a User-Agent string that makes them seem to be a
977 @ normal browser and they can run javascript just like browsers. But most
978 @ bots do not go to that much trouble so this is normally an effective defense.</p>
979 @
980 @ <p>You do not normally want a bot to walk your entire repository because
981 @ if it does, your server will end up computing diffs and annotations for
982 @ every historical version of every file and creating ZIPs and tarballs of
983 @ every historical check-in, which can use a lot of CPU and bandwidth
984 @ even for relatively small projects.</p>
985 @
986 @ <p>Additional parameters that control this behavior:</p>
987 @ <blockquote>
988 onoff_attribute("Require mouse movement before enabling hyperlinks",
989 "auto-hyperlink-mouseover", "ahmo", 0, 0);
990 @ <br>
@@ -1151,11 +1148,11 @@
1148 ** WEBPAGE: setup_timeline
1149 */
1150 void setup_timeline(void){
1151 double tmDiff;
1152 char zTmDiff[20];
1153 static const char *const azTimeFormats[] = {
1154 "0", "HH:MM",
1155 "1", "HH:MM:SS",
1156 "2", "YYYY-MM-DD HH:MM",
1157 "3", "YYMMDD HH:MM"
1158 };
@@ -1177,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
+2 -2
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -42,11 +42,11 @@
4242
g.db = sqlite3_context_db_handle(context);
4343
g.repositoryOpen = 1;
4444
rid = name_to_rid(zName);
4545
if( rid==0 ) return;
4646
if( content_get(rid, &cx) ){
47
- sqlite3_result_blob(context, blob_buffer(&cx), blob_size(&cx),
47
+ sqlite3_result_blob(context, blob_buffer(&cx), blob_size(&cx),
4848
SQLITE_TRANSIENT);
4949
blob_reset(&cx);
5050
}
5151
}
5252
@@ -137,11 +137,11 @@
137137
**
138138
** WARNING: Careless use of this command can corrupt a Fossil repository
139139
** in ways that are unrecoverable. Be sure you know what you are doing before
140140
** running any SQL commands that modifies the repository database.
141141
*/
142
-void sqlite3_cmd(void){
142
+void cmd_sqlite3(void){
143143
extern int sqlite3_shell(int, char**);
144144
db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
145145
db_close(1);
146146
sqlite3_shutdown();
147147
sqlite3_shell(g.argc-1, g.argv+1);
148148
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -42,11 +42,11 @@
42 g.db = sqlite3_context_db_handle(context);
43 g.repositoryOpen = 1;
44 rid = name_to_rid(zName);
45 if( rid==0 ) return;
46 if( content_get(rid, &cx) ){
47 sqlite3_result_blob(context, blob_buffer(&cx), blob_size(&cx),
48 SQLITE_TRANSIENT);
49 blob_reset(&cx);
50 }
51 }
52
@@ -137,11 +137,11 @@
137 **
138 ** WARNING: Careless use of this command can corrupt a Fossil repository
139 ** in ways that are unrecoverable. Be sure you know what you are doing before
140 ** running any SQL commands that modifies the repository database.
141 */
142 void sqlite3_cmd(void){
143 extern int sqlite3_shell(int, char**);
144 db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
145 db_close(1);
146 sqlite3_shutdown();
147 sqlite3_shell(g.argc-1, g.argv+1);
148
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -42,11 +42,11 @@
42 g.db = sqlite3_context_db_handle(context);
43 g.repositoryOpen = 1;
44 rid = name_to_rid(zName);
45 if( rid==0 ) return;
46 if( content_get(rid, &cx) ){
47 sqlite3_result_blob(context, blob_buffer(&cx), blob_size(&cx),
48 SQLITE_TRANSIENT);
49 blob_reset(&cx);
50 }
51 }
52
@@ -137,11 +137,11 @@
137 **
138 ** WARNING: Careless use of this command can corrupt a Fossil repository
139 ** in ways that are unrecoverable. Be sure you know what you are doing before
140 ** running any SQL commands that modifies the repository database.
141 */
142 void cmd_sqlite3(void){
143 extern int sqlite3_shell(int, char**);
144 db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
145 db_close(1);
146 sqlite3_shutdown();
147 sqlite3_shell(g.argc-1, g.argv+1);
148
+119 -115
--- 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-22 18:31:27 dea2ca6a159d5dcfd8deceedf1c2a73fb4ac1cfc"
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
**
@@ -11303,10 +11303,11 @@
1130311303
1130411304
/*
1130511305
** A bit in a Bitmask
1130611306
*/
1130711307
#define MASKBIT(n) (((Bitmask)1)<<(n))
11308
+#define MASKBIT32(n) (((unsigned int)1)<<(n))
1130811309
1130911310
/*
1131011311
** The following structure describes the FROM clause of a SELECT statement.
1131111312
** Each table or subquery in the FROM clause is a separate element of
1131211313
** the SrcList.a[] array.
@@ -22605,11 +22606,12 @@
2260522606
2260622607
/*
2260722608
** Read or write a four-byte big-endian integer value.
2260822609
*/
2260922610
SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
22610
- return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
22611
+ testcase( p[0]&0x80 );
22612
+ return ((unsigned)p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
2261122613
}
2261222614
SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
2261322615
p[0] = (u8)(v>>24);
2261422616
p[1] = (u8)(v>>16);
2261522617
p[2] = (u8)(v>>8);
@@ -22946,11 +22948,11 @@
2294622948
2294722949
/*
2294822950
** The hashing function.
2294922951
*/
2295022952
static unsigned int strHash(const char *z, int nKey){
22951
- int h = 0;
22953
+ unsigned int h = 0;
2295222954
assert( nKey>=0 );
2295322955
while( nKey > 0 ){
2295422956
h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
2295522957
nKey--;
2295622958
}
@@ -27650,11 +27652,11 @@
2765027652
2765127653
/* Update the global lock state and do debug tracing */
2765227654
#ifdef SQLITE_DEBUG
2765327655
{ u16 mask;
2765427656
OSTRACE(("SHM-LOCK "));
27655
- mask = ofst>31 ? 0xffffffff : (1<<(ofst+n)) - (1<<ofst);
27657
+ mask = ofst>31 ? 0xffff : (1<<(ofst+n)) - (1<<ofst);
2765627658
if( rc==SQLITE_OK ){
2765727659
if( lockType==F_UNLCK ){
2765827660
OSTRACE(("unlock %d ok", ofst));
2765927661
pShmNode->exclMask &= ~mask;
2766027662
pShmNode->sharedMask &= ~mask;
@@ -35374,11 +35376,34 @@
3537435376
** function.
3537535377
*/
3537635378
static void *winConvertFromUtf8Filename(const char *zFilename){
3537735379
void *zConverted = 0;
3537835380
if( osIsNT() ){
35379
- zConverted = winUtf8ToUnicode(zFilename);
35381
+ int nChar;
35382
+ LPWSTR zWideFilename;
35383
+
35384
+ nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
35385
+ if( nChar==0 ){
35386
+ return 0;
35387
+ }
35388
+ zWideFilename = sqlite3MallocZero( nChar*sizeof(WCHAR)+8 );
35389
+ if( zWideFilename==0 ){
35390
+ return 0;
35391
+ }
35392
+ nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1,
35393
+ zWideFilename+4, nChar);
35394
+ if( nChar==0 ){
35395
+ sqlite3_free(zWideFilename);
35396
+ return 0;
35397
+ }else if( nChar>SQLITE_WIN32_MAX_PATH_CHARS
35398
+ && winIsDriveLetterAndColon(zFilename)
35399
+ && zFilename[2] == '\\' ){
35400
+ memcpy(zWideFilename, L"\\\\?\\", 8);
35401
+ }else{
35402
+ memmove(zWideFilename, zWideFilename+4, nChar*sizeof(WCHAR));
35403
+ }
35404
+ zConverted = zWideFilename;
3538035405
}
3538135406
#ifdef SQLITE_WIN32_HAS_ANSI
3538235407
else{
3538335408
zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
3538435409
}
@@ -36305,67 +36330,14 @@
3630536330
*/
3630636331
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
3630736332
sqlite3_data_directory, winGetDirSep(), zRelative);
3630836333
return SQLITE_OK;
3630936334
}
36310
- nByte = osMultiByteToWideChar(CP_UTF8, 0, zRelative, -1, NULL, 0);
36311
- if( nByte==0 ){
36312
- return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)osGetLastError(),
36313
- "winFullPathname", zRelative);
36314
- }
36315
- if( osIsNT() ){
36316
- LPWSTR zWideFilename;
36317
-
36318
- if( nByte>SQLITE_WIN32_MAX_PATH_CHARS ){
36319
- /* No Win32 API functions can handle such long paths. Let's see if
36320
- * we can do something about it. If not, just leave it as is. */
36321
- if( winIsDirSep(zRelative[0]) && winIsDirSep(zRelative[1])
36322
- && zRelative[2]!='?' ){
36323
- /* It's an UNC path, convert it to an extended UNC path. */
36324
- zWideFilename = sqlite3MallocZero( (nByte+6)*sizeof(WCHAR) );
36325
- if( zWideFilename==0 ){
36326
- return SQLITE_IOERR_NOMEM;
36327
- }
36328
- memcpy(zWideFilename, L"\\\\?\\UNC\\", 16);
36329
- nByte = osMultiByteToWideChar(CP_UTF8, 0, zRelative+2, -1,
36330
- zWideFilename+8, nByte);
36331
- goto finished;
36332
- }else if( winIsDriveLetterAndColon(zRelative)
36333
- && winIsDirSep(zRelative[2]) ){
36334
- /* It has a correct drive prefix, convert to extended form. */
36335
- zWideFilename = sqlite3MallocZero( (nByte+4)*sizeof(WCHAR) );
36336
- if( zWideFilename==0 ){
36337
- return SQLITE_IOERR_NOMEM;
36338
- }
36339
- memcpy(zWideFilename, L"\\\\?\\", 8);
36340
- nByte = osMultiByteToWideChar(CP_UTF8, 0, zRelative, -1,
36341
- zWideFilename+4, nByte);
36342
- zWideFilename[6] = '\\';
36343
- goto finished;
36344
- }
36345
- /* Another form, e.g. relative path or maybe it already
36346
- * has the '\\?\' prefix. Just leave it as-is. */
36347
- }
36348
- zWideFilename = sqlite3Malloc( nByte*sizeof(WCHAR) );
36349
- if( zWideFilename==0 ){
36350
- return SQLITE_IOERR_NOMEM;
36351
- }
36352
- nByte = osMultiByteToWideChar(CP_UTF8, 0, zRelative, -1,
36353
- zWideFilename, nByte);
36354
- if( nByte==0 ){
36355
- sqlite3_free(zWideFilename);
36356
- return SQLITE_IOERR_NOMEM;
36357
- }
36358
- finished:
36359
- zConverted = zWideFilename;
36360
- }else{
36361
- zConverted = sqlite3_win32_utf8_to_mbcs(zRelative);
36362
- if( zConverted==0 ){
36363
- return SQLITE_IOERR_NOMEM;
36364
- }
36365
- }
36366
-
36335
+ zConverted = winConvertFromUtf8Filename(zRelative);
36336
+ if( zConverted==0 ){
36337
+ return SQLITE_IOERR_NOMEM;
36338
+ }
3636736339
if( osIsNT() ){
3636836340
LPWSTR zTemp;
3636936341
nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
3637036342
if( nByte==0 ){
3637136343
sqlite3_free(zConverted);
@@ -38479,10 +38451,11 @@
3847938451
unsigned int nPinned;
3848038452
PCache1 *pCache = (PCache1 *)p;
3848138453
PGroup *pGroup;
3848238454
PgHdr1 *pPage = 0;
3848338455
38456
+ assert( offsetof(PgHdr1,page)==0 );
3848438457
assert( pCache->bPurgeable || createFlag!=1 );
3848538458
assert( pCache->bPurgeable || pCache->nMin==0 );
3848638459
assert( pCache->bPurgeable==0 || pCache->nMin==10 );
3848738460
assert( pCache->nMin==0 || pCache->bPurgeable );
3848838461
pcache1EnterMutex(pGroup = pCache->pGroup);
@@ -38584,11 +38557,11 @@
3858438557
fetch_out:
3858538558
if( pPage && iKey>pCache->iMaxKey ){
3858638559
pCache->iMaxKey = iKey;
3858738560
}
3858838561
pcache1LeaveMutex(pGroup);
38589
- return &pPage->page;
38562
+ return (sqlite3_pcache_page*)pPage;
3859038563
}
3859138564
3859238565
3859338566
/*
3859438567
** Implementation of the sqlite3_pcache.xUnpin method.
@@ -41124,11 +41097,11 @@
4112441097
** Find a page in the hash table given its page number. Return
4112541098
** a pointer to the page or NULL if the requested page is not
4112641099
** already in memory.
4112741100
*/
4112841101
static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
41129
- PgHdr *p; /* Return value */
41102
+ PgHdr *p = 0; /* Return value */
4113041103
4113141104
/* It is not possible for a call to PcacheFetch() with createFlag==0 to
4113241105
** fail, since no attempt to allocate dynamic memory will be made.
4113341106
*/
4113441107
(void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);
@@ -60551,11 +60524,11 @@
6055160524
#endif /* SQLITE_DEBUG */
6055260525
6055360526
/*
6055460527
** Size of struct Mem not including the Mem.zMalloc member.
6055560528
*/
60556
-#define MEMCELLSIZE (size_t)(&(((Mem *)0)->zMalloc))
60529
+#define MEMCELLSIZE offsetof(Mem,zMalloc)
6055760530
6055860531
/*
6055960532
** Make an shallow copy of pFrom into pTo. Prior contents of
6056060533
** pTo are freed. The pFrom->z field is not duplicated. If
6056160534
** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
@@ -63955,12 +63928,13 @@
6395563928
SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){
6395663929
AuxData **pp = &pVdbe->pAuxData;
6395763930
while( *pp ){
6395863931
AuxData *pAux = *pp;
6395963932
if( (iOp<0)
63960
- || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & ((u32)1<<pAux->iArg))))
63933
+ || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & MASKBIT32(pAux->iArg))))
6396163934
){
63935
+ testcase( pAux->iArg==31 );
6396263936
if( pAux->xDelete ){
6396363937
pAux->xDelete(pAux->pAux);
6396463938
}
6396563939
*pp = pAux->pNext;
6396663940
sqlite3DbFree(pVdbe->db, pAux);
@@ -64271,10 +64245,13 @@
6427164245
SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
6427264246
const unsigned char *buf, /* Buffer to deserialize from */
6427364247
u32 serial_type, /* Serial type to deserialize */
6427464248
Mem *pMem /* Memory cell to write value into */
6427564249
){
64250
+ u64 x;
64251
+ u32 y;
64252
+ int i;
6427664253
switch( serial_type ){
6427764254
case 10: /* Reserved for future use */
6427864255
case 11: /* Reserved for future use */
6427964256
case 0: { /* NULL */
6428064257
pMem->flags = MEM_Null;
@@ -64284,36 +64261,37 @@
6428464261
pMem->u.i = (signed char)buf[0];
6428564262
pMem->flags = MEM_Int;
6428664263
return 1;
6428764264
}
6428864265
case 2: { /* 2-byte signed integer */
64289
- pMem->u.i = (((signed char)buf[0])<<8) | buf[1];
64266
+ i = 256*(signed char)buf[0] | buf[1];
64267
+ pMem->u.i = (i64)i;
6429064268
pMem->flags = MEM_Int;
6429164269
return 2;
6429264270
}
6429364271
case 3: { /* 3-byte signed integer */
64294
- pMem->u.i = (((signed char)buf[0])<<16) | (buf[1]<<8) | buf[2];
64272
+ i = 65536*(signed char)buf[0] | (buf[1]<<8) | buf[2];
64273
+ pMem->u.i = (i64)i;
6429564274
pMem->flags = MEM_Int;
6429664275
return 3;
6429764276
}
6429864277
case 4: { /* 4-byte signed integer */
64299
- pMem->u.i = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
64278
+ y = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
64279
+ pMem->u.i = (i64)*(int*)&y;
6430064280
pMem->flags = MEM_Int;
6430164281
return 4;
6430264282
}
6430364283
case 5: { /* 6-byte signed integer */
64304
- u64 x = (((signed char)buf[0])<<8) | buf[1];
64305
- u32 y = (buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
64284
+ x = 256*(signed char)buf[0] + buf[1];
64285
+ y = ((unsigned)buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
6430664286
x = (x<<32) | y;
6430764287
pMem->u.i = *(i64*)&x;
6430864288
pMem->flags = MEM_Int;
6430964289
return 6;
6431064290
}
6431164291
case 6: /* 8-byte signed integer */
6431264292
case 7: { /* IEEE floating point */
64313
- u64 x;
64314
- u32 y;
6431564293
#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT)
6431664294
/* Verify that integers and floating point values use the same
6431764295
** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
6431864296
** defined that 64-bit floating point values really are mixed
6431964297
** endian.
@@ -64322,13 +64300,12 @@
6432264300
static const double r1 = 1.0;
6432364301
u64 t2 = t1;
6432464302
swapMixedEndianFloat(t2);
6432564303
assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
6432664304
#endif
64327
-
64328
- x = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
64329
- y = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
64305
+ x = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
64306
+ y = ((unsigned)buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
6433064307
x = (x<<32) | y;
6433164308
if( serial_type==6 ){
6433264309
pMem->u.i = *(i64*)&x;
6433364310
pMem->flags = MEM_Int;
6433464311
}else{
@@ -72653,11 +72630,11 @@
7265372630
#ifdef SQLITE_USE_FCNTL_TRACE
7265472631
zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
7265572632
if( zTrace ){
7265672633
int i;
7265772634
for(i=0; i<db->nDb; i++){
72658
- if( ((1<<i) & p->btreeMask)==0 ) continue;
72635
+ if( MASKBIT(i) & p->btreeMask)==0 ) continue;
7265972636
sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
7266072637
}
7266172638
}
7266272639
#endif /* SQLITE_USE_FCNTL_TRACE */
7266372640
#ifdef SQLITE_DEBUG
@@ -77499,10 +77476,11 @@
7749977476
pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
7750077477
pNew->pRightmost = 0;
7750177478
pNew->addrOpenEphm[0] = -1;
7750277479
pNew->addrOpenEphm[1] = -1;
7750377480
pNew->addrOpenEphm[2] = -1;
77481
+ pNew->nSelectRow = p->nSelectRow;
7750477482
pNew->pWith = withDup(db, p->pWith);
7750577483
return pNew;
7750677484
}
7750777485
#else
7750877486
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
@@ -79120,11 +79098,11 @@
7912079098
ExprList *pFarg; /* List of function arguments */
7912179099
int nFarg; /* Number of function arguments */
7912279100
FuncDef *pDef; /* The function definition object */
7912379101
int nId; /* Length of the function name in bytes */
7912479102
const char *zId; /* The function name */
79125
- int constMask = 0; /* Mask of function arguments that are constant */
79103
+ u32 constMask = 0; /* Mask of function arguments that are constant */
7912679104
int i; /* Loop counter */
7912779105
u8 enc = ENC(db); /* The text encoding used by this database */
7912879106
CollSeq *pColl = 0; /* A collating sequence */
7912979107
7913079108
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
@@ -79171,11 +79149,12 @@
7917179149
break;
7917279150
}
7917379151
7917479152
for(i=0; i<nFarg; i++){
7917579153
if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
79176
- constMask |= (1<<i);
79154
+ testcase( i==31 );
79155
+ constMask |= MASKBIT32(i);
7917779156
}
7917879157
if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
7917979158
pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
7918079159
}
7918179160
}
@@ -89527,11 +89506,13 @@
8952789506
8952889507
/* Populate the OLD.* pseudo-table register array. These values will be
8952989508
** used by any BEFORE and AFTER triggers that exist. */
8953089509
sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld);
8953189510
for(iCol=0; iCol<pTab->nCol; iCol++){
89532
- if( mask==0xffffffff || mask&(1<<iCol) ){
89511
+ testcase( mask!=0xffffffff && iCol==31 );
89512
+ testcase( mask!=0xffffffff && iCol==32 );
89513
+ if( mask==0xffffffff || (iCol<=31 && (mask & MASKBIT32(iCol))!=0) ){
8953389514
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1);
8953489515
}
8953589516
}
8953689517
8953789518
/* Invoke BEFORE DELETE trigger programs. */
@@ -89847,11 +89828,11 @@
8984789828
UNUSED_PARAMETER(argc);
8984889829
switch( sqlite3_value_type(argv[0]) ){
8984989830
case SQLITE_INTEGER: {
8985089831
i64 iVal = sqlite3_value_int64(argv[0]);
8985189832
if( iVal<0 ){
89852
- if( (iVal<<1)==0 ){
89833
+ if( iVal==SMALLEST_INT64 ){
8985389834
/* IMP: R-31676-45509 If X is the integer -9223372036854775808
8985489835
** then abs(X) throws an integer overflow error since there is no
8985589836
** equivalent positive 64-bit two complement value. */
8985689837
sqlite3_result_error(context, "integer overflow", -1);
8985789838
return;
@@ -100310,10 +100291,11 @@
100310100291
** on a second ephemeral index that holds all values every previously
100311100292
** added to the queue. Only add this new value if it has never before
100312100293
** been added */
100313100294
addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, r3, 0);
100314100295
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3);
100296
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
100315100297
}
100316100298
for(i=0; i<nKey; i++){
100317100299
sqlite3VdbeAddOp2(v, OP_SCopy,
100318100300
regResult + pSO->a[i].u.x.iOrderByCol - 1,
100319100301
r2+i);
@@ -101220,11 +101202,48 @@
101220101202
if( pRet==0 && iCol<p->pEList->nExpr ){
101221101203
pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr);
101222101204
}
101223101205
return pRet;
101224101206
}
101225
-#endif /* SQLITE_OMIT_COMPOUND_SELECT */
101207
+
101208
+/*
101209
+** The select statement passed as the second parameter is a compound SELECT
101210
+** with an ORDER BY clause. This function allocates and returns a KeyInfo
101211
+** structure suitable for implementing the ORDER BY.
101212
+**
101213
+** Space to hold the KeyInfo structure is obtained from malloc. The calling
101214
+** function is responsible for ensuring that this structure is eventually
101215
+** freed.
101216
+*/
101217
+static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
101218
+ ExprList *pOrderBy = p->pOrderBy;
101219
+ int nOrderBy = p->pOrderBy->nExpr;
101220
+ sqlite3 *db = pParse->db;
101221
+ KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1);
101222
+ if( pRet ){
101223
+ int i;
101224
+ for(i=0; i<nOrderBy; i++){
101225
+ struct ExprList_item *pItem = &pOrderBy->a[i];
101226
+ Expr *pTerm = pItem->pExpr;
101227
+ CollSeq *pColl;
101228
+
101229
+ if( pTerm->flags & EP_Collate ){
101230
+ pColl = sqlite3ExprCollSeq(pParse, pTerm);
101231
+ }else{
101232
+ pColl = multiSelectCollSeq(pParse, p, pItem->u.x.iOrderByCol-1);
101233
+ if( pColl==0 ) pColl = db->pDfltColl;
101234
+ pOrderBy->a[i].pExpr =
101235
+ sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
101236
+ }
101237
+ assert( sqlite3KeyInfoIsWriteable(pRet) );
101238
+ pRet->aColl[i] = pColl;
101239
+ pRet->aSortOrder[i] = pOrderBy->a[i].sortOrder;
101240
+ }
101241
+ }
101242
+
101243
+ return pRet;
101244
+}
101226101245
101227101246
#ifndef SQLITE_OMIT_CTE
101228101247
/*
101229101248
** This routine generates VDBE code to compute the content of a WITH RECURSIVE
101230101249
** query of the form:
@@ -101294,23 +101313,20 @@
101294101313
pOffset = p->pOffset;
101295101314
regLimit = p->iLimit;
101296101315
regOffset = p->iOffset;
101297101316
p->pLimit = p->pOffset = 0;
101298101317
p->iLimit = p->iOffset = 0;
101318
+ pOrderBy = p->pOrderBy;
101299101319
101300101320
/* Locate the cursor number of the Current table */
101301101321
for(i=0; ALWAYS(i<pSrc->nSrc); i++){
101302101322
if( pSrc->a[i].isRecursive ){
101303101323
iCurrent = pSrc->a[i].iCursor;
101304101324
break;
101305101325
}
101306101326
}
101307101327
101308
- /* Detach the ORDER BY clause from the compound SELECT */
101309
- pOrderBy = p->pOrderBy;
101310
- p->pOrderBy = 0;
101311
-
101312101328
/* Allocate cursors numbers for Queue and Distinct. The cursor number for
101313101329
** the Distinct table must be exactly one greater than Queue in order
101314101330
** for the SRT_DistTable and SRT_DistQueue destinations to work. */
101315101331
iQueue = pParse->nTab++;
101316101332
if( p->op==TK_UNION ){
@@ -101323,11 +101339,11 @@
101323101339
101324101340
/* Allocate cursors for Current, Queue, and Distinct. */
101325101341
regCurrent = ++pParse->nMem;
101326101342
sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol);
101327101343
if( pOrderBy ){
101328
- KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pOrderBy, 1);
101344
+ KeyInfo *pKeyInfo = multiSelectOrderByKeyInfo(pParse, p, 1);
101329101345
sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0,
101330101346
(char*)pKeyInfo, P4_KEYINFO);
101331101347
destQueue.pOrderBy = pOrderBy;
101332101348
}else{
101333101349
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iQueue, nCol);
@@ -101335,10 +101351,13 @@
101335101351
VdbeComment((v, "Queue table"));
101336101352
if( iDistinct ){
101337101353
p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0);
101338101354
p->selFlags |= SF_UsesEphemeral;
101339101355
}
101356
+
101357
+ /* Detach the ORDER BY clause from the compound SELECT */
101358
+ p->pOrderBy = 0;
101340101359
101341101360
/* Store the results of the setup-query in Queue. */
101342101361
rc = sqlite3Select(pParse, pSetup, &destQueue);
101343101362
if( rc ) goto end_of_recursive_query;
101344101363
@@ -101378,21 +101397,20 @@
101378101397
p->pOrderBy = pOrderBy;
101379101398
p->pLimit = pLimit;
101380101399
p->pOffset = pOffset;
101381101400
return;
101382101401
}
101383
-#endif
101402
+#endif /* SQLITE_OMIT_CTE */
101384101403
101385101404
/* Forward references */
101386101405
static int multiSelectOrderBy(
101387101406
Parse *pParse, /* Parsing context */
101388101407
Select *p, /* The right-most of SELECTs to be coded */
101389101408
SelectDest *pDest /* What to do with query results */
101390101409
);
101391101410
101392101411
101393
-#ifndef SQLITE_OMIT_COMPOUND_SELECT
101394101412
/*
101395101413
** This routine is called to process a compound query form from
101396101414
** two or more separate queries using UNION, UNION ALL, EXCEPT, or
101397101415
** INTERSECT
101398101416
**
@@ -102120,28 +102138,11 @@
102120102138
for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
102121102139
assert( pItem->u.x.iOrderByCol>0
102122102140
&& pItem->u.x.iOrderByCol<=p->pEList->nExpr );
102123102141
aPermute[i] = pItem->u.x.iOrderByCol - 1;
102124102142
}
102125
- pKeyMerge = sqlite3KeyInfoAlloc(db, nOrderBy, 1);
102126
- if( pKeyMerge ){
102127
- for(i=0; i<nOrderBy; i++){
102128
- CollSeq *pColl;
102129
- Expr *pTerm = pOrderBy->a[i].pExpr;
102130
- if( pTerm->flags & EP_Collate ){
102131
- pColl = sqlite3ExprCollSeq(pParse, pTerm);
102132
- }else{
102133
- pColl = multiSelectCollSeq(pParse, p, aPermute[i]);
102134
- if( pColl==0 ) pColl = db->pDfltColl;
102135
- pOrderBy->a[i].pExpr =
102136
- sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
102137
- }
102138
- assert( sqlite3KeyInfoIsWriteable(pKeyMerge) );
102139
- pKeyMerge->aColl[i] = pColl;
102140
- pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder;
102141
- }
102142
- }
102143
+ pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1);
102143102144
}else{
102144102145
pKeyMerge = 0;
102145102146
}
102146102147
102147102148
/* Reattach the ORDER BY clause to the query.
@@ -106614,13 +106615,14 @@
106614106615
oldmask |= sqlite3TriggerColmask(pParse,
106615106616
pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
106616106617
);
106617106618
for(i=0; i<pTab->nCol; i++){
106618106619
if( oldmask==0xffffffff
106619
- || (i<32 && (oldmask & (1<<i)))
106620
+ || (i<32 && (oldmask & MASKBIT32(i))!=0)
106620106621
|| (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0
106621106622
){
106623
+ testcase( oldmask!=0xffffffff && i==31 );
106622106624
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i);
106623106625
}else{
106624106626
sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
106625106627
}
106626106628
}
@@ -106651,11 +106653,11 @@
106651106653
sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
106652106654
}else{
106653106655
j = aXRef[i];
106654106656
if( j>=0 ){
106655106657
sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
106656
- }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask&(1<<i)) ){
106658
+ }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){
106657106659
/* This branch loads the value of a column that will not be changed
106658106660
** into a register. This is done if there are no BEFORE triggers, or
106659106661
** if there are one or more BEFORE triggers that use this value via
106660106662
** a new.* reference in a trigger program.
106661106663
*/
@@ -112160,11 +112162,13 @@
112160112162
int iTerm;
112161112163
for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
112162112164
Expr *pExpr = pWC->a[iTerm].pExpr;
112163112165
if( &pWC->a[iTerm] == pTerm ) continue;
112164112166
if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
112165
- if( pWC->a[iTerm].wtFlags & (TERM_ORINFO) ) continue;
112167
+ testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO );
112168
+ testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL );
112169
+ if( pWC->a[iTerm].wtFlags & (TERM_ORINFO|TERM_VIRTUAL) ) continue;
112166112170
if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
112167112171
pExpr = sqlite3ExprDup(db, pExpr, 0);
112168112172
pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
112169112173
}
112170112174
if( pAndExpr ){
@@ -122726,11 +122730,11 @@
122726122730
** database files might have arbitrary corruption. Setting the flag during
122727122731
** testing causes certain assert() statements in the code to be activated
122728122732
** that demonstrat invariants on well-formed database files.
122729122733
*/
122730122734
case SQLITE_TESTCTRL_NEVER_CORRUPT: {
122731
- sqlite3Config.neverCorrupt = va_arg(ap, int);
122735
+ sqlite3GlobalConfig.neverCorrupt = va_arg(ap, int);
122732122736
break;
122733122737
}
122734122738
122735122739
}
122736122740
va_end(ap);
@@ -131724,17 +131728,17 @@
131724131728
/*
131725131729
** Hash and comparison functions when the mode is FTS3_HASH_STRING
131726131730
*/
131727131731
static int fts3StrHash(const void *pKey, int nKey){
131728131732
const char *z = (const char *)pKey;
131729
- int h = 0;
131733
+ unsigned h = 0;
131730131734
if( nKey<=0 ) nKey = (int) strlen(z);
131731131735
while( nKey > 0 ){
131732131736
h = (h<<3) ^ h ^ *z++;
131733131737
nKey--;
131734131738
}
131735
- return h & 0x7fffffff;
131739
+ return (int)(h & 0x7fffffff);
131736131740
}
131737131741
static int fts3StrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
131738131742
if( n1!=n2 ) return 1;
131739131743
return strncmp((const char*)pKey1,(const char*)pKey2,n1);
131740131744
}
131741131745
--- 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-22 18:31:27 dea2ca6a159d5dcfd8deceedf1c2a73fb4ac1cfc"
141
142 /*
143 ** CAPI3REF: Run-Time Library Version Numbers
144 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
145 **
@@ -11303,10 +11303,11 @@
11303
11304 /*
11305 ** A bit in a Bitmask
11306 */
11307 #define MASKBIT(n) (((Bitmask)1)<<(n))
 
11308
11309 /*
11310 ** The following structure describes the FROM clause of a SELECT statement.
11311 ** Each table or subquery in the FROM clause is a separate element of
11312 ** the SrcList.a[] array.
@@ -22605,11 +22606,12 @@
22605
22606 /*
22607 ** Read or write a four-byte big-endian integer value.
22608 */
22609 SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
22610 return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
 
22611 }
22612 SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
22613 p[0] = (u8)(v>>24);
22614 p[1] = (u8)(v>>16);
22615 p[2] = (u8)(v>>8);
@@ -22946,11 +22948,11 @@
22946
22947 /*
22948 ** The hashing function.
22949 */
22950 static unsigned int strHash(const char *z, int nKey){
22951 int h = 0;
22952 assert( nKey>=0 );
22953 while( nKey > 0 ){
22954 h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
22955 nKey--;
22956 }
@@ -27650,11 +27652,11 @@
27650
27651 /* Update the global lock state and do debug tracing */
27652 #ifdef SQLITE_DEBUG
27653 { u16 mask;
27654 OSTRACE(("SHM-LOCK "));
27655 mask = ofst>31 ? 0xffffffff : (1<<(ofst+n)) - (1<<ofst);
27656 if( rc==SQLITE_OK ){
27657 if( lockType==F_UNLCK ){
27658 OSTRACE(("unlock %d ok", ofst));
27659 pShmNode->exclMask &= ~mask;
27660 pShmNode->sharedMask &= ~mask;
@@ -35374,11 +35376,34 @@
35374 ** function.
35375 */
35376 static void *winConvertFromUtf8Filename(const char *zFilename){
35377 void *zConverted = 0;
35378 if( osIsNT() ){
35379 zConverted = winUtf8ToUnicode(zFilename);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35380 }
35381 #ifdef SQLITE_WIN32_HAS_ANSI
35382 else{
35383 zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
35384 }
@@ -36305,67 +36330,14 @@
36305 */
36306 sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
36307 sqlite3_data_directory, winGetDirSep(), zRelative);
36308 return SQLITE_OK;
36309 }
36310 nByte = osMultiByteToWideChar(CP_UTF8, 0, zRelative, -1, NULL, 0);
36311 if( nByte==0 ){
36312 return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)osGetLastError(),
36313 "winFullPathname", zRelative);
36314 }
36315 if( osIsNT() ){
36316 LPWSTR zWideFilename;
36317
36318 if( nByte>SQLITE_WIN32_MAX_PATH_CHARS ){
36319 /* No Win32 API functions can handle such long paths. Let's see if
36320 * we can do something about it. If not, just leave it as is. */
36321 if( winIsDirSep(zRelative[0]) && winIsDirSep(zRelative[1])
36322 && zRelative[2]!='?' ){
36323 /* It's an UNC path, convert it to an extended UNC path. */
36324 zWideFilename = sqlite3MallocZero( (nByte+6)*sizeof(WCHAR) );
36325 if( zWideFilename==0 ){
36326 return SQLITE_IOERR_NOMEM;
36327 }
36328 memcpy(zWideFilename, L"\\\\?\\UNC\\", 16);
36329 nByte = osMultiByteToWideChar(CP_UTF8, 0, zRelative+2, -1,
36330 zWideFilename+8, nByte);
36331 goto finished;
36332 }else if( winIsDriveLetterAndColon(zRelative)
36333 && winIsDirSep(zRelative[2]) ){
36334 /* It has a correct drive prefix, convert to extended form. */
36335 zWideFilename = sqlite3MallocZero( (nByte+4)*sizeof(WCHAR) );
36336 if( zWideFilename==0 ){
36337 return SQLITE_IOERR_NOMEM;
36338 }
36339 memcpy(zWideFilename, L"\\\\?\\", 8);
36340 nByte = osMultiByteToWideChar(CP_UTF8, 0, zRelative, -1,
36341 zWideFilename+4, nByte);
36342 zWideFilename[6] = '\\';
36343 goto finished;
36344 }
36345 /* Another form, e.g. relative path or maybe it already
36346 * has the '\\?\' prefix. Just leave it as-is. */
36347 }
36348 zWideFilename = sqlite3Malloc( nByte*sizeof(WCHAR) );
36349 if( zWideFilename==0 ){
36350 return SQLITE_IOERR_NOMEM;
36351 }
36352 nByte = osMultiByteToWideChar(CP_UTF8, 0, zRelative, -1,
36353 zWideFilename, nByte);
36354 if( nByte==0 ){
36355 sqlite3_free(zWideFilename);
36356 return SQLITE_IOERR_NOMEM;
36357 }
36358 finished:
36359 zConverted = zWideFilename;
36360 }else{
36361 zConverted = sqlite3_win32_utf8_to_mbcs(zRelative);
36362 if( zConverted==0 ){
36363 return SQLITE_IOERR_NOMEM;
36364 }
36365 }
36366
36367 if( osIsNT() ){
36368 LPWSTR zTemp;
36369 nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
36370 if( nByte==0 ){
36371 sqlite3_free(zConverted);
@@ -38479,10 +38451,11 @@
38479 unsigned int nPinned;
38480 PCache1 *pCache = (PCache1 *)p;
38481 PGroup *pGroup;
38482 PgHdr1 *pPage = 0;
38483
 
38484 assert( pCache->bPurgeable || createFlag!=1 );
38485 assert( pCache->bPurgeable || pCache->nMin==0 );
38486 assert( pCache->bPurgeable==0 || pCache->nMin==10 );
38487 assert( pCache->nMin==0 || pCache->bPurgeable );
38488 pcache1EnterMutex(pGroup = pCache->pGroup);
@@ -38584,11 +38557,11 @@
38584 fetch_out:
38585 if( pPage && iKey>pCache->iMaxKey ){
38586 pCache->iMaxKey = iKey;
38587 }
38588 pcache1LeaveMutex(pGroup);
38589 return &pPage->page;
38590 }
38591
38592
38593 /*
38594 ** Implementation of the sqlite3_pcache.xUnpin method.
@@ -41124,11 +41097,11 @@
41124 ** Find a page in the hash table given its page number. Return
41125 ** a pointer to the page or NULL if the requested page is not
41126 ** already in memory.
41127 */
41128 static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
41129 PgHdr *p; /* Return value */
41130
41131 /* It is not possible for a call to PcacheFetch() with createFlag==0 to
41132 ** fail, since no attempt to allocate dynamic memory will be made.
41133 */
41134 (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);
@@ -60551,11 +60524,11 @@
60551 #endif /* SQLITE_DEBUG */
60552
60553 /*
60554 ** Size of struct Mem not including the Mem.zMalloc member.
60555 */
60556 #define MEMCELLSIZE (size_t)(&(((Mem *)0)->zMalloc))
60557
60558 /*
60559 ** Make an shallow copy of pFrom into pTo. Prior contents of
60560 ** pTo are freed. The pFrom->z field is not duplicated. If
60561 ** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
@@ -63955,12 +63928,13 @@
63955 SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){
63956 AuxData **pp = &pVdbe->pAuxData;
63957 while( *pp ){
63958 AuxData *pAux = *pp;
63959 if( (iOp<0)
63960 || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & ((u32)1<<pAux->iArg))))
63961 ){
 
63962 if( pAux->xDelete ){
63963 pAux->xDelete(pAux->pAux);
63964 }
63965 *pp = pAux->pNext;
63966 sqlite3DbFree(pVdbe->db, pAux);
@@ -64271,10 +64245,13 @@
64271 SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
64272 const unsigned char *buf, /* Buffer to deserialize from */
64273 u32 serial_type, /* Serial type to deserialize */
64274 Mem *pMem /* Memory cell to write value into */
64275 ){
 
 
 
64276 switch( serial_type ){
64277 case 10: /* Reserved for future use */
64278 case 11: /* Reserved for future use */
64279 case 0: { /* NULL */
64280 pMem->flags = MEM_Null;
@@ -64284,36 +64261,37 @@
64284 pMem->u.i = (signed char)buf[0];
64285 pMem->flags = MEM_Int;
64286 return 1;
64287 }
64288 case 2: { /* 2-byte signed integer */
64289 pMem->u.i = (((signed char)buf[0])<<8) | buf[1];
 
64290 pMem->flags = MEM_Int;
64291 return 2;
64292 }
64293 case 3: { /* 3-byte signed integer */
64294 pMem->u.i = (((signed char)buf[0])<<16) | (buf[1]<<8) | buf[2];
 
64295 pMem->flags = MEM_Int;
64296 return 3;
64297 }
64298 case 4: { /* 4-byte signed integer */
64299 pMem->u.i = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
 
64300 pMem->flags = MEM_Int;
64301 return 4;
64302 }
64303 case 5: { /* 6-byte signed integer */
64304 u64 x = (((signed char)buf[0])<<8) | buf[1];
64305 u32 y = (buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
64306 x = (x<<32) | y;
64307 pMem->u.i = *(i64*)&x;
64308 pMem->flags = MEM_Int;
64309 return 6;
64310 }
64311 case 6: /* 8-byte signed integer */
64312 case 7: { /* IEEE floating point */
64313 u64 x;
64314 u32 y;
64315 #if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT)
64316 /* Verify that integers and floating point values use the same
64317 ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
64318 ** defined that 64-bit floating point values really are mixed
64319 ** endian.
@@ -64322,13 +64300,12 @@
64322 static const double r1 = 1.0;
64323 u64 t2 = t1;
64324 swapMixedEndianFloat(t2);
64325 assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
64326 #endif
64327
64328 x = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
64329 y = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
64330 x = (x<<32) | y;
64331 if( serial_type==6 ){
64332 pMem->u.i = *(i64*)&x;
64333 pMem->flags = MEM_Int;
64334 }else{
@@ -72653,11 +72630,11 @@
72653 #ifdef SQLITE_USE_FCNTL_TRACE
72654 zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
72655 if( zTrace ){
72656 int i;
72657 for(i=0; i<db->nDb; i++){
72658 if( ((1<<i) & p->btreeMask)==0 ) continue;
72659 sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
72660 }
72661 }
72662 #endif /* SQLITE_USE_FCNTL_TRACE */
72663 #ifdef SQLITE_DEBUG
@@ -77499,10 +77476,11 @@
77499 pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
77500 pNew->pRightmost = 0;
77501 pNew->addrOpenEphm[0] = -1;
77502 pNew->addrOpenEphm[1] = -1;
77503 pNew->addrOpenEphm[2] = -1;
 
77504 pNew->pWith = withDup(db, p->pWith);
77505 return pNew;
77506 }
77507 #else
77508 SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
@@ -79120,11 +79098,11 @@
79120 ExprList *pFarg; /* List of function arguments */
79121 int nFarg; /* Number of function arguments */
79122 FuncDef *pDef; /* The function definition object */
79123 int nId; /* Length of the function name in bytes */
79124 const char *zId; /* The function name */
79125 int constMask = 0; /* Mask of function arguments that are constant */
79126 int i; /* Loop counter */
79127 u8 enc = ENC(db); /* The text encoding used by this database */
79128 CollSeq *pColl = 0; /* A collating sequence */
79129
79130 assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
@@ -79171,11 +79149,12 @@
79171 break;
79172 }
79173
79174 for(i=0; i<nFarg; i++){
79175 if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
79176 constMask |= (1<<i);
 
79177 }
79178 if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
79179 pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
79180 }
79181 }
@@ -89527,11 +89506,13 @@
89527
89528 /* Populate the OLD.* pseudo-table register array. These values will be
89529 ** used by any BEFORE and AFTER triggers that exist. */
89530 sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld);
89531 for(iCol=0; iCol<pTab->nCol; iCol++){
89532 if( mask==0xffffffff || mask&(1<<iCol) ){
 
 
89533 sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1);
89534 }
89535 }
89536
89537 /* Invoke BEFORE DELETE trigger programs. */
@@ -89847,11 +89828,11 @@
89847 UNUSED_PARAMETER(argc);
89848 switch( sqlite3_value_type(argv[0]) ){
89849 case SQLITE_INTEGER: {
89850 i64 iVal = sqlite3_value_int64(argv[0]);
89851 if( iVal<0 ){
89852 if( (iVal<<1)==0 ){
89853 /* IMP: R-31676-45509 If X is the integer -9223372036854775808
89854 ** then abs(X) throws an integer overflow error since there is no
89855 ** equivalent positive 64-bit two complement value. */
89856 sqlite3_result_error(context, "integer overflow", -1);
89857 return;
@@ -100310,10 +100291,11 @@
100310 ** on a second ephemeral index that holds all values every previously
100311 ** added to the queue. Only add this new value if it has never before
100312 ** been added */
100313 addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, r3, 0);
100314 sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3);
 
100315 }
100316 for(i=0; i<nKey; i++){
100317 sqlite3VdbeAddOp2(v, OP_SCopy,
100318 regResult + pSO->a[i].u.x.iOrderByCol - 1,
100319 r2+i);
@@ -101220,11 +101202,48 @@
101220 if( pRet==0 && iCol<p->pEList->nExpr ){
101221 pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr);
101222 }
101223 return pRet;
101224 }
101225 #endif /* SQLITE_OMIT_COMPOUND_SELECT */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101226
101227 #ifndef SQLITE_OMIT_CTE
101228 /*
101229 ** This routine generates VDBE code to compute the content of a WITH RECURSIVE
101230 ** query of the form:
@@ -101294,23 +101313,20 @@
101294 pOffset = p->pOffset;
101295 regLimit = p->iLimit;
101296 regOffset = p->iOffset;
101297 p->pLimit = p->pOffset = 0;
101298 p->iLimit = p->iOffset = 0;
 
101299
101300 /* Locate the cursor number of the Current table */
101301 for(i=0; ALWAYS(i<pSrc->nSrc); i++){
101302 if( pSrc->a[i].isRecursive ){
101303 iCurrent = pSrc->a[i].iCursor;
101304 break;
101305 }
101306 }
101307
101308 /* Detach the ORDER BY clause from the compound SELECT */
101309 pOrderBy = p->pOrderBy;
101310 p->pOrderBy = 0;
101311
101312 /* Allocate cursors numbers for Queue and Distinct. The cursor number for
101313 ** the Distinct table must be exactly one greater than Queue in order
101314 ** for the SRT_DistTable and SRT_DistQueue destinations to work. */
101315 iQueue = pParse->nTab++;
101316 if( p->op==TK_UNION ){
@@ -101323,11 +101339,11 @@
101323
101324 /* Allocate cursors for Current, Queue, and Distinct. */
101325 regCurrent = ++pParse->nMem;
101326 sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol);
101327 if( pOrderBy ){
101328 KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pOrderBy, 1);
101329 sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0,
101330 (char*)pKeyInfo, P4_KEYINFO);
101331 destQueue.pOrderBy = pOrderBy;
101332 }else{
101333 sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iQueue, nCol);
@@ -101335,10 +101351,13 @@
101335 VdbeComment((v, "Queue table"));
101336 if( iDistinct ){
101337 p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0);
101338 p->selFlags |= SF_UsesEphemeral;
101339 }
 
 
 
101340
101341 /* Store the results of the setup-query in Queue. */
101342 rc = sqlite3Select(pParse, pSetup, &destQueue);
101343 if( rc ) goto end_of_recursive_query;
101344
@@ -101378,21 +101397,20 @@
101378 p->pOrderBy = pOrderBy;
101379 p->pLimit = pLimit;
101380 p->pOffset = pOffset;
101381 return;
101382 }
101383 #endif
101384
101385 /* Forward references */
101386 static int multiSelectOrderBy(
101387 Parse *pParse, /* Parsing context */
101388 Select *p, /* The right-most of SELECTs to be coded */
101389 SelectDest *pDest /* What to do with query results */
101390 );
101391
101392
101393 #ifndef SQLITE_OMIT_COMPOUND_SELECT
101394 /*
101395 ** This routine is called to process a compound query form from
101396 ** two or more separate queries using UNION, UNION ALL, EXCEPT, or
101397 ** INTERSECT
101398 **
@@ -102120,28 +102138,11 @@
102120 for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
102121 assert( pItem->u.x.iOrderByCol>0
102122 && pItem->u.x.iOrderByCol<=p->pEList->nExpr );
102123 aPermute[i] = pItem->u.x.iOrderByCol - 1;
102124 }
102125 pKeyMerge = sqlite3KeyInfoAlloc(db, nOrderBy, 1);
102126 if( pKeyMerge ){
102127 for(i=0; i<nOrderBy; i++){
102128 CollSeq *pColl;
102129 Expr *pTerm = pOrderBy->a[i].pExpr;
102130 if( pTerm->flags & EP_Collate ){
102131 pColl = sqlite3ExprCollSeq(pParse, pTerm);
102132 }else{
102133 pColl = multiSelectCollSeq(pParse, p, aPermute[i]);
102134 if( pColl==0 ) pColl = db->pDfltColl;
102135 pOrderBy->a[i].pExpr =
102136 sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
102137 }
102138 assert( sqlite3KeyInfoIsWriteable(pKeyMerge) );
102139 pKeyMerge->aColl[i] = pColl;
102140 pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder;
102141 }
102142 }
102143 }else{
102144 pKeyMerge = 0;
102145 }
102146
102147 /* Reattach the ORDER BY clause to the query.
@@ -106614,13 +106615,14 @@
106614 oldmask |= sqlite3TriggerColmask(pParse,
106615 pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
106616 );
106617 for(i=0; i<pTab->nCol; i++){
106618 if( oldmask==0xffffffff
106619 || (i<32 && (oldmask & (1<<i)))
106620 || (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0
106621 ){
 
106622 sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i);
106623 }else{
106624 sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
106625 }
106626 }
@@ -106651,11 +106653,11 @@
106651 sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
106652 }else{
106653 j = aXRef[i];
106654 if( j>=0 ){
106655 sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
106656 }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask&(1<<i)) ){
106657 /* This branch loads the value of a column that will not be changed
106658 ** into a register. This is done if there are no BEFORE triggers, or
106659 ** if there are one or more BEFORE triggers that use this value via
106660 ** a new.* reference in a trigger program.
106661 */
@@ -112160,11 +112162,13 @@
112160 int iTerm;
112161 for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
112162 Expr *pExpr = pWC->a[iTerm].pExpr;
112163 if( &pWC->a[iTerm] == pTerm ) continue;
112164 if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
112165 if( pWC->a[iTerm].wtFlags & (TERM_ORINFO) ) continue;
 
 
112166 if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
112167 pExpr = sqlite3ExprDup(db, pExpr, 0);
112168 pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
112169 }
112170 if( pAndExpr ){
@@ -122726,11 +122730,11 @@
122726 ** database files might have arbitrary corruption. Setting the flag during
122727 ** testing causes certain assert() statements in the code to be activated
122728 ** that demonstrat invariants on well-formed database files.
122729 */
122730 case SQLITE_TESTCTRL_NEVER_CORRUPT: {
122731 sqlite3Config.neverCorrupt = va_arg(ap, int);
122732 break;
122733 }
122734
122735 }
122736 va_end(ap);
@@ -131724,17 +131728,17 @@
131724 /*
131725 ** Hash and comparison functions when the mode is FTS3_HASH_STRING
131726 */
131727 static int fts3StrHash(const void *pKey, int nKey){
131728 const char *z = (const char *)pKey;
131729 int h = 0;
131730 if( nKey<=0 ) nKey = (int) strlen(z);
131731 while( nKey > 0 ){
131732 h = (h<<3) ^ h ^ *z++;
131733 nKey--;
131734 }
131735 return h & 0x7fffffff;
131736 }
131737 static int fts3StrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
131738 if( n1!=n2 ) return 1;
131739 return strncmp((const char*)pKey1,(const char*)pKey2,n1);
131740 }
131741
--- 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 **
@@ -11303,10 +11303,11 @@
11303
11304 /*
11305 ** A bit in a Bitmask
11306 */
11307 #define MASKBIT(n) (((Bitmask)1)<<(n))
11308 #define MASKBIT32(n) (((unsigned int)1)<<(n))
11309
11310 /*
11311 ** The following structure describes the FROM clause of a SELECT statement.
11312 ** Each table or subquery in the FROM clause is a separate element of
11313 ** the SrcList.a[] array.
@@ -22605,11 +22606,12 @@
22606
22607 /*
22608 ** Read or write a four-byte big-endian integer value.
22609 */
22610 SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
22611 testcase( p[0]&0x80 );
22612 return ((unsigned)p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
22613 }
22614 SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
22615 p[0] = (u8)(v>>24);
22616 p[1] = (u8)(v>>16);
22617 p[2] = (u8)(v>>8);
@@ -22946,11 +22948,11 @@
22948
22949 /*
22950 ** The hashing function.
22951 */
22952 static unsigned int strHash(const char *z, int nKey){
22953 unsigned int h = 0;
22954 assert( nKey>=0 );
22955 while( nKey > 0 ){
22956 h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
22957 nKey--;
22958 }
@@ -27650,11 +27652,11 @@
27652
27653 /* Update the global lock state and do debug tracing */
27654 #ifdef SQLITE_DEBUG
27655 { u16 mask;
27656 OSTRACE(("SHM-LOCK "));
27657 mask = ofst>31 ? 0xffff : (1<<(ofst+n)) - (1<<ofst);
27658 if( rc==SQLITE_OK ){
27659 if( lockType==F_UNLCK ){
27660 OSTRACE(("unlock %d ok", ofst));
27661 pShmNode->exclMask &= ~mask;
27662 pShmNode->sharedMask &= ~mask;
@@ -35374,11 +35376,34 @@
35376 ** function.
35377 */
35378 static void *winConvertFromUtf8Filename(const char *zFilename){
35379 void *zConverted = 0;
35380 if( osIsNT() ){
35381 int nChar;
35382 LPWSTR zWideFilename;
35383
35384 nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
35385 if( nChar==0 ){
35386 return 0;
35387 }
35388 zWideFilename = sqlite3MallocZero( nChar*sizeof(WCHAR)+8 );
35389 if( zWideFilename==0 ){
35390 return 0;
35391 }
35392 nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1,
35393 zWideFilename+4, nChar);
35394 if( nChar==0 ){
35395 sqlite3_free(zWideFilename);
35396 return 0;
35397 }else if( nChar>SQLITE_WIN32_MAX_PATH_CHARS
35398 && winIsDriveLetterAndColon(zFilename)
35399 && zFilename[2] == '\\' ){
35400 memcpy(zWideFilename, L"\\\\?\\", 8);
35401 }else{
35402 memmove(zWideFilename, zWideFilename+4, nChar*sizeof(WCHAR));
35403 }
35404 zConverted = zWideFilename;
35405 }
35406 #ifdef SQLITE_WIN32_HAS_ANSI
35407 else{
35408 zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
35409 }
@@ -36305,67 +36330,14 @@
36330 */
36331 sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
36332 sqlite3_data_directory, winGetDirSep(), zRelative);
36333 return SQLITE_OK;
36334 }
36335 zConverted = winConvertFromUtf8Filename(zRelative);
36336 if( zConverted==0 ){
36337 return SQLITE_IOERR_NOMEM;
36338 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36339 if( osIsNT() ){
36340 LPWSTR zTemp;
36341 nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
36342 if( nByte==0 ){
36343 sqlite3_free(zConverted);
@@ -38479,10 +38451,11 @@
38451 unsigned int nPinned;
38452 PCache1 *pCache = (PCache1 *)p;
38453 PGroup *pGroup;
38454 PgHdr1 *pPage = 0;
38455
38456 assert( offsetof(PgHdr1,page)==0 );
38457 assert( pCache->bPurgeable || createFlag!=1 );
38458 assert( pCache->bPurgeable || pCache->nMin==0 );
38459 assert( pCache->bPurgeable==0 || pCache->nMin==10 );
38460 assert( pCache->nMin==0 || pCache->bPurgeable );
38461 pcache1EnterMutex(pGroup = pCache->pGroup);
@@ -38584,11 +38557,11 @@
38557 fetch_out:
38558 if( pPage && iKey>pCache->iMaxKey ){
38559 pCache->iMaxKey = iKey;
38560 }
38561 pcache1LeaveMutex(pGroup);
38562 return (sqlite3_pcache_page*)pPage;
38563 }
38564
38565
38566 /*
38567 ** Implementation of the sqlite3_pcache.xUnpin method.
@@ -41124,11 +41097,11 @@
41097 ** Find a page in the hash table given its page number. Return
41098 ** a pointer to the page or NULL if the requested page is not
41099 ** already in memory.
41100 */
41101 static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
41102 PgHdr *p = 0; /* Return value */
41103
41104 /* It is not possible for a call to PcacheFetch() with createFlag==0 to
41105 ** fail, since no attempt to allocate dynamic memory will be made.
41106 */
41107 (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);
@@ -60551,11 +60524,11 @@
60524 #endif /* SQLITE_DEBUG */
60525
60526 /*
60527 ** Size of struct Mem not including the Mem.zMalloc member.
60528 */
60529 #define MEMCELLSIZE offsetof(Mem,zMalloc)
60530
60531 /*
60532 ** Make an shallow copy of pFrom into pTo. Prior contents of
60533 ** pTo are freed. The pFrom->z field is not duplicated. If
60534 ** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
@@ -63955,12 +63928,13 @@
63928 SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){
63929 AuxData **pp = &pVdbe->pAuxData;
63930 while( *pp ){
63931 AuxData *pAux = *pp;
63932 if( (iOp<0)
63933 || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & MASKBIT32(pAux->iArg))))
63934 ){
63935 testcase( pAux->iArg==31 );
63936 if( pAux->xDelete ){
63937 pAux->xDelete(pAux->pAux);
63938 }
63939 *pp = pAux->pNext;
63940 sqlite3DbFree(pVdbe->db, pAux);
@@ -64271,10 +64245,13 @@
64245 SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
64246 const unsigned char *buf, /* Buffer to deserialize from */
64247 u32 serial_type, /* Serial type to deserialize */
64248 Mem *pMem /* Memory cell to write value into */
64249 ){
64250 u64 x;
64251 u32 y;
64252 int i;
64253 switch( serial_type ){
64254 case 10: /* Reserved for future use */
64255 case 11: /* Reserved for future use */
64256 case 0: { /* NULL */
64257 pMem->flags = MEM_Null;
@@ -64284,36 +64261,37 @@
64261 pMem->u.i = (signed char)buf[0];
64262 pMem->flags = MEM_Int;
64263 return 1;
64264 }
64265 case 2: { /* 2-byte signed integer */
64266 i = 256*(signed char)buf[0] | buf[1];
64267 pMem->u.i = (i64)i;
64268 pMem->flags = MEM_Int;
64269 return 2;
64270 }
64271 case 3: { /* 3-byte signed integer */
64272 i = 65536*(signed char)buf[0] | (buf[1]<<8) | buf[2];
64273 pMem->u.i = (i64)i;
64274 pMem->flags = MEM_Int;
64275 return 3;
64276 }
64277 case 4: { /* 4-byte signed integer */
64278 y = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
64279 pMem->u.i = (i64)*(int*)&y;
64280 pMem->flags = MEM_Int;
64281 return 4;
64282 }
64283 case 5: { /* 6-byte signed integer */
64284 x = 256*(signed char)buf[0] + buf[1];
64285 y = ((unsigned)buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
64286 x = (x<<32) | y;
64287 pMem->u.i = *(i64*)&x;
64288 pMem->flags = MEM_Int;
64289 return 6;
64290 }
64291 case 6: /* 8-byte signed integer */
64292 case 7: { /* IEEE floating point */
 
 
64293 #if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT)
64294 /* Verify that integers and floating point values use the same
64295 ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
64296 ** defined that 64-bit floating point values really are mixed
64297 ** endian.
@@ -64322,13 +64300,12 @@
64300 static const double r1 = 1.0;
64301 u64 t2 = t1;
64302 swapMixedEndianFloat(t2);
64303 assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
64304 #endif
64305 x = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
64306 y = ((unsigned)buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
 
64307 x = (x<<32) | y;
64308 if( serial_type==6 ){
64309 pMem->u.i = *(i64*)&x;
64310 pMem->flags = MEM_Int;
64311 }else{
@@ -72653,11 +72630,11 @@
72630 #ifdef SQLITE_USE_FCNTL_TRACE
72631 zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
72632 if( zTrace ){
72633 int i;
72634 for(i=0; i<db->nDb; i++){
72635 if( MASKBIT(i) & p->btreeMask)==0 ) continue;
72636 sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
72637 }
72638 }
72639 #endif /* SQLITE_USE_FCNTL_TRACE */
72640 #ifdef SQLITE_DEBUG
@@ -77499,10 +77476,11 @@
77476 pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
77477 pNew->pRightmost = 0;
77478 pNew->addrOpenEphm[0] = -1;
77479 pNew->addrOpenEphm[1] = -1;
77480 pNew->addrOpenEphm[2] = -1;
77481 pNew->nSelectRow = p->nSelectRow;
77482 pNew->pWith = withDup(db, p->pWith);
77483 return pNew;
77484 }
77485 #else
77486 SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
@@ -79120,11 +79098,11 @@
79098 ExprList *pFarg; /* List of function arguments */
79099 int nFarg; /* Number of function arguments */
79100 FuncDef *pDef; /* The function definition object */
79101 int nId; /* Length of the function name in bytes */
79102 const char *zId; /* The function name */
79103 u32 constMask = 0; /* Mask of function arguments that are constant */
79104 int i; /* Loop counter */
79105 u8 enc = ENC(db); /* The text encoding used by this database */
79106 CollSeq *pColl = 0; /* A collating sequence */
79107
79108 assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
@@ -79171,11 +79149,12 @@
79149 break;
79150 }
79151
79152 for(i=0; i<nFarg; i++){
79153 if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
79154 testcase( i==31 );
79155 constMask |= MASKBIT32(i);
79156 }
79157 if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
79158 pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
79159 }
79160 }
@@ -89527,11 +89506,13 @@
89506
89507 /* Populate the OLD.* pseudo-table register array. These values will be
89508 ** used by any BEFORE and AFTER triggers that exist. */
89509 sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld);
89510 for(iCol=0; iCol<pTab->nCol; iCol++){
89511 testcase( mask!=0xffffffff && iCol==31 );
89512 testcase( mask!=0xffffffff && iCol==32 );
89513 if( mask==0xffffffff || (iCol<=31 && (mask & MASKBIT32(iCol))!=0) ){
89514 sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1);
89515 }
89516 }
89517
89518 /* Invoke BEFORE DELETE trigger programs. */
@@ -89847,11 +89828,11 @@
89828 UNUSED_PARAMETER(argc);
89829 switch( sqlite3_value_type(argv[0]) ){
89830 case SQLITE_INTEGER: {
89831 i64 iVal = sqlite3_value_int64(argv[0]);
89832 if( iVal<0 ){
89833 if( iVal==SMALLEST_INT64 ){
89834 /* IMP: R-31676-45509 If X is the integer -9223372036854775808
89835 ** then abs(X) throws an integer overflow error since there is no
89836 ** equivalent positive 64-bit two complement value. */
89837 sqlite3_result_error(context, "integer overflow", -1);
89838 return;
@@ -100310,10 +100291,11 @@
100291 ** on a second ephemeral index that holds all values every previously
100292 ** added to the queue. Only add this new value if it has never before
100293 ** been added */
100294 addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, r3, 0);
100295 sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3);
100296 sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
100297 }
100298 for(i=0; i<nKey; i++){
100299 sqlite3VdbeAddOp2(v, OP_SCopy,
100300 regResult + pSO->a[i].u.x.iOrderByCol - 1,
100301 r2+i);
@@ -101220,11 +101202,48 @@
101202 if( pRet==0 && iCol<p->pEList->nExpr ){
101203 pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr);
101204 }
101205 return pRet;
101206 }
101207
101208 /*
101209 ** The select statement passed as the second parameter is a compound SELECT
101210 ** with an ORDER BY clause. This function allocates and returns a KeyInfo
101211 ** structure suitable for implementing the ORDER BY.
101212 **
101213 ** Space to hold the KeyInfo structure is obtained from malloc. The calling
101214 ** function is responsible for ensuring that this structure is eventually
101215 ** freed.
101216 */
101217 static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
101218 ExprList *pOrderBy = p->pOrderBy;
101219 int nOrderBy = p->pOrderBy->nExpr;
101220 sqlite3 *db = pParse->db;
101221 KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1);
101222 if( pRet ){
101223 int i;
101224 for(i=0; i<nOrderBy; i++){
101225 struct ExprList_item *pItem = &pOrderBy->a[i];
101226 Expr *pTerm = pItem->pExpr;
101227 CollSeq *pColl;
101228
101229 if( pTerm->flags & EP_Collate ){
101230 pColl = sqlite3ExprCollSeq(pParse, pTerm);
101231 }else{
101232 pColl = multiSelectCollSeq(pParse, p, pItem->u.x.iOrderByCol-1);
101233 if( pColl==0 ) pColl = db->pDfltColl;
101234 pOrderBy->a[i].pExpr =
101235 sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
101236 }
101237 assert( sqlite3KeyInfoIsWriteable(pRet) );
101238 pRet->aColl[i] = pColl;
101239 pRet->aSortOrder[i] = pOrderBy->a[i].sortOrder;
101240 }
101241 }
101242
101243 return pRet;
101244 }
101245
101246 #ifndef SQLITE_OMIT_CTE
101247 /*
101248 ** This routine generates VDBE code to compute the content of a WITH RECURSIVE
101249 ** query of the form:
@@ -101294,23 +101313,20 @@
101313 pOffset = p->pOffset;
101314 regLimit = p->iLimit;
101315 regOffset = p->iOffset;
101316 p->pLimit = p->pOffset = 0;
101317 p->iLimit = p->iOffset = 0;
101318 pOrderBy = p->pOrderBy;
101319
101320 /* Locate the cursor number of the Current table */
101321 for(i=0; ALWAYS(i<pSrc->nSrc); i++){
101322 if( pSrc->a[i].isRecursive ){
101323 iCurrent = pSrc->a[i].iCursor;
101324 break;
101325 }
101326 }
101327
 
 
 
 
101328 /* Allocate cursors numbers for Queue and Distinct. The cursor number for
101329 ** the Distinct table must be exactly one greater than Queue in order
101330 ** for the SRT_DistTable and SRT_DistQueue destinations to work. */
101331 iQueue = pParse->nTab++;
101332 if( p->op==TK_UNION ){
@@ -101323,11 +101339,11 @@
101339
101340 /* Allocate cursors for Current, Queue, and Distinct. */
101341 regCurrent = ++pParse->nMem;
101342 sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol);
101343 if( pOrderBy ){
101344 KeyInfo *pKeyInfo = multiSelectOrderByKeyInfo(pParse, p, 1);
101345 sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0,
101346 (char*)pKeyInfo, P4_KEYINFO);
101347 destQueue.pOrderBy = pOrderBy;
101348 }else{
101349 sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iQueue, nCol);
@@ -101335,10 +101351,13 @@
101351 VdbeComment((v, "Queue table"));
101352 if( iDistinct ){
101353 p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0);
101354 p->selFlags |= SF_UsesEphemeral;
101355 }
101356
101357 /* Detach the ORDER BY clause from the compound SELECT */
101358 p->pOrderBy = 0;
101359
101360 /* Store the results of the setup-query in Queue. */
101361 rc = sqlite3Select(pParse, pSetup, &destQueue);
101362 if( rc ) goto end_of_recursive_query;
101363
@@ -101378,21 +101397,20 @@
101397 p->pOrderBy = pOrderBy;
101398 p->pLimit = pLimit;
101399 p->pOffset = pOffset;
101400 return;
101401 }
101402 #endif /* SQLITE_OMIT_CTE */
101403
101404 /* Forward references */
101405 static int multiSelectOrderBy(
101406 Parse *pParse, /* Parsing context */
101407 Select *p, /* The right-most of SELECTs to be coded */
101408 SelectDest *pDest /* What to do with query results */
101409 );
101410
101411
 
101412 /*
101413 ** This routine is called to process a compound query form from
101414 ** two or more separate queries using UNION, UNION ALL, EXCEPT, or
101415 ** INTERSECT
101416 **
@@ -102120,28 +102138,11 @@
102138 for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
102139 assert( pItem->u.x.iOrderByCol>0
102140 && pItem->u.x.iOrderByCol<=p->pEList->nExpr );
102141 aPermute[i] = pItem->u.x.iOrderByCol - 1;
102142 }
102143 pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102144 }else{
102145 pKeyMerge = 0;
102146 }
102147
102148 /* Reattach the ORDER BY clause to the query.
@@ -106614,13 +106615,14 @@
106615 oldmask |= sqlite3TriggerColmask(pParse,
106616 pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
106617 );
106618 for(i=0; i<pTab->nCol; i++){
106619 if( oldmask==0xffffffff
106620 || (i<32 && (oldmask & MASKBIT32(i))!=0)
106621 || (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0
106622 ){
106623 testcase( oldmask!=0xffffffff && i==31 );
106624 sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i);
106625 }else{
106626 sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
106627 }
106628 }
@@ -106651,11 +106653,11 @@
106653 sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
106654 }else{
106655 j = aXRef[i];
106656 if( j>=0 ){
106657 sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
106658 }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){
106659 /* This branch loads the value of a column that will not be changed
106660 ** into a register. This is done if there are no BEFORE triggers, or
106661 ** if there are one or more BEFORE triggers that use this value via
106662 ** a new.* reference in a trigger program.
106663 */
@@ -112160,11 +112162,13 @@
112162 int iTerm;
112163 for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
112164 Expr *pExpr = pWC->a[iTerm].pExpr;
112165 if( &pWC->a[iTerm] == pTerm ) continue;
112166 if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
112167 testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO );
112168 testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL );
112169 if( pWC->a[iTerm].wtFlags & (TERM_ORINFO|TERM_VIRTUAL) ) continue;
112170 if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
112171 pExpr = sqlite3ExprDup(db, pExpr, 0);
112172 pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
112173 }
112174 if( pAndExpr ){
@@ -122726,11 +122730,11 @@
122730 ** database files might have arbitrary corruption. Setting the flag during
122731 ** testing causes certain assert() statements in the code to be activated
122732 ** that demonstrat invariants on well-formed database files.
122733 */
122734 case SQLITE_TESTCTRL_NEVER_CORRUPT: {
122735 sqlite3GlobalConfig.neverCorrupt = va_arg(ap, int);
122736 break;
122737 }
122738
122739 }
122740 va_end(ap);
@@ -131724,17 +131728,17 @@
131728 /*
131729 ** Hash and comparison functions when the mode is FTS3_HASH_STRING
131730 */
131731 static int fts3StrHash(const void *pKey, int nKey){
131732 const char *z = (const char *)pKey;
131733 unsigned h = 0;
131734 if( nKey<=0 ) nKey = (int) strlen(z);
131735 while( nKey > 0 ){
131736 h = (h<<3) ^ h ^ *z++;
131737 nKey--;
131738 }
131739 return (int)(h & 0x7fffffff);
131740 }
131741 static int fts3StrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
131742 if( n1!=n2 ) return 1;
131743 return strncmp((const char*)pKey1,(const char*)pKey2,n1);
131744 }
131745
+119 -115
--- 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-22 18:31:27 dea2ca6a159d5dcfd8deceedf1c2a73fb4ac1cfc"
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
**
@@ -11303,10 +11303,11 @@
1130311303
1130411304
/*
1130511305
** A bit in a Bitmask
1130611306
*/
1130711307
#define MASKBIT(n) (((Bitmask)1)<<(n))
11308
+#define MASKBIT32(n) (((unsigned int)1)<<(n))
1130811309
1130911310
/*
1131011311
** The following structure describes the FROM clause of a SELECT statement.
1131111312
** Each table or subquery in the FROM clause is a separate element of
1131211313
** the SrcList.a[] array.
@@ -22605,11 +22606,12 @@
2260522606
2260622607
/*
2260722608
** Read or write a four-byte big-endian integer value.
2260822609
*/
2260922610
SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
22610
- return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
22611
+ testcase( p[0]&0x80 );
22612
+ return ((unsigned)p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
2261122613
}
2261222614
SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
2261322615
p[0] = (u8)(v>>24);
2261422616
p[1] = (u8)(v>>16);
2261522617
p[2] = (u8)(v>>8);
@@ -22946,11 +22948,11 @@
2294622948
2294722949
/*
2294822950
** The hashing function.
2294922951
*/
2295022952
static unsigned int strHash(const char *z, int nKey){
22951
- int h = 0;
22953
+ unsigned int h = 0;
2295222954
assert( nKey>=0 );
2295322955
while( nKey > 0 ){
2295422956
h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
2295522957
nKey--;
2295622958
}
@@ -27650,11 +27652,11 @@
2765027652
2765127653
/* Update the global lock state and do debug tracing */
2765227654
#ifdef SQLITE_DEBUG
2765327655
{ u16 mask;
2765427656
OSTRACE(("SHM-LOCK "));
27655
- mask = ofst>31 ? 0xffffffff : (1<<(ofst+n)) - (1<<ofst);
27657
+ mask = ofst>31 ? 0xffff : (1<<(ofst+n)) - (1<<ofst);
2765627658
if( rc==SQLITE_OK ){
2765727659
if( lockType==F_UNLCK ){
2765827660
OSTRACE(("unlock %d ok", ofst));
2765927661
pShmNode->exclMask &= ~mask;
2766027662
pShmNode->sharedMask &= ~mask;
@@ -35374,11 +35376,34 @@
3537435376
** function.
3537535377
*/
3537635378
static void *winConvertFromUtf8Filename(const char *zFilename){
3537735379
void *zConverted = 0;
3537835380
if( osIsNT() ){
35379
- zConverted = winUtf8ToUnicode(zFilename);
35381
+ int nChar;
35382
+ LPWSTR zWideFilename;
35383
+
35384
+ nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
35385
+ if( nChar==0 ){
35386
+ return 0;
35387
+ }
35388
+ zWideFilename = sqlite3MallocZero( nChar*sizeof(WCHAR)+8 );
35389
+ if( zWideFilename==0 ){
35390
+ return 0;
35391
+ }
35392
+ nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1,
35393
+ zWideFilename+4, nChar);
35394
+ if( nChar==0 ){
35395
+ sqlite3_free(zWideFilename);
35396
+ return 0;
35397
+ }else if( nChar>SQLITE_WIN32_MAX_PATH_CHARS
35398
+ && winIsDriveLetterAndColon(zFilename)
35399
+ && zFilename[2] == '\\' ){
35400
+ memcpy(zWideFilename, L"\\\\?\\", 8);
35401
+ }else{
35402
+ memmove(zWideFilename, zWideFilename+4, nChar*sizeof(WCHAR));
35403
+ }
35404
+ zConverted = zWideFilename;
3538035405
}
3538135406
#ifdef SQLITE_WIN32_HAS_ANSI
3538235407
else{
3538335408
zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
3538435409
}
@@ -36305,67 +36330,14 @@
3630536330
*/
3630636331
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
3630736332
sqlite3_data_directory, winGetDirSep(), zRelative);
3630836333
return SQLITE_OK;
3630936334
}
36310
- nByte = osMultiByteToWideChar(CP_UTF8, 0, zRelative, -1, NULL, 0);
36311
- if( nByte==0 ){
36312
- return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)osGetLastError(),
36313
- "winFullPathname", zRelative);
36314
- }
36315
- if( osIsNT() ){
36316
- LPWSTR zWideFilename;
36317
-
36318
- if( nByte>SQLITE_WIN32_MAX_PATH_CHARS ){
36319
- /* No Win32 API functions can handle such long paths. Let's see if
36320
- * we can do something about it. If not, just leave it as is. */
36321
- if( winIsDirSep(zRelative[0]) && winIsDirSep(zRelative[1])
36322
- && zRelative[2]!='?' ){
36323
- /* It's an UNC path, convert it to an extended UNC path. */
36324
- zWideFilename = sqlite3MallocZero( (nByte+6)*sizeof(WCHAR) );
36325
- if( zWideFilename==0 ){
36326
- return SQLITE_IOERR_NOMEM;
36327
- }
36328
- memcpy(zWideFilename, L"\\\\?\\UNC\\", 16);
36329
- nByte = osMultiByteToWideChar(CP_UTF8, 0, zRelative+2, -1,
36330
- zWideFilename+8, nByte);
36331
- goto finished;
36332
- }else if( winIsDriveLetterAndColon(zRelative)
36333
- && winIsDirSep(zRelative[2]) ){
36334
- /* It has a correct drive prefix, convert to extended form. */
36335
- zWideFilename = sqlite3MallocZero( (nByte+4)*sizeof(WCHAR) );
36336
- if( zWideFilename==0 ){
36337
- return SQLITE_IOERR_NOMEM;
36338
- }
36339
- memcpy(zWideFilename, L"\\\\?\\", 8);
36340
- nByte = osMultiByteToWideChar(CP_UTF8, 0, zRelative, -1,
36341
- zWideFilename+4, nByte);
36342
- zWideFilename[6] = '\\';
36343
- goto finished;
36344
- }
36345
- /* Another form, e.g. relative path or maybe it already
36346
- * has the '\\?\' prefix. Just leave it as-is. */
36347
- }
36348
- zWideFilename = sqlite3Malloc( nByte*sizeof(WCHAR) );
36349
- if( zWideFilename==0 ){
36350
- return SQLITE_IOERR_NOMEM;
36351
- }
36352
- nByte = osMultiByteToWideChar(CP_UTF8, 0, zRelative, -1,
36353
- zWideFilename, nByte);
36354
- if( nByte==0 ){
36355
- sqlite3_free(zWideFilename);
36356
- return SQLITE_IOERR_NOMEM;
36357
- }
36358
- finished:
36359
- zConverted = zWideFilename;
36360
- }else{
36361
- zConverted = sqlite3_win32_utf8_to_mbcs(zRelative);
36362
- if( zConverted==0 ){
36363
- return SQLITE_IOERR_NOMEM;
36364
- }
36365
- }
36366
-
36335
+ zConverted = winConvertFromUtf8Filename(zRelative);
36336
+ if( zConverted==0 ){
36337
+ return SQLITE_IOERR_NOMEM;
36338
+ }
3636736339
if( osIsNT() ){
3636836340
LPWSTR zTemp;
3636936341
nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
3637036342
if( nByte==0 ){
3637136343
sqlite3_free(zConverted);
@@ -38479,10 +38451,11 @@
3847938451
unsigned int nPinned;
3848038452
PCache1 *pCache = (PCache1 *)p;
3848138453
PGroup *pGroup;
3848238454
PgHdr1 *pPage = 0;
3848338455
38456
+ assert( offsetof(PgHdr1,page)==0 );
3848438457
assert( pCache->bPurgeable || createFlag!=1 );
3848538458
assert( pCache->bPurgeable || pCache->nMin==0 );
3848638459
assert( pCache->bPurgeable==0 || pCache->nMin==10 );
3848738460
assert( pCache->nMin==0 || pCache->bPurgeable );
3848838461
pcache1EnterMutex(pGroup = pCache->pGroup);
@@ -38584,11 +38557,11 @@
3858438557
fetch_out:
3858538558
if( pPage && iKey>pCache->iMaxKey ){
3858638559
pCache->iMaxKey = iKey;
3858738560
}
3858838561
pcache1LeaveMutex(pGroup);
38589
- return &pPage->page;
38562
+ return (sqlite3_pcache_page*)pPage;
3859038563
}
3859138564
3859238565
3859338566
/*
3859438567
** Implementation of the sqlite3_pcache.xUnpin method.
@@ -41124,11 +41097,11 @@
4112441097
** Find a page in the hash table given its page number. Return
4112541098
** a pointer to the page or NULL if the requested page is not
4112641099
** already in memory.
4112741100
*/
4112841101
static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
41129
- PgHdr *p; /* Return value */
41102
+ PgHdr *p = 0; /* Return value */
4113041103
4113141104
/* It is not possible for a call to PcacheFetch() with createFlag==0 to
4113241105
** fail, since no attempt to allocate dynamic memory will be made.
4113341106
*/
4113441107
(void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);
@@ -60551,11 +60524,11 @@
6055160524
#endif /* SQLITE_DEBUG */
6055260525
6055360526
/*
6055460527
** Size of struct Mem not including the Mem.zMalloc member.
6055560528
*/
60556
-#define MEMCELLSIZE (size_t)(&(((Mem *)0)->zMalloc))
60529
+#define MEMCELLSIZE offsetof(Mem,zMalloc)
6055760530
6055860531
/*
6055960532
** Make an shallow copy of pFrom into pTo. Prior contents of
6056060533
** pTo are freed. The pFrom->z field is not duplicated. If
6056160534
** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
@@ -63955,12 +63928,13 @@
6395563928
SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){
6395663929
AuxData **pp = &pVdbe->pAuxData;
6395763930
while( *pp ){
6395863931
AuxData *pAux = *pp;
6395963932
if( (iOp<0)
63960
- || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & ((u32)1<<pAux->iArg))))
63933
+ || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & MASKBIT32(pAux->iArg))))
6396163934
){
63935
+ testcase( pAux->iArg==31 );
6396263936
if( pAux->xDelete ){
6396363937
pAux->xDelete(pAux->pAux);
6396463938
}
6396563939
*pp = pAux->pNext;
6396663940
sqlite3DbFree(pVdbe->db, pAux);
@@ -64271,10 +64245,13 @@
6427164245
SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
6427264246
const unsigned char *buf, /* Buffer to deserialize from */
6427364247
u32 serial_type, /* Serial type to deserialize */
6427464248
Mem *pMem /* Memory cell to write value into */
6427564249
){
64250
+ u64 x;
64251
+ u32 y;
64252
+ int i;
6427664253
switch( serial_type ){
6427764254
case 10: /* Reserved for future use */
6427864255
case 11: /* Reserved for future use */
6427964256
case 0: { /* NULL */
6428064257
pMem->flags = MEM_Null;
@@ -64284,36 +64261,37 @@
6428464261
pMem->u.i = (signed char)buf[0];
6428564262
pMem->flags = MEM_Int;
6428664263
return 1;
6428764264
}
6428864265
case 2: { /* 2-byte signed integer */
64289
- pMem->u.i = (((signed char)buf[0])<<8) | buf[1];
64266
+ i = 256*(signed char)buf[0] | buf[1];
64267
+ pMem->u.i = (i64)i;
6429064268
pMem->flags = MEM_Int;
6429164269
return 2;
6429264270
}
6429364271
case 3: { /* 3-byte signed integer */
64294
- pMem->u.i = (((signed char)buf[0])<<16) | (buf[1]<<8) | buf[2];
64272
+ i = 65536*(signed char)buf[0] | (buf[1]<<8) | buf[2];
64273
+ pMem->u.i = (i64)i;
6429564274
pMem->flags = MEM_Int;
6429664275
return 3;
6429764276
}
6429864277
case 4: { /* 4-byte signed integer */
64299
- pMem->u.i = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
64278
+ y = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
64279
+ pMem->u.i = (i64)*(int*)&y;
6430064280
pMem->flags = MEM_Int;
6430164281
return 4;
6430264282
}
6430364283
case 5: { /* 6-byte signed integer */
64304
- u64 x = (((signed char)buf[0])<<8) | buf[1];
64305
- u32 y = (buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
64284
+ x = 256*(signed char)buf[0] + buf[1];
64285
+ y = ((unsigned)buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
6430664286
x = (x<<32) | y;
6430764287
pMem->u.i = *(i64*)&x;
6430864288
pMem->flags = MEM_Int;
6430964289
return 6;
6431064290
}
6431164291
case 6: /* 8-byte signed integer */
6431264292
case 7: { /* IEEE floating point */
64313
- u64 x;
64314
- u32 y;
6431564293
#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT)
6431664294
/* Verify that integers and floating point values use the same
6431764295
** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
6431864296
** defined that 64-bit floating point values really are mixed
6431964297
** endian.
@@ -64322,13 +64300,12 @@
6432264300
static const double r1 = 1.0;
6432364301
u64 t2 = t1;
6432464302
swapMixedEndianFloat(t2);
6432564303
assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
6432664304
#endif
64327
-
64328
- x = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
64329
- y = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
64305
+ x = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
64306
+ y = ((unsigned)buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
6433064307
x = (x<<32) | y;
6433164308
if( serial_type==6 ){
6433264309
pMem->u.i = *(i64*)&x;
6433364310
pMem->flags = MEM_Int;
6433464311
}else{
@@ -72653,11 +72630,11 @@
7265372630
#ifdef SQLITE_USE_FCNTL_TRACE
7265472631
zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
7265572632
if( zTrace ){
7265672633
int i;
7265772634
for(i=0; i<db->nDb; i++){
72658
- if( ((1<<i) & p->btreeMask)==0 ) continue;
72635
+ if( MASKBIT(i) & p->btreeMask)==0 ) continue;
7265972636
sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
7266072637
}
7266172638
}
7266272639
#endif /* SQLITE_USE_FCNTL_TRACE */
7266372640
#ifdef SQLITE_DEBUG
@@ -77499,10 +77476,11 @@
7749977476
pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
7750077477
pNew->pRightmost = 0;
7750177478
pNew->addrOpenEphm[0] = -1;
7750277479
pNew->addrOpenEphm[1] = -1;
7750377480
pNew->addrOpenEphm[2] = -1;
77481
+ pNew->nSelectRow = p->nSelectRow;
7750477482
pNew->pWith = withDup(db, p->pWith);
7750577483
return pNew;
7750677484
}
7750777485
#else
7750877486
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
@@ -79120,11 +79098,11 @@
7912079098
ExprList *pFarg; /* List of function arguments */
7912179099
int nFarg; /* Number of function arguments */
7912279100
FuncDef *pDef; /* The function definition object */
7912379101
int nId; /* Length of the function name in bytes */
7912479102
const char *zId; /* The function name */
79125
- int constMask = 0; /* Mask of function arguments that are constant */
79103
+ u32 constMask = 0; /* Mask of function arguments that are constant */
7912679104
int i; /* Loop counter */
7912779105
u8 enc = ENC(db); /* The text encoding used by this database */
7912879106
CollSeq *pColl = 0; /* A collating sequence */
7912979107
7913079108
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
@@ -79171,11 +79149,12 @@
7917179149
break;
7917279150
}
7917379151
7917479152
for(i=0; i<nFarg; i++){
7917579153
if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
79176
- constMask |= (1<<i);
79154
+ testcase( i==31 );
79155
+ constMask |= MASKBIT32(i);
7917779156
}
7917879157
if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
7917979158
pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
7918079159
}
7918179160
}
@@ -89527,11 +89506,13 @@
8952789506
8952889507
/* Populate the OLD.* pseudo-table register array. These values will be
8952989508
** used by any BEFORE and AFTER triggers that exist. */
8953089509
sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld);
8953189510
for(iCol=0; iCol<pTab->nCol; iCol++){
89532
- if( mask==0xffffffff || mask&(1<<iCol) ){
89511
+ testcase( mask!=0xffffffff && iCol==31 );
89512
+ testcase( mask!=0xffffffff && iCol==32 );
89513
+ if( mask==0xffffffff || (iCol<=31 && (mask & MASKBIT32(iCol))!=0) ){
8953389514
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1);
8953489515
}
8953589516
}
8953689517
8953789518
/* Invoke BEFORE DELETE trigger programs. */
@@ -89847,11 +89828,11 @@
8984789828
UNUSED_PARAMETER(argc);
8984889829
switch( sqlite3_value_type(argv[0]) ){
8984989830
case SQLITE_INTEGER: {
8985089831
i64 iVal = sqlite3_value_int64(argv[0]);
8985189832
if( iVal<0 ){
89852
- if( (iVal<<1)==0 ){
89833
+ if( iVal==SMALLEST_INT64 ){
8985389834
/* IMP: R-31676-45509 If X is the integer -9223372036854775808
8985489835
** then abs(X) throws an integer overflow error since there is no
8985589836
** equivalent positive 64-bit two complement value. */
8985689837
sqlite3_result_error(context, "integer overflow", -1);
8985789838
return;
@@ -100310,10 +100291,11 @@
100310100291
** on a second ephemeral index that holds all values every previously
100311100292
** added to the queue. Only add this new value if it has never before
100312100293
** been added */
100313100294
addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, r3, 0);
100314100295
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3);
100296
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
100315100297
}
100316100298
for(i=0; i<nKey; i++){
100317100299
sqlite3VdbeAddOp2(v, OP_SCopy,
100318100300
regResult + pSO->a[i].u.x.iOrderByCol - 1,
100319100301
r2+i);
@@ -101220,11 +101202,48 @@
101220101202
if( pRet==0 && iCol<p->pEList->nExpr ){
101221101203
pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr);
101222101204
}
101223101205
return pRet;
101224101206
}
101225
-#endif /* SQLITE_OMIT_COMPOUND_SELECT */
101207
+
101208
+/*
101209
+** The select statement passed as the second parameter is a compound SELECT
101210
+** with an ORDER BY clause. This function allocates and returns a KeyInfo
101211
+** structure suitable for implementing the ORDER BY.
101212
+**
101213
+** Space to hold the KeyInfo structure is obtained from malloc. The calling
101214
+** function is responsible for ensuring that this structure is eventually
101215
+** freed.
101216
+*/
101217
+static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
101218
+ ExprList *pOrderBy = p->pOrderBy;
101219
+ int nOrderBy = p->pOrderBy->nExpr;
101220
+ sqlite3 *db = pParse->db;
101221
+ KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1);
101222
+ if( pRet ){
101223
+ int i;
101224
+ for(i=0; i<nOrderBy; i++){
101225
+ struct ExprList_item *pItem = &pOrderBy->a[i];
101226
+ Expr *pTerm = pItem->pExpr;
101227
+ CollSeq *pColl;
101228
+
101229
+ if( pTerm->flags & EP_Collate ){
101230
+ pColl = sqlite3ExprCollSeq(pParse, pTerm);
101231
+ }else{
101232
+ pColl = multiSelectCollSeq(pParse, p, pItem->u.x.iOrderByCol-1);
101233
+ if( pColl==0 ) pColl = db->pDfltColl;
101234
+ pOrderBy->a[i].pExpr =
101235
+ sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
101236
+ }
101237
+ assert( sqlite3KeyInfoIsWriteable(pRet) );
101238
+ pRet->aColl[i] = pColl;
101239
+ pRet->aSortOrder[i] = pOrderBy->a[i].sortOrder;
101240
+ }
101241
+ }
101242
+
101243
+ return pRet;
101244
+}
101226101245
101227101246
#ifndef SQLITE_OMIT_CTE
101228101247
/*
101229101248
** This routine generates VDBE code to compute the content of a WITH RECURSIVE
101230101249
** query of the form:
@@ -101294,23 +101313,20 @@
101294101313
pOffset = p->pOffset;
101295101314
regLimit = p->iLimit;
101296101315
regOffset = p->iOffset;
101297101316
p->pLimit = p->pOffset = 0;
101298101317
p->iLimit = p->iOffset = 0;
101318
+ pOrderBy = p->pOrderBy;
101299101319
101300101320
/* Locate the cursor number of the Current table */
101301101321
for(i=0; ALWAYS(i<pSrc->nSrc); i++){
101302101322
if( pSrc->a[i].isRecursive ){
101303101323
iCurrent = pSrc->a[i].iCursor;
101304101324
break;
101305101325
}
101306101326
}
101307101327
101308
- /* Detach the ORDER BY clause from the compound SELECT */
101309
- pOrderBy = p->pOrderBy;
101310
- p->pOrderBy = 0;
101311
-
101312101328
/* Allocate cursors numbers for Queue and Distinct. The cursor number for
101313101329
** the Distinct table must be exactly one greater than Queue in order
101314101330
** for the SRT_DistTable and SRT_DistQueue destinations to work. */
101315101331
iQueue = pParse->nTab++;
101316101332
if( p->op==TK_UNION ){
@@ -101323,11 +101339,11 @@
101323101339
101324101340
/* Allocate cursors for Current, Queue, and Distinct. */
101325101341
regCurrent = ++pParse->nMem;
101326101342
sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol);
101327101343
if( pOrderBy ){
101328
- KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pOrderBy, 1);
101344
+ KeyInfo *pKeyInfo = multiSelectOrderByKeyInfo(pParse, p, 1);
101329101345
sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0,
101330101346
(char*)pKeyInfo, P4_KEYINFO);
101331101347
destQueue.pOrderBy = pOrderBy;
101332101348
}else{
101333101349
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iQueue, nCol);
@@ -101335,10 +101351,13 @@
101335101351
VdbeComment((v, "Queue table"));
101336101352
if( iDistinct ){
101337101353
p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0);
101338101354
p->selFlags |= SF_UsesEphemeral;
101339101355
}
101356
+
101357
+ /* Detach the ORDER BY clause from the compound SELECT */
101358
+ p->pOrderBy = 0;
101340101359
101341101360
/* Store the results of the setup-query in Queue. */
101342101361
rc = sqlite3Select(pParse, pSetup, &destQueue);
101343101362
if( rc ) goto end_of_recursive_query;
101344101363
@@ -101378,21 +101397,20 @@
101378101397
p->pOrderBy = pOrderBy;
101379101398
p->pLimit = pLimit;
101380101399
p->pOffset = pOffset;
101381101400
return;
101382101401
}
101383
-#endif
101402
+#endif /* SQLITE_OMIT_CTE */
101384101403
101385101404
/* Forward references */
101386101405
static int multiSelectOrderBy(
101387101406
Parse *pParse, /* Parsing context */
101388101407
Select *p, /* The right-most of SELECTs to be coded */
101389101408
SelectDest *pDest /* What to do with query results */
101390101409
);
101391101410
101392101411
101393
-#ifndef SQLITE_OMIT_COMPOUND_SELECT
101394101412
/*
101395101413
** This routine is called to process a compound query form from
101396101414
** two or more separate queries using UNION, UNION ALL, EXCEPT, or
101397101415
** INTERSECT
101398101416
**
@@ -102120,28 +102138,11 @@
102120102138
for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
102121102139
assert( pItem->u.x.iOrderByCol>0
102122102140
&& pItem->u.x.iOrderByCol<=p->pEList->nExpr );
102123102141
aPermute[i] = pItem->u.x.iOrderByCol - 1;
102124102142
}
102125
- pKeyMerge = sqlite3KeyInfoAlloc(db, nOrderBy, 1);
102126
- if( pKeyMerge ){
102127
- for(i=0; i<nOrderBy; i++){
102128
- CollSeq *pColl;
102129
- Expr *pTerm = pOrderBy->a[i].pExpr;
102130
- if( pTerm->flags & EP_Collate ){
102131
- pColl = sqlite3ExprCollSeq(pParse, pTerm);
102132
- }else{
102133
- pColl = multiSelectCollSeq(pParse, p, aPermute[i]);
102134
- if( pColl==0 ) pColl = db->pDfltColl;
102135
- pOrderBy->a[i].pExpr =
102136
- sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
102137
- }
102138
- assert( sqlite3KeyInfoIsWriteable(pKeyMerge) );
102139
- pKeyMerge->aColl[i] = pColl;
102140
- pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder;
102141
- }
102142
- }
102143
+ pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1);
102143102144
}else{
102144102145
pKeyMerge = 0;
102145102146
}
102146102147
102147102148
/* Reattach the ORDER BY clause to the query.
@@ -106614,13 +106615,14 @@
106614106615
oldmask |= sqlite3TriggerColmask(pParse,
106615106616
pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
106616106617
);
106617106618
for(i=0; i<pTab->nCol; i++){
106618106619
if( oldmask==0xffffffff
106619
- || (i<32 && (oldmask & (1<<i)))
106620
+ || (i<32 && (oldmask & MASKBIT32(i))!=0)
106620106621
|| (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0
106621106622
){
106623
+ testcase( oldmask!=0xffffffff && i==31 );
106622106624
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i);
106623106625
}else{
106624106626
sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
106625106627
}
106626106628
}
@@ -106651,11 +106653,11 @@
106651106653
sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
106652106654
}else{
106653106655
j = aXRef[i];
106654106656
if( j>=0 ){
106655106657
sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
106656
- }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask&(1<<i)) ){
106658
+ }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){
106657106659
/* This branch loads the value of a column that will not be changed
106658106660
** into a register. This is done if there are no BEFORE triggers, or
106659106661
** if there are one or more BEFORE triggers that use this value via
106660106662
** a new.* reference in a trigger program.
106661106663
*/
@@ -112160,11 +112162,13 @@
112160112162
int iTerm;
112161112163
for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
112162112164
Expr *pExpr = pWC->a[iTerm].pExpr;
112163112165
if( &pWC->a[iTerm] == pTerm ) continue;
112164112166
if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
112165
- if( pWC->a[iTerm].wtFlags & (TERM_ORINFO) ) continue;
112167
+ testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO );
112168
+ testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL );
112169
+ if( pWC->a[iTerm].wtFlags & (TERM_ORINFO|TERM_VIRTUAL) ) continue;
112166112170
if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
112167112171
pExpr = sqlite3ExprDup(db, pExpr, 0);
112168112172
pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
112169112173
}
112170112174
if( pAndExpr ){
@@ -122726,11 +122730,11 @@
122726122730
** database files might have arbitrary corruption. Setting the flag during
122727122731
** testing causes certain assert() statements in the code to be activated
122728122732
** that demonstrat invariants on well-formed database files.
122729122733
*/
122730122734
case SQLITE_TESTCTRL_NEVER_CORRUPT: {
122731
- sqlite3Config.neverCorrupt = va_arg(ap, int);
122735
+ sqlite3GlobalConfig.neverCorrupt = va_arg(ap, int);
122732122736
break;
122733122737
}
122734122738
122735122739
}
122736122740
va_end(ap);
@@ -131724,17 +131728,17 @@
131724131728
/*
131725131729
** Hash and comparison functions when the mode is FTS3_HASH_STRING
131726131730
*/
131727131731
static int fts3StrHash(const void *pKey, int nKey){
131728131732
const char *z = (const char *)pKey;
131729
- int h = 0;
131733
+ unsigned h = 0;
131730131734
if( nKey<=0 ) nKey = (int) strlen(z);
131731131735
while( nKey > 0 ){
131732131736
h = (h<<3) ^ h ^ *z++;
131733131737
nKey--;
131734131738
}
131735
- return h & 0x7fffffff;
131739
+ return (int)(h & 0x7fffffff);
131736131740
}
131737131741
static int fts3StrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
131738131742
if( n1!=n2 ) return 1;
131739131743
return strncmp((const char*)pKey1,(const char*)pKey2,n1);
131740131744
}
131741131745
--- 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-22 18:31:27 dea2ca6a159d5dcfd8deceedf1c2a73fb4ac1cfc"
141
142 /*
143 ** CAPI3REF: Run-Time Library Version Numbers
144 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
145 **
@@ -11303,10 +11303,11 @@
11303
11304 /*
11305 ** A bit in a Bitmask
11306 */
11307 #define MASKBIT(n) (((Bitmask)1)<<(n))
 
11308
11309 /*
11310 ** The following structure describes the FROM clause of a SELECT statement.
11311 ** Each table or subquery in the FROM clause is a separate element of
11312 ** the SrcList.a[] array.
@@ -22605,11 +22606,12 @@
22605
22606 /*
22607 ** Read or write a four-byte big-endian integer value.
22608 */
22609 SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
22610 return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
 
22611 }
22612 SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
22613 p[0] = (u8)(v>>24);
22614 p[1] = (u8)(v>>16);
22615 p[2] = (u8)(v>>8);
@@ -22946,11 +22948,11 @@
22946
22947 /*
22948 ** The hashing function.
22949 */
22950 static unsigned int strHash(const char *z, int nKey){
22951 int h = 0;
22952 assert( nKey>=0 );
22953 while( nKey > 0 ){
22954 h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
22955 nKey--;
22956 }
@@ -27650,11 +27652,11 @@
27650
27651 /* Update the global lock state and do debug tracing */
27652 #ifdef SQLITE_DEBUG
27653 { u16 mask;
27654 OSTRACE(("SHM-LOCK "));
27655 mask = ofst>31 ? 0xffffffff : (1<<(ofst+n)) - (1<<ofst);
27656 if( rc==SQLITE_OK ){
27657 if( lockType==F_UNLCK ){
27658 OSTRACE(("unlock %d ok", ofst));
27659 pShmNode->exclMask &= ~mask;
27660 pShmNode->sharedMask &= ~mask;
@@ -35374,11 +35376,34 @@
35374 ** function.
35375 */
35376 static void *winConvertFromUtf8Filename(const char *zFilename){
35377 void *zConverted = 0;
35378 if( osIsNT() ){
35379 zConverted = winUtf8ToUnicode(zFilename);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35380 }
35381 #ifdef SQLITE_WIN32_HAS_ANSI
35382 else{
35383 zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
35384 }
@@ -36305,67 +36330,14 @@
36305 */
36306 sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
36307 sqlite3_data_directory, winGetDirSep(), zRelative);
36308 return SQLITE_OK;
36309 }
36310 nByte = osMultiByteToWideChar(CP_UTF8, 0, zRelative, -1, NULL, 0);
36311 if( nByte==0 ){
36312 return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)osGetLastError(),
36313 "winFullPathname", zRelative);
36314 }
36315 if( osIsNT() ){
36316 LPWSTR zWideFilename;
36317
36318 if( nByte>SQLITE_WIN32_MAX_PATH_CHARS ){
36319 /* No Win32 API functions can handle such long paths. Let's see if
36320 * we can do something about it. If not, just leave it as is. */
36321 if( winIsDirSep(zRelative[0]) && winIsDirSep(zRelative[1])
36322 && zRelative[2]!='?' ){
36323 /* It's an UNC path, convert it to an extended UNC path. */
36324 zWideFilename = sqlite3MallocZero( (nByte+6)*sizeof(WCHAR) );
36325 if( zWideFilename==0 ){
36326 return SQLITE_IOERR_NOMEM;
36327 }
36328 memcpy(zWideFilename, L"\\\\?\\UNC\\", 16);
36329 nByte = osMultiByteToWideChar(CP_UTF8, 0, zRelative+2, -1,
36330 zWideFilename+8, nByte);
36331 goto finished;
36332 }else if( winIsDriveLetterAndColon(zRelative)
36333 && winIsDirSep(zRelative[2]) ){
36334 /* It has a correct drive prefix, convert to extended form. */
36335 zWideFilename = sqlite3MallocZero( (nByte+4)*sizeof(WCHAR) );
36336 if( zWideFilename==0 ){
36337 return SQLITE_IOERR_NOMEM;
36338 }
36339 memcpy(zWideFilename, L"\\\\?\\", 8);
36340 nByte = osMultiByteToWideChar(CP_UTF8, 0, zRelative, -1,
36341 zWideFilename+4, nByte);
36342 zWideFilename[6] = '\\';
36343 goto finished;
36344 }
36345 /* Another form, e.g. relative path or maybe it already
36346 * has the '\\?\' prefix. Just leave it as-is. */
36347 }
36348 zWideFilename = sqlite3Malloc( nByte*sizeof(WCHAR) );
36349 if( zWideFilename==0 ){
36350 return SQLITE_IOERR_NOMEM;
36351 }
36352 nByte = osMultiByteToWideChar(CP_UTF8, 0, zRelative, -1,
36353 zWideFilename, nByte);
36354 if( nByte==0 ){
36355 sqlite3_free(zWideFilename);
36356 return SQLITE_IOERR_NOMEM;
36357 }
36358 finished:
36359 zConverted = zWideFilename;
36360 }else{
36361 zConverted = sqlite3_win32_utf8_to_mbcs(zRelative);
36362 if( zConverted==0 ){
36363 return SQLITE_IOERR_NOMEM;
36364 }
36365 }
36366
36367 if( osIsNT() ){
36368 LPWSTR zTemp;
36369 nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
36370 if( nByte==0 ){
36371 sqlite3_free(zConverted);
@@ -38479,10 +38451,11 @@
38479 unsigned int nPinned;
38480 PCache1 *pCache = (PCache1 *)p;
38481 PGroup *pGroup;
38482 PgHdr1 *pPage = 0;
38483
 
38484 assert( pCache->bPurgeable || createFlag!=1 );
38485 assert( pCache->bPurgeable || pCache->nMin==0 );
38486 assert( pCache->bPurgeable==0 || pCache->nMin==10 );
38487 assert( pCache->nMin==0 || pCache->bPurgeable );
38488 pcache1EnterMutex(pGroup = pCache->pGroup);
@@ -38584,11 +38557,11 @@
38584 fetch_out:
38585 if( pPage && iKey>pCache->iMaxKey ){
38586 pCache->iMaxKey = iKey;
38587 }
38588 pcache1LeaveMutex(pGroup);
38589 return &pPage->page;
38590 }
38591
38592
38593 /*
38594 ** Implementation of the sqlite3_pcache.xUnpin method.
@@ -41124,11 +41097,11 @@
41124 ** Find a page in the hash table given its page number. Return
41125 ** a pointer to the page or NULL if the requested page is not
41126 ** already in memory.
41127 */
41128 static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
41129 PgHdr *p; /* Return value */
41130
41131 /* It is not possible for a call to PcacheFetch() with createFlag==0 to
41132 ** fail, since no attempt to allocate dynamic memory will be made.
41133 */
41134 (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);
@@ -60551,11 +60524,11 @@
60551 #endif /* SQLITE_DEBUG */
60552
60553 /*
60554 ** Size of struct Mem not including the Mem.zMalloc member.
60555 */
60556 #define MEMCELLSIZE (size_t)(&(((Mem *)0)->zMalloc))
60557
60558 /*
60559 ** Make an shallow copy of pFrom into pTo. Prior contents of
60560 ** pTo are freed. The pFrom->z field is not duplicated. If
60561 ** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
@@ -63955,12 +63928,13 @@
63955 SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){
63956 AuxData **pp = &pVdbe->pAuxData;
63957 while( *pp ){
63958 AuxData *pAux = *pp;
63959 if( (iOp<0)
63960 || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & ((u32)1<<pAux->iArg))))
63961 ){
 
63962 if( pAux->xDelete ){
63963 pAux->xDelete(pAux->pAux);
63964 }
63965 *pp = pAux->pNext;
63966 sqlite3DbFree(pVdbe->db, pAux);
@@ -64271,10 +64245,13 @@
64271 SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
64272 const unsigned char *buf, /* Buffer to deserialize from */
64273 u32 serial_type, /* Serial type to deserialize */
64274 Mem *pMem /* Memory cell to write value into */
64275 ){
 
 
 
64276 switch( serial_type ){
64277 case 10: /* Reserved for future use */
64278 case 11: /* Reserved for future use */
64279 case 0: { /* NULL */
64280 pMem->flags = MEM_Null;
@@ -64284,36 +64261,37 @@
64284 pMem->u.i = (signed char)buf[0];
64285 pMem->flags = MEM_Int;
64286 return 1;
64287 }
64288 case 2: { /* 2-byte signed integer */
64289 pMem->u.i = (((signed char)buf[0])<<8) | buf[1];
 
64290 pMem->flags = MEM_Int;
64291 return 2;
64292 }
64293 case 3: { /* 3-byte signed integer */
64294 pMem->u.i = (((signed char)buf[0])<<16) | (buf[1]<<8) | buf[2];
 
64295 pMem->flags = MEM_Int;
64296 return 3;
64297 }
64298 case 4: { /* 4-byte signed integer */
64299 pMem->u.i = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
 
64300 pMem->flags = MEM_Int;
64301 return 4;
64302 }
64303 case 5: { /* 6-byte signed integer */
64304 u64 x = (((signed char)buf[0])<<8) | buf[1];
64305 u32 y = (buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
64306 x = (x<<32) | y;
64307 pMem->u.i = *(i64*)&x;
64308 pMem->flags = MEM_Int;
64309 return 6;
64310 }
64311 case 6: /* 8-byte signed integer */
64312 case 7: { /* IEEE floating point */
64313 u64 x;
64314 u32 y;
64315 #if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT)
64316 /* Verify that integers and floating point values use the same
64317 ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
64318 ** defined that 64-bit floating point values really are mixed
64319 ** endian.
@@ -64322,13 +64300,12 @@
64322 static const double r1 = 1.0;
64323 u64 t2 = t1;
64324 swapMixedEndianFloat(t2);
64325 assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
64326 #endif
64327
64328 x = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
64329 y = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
64330 x = (x<<32) | y;
64331 if( serial_type==6 ){
64332 pMem->u.i = *(i64*)&x;
64333 pMem->flags = MEM_Int;
64334 }else{
@@ -72653,11 +72630,11 @@
72653 #ifdef SQLITE_USE_FCNTL_TRACE
72654 zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
72655 if( zTrace ){
72656 int i;
72657 for(i=0; i<db->nDb; i++){
72658 if( ((1<<i) & p->btreeMask)==0 ) continue;
72659 sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
72660 }
72661 }
72662 #endif /* SQLITE_USE_FCNTL_TRACE */
72663 #ifdef SQLITE_DEBUG
@@ -77499,10 +77476,11 @@
77499 pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
77500 pNew->pRightmost = 0;
77501 pNew->addrOpenEphm[0] = -1;
77502 pNew->addrOpenEphm[1] = -1;
77503 pNew->addrOpenEphm[2] = -1;
 
77504 pNew->pWith = withDup(db, p->pWith);
77505 return pNew;
77506 }
77507 #else
77508 SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
@@ -79120,11 +79098,11 @@
79120 ExprList *pFarg; /* List of function arguments */
79121 int nFarg; /* Number of function arguments */
79122 FuncDef *pDef; /* The function definition object */
79123 int nId; /* Length of the function name in bytes */
79124 const char *zId; /* The function name */
79125 int constMask = 0; /* Mask of function arguments that are constant */
79126 int i; /* Loop counter */
79127 u8 enc = ENC(db); /* The text encoding used by this database */
79128 CollSeq *pColl = 0; /* A collating sequence */
79129
79130 assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
@@ -79171,11 +79149,12 @@
79171 break;
79172 }
79173
79174 for(i=0; i<nFarg; i++){
79175 if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
79176 constMask |= (1<<i);
 
79177 }
79178 if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
79179 pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
79180 }
79181 }
@@ -89527,11 +89506,13 @@
89527
89528 /* Populate the OLD.* pseudo-table register array. These values will be
89529 ** used by any BEFORE and AFTER triggers that exist. */
89530 sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld);
89531 for(iCol=0; iCol<pTab->nCol; iCol++){
89532 if( mask==0xffffffff || mask&(1<<iCol) ){
 
 
89533 sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1);
89534 }
89535 }
89536
89537 /* Invoke BEFORE DELETE trigger programs. */
@@ -89847,11 +89828,11 @@
89847 UNUSED_PARAMETER(argc);
89848 switch( sqlite3_value_type(argv[0]) ){
89849 case SQLITE_INTEGER: {
89850 i64 iVal = sqlite3_value_int64(argv[0]);
89851 if( iVal<0 ){
89852 if( (iVal<<1)==0 ){
89853 /* IMP: R-31676-45509 If X is the integer -9223372036854775808
89854 ** then abs(X) throws an integer overflow error since there is no
89855 ** equivalent positive 64-bit two complement value. */
89856 sqlite3_result_error(context, "integer overflow", -1);
89857 return;
@@ -100310,10 +100291,11 @@
100310 ** on a second ephemeral index that holds all values every previously
100311 ** added to the queue. Only add this new value if it has never before
100312 ** been added */
100313 addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, r3, 0);
100314 sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3);
 
100315 }
100316 for(i=0; i<nKey; i++){
100317 sqlite3VdbeAddOp2(v, OP_SCopy,
100318 regResult + pSO->a[i].u.x.iOrderByCol - 1,
100319 r2+i);
@@ -101220,11 +101202,48 @@
101220 if( pRet==0 && iCol<p->pEList->nExpr ){
101221 pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr);
101222 }
101223 return pRet;
101224 }
101225 #endif /* SQLITE_OMIT_COMPOUND_SELECT */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101226
101227 #ifndef SQLITE_OMIT_CTE
101228 /*
101229 ** This routine generates VDBE code to compute the content of a WITH RECURSIVE
101230 ** query of the form:
@@ -101294,23 +101313,20 @@
101294 pOffset = p->pOffset;
101295 regLimit = p->iLimit;
101296 regOffset = p->iOffset;
101297 p->pLimit = p->pOffset = 0;
101298 p->iLimit = p->iOffset = 0;
 
101299
101300 /* Locate the cursor number of the Current table */
101301 for(i=0; ALWAYS(i<pSrc->nSrc); i++){
101302 if( pSrc->a[i].isRecursive ){
101303 iCurrent = pSrc->a[i].iCursor;
101304 break;
101305 }
101306 }
101307
101308 /* Detach the ORDER BY clause from the compound SELECT */
101309 pOrderBy = p->pOrderBy;
101310 p->pOrderBy = 0;
101311
101312 /* Allocate cursors numbers for Queue and Distinct. The cursor number for
101313 ** the Distinct table must be exactly one greater than Queue in order
101314 ** for the SRT_DistTable and SRT_DistQueue destinations to work. */
101315 iQueue = pParse->nTab++;
101316 if( p->op==TK_UNION ){
@@ -101323,11 +101339,11 @@
101323
101324 /* Allocate cursors for Current, Queue, and Distinct. */
101325 regCurrent = ++pParse->nMem;
101326 sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol);
101327 if( pOrderBy ){
101328 KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pOrderBy, 1);
101329 sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0,
101330 (char*)pKeyInfo, P4_KEYINFO);
101331 destQueue.pOrderBy = pOrderBy;
101332 }else{
101333 sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iQueue, nCol);
@@ -101335,10 +101351,13 @@
101335 VdbeComment((v, "Queue table"));
101336 if( iDistinct ){
101337 p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0);
101338 p->selFlags |= SF_UsesEphemeral;
101339 }
 
 
 
101340
101341 /* Store the results of the setup-query in Queue. */
101342 rc = sqlite3Select(pParse, pSetup, &destQueue);
101343 if( rc ) goto end_of_recursive_query;
101344
@@ -101378,21 +101397,20 @@
101378 p->pOrderBy = pOrderBy;
101379 p->pLimit = pLimit;
101380 p->pOffset = pOffset;
101381 return;
101382 }
101383 #endif
101384
101385 /* Forward references */
101386 static int multiSelectOrderBy(
101387 Parse *pParse, /* Parsing context */
101388 Select *p, /* The right-most of SELECTs to be coded */
101389 SelectDest *pDest /* What to do with query results */
101390 );
101391
101392
101393 #ifndef SQLITE_OMIT_COMPOUND_SELECT
101394 /*
101395 ** This routine is called to process a compound query form from
101396 ** two or more separate queries using UNION, UNION ALL, EXCEPT, or
101397 ** INTERSECT
101398 **
@@ -102120,28 +102138,11 @@
102120 for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
102121 assert( pItem->u.x.iOrderByCol>0
102122 && pItem->u.x.iOrderByCol<=p->pEList->nExpr );
102123 aPermute[i] = pItem->u.x.iOrderByCol - 1;
102124 }
102125 pKeyMerge = sqlite3KeyInfoAlloc(db, nOrderBy, 1);
102126 if( pKeyMerge ){
102127 for(i=0; i<nOrderBy; i++){
102128 CollSeq *pColl;
102129 Expr *pTerm = pOrderBy->a[i].pExpr;
102130 if( pTerm->flags & EP_Collate ){
102131 pColl = sqlite3ExprCollSeq(pParse, pTerm);
102132 }else{
102133 pColl = multiSelectCollSeq(pParse, p, aPermute[i]);
102134 if( pColl==0 ) pColl = db->pDfltColl;
102135 pOrderBy->a[i].pExpr =
102136 sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
102137 }
102138 assert( sqlite3KeyInfoIsWriteable(pKeyMerge) );
102139 pKeyMerge->aColl[i] = pColl;
102140 pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder;
102141 }
102142 }
102143 }else{
102144 pKeyMerge = 0;
102145 }
102146
102147 /* Reattach the ORDER BY clause to the query.
@@ -106614,13 +106615,14 @@
106614 oldmask |= sqlite3TriggerColmask(pParse,
106615 pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
106616 );
106617 for(i=0; i<pTab->nCol; i++){
106618 if( oldmask==0xffffffff
106619 || (i<32 && (oldmask & (1<<i)))
106620 || (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0
106621 ){
 
106622 sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i);
106623 }else{
106624 sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
106625 }
106626 }
@@ -106651,11 +106653,11 @@
106651 sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
106652 }else{
106653 j = aXRef[i];
106654 if( j>=0 ){
106655 sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
106656 }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask&(1<<i)) ){
106657 /* This branch loads the value of a column that will not be changed
106658 ** into a register. This is done if there are no BEFORE triggers, or
106659 ** if there are one or more BEFORE triggers that use this value via
106660 ** a new.* reference in a trigger program.
106661 */
@@ -112160,11 +112162,13 @@
112160 int iTerm;
112161 for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
112162 Expr *pExpr = pWC->a[iTerm].pExpr;
112163 if( &pWC->a[iTerm] == pTerm ) continue;
112164 if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
112165 if( pWC->a[iTerm].wtFlags & (TERM_ORINFO) ) continue;
 
 
112166 if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
112167 pExpr = sqlite3ExprDup(db, pExpr, 0);
112168 pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
112169 }
112170 if( pAndExpr ){
@@ -122726,11 +122730,11 @@
122726 ** database files might have arbitrary corruption. Setting the flag during
122727 ** testing causes certain assert() statements in the code to be activated
122728 ** that demonstrat invariants on well-formed database files.
122729 */
122730 case SQLITE_TESTCTRL_NEVER_CORRUPT: {
122731 sqlite3Config.neverCorrupt = va_arg(ap, int);
122732 break;
122733 }
122734
122735 }
122736 va_end(ap);
@@ -131724,17 +131728,17 @@
131724 /*
131725 ** Hash and comparison functions when the mode is FTS3_HASH_STRING
131726 */
131727 static int fts3StrHash(const void *pKey, int nKey){
131728 const char *z = (const char *)pKey;
131729 int h = 0;
131730 if( nKey<=0 ) nKey = (int) strlen(z);
131731 while( nKey > 0 ){
131732 h = (h<<3) ^ h ^ *z++;
131733 nKey--;
131734 }
131735 return h & 0x7fffffff;
131736 }
131737 static int fts3StrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
131738 if( n1!=n2 ) return 1;
131739 return strncmp((const char*)pKey1,(const char*)pKey2,n1);
131740 }
131741
--- 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 **
@@ -11303,10 +11303,11 @@
11303
11304 /*
11305 ** A bit in a Bitmask
11306 */
11307 #define MASKBIT(n) (((Bitmask)1)<<(n))
11308 #define MASKBIT32(n) (((unsigned int)1)<<(n))
11309
11310 /*
11311 ** The following structure describes the FROM clause of a SELECT statement.
11312 ** Each table or subquery in the FROM clause is a separate element of
11313 ** the SrcList.a[] array.
@@ -22605,11 +22606,12 @@
22606
22607 /*
22608 ** Read or write a four-byte big-endian integer value.
22609 */
22610 SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
22611 testcase( p[0]&0x80 );
22612 return ((unsigned)p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
22613 }
22614 SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
22615 p[0] = (u8)(v>>24);
22616 p[1] = (u8)(v>>16);
22617 p[2] = (u8)(v>>8);
@@ -22946,11 +22948,11 @@
22948
22949 /*
22950 ** The hashing function.
22951 */
22952 static unsigned int strHash(const char *z, int nKey){
22953 unsigned int h = 0;
22954 assert( nKey>=0 );
22955 while( nKey > 0 ){
22956 h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
22957 nKey--;
22958 }
@@ -27650,11 +27652,11 @@
27652
27653 /* Update the global lock state and do debug tracing */
27654 #ifdef SQLITE_DEBUG
27655 { u16 mask;
27656 OSTRACE(("SHM-LOCK "));
27657 mask = ofst>31 ? 0xffff : (1<<(ofst+n)) - (1<<ofst);
27658 if( rc==SQLITE_OK ){
27659 if( lockType==F_UNLCK ){
27660 OSTRACE(("unlock %d ok", ofst));
27661 pShmNode->exclMask &= ~mask;
27662 pShmNode->sharedMask &= ~mask;
@@ -35374,11 +35376,34 @@
35376 ** function.
35377 */
35378 static void *winConvertFromUtf8Filename(const char *zFilename){
35379 void *zConverted = 0;
35380 if( osIsNT() ){
35381 int nChar;
35382 LPWSTR zWideFilename;
35383
35384 nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
35385 if( nChar==0 ){
35386 return 0;
35387 }
35388 zWideFilename = sqlite3MallocZero( nChar*sizeof(WCHAR)+8 );
35389 if( zWideFilename==0 ){
35390 return 0;
35391 }
35392 nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1,
35393 zWideFilename+4, nChar);
35394 if( nChar==0 ){
35395 sqlite3_free(zWideFilename);
35396 return 0;
35397 }else if( nChar>SQLITE_WIN32_MAX_PATH_CHARS
35398 && winIsDriveLetterAndColon(zFilename)
35399 && zFilename[2] == '\\' ){
35400 memcpy(zWideFilename, L"\\\\?\\", 8);
35401 }else{
35402 memmove(zWideFilename, zWideFilename+4, nChar*sizeof(WCHAR));
35403 }
35404 zConverted = zWideFilename;
35405 }
35406 #ifdef SQLITE_WIN32_HAS_ANSI
35407 else{
35408 zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
35409 }
@@ -36305,67 +36330,14 @@
36330 */
36331 sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
36332 sqlite3_data_directory, winGetDirSep(), zRelative);
36333 return SQLITE_OK;
36334 }
36335 zConverted = winConvertFromUtf8Filename(zRelative);
36336 if( zConverted==0 ){
36337 return SQLITE_IOERR_NOMEM;
36338 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36339 if( osIsNT() ){
36340 LPWSTR zTemp;
36341 nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
36342 if( nByte==0 ){
36343 sqlite3_free(zConverted);
@@ -38479,10 +38451,11 @@
38451 unsigned int nPinned;
38452 PCache1 *pCache = (PCache1 *)p;
38453 PGroup *pGroup;
38454 PgHdr1 *pPage = 0;
38455
38456 assert( offsetof(PgHdr1,page)==0 );
38457 assert( pCache->bPurgeable || createFlag!=1 );
38458 assert( pCache->bPurgeable || pCache->nMin==0 );
38459 assert( pCache->bPurgeable==0 || pCache->nMin==10 );
38460 assert( pCache->nMin==0 || pCache->bPurgeable );
38461 pcache1EnterMutex(pGroup = pCache->pGroup);
@@ -38584,11 +38557,11 @@
38557 fetch_out:
38558 if( pPage && iKey>pCache->iMaxKey ){
38559 pCache->iMaxKey = iKey;
38560 }
38561 pcache1LeaveMutex(pGroup);
38562 return (sqlite3_pcache_page*)pPage;
38563 }
38564
38565
38566 /*
38567 ** Implementation of the sqlite3_pcache.xUnpin method.
@@ -41124,11 +41097,11 @@
41097 ** Find a page in the hash table given its page number. Return
41098 ** a pointer to the page or NULL if the requested page is not
41099 ** already in memory.
41100 */
41101 static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
41102 PgHdr *p = 0; /* Return value */
41103
41104 /* It is not possible for a call to PcacheFetch() with createFlag==0 to
41105 ** fail, since no attempt to allocate dynamic memory will be made.
41106 */
41107 (void)sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);
@@ -60551,11 +60524,11 @@
60524 #endif /* SQLITE_DEBUG */
60525
60526 /*
60527 ** Size of struct Mem not including the Mem.zMalloc member.
60528 */
60529 #define MEMCELLSIZE offsetof(Mem,zMalloc)
60530
60531 /*
60532 ** Make an shallow copy of pFrom into pTo. Prior contents of
60533 ** pTo are freed. The pFrom->z field is not duplicated. If
60534 ** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
@@ -63955,12 +63928,13 @@
63928 SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){
63929 AuxData **pp = &pVdbe->pAuxData;
63930 while( *pp ){
63931 AuxData *pAux = *pp;
63932 if( (iOp<0)
63933 || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & MASKBIT32(pAux->iArg))))
63934 ){
63935 testcase( pAux->iArg==31 );
63936 if( pAux->xDelete ){
63937 pAux->xDelete(pAux->pAux);
63938 }
63939 *pp = pAux->pNext;
63940 sqlite3DbFree(pVdbe->db, pAux);
@@ -64271,10 +64245,13 @@
64245 SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
64246 const unsigned char *buf, /* Buffer to deserialize from */
64247 u32 serial_type, /* Serial type to deserialize */
64248 Mem *pMem /* Memory cell to write value into */
64249 ){
64250 u64 x;
64251 u32 y;
64252 int i;
64253 switch( serial_type ){
64254 case 10: /* Reserved for future use */
64255 case 11: /* Reserved for future use */
64256 case 0: { /* NULL */
64257 pMem->flags = MEM_Null;
@@ -64284,36 +64261,37 @@
64261 pMem->u.i = (signed char)buf[0];
64262 pMem->flags = MEM_Int;
64263 return 1;
64264 }
64265 case 2: { /* 2-byte signed integer */
64266 i = 256*(signed char)buf[0] | buf[1];
64267 pMem->u.i = (i64)i;
64268 pMem->flags = MEM_Int;
64269 return 2;
64270 }
64271 case 3: { /* 3-byte signed integer */
64272 i = 65536*(signed char)buf[0] | (buf[1]<<8) | buf[2];
64273 pMem->u.i = (i64)i;
64274 pMem->flags = MEM_Int;
64275 return 3;
64276 }
64277 case 4: { /* 4-byte signed integer */
64278 y = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
64279 pMem->u.i = (i64)*(int*)&y;
64280 pMem->flags = MEM_Int;
64281 return 4;
64282 }
64283 case 5: { /* 6-byte signed integer */
64284 x = 256*(signed char)buf[0] + buf[1];
64285 y = ((unsigned)buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
64286 x = (x<<32) | y;
64287 pMem->u.i = *(i64*)&x;
64288 pMem->flags = MEM_Int;
64289 return 6;
64290 }
64291 case 6: /* 8-byte signed integer */
64292 case 7: { /* IEEE floating point */
 
 
64293 #if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT)
64294 /* Verify that integers and floating point values use the same
64295 ** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
64296 ** defined that 64-bit floating point values really are mixed
64297 ** endian.
@@ -64322,13 +64300,12 @@
64300 static const double r1 = 1.0;
64301 u64 t2 = t1;
64302 swapMixedEndianFloat(t2);
64303 assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
64304 #endif
64305 x = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
64306 y = ((unsigned)buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
 
64307 x = (x<<32) | y;
64308 if( serial_type==6 ){
64309 pMem->u.i = *(i64*)&x;
64310 pMem->flags = MEM_Int;
64311 }else{
@@ -72653,11 +72630,11 @@
72630 #ifdef SQLITE_USE_FCNTL_TRACE
72631 zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
72632 if( zTrace ){
72633 int i;
72634 for(i=0; i<db->nDb; i++){
72635 if( MASKBIT(i) & p->btreeMask)==0 ) continue;
72636 sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
72637 }
72638 }
72639 #endif /* SQLITE_USE_FCNTL_TRACE */
72640 #ifdef SQLITE_DEBUG
@@ -77499,10 +77476,11 @@
77476 pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
77477 pNew->pRightmost = 0;
77478 pNew->addrOpenEphm[0] = -1;
77479 pNew->addrOpenEphm[1] = -1;
77480 pNew->addrOpenEphm[2] = -1;
77481 pNew->nSelectRow = p->nSelectRow;
77482 pNew->pWith = withDup(db, p->pWith);
77483 return pNew;
77484 }
77485 #else
77486 SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
@@ -79120,11 +79098,11 @@
79098 ExprList *pFarg; /* List of function arguments */
79099 int nFarg; /* Number of function arguments */
79100 FuncDef *pDef; /* The function definition object */
79101 int nId; /* Length of the function name in bytes */
79102 const char *zId; /* The function name */
79103 u32 constMask = 0; /* Mask of function arguments that are constant */
79104 int i; /* Loop counter */
79105 u8 enc = ENC(db); /* The text encoding used by this database */
79106 CollSeq *pColl = 0; /* A collating sequence */
79107
79108 assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
@@ -79171,11 +79149,12 @@
79149 break;
79150 }
79151
79152 for(i=0; i<nFarg; i++){
79153 if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
79154 testcase( i==31 );
79155 constMask |= MASKBIT32(i);
79156 }
79157 if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
79158 pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
79159 }
79160 }
@@ -89527,11 +89506,13 @@
89506
89507 /* Populate the OLD.* pseudo-table register array. These values will be
89508 ** used by any BEFORE and AFTER triggers that exist. */
89509 sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld);
89510 for(iCol=0; iCol<pTab->nCol; iCol++){
89511 testcase( mask!=0xffffffff && iCol==31 );
89512 testcase( mask!=0xffffffff && iCol==32 );
89513 if( mask==0xffffffff || (iCol<=31 && (mask & MASKBIT32(iCol))!=0) ){
89514 sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1);
89515 }
89516 }
89517
89518 /* Invoke BEFORE DELETE trigger programs. */
@@ -89847,11 +89828,11 @@
89828 UNUSED_PARAMETER(argc);
89829 switch( sqlite3_value_type(argv[0]) ){
89830 case SQLITE_INTEGER: {
89831 i64 iVal = sqlite3_value_int64(argv[0]);
89832 if( iVal<0 ){
89833 if( iVal==SMALLEST_INT64 ){
89834 /* IMP: R-31676-45509 If X is the integer -9223372036854775808
89835 ** then abs(X) throws an integer overflow error since there is no
89836 ** equivalent positive 64-bit two complement value. */
89837 sqlite3_result_error(context, "integer overflow", -1);
89838 return;
@@ -100310,10 +100291,11 @@
100291 ** on a second ephemeral index that holds all values every previously
100292 ** added to the queue. Only add this new value if it has never before
100293 ** been added */
100294 addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, r3, 0);
100295 sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3);
100296 sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
100297 }
100298 for(i=0; i<nKey; i++){
100299 sqlite3VdbeAddOp2(v, OP_SCopy,
100300 regResult + pSO->a[i].u.x.iOrderByCol - 1,
100301 r2+i);
@@ -101220,11 +101202,48 @@
101202 if( pRet==0 && iCol<p->pEList->nExpr ){
101203 pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr);
101204 }
101205 return pRet;
101206 }
101207
101208 /*
101209 ** The select statement passed as the second parameter is a compound SELECT
101210 ** with an ORDER BY clause. This function allocates and returns a KeyInfo
101211 ** structure suitable for implementing the ORDER BY.
101212 **
101213 ** Space to hold the KeyInfo structure is obtained from malloc. The calling
101214 ** function is responsible for ensuring that this structure is eventually
101215 ** freed.
101216 */
101217 static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
101218 ExprList *pOrderBy = p->pOrderBy;
101219 int nOrderBy = p->pOrderBy->nExpr;
101220 sqlite3 *db = pParse->db;
101221 KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1);
101222 if( pRet ){
101223 int i;
101224 for(i=0; i<nOrderBy; i++){
101225 struct ExprList_item *pItem = &pOrderBy->a[i];
101226 Expr *pTerm = pItem->pExpr;
101227 CollSeq *pColl;
101228
101229 if( pTerm->flags & EP_Collate ){
101230 pColl = sqlite3ExprCollSeq(pParse, pTerm);
101231 }else{
101232 pColl = multiSelectCollSeq(pParse, p, pItem->u.x.iOrderByCol-1);
101233 if( pColl==0 ) pColl = db->pDfltColl;
101234 pOrderBy->a[i].pExpr =
101235 sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
101236 }
101237 assert( sqlite3KeyInfoIsWriteable(pRet) );
101238 pRet->aColl[i] = pColl;
101239 pRet->aSortOrder[i] = pOrderBy->a[i].sortOrder;
101240 }
101241 }
101242
101243 return pRet;
101244 }
101245
101246 #ifndef SQLITE_OMIT_CTE
101247 /*
101248 ** This routine generates VDBE code to compute the content of a WITH RECURSIVE
101249 ** query of the form:
@@ -101294,23 +101313,20 @@
101313 pOffset = p->pOffset;
101314 regLimit = p->iLimit;
101315 regOffset = p->iOffset;
101316 p->pLimit = p->pOffset = 0;
101317 p->iLimit = p->iOffset = 0;
101318 pOrderBy = p->pOrderBy;
101319
101320 /* Locate the cursor number of the Current table */
101321 for(i=0; ALWAYS(i<pSrc->nSrc); i++){
101322 if( pSrc->a[i].isRecursive ){
101323 iCurrent = pSrc->a[i].iCursor;
101324 break;
101325 }
101326 }
101327
 
 
 
 
101328 /* Allocate cursors numbers for Queue and Distinct. The cursor number for
101329 ** the Distinct table must be exactly one greater than Queue in order
101330 ** for the SRT_DistTable and SRT_DistQueue destinations to work. */
101331 iQueue = pParse->nTab++;
101332 if( p->op==TK_UNION ){
@@ -101323,11 +101339,11 @@
101339
101340 /* Allocate cursors for Current, Queue, and Distinct. */
101341 regCurrent = ++pParse->nMem;
101342 sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol);
101343 if( pOrderBy ){
101344 KeyInfo *pKeyInfo = multiSelectOrderByKeyInfo(pParse, p, 1);
101345 sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0,
101346 (char*)pKeyInfo, P4_KEYINFO);
101347 destQueue.pOrderBy = pOrderBy;
101348 }else{
101349 sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iQueue, nCol);
@@ -101335,10 +101351,13 @@
101351 VdbeComment((v, "Queue table"));
101352 if( iDistinct ){
101353 p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0);
101354 p->selFlags |= SF_UsesEphemeral;
101355 }
101356
101357 /* Detach the ORDER BY clause from the compound SELECT */
101358 p->pOrderBy = 0;
101359
101360 /* Store the results of the setup-query in Queue. */
101361 rc = sqlite3Select(pParse, pSetup, &destQueue);
101362 if( rc ) goto end_of_recursive_query;
101363
@@ -101378,21 +101397,20 @@
101397 p->pOrderBy = pOrderBy;
101398 p->pLimit = pLimit;
101399 p->pOffset = pOffset;
101400 return;
101401 }
101402 #endif /* SQLITE_OMIT_CTE */
101403
101404 /* Forward references */
101405 static int multiSelectOrderBy(
101406 Parse *pParse, /* Parsing context */
101407 Select *p, /* The right-most of SELECTs to be coded */
101408 SelectDest *pDest /* What to do with query results */
101409 );
101410
101411
 
101412 /*
101413 ** This routine is called to process a compound query form from
101414 ** two or more separate queries using UNION, UNION ALL, EXCEPT, or
101415 ** INTERSECT
101416 **
@@ -102120,28 +102138,11 @@
102138 for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
102139 assert( pItem->u.x.iOrderByCol>0
102140 && pItem->u.x.iOrderByCol<=p->pEList->nExpr );
102141 aPermute[i] = pItem->u.x.iOrderByCol - 1;
102142 }
102143 pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102144 }else{
102145 pKeyMerge = 0;
102146 }
102147
102148 /* Reattach the ORDER BY clause to the query.
@@ -106614,13 +106615,14 @@
106615 oldmask |= sqlite3TriggerColmask(pParse,
106616 pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
106617 );
106618 for(i=0; i<pTab->nCol; i++){
106619 if( oldmask==0xffffffff
106620 || (i<32 && (oldmask & MASKBIT32(i))!=0)
106621 || (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0
106622 ){
106623 testcase( oldmask!=0xffffffff && i==31 );
106624 sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i);
106625 }else{
106626 sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
106627 }
106628 }
@@ -106651,11 +106653,11 @@
106653 sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
106654 }else{
106655 j = aXRef[i];
106656 if( j>=0 ){
106657 sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
106658 }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){
106659 /* This branch loads the value of a column that will not be changed
106660 ** into a register. This is done if there are no BEFORE triggers, or
106661 ** if there are one or more BEFORE triggers that use this value via
106662 ** a new.* reference in a trigger program.
106663 */
@@ -112160,11 +112162,13 @@
112162 int iTerm;
112163 for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
112164 Expr *pExpr = pWC->a[iTerm].pExpr;
112165 if( &pWC->a[iTerm] == pTerm ) continue;
112166 if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
112167 testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO );
112168 testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL );
112169 if( pWC->a[iTerm].wtFlags & (TERM_ORINFO|TERM_VIRTUAL) ) continue;
112170 if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
112171 pExpr = sqlite3ExprDup(db, pExpr, 0);
112172 pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
112173 }
112174 if( pAndExpr ){
@@ -122726,11 +122730,11 @@
122730 ** database files might have arbitrary corruption. Setting the flag during
122731 ** testing causes certain assert() statements in the code to be activated
122732 ** that demonstrat invariants on well-formed database files.
122733 */
122734 case SQLITE_TESTCTRL_NEVER_CORRUPT: {
122735 sqlite3GlobalConfig.neverCorrupt = va_arg(ap, int);
122736 break;
122737 }
122738
122739 }
122740 va_end(ap);
@@ -131724,17 +131728,17 @@
131728 /*
131729 ** Hash and comparison functions when the mode is FTS3_HASH_STRING
131730 */
131731 static int fts3StrHash(const void *pKey, int nKey){
131732 const char *z = (const char *)pKey;
131733 unsigned h = 0;
131734 if( nKey<=0 ) nKey = (int) strlen(z);
131735 while( nKey > 0 ){
131736 h = (h<<3) ^ h ^ *z++;
131737 nKey--;
131738 }
131739 return (int)(h & 0x7fffffff);
131740 }
131741 static int fts3StrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
131742 if( n1!=n2 ) return 1;
131743 return strncmp((const char*)pKey1,(const char*)pKey2,n1);
131744 }
131745
+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-22 18:31:27 dea2ca6a159d5dcfd8deceedf1c2a73fb4ac1cfc"
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-22 18:31:27 dea2ca6a159d5dcfd8deceedf1c2a73fb4ac1cfc"
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
+5 -9
--- 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
},
@@ -1264,11 +1260,11 @@
12641260
void page_test_env(void){
12651261
char c;
12661262
int i;
12671263
int showAll;
12681264
char zCap[30];
1269
- static const char *azCgiVars[] = {
1265
+ static const char *const azCgiVars[] = {
12701266
"COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE",
12711267
"HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET", "HTTP_ACCEPT_ENCODING",
12721268
"HTTP_ACCEPT_LANGUAGE", "HTTP_CONNECTION", "HTTP_HOST",
12731269
"HTTP_USER_AGENT", "HTTP_REFERER", "PATH_INFO", "PATH_TRANSLATED",
12741270
"QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT", "REQUEST_METHOD",
12751271
--- 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 },
@@ -1264,11 +1260,11 @@
1264 void page_test_env(void){
1265 char c;
1266 int i;
1267 int showAll;
1268 char zCap[30];
1269 static const char *azCgiVars[] = {
1270 "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE",
1271 "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET", "HTTP_ACCEPT_ENCODING",
1272 "HTTP_ACCEPT_LANGUAGE", "HTTP_CONNECTION", "HTTP_HOST",
1273 "HTTP_USER_AGENT", "HTTP_REFERER", "PATH_INFO", "PATH_TRANSLATED",
1274 "QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT", "REQUEST_METHOD",
1275
--- 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 },
@@ -1264,11 +1260,11 @@
1260 void page_test_env(void){
1261 char c;
1262 int i;
1263 int showAll;
1264 char zCap[30];
1265 static const char *const azCgiVars[] = {
1266 "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE",
1267 "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET", "HTTP_ACCEPT_ENCODING",
1268 "HTTP_ACCEPT_LANGUAGE", "HTTP_CONNECTION", "HTTP_HOST",
1269 "HTTP_USER_AGENT", "HTTP_REFERER", "PATH_INFO", "PATH_TRANSLATED",
1270 "QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT", "REQUEST_METHOD",
1271
-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
+8 -4
--- 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
*/
@@ -182,7 +186,7 @@
182186
/*
183187
** Useful functions from th_lang.c.
184188
*/
185189
int Th_WrongNumArgs(Th_Interp *interp, const char *zMsg);
186190
187
-typedef struct Th_SubCommand {char *zName; Th_CommandProc xProc;} Th_SubCommand;
188
-int Th_CallSubCommand(Th_Interp*,void*,int,const char**,int*,Th_SubCommand*);
191
+typedef struct Th_SubCommand {const char *zName; Th_CommandProc xProc;} Th_SubCommand;
192
+int Th_CallSubCommand(Th_Interp*,void*,int,const char**,int*,const Th_SubCommand*);
189193
--- 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 */
@@ -182,7 +186,7 @@
182 /*
183 ** Useful functions from th_lang.c.
184 */
185 int Th_WrongNumArgs(Th_Interp *interp, const char *zMsg);
186
187 typedef struct Th_SubCommand {char *zName; Th_CommandProc xProc;} Th_SubCommand;
188 int Th_CallSubCommand(Th_Interp*,void*,int,const char**,int*,Th_SubCommand*);
189
--- 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 */
@@ -182,7 +186,7 @@
186 /*
187 ** Useful functions from th_lang.c.
188 */
189 int Th_WrongNumArgs(Th_Interp *interp, const char *zMsg);
190
191 typedef struct Th_SubCommand {const char *zName; Th_CommandProc xProc;} Th_SubCommand;
192 int Th_CallSubCommand(Th_Interp*,void*,int,const char**,int*,const Th_SubCommand*);
193
+7 -7
--- src/th_lang.c
+++ src/th_lang.c
@@ -425,11 +425,11 @@
425425
int argc,
426426
const char **argv,
427427
int *argl
428428
){
429429
int rc;
430
- char *zName;
430
+ const char *zName;
431431
432432
ProcDefn *p;
433433
int nByte;
434434
int i;
435435
char *zSpace;
@@ -521,11 +521,11 @@
521521
}
522522
p->zUsage = zUsage;
523523
p->nUsage = nUsage;
524524
525525
/* Register the new command with the th1 interpreter. */
526
- zName = (char *)argv[1];
526
+ zName = argv[1];
527527
rc = Th_CreateCommand(interp, zName, proc_call1, (void *)p, proc_del);
528528
if( rc==TH_OK ){
529529
Th_SetResult(interp, 0, 0);
530530
}
531531
@@ -887,16 +887,16 @@
887887
Th_Interp *interp,
888888
void *ctx,
889889
int argc,
890890
const char **argv,
891891
int *argl,
892
- Th_SubCommand *aSub
892
+ const Th_SubCommand *aSub
893893
){
894894
if( argc>1 ){
895895
int i;
896896
for(i=0; aSub[i].zName; i++){
897
- char *zName = (char *)aSub[i].zName;
897
+ const char *zName = aSub[i].zName;
898898
if( th_strlen(zName)==argl[1] && 0==memcmp(zName, argv[1], argl[1]) ){
899899
return aSub[i].xProc(interp, ctx, argc, argv, argl);
900900
}
901901
}
902902
}
@@ -924,11 +924,11 @@
924924
void *ctx,
925925
int argc,
926926
const char **argv,
927927
int *argl
928928
){
929
- Th_SubCommand aSub[] = {
929
+ static const Th_SubCommand aSub[] = {
930930
{ "compare", string_compare_command },
931931
{ "first", string_first_command },
932932
{ "is", string_is_command },
933933
{ "last", string_last_command },
934934
{ "length", string_length_command },
@@ -952,11 +952,11 @@
952952
void *ctx,
953953
int argc,
954954
const char **argv,
955955
int *argl
956956
){
957
- Th_SubCommand aSub[] = {
957
+ static const Th_SubCommand aSub[] = {
958958
{ "exists", info_exists_command },
959959
{ 0, 0 }
960960
};
961961
return Th_CallSubCommand(interp, ctx, argc, argv, argl, aSub);
962962
}
@@ -1097,11 +1097,11 @@
10971097
{"continue", simple_command, (void *)TH_CONTINUE},
10981098
{"error", simple_command, (void *)TH_ERROR},
10991099
11001100
{0, 0, 0}
11011101
};
1102
- int i;
1102
+ size_t i;
11031103
11041104
/* Add the language commands. */
11051105
for(i=0; i<(sizeof(aCommand)/sizeof(aCommand[0])); i++){
11061106
void *ctx;
11071107
if ( !aCommand[i].zName || !aCommand[i].xProc ) continue;
11081108
--- src/th_lang.c
+++ src/th_lang.c
@@ -425,11 +425,11 @@
425 int argc,
426 const char **argv,
427 int *argl
428 ){
429 int rc;
430 char *zName;
431
432 ProcDefn *p;
433 int nByte;
434 int i;
435 char *zSpace;
@@ -521,11 +521,11 @@
521 }
522 p->zUsage = zUsage;
523 p->nUsage = nUsage;
524
525 /* Register the new command with the th1 interpreter. */
526 zName = (char *)argv[1];
527 rc = Th_CreateCommand(interp, zName, proc_call1, (void *)p, proc_del);
528 if( rc==TH_OK ){
529 Th_SetResult(interp, 0, 0);
530 }
531
@@ -887,16 +887,16 @@
887 Th_Interp *interp,
888 void *ctx,
889 int argc,
890 const char **argv,
891 int *argl,
892 Th_SubCommand *aSub
893 ){
894 if( argc>1 ){
895 int i;
896 for(i=0; aSub[i].zName; i++){
897 char *zName = (char *)aSub[i].zName;
898 if( th_strlen(zName)==argl[1] && 0==memcmp(zName, argv[1], argl[1]) ){
899 return aSub[i].xProc(interp, ctx, argc, argv, argl);
900 }
901 }
902 }
@@ -924,11 +924,11 @@
924 void *ctx,
925 int argc,
926 const char **argv,
927 int *argl
928 ){
929 Th_SubCommand aSub[] = {
930 { "compare", string_compare_command },
931 { "first", string_first_command },
932 { "is", string_is_command },
933 { "last", string_last_command },
934 { "length", string_length_command },
@@ -952,11 +952,11 @@
952 void *ctx,
953 int argc,
954 const char **argv,
955 int *argl
956 ){
957 Th_SubCommand aSub[] = {
958 { "exists", info_exists_command },
959 { 0, 0 }
960 };
961 return Th_CallSubCommand(interp, ctx, argc, argv, argl, aSub);
962 }
@@ -1097,11 +1097,11 @@
1097 {"continue", simple_command, (void *)TH_CONTINUE},
1098 {"error", simple_command, (void *)TH_ERROR},
1099
1100 {0, 0, 0}
1101 };
1102 int i;
1103
1104 /* Add the language commands. */
1105 for(i=0; i<(sizeof(aCommand)/sizeof(aCommand[0])); i++){
1106 void *ctx;
1107 if ( !aCommand[i].zName || !aCommand[i].xProc ) continue;
1108
--- src/th_lang.c
+++ src/th_lang.c
@@ -425,11 +425,11 @@
425 int argc,
426 const char **argv,
427 int *argl
428 ){
429 int rc;
430 const char *zName;
431
432 ProcDefn *p;
433 int nByte;
434 int i;
435 char *zSpace;
@@ -521,11 +521,11 @@
521 }
522 p->zUsage = zUsage;
523 p->nUsage = nUsage;
524
525 /* Register the new command with the th1 interpreter. */
526 zName = argv[1];
527 rc = Th_CreateCommand(interp, zName, proc_call1, (void *)p, proc_del);
528 if( rc==TH_OK ){
529 Th_SetResult(interp, 0, 0);
530 }
531
@@ -887,16 +887,16 @@
887 Th_Interp *interp,
888 void *ctx,
889 int argc,
890 const char **argv,
891 int *argl,
892 const Th_SubCommand *aSub
893 ){
894 if( argc>1 ){
895 int i;
896 for(i=0; aSub[i].zName; i++){
897 const char *zName = aSub[i].zName;
898 if( th_strlen(zName)==argl[1] && 0==memcmp(zName, argv[1], argl[1]) ){
899 return aSub[i].xProc(interp, ctx, argc, argv, argl);
900 }
901 }
902 }
@@ -924,11 +924,11 @@
924 void *ctx,
925 int argc,
926 const char **argv,
927 int *argl
928 ){
929 static const Th_SubCommand aSub[] = {
930 { "compare", string_compare_command },
931 { "first", string_first_command },
932 { "is", string_is_command },
933 { "last", string_last_command },
934 { "length", string_length_command },
@@ -952,11 +952,11 @@
952 void *ctx,
953 int argc,
954 const char **argv,
955 int *argl
956 ){
957 static const Th_SubCommand aSub[] = {
958 { "exists", info_exists_command },
959 { 0, 0 }
960 };
961 return Th_CallSubCommand(interp, ctx, argc, argv, argl, aSub);
962 }
@@ -1097,11 +1097,11 @@
1097 {"continue", simple_command, (void *)TH_CONTINUE},
1098 {"error", simple_command, (void *)TH_ERROR},
1099
1100 {0, 0, 0}
1101 };
1102 size_t i;
1103
1104 /* Add the language commands. */
1105 for(i=0; i<(sizeof(aCommand)/sizeof(aCommand[0])); i++){
1106 void *ctx;
1107 if ( !aCommand[i].zName || !aCommand[i].xProc ) continue;
1108
--- 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
+39 -24
--- src/timeline.c
+++ src/timeline.c
@@ -247,14 +247,14 @@
247247
int fchngQueryInit = 0; /* True if fchngQuery is initialized */
248248
Stmt fchngQuery; /* Query for file changes on check-ins */
249249
static Stmt qbranch;
250250
int pendingEndTr = 0; /* True if a </td></tr> is needed */
251251
int vid = 0; /* Current checkout version */
252
- int dateFormat = 0; /* 0: HH:MM 1: HH:MM:SS
252
+ int dateFormat = 0; /* 0: HH:MM 1: HH:MM:SS
253253
2: YYYY-MM-DD HH:MM
254254
3: YYMMDD HH:MM */
255
-
255
+
256256
if( fossil_strcmp(g.zIpAddr, "127.0.0.1")==0 && db_open_local(0) ){
257257
vid = db_lget_int("checkout", 0);
258258
}
259259
zPrevDate[0] = 0;
260260
mxWikiLen = db_get_int("timeline-max-comment", 0);
@@ -591,13 +591,12 @@
591591
){
592592
if( pGraph && pGraph->nErr==0 && pGraph->nRow>0 ){
593593
GraphRow *pRow;
594594
int i;
595595
char cSep;
596
-
597
- @ <script type="text/JavaScript">
598
- @ /* <![CDATA[ */
596
+
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
/*
@@ -2077,16 +2075,24 @@
20772075
}
20782076
20792077
/*
20802078
** A helper for the /reports family of pages which prints out a menu
20812079
** of links for the various type=XXX flags. zCurrentViewName must be
2082
-** the name/value of the 'view' parameter which is in effect at
2083
-** the time this is called. e.g. if called from the 'byuser' view
2084
-** then zCurrentViewName must be "byuser".
2085
-*/
2086
-static void stats_report_event_types_menu(char const * zCurrentViewName){
2087
- char * zTop = mprintf("%s/reports?view=%s", g.zTop, zCurrentViewName);
2080
+** the name/value of the 'view' parameter which is in effect at the
2081
+** time this is called. e.g. if called from the 'byuser' view then
2082
+** zCurrentViewName must be "byuser". Any URL parameters which need to
2083
+** be added to the generated URLs should be passed in zParam. The
2084
+** caller is expected to have already encoded any zParam in the %T or
2085
+** %t encoding. */
2086
+static void stats_report_event_types_menu(char const * zCurrentViewName,
2087
+ char const * zParam){
2088
+ char * zTop;
2089
+ if(zParam && !*zParam){
2090
+ zParam = NULL;
2091
+ }
2092
+ zTop = mprintf("%s/reports?view=%s%s%s", g.zTop, zCurrentViewName,
2093
+ zParam ? "&" : "", zParam);
20882094
cgi_printf("<div>");
20892095
cgi_printf("<span>Event types:</span> ");
20902096
if('*' == statsReportType){
20912097
cgi_printf(" <strong>all</strong>", zTop);
20922098
}else{
@@ -2173,11 +2179,11 @@
21732179
int nMaxEvents = 1; /* for calculating length of graph
21742180
bars. */
21752181
int iterations = 0; /* number of weeks/months we iterate
21762182
over */
21772183
stats_report_init_view();
2178
- stats_report_event_types_menu( includeMonth ? "bymonth" : "byyear" );
2184
+ stats_report_event_types_menu( includeMonth ? "bymonth" : "byyear", NULL );
21792185
blob_appendf(&header, "Timeline Events (%s) by year%s",
21802186
stats_report_label_for_type(),
21812187
(includeMonth ? "/month" : ""));
21822188
blob_appendf(&sql,
21832189
"SELECT substr(date(mtime),1,%d) AS timeframe, "
@@ -2232,11 +2238,11 @@
22322238
if(showYearTotal){
22332239
rowClass = ++nRowNumber % 2;
22342240
@ <tr class='row%d(rowClass)'>
22352241
@ <td></td>
22362242
@ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
2237
- @</tr>
2243
+ @</tr>
22382244
}
22392245
nEventsPerYear = 0;
22402246
memcpy(zPrevYear,zTimeframe,4);
22412247
rowClass = ++nRowNumber % 2;
22422248
@ <tr class='row%d(rowClass)'>
@@ -2270,12 +2276,12 @@
22702276
cgi_printf("'>%s</a>", zTimeframe);
22712277
}
22722278
@ </td><td>%d(nCount)</td>
22732279
@ <td>
22742280
@ <div class='statistics-report-graph-line'
2275
- @ style='height:16px;width:%d(nSize)%%;'>
2276
- @ </div></td>
2281
+ @ style='width:%d(nSize)%%;'>&nbsp;</div>
2282
+ @ </td>
22772283
@</tr>
22782284
if(includeWeeks){
22792285
/* This part works fine for months but it terribly slow (4.5s on my PC),
22802286
so it's only shown for by-year for now. Suggestions/patches for
22812287
a better/faster layout are welcomed. */
@@ -2296,11 +2302,11 @@
22962302
/* Add final year total separator. */
22972303
rowClass = ++nRowNumber % 2;
22982304
@ <tr class='row%d(rowClass)'>
22992305
@ <td></td>
23002306
@ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
2301
- @</tr>
2307
+ @</tr>
23022308
}
23032309
@ </tbody></table>
23042310
if(nEventTotal){
23052311
char const * zAvgLabel = includeMonth ? "month" : "year";
23062312
int nAvg = iterations ? (nEventTotal/iterations) : 0;
@@ -2324,11 +2330,11 @@
23242330
row colors */
23252331
Blob sql = empty_blob; /* SQL */
23262332
int nMaxEvents = 1; /* max number of events for
23272333
all rows. */
23282334
stats_report_init_view();
2329
- stats_report_event_types_menu("byuser");
2335
+ stats_report_event_types_menu("byuser", NULL);
23302336
blob_append(&sql,
23312337
"SELECT user, "
23322338
"COUNT(*) AS eventCount "
23332339
"FROM v_reports "
23342340
"GROUP BY user ORDER BY eventCount DESC",
@@ -2365,12 +2371,12 @@
23652371
@ <td>
23662372
@ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a>
23672373
@ </td><td>%d(nCount)</td>
23682374
@ <td>
23692375
@ <div class='statistics-report-graph-line'
2370
- @ style='height:16px;width:%d(nSize)%%;'>
2371
- @ </div></td>
2376
+ @ style='width:%d(nSize)%%;'>&nbsp;</div>
2377
+ @ </td>
23722378
@</tr>
23732379
/*
23742380
Potential improvement: calculate the min/max event counts and
23752381
use percent-based graph bars.
23762382
*/
@@ -2395,21 +2401,28 @@
23952401
Blob sql = empty_blob;
23962402
int nMaxEvents = 1; /* max number of events for
23972403
all rows. */
23982404
int iterations = 0; /* # of active time periods. */
23992405
stats_report_init_view();
2400
- stats_report_event_types_menu("byweek");
2401
- cgi_printf("Select year: ");
2406
+ if(4==nYear){
2407
+ Blob urlParams = empty_blob;
2408
+ blob_appendf(&urlParams, "y=%T", zYear);
2409
+ stats_report_event_types_menu("byweek", blob_str(&urlParams));
2410
+ blob_reset(&urlParams);
2411
+ }else{
2412
+ stats_report_event_types_menu("byweek", NULL);
2413
+ }
24022414
blob_append(&sql,
24032415
"SELECT DISTINCT substr(date(mtime),1,4) AS y "
24042416
"FROM v_reports WHERE 1 ", -1);
24052417
if(zUserName&&*zUserName){
24062418
blob_appendf(&sql,"AND user=%Q ", zUserName);
24072419
}
24082420
blob_append(&sql,"GROUP BY y ORDER BY y", -1);
24092421
db_prepare(&qYears, blob_str(&sql));
24102422
blob_reset(&sql);
2423
+ cgi_printf("Select year: ");
24112424
while( SQLITE_ROW == db_step(&qYears) ){
24122425
const char * zT = db_column_text(&qYears, 0);
24132426
if( i++ ){
24142427
cgi_printf(" ");
24152428
}
@@ -2487,11 +2500,11 @@
24872500
24882501
cgi_printf("<td>%d</td>",nCount);
24892502
cgi_printf("<td>");
24902503
if(nCount){
24912504
cgi_printf("<div class='statistics-report-graph-line'"
2492
- "style='height:16px;width:%d%%;'></div>",
2505
+ "style='width:%d%%;'>&nbsp;</div>",
24932506
nSize);
24942507
}
24952508
cgi_printf("</td></tr>");
24962509
}
24972510
db_finalize(&stWeek);
@@ -2529,13 +2542,15 @@
25292542
*/
25302543
void stats_report_page(){
25312544
HQuery url; /* URL for various branch links */
25322545
const char * zView = P("view"); /* Which view/report to show. */
25332546
const char *zUserName = P("user");
2547
+
2548
+ login_check_credentials();
2549
+ if( !g.perm.Read ){ login_needed(); return; }
25342550
if(!zUserName) zUserName = P("u");
25352551
url_initialize(&url, "reports");
2536
-
25372552
if(zUserName && *zUserName){
25382553
url_add_parameter(&url,"user", zUserName);
25392554
timeline_submenu(&url, "(Remove User Flag)", "view", zView, "user");
25402555
}
25412556
timeline_submenu(&url, "By Year", "view", "byyear", 0);
25422557
--- src/timeline.c
+++ src/timeline.c
@@ -247,14 +247,14 @@
247 int fchngQueryInit = 0; /* True if fchngQuery is initialized */
248 Stmt fchngQuery; /* Query for file changes on check-ins */
249 static Stmt qbranch;
250 int pendingEndTr = 0; /* True if a </td></tr> is needed */
251 int vid = 0; /* Current checkout version */
252 int dateFormat = 0; /* 0: HH:MM 1: HH:MM:SS
253 2: YYYY-MM-DD HH:MM
254 3: YYMMDD HH:MM */
255
256 if( fossil_strcmp(g.zIpAddr, "127.0.0.1")==0 && db_open_local(0) ){
257 vid = db_lget_int("checkout", 0);
258 }
259 zPrevDate[0] = 0;
260 mxWikiLen = db_get_int("timeline-max-comment", 0);
@@ -591,13 +591,12 @@
591 ){
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 /*
@@ -2077,16 +2075,24 @@
2077 }
2078
2079 /*
2080 ** A helper for the /reports family of pages which prints out a menu
2081 ** of links for the various type=XXX flags. zCurrentViewName must be
2082 ** the name/value of the 'view' parameter which is in effect at
2083 ** the time this is called. e.g. if called from the 'byuser' view
2084 ** then zCurrentViewName must be "byuser".
2085 */
2086 static void stats_report_event_types_menu(char const * zCurrentViewName){
2087 char * zTop = mprintf("%s/reports?view=%s", g.zTop, zCurrentViewName);
 
 
 
 
 
 
 
 
2088 cgi_printf("<div>");
2089 cgi_printf("<span>Event types:</span> ");
2090 if('*' == statsReportType){
2091 cgi_printf(" <strong>all</strong>", zTop);
2092 }else{
@@ -2173,11 +2179,11 @@
2173 int nMaxEvents = 1; /* for calculating length of graph
2174 bars. */
2175 int iterations = 0; /* number of weeks/months we iterate
2176 over */
2177 stats_report_init_view();
2178 stats_report_event_types_menu( includeMonth ? "bymonth" : "byyear" );
2179 blob_appendf(&header, "Timeline Events (%s) by year%s",
2180 stats_report_label_for_type(),
2181 (includeMonth ? "/month" : ""));
2182 blob_appendf(&sql,
2183 "SELECT substr(date(mtime),1,%d) AS timeframe, "
@@ -2232,11 +2238,11 @@
2232 if(showYearTotal){
2233 rowClass = ++nRowNumber % 2;
2234 @ <tr class='row%d(rowClass)'>
2235 @ <td></td>
2236 @ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
2237 @</tr>
2238 }
2239 nEventsPerYear = 0;
2240 memcpy(zPrevYear,zTimeframe,4);
2241 rowClass = ++nRowNumber % 2;
2242 @ <tr class='row%d(rowClass)'>
@@ -2270,12 +2276,12 @@
2270 cgi_printf("'>%s</a>", zTimeframe);
2271 }
2272 @ </td><td>%d(nCount)</td>
2273 @ <td>
2274 @ <div class='statistics-report-graph-line'
2275 @ style='height:16px;width:%d(nSize)%%;'>
2276 @ </div></td>
2277 @</tr>
2278 if(includeWeeks){
2279 /* This part works fine for months but it terribly slow (4.5s on my PC),
2280 so it's only shown for by-year for now. Suggestions/patches for
2281 a better/faster layout are welcomed. */
@@ -2296,11 +2302,11 @@
2296 /* Add final year total separator. */
2297 rowClass = ++nRowNumber % 2;
2298 @ <tr class='row%d(rowClass)'>
2299 @ <td></td>
2300 @ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
2301 @</tr>
2302 }
2303 @ </tbody></table>
2304 if(nEventTotal){
2305 char const * zAvgLabel = includeMonth ? "month" : "year";
2306 int nAvg = iterations ? (nEventTotal/iterations) : 0;
@@ -2324,11 +2330,11 @@
2324 row colors */
2325 Blob sql = empty_blob; /* SQL */
2326 int nMaxEvents = 1; /* max number of events for
2327 all rows. */
2328 stats_report_init_view();
2329 stats_report_event_types_menu("byuser");
2330 blob_append(&sql,
2331 "SELECT user, "
2332 "COUNT(*) AS eventCount "
2333 "FROM v_reports "
2334 "GROUP BY user ORDER BY eventCount DESC",
@@ -2365,12 +2371,12 @@
2365 @ <td>
2366 @ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a>
2367 @ </td><td>%d(nCount)</td>
2368 @ <td>
2369 @ <div class='statistics-report-graph-line'
2370 @ style='height:16px;width:%d(nSize)%%;'>
2371 @ </div></td>
2372 @</tr>
2373 /*
2374 Potential improvement: calculate the min/max event counts and
2375 use percent-based graph bars.
2376 */
@@ -2395,21 +2401,28 @@
2395 Blob sql = empty_blob;
2396 int nMaxEvents = 1; /* max number of events for
2397 all rows. */
2398 int iterations = 0; /* # of active time periods. */
2399 stats_report_init_view();
2400 stats_report_event_types_menu("byweek");
2401 cgi_printf("Select year: ");
 
 
 
 
 
 
2402 blob_append(&sql,
2403 "SELECT DISTINCT substr(date(mtime),1,4) AS y "
2404 "FROM v_reports WHERE 1 ", -1);
2405 if(zUserName&&*zUserName){
2406 blob_appendf(&sql,"AND user=%Q ", zUserName);
2407 }
2408 blob_append(&sql,"GROUP BY y ORDER BY y", -1);
2409 db_prepare(&qYears, blob_str(&sql));
2410 blob_reset(&sql);
 
2411 while( SQLITE_ROW == db_step(&qYears) ){
2412 const char * zT = db_column_text(&qYears, 0);
2413 if( i++ ){
2414 cgi_printf(" ");
2415 }
@@ -2487,11 +2500,11 @@
2487
2488 cgi_printf("<td>%d</td>",nCount);
2489 cgi_printf("<td>");
2490 if(nCount){
2491 cgi_printf("<div class='statistics-report-graph-line'"
2492 "style='height:16px;width:%d%%;'></div>",
2493 nSize);
2494 }
2495 cgi_printf("</td></tr>");
2496 }
2497 db_finalize(&stWeek);
@@ -2529,13 +2542,15 @@
2529 */
2530 void stats_report_page(){
2531 HQuery url; /* URL for various branch links */
2532 const char * zView = P("view"); /* Which view/report to show. */
2533 const char *zUserName = P("user");
 
 
 
2534 if(!zUserName) zUserName = P("u");
2535 url_initialize(&url, "reports");
2536
2537 if(zUserName && *zUserName){
2538 url_add_parameter(&url,"user", zUserName);
2539 timeline_submenu(&url, "(Remove User Flag)", "view", zView, "user");
2540 }
2541 timeline_submenu(&url, "By Year", "view", "byyear", 0);
2542
--- src/timeline.c
+++ src/timeline.c
@@ -247,14 +247,14 @@
247 int fchngQueryInit = 0; /* True if fchngQuery is initialized */
248 Stmt fchngQuery; /* Query for file changes on check-ins */
249 static Stmt qbranch;
250 int pendingEndTr = 0; /* True if a </td></tr> is needed */
251 int vid = 0; /* Current checkout version */
252 int dateFormat = 0; /* 0: HH:MM 1: HH:MM:SS
253 2: YYYY-MM-DD HH:MM
254 3: YYMMDD HH:MM */
255
256 if( fossil_strcmp(g.zIpAddr, "127.0.0.1")==0 && db_open_local(0) ){
257 vid = db_lget_int("checkout", 0);
258 }
259 zPrevDate[0] = 0;
260 mxWikiLen = db_get_int("timeline-max-comment", 0);
@@ -591,13 +591,12 @@
591 ){
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 /*
@@ -2077,16 +2075,24 @@
2075 }
2076
2077 /*
2078 ** A helper for the /reports family of pages which prints out a menu
2079 ** of links for the various type=XXX flags. zCurrentViewName must be
2080 ** the name/value of the 'view' parameter which is in effect at the
2081 ** time this is called. e.g. if called from the 'byuser' view then
2082 ** zCurrentViewName must be "byuser". Any URL parameters which need to
2083 ** be added to the generated URLs should be passed in zParam. The
2084 ** caller is expected to have already encoded any zParam in the %T or
2085 ** %t encoding. */
2086 static void stats_report_event_types_menu(char const * zCurrentViewName,
2087 char const * zParam){
2088 char * zTop;
2089 if(zParam && !*zParam){
2090 zParam = NULL;
2091 }
2092 zTop = mprintf("%s/reports?view=%s%s%s", g.zTop, zCurrentViewName,
2093 zParam ? "&" : "", zParam);
2094 cgi_printf("<div>");
2095 cgi_printf("<span>Event types:</span> ");
2096 if('*' == statsReportType){
2097 cgi_printf(" <strong>all</strong>", zTop);
2098 }else{
@@ -2173,11 +2179,11 @@
2179 int nMaxEvents = 1; /* for calculating length of graph
2180 bars. */
2181 int iterations = 0; /* number of weeks/months we iterate
2182 over */
2183 stats_report_init_view();
2184 stats_report_event_types_menu( includeMonth ? "bymonth" : "byyear", NULL );
2185 blob_appendf(&header, "Timeline Events (%s) by year%s",
2186 stats_report_label_for_type(),
2187 (includeMonth ? "/month" : ""));
2188 blob_appendf(&sql,
2189 "SELECT substr(date(mtime),1,%d) AS timeframe, "
@@ -2232,11 +2238,11 @@
2238 if(showYearTotal){
2239 rowClass = ++nRowNumber % 2;
2240 @ <tr class='row%d(rowClass)'>
2241 @ <td></td>
2242 @ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
2243 @</tr>
2244 }
2245 nEventsPerYear = 0;
2246 memcpy(zPrevYear,zTimeframe,4);
2247 rowClass = ++nRowNumber % 2;
2248 @ <tr class='row%d(rowClass)'>
@@ -2270,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. */
@@ -2296,11 +2302,11 @@
2302 /* Add final year total separator. */
2303 rowClass = ++nRowNumber % 2;
2304 @ <tr class='row%d(rowClass)'>
2305 @ <td></td>
2306 @ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
2307 @</tr>
2308 }
2309 @ </tbody></table>
2310 if(nEventTotal){
2311 char const * zAvgLabel = includeMonth ? "month" : "year";
2312 int nAvg = iterations ? (nEventTotal/iterations) : 0;
@@ -2324,11 +2330,11 @@
2330 row colors */
2331 Blob sql = empty_blob; /* SQL */
2332 int nMaxEvents = 1; /* max number of events for
2333 all rows. */
2334 stats_report_init_view();
2335 stats_report_event_types_menu("byuser", NULL);
2336 blob_append(&sql,
2337 "SELECT user, "
2338 "COUNT(*) AS eventCount "
2339 "FROM v_reports "
2340 "GROUP BY user ORDER BY eventCount DESC",
@@ -2365,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 */
@@ -2395,21 +2401,28 @@
2401 Blob sql = empty_blob;
2402 int nMaxEvents = 1; /* max number of events for
2403 all rows. */
2404 int iterations = 0; /* # of active time periods. */
2405 stats_report_init_view();
2406 if(4==nYear){
2407 Blob urlParams = empty_blob;
2408 blob_appendf(&urlParams, "y=%T", zYear);
2409 stats_report_event_types_menu("byweek", blob_str(&urlParams));
2410 blob_reset(&urlParams);
2411 }else{
2412 stats_report_event_types_menu("byweek", NULL);
2413 }
2414 blob_append(&sql,
2415 "SELECT DISTINCT substr(date(mtime),1,4) AS y "
2416 "FROM v_reports WHERE 1 ", -1);
2417 if(zUserName&&*zUserName){
2418 blob_appendf(&sql,"AND user=%Q ", zUserName);
2419 }
2420 blob_append(&sql,"GROUP BY y ORDER BY y", -1);
2421 db_prepare(&qYears, blob_str(&sql));
2422 blob_reset(&sql);
2423 cgi_printf("Select year: ");
2424 while( SQLITE_ROW == db_step(&qYears) ){
2425 const char * zT = db_column_text(&qYears, 0);
2426 if( i++ ){
2427 cgi_printf(" ");
2428 }
@@ -2487,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);
@@ -2529,13 +2542,15 @@
2542 */
2543 void stats_report_page(){
2544 HQuery url; /* URL for various branch links */
2545 const char * zView = P("view"); /* Which view/report to show. */
2546 const char *zUserName = P("user");
2547
2548 login_check_credentials();
2549 if( !g.perm.Read ){ login_needed(); return; }
2550 if(!zUserName) zUserName = P("u");
2551 url_initialize(&url, "reports");
 
2552 if(zUserName && *zUserName){
2553 url_add_parameter(&url,"user", zUserName);
2554 timeline_submenu(&url, "(Remove User Flag)", "view", zView, "user");
2555 }
2556 timeline_submenu(&url, "By Year", "view", "byyear", 0);
2557
+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
+40 -33
--- 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
**
@@ -189,48 +190,54 @@
189190
**
190191
*/
191192
void *fossil_utf8_to_filename(const char *zUtf8){
192193
#ifdef _WIN32
193194
int nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0);
194
- /* Overallocate 6 chars, making some room for extended paths */
195
- wchar_t *zUnicode = sqlite3_malloc( (nChar+6) * sizeof(wchar_t) );
195
+ /* Overallocate 4 chars, making some room for extended paths */
196
+ wchar_t *zUnicode = sqlite3_malloc( (nChar+4) * sizeof(wchar_t) );
196197
wchar_t *wUnicode = zUnicode;
197198
if( zUnicode==0 ){
198199
return 0;
199200
}
201
+ MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
202
+ /*
203
+ ** If path starts with "//?/" or "\\?\" (extended path), translate
204
+ ** any slashes to backslashes but leave the '?' intact
205
+ */
206
+ if( (zUtf8[0]=='\\' || zUtf8[0]=='/') && (zUtf8[1]=='\\' || zUtf8[1]=='/')
207
+ && zUtf8[2]=='?' && (zUtf8[3]=='\\' || zUtf8[3]=='/')) {
208
+ wUnicode[0] = wUnicode[1] = wUnicode[3] = '\\';
209
+ zUtf8 += 4;
210
+ wUnicode += 4;
211
+ }
212
+ /*
213
+ ** If (remainder of) path starts with "<drive>:/" or "<drive>:\",
214
+ ** leave the ':' intact
215
+ */
200216
if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
201217
&& (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
202
- /* If path starts with "<drive>:[/\]", don't process the ':' */
203
- if( nChar>MAX_PATH ) {
204
- memcpy(zUnicode, L"\\\\?\\", 8);
205
- wUnicode += 4;
206
- MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, wUnicode, nChar);
207
- wUnicode[2] = '\\';
208
- wUnicode += 3;
209
- }else{
210
- zUnicode[0] = zUtf8[0];
211
- memcpy(&zUnicode[1], L":\\", 2 * sizeof(wchar_t));
212
- wUnicode += 3;
213
- MultiByteToWideChar(CP_UTF8, 0, zUtf8+3, -1, wUnicode, nChar-3);
214
- }
215
- }else if( (zUtf8[0]=='\\' || zUtf8[0]=='/') &&
216
- (zUtf8[1]=='\\' || zUtf8[1]=='/') ) {
217
- if( zUtf8[2]=='?' && nChar>7 ){
218
- /* Don't postprocess [?:] in extended path, but do '/' -> '\' */
219
- memcpy(zUnicode, L"\\\\", 2 * sizeof(wchar_t));
220
- MultiByteToWideChar(CP_UTF8, 0, zUtf8+2, -1, zUnicode+2, nChar-2);
221
- if( zUtf8[3]=='/' ) zUnicode[3]='\\';
222
- wUnicode += 6;
223
- }else if( nChar>MAX_PATH ){
224
- /* Convert to extended UNC path. */
225
- memcpy(zUnicode, L"\\\\?\\UNC\\", 16);
226
- wUnicode += 8;
227
- MultiByteToWideChar(CP_UTF8, 0, zUtf8+2, -1, wUnicode, nChar-2);
228
- }else{
229
- MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
230
- }
231
- }
218
+ if( wUnicode==zUnicode && nChar>MAX_PATH){
219
+ /*
220
+ ** If there is no "\\?\" prefix but there is a drive
221
+ ** prefix and the path is larger than MAX_PATH chars,
222
+ ** no Win32 API function can handle that unless it is
223
+ ** prefixed with the extended path prefix. See:
224
+ ** <http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath>
225
+ **/
226
+ memmove(wUnicode+4, wUnicode, nChar*sizeof(wchar_t));
227
+ memcpy(wUnicode, L"\\\\?\\", 4*sizeof(wchar_t));
228
+ wUnicode += 4;
229
+ }
230
+ wUnicode[2] = '\\';
231
+ wUnicode += 3;
232
+ }
233
+ /*
234
+ ** In the remainder of the path, translate invalid characters to
235
+ ** characters in the Unicode private use area. This is what makes
236
+ ** Win32 fossil.exe work well in a Cygwin environment even when a
237
+ ** filename contains characters which are invalid for Win32.
238
+ */
232239
while( *wUnicode != '\0' ){
233240
if ( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){
234241
*wUnicode |= 0xF000;
235242
}else if( *wUnicode == '/' ){
236243
*wUnicode = '\\';
237244
--- 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 **
@@ -189,48 +190,54 @@
189 **
190 */
191 void *fossil_utf8_to_filename(const char *zUtf8){
192 #ifdef _WIN32
193 int nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0);
194 /* Overallocate 6 chars, making some room for extended paths */
195 wchar_t *zUnicode = sqlite3_malloc( (nChar+6) * sizeof(wchar_t) );
196 wchar_t *wUnicode = zUnicode;
197 if( zUnicode==0 ){
198 return 0;
199 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200 if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
201 && (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
202 /* If path starts with "<drive>:[/\]", don't process the ':' */
203 if( nChar>MAX_PATH ) {
204 memcpy(zUnicode, L"\\\\?\\", 8);
205 wUnicode += 4;
206 MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, wUnicode, nChar);
207 wUnicode[2] = '\\';
208 wUnicode += 3;
209 }else{
210 zUnicode[0] = zUtf8[0];
211 memcpy(&zUnicode[1], L":\\", 2 * sizeof(wchar_t));
212 wUnicode += 3;
213 MultiByteToWideChar(CP_UTF8, 0, zUtf8+3, -1, wUnicode, nChar-3);
214 }
215 }else if( (zUtf8[0]=='\\' || zUtf8[0]=='/') &&
216 (zUtf8[1]=='\\' || zUtf8[1]=='/') ) {
217 if( zUtf8[2]=='?' && nChar>7 ){
218 /* Don't postprocess [?:] in extended path, but do '/' -> '\' */
219 memcpy(zUnicode, L"\\\\", 2 * sizeof(wchar_t));
220 MultiByteToWideChar(CP_UTF8, 0, zUtf8+2, -1, zUnicode+2, nChar-2);
221 if( zUtf8[3]=='/' ) zUnicode[3]='\\';
222 wUnicode += 6;
223 }else if( nChar>MAX_PATH ){
224 /* Convert to extended UNC path. */
225 memcpy(zUnicode, L"\\\\?\\UNC\\", 16);
226 wUnicode += 8;
227 MultiByteToWideChar(CP_UTF8, 0, zUtf8+2, -1, wUnicode, nChar-2);
228 }else{
229 MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
230 }
231 }
232 while( *wUnicode != '\0' ){
233 if ( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){
234 *wUnicode |= 0xF000;
235 }else if( *wUnicode == '/' ){
236 *wUnicode = '\\';
237
--- 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 **
@@ -189,48 +190,54 @@
190 **
191 */
192 void *fossil_utf8_to_filename(const char *zUtf8){
193 #ifdef _WIN32
194 int nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0);
195 /* Overallocate 4 chars, making some room for extended paths */
196 wchar_t *zUnicode = sqlite3_malloc( (nChar+4) * sizeof(wchar_t) );
197 wchar_t *wUnicode = zUnicode;
198 if( zUnicode==0 ){
199 return 0;
200 }
201 MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
202 /*
203 ** If path starts with "//?/" or "\\?\" (extended path), translate
204 ** any slashes to backslashes but leave the '?' intact
205 */
206 if( (zUtf8[0]=='\\' || zUtf8[0]=='/') && (zUtf8[1]=='\\' || zUtf8[1]=='/')
207 && zUtf8[2]=='?' && (zUtf8[3]=='\\' || zUtf8[3]=='/')) {
208 wUnicode[0] = wUnicode[1] = wUnicode[3] = '\\';
209 zUtf8 += 4;
210 wUnicode += 4;
211 }
212 /*
213 ** If (remainder of) path starts with "<drive>:/" or "<drive>:\",
214 ** leave the ':' intact
215 */
216 if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
217 && (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
218 if( wUnicode==zUnicode && nChar>MAX_PATH){
219 /*
220 ** If there is no "\\?\" prefix but there is a drive
221 ** prefix and the path is larger than MAX_PATH chars,
222 ** no Win32 API function can handle that unless it is
223 ** prefixed with the extended path prefix. See:
224 ** <http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath>
225 **/
226 memmove(wUnicode+4, wUnicode, nChar*sizeof(wchar_t));
227 memcpy(wUnicode, L"\\\\?\\", 4*sizeof(wchar_t));
228 wUnicode += 4;
229 }
230 wUnicode[2] = '\\';
231 wUnicode += 3;
232 }
233 /*
234 ** In the remainder of the path, translate invalid characters to
235 ** characters in the Unicode private use area. This is what makes
236 ** Win32 fossil.exe work well in a Cygwin environment even when a
237 ** filename contains characters which are invalid for Win32.
238 */
 
 
 
 
 
 
 
 
 
239 while( *wUnicode != '\0' ){
240 if ( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){
241 *wUnicode |= 0xF000;
242 }else if( *wUnicode == '/' ){
243 *wUnicode = '\\';
244
+40 -33
--- 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
**
@@ -189,48 +190,54 @@
189190
**
190191
*/
191192
void *fossil_utf8_to_filename(const char *zUtf8){
192193
#ifdef _WIN32
193194
int nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0);
194
- /* Overallocate 6 chars, making some room for extended paths */
195
- wchar_t *zUnicode = sqlite3_malloc( (nChar+6) * sizeof(wchar_t) );
195
+ /* Overallocate 4 chars, making some room for extended paths */
196
+ wchar_t *zUnicode = sqlite3_malloc( (nChar+4) * sizeof(wchar_t) );
196197
wchar_t *wUnicode = zUnicode;
197198
if( zUnicode==0 ){
198199
return 0;
199200
}
201
+ MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
202
+ /*
203
+ ** If path starts with "//?/" or "\\?\" (extended path), translate
204
+ ** any slashes to backslashes but leave the '?' intact
205
+ */
206
+ if( (zUtf8[0]=='\\' || zUtf8[0]=='/') && (zUtf8[1]=='\\' || zUtf8[1]=='/')
207
+ && zUtf8[2]=='?' && (zUtf8[3]=='\\' || zUtf8[3]=='/')) {
208
+ wUnicode[0] = wUnicode[1] = wUnicode[3] = '\\';
209
+ zUtf8 += 4;
210
+ wUnicode += 4;
211
+ }
212
+ /*
213
+ ** If (remainder of) path starts with "<drive>:/" or "<drive>:\",
214
+ ** leave the ':' intact
215
+ */
200216
if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
201217
&& (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
202
- /* If path starts with "<drive>:[/\]", don't process the ':' */
203
- if( nChar>MAX_PATH ) {
204
- memcpy(zUnicode, L"\\\\?\\", 8);
205
- wUnicode += 4;
206
- MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, wUnicode, nChar);
207
- wUnicode[2] = '\\';
208
- wUnicode += 3;
209
- }else{
210
- zUnicode[0] = zUtf8[0];
211
- memcpy(&zUnicode[1], L":\\", 2 * sizeof(wchar_t));
212
- wUnicode += 3;
213
- MultiByteToWideChar(CP_UTF8, 0, zUtf8+3, -1, wUnicode, nChar-3);
214
- }
215
- }else if( (zUtf8[0]=='\\' || zUtf8[0]=='/') &&
216
- (zUtf8[1]=='\\' || zUtf8[1]=='/') ) {
217
- if( zUtf8[2]=='?' && nChar>7 ){
218
- /* Don't postprocess [?:] in extended path, but do '/' -> '\' */
219
- memcpy(zUnicode, L"\\\\", 2 * sizeof(wchar_t));
220
- MultiByteToWideChar(CP_UTF8, 0, zUtf8+2, -1, zUnicode+2, nChar-2);
221
- if( zUtf8[3]=='/' ) zUnicode[3]='\\';
222
- wUnicode += 6;
223
- }else if( nChar>MAX_PATH ){
224
- /* Convert to extended UNC path. */
225
- memcpy(zUnicode, L"\\\\?\\UNC\\", 16);
226
- wUnicode += 8;
227
- MultiByteToWideChar(CP_UTF8, 0, zUtf8+2, -1, wUnicode, nChar-2);
228
- }else{
229
- MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
230
- }
231
- }
218
+ if( wUnicode==zUnicode && nChar>MAX_PATH){
219
+ /*
220
+ ** If there is no "\\?\" prefix but there is a drive
221
+ ** prefix and the path is larger than MAX_PATH chars,
222
+ ** no Win32 API function can handle that unless it is
223
+ ** prefixed with the extended path prefix. See:
224
+ ** <http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath>
225
+ **/
226
+ memmove(wUnicode+4, wUnicode, nChar*sizeof(wchar_t));
227
+ memcpy(wUnicode, L"\\\\?\\", 4*sizeof(wchar_t));
228
+ wUnicode += 4;
229
+ }
230
+ wUnicode[2] = '\\';
231
+ wUnicode += 3;
232
+ }
233
+ /*
234
+ ** In the remainder of the path, translate invalid characters to
235
+ ** characters in the Unicode private use area. This is what makes
236
+ ** Win32 fossil.exe work well in a Cygwin environment even when a
237
+ ** filename contains characters which are invalid for Win32.
238
+ */
232239
while( *wUnicode != '\0' ){
233240
if ( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){
234241
*wUnicode |= 0xF000;
235242
}else if( *wUnicode == '/' ){
236243
*wUnicode = '\\';
237244
--- 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 **
@@ -189,48 +190,54 @@
189 **
190 */
191 void *fossil_utf8_to_filename(const char *zUtf8){
192 #ifdef _WIN32
193 int nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0);
194 /* Overallocate 6 chars, making some room for extended paths */
195 wchar_t *zUnicode = sqlite3_malloc( (nChar+6) * sizeof(wchar_t) );
196 wchar_t *wUnicode = zUnicode;
197 if( zUnicode==0 ){
198 return 0;
199 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200 if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
201 && (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
202 /* If path starts with "<drive>:[/\]", don't process the ':' */
203 if( nChar>MAX_PATH ) {
204 memcpy(zUnicode, L"\\\\?\\", 8);
205 wUnicode += 4;
206 MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, wUnicode, nChar);
207 wUnicode[2] = '\\';
208 wUnicode += 3;
209 }else{
210 zUnicode[0] = zUtf8[0];
211 memcpy(&zUnicode[1], L":\\", 2 * sizeof(wchar_t));
212 wUnicode += 3;
213 MultiByteToWideChar(CP_UTF8, 0, zUtf8+3, -1, wUnicode, nChar-3);
214 }
215 }else if( (zUtf8[0]=='\\' || zUtf8[0]=='/') &&
216 (zUtf8[1]=='\\' || zUtf8[1]=='/') ) {
217 if( zUtf8[2]=='?' && nChar>7 ){
218 /* Don't postprocess [?:] in extended path, but do '/' -> '\' */
219 memcpy(zUnicode, L"\\\\", 2 * sizeof(wchar_t));
220 MultiByteToWideChar(CP_UTF8, 0, zUtf8+2, -1, zUnicode+2, nChar-2);
221 if( zUtf8[3]=='/' ) zUnicode[3]='\\';
222 wUnicode += 6;
223 }else if( nChar>MAX_PATH ){
224 /* Convert to extended UNC path. */
225 memcpy(zUnicode, L"\\\\?\\UNC\\", 16);
226 wUnicode += 8;
227 MultiByteToWideChar(CP_UTF8, 0, zUtf8+2, -1, wUnicode, nChar-2);
228 }else{
229 MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
230 }
231 }
232 while( *wUnicode != '\0' ){
233 if ( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){
234 *wUnicode |= 0xF000;
235 }else if( *wUnicode == '/' ){
236 *wUnicode = '\\';
237
--- 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 **
@@ -189,48 +190,54 @@
190 **
191 */
192 void *fossil_utf8_to_filename(const char *zUtf8){
193 #ifdef _WIN32
194 int nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0);
195 /* Overallocate 4 chars, making some room for extended paths */
196 wchar_t *zUnicode = sqlite3_malloc( (nChar+4) * sizeof(wchar_t) );
197 wchar_t *wUnicode = zUnicode;
198 if( zUnicode==0 ){
199 return 0;
200 }
201 MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar);
202 /*
203 ** If path starts with "//?/" or "\\?\" (extended path), translate
204 ** any slashes to backslashes but leave the '?' intact
205 */
206 if( (zUtf8[0]=='\\' || zUtf8[0]=='/') && (zUtf8[1]=='\\' || zUtf8[1]=='/')
207 && zUtf8[2]=='?' && (zUtf8[3]=='\\' || zUtf8[3]=='/')) {
208 wUnicode[0] = wUnicode[1] = wUnicode[3] = '\\';
209 zUtf8 += 4;
210 wUnicode += 4;
211 }
212 /*
213 ** If (remainder of) path starts with "<drive>:/" or "<drive>:\",
214 ** leave the ':' intact
215 */
216 if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':'
217 && (zUtf8[2]=='\\' || zUtf8[2]=='/')) {
218 if( wUnicode==zUnicode && nChar>MAX_PATH){
219 /*
220 ** If there is no "\\?\" prefix but there is a drive
221 ** prefix and the path is larger than MAX_PATH chars,
222 ** no Win32 API function can handle that unless it is
223 ** prefixed with the extended path prefix. See:
224 ** <http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath>
225 **/
226 memmove(wUnicode+4, wUnicode, nChar*sizeof(wchar_t));
227 memcpy(wUnicode, L"\\\\?\\", 4*sizeof(wchar_t));
228 wUnicode += 4;
229 }
230 wUnicode[2] = '\\';
231 wUnicode += 3;
232 }
233 /*
234 ** In the remainder of the path, translate invalid characters to
235 ** characters in the Unicode private use area. This is what makes
236 ** Win32 fossil.exe work well in a Cygwin environment even when a
237 ** filename contains characters which are invalid for Win32.
238 */
 
 
 
 
 
 
 
 
 
239 while( *wUnicode != '\0' ){
240 if ( (*wUnicode < ' ') || wcschr(L"\"*:<>?|", *wUnicode) ){
241 *wUnicode |= 0xF000;
242 }else if( *wUnicode == '/' ){
243 *wUnicode = '\\';
244
+12 -12
--- src/vfile.c
+++ src/vfile.c
@@ -45,18 +45,18 @@
4545
** does not exist, then return 0.
4646
**
4747
** For this routine, the UUID must be exact. For a match against
4848
** user input with mixed case, use resolve_uuid().
4949
**
50
-** If the UUID is not found and phantomize is 1 or 2, then attempt to
50
+** If the UUID is not found and phantomize is 1 or 2, then attempt to
5151
** create a phantom record. A private phantom is created for 2 and
5252
** a public phantom is created for 1.
5353
*/
5454
int uuid_to_rid(const char *zUuid, int phantomize){
5555
int rid, sz;
5656
char z[UUID_SIZE+1];
57
-
57
+
5858
sz = strlen(zUuid);
5959
if( sz!=UUID_SIZE || !validate16(zUuid, sz) ){
6060
return 0;
6161
}
6262
memcpy(z, zUuid, UUID_SIZE+1);
@@ -140,11 +140,11 @@
140140
** the file has changed due to a merge. 3 means the file was added
141141
** by a merge.
142142
**
143143
** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was either
144144
** removed from configuration management via "fossil rm" or added via
145
-** "fossil add", respectively, and in both cases we always know that
145
+** "fossil add", respectively, and in both cases we always know that
146146
** the file has changed without having the check the size, mtime,
147147
** or on-disk content.
148148
**
149149
** If the size of the file has changed, then we always know that the file
150150
** changed without having to look at the mtime or on-disk content.
@@ -315,11 +315,11 @@
315315
}
316316
if( verbose ) fossil_print("%s\n", &zName[nRepos]);
317317
if( file_wd_isdir(zName) == 1 ){
318318
/*TODO(dchest): remove directories? */
319319
fossil_fatal("%s is directory, cannot overwrite\n", zName);
320
- }
320
+ }
321321
if( file_wd_size(zName)>=0 && (isLink || file_wd_islink(zName)) ){
322322
file_delete(zName);
323323
}
324324
if( isLink ){
325325
symlink_create(blob_str(&content), zName);
@@ -392,11 +392,11 @@
392392
"merge",
393393
"original",
394394
"output",
395395
};
396396
int i, j, n;
397
-
397
+
398398
if( strglob("ci-comment-????????????.txt", zName) ) return 1;
399399
for(; zName[0]!=0; zName++){
400400
if( zName[0]=='/' && strglob("/ci-comment-????????????.txt", zName) ){
401401
return 1;
402402
}
@@ -407,11 +407,11 @@
407407
if( zName[n+1]==0 ) return 1;
408408
if( zName[n+1]=='-' ){
409409
for(j=n+2; zName[j] && fossil_isdigit(zName[j]); j++){}
410410
if( zName[j]==0 ) return 1;
411411
}
412
- }
412
+ }
413413
}
414414
return 0;
415415
}
416416
417417
#if INTERFACE
@@ -654,11 +654,11 @@
654654
FILE *in;
655655
Stmt q;
656656
char zBuf[4096];
657657
658658
db_must_be_within_tree();
659
- db_prepare(&q,
659
+ db_prepare(&q,
660660
"SELECT %Q || pathname, pathname, origname, is_selected(id), rid"
661661
" FROM vfile"
662662
" WHERE (NOT deleted OR NOT is_selected(id)) AND vid=%d"
663663
" ORDER BY if_selected(id, pathname, origname) /*scan*/",
664664
g.zLocalRoot, vid
@@ -673,11 +673,11 @@
673673
md5sum_step_text(zName, -1);
674674
if( file_wd_islink(zFullpath) ){
675675
/* Instead of file content, use link destination path */
676676
Blob pathBuf;
677677
678
- sqlite3_snprintf(sizeof(zBuf), zBuf, " %ld\n",
678
+ sqlite3_snprintf(sizeof(zBuf), zBuf, " %ld\n",
679679
blob_read_link(&pathBuf, zFullpath));
680680
md5sum_step_text(zBuf, -1);
681681
md5sum_step_text(blob_str(&pathBuf), -1);
682682
blob_reset(&pathBuf);
683683
}else{
@@ -743,13 +743,13 @@
743743
void vfile_compare_repository_to_disk(int vid){
744744
int rc;
745745
Stmt q;
746746
Blob disk, repo;
747747
char *zOut;
748
-
748
+
749749
db_must_be_within_tree();
750
- db_prepare(&q,
750
+ db_prepare(&q,
751751
"SELECT %Q || pathname, pathname, rid FROM vfile"
752752
" WHERE NOT deleted AND vid=%d AND is_selected(id)"
753753
" ORDER BY if_selected(id, pathname, origname) /*scan*/",
754754
g.zLocalRoot, vid
755755
);
@@ -809,11 +809,11 @@
809809
Blob file;
810810
Stmt q;
811811
char zBuf[100];
812812
813813
db_must_be_within_tree();
814
-
814
+
815815
db_prepare(&q, "SELECT pathname, origname, rid, is_selected(id)"
816816
" FROM vfile"
817817
" WHERE (NOT deleted OR NOT is_selected(id))"
818818
" AND rid>0 AND vid=%d"
819819
" ORDER BY if_selected(id,pathname,origname) /*scan*/",
@@ -847,11 +847,11 @@
847847
**
848848
** If pManOut is not NULL then fill it with the checksum found in the
849849
** "R" card near the end of the manifest.
850850
**
851851
** In a well-formed manifest, the two checksums computed here, pOut and
852
-** pManOut, should be identical.
852
+** pManOut, should be identical.
853853
*/
854854
void vfile_aggregate_checksum_manifest(int vid, Blob *pOut, Blob *pManOut){
855855
int fid;
856856
Blob file;
857857
Blob err;
858858
--- src/vfile.c
+++ src/vfile.c
@@ -45,18 +45,18 @@
45 ** does not exist, then return 0.
46 **
47 ** For this routine, the UUID must be exact. For a match against
48 ** user input with mixed case, use resolve_uuid().
49 **
50 ** If the UUID is not found and phantomize is 1 or 2, then attempt to
51 ** create a phantom record. A private phantom is created for 2 and
52 ** a public phantom is created for 1.
53 */
54 int uuid_to_rid(const char *zUuid, int phantomize){
55 int rid, sz;
56 char z[UUID_SIZE+1];
57
58 sz = strlen(zUuid);
59 if( sz!=UUID_SIZE || !validate16(zUuid, sz) ){
60 return 0;
61 }
62 memcpy(z, zUuid, UUID_SIZE+1);
@@ -140,11 +140,11 @@
140 ** the file has changed due to a merge. 3 means the file was added
141 ** by a merge.
142 **
143 ** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was either
144 ** removed from configuration management via "fossil rm" or added via
145 ** "fossil add", respectively, and in both cases we always know that
146 ** the file has changed without having the check the size, mtime,
147 ** or on-disk content.
148 **
149 ** If the size of the file has changed, then we always know that the file
150 ** changed without having to look at the mtime or on-disk content.
@@ -315,11 +315,11 @@
315 }
316 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
317 if( file_wd_isdir(zName) == 1 ){
318 /*TODO(dchest): remove directories? */
319 fossil_fatal("%s is directory, cannot overwrite\n", zName);
320 }
321 if( file_wd_size(zName)>=0 && (isLink || file_wd_islink(zName)) ){
322 file_delete(zName);
323 }
324 if( isLink ){
325 symlink_create(blob_str(&content), zName);
@@ -392,11 +392,11 @@
392 "merge",
393 "original",
394 "output",
395 };
396 int i, j, n;
397
398 if( strglob("ci-comment-????????????.txt", zName) ) return 1;
399 for(; zName[0]!=0; zName++){
400 if( zName[0]=='/' && strglob("/ci-comment-????????????.txt", zName) ){
401 return 1;
402 }
@@ -407,11 +407,11 @@
407 if( zName[n+1]==0 ) return 1;
408 if( zName[n+1]=='-' ){
409 for(j=n+2; zName[j] && fossil_isdigit(zName[j]); j++){}
410 if( zName[j]==0 ) return 1;
411 }
412 }
413 }
414 return 0;
415 }
416
417 #if INTERFACE
@@ -654,11 +654,11 @@
654 FILE *in;
655 Stmt q;
656 char zBuf[4096];
657
658 db_must_be_within_tree();
659 db_prepare(&q,
660 "SELECT %Q || pathname, pathname, origname, is_selected(id), rid"
661 " FROM vfile"
662 " WHERE (NOT deleted OR NOT is_selected(id)) AND vid=%d"
663 " ORDER BY if_selected(id, pathname, origname) /*scan*/",
664 g.zLocalRoot, vid
@@ -673,11 +673,11 @@
673 md5sum_step_text(zName, -1);
674 if( file_wd_islink(zFullpath) ){
675 /* Instead of file content, use link destination path */
676 Blob pathBuf;
677
678 sqlite3_snprintf(sizeof(zBuf), zBuf, " %ld\n",
679 blob_read_link(&pathBuf, zFullpath));
680 md5sum_step_text(zBuf, -1);
681 md5sum_step_text(blob_str(&pathBuf), -1);
682 blob_reset(&pathBuf);
683 }else{
@@ -743,13 +743,13 @@
743 void vfile_compare_repository_to_disk(int vid){
744 int rc;
745 Stmt q;
746 Blob disk, repo;
747 char *zOut;
748
749 db_must_be_within_tree();
750 db_prepare(&q,
751 "SELECT %Q || pathname, pathname, rid FROM vfile"
752 " WHERE NOT deleted AND vid=%d AND is_selected(id)"
753 " ORDER BY if_selected(id, pathname, origname) /*scan*/",
754 g.zLocalRoot, vid
755 );
@@ -809,11 +809,11 @@
809 Blob file;
810 Stmt q;
811 char zBuf[100];
812
813 db_must_be_within_tree();
814
815 db_prepare(&q, "SELECT pathname, origname, rid, is_selected(id)"
816 " FROM vfile"
817 " WHERE (NOT deleted OR NOT is_selected(id))"
818 " AND rid>0 AND vid=%d"
819 " ORDER BY if_selected(id,pathname,origname) /*scan*/",
@@ -847,11 +847,11 @@
847 **
848 ** If pManOut is not NULL then fill it with the checksum found in the
849 ** "R" card near the end of the manifest.
850 **
851 ** In a well-formed manifest, the two checksums computed here, pOut and
852 ** pManOut, should be identical.
853 */
854 void vfile_aggregate_checksum_manifest(int vid, Blob *pOut, Blob *pManOut){
855 int fid;
856 Blob file;
857 Blob err;
858
--- src/vfile.c
+++ src/vfile.c
@@ -45,18 +45,18 @@
45 ** does not exist, then return 0.
46 **
47 ** For this routine, the UUID must be exact. For a match against
48 ** user input with mixed case, use resolve_uuid().
49 **
50 ** If the UUID is not found and phantomize is 1 or 2, then attempt to
51 ** create a phantom record. A private phantom is created for 2 and
52 ** a public phantom is created for 1.
53 */
54 int uuid_to_rid(const char *zUuid, int phantomize){
55 int rid, sz;
56 char z[UUID_SIZE+1];
57
58 sz = strlen(zUuid);
59 if( sz!=UUID_SIZE || !validate16(zUuid, sz) ){
60 return 0;
61 }
62 memcpy(z, zUuid, UUID_SIZE+1);
@@ -140,11 +140,11 @@
140 ** the file has changed due to a merge. 3 means the file was added
141 ** by a merge.
142 **
143 ** If VFILE.DELETED is true or if VFILE.RID is zero, then the file was either
144 ** removed from configuration management via "fossil rm" or added via
145 ** "fossil add", respectively, and in both cases we always know that
146 ** the file has changed without having the check the size, mtime,
147 ** or on-disk content.
148 **
149 ** If the size of the file has changed, then we always know that the file
150 ** changed without having to look at the mtime or on-disk content.
@@ -315,11 +315,11 @@
315 }
316 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
317 if( file_wd_isdir(zName) == 1 ){
318 /*TODO(dchest): remove directories? */
319 fossil_fatal("%s is directory, cannot overwrite\n", zName);
320 }
321 if( file_wd_size(zName)>=0 && (isLink || file_wd_islink(zName)) ){
322 file_delete(zName);
323 }
324 if( isLink ){
325 symlink_create(blob_str(&content), zName);
@@ -392,11 +392,11 @@
392 "merge",
393 "original",
394 "output",
395 };
396 int i, j, n;
397
398 if( strglob("ci-comment-????????????.txt", zName) ) return 1;
399 for(; zName[0]!=0; zName++){
400 if( zName[0]=='/' && strglob("/ci-comment-????????????.txt", zName) ){
401 return 1;
402 }
@@ -407,11 +407,11 @@
407 if( zName[n+1]==0 ) return 1;
408 if( zName[n+1]=='-' ){
409 for(j=n+2; zName[j] && fossil_isdigit(zName[j]); j++){}
410 if( zName[j]==0 ) return 1;
411 }
412 }
413 }
414 return 0;
415 }
416
417 #if INTERFACE
@@ -654,11 +654,11 @@
654 FILE *in;
655 Stmt q;
656 char zBuf[4096];
657
658 db_must_be_within_tree();
659 db_prepare(&q,
660 "SELECT %Q || pathname, pathname, origname, is_selected(id), rid"
661 " FROM vfile"
662 " WHERE (NOT deleted OR NOT is_selected(id)) AND vid=%d"
663 " ORDER BY if_selected(id, pathname, origname) /*scan*/",
664 g.zLocalRoot, vid
@@ -673,11 +673,11 @@
673 md5sum_step_text(zName, -1);
674 if( file_wd_islink(zFullpath) ){
675 /* Instead of file content, use link destination path */
676 Blob pathBuf;
677
678 sqlite3_snprintf(sizeof(zBuf), zBuf, " %ld\n",
679 blob_read_link(&pathBuf, zFullpath));
680 md5sum_step_text(zBuf, -1);
681 md5sum_step_text(blob_str(&pathBuf), -1);
682 blob_reset(&pathBuf);
683 }else{
@@ -743,13 +743,13 @@
743 void vfile_compare_repository_to_disk(int vid){
744 int rc;
745 Stmt q;
746 Blob disk, repo;
747 char *zOut;
748
749 db_must_be_within_tree();
750 db_prepare(&q,
751 "SELECT %Q || pathname, pathname, rid FROM vfile"
752 " WHERE NOT deleted AND vid=%d AND is_selected(id)"
753 " ORDER BY if_selected(id, pathname, origname) /*scan*/",
754 g.zLocalRoot, vid
755 );
@@ -809,11 +809,11 @@
809 Blob file;
810 Stmt q;
811 char zBuf[100];
812
813 db_must_be_within_tree();
814
815 db_prepare(&q, "SELECT pathname, origname, rid, is_selected(id)"
816 " FROM vfile"
817 " WHERE (NOT deleted OR NOT is_selected(id))"
818 " AND rid>0 AND vid=%d"
819 " ORDER BY if_selected(id,pathname,origname) /*scan*/",
@@ -847,11 +847,11 @@
847 **
848 ** If pManOut is not NULL then fill it with the checksum found in the
849 ** "R" card near the end of the manifest.
850 **
851 ** In a well-formed manifest, the two checksums computed here, pOut and
852 ** pManOut, should be identical.
853 */
854 void vfile_aggregate_checksum_manifest(int vid, Blob *pOut, Blob *pManOut){
855 int fid;
856 Blob file;
857 Blob err;
858
+14 -14
--- src/wiki.c
+++ src/wiki.c
@@ -222,11 +222,11 @@
222222
zBody = db_get("sandbox",zBody);
223223
zMimetype = db_get("sandbox-mimetype","text/x-fossil-wiki");
224224
rid = 0;
225225
}else{
226226
zTag = mprintf("wiki-%s", zPageName);
227
- rid = db_int(0,
227
+ rid = db_int(0,
228228
"SELECT rid FROM tagxref"
229229
" WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
230230
" ORDER BY mtime DESC", zTag
231231
);
232232
free(zTag);
@@ -260,11 +260,11 @@
260260
style_submenu_element("Attach", "Add An Attachment",
261261
"%s/attachadd?page=%T&from=%s/wiki%%3fname=%T",
262262
g.zTop, zPageName, g.zTop, zPageName);
263263
}
264264
if( rid && g.perm.ApndWiki ){
265
- style_submenu_element("Append", "Add A Comment",
265
+ style_submenu_element("Append", "Add A Comment",
266266
"%s/wikiappend?name=%T&mimetype=%s",
267267
g.zTop, zPageName, zMimetype);
268268
}
269269
if( g.perm.Hyperlink ){
270270
style_submenu_element("History", "History", "%s/whistory?name=%T",
@@ -300,11 +300,11 @@
300300
}
301301
302302
/*
303303
** Formal names and common names for the various wiki styles.
304304
*/
305
-static const char *azStyles[] = {
305
+static const char *const azStyles[] = {
306306
"text/x-fossil-wiki", "Fossil Wiki",
307307
"text/x-markdown", "Markdown",
308308
"text/plain", "Plain Text"
309309
};
310310
@@ -381,11 +381,11 @@
381381
zBody = db_get("sandbox","");
382382
zMimetype = db_get("sandbox-mimetype","text/x-fossil-wiki");
383383
}
384384
}else{
385385
zTag = mprintf("wiki-%s", zPageName);
386
- rid = db_int(0,
386
+ rid = db_int(0,
387387
"SELECT rid FROM tagxref"
388388
" WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
389389
" ORDER BY mtime DESC", zTag
390390
);
391391
free(zTag);
@@ -462,11 +462,11 @@
462462
if( !isWysiwyg ){
463463
/* Traditional markup-only editing */
464464
form_begin(0, "%R/wikiedit");
465465
@ <div>
466466
mimetype_option_menu(zMimetype);
467
- @ <br /><textarea name="w" class="wikiedit" cols="80"
467
+ @ <br /><textarea name="w" class="wikiedit" cols="80"
468468
@ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
469469
@ <br />
470470
if( db_get_boolean("wysiwyg-wiki", 0) ){
471471
@ <input type="submit" name="edit-wysiwyg" value="Wysiwyg Editor"
472472
@ onclick='return confirm("Switching to WYSIWYG-mode\nwill erase your markup\nedits. Continue?")' />
@@ -514,11 +514,11 @@
514514
const char *zMimetype;
515515
login_check_credentials();
516516
if( !g.perm.NewWiki ){
517517
login_needed();
518518
return;
519
- }
519
+ }
520520
zName = PD("name","");
521521
zMimetype = wiki_filter_mimetypes(P("mimetype"));
522522
if( zName[0] && wiki_name_is_wellformed((const unsigned char *)zName) ){
523523
if( fossil_strcmp(zMimetype,"text/x-fossil-wiki")==0
524524
&& db_get_boolean("wysiwyg-wiki", 0)
@@ -557,11 +557,11 @@
557557
zDate = db_text(0, "SELECT datetime('now')");
558558
zRemark = PD("r","");
559559
zUser = PD("u",g.zLogin);
560560
if( fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){
561561
zId = db_text(0, "SELECT lower(hex(randomblob(8)))");
562
- blob_appendf(p, "\n\n<hr><div id=\"%s\"><i>On %s UTC %h",
562
+ blob_appendf(p, "\n\n<hr><div id=\"%s\"><i>On %s UTC %h",
563563
zId, zDate, g.zLogin);
564564
if( zUser[0] && fossil_strcmp(zUser,g.zLogin) ){
565565
blob_appendf(p, " (claiming to be %h)", zUser);
566566
}
567567
blob_appendf(p, " added:</i><br />\n%s</div id=\"%s\">", zRemark, zId);
@@ -601,11 +601,11 @@
601601
zMimetype = wiki_filter_mimetypes(P("mimetype"));
602602
if( check_name(zPageName) ) return;
603603
isSandbox = is_sandbox(zPageName);
604604
if( !isSandbox ){
605605
zTag = mprintf("wiki-%s", zPageName);
606
- rid = db_int(0,
606
+ rid = db_int(0,
607607
"SELECT rid FROM tagxref"
608608
" WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
609609
" ORDER BY mtime DESC", zTag
610610
);
611611
free(zTag);
@@ -690,11 +690,11 @@
690690
@ <input type="hidden" name="mimetype" value="%h(zMimetype)" />
691691
@ Your Name:
692692
@ <input type="text" name="u" size="20" value="%h(zUser)" /><br />
693693
zFormat = mimetype_common_name(zMimetype);
694694
@ Comment to append (formatted as %s(zFormat)):<br />
695
- @ <textarea name="r" class="wikiedit" cols="80"
695
+ @ <textarea name="r" class="wikiedit" cols="80"
696696
@ rows="10" wrap="virtual">%h(PD("r",""))</textarea>
697697
@ <br />
698698
@ <input type="submit" name="preview" value="Preview Your Comment" />
699699
@ <input type="submit" name="submit" value="Append Your Changes" />
700700
@ <input type="submit" name="cancel" value="Cancel" />
@@ -809,11 +809,11 @@
809809
** - tagxref (whatever that really is!)
810810
**
811811
** Used by wcontent_page() and the JSON wiki code.
812812
*/
813813
void wiki_prepare_page_list( Stmt * pStmt ){
814
- db_prepare(pStmt,
814
+ db_prepare(pStmt,
815815
"SELECT"
816816
" substr(tagname, 6) as name,"
817817
" (SELECT value FROM tagxref WHERE tagid=tag.tagid ORDER BY mtime DESC) as tagXref"
818818
" FROM tag WHERE tagname GLOB 'wiki-*'"
819819
" ORDER BY lower(tagname) /*sort*/"
@@ -866,11 +866,11 @@
866866
login_check_credentials();
867867
if( !g.perm.RdWiki ){ login_needed(); return; }
868868
zTitle = PD("title","*");
869869
style_header("Wiki Pages Found");
870870
@ <ul>
871
- db_prepare(&q,
871
+ db_prepare(&q,
872872
"SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'"
873873
" ORDER BY lower(tagname) /*sort*/" ,
874874
zTitle);
875875
while( db_step(&q)==SQLITE_ROW ){
876876
const char *zName = db_column_text(&q, 0);
@@ -917,11 +917,11 @@
917917
@ surrounded on both sides by two or more spaces or by a tab. Only a single
918918
@ level of enumeration list is supported by wiki. For nested lists or for
919919
@ enumerations that count using letters or roman numerials, use HTML.</p></li>
920920
@ <li> <p><span class="wikiruleHead">Indented Paragraphs</span>.
921921
@ Any paragraph that begins with two or more spaces or a tab and
922
- @ which is not a bullet or enumeration list item is rendered
922
+ @ which is not a bullet or enumeration list item is rendered
923923
@ indented. Only a single level of indentation is supported by wiki; use
924924
@ HTML for deeper indentation.</p></li>
925925
@ <li> <p><span class="wikiruleHead">Hyperlinks</span>.
926926
@ Text within square brackets ("[...]") becomes a hyperlink. The
927927
@ target can be a wiki page name, the artifact ID of a check-in or ticket,
@@ -1062,11 +1062,11 @@
10621062
}
10631063
zPageName = g.argv[3];
10641064
rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x"
10651065
" WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
10661066
" ORDER BY x.mtime DESC LIMIT 1",
1067
- zPageName
1067
+ zPageName
10681068
);
10691069
if( (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){
10701070
zBody = pWiki->zWiki;
10711071
}
10721072
if( zBody==0 ){
@@ -1110,11 +1110,11 @@
11101110
}
11111111
fossil_fatal("delete not yet implemented.");
11121112
}else
11131113
if( strncmp(g.argv[2],"list",n)==0 ){
11141114
Stmt q;
1115
- db_prepare(&q,
1115
+ db_prepare(&q,
11161116
"SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'"
11171117
" ORDER BY lower(tagname) /*sort*/"
11181118
);
11191119
while( db_step(&q)==SQLITE_ROW ){
11201120
const char *zName = db_column_text(&q, 0);
11211121
--- src/wiki.c
+++ src/wiki.c
@@ -222,11 +222,11 @@
222 zBody = db_get("sandbox",zBody);
223 zMimetype = db_get("sandbox-mimetype","text/x-fossil-wiki");
224 rid = 0;
225 }else{
226 zTag = mprintf("wiki-%s", zPageName);
227 rid = db_int(0,
228 "SELECT rid FROM tagxref"
229 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
230 " ORDER BY mtime DESC", zTag
231 );
232 free(zTag);
@@ -260,11 +260,11 @@
260 style_submenu_element("Attach", "Add An Attachment",
261 "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T",
262 g.zTop, zPageName, g.zTop, zPageName);
263 }
264 if( rid && g.perm.ApndWiki ){
265 style_submenu_element("Append", "Add A Comment",
266 "%s/wikiappend?name=%T&mimetype=%s",
267 g.zTop, zPageName, zMimetype);
268 }
269 if( g.perm.Hyperlink ){
270 style_submenu_element("History", "History", "%s/whistory?name=%T",
@@ -300,11 +300,11 @@
300 }
301
302 /*
303 ** Formal names and common names for the various wiki styles.
304 */
305 static const char *azStyles[] = {
306 "text/x-fossil-wiki", "Fossil Wiki",
307 "text/x-markdown", "Markdown",
308 "text/plain", "Plain Text"
309 };
310
@@ -381,11 +381,11 @@
381 zBody = db_get("sandbox","");
382 zMimetype = db_get("sandbox-mimetype","text/x-fossil-wiki");
383 }
384 }else{
385 zTag = mprintf("wiki-%s", zPageName);
386 rid = db_int(0,
387 "SELECT rid FROM tagxref"
388 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
389 " ORDER BY mtime DESC", zTag
390 );
391 free(zTag);
@@ -462,11 +462,11 @@
462 if( !isWysiwyg ){
463 /* Traditional markup-only editing */
464 form_begin(0, "%R/wikiedit");
465 @ <div>
466 mimetype_option_menu(zMimetype);
467 @ <br /><textarea name="w" class="wikiedit" cols="80"
468 @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
469 @ <br />
470 if( db_get_boolean("wysiwyg-wiki", 0) ){
471 @ <input type="submit" name="edit-wysiwyg" value="Wysiwyg Editor"
472 @ onclick='return confirm("Switching to WYSIWYG-mode\nwill erase your markup\nedits. Continue?")' />
@@ -514,11 +514,11 @@
514 const char *zMimetype;
515 login_check_credentials();
516 if( !g.perm.NewWiki ){
517 login_needed();
518 return;
519 }
520 zName = PD("name","");
521 zMimetype = wiki_filter_mimetypes(P("mimetype"));
522 if( zName[0] && wiki_name_is_wellformed((const unsigned char *)zName) ){
523 if( fossil_strcmp(zMimetype,"text/x-fossil-wiki")==0
524 && db_get_boolean("wysiwyg-wiki", 0)
@@ -557,11 +557,11 @@
557 zDate = db_text(0, "SELECT datetime('now')");
558 zRemark = PD("r","");
559 zUser = PD("u",g.zLogin);
560 if( fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){
561 zId = db_text(0, "SELECT lower(hex(randomblob(8)))");
562 blob_appendf(p, "\n\n<hr><div id=\"%s\"><i>On %s UTC %h",
563 zId, zDate, g.zLogin);
564 if( zUser[0] && fossil_strcmp(zUser,g.zLogin) ){
565 blob_appendf(p, " (claiming to be %h)", zUser);
566 }
567 blob_appendf(p, " added:</i><br />\n%s</div id=\"%s\">", zRemark, zId);
@@ -601,11 +601,11 @@
601 zMimetype = wiki_filter_mimetypes(P("mimetype"));
602 if( check_name(zPageName) ) return;
603 isSandbox = is_sandbox(zPageName);
604 if( !isSandbox ){
605 zTag = mprintf("wiki-%s", zPageName);
606 rid = db_int(0,
607 "SELECT rid FROM tagxref"
608 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
609 " ORDER BY mtime DESC", zTag
610 );
611 free(zTag);
@@ -690,11 +690,11 @@
690 @ <input type="hidden" name="mimetype" value="%h(zMimetype)" />
691 @ Your Name:
692 @ <input type="text" name="u" size="20" value="%h(zUser)" /><br />
693 zFormat = mimetype_common_name(zMimetype);
694 @ Comment to append (formatted as %s(zFormat)):<br />
695 @ <textarea name="r" class="wikiedit" cols="80"
696 @ rows="10" wrap="virtual">%h(PD("r",""))</textarea>
697 @ <br />
698 @ <input type="submit" name="preview" value="Preview Your Comment" />
699 @ <input type="submit" name="submit" value="Append Your Changes" />
700 @ <input type="submit" name="cancel" value="Cancel" />
@@ -809,11 +809,11 @@
809 ** - tagxref (whatever that really is!)
810 **
811 ** Used by wcontent_page() and the JSON wiki code.
812 */
813 void wiki_prepare_page_list( Stmt * pStmt ){
814 db_prepare(pStmt,
815 "SELECT"
816 " substr(tagname, 6) as name,"
817 " (SELECT value FROM tagxref WHERE tagid=tag.tagid ORDER BY mtime DESC) as tagXref"
818 " FROM tag WHERE tagname GLOB 'wiki-*'"
819 " ORDER BY lower(tagname) /*sort*/"
@@ -866,11 +866,11 @@
866 login_check_credentials();
867 if( !g.perm.RdWiki ){ login_needed(); return; }
868 zTitle = PD("title","*");
869 style_header("Wiki Pages Found");
870 @ <ul>
871 db_prepare(&q,
872 "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'"
873 " ORDER BY lower(tagname) /*sort*/" ,
874 zTitle);
875 while( db_step(&q)==SQLITE_ROW ){
876 const char *zName = db_column_text(&q, 0);
@@ -917,11 +917,11 @@
917 @ surrounded on both sides by two or more spaces or by a tab. Only a single
918 @ level of enumeration list is supported by wiki. For nested lists or for
919 @ enumerations that count using letters or roman numerials, use HTML.</p></li>
920 @ <li> <p><span class="wikiruleHead">Indented Paragraphs</span>.
921 @ Any paragraph that begins with two or more spaces or a tab and
922 @ which is not a bullet or enumeration list item is rendered
923 @ indented. Only a single level of indentation is supported by wiki; use
924 @ HTML for deeper indentation.</p></li>
925 @ <li> <p><span class="wikiruleHead">Hyperlinks</span>.
926 @ Text within square brackets ("[...]") becomes a hyperlink. The
927 @ target can be a wiki page name, the artifact ID of a check-in or ticket,
@@ -1062,11 +1062,11 @@
1062 }
1063 zPageName = g.argv[3];
1064 rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x"
1065 " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
1066 " ORDER BY x.mtime DESC LIMIT 1",
1067 zPageName
1068 );
1069 if( (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){
1070 zBody = pWiki->zWiki;
1071 }
1072 if( zBody==0 ){
@@ -1110,11 +1110,11 @@
1110 }
1111 fossil_fatal("delete not yet implemented.");
1112 }else
1113 if( strncmp(g.argv[2],"list",n)==0 ){
1114 Stmt q;
1115 db_prepare(&q,
1116 "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'"
1117 " ORDER BY lower(tagname) /*sort*/"
1118 );
1119 while( db_step(&q)==SQLITE_ROW ){
1120 const char *zName = db_column_text(&q, 0);
1121
--- src/wiki.c
+++ src/wiki.c
@@ -222,11 +222,11 @@
222 zBody = db_get("sandbox",zBody);
223 zMimetype = db_get("sandbox-mimetype","text/x-fossil-wiki");
224 rid = 0;
225 }else{
226 zTag = mprintf("wiki-%s", zPageName);
227 rid = db_int(0,
228 "SELECT rid FROM tagxref"
229 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
230 " ORDER BY mtime DESC", zTag
231 );
232 free(zTag);
@@ -260,11 +260,11 @@
260 style_submenu_element("Attach", "Add An Attachment",
261 "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T",
262 g.zTop, zPageName, g.zTop, zPageName);
263 }
264 if( rid && g.perm.ApndWiki ){
265 style_submenu_element("Append", "Add A Comment",
266 "%s/wikiappend?name=%T&mimetype=%s",
267 g.zTop, zPageName, zMimetype);
268 }
269 if( g.perm.Hyperlink ){
270 style_submenu_element("History", "History", "%s/whistory?name=%T",
@@ -300,11 +300,11 @@
300 }
301
302 /*
303 ** Formal names and common names for the various wiki styles.
304 */
305 static const char *const azStyles[] = {
306 "text/x-fossil-wiki", "Fossil Wiki",
307 "text/x-markdown", "Markdown",
308 "text/plain", "Plain Text"
309 };
310
@@ -381,11 +381,11 @@
381 zBody = db_get("sandbox","");
382 zMimetype = db_get("sandbox-mimetype","text/x-fossil-wiki");
383 }
384 }else{
385 zTag = mprintf("wiki-%s", zPageName);
386 rid = db_int(0,
387 "SELECT rid FROM tagxref"
388 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
389 " ORDER BY mtime DESC", zTag
390 );
391 free(zTag);
@@ -462,11 +462,11 @@
462 if( !isWysiwyg ){
463 /* Traditional markup-only editing */
464 form_begin(0, "%R/wikiedit");
465 @ <div>
466 mimetype_option_menu(zMimetype);
467 @ <br /><textarea name="w" class="wikiedit" cols="80"
468 @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
469 @ <br />
470 if( db_get_boolean("wysiwyg-wiki", 0) ){
471 @ <input type="submit" name="edit-wysiwyg" value="Wysiwyg Editor"
472 @ onclick='return confirm("Switching to WYSIWYG-mode\nwill erase your markup\nedits. Continue?")' />
@@ -514,11 +514,11 @@
514 const char *zMimetype;
515 login_check_credentials();
516 if( !g.perm.NewWiki ){
517 login_needed();
518 return;
519 }
520 zName = PD("name","");
521 zMimetype = wiki_filter_mimetypes(P("mimetype"));
522 if( zName[0] && wiki_name_is_wellformed((const unsigned char *)zName) ){
523 if( fossil_strcmp(zMimetype,"text/x-fossil-wiki")==0
524 && db_get_boolean("wysiwyg-wiki", 0)
@@ -557,11 +557,11 @@
557 zDate = db_text(0, "SELECT datetime('now')");
558 zRemark = PD("r","");
559 zUser = PD("u",g.zLogin);
560 if( fossil_strcmp(zMimetype, "text/x-fossil-wiki")==0 ){
561 zId = db_text(0, "SELECT lower(hex(randomblob(8)))");
562 blob_appendf(p, "\n\n<hr><div id=\"%s\"><i>On %s UTC %h",
563 zId, zDate, g.zLogin);
564 if( zUser[0] && fossil_strcmp(zUser,g.zLogin) ){
565 blob_appendf(p, " (claiming to be %h)", zUser);
566 }
567 blob_appendf(p, " added:</i><br />\n%s</div id=\"%s\">", zRemark, zId);
@@ -601,11 +601,11 @@
601 zMimetype = wiki_filter_mimetypes(P("mimetype"));
602 if( check_name(zPageName) ) return;
603 isSandbox = is_sandbox(zPageName);
604 if( !isSandbox ){
605 zTag = mprintf("wiki-%s", zPageName);
606 rid = db_int(0,
607 "SELECT rid FROM tagxref"
608 " WHERE tagid=(SELECT tagid FROM tag WHERE tagname=%Q)"
609 " ORDER BY mtime DESC", zTag
610 );
611 free(zTag);
@@ -690,11 +690,11 @@
690 @ <input type="hidden" name="mimetype" value="%h(zMimetype)" />
691 @ Your Name:
692 @ <input type="text" name="u" size="20" value="%h(zUser)" /><br />
693 zFormat = mimetype_common_name(zMimetype);
694 @ Comment to append (formatted as %s(zFormat)):<br />
695 @ <textarea name="r" class="wikiedit" cols="80"
696 @ rows="10" wrap="virtual">%h(PD("r",""))</textarea>
697 @ <br />
698 @ <input type="submit" name="preview" value="Preview Your Comment" />
699 @ <input type="submit" name="submit" value="Append Your Changes" />
700 @ <input type="submit" name="cancel" value="Cancel" />
@@ -809,11 +809,11 @@
809 ** - tagxref (whatever that really is!)
810 **
811 ** Used by wcontent_page() and the JSON wiki code.
812 */
813 void wiki_prepare_page_list( Stmt * pStmt ){
814 db_prepare(pStmt,
815 "SELECT"
816 " substr(tagname, 6) as name,"
817 " (SELECT value FROM tagxref WHERE tagid=tag.tagid ORDER BY mtime DESC) as tagXref"
818 " FROM tag WHERE tagname GLOB 'wiki-*'"
819 " ORDER BY lower(tagname) /*sort*/"
@@ -866,11 +866,11 @@
866 login_check_credentials();
867 if( !g.perm.RdWiki ){ login_needed(); return; }
868 zTitle = PD("title","*");
869 style_header("Wiki Pages Found");
870 @ <ul>
871 db_prepare(&q,
872 "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'"
873 " ORDER BY lower(tagname) /*sort*/" ,
874 zTitle);
875 while( db_step(&q)==SQLITE_ROW ){
876 const char *zName = db_column_text(&q, 0);
@@ -917,11 +917,11 @@
917 @ surrounded on both sides by two or more spaces or by a tab. Only a single
918 @ level of enumeration list is supported by wiki. For nested lists or for
919 @ enumerations that count using letters or roman numerials, use HTML.</p></li>
920 @ <li> <p><span class="wikiruleHead">Indented Paragraphs</span>.
921 @ Any paragraph that begins with two or more spaces or a tab and
922 @ which is not a bullet or enumeration list item is rendered
923 @ indented. Only a single level of indentation is supported by wiki; use
924 @ HTML for deeper indentation.</p></li>
925 @ <li> <p><span class="wikiruleHead">Hyperlinks</span>.
926 @ Text within square brackets ("[...]") becomes a hyperlink. The
927 @ target can be a wiki page name, the artifact ID of a check-in or ticket,
@@ -1062,11 +1062,11 @@
1062 }
1063 zPageName = g.argv[3];
1064 rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x"
1065 " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'"
1066 " ORDER BY x.mtime DESC LIMIT 1",
1067 zPageName
1068 );
1069 if( (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 ){
1070 zBody = pWiki->zWiki;
1071 }
1072 if( zBody==0 ){
@@ -1110,11 +1110,11 @@
1110 }
1111 fossil_fatal("delete not yet implemented.");
1112 }else
1113 if( strncmp(g.argv[2],"list",n)==0 ){
1114 Stmt q;
1115 db_prepare(&q,
1116 "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'"
1117 " ORDER BY lower(tagname) /*sort*/"
1118 );
1119 while( db_step(&q)==SQLITE_ROW ){
1120 const char *zName = db_column_text(&q, 0);
1121
+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
+7 -7
--- src/wysiwyg.c
+++ src/wysiwyg.c
@@ -228,18 +228,18 @@
228228
@ <div id="wysiwygBox"
229229
@ style="resize:both; overflow:auto; width: %d(w)em; height: %d(h)em;"
230230
@ contenteditable="true">%s(zContent)</div>
231231
@ <script>
232232
@ var oDoc;
233
- @
233
+ @
234234
@ /* Initialize the document editor */
235235
@ function initDoc() {
236236
@ oDoc = document.getElementById("wysiwygBox");
237237
@ if (!isWysiwyg()) { setDocMode(true); }
238238
@ }
239
- @
240
- @ /* Return true if the document editor is in WYSIWYG mode. Return
239
+ @
240
+ @ /* Return true if the document editor is in WYSIWYG mode. Return
241241
@ ** false if it is in Markup mode */
242242
@ function isWysiwyg() {
243243
@ return document.getElementById("editMode").selectedIndex==0;
244244
@ }
245245
@
@@ -247,22 +247,22 @@
247247
@ ** to the server */
248248
@ function wysiwygSubmit() {
249249
@ if(oDoc.style.whiteSpace=="pre-wrap"){setDocMode(0);}
250250
@ document.getElementById("wysiwygValue").value=oDoc.innerHTML;
251251
@ }
252
- @
253
- @ /* Run the editing command if in WYSIWYG mode */
252
+ @
253
+ @ /* Run the editing command if in WYSIWYG mode */
254254
@ function formatDoc(sCmd, sValue) {
255255
@ if (isWysiwyg()){
256256
@ document.execCommand("styleWithCSS", false, false);
257257
@ document.execCommand(sCmd, false, sValue);
258258
@ oDoc.focus();
259259
@ }
260260
@ }
261
- @
261
+ @
262262
@ /* Change the editing mode. Convert to markup if the argument
263
- @ ** is true and wysiwyg if the argument is false. */
263
+ @ ** is true and wysiwyg if the argument is false. */
264264
@ function setDocMode(bToMarkup) {
265265
@ var oContent;
266266
@ if (bToMarkup) {
267267
@ /* WYSIWYG -> Markup */
268268
@ var linebreak = new RegExp("</p><p>","ig");
269269
--- src/wysiwyg.c
+++ src/wysiwyg.c
@@ -228,18 +228,18 @@
228 @ <div id="wysiwygBox"
229 @ style="resize:both; overflow:auto; width: %d(w)em; height: %d(h)em;"
230 @ contenteditable="true">%s(zContent)</div>
231 @ <script>
232 @ var oDoc;
233 @
234 @ /* Initialize the document editor */
235 @ function initDoc() {
236 @ oDoc = document.getElementById("wysiwygBox");
237 @ if (!isWysiwyg()) { setDocMode(true); }
238 @ }
239 @
240 @ /* Return true if the document editor is in WYSIWYG mode. Return
241 @ ** false if it is in Markup mode */
242 @ function isWysiwyg() {
243 @ return document.getElementById("editMode").selectedIndex==0;
244 @ }
245 @
@@ -247,22 +247,22 @@
247 @ ** to the server */
248 @ function wysiwygSubmit() {
249 @ if(oDoc.style.whiteSpace=="pre-wrap"){setDocMode(0);}
250 @ document.getElementById("wysiwygValue").value=oDoc.innerHTML;
251 @ }
252 @
253 @ /* Run the editing command if in WYSIWYG mode */
254 @ function formatDoc(sCmd, sValue) {
255 @ if (isWysiwyg()){
256 @ document.execCommand("styleWithCSS", false, false);
257 @ document.execCommand(sCmd, false, sValue);
258 @ oDoc.focus();
259 @ }
260 @ }
261 @
262 @ /* Change the editing mode. Convert to markup if the argument
263 @ ** is true and wysiwyg if the argument is false. */
264 @ function setDocMode(bToMarkup) {
265 @ var oContent;
266 @ if (bToMarkup) {
267 @ /* WYSIWYG -> Markup */
268 @ var linebreak = new RegExp("</p><p>","ig");
269
--- src/wysiwyg.c
+++ src/wysiwyg.c
@@ -228,18 +228,18 @@
228 @ <div id="wysiwygBox"
229 @ style="resize:both; overflow:auto; width: %d(w)em; height: %d(h)em;"
230 @ contenteditable="true">%s(zContent)</div>
231 @ <script>
232 @ var oDoc;
233 @
234 @ /* Initialize the document editor */
235 @ function initDoc() {
236 @ oDoc = document.getElementById("wysiwygBox");
237 @ if (!isWysiwyg()) { setDocMode(true); }
238 @ }
239 @
240 @ /* Return true if the document editor is in WYSIWYG mode. Return
241 @ ** false if it is in Markup mode */
242 @ function isWysiwyg() {
243 @ return document.getElementById("editMode").selectedIndex==0;
244 @ }
245 @
@@ -247,22 +247,22 @@
247 @ ** to the server */
248 @ function wysiwygSubmit() {
249 @ if(oDoc.style.whiteSpace=="pre-wrap"){setDocMode(0);}
250 @ document.getElementById("wysiwygValue").value=oDoc.innerHTML;
251 @ }
252 @
253 @ /* Run the editing command if in WYSIWYG mode */
254 @ function formatDoc(sCmd, sValue) {
255 @ if (isWysiwyg()){
256 @ document.execCommand("styleWithCSS", false, false);
257 @ document.execCommand(sCmd, false, sValue);
258 @ oDoc.focus();
259 @ }
260 @ }
261 @
262 @ /* Change the editing mode. Convert to markup if the argument
263 @ ** is true and wysiwyg if the argument is false. */
264 @ function setDocMode(bToMarkup) {
265 @ var oContent;
266 @ if (bToMarkup) {
267 @ /* WYSIWYG -> Markup */
268 @ var linebreak = new RegExp("</p><p>","ig");
269
+39 -39
--- src/xfer.c
+++ src/xfer.c
@@ -94,11 +94,11 @@
9494
db_reset(&q);
9595
}
9696
}
9797
9898
/*
99
-** The aToken[0..nToken-1] blob array is a parse of a "file" line
99
+** The aToken[0..nToken-1] blob array is a parse of a "file" line
100100
** message. This routine finishes parsing that message and does
101101
** a record insert of the file.
102102
**
103103
** The file line is in one of the following two forms:
104104
**
@@ -119,14 +119,14 @@
119119
int n;
120120
int rid;
121121
int srcid = 0;
122122
Blob content, hash;
123123
int isPriv;
124
-
124
+
125125
isPriv = pXfer->nextIsPrivate;
126126
pXfer->nextIsPrivate = 0;
127
- if( pXfer->nToken<3
127
+ if( pXfer->nToken<3
128128
|| pXfer->nToken>4
129129
|| !blob_is_uuid(&pXfer->aToken[1])
130130
|| !blob_is_int(&pXfer->aToken[pXfer->nToken-1], &n)
131131
|| n<0
132132
|| (pXfer->nToken==4 && !blob_is_uuid(&pXfer->aToken[2]))
@@ -198,11 +198,11 @@
198198
assert( blob_is_reset(&content) );
199199
remote_has(rid);
200200
}
201201
202202
/*
203
-** The aToken[0..nToken-1] blob array is a parse of a "cfile" line
203
+** The aToken[0..nToken-1] blob array is a parse of a "cfile" line
204204
** message. This routine finishes parsing that message and does
205205
** a record insert of the file. The difference between "file" and
206206
** "cfile" is that with "cfile" the content is already compressed.
207207
**
208208
** The file line is in one of the following two forms:
@@ -227,14 +227,14 @@
227227
int szU; /* USIZE */
228228
int rid;
229229
int srcid = 0;
230230
Blob content;
231231
int isPriv;
232
-
232
+
233233
isPriv = pXfer->nextIsPrivate;
234234
pXfer->nextIsPrivate = 0;
235
- if( pXfer->nToken<4
235
+ if( pXfer->nToken<4
236236
|| pXfer->nToken>5
237237
|| !blob_is_uuid(&pXfer->aToken[1])
238238
|| !blob_is_int(&pXfer->aToken[pXfer->nToken-2], &szU)
239239
|| !blob_is_int(&pXfer->aToken[pXfer->nToken-1], &szC)
240240
|| szC<0 || szU<0
@@ -284,11 +284,11 @@
284284
){
285285
static const char *const azQuery[] = {
286286
"SELECT pid FROM plink x"
287287
" WHERE cid=%d"
288288
" AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)",
289
-
289
+
290290
"SELECT pid, min(mtime) FROM mlink, event ON mlink.mid=event.objid"
291291
" WHERE fid=%d"
292292
" AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)"
293293
};
294294
int i;
@@ -321,11 +321,11 @@
321321
}
322322
return size;
323323
}
324324
325325
/*
326
-** Try to send a file as a native delta.
326
+** Try to send a file as a native delta.
327327
** If successful, return the number of bytes in the delta.
328328
** If we cannot generate an appropriate delta, then send
329329
** nothing and return zero.
330330
**
331331
** Never send a delta against a private artifact.
@@ -403,11 +403,11 @@
403403
}
404404
if( uuid_is_shunned(blob_str(pUuid)) ){
405405
blob_reset(&uuid);
406406
return;
407407
}
408
- if( (pXfer->maxTime != -1 && time(NULL) >= pXfer->maxTime) ||
408
+ if( (pXfer->maxTime != -1 && time(NULL) >= pXfer->maxTime) ||
409409
pXfer->mxSend<=blob_size(pXfer->pOut) ){
410410
const char *zFormat = isPriv ? "igot %b 1\n" : "igot %b\n";
411411
blob_appendf(pXfer->pOut, zFormat, pUuid);
412412
pXfer->nIGotSent++;
413413
blob_reset(&uuid);
@@ -445,11 +445,11 @@
445445
#endif
446446
}
447447
448448
/*
449449
** Send the file identified by rid as a compressed artifact. Basically,
450
-** send the content exactly as it appears in the BLOB table using
450
+** send the content exactly as it appears in the BLOB table using
451451
** a "cfile" card.
452452
*/
453453
static void send_compressed_file(Xfer *pXfer, int rid){
454454
const char *zContent;
455455
const char *zUuid;
@@ -515,11 +515,11 @@
515515
** Except: do not request shunned artifacts. And do not request
516516
** private artifacts if we are not doing a private transfer.
517517
*/
518518
static void request_phantoms(Xfer *pXfer, int maxReq){
519519
Stmt q;
520
- db_prepare(&q,
520
+ db_prepare(&q,
521521
"SELECT uuid FROM phantom JOIN blob USING(rid)"
522522
" WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s",
523523
(pXfer->syncPrivate ? "" :
524524
" AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)")
525525
);
@@ -551,12 +551,12 @@
551551
** Check the signature on an application/x-fossil payload received by
552552
** the HTTP server. The signature is a line of the following form:
553553
**
554554
** login LOGIN NONCE SIGNATURE
555555
**
556
-** The NONCE is the SHA1 hash of the remainder of the input.
557
-** SIGNATURE is the SHA1 checksum of the NONCE concatenated
556
+** The NONCE is the SHA1 hash of the remainder of the input.
557
+** SIGNATURE is the SHA1 checksum of the NONCE concatenated
558558
** with the users password.
559559
**
560560
** The parameters to this routine are ephemeral blobs holding the
561561
** LOGIN, NONCE and SIGNATURE.
562562
**
@@ -564,11 +564,11 @@
564564
** If everything checks out, the USER.CAP column for the USER table
565565
** is consulted to set privileges in the global g variable.
566566
**
567567
** If anything fails to check out, no changes are made to privileges.
568568
**
569
-** Signature generation on the client side is handled by the
569
+** Signature generation on the client side is handled by the
570570
** http_exchange() routine.
571571
**
572572
** Return non-zero for a login failure and zero for success.
573573
*/
574574
int check_login(Blob *pLogin, Blob *pNonce, Blob *pSig){
@@ -699,11 +699,11 @@
699699
blob_appendf(&deleteWhere, ",%d", rid);
700700
}
701701
}
702702
db_finalize(&q);
703703
db_multi_exec(
704
- "DELETE FROM unclustered WHERE rid NOT IN (0 %s)",
704
+ "DELETE FROM unclustered WHERE rid NOT IN (0 %s)",
705705
blob_str(&deleteWhere)
706706
);
707707
blob_reset(&deleteWhere);
708708
if( nRow>0 ){
709709
md5sum_blob(&cluster, &cksum);
@@ -738,21 +738,21 @@
738738
*/
739739
static int send_unclustered(Xfer *pXfer){
740740
Stmt q;
741741
int cnt = 0;
742742
if( pXfer->resync ){
743
- db_prepare(&q,
743
+ db_prepare(&q,
744744
"SELECT uuid, rid FROM blob"
745745
" WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
746746
" AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=blob.rid)"
747747
" AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)"
748748
" AND blob.rid<=%d"
749749
" ORDER BY blob.rid DESC",
750750
pXfer->resync
751751
);
752752
}else{
753
- db_prepare(&q,
753
+ db_prepare(&q,
754754
"SELECT uuid FROM unclustered JOIN blob USING(rid)"
755755
" WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
756756
" AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=blob.rid)"
757757
" AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)"
758758
);
@@ -772,11 +772,11 @@
772772
/*
773773
** Send an igot message for every artifact.
774774
*/
775775
static void send_all(Xfer *pXfer){
776776
Stmt q;
777
- db_prepare(&q,
777
+ db_prepare(&q,
778778
"SELECT uuid FROM blob "
779779
" WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
780780
" AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)"
781781
" AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=blob.rid)"
782782
);
@@ -1033,12 +1033,12 @@
10331033
}else{
10341034
server_private_xfer_not_authorized();
10351035
}
10361036
}
10371037
}else
1038
-
1039
-
1038
+
1039
+
10401040
/* pull SERVERCODE PROJECTCODE
10411041
** push SERVERCODE PROJECTCODE
10421042
**
10431043
** The client wants either send or receive. The server should
10441044
** verify that the project code matches.
@@ -1142,14 +1142,14 @@
11421142
){
11431143
cgi_reset_content();
11441144
@ error login\sfailed
11451145
nErr++;
11461146
break;
1147
- }
1147
+ }
11481148
}
11491149
}else
1150
-
1150
+
11511151
/* reqconfig NAME
11521152
**
11531153
** Request a configuration value
11541154
*/
11551155
if( blob_eq(&xfer.aToken[0], "reqconfig")
@@ -1167,11 +1167,11 @@
11671167
/* Old style configuration transfer */
11681168
send_legacy_config_card(&xfer, zName);
11691169
}
11701170
}
11711171
}else
1172
-
1172
+
11731173
/* config NAME SIZE \n CONTENT
11741174
**
11751175
** Receive a configuration value from the client. This is only
11761176
** permitted for high-privilege users.
11771177
*/
@@ -1194,11 +1194,11 @@
11941194
configure_receive(zName, &content, CONFIGSET_ALL);
11951195
blob_reset(&content);
11961196
blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
11971197
}else
11981198
1199
-
1199
+
12001200
12011201
/* cookie TEXT
12021202
**
12031203
** A cookie contains a arbitrary-length argument that is server-defined.
12041204
** The argument must be encoded so as not to contain any whitespace.
@@ -1413,11 +1413,11 @@
14131413
int nArtifactRcvd = 0; /* Total artifacts received */
14141414
const char *zOpType = 0;/* Push, Pull, Sync, Clone */
14151415
double rSkew = 0.0; /* Maximum time skew */
14161416
14171417
if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
1418
- if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE))==0
1418
+ if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE))==0
14191419
&& configRcvMask==0 && configSendMask==0 ) return 0;
14201420
14211421
transport_stats(0, 0, 1);
14221422
socket_global_init();
14231423
memset(&xfer, 0, sizeof(xfer));
@@ -1487,11 +1487,11 @@
14871487
*/
14881488
zCookie = db_get("cookie", 0);
14891489
if( zCookie ){
14901490
blob_appendf(&send, "cookie %s\n", zCookie);
14911491
}
1492
-
1492
+
14931493
/* Generate gimme cards for phantoms and leaf cards
14941494
** for all leaves.
14951495
*/
14961496
if( (syncFlags & SYNC_PULL)!=0
14971497
|| ((syncFlags & SYNC_CLONE)!=0 && cloneSeqno==1)
@@ -1503,11 +1503,11 @@
15031503
nCardSent += send_unclustered(&xfer);
15041504
if( syncFlags & SYNC_PRIVATE ) send_private(&xfer);
15051505
}
15061506
15071507
/* Send configuration parameter requests. On a clone, delay sending
1508
- ** this until the second cycle since the login card might fail on
1508
+ ** this until the second cycle since the login card might fail on
15091509
** the first cycle.
15101510
*/
15111511
if( configRcvMask && ((syncFlags & SYNC_CLONE)==0 || nCycle>0) ){
15121512
const char *zName;
15131513
if( zOpType==0 ) zOpType = "Pull";
@@ -1663,20 +1663,20 @@
16631663
if( syncFlags & SYNC_PUSH ){
16641664
int rid = rid_from_uuid(&xfer.aToken[1], 0, 0);
16651665
if( rid ) send_file(&xfer, rid, &xfer.aToken[1], 0);
16661666
}
16671667
}else
1668
-
1668
+
16691669
/* igot UUID ?PRIVATEFLAG?
16701670
**
16711671
** Server announces that it has a particular file. If this is
16721672
** not a file that we have and we are pulling, then create a
16731673
** phantom to cause this file to be requested on the next cycle.
16741674
** Always remember that the server has this file so that we do
16751675
** not transmit it by accident.
16761676
**
1677
- ** If the PRIVATE argument exists and is 1, then the file is
1677
+ ** If the PRIVATE argument exists and is 1, then the file is
16781678
** private. Pretend it does not exists if we are not pulling
16791679
** private files.
16801680
*/
16811681
if( xfer.nToken>=2
16821682
&& blob_eq(&xfer.aToken[0], "igot")
@@ -1693,12 +1693,12 @@
16931693
rid = content_new(blob_str(&xfer.aToken[1]), isPriv);
16941694
if( rid ) newPhantom = 1;
16951695
}
16961696
remote_has(rid);
16971697
}else
1698
-
1699
-
1698
+
1699
+
17001700
/* push SERVERCODE PRODUCTCODE
17011701
**
17021702
** Should only happen in response to a clone. This message tells
17031703
** the client what product to use for the new database.
17041704
*/
@@ -1716,11 +1716,11 @@
17161716
db_set("project-code", zPCode, 0);
17171717
}
17181718
if( cloneSeqno>0 ) blob_appendf(&send, "clone 3 %d\n", cloneSeqno);
17191719
nCardSent++;
17201720
}else
1721
-
1721
+
17221722
/* config NAME SIZE \n CONTENT
17231723
**
17241724
** Receive a configuration value from the server.
17251725
**
17261726
** The received configuration setting is silently ignored if it was
@@ -1738,11 +1738,11 @@
17381738
nArtifactRcvd++;
17391739
blob_reset(&content);
17401740
blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
17411741
}else
17421742
1743
-
1743
+
17441744
/* cookie TEXT
17451745
**
17461746
** The server might include a cookie in its reply. The client
17471747
** should remember this cookie and send it back to the server
17481748
** in its next query.
@@ -1780,11 +1780,11 @@
17801780
**
17811781
** Print a message. Similar to "error" but does not stop processing.
17821782
**
17831783
** If the "login failed" message is seen, clear the sync password prior
17841784
** to the next cycle.
1785
- */
1785
+ */
17861786
if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){
17871787
char *zMsg = blob_terminate(&xfer.aToken[1]);
17881788
defossilize(zMsg);
17891789
if( (syncFlags & SYNC_PUSH) && zMsg && strglob("pull only *", zMsg) ){
17901790
syncFlags &= ~SYNC_PUSH;
@@ -1797,11 +1797,11 @@
17971797
}else
17981798
17991799
/* pragma NAME VALUE...
18001800
**
18011801
** The server can send pragmas to try to convey meta-information to
1802
- ** the client. These are informational only. Unknown pragmas are
1802
+ ** the client. These are informational only. Unknown pragmas are
18031803
** silently ignored.
18041804
*/
18051805
if( blob_eq(&xfer.aToken[0], "pragma") && xfer.nToken>=2 ){
18061806
}else
18071807
@@ -1810,14 +1810,14 @@
18101810
** Report an error and abandon the sync session.
18111811
**
18121812
** Except, when cloning we will sometimes get an error on the
18131813
** first message exchange because the project-code is unknown
18141814
** and so the login card on the request was invalid. The project-code
1815
- ** is returned in the reply before the error card, so second and
1815
+ ** is returned in the reply before the error card, so second and
18161816
** subsequent messages should be OK. Nevertheless, we need to ignore
18171817
** the error card on the first message of a clone.
1818
- */
1818
+ */
18191819
if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){
18201820
if( (syncFlags & SYNC_CLONE)==0 || nCycle>0 ){
18211821
char *zMsg = blob_terminate(&xfer.aToken[1]);
18221822
defossilize(zMsg);
18231823
fossil_force_newline();
@@ -1894,11 +1894,11 @@
18941894
xfer.nFileRcvd = 0;
18951895
xfer.nDeltaRcvd = 0;
18961896
xfer.nDanglingFile = 0;
18971897
18981898
/* If we have one or more files queued to send, then go
1899
- ** another round
1899
+ ** another round
19001900
*/
19011901
if( xfer.nFileSent+xfer.nDeltaSent>0 ){
19021902
go = 1;
19031903
}
19041904
@@ -1908,11 +1908,11 @@
19081908
/* Stop the cycle if the server sends a "clone_seqno 0" card and
19091909
** we have gone at least two rounds. Always go at least two rounds
19101910
** on a clone in order to be sure to retrieve the configuration
19111911
** information which is only sent on the second round.
19121912
*/
1913
- if( cloneSeqno<=0 && nCycle>1 ) go = 0;
1913
+ if( cloneSeqno<=0 && nCycle>1 ) go = 0;
19141914
};
19151915
transport_stats(&nSent, &nRcvd, 1);
19161916
if( (rSkew*24.0*3600.0) > 10.0 ){
19171917
fossil_warning("*** time skew *** server is fast by %s",
19181918
db_timespan_name(rSkew));
19191919
--- src/xfer.c
+++ src/xfer.c
@@ -94,11 +94,11 @@
94 db_reset(&q);
95 }
96 }
97
98 /*
99 ** The aToken[0..nToken-1] blob array is a parse of a "file" line
100 ** message. This routine finishes parsing that message and does
101 ** a record insert of the file.
102 **
103 ** The file line is in one of the following two forms:
104 **
@@ -119,14 +119,14 @@
119 int n;
120 int rid;
121 int srcid = 0;
122 Blob content, hash;
123 int isPriv;
124
125 isPriv = pXfer->nextIsPrivate;
126 pXfer->nextIsPrivate = 0;
127 if( pXfer->nToken<3
128 || pXfer->nToken>4
129 || !blob_is_uuid(&pXfer->aToken[1])
130 || !blob_is_int(&pXfer->aToken[pXfer->nToken-1], &n)
131 || n<0
132 || (pXfer->nToken==4 && !blob_is_uuid(&pXfer->aToken[2]))
@@ -198,11 +198,11 @@
198 assert( blob_is_reset(&content) );
199 remote_has(rid);
200 }
201
202 /*
203 ** The aToken[0..nToken-1] blob array is a parse of a "cfile" line
204 ** message. This routine finishes parsing that message and does
205 ** a record insert of the file. The difference between "file" and
206 ** "cfile" is that with "cfile" the content is already compressed.
207 **
208 ** The file line is in one of the following two forms:
@@ -227,14 +227,14 @@
227 int szU; /* USIZE */
228 int rid;
229 int srcid = 0;
230 Blob content;
231 int isPriv;
232
233 isPriv = pXfer->nextIsPrivate;
234 pXfer->nextIsPrivate = 0;
235 if( pXfer->nToken<4
236 || pXfer->nToken>5
237 || !blob_is_uuid(&pXfer->aToken[1])
238 || !blob_is_int(&pXfer->aToken[pXfer->nToken-2], &szU)
239 || !blob_is_int(&pXfer->aToken[pXfer->nToken-1], &szC)
240 || szC<0 || szU<0
@@ -284,11 +284,11 @@
284 ){
285 static const char *const azQuery[] = {
286 "SELECT pid FROM plink x"
287 " WHERE cid=%d"
288 " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)",
289
290 "SELECT pid, min(mtime) FROM mlink, event ON mlink.mid=event.objid"
291 " WHERE fid=%d"
292 " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)"
293 };
294 int i;
@@ -321,11 +321,11 @@
321 }
322 return size;
323 }
324
325 /*
326 ** Try to send a file as a native delta.
327 ** If successful, return the number of bytes in the delta.
328 ** If we cannot generate an appropriate delta, then send
329 ** nothing and return zero.
330 **
331 ** Never send a delta against a private artifact.
@@ -403,11 +403,11 @@
403 }
404 if( uuid_is_shunned(blob_str(pUuid)) ){
405 blob_reset(&uuid);
406 return;
407 }
408 if( (pXfer->maxTime != -1 && time(NULL) >= pXfer->maxTime) ||
409 pXfer->mxSend<=blob_size(pXfer->pOut) ){
410 const char *zFormat = isPriv ? "igot %b 1\n" : "igot %b\n";
411 blob_appendf(pXfer->pOut, zFormat, pUuid);
412 pXfer->nIGotSent++;
413 blob_reset(&uuid);
@@ -445,11 +445,11 @@
445 #endif
446 }
447
448 /*
449 ** Send the file identified by rid as a compressed artifact. Basically,
450 ** send the content exactly as it appears in the BLOB table using
451 ** a "cfile" card.
452 */
453 static void send_compressed_file(Xfer *pXfer, int rid){
454 const char *zContent;
455 const char *zUuid;
@@ -515,11 +515,11 @@
515 ** Except: do not request shunned artifacts. And do not request
516 ** private artifacts if we are not doing a private transfer.
517 */
518 static void request_phantoms(Xfer *pXfer, int maxReq){
519 Stmt q;
520 db_prepare(&q,
521 "SELECT uuid FROM phantom JOIN blob USING(rid)"
522 " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s",
523 (pXfer->syncPrivate ? "" :
524 " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)")
525 );
@@ -551,12 +551,12 @@
551 ** Check the signature on an application/x-fossil payload received by
552 ** the HTTP server. The signature is a line of the following form:
553 **
554 ** login LOGIN NONCE SIGNATURE
555 **
556 ** The NONCE is the SHA1 hash of the remainder of the input.
557 ** SIGNATURE is the SHA1 checksum of the NONCE concatenated
558 ** with the users password.
559 **
560 ** The parameters to this routine are ephemeral blobs holding the
561 ** LOGIN, NONCE and SIGNATURE.
562 **
@@ -564,11 +564,11 @@
564 ** If everything checks out, the USER.CAP column for the USER table
565 ** is consulted to set privileges in the global g variable.
566 **
567 ** If anything fails to check out, no changes are made to privileges.
568 **
569 ** Signature generation on the client side is handled by the
570 ** http_exchange() routine.
571 **
572 ** Return non-zero for a login failure and zero for success.
573 */
574 int check_login(Blob *pLogin, Blob *pNonce, Blob *pSig){
@@ -699,11 +699,11 @@
699 blob_appendf(&deleteWhere, ",%d", rid);
700 }
701 }
702 db_finalize(&q);
703 db_multi_exec(
704 "DELETE FROM unclustered WHERE rid NOT IN (0 %s)",
705 blob_str(&deleteWhere)
706 );
707 blob_reset(&deleteWhere);
708 if( nRow>0 ){
709 md5sum_blob(&cluster, &cksum);
@@ -738,21 +738,21 @@
738 */
739 static int send_unclustered(Xfer *pXfer){
740 Stmt q;
741 int cnt = 0;
742 if( pXfer->resync ){
743 db_prepare(&q,
744 "SELECT uuid, rid FROM blob"
745 " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
746 " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=blob.rid)"
747 " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)"
748 " AND blob.rid<=%d"
749 " ORDER BY blob.rid DESC",
750 pXfer->resync
751 );
752 }else{
753 db_prepare(&q,
754 "SELECT uuid FROM unclustered JOIN blob USING(rid)"
755 " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
756 " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=blob.rid)"
757 " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)"
758 );
@@ -772,11 +772,11 @@
772 /*
773 ** Send an igot message for every artifact.
774 */
775 static void send_all(Xfer *pXfer){
776 Stmt q;
777 db_prepare(&q,
778 "SELECT uuid FROM blob "
779 " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
780 " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)"
781 " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=blob.rid)"
782 );
@@ -1033,12 +1033,12 @@
1033 }else{
1034 server_private_xfer_not_authorized();
1035 }
1036 }
1037 }else
1038
1039
1040 /* pull SERVERCODE PROJECTCODE
1041 ** push SERVERCODE PROJECTCODE
1042 **
1043 ** The client wants either send or receive. The server should
1044 ** verify that the project code matches.
@@ -1142,14 +1142,14 @@
1142 ){
1143 cgi_reset_content();
1144 @ error login\sfailed
1145 nErr++;
1146 break;
1147 }
1148 }
1149 }else
1150
1151 /* reqconfig NAME
1152 **
1153 ** Request a configuration value
1154 */
1155 if( blob_eq(&xfer.aToken[0], "reqconfig")
@@ -1167,11 +1167,11 @@
1167 /* Old style configuration transfer */
1168 send_legacy_config_card(&xfer, zName);
1169 }
1170 }
1171 }else
1172
1173 /* config NAME SIZE \n CONTENT
1174 **
1175 ** Receive a configuration value from the client. This is only
1176 ** permitted for high-privilege users.
1177 */
@@ -1194,11 +1194,11 @@
1194 configure_receive(zName, &content, CONFIGSET_ALL);
1195 blob_reset(&content);
1196 blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
1197 }else
1198
1199
1200
1201 /* cookie TEXT
1202 **
1203 ** A cookie contains a arbitrary-length argument that is server-defined.
1204 ** The argument must be encoded so as not to contain any whitespace.
@@ -1413,11 +1413,11 @@
1413 int nArtifactRcvd = 0; /* Total artifacts received */
1414 const char *zOpType = 0;/* Push, Pull, Sync, Clone */
1415 double rSkew = 0.0; /* Maximum time skew */
1416
1417 if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
1418 if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE))==0
1419 && configRcvMask==0 && configSendMask==0 ) return 0;
1420
1421 transport_stats(0, 0, 1);
1422 socket_global_init();
1423 memset(&xfer, 0, sizeof(xfer));
@@ -1487,11 +1487,11 @@
1487 */
1488 zCookie = db_get("cookie", 0);
1489 if( zCookie ){
1490 blob_appendf(&send, "cookie %s\n", zCookie);
1491 }
1492
1493 /* Generate gimme cards for phantoms and leaf cards
1494 ** for all leaves.
1495 */
1496 if( (syncFlags & SYNC_PULL)!=0
1497 || ((syncFlags & SYNC_CLONE)!=0 && cloneSeqno==1)
@@ -1503,11 +1503,11 @@
1503 nCardSent += send_unclustered(&xfer);
1504 if( syncFlags & SYNC_PRIVATE ) send_private(&xfer);
1505 }
1506
1507 /* Send configuration parameter requests. On a clone, delay sending
1508 ** this until the second cycle since the login card might fail on
1509 ** the first cycle.
1510 */
1511 if( configRcvMask && ((syncFlags & SYNC_CLONE)==0 || nCycle>0) ){
1512 const char *zName;
1513 if( zOpType==0 ) zOpType = "Pull";
@@ -1663,20 +1663,20 @@
1663 if( syncFlags & SYNC_PUSH ){
1664 int rid = rid_from_uuid(&xfer.aToken[1], 0, 0);
1665 if( rid ) send_file(&xfer, rid, &xfer.aToken[1], 0);
1666 }
1667 }else
1668
1669 /* igot UUID ?PRIVATEFLAG?
1670 **
1671 ** Server announces that it has a particular file. If this is
1672 ** not a file that we have and we are pulling, then create a
1673 ** phantom to cause this file to be requested on the next cycle.
1674 ** Always remember that the server has this file so that we do
1675 ** not transmit it by accident.
1676 **
1677 ** If the PRIVATE argument exists and is 1, then the file is
1678 ** private. Pretend it does not exists if we are not pulling
1679 ** private files.
1680 */
1681 if( xfer.nToken>=2
1682 && blob_eq(&xfer.aToken[0], "igot")
@@ -1693,12 +1693,12 @@
1693 rid = content_new(blob_str(&xfer.aToken[1]), isPriv);
1694 if( rid ) newPhantom = 1;
1695 }
1696 remote_has(rid);
1697 }else
1698
1699
1700 /* push SERVERCODE PRODUCTCODE
1701 **
1702 ** Should only happen in response to a clone. This message tells
1703 ** the client what product to use for the new database.
1704 */
@@ -1716,11 +1716,11 @@
1716 db_set("project-code", zPCode, 0);
1717 }
1718 if( cloneSeqno>0 ) blob_appendf(&send, "clone 3 %d\n", cloneSeqno);
1719 nCardSent++;
1720 }else
1721
1722 /* config NAME SIZE \n CONTENT
1723 **
1724 ** Receive a configuration value from the server.
1725 **
1726 ** The received configuration setting is silently ignored if it was
@@ -1738,11 +1738,11 @@
1738 nArtifactRcvd++;
1739 blob_reset(&content);
1740 blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
1741 }else
1742
1743
1744 /* cookie TEXT
1745 **
1746 ** The server might include a cookie in its reply. The client
1747 ** should remember this cookie and send it back to the server
1748 ** in its next query.
@@ -1780,11 +1780,11 @@
1780 **
1781 ** Print a message. Similar to "error" but does not stop processing.
1782 **
1783 ** If the "login failed" message is seen, clear the sync password prior
1784 ** to the next cycle.
1785 */
1786 if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){
1787 char *zMsg = blob_terminate(&xfer.aToken[1]);
1788 defossilize(zMsg);
1789 if( (syncFlags & SYNC_PUSH) && zMsg && strglob("pull only *", zMsg) ){
1790 syncFlags &= ~SYNC_PUSH;
@@ -1797,11 +1797,11 @@
1797 }else
1798
1799 /* pragma NAME VALUE...
1800 **
1801 ** The server can send pragmas to try to convey meta-information to
1802 ** the client. These are informational only. Unknown pragmas are
1803 ** silently ignored.
1804 */
1805 if( blob_eq(&xfer.aToken[0], "pragma") && xfer.nToken>=2 ){
1806 }else
1807
@@ -1810,14 +1810,14 @@
1810 ** Report an error and abandon the sync session.
1811 **
1812 ** Except, when cloning we will sometimes get an error on the
1813 ** first message exchange because the project-code is unknown
1814 ** and so the login card on the request was invalid. The project-code
1815 ** is returned in the reply before the error card, so second and
1816 ** subsequent messages should be OK. Nevertheless, we need to ignore
1817 ** the error card on the first message of a clone.
1818 */
1819 if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){
1820 if( (syncFlags & SYNC_CLONE)==0 || nCycle>0 ){
1821 char *zMsg = blob_terminate(&xfer.aToken[1]);
1822 defossilize(zMsg);
1823 fossil_force_newline();
@@ -1894,11 +1894,11 @@
1894 xfer.nFileRcvd = 0;
1895 xfer.nDeltaRcvd = 0;
1896 xfer.nDanglingFile = 0;
1897
1898 /* If we have one or more files queued to send, then go
1899 ** another round
1900 */
1901 if( xfer.nFileSent+xfer.nDeltaSent>0 ){
1902 go = 1;
1903 }
1904
@@ -1908,11 +1908,11 @@
1908 /* Stop the cycle if the server sends a "clone_seqno 0" card and
1909 ** we have gone at least two rounds. Always go at least two rounds
1910 ** on a clone in order to be sure to retrieve the configuration
1911 ** information which is only sent on the second round.
1912 */
1913 if( cloneSeqno<=0 && nCycle>1 ) go = 0;
1914 };
1915 transport_stats(&nSent, &nRcvd, 1);
1916 if( (rSkew*24.0*3600.0) > 10.0 ){
1917 fossil_warning("*** time skew *** server is fast by %s",
1918 db_timespan_name(rSkew));
1919
--- src/xfer.c
+++ src/xfer.c
@@ -94,11 +94,11 @@
94 db_reset(&q);
95 }
96 }
97
98 /*
99 ** The aToken[0..nToken-1] blob array is a parse of a "file" line
100 ** message. This routine finishes parsing that message and does
101 ** a record insert of the file.
102 **
103 ** The file line is in one of the following two forms:
104 **
@@ -119,14 +119,14 @@
119 int n;
120 int rid;
121 int srcid = 0;
122 Blob content, hash;
123 int isPriv;
124
125 isPriv = pXfer->nextIsPrivate;
126 pXfer->nextIsPrivate = 0;
127 if( pXfer->nToken<3
128 || pXfer->nToken>4
129 || !blob_is_uuid(&pXfer->aToken[1])
130 || !blob_is_int(&pXfer->aToken[pXfer->nToken-1], &n)
131 || n<0
132 || (pXfer->nToken==4 && !blob_is_uuid(&pXfer->aToken[2]))
@@ -198,11 +198,11 @@
198 assert( blob_is_reset(&content) );
199 remote_has(rid);
200 }
201
202 /*
203 ** The aToken[0..nToken-1] blob array is a parse of a "cfile" line
204 ** message. This routine finishes parsing that message and does
205 ** a record insert of the file. The difference between "file" and
206 ** "cfile" is that with "cfile" the content is already compressed.
207 **
208 ** The file line is in one of the following two forms:
@@ -227,14 +227,14 @@
227 int szU; /* USIZE */
228 int rid;
229 int srcid = 0;
230 Blob content;
231 int isPriv;
232
233 isPriv = pXfer->nextIsPrivate;
234 pXfer->nextIsPrivate = 0;
235 if( pXfer->nToken<4
236 || pXfer->nToken>5
237 || !blob_is_uuid(&pXfer->aToken[1])
238 || !blob_is_int(&pXfer->aToken[pXfer->nToken-2], &szU)
239 || !blob_is_int(&pXfer->aToken[pXfer->nToken-1], &szC)
240 || szC<0 || szU<0
@@ -284,11 +284,11 @@
284 ){
285 static const char *const azQuery[] = {
286 "SELECT pid FROM plink x"
287 " WHERE cid=%d"
288 " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)",
289
290 "SELECT pid, min(mtime) FROM mlink, event ON mlink.mid=event.objid"
291 " WHERE fid=%d"
292 " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)"
293 };
294 int i;
@@ -321,11 +321,11 @@
321 }
322 return size;
323 }
324
325 /*
326 ** Try to send a file as a native delta.
327 ** If successful, return the number of bytes in the delta.
328 ** If we cannot generate an appropriate delta, then send
329 ** nothing and return zero.
330 **
331 ** Never send a delta against a private artifact.
@@ -403,11 +403,11 @@
403 }
404 if( uuid_is_shunned(blob_str(pUuid)) ){
405 blob_reset(&uuid);
406 return;
407 }
408 if( (pXfer->maxTime != -1 && time(NULL) >= pXfer->maxTime) ||
409 pXfer->mxSend<=blob_size(pXfer->pOut) ){
410 const char *zFormat = isPriv ? "igot %b 1\n" : "igot %b\n";
411 blob_appendf(pXfer->pOut, zFormat, pUuid);
412 pXfer->nIGotSent++;
413 blob_reset(&uuid);
@@ -445,11 +445,11 @@
445 #endif
446 }
447
448 /*
449 ** Send the file identified by rid as a compressed artifact. Basically,
450 ** send the content exactly as it appears in the BLOB table using
451 ** a "cfile" card.
452 */
453 static void send_compressed_file(Xfer *pXfer, int rid){
454 const char *zContent;
455 const char *zUuid;
@@ -515,11 +515,11 @@
515 ** Except: do not request shunned artifacts. And do not request
516 ** private artifacts if we are not doing a private transfer.
517 */
518 static void request_phantoms(Xfer *pXfer, int maxReq){
519 Stmt q;
520 db_prepare(&q,
521 "SELECT uuid FROM phantom JOIN blob USING(rid)"
522 " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid) %s",
523 (pXfer->syncPrivate ? "" :
524 " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)")
525 );
@@ -551,12 +551,12 @@
551 ** Check the signature on an application/x-fossil payload received by
552 ** the HTTP server. The signature is a line of the following form:
553 **
554 ** login LOGIN NONCE SIGNATURE
555 **
556 ** The NONCE is the SHA1 hash of the remainder of the input.
557 ** SIGNATURE is the SHA1 checksum of the NONCE concatenated
558 ** with the users password.
559 **
560 ** The parameters to this routine are ephemeral blobs holding the
561 ** LOGIN, NONCE and SIGNATURE.
562 **
@@ -564,11 +564,11 @@
564 ** If everything checks out, the USER.CAP column for the USER table
565 ** is consulted to set privileges in the global g variable.
566 **
567 ** If anything fails to check out, no changes are made to privileges.
568 **
569 ** Signature generation on the client side is handled by the
570 ** http_exchange() routine.
571 **
572 ** Return non-zero for a login failure and zero for success.
573 */
574 int check_login(Blob *pLogin, Blob *pNonce, Blob *pSig){
@@ -699,11 +699,11 @@
699 blob_appendf(&deleteWhere, ",%d", rid);
700 }
701 }
702 db_finalize(&q);
703 db_multi_exec(
704 "DELETE FROM unclustered WHERE rid NOT IN (0 %s)",
705 blob_str(&deleteWhere)
706 );
707 blob_reset(&deleteWhere);
708 if( nRow>0 ){
709 md5sum_blob(&cluster, &cksum);
@@ -738,21 +738,21 @@
738 */
739 static int send_unclustered(Xfer *pXfer){
740 Stmt q;
741 int cnt = 0;
742 if( pXfer->resync ){
743 db_prepare(&q,
744 "SELECT uuid, rid FROM blob"
745 " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
746 " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=blob.rid)"
747 " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)"
748 " AND blob.rid<=%d"
749 " ORDER BY blob.rid DESC",
750 pXfer->resync
751 );
752 }else{
753 db_prepare(&q,
754 "SELECT uuid FROM unclustered JOIN blob USING(rid)"
755 " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
756 " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=blob.rid)"
757 " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)"
758 );
@@ -772,11 +772,11 @@
772 /*
773 ** Send an igot message for every artifact.
774 */
775 static void send_all(Xfer *pXfer){
776 Stmt q;
777 db_prepare(&q,
778 "SELECT uuid FROM blob "
779 " WHERE NOT EXISTS(SELECT 1 FROM shun WHERE uuid=blob.uuid)"
780 " AND NOT EXISTS(SELECT 1 FROM private WHERE rid=blob.rid)"
781 " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=blob.rid)"
782 );
@@ -1033,12 +1033,12 @@
1033 }else{
1034 server_private_xfer_not_authorized();
1035 }
1036 }
1037 }else
1038
1039
1040 /* pull SERVERCODE PROJECTCODE
1041 ** push SERVERCODE PROJECTCODE
1042 **
1043 ** The client wants either send or receive. The server should
1044 ** verify that the project code matches.
@@ -1142,14 +1142,14 @@
1142 ){
1143 cgi_reset_content();
1144 @ error login\sfailed
1145 nErr++;
1146 break;
1147 }
1148 }
1149 }else
1150
1151 /* reqconfig NAME
1152 **
1153 ** Request a configuration value
1154 */
1155 if( blob_eq(&xfer.aToken[0], "reqconfig")
@@ -1167,11 +1167,11 @@
1167 /* Old style configuration transfer */
1168 send_legacy_config_card(&xfer, zName);
1169 }
1170 }
1171 }else
1172
1173 /* config NAME SIZE \n CONTENT
1174 **
1175 ** Receive a configuration value from the client. This is only
1176 ** permitted for high-privilege users.
1177 */
@@ -1194,11 +1194,11 @@
1194 configure_receive(zName, &content, CONFIGSET_ALL);
1195 blob_reset(&content);
1196 blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
1197 }else
1198
1199
1200
1201 /* cookie TEXT
1202 **
1203 ** A cookie contains a arbitrary-length argument that is server-defined.
1204 ** The argument must be encoded so as not to contain any whitespace.
@@ -1413,11 +1413,11 @@
1413 int nArtifactRcvd = 0; /* Total artifacts received */
1414 const char *zOpType = 0;/* Push, Pull, Sync, Clone */
1415 double rSkew = 0.0; /* Maximum time skew */
1416
1417 if( db_get_boolean("dont-push", 0) ) syncFlags &= ~SYNC_PUSH;
1418 if( (syncFlags & (SYNC_PUSH|SYNC_PULL|SYNC_CLONE))==0
1419 && configRcvMask==0 && configSendMask==0 ) return 0;
1420
1421 transport_stats(0, 0, 1);
1422 socket_global_init();
1423 memset(&xfer, 0, sizeof(xfer));
@@ -1487,11 +1487,11 @@
1487 */
1488 zCookie = db_get("cookie", 0);
1489 if( zCookie ){
1490 blob_appendf(&send, "cookie %s\n", zCookie);
1491 }
1492
1493 /* Generate gimme cards for phantoms and leaf cards
1494 ** for all leaves.
1495 */
1496 if( (syncFlags & SYNC_PULL)!=0
1497 || ((syncFlags & SYNC_CLONE)!=0 && cloneSeqno==1)
@@ -1503,11 +1503,11 @@
1503 nCardSent += send_unclustered(&xfer);
1504 if( syncFlags & SYNC_PRIVATE ) send_private(&xfer);
1505 }
1506
1507 /* Send configuration parameter requests. On a clone, delay sending
1508 ** this until the second cycle since the login card might fail on
1509 ** the first cycle.
1510 */
1511 if( configRcvMask && ((syncFlags & SYNC_CLONE)==0 || nCycle>0) ){
1512 const char *zName;
1513 if( zOpType==0 ) zOpType = "Pull";
@@ -1663,20 +1663,20 @@
1663 if( syncFlags & SYNC_PUSH ){
1664 int rid = rid_from_uuid(&xfer.aToken[1], 0, 0);
1665 if( rid ) send_file(&xfer, rid, &xfer.aToken[1], 0);
1666 }
1667 }else
1668
1669 /* igot UUID ?PRIVATEFLAG?
1670 **
1671 ** Server announces that it has a particular file. If this is
1672 ** not a file that we have and we are pulling, then create a
1673 ** phantom to cause this file to be requested on the next cycle.
1674 ** Always remember that the server has this file so that we do
1675 ** not transmit it by accident.
1676 **
1677 ** If the PRIVATE argument exists and is 1, then the file is
1678 ** private. Pretend it does not exists if we are not pulling
1679 ** private files.
1680 */
1681 if( xfer.nToken>=2
1682 && blob_eq(&xfer.aToken[0], "igot")
@@ -1693,12 +1693,12 @@
1693 rid = content_new(blob_str(&xfer.aToken[1]), isPriv);
1694 if( rid ) newPhantom = 1;
1695 }
1696 remote_has(rid);
1697 }else
1698
1699
1700 /* push SERVERCODE PRODUCTCODE
1701 **
1702 ** Should only happen in response to a clone. This message tells
1703 ** the client what product to use for the new database.
1704 */
@@ -1716,11 +1716,11 @@
1716 db_set("project-code", zPCode, 0);
1717 }
1718 if( cloneSeqno>0 ) blob_appendf(&send, "clone 3 %d\n", cloneSeqno);
1719 nCardSent++;
1720 }else
1721
1722 /* config NAME SIZE \n CONTENT
1723 **
1724 ** Receive a configuration value from the server.
1725 **
1726 ** The received configuration setting is silently ignored if it was
@@ -1738,11 +1738,11 @@
1738 nArtifactRcvd++;
1739 blob_reset(&content);
1740 blob_seek(xfer.pIn, 1, BLOB_SEEK_CUR);
1741 }else
1742
1743
1744 /* cookie TEXT
1745 **
1746 ** The server might include a cookie in its reply. The client
1747 ** should remember this cookie and send it back to the server
1748 ** in its next query.
@@ -1780,11 +1780,11 @@
1780 **
1781 ** Print a message. Similar to "error" but does not stop processing.
1782 **
1783 ** If the "login failed" message is seen, clear the sync password prior
1784 ** to the next cycle.
1785 */
1786 if( blob_eq(&xfer.aToken[0],"message") && xfer.nToken==2 ){
1787 char *zMsg = blob_terminate(&xfer.aToken[1]);
1788 defossilize(zMsg);
1789 if( (syncFlags & SYNC_PUSH) && zMsg && strglob("pull only *", zMsg) ){
1790 syncFlags &= ~SYNC_PUSH;
@@ -1797,11 +1797,11 @@
1797 }else
1798
1799 /* pragma NAME VALUE...
1800 **
1801 ** The server can send pragmas to try to convey meta-information to
1802 ** the client. These are informational only. Unknown pragmas are
1803 ** silently ignored.
1804 */
1805 if( blob_eq(&xfer.aToken[0], "pragma") && xfer.nToken>=2 ){
1806 }else
1807
@@ -1810,14 +1810,14 @@
1810 ** Report an error and abandon the sync session.
1811 **
1812 ** Except, when cloning we will sometimes get an error on the
1813 ** first message exchange because the project-code is unknown
1814 ** and so the login card on the request was invalid. The project-code
1815 ** is returned in the reply before the error card, so second and
1816 ** subsequent messages should be OK. Nevertheless, we need to ignore
1817 ** the error card on the first message of a clone.
1818 */
1819 if( blob_eq(&xfer.aToken[0],"error") && xfer.nToken==2 ){
1820 if( (syncFlags & SYNC_CLONE)==0 || nCycle>0 ){
1821 char *zMsg = blob_terminate(&xfer.aToken[1]);
1822 defossilize(zMsg);
1823 fossil_force_newline();
@@ -1894,11 +1894,11 @@
1894 xfer.nFileRcvd = 0;
1895 xfer.nDeltaRcvd = 0;
1896 xfer.nDanglingFile = 0;
1897
1898 /* If we have one or more files queued to send, then go
1899 ** another round
1900 */
1901 if( xfer.nFileSent+xfer.nDeltaSent>0 ){
1902 go = 1;
1903 }
1904
@@ -1908,11 +1908,11 @@
1908 /* Stop the cycle if the server sends a "clone_seqno 0" card and
1909 ** we have gone at least two rounds. Always go at least two rounds
1910 ** on a clone in order to be sure to retrieve the configuration
1911 ** information which is only sent on the second round.
1912 */
1913 if( cloneSeqno<=0 && nCycle>1 ) go = 0;
1914 };
1915 transport_stats(&nSent, &nRcvd, 1);
1916 if( (rSkew*24.0*3600.0) > 10.0 ){
1917 fossil_warning("*** time skew *** server is fast by %s",
1918 db_timespan_name(rSkew));
1919
+5 -5
--- src/zip.c
+++ src/zip.c
@@ -158,17 +158,17 @@
158158
put16(&zHdr[8], iMethod);
159159
put16(&zHdr[10], dosTime);
160160
put16(&zHdr[12], dosDate);
161161
put16(&zHdr[26], nameLen);
162162
put16(&zHdr[28], 13);
163
-
163
+
164164
put16(&zExTime[0], 0x5455);
165165
put16(&zExTime[2], 9);
166166
zExTime[4] = 3;
167167
put32(&zExTime[5], unixTime);
168168
put32(&zExTime[9], unixTime);
169
-
169
+
170170
171171
/* Write the header and filename.
172172
*/
173173
iStart = blob_size(&body);
174174
blob_append(&body, zHdr, 30);
@@ -202,19 +202,19 @@
202202
blob_append(&body, zOutBuf, toOut);
203203
}while( stream.avail_out==0 );
204204
nByte = stream.total_in;
205205
nByteCompr = stream.total_out;
206206
deflateEnd(&stream);
207
-
207
+
208208
/* Go back and write the header, now that we know the compressed file size.
209209
*/
210210
z = &blob_buffer(&body)[iStart];
211211
put32(&z[14], iCRC);
212212
put32(&z[18], nByteCompr);
213213
put32(&z[22], nByte);
214214
}
215
-
215
+
216216
/* Make an entry in the tables of contents
217217
*/
218218
memset(zBuf, 0, sizeof(zBuf));
219219
put32(&zBuf[0], 0x02014b50);
220220
put16(&zBuf[4], 0x0317);
@@ -322,11 +322,11 @@
322322
Blob mfile, hash, file;
323323
Manifest *pManifest;
324324
ManifestFile *pFile;
325325
Blob filename;
326326
int nPrefix;
327
-
327
+
328328
content_get(rid, &mfile);
329329
if( blob_size(&mfile)==0 ){
330330
blob_zero(pZip);
331331
return;
332332
}
333333
--- src/zip.c
+++ src/zip.c
@@ -158,17 +158,17 @@
158 put16(&zHdr[8], iMethod);
159 put16(&zHdr[10], dosTime);
160 put16(&zHdr[12], dosDate);
161 put16(&zHdr[26], nameLen);
162 put16(&zHdr[28], 13);
163
164 put16(&zExTime[0], 0x5455);
165 put16(&zExTime[2], 9);
166 zExTime[4] = 3;
167 put32(&zExTime[5], unixTime);
168 put32(&zExTime[9], unixTime);
169
170
171 /* Write the header and filename.
172 */
173 iStart = blob_size(&body);
174 blob_append(&body, zHdr, 30);
@@ -202,19 +202,19 @@
202 blob_append(&body, zOutBuf, toOut);
203 }while( stream.avail_out==0 );
204 nByte = stream.total_in;
205 nByteCompr = stream.total_out;
206 deflateEnd(&stream);
207
208 /* Go back and write the header, now that we know the compressed file size.
209 */
210 z = &blob_buffer(&body)[iStart];
211 put32(&z[14], iCRC);
212 put32(&z[18], nByteCompr);
213 put32(&z[22], nByte);
214 }
215
216 /* Make an entry in the tables of contents
217 */
218 memset(zBuf, 0, sizeof(zBuf));
219 put32(&zBuf[0], 0x02014b50);
220 put16(&zBuf[4], 0x0317);
@@ -322,11 +322,11 @@
322 Blob mfile, hash, file;
323 Manifest *pManifest;
324 ManifestFile *pFile;
325 Blob filename;
326 int nPrefix;
327
328 content_get(rid, &mfile);
329 if( blob_size(&mfile)==0 ){
330 blob_zero(pZip);
331 return;
332 }
333
--- src/zip.c
+++ src/zip.c
@@ -158,17 +158,17 @@
158 put16(&zHdr[8], iMethod);
159 put16(&zHdr[10], dosTime);
160 put16(&zHdr[12], dosDate);
161 put16(&zHdr[26], nameLen);
162 put16(&zHdr[28], 13);
163
164 put16(&zExTime[0], 0x5455);
165 put16(&zExTime[2], 9);
166 zExTime[4] = 3;
167 put32(&zExTime[5], unixTime);
168 put32(&zExTime[9], unixTime);
169
170
171 /* Write the header and filename.
172 */
173 iStart = blob_size(&body);
174 blob_append(&body, zHdr, 30);
@@ -202,19 +202,19 @@
202 blob_append(&body, zOutBuf, toOut);
203 }while( stream.avail_out==0 );
204 nByte = stream.total_in;
205 nByteCompr = stream.total_out;
206 deflateEnd(&stream);
207
208 /* Go back and write the header, now that we know the compressed file size.
209 */
210 z = &blob_buffer(&body)[iStart];
211 put32(&z[14], iCRC);
212 put32(&z[18], nByteCompr);
213 put32(&z[22], nByte);
214 }
215
216 /* Make an entry in the tables of contents
217 */
218 memset(zBuf, 0, sizeof(zBuf));
219 put32(&zBuf[0], 0x02014b50);
220 put16(&zBuf[4], 0x0317);
@@ -322,11 +322,11 @@
322 Blob mfile, hash, file;
323 Manifest *pManifest;
324 ManifestFile *pFile;
325 Blob filename;
326 int nPrefix;
327
328 content_get(rid, &mfile);
329 if( blob_size(&mfile)==0 ){
330 blob_zero(pZip);
331 return;
332 }
333
--- 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/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/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
--- 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
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -13,14 +13,14 @@
1313
#
1414
1515
#### Select one of MinGW, MinGW-w64 (32-bit) or MinGW-w64 (64-bit) compilers.
1616
# By default, this is an empty string (i.e. use the native compiler).
1717
#
18
-PREFIX =
18
+# PREFIX =
1919
# PREFIX = mingw32-
2020
# PREFIX = i686-pc-mingw32-
21
-# PREFIX = i686-w64-mingw32-
21
+PREFIX = i686-w64-mingw32-
2222
# PREFIX = x86_64-w64-mingw32-
2323
2424
#### The toplevel directory of the source tree. Fossil can be built
2525
# in a directory that is separate from the source tree. Just change
2626
# the following to point from the build directory to the src/ folder.
2727
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -13,14 +13,14 @@
13 #
14
15 #### Select one of MinGW, MinGW-w64 (32-bit) or MinGW-w64 (64-bit) compilers.
16 # By default, this is an empty string (i.e. use the native compiler).
17 #
18 PREFIX =
19 # PREFIX = mingw32-
20 # PREFIX = i686-pc-mingw32-
21 # PREFIX = i686-w64-mingw32-
22 # PREFIX = x86_64-w64-mingw32-
23
24 #### The toplevel directory of the source tree. Fossil can be built
25 # in a directory that is separate from the source tree. Just change
26 # the following to point from the build directory to the src/ folder.
27
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -13,14 +13,14 @@
13 #
14
15 #### Select one of MinGW, MinGW-w64 (32-bit) or MinGW-w64 (64-bit) compilers.
16 # By default, this is an empty string (i.e. use the native compiler).
17 #
18 # PREFIX =
19 # PREFIX = mingw32-
20 # PREFIX = i686-pc-mingw32-
21 PREFIX = i686-w64-mingw32-
22 # PREFIX = x86_64-w64-mingw32-
23
24 #### The toplevel directory of the source tree. Fossil can be built
25 # in a directory that is separate from the source tree. Just change
26 # the following to point from the build directory to the src/ folder.
27
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -13,14 +13,14 @@
1313
#
1414
1515
#### Select one of MinGW, MinGW-w64 (32-bit) or MinGW-w64 (64-bit) compilers.
1616
# By default, this is an empty string (i.e. use the native compiler).
1717
#
18
-PREFIX =
18
+# PREFIX =
1919
# PREFIX = mingw32-
2020
# PREFIX = i686-pc-mingw32-
21
-# PREFIX = i686-w64-mingw32-
21
+PREFIX = i686-w64-mingw32-
2222
# PREFIX = x86_64-w64-mingw32-
2323
2424
#### The toplevel directory of the source tree. Fossil can be built
2525
# in a directory that is separate from the source tree. Just change
2626
# the following to point from the build directory to the src/ folder.
2727
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -13,14 +13,14 @@
13 #
14
15 #### Select one of MinGW, MinGW-w64 (32-bit) or MinGW-w64 (64-bit) compilers.
16 # By default, this is an empty string (i.e. use the native compiler).
17 #
18 PREFIX =
19 # PREFIX = mingw32-
20 # PREFIX = i686-pc-mingw32-
21 # PREFIX = i686-w64-mingw32-
22 # PREFIX = x86_64-w64-mingw32-
23
24 #### The toplevel directory of the source tree. Fossil can be built
25 # in a directory that is separate from the source tree. Just change
26 # the following to point from the build directory to the src/ folder.
27
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -13,14 +13,14 @@
13 #
14
15 #### Select one of MinGW, MinGW-w64 (32-bit) or MinGW-w64 (64-bit) compilers.
16 # By default, this is an empty string (i.e. use the native compiler).
17 #
18 # PREFIX =
19 # PREFIX = mingw32-
20 # PREFIX = i686-pc-mingw32-
21 PREFIX = i686-w64-mingw32-
22 # PREFIX = x86_64-w64-mingw32-
23
24 #### The toplevel directory of the source tree. Fossil can be built
25 # in a directory that is separate from the source tree. Just change
26 # the following to point from the build directory to the src/ folder.
27
+11 -1
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,8 +1,18 @@
11
<title>Change Log</title>
22
3
-<h2>Changes For Version 1.28 (as yet unreleased)</h2>
3
+<h2>Changes For Version 1.29 (as yet unreleased)</h2>
4
+ * Add the ability to display content and diffs for UTF16 text files
5
+ in the web interface.
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>
414
* Enhance [/help?cmd=/reports | /reports] to support event type filtering.
515
* When cloning a repository, the user name passed via the URL (if any)
616
is now used as the default local admin user's name.
717
* Enhance the SSH transport mechanism so that it runs a single instance of
818
the "fossil" executable on the remote side, obviating the need for a shell
919
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,8 +1,18 @@
1 <title>Change Log</title>
2
3 <h2>Changes For Version 1.28 (as yet unreleased)</h2>
 
 
 
 
 
 
 
 
 
 
4 * Enhance [/help?cmd=/reports | /reports] to support event type filtering.
5 * When cloning a repository, the user name passed via the URL (if any)
6 is now used as the default local admin user's name.
7 * Enhance the SSH transport mechanism so that it runs a single instance of
8 the "fossil" executable on the remote side, obviating the need for a shell
9
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,8 +1,18 @@
1 <title>Change Log</title>
2
3 <h2>Changes For Version 1.29 (as yet unreleased)</h2>
4 * Add the ability to display content and diffs for UTF16 text files
5 in the web interface.
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 * Enhance the SSH transport mechanism so that it runs a single instance of
18 the "fossil" executable on the remote side, obviating the need for a shell
19
+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