Fossil SCM

In the built-in customized printf(), change the wiki conversion format character from "%w" to "%W". Then add "%w" to for SQL identifiers within double-quotes, the same as used for SQLite.

drh 2014-10-20 10:07 trunk
Commit 43b30dcfc330ba9fae27401ef8f90184c3c98585
+1 -1
--- src/finfo.c
+++ src/finfo.c
@@ -473,11 +473,11 @@
473473
}else{
474474
@ <b>Deleted</b> by check-in
475475
}
476476
}
477477
hyperlink_to_uuid(zCkin);
478
- @ %w(zCom) (user:
478
+ @ %W(zCom) (user:
479479
hyperlink_to_user(zUser, zDate, "");
480480
@ branch: %h(zBr))
481481
if( g.perm.Hyperlink && zUuid ){
482482
const char *z = zFilename;
483483
@ %z(href("%R/annotate?filename=%h&checkin=%s",z,zCkin))
484484
--- src/finfo.c
+++ src/finfo.c
@@ -473,11 +473,11 @@
473 }else{
474 @ <b>Deleted</b> by check-in
475 }
476 }
477 hyperlink_to_uuid(zCkin);
478 @ %w(zCom) (user:
479 hyperlink_to_user(zUser, zDate, "");
480 @ branch: %h(zBr))
481 if( g.perm.Hyperlink && zUuid ){
482 const char *z = zFilename;
483 @ %z(href("%R/annotate?filename=%h&checkin=%s",z,zCkin))
484
--- src/finfo.c
+++ src/finfo.c
@@ -473,11 +473,11 @@
473 }else{
474 @ <b>Deleted</b> by check-in
475 }
476 }
477 hyperlink_to_uuid(zCkin);
478 @ %W(zCom) (user:
479 hyperlink_to_user(zUser, zDate, "");
480 @ branch: %h(zBr))
481 if( g.perm.Hyperlink && zUuid ){
482 const char *z = zFilename;
483 @ %z(href("%R/annotate?filename=%h&checkin=%s",z,zCkin))
484
+1 -1
--- src/main.c
+++ src/main.c
@@ -169,11 +169,11 @@
169169
int xlinkClusterOnly; /* Set when cloning. Only process clusters */
170170
int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */
171171
int *aCommitFile; /* Array of files to be committed */
172172
int markPrivate; /* All new artifacts are private if true */
173173
int clockSkewSeen; /* True if clocks on client and server out of sync */
174
- int wikiFlags; /* Wiki conversion flags applied to %w and %W */
174
+ int wikiFlags; /* Wiki conversion flags applied to %W */
175175
char isHTTP; /* True if server/CGI modes, else assume CLI. */
176176
char javascriptHyperlink; /* If true, set href= using script, not HTML */
177177
Blob httpHeader; /* Complete text of the HTTP request header */
178178
UrlData url; /* Information about current URL */
179179
const char *zLogin; /* Login name. NULL or "" if not logged in. */
180180
--- src/main.c
+++ src/main.c
@@ -169,11 +169,11 @@
169 int xlinkClusterOnly; /* Set when cloning. Only process clusters */
170 int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */
171 int *aCommitFile; /* Array of files to be committed */
172 int markPrivate; /* All new artifacts are private if true */
173 int clockSkewSeen; /* True if clocks on client and server out of sync */
174 int wikiFlags; /* Wiki conversion flags applied to %w and %W */
175 char isHTTP; /* True if server/CGI modes, else assume CLI. */
176 char javascriptHyperlink; /* If true, set href= using script, not HTML */
177 Blob httpHeader; /* Complete text of the HTTP request header */
178 UrlData url; /* Information about current URL */
179 const char *zLogin; /* Login name. NULL or "" if not logged in. */
180
--- src/main.c
+++ src/main.c
@@ -169,11 +169,11 @@
169 int xlinkClusterOnly; /* Set when cloning. Only process clusters */
170 int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */
171 int *aCommitFile; /* Array of files to be committed */
172 int markPrivate; /* All new artifacts are private if true */
173 int clockSkewSeen; /* True if clocks on client and server out of sync */
174 int wikiFlags; /* Wiki conversion flags applied to %W */
175 char isHTTP; /* True if server/CGI modes, else assume CLI. */
176 char javascriptHyperlink; /* If true, set href= using script, not HTML */
177 Blob httpHeader; /* Complete text of the HTTP request header */
178 UrlData url; /* Information about current URL */
179 const char *zLogin; /* Login name. NULL or "" if not logged in. */
180
+18 -14
--- src/printf.c
+++ src/printf.c
@@ -44,19 +44,20 @@
4444
#define etBLOB 11 /* Blob objects. %b */
4545
#define etBLOBSQL 12 /* Blob objects quoted for SQL. %B */
4646
#define etSQLESCAPE 13 /* Strings with '\'' doubled. %q */
4747
#define etSQLESCAPE2 14 /* Strings with '\'' doubled and enclosed in '',
4848
NULL pointers replaced by SQL NULL. %Q */
49
-#define etPOINTER 15 /* The %p conversion */
50
-#define etHTMLIZE 16 /* Make text safe for HTML */
51
-#define etHTTPIZE 17 /* Make text safe for HTTP. "/" encoded as %2f */
52
-#define etURLIZE 18 /* Make text safe for HTTP. "/" not encoded */
53
-#define etFOSSILIZE 19 /* The fossil header encoding format. */
54
-#define etPATH 20 /* Path type */
55
-#define etWIKISTR 21 /* Timeline comment text rendered from a char*: %w */
49
+#define etSQLESCAPE3 15 /* Double '"' characters within an indentifier. %w */
50
+#define etPOINTER 16 /* The %p conversion */
51
+#define etHTMLIZE 17 /* Make text safe for HTML */
52
+#define etHTTPIZE 18 /* Make text safe for HTTP. "/" encoded as %2f */
53
+#define etURLIZE 19 /* Make text safe for HTTP. "/" not encoded */
54
+#define etFOSSILIZE 20 /* The fossil header encoding format. */
55
+#define etPATH 21 /* Path type */
56
+#define etWIKISTR 22 /* Timeline comment text rendered from a char*: %W */
5657
#define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */
57
-#define etROOT 24 /* String value of g.zTop: % */
58
+#define etROOT 24 /* String value of g.zTop: %R */
5859
5960
6061
/*
6162
** An "etByte" is an 8-bit unsigned value.
6263
*/
@@ -96,15 +97,16 @@
9697
{ 'z', 0, 6, etDYNSTRING, 0, 0 },
9798
{ 'q', 0, 4, etSQLESCAPE, 0, 0 },
9899
{ 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
99100
{ 'b', 0, 2, etBLOB, 0, 0 },
100101
{ 'B', 0, 2, etBLOBSQL, 0, 0 },
101
- { 'w', 0, 2, etWIKISTR, 0, 0 },
102
+ { 'W', 0, 2, etWIKISTR, 0, 0 },
102103
{ 'h', 0, 4, etHTMLIZE, 0, 0 },
103104
{ 'R', 0, 0, etROOT, 0, 0 },
104105
{ 't', 0, 4, etHTTPIZE, 0, 0 }, /* "/" -> "%2F" */
105106
{ 'T', 0, 4, etURLIZE, 0, 0 }, /* "/" unchanged */
107
+ { 'w', 0, 4, etSQLESCAPE3, 0, 0 },
106108
{ 'F', 0, 4, etFOSSILIZE, 0, 0 },
107109
{ 'S', 0, 4, etSTRINGID, 0, 0 },
108110
{ 'c', 0, 0, etCHARX, 0, 0 },
109111
{ 'o', 8, 0, etRADIX, 0, 2 },
110112
{ 'u', 10, 0, etRADIX, 0, 0 },
@@ -661,35 +663,37 @@
661663
length = j;
662664
assert( length==n+cnt+2 );
663665
break;
664666
}
665667
case etSQLESCAPE:
666
- case etSQLESCAPE2: {
668
+ case etSQLESCAPE2:
669
+ case etSQLESCAPE3: {
667670
int i, j, n, ch, isnull;
668671
int needQuote;
669672
int limit = flag_alternateform ? va_arg(ap,int) : -1;
673
+ char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote characters */
670674
char *escarg = va_arg(ap,char*);
671675
isnull = escarg==0;
672676
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
673677
if( limit<0 ) limit = strlen(escarg);
674678
for(i=n=0; i<limit; i++){
675
- if( escarg[i]=='\'' ) n++;
679
+ if( escarg[i]==q ) n++;
676680
}
677681
needQuote = !isnull && xtype==etSQLESCAPE2;
678682
n += i + 1 + needQuote*2;
679683
if( n>etBUFSIZE ){
680684
bufpt = zExtra = fossil_malloc( n );
681685
}else{
682686
bufpt = buf;
683687
}
684688
j = 0;
685
- if( needQuote ) bufpt[j++] = '\'';
689
+ if( needQuote ) bufpt[j++] = q;
686690
for(i=0; i<limit; i++){
687691
bufpt[j++] = ch = escarg[i];
688
- if( ch=='\'' ) bufpt[j++] = ch;
692
+ if( ch==q ) bufpt[j++] = ch;
689693
}
690
- if( needQuote ) bufpt[j++] = '\'';
694
+ if( needQuote ) bufpt[j++] = q;
691695
bufpt[j] = 0;
692696
length = j;
693697
if( precision>=0 && precision<length ) length = precision;
694698
break;
695699
}
696700
--- src/printf.c
+++ src/printf.c
@@ -44,19 +44,20 @@
44 #define etBLOB 11 /* Blob objects. %b */
45 #define etBLOBSQL 12 /* Blob objects quoted for SQL. %B */
46 #define etSQLESCAPE 13 /* Strings with '\'' doubled. %q */
47 #define etSQLESCAPE2 14 /* Strings with '\'' doubled and enclosed in '',
48 NULL pointers replaced by SQL NULL. %Q */
49 #define etPOINTER 15 /* The %p conversion */
50 #define etHTMLIZE 16 /* Make text safe for HTML */
51 #define etHTTPIZE 17 /* Make text safe for HTTP. "/" encoded as %2f */
52 #define etURLIZE 18 /* Make text safe for HTTP. "/" not encoded */
53 #define etFOSSILIZE 19 /* The fossil header encoding format. */
54 #define etPATH 20 /* Path type */
55 #define etWIKISTR 21 /* Timeline comment text rendered from a char*: %w */
 
56 #define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */
57 #define etROOT 24 /* String value of g.zTop: % */
58
59
60 /*
61 ** An "etByte" is an 8-bit unsigned value.
62 */
@@ -96,15 +97,16 @@
96 { 'z', 0, 6, etDYNSTRING, 0, 0 },
97 { 'q', 0, 4, etSQLESCAPE, 0, 0 },
98 { 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
99 { 'b', 0, 2, etBLOB, 0, 0 },
100 { 'B', 0, 2, etBLOBSQL, 0, 0 },
101 { 'w', 0, 2, etWIKISTR, 0, 0 },
102 { 'h', 0, 4, etHTMLIZE, 0, 0 },
103 { 'R', 0, 0, etROOT, 0, 0 },
104 { 't', 0, 4, etHTTPIZE, 0, 0 }, /* "/" -> "%2F" */
105 { 'T', 0, 4, etURLIZE, 0, 0 }, /* "/" unchanged */
 
106 { 'F', 0, 4, etFOSSILIZE, 0, 0 },
107 { 'S', 0, 4, etSTRINGID, 0, 0 },
108 { 'c', 0, 0, etCHARX, 0, 0 },
109 { 'o', 8, 0, etRADIX, 0, 2 },
110 { 'u', 10, 0, etRADIX, 0, 0 },
@@ -661,35 +663,37 @@
661 length = j;
662 assert( length==n+cnt+2 );
663 break;
664 }
665 case etSQLESCAPE:
666 case etSQLESCAPE2: {
 
667 int i, j, n, ch, isnull;
668 int needQuote;
669 int limit = flag_alternateform ? va_arg(ap,int) : -1;
 
670 char *escarg = va_arg(ap,char*);
671 isnull = escarg==0;
672 if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
673 if( limit<0 ) limit = strlen(escarg);
674 for(i=n=0; i<limit; i++){
675 if( escarg[i]=='\'' ) n++;
676 }
677 needQuote = !isnull && xtype==etSQLESCAPE2;
678 n += i + 1 + needQuote*2;
679 if( n>etBUFSIZE ){
680 bufpt = zExtra = fossil_malloc( n );
681 }else{
682 bufpt = buf;
683 }
684 j = 0;
685 if( needQuote ) bufpt[j++] = '\'';
686 for(i=0; i<limit; i++){
687 bufpt[j++] = ch = escarg[i];
688 if( ch=='\'' ) bufpt[j++] = ch;
689 }
690 if( needQuote ) bufpt[j++] = '\'';
691 bufpt[j] = 0;
692 length = j;
693 if( precision>=0 && precision<length ) length = precision;
694 break;
695 }
696
--- src/printf.c
+++ src/printf.c
@@ -44,19 +44,20 @@
44 #define etBLOB 11 /* Blob objects. %b */
45 #define etBLOBSQL 12 /* Blob objects quoted for SQL. %B */
46 #define etSQLESCAPE 13 /* Strings with '\'' doubled. %q */
47 #define etSQLESCAPE2 14 /* Strings with '\'' doubled and enclosed in '',
48 NULL pointers replaced by SQL NULL. %Q */
49 #define etSQLESCAPE3 15 /* Double '"' characters within an indentifier. %w */
50 #define etPOINTER 16 /* The %p conversion */
51 #define etHTMLIZE 17 /* Make text safe for HTML */
52 #define etHTTPIZE 18 /* Make text safe for HTTP. "/" encoded as %2f */
53 #define etURLIZE 19 /* Make text safe for HTTP. "/" not encoded */
54 #define etFOSSILIZE 20 /* The fossil header encoding format. */
55 #define etPATH 21 /* Path type */
56 #define etWIKISTR 22 /* Timeline comment text rendered from a char*: %W */
57 #define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */
58 #define etROOT 24 /* String value of g.zTop: %R */
59
60
61 /*
62 ** An "etByte" is an 8-bit unsigned value.
63 */
@@ -96,15 +97,16 @@
97 { 'z', 0, 6, etDYNSTRING, 0, 0 },
98 { 'q', 0, 4, etSQLESCAPE, 0, 0 },
99 { 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
100 { 'b', 0, 2, etBLOB, 0, 0 },
101 { 'B', 0, 2, etBLOBSQL, 0, 0 },
102 { 'W', 0, 2, etWIKISTR, 0, 0 },
103 { 'h', 0, 4, etHTMLIZE, 0, 0 },
104 { 'R', 0, 0, etROOT, 0, 0 },
105 { 't', 0, 4, etHTTPIZE, 0, 0 }, /* "/" -> "%2F" */
106 { 'T', 0, 4, etURLIZE, 0, 0 }, /* "/" unchanged */
107 { 'w', 0, 4, etSQLESCAPE3, 0, 0 },
108 { 'F', 0, 4, etFOSSILIZE, 0, 0 },
109 { 'S', 0, 4, etSTRINGID, 0, 0 },
110 { 'c', 0, 0, etCHARX, 0, 0 },
111 { 'o', 8, 0, etRADIX, 0, 2 },
112 { 'u', 10, 0, etRADIX, 0, 0 },
@@ -661,35 +663,37 @@
663 length = j;
664 assert( length==n+cnt+2 );
665 break;
666 }
667 case etSQLESCAPE:
668 case etSQLESCAPE2:
669 case etSQLESCAPE3: {
670 int i, j, n, ch, isnull;
671 int needQuote;
672 int limit = flag_alternateform ? va_arg(ap,int) : -1;
673 char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote characters */
674 char *escarg = va_arg(ap,char*);
675 isnull = escarg==0;
676 if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
677 if( limit<0 ) limit = strlen(escarg);
678 for(i=n=0; i<limit; i++){
679 if( escarg[i]==q ) n++;
680 }
681 needQuote = !isnull && xtype==etSQLESCAPE2;
682 n += i + 1 + needQuote*2;
683 if( n>etBUFSIZE ){
684 bufpt = zExtra = fossil_malloc( n );
685 }else{
686 bufpt = buf;
687 }
688 j = 0;
689 if( needQuote ) bufpt[j++] = q;
690 for(i=0; i<limit; i++){
691 bufpt[j++] = ch = escarg[i];
692 if( ch==q ) bufpt[j++] = ch;
693 }
694 if( needQuote ) bufpt[j++] = q;
695 bufpt[j] = 0;
696 length = j;
697 if( precision>=0 && precision<length ) length = precision;
698 break;
699 }
700
+2 -2
--- src/timeline.c
+++ src/timeline.c
@@ -393,14 +393,14 @@
393393
}else if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
394394
Blob truncated;
395395
blob_zero(&truncated);
396396
blob_append(&truncated, blob_buffer(&comment), mxWikiLen);
397397
blob_append(&truncated, "...", 3);
398
- @ <span class="timelineComment">%w(blob_str(&truncated))</span>
398
+ @ <span class="timelineComment">%W(blob_str(&truncated))</span>
399399
blob_reset(&truncated);
400400
}else{
401
- @ <span class="timelineComment">%w(blob_str(&comment))</span>
401
+ @ <span class="timelineComment">%W(blob_str(&comment))</span>
402402
}
403403
blob_reset(&comment);
404404
405405
/* Generate the "user: USERNAME" at the end of the comment, together
406406
** with a hyperlink to another timeline for that user.
407407
--- src/timeline.c
+++ src/timeline.c
@@ -393,14 +393,14 @@
393 }else if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
394 Blob truncated;
395 blob_zero(&truncated);
396 blob_append(&truncated, blob_buffer(&comment), mxWikiLen);
397 blob_append(&truncated, "...", 3);
398 @ <span class="timelineComment">%w(blob_str(&truncated))</span>
399 blob_reset(&truncated);
400 }else{
401 @ <span class="timelineComment">%w(blob_str(&comment))</span>
402 }
403 blob_reset(&comment);
404
405 /* Generate the "user: USERNAME" at the end of the comment, together
406 ** with a hyperlink to another timeline for that user.
407
--- src/timeline.c
+++ src/timeline.c
@@ -393,14 +393,14 @@
393 }else if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
394 Blob truncated;
395 blob_zero(&truncated);
396 blob_append(&truncated, blob_buffer(&comment), mxWikiLen);
397 blob_append(&truncated, "...", 3);
398 @ <span class="timelineComment">%W(blob_str(&truncated))</span>
399 blob_reset(&truncated);
400 }else{
401 @ <span class="timelineComment">%W(blob_str(&comment))</span>
402 }
403 blob_reset(&comment);
404
405 /* Generate the "user: USERNAME" at the end of the comment, together
406 ** with a hyperlink to another timeline for that user.
407

Keyboard Shortcuts

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