Fossil SCM

Refinements to the new hyperlink logic and spider defense.

drh 2012-04-28 08:03 UTC spider-defense
Commit d9c8a7dd73a7718527a8b95eb6971b059ce99636
+2 -2
--- src/attach.c
+++ src/attach.c
@@ -75,13 +75,13 @@
7575
zFilename = &zFilename[i+1];
7676
i = -1;
7777
}
7878
}
7979
if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
80
- zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
80
+ zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
8181
}else{
82
- zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename);
82
+ zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename);
8383
}
8484
@
8585
@ <p><a href="/attachview?%s(zUrlTail)">%h(zFilename)</a>
8686
@ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br />
8787
if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++;
8888
--- src/attach.c
+++ src/attach.c
@@ -75,13 +75,13 @@
75 zFilename = &zFilename[i+1];
76 i = -1;
77 }
78 }
79 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
80 zUrlTail = mprintf("tkt=%s&amp;file=%t", zTarget, zFilename);
81 }else{
82 zUrlTail = mprintf("page=%t&amp;file=%t", zTarget, zFilename);
83 }
84 @
85 @ <p><a href="/attachview?%s(zUrlTail)">%h(zFilename)</a>
86 @ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br />
87 if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++;
88
--- src/attach.c
+++ src/attach.c
@@ -75,13 +75,13 @@
75 zFilename = &zFilename[i+1];
76 i = -1;
77 }
78 }
79 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
80 zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
81 }else{
82 zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename);
83 }
84 @
85 @ <p><a href="/attachview?%s(zUrlTail)">%h(zFilename)</a>
86 @ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br />
87 if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++;
88
+6 -6
--- src/browse.c
+++ src/browse.c
@@ -77,13 +77,13 @@
7777
int i, j;
7878
char *zSep = "";
7979
8080
for(i=0; zPath[i]; i=j){
8181
for(j=i; zPath[j] && zPath[j]!='/'; j++){}
82
- if( zPath[j] && g.perm.History ){
82
+ if( zPath[j] && g.perm.Hyperlink ){
8383
if( zCI ){
84
- char *zLink = href("%R/dir?ci=%S&amp;name=%#T", zCI, j, zPath);
84
+ char *zLink = href("%R/dir?ci=%S&name=%#T", zCI, j, zPath);
8585
blob_appendf(pOut, "%s%z%#h</a>",
8686
zSep, zLink, j-i, &zPath[i]);
8787
}else{
8888
char *zLink = href("%R/dir?name=%#T", j, zPath);
8989
blob_appendf(pOut, "%s%z%#h</a>",
@@ -120,11 +120,11 @@
120120
Blob dirname;
121121
Manifest *pM = 0;
122122
const char *zSubdirLink;
123123
124124
login_check_credentials();
125
- if( !g.perm.History ){ login_needed(); return; }
125
+ if( !g.perm.Hyperlink ){ login_needed(); return; }
126126
while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
127127
style_header("File List");
128128
sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
129129
pathelementFunc, 0, 0);
130130
@@ -159,11 +159,11 @@
159159
char zShort[20];
160160
memcpy(zShort, zUuid, 10);
161161
zShort[10] = 0;
162162
@ <h2>Files of check-in [%z(href("vinfo?name=%T",zUuid))%s(zShort)</a>]
163163
@ %s(blob_str(&dirname))</h2>
164
- zSubdirLink = mprintf("%R/dir?ci=%S&amp;name=%T", zUuid, zPrefix);
164
+ zSubdirLink = mprintf("%R/dir?ci=%S&name=%T", zUuid, zPrefix);
165165
if( zD ){
166166
style_submenu_element("Top", "Top", "%R/dir?ci=%S", zUuid);
167167
style_submenu_element("All", "All", "%R/dir?name=%t", zD);
168168
}else{
169169
style_submenu_element("All", "All", "%R/dir");
@@ -176,13 +176,13 @@
176176
"SELECT 1 FROM tagxref WHERE tagid=%d AND value='trunk'",
177177
TAG_BRANCH);
178178
zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
179179
if( zD ){
180180
style_submenu_element("Top", "Top", "%R/dir");
181
- style_submenu_element("Tip", "Tip", "%R/dir?name=%t&amp;ci=tip", zD);
181
+ style_submenu_element("Tip", "Tip", "%R/dir?name=%t&ci=tip", zD);
182182
if( hasTrunk ){
183
- style_submenu_element("Trunk", "Trunk", "%R/dir?name=%t&amp;ci=trunk",
183
+ style_submenu_element("Trunk", "Trunk", "%R/dir?name=%t&ci=trunk",
184184
zD);
185185
}
186186
}else{
187187
style_submenu_element("Tip", "Tip", "%R/dir?ci=tip");
188188
if( hasTrunk ){
189189
--- src/browse.c
+++ src/browse.c
@@ -77,13 +77,13 @@
77 int i, j;
78 char *zSep = "";
79
80 for(i=0; zPath[i]; i=j){
81 for(j=i; zPath[j] && zPath[j]!='/'; j++){}
82 if( zPath[j] && g.perm.History ){
83 if( zCI ){
84 char *zLink = href("%R/dir?ci=%S&amp;name=%#T", zCI, j, zPath);
85 blob_appendf(pOut, "%s%z%#h</a>",
86 zSep, zLink, j-i, &zPath[i]);
87 }else{
88 char *zLink = href("%R/dir?name=%#T", j, zPath);
89 blob_appendf(pOut, "%s%z%#h</a>",
@@ -120,11 +120,11 @@
120 Blob dirname;
121 Manifest *pM = 0;
122 const char *zSubdirLink;
123
124 login_check_credentials();
125 if( !g.perm.History ){ login_needed(); return; }
126 while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
127 style_header("File List");
128 sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
129 pathelementFunc, 0, 0);
130
@@ -159,11 +159,11 @@
159 char zShort[20];
160 memcpy(zShort, zUuid, 10);
161 zShort[10] = 0;
162 @ <h2>Files of check-in [%z(href("vinfo?name=%T",zUuid))%s(zShort)</a>]
163 @ %s(blob_str(&dirname))</h2>
164 zSubdirLink = mprintf("%R/dir?ci=%S&amp;name=%T", zUuid, zPrefix);
165 if( zD ){
166 style_submenu_element("Top", "Top", "%R/dir?ci=%S", zUuid);
167 style_submenu_element("All", "All", "%R/dir?name=%t", zD);
168 }else{
169 style_submenu_element("All", "All", "%R/dir");
@@ -176,13 +176,13 @@
176 "SELECT 1 FROM tagxref WHERE tagid=%d AND value='trunk'",
177 TAG_BRANCH);
178 zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
179 if( zD ){
180 style_submenu_element("Top", "Top", "%R/dir");
181 style_submenu_element("Tip", "Tip", "%R/dir?name=%t&amp;ci=tip", zD);
182 if( hasTrunk ){
183 style_submenu_element("Trunk", "Trunk", "%R/dir?name=%t&amp;ci=trunk",
184 zD);
185 }
186 }else{
187 style_submenu_element("Tip", "Tip", "%R/dir?ci=tip");
188 if( hasTrunk ){
189
--- src/browse.c
+++ src/browse.c
@@ -77,13 +77,13 @@
77 int i, j;
78 char *zSep = "";
79
80 for(i=0; zPath[i]; i=j){
81 for(j=i; zPath[j] && zPath[j]!='/'; j++){}
82 if( zPath[j] && g.perm.Hyperlink ){
83 if( zCI ){
84 char *zLink = href("%R/dir?ci=%S&name=%#T", zCI, j, zPath);
85 blob_appendf(pOut, "%s%z%#h</a>",
86 zSep, zLink, j-i, &zPath[i]);
87 }else{
88 char *zLink = href("%R/dir?name=%#T", j, zPath);
89 blob_appendf(pOut, "%s%z%#h</a>",
@@ -120,11 +120,11 @@
120 Blob dirname;
121 Manifest *pM = 0;
122 const char *zSubdirLink;
123
124 login_check_credentials();
125 if( !g.perm.Hyperlink ){ login_needed(); return; }
126 while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; }
127 style_header("File List");
128 sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
129 pathelementFunc, 0, 0);
130
@@ -159,11 +159,11 @@
159 char zShort[20];
160 memcpy(zShort, zUuid, 10);
161 zShort[10] = 0;
162 @ <h2>Files of check-in [%z(href("vinfo?name=%T",zUuid))%s(zShort)</a>]
163 @ %s(blob_str(&dirname))</h2>
164 zSubdirLink = mprintf("%R/dir?ci=%S&name=%T", zUuid, zPrefix);
165 if( zD ){
166 style_submenu_element("Top", "Top", "%R/dir?ci=%S", zUuid);
167 style_submenu_element("All", "All", "%R/dir?name=%t", zD);
168 }else{
169 style_submenu_element("All", "All", "%R/dir");
@@ -176,13 +176,13 @@
176 "SELECT 1 FROM tagxref WHERE tagid=%d AND value='trunk'",
177 TAG_BRANCH);
178 zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
179 if( zD ){
180 style_submenu_element("Top", "Top", "%R/dir");
181 style_submenu_element("Tip", "Tip", "%R/dir?name=%t&ci=tip", zD);
182 if( hasTrunk ){
183 style_submenu_element("Trunk", "Trunk", "%R/dir?name=%t&ci=trunk",
184 zD);
185 }
186 }else{
187 style_submenu_element("Tip", "Tip", "%R/dir?ci=tip");
188 if( hasTrunk ){
189
+1 -1
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -541,11 +541,11 @@
541541
}
542542
}
543543
544544
/*
545545
** WEBPAGE: vpatch
546
-** URL vpatch?from=UUID&amp;to=UUID
546
+** URL vpatch?from=UUID&to=UUID
547547
*/
548548
void vpatch_page(void){
549549
const char *zFrom = P("from");
550550
const char *zTo = P("to");
551551
login_check_credentials();
552552
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -541,11 +541,11 @@
541 }
542 }
543
544 /*
545 ** WEBPAGE: vpatch
546 ** URL vpatch?from=UUID&amp;to=UUID
547 */
548 void vpatch_page(void){
549 const char *zFrom = P("from");
550 const char *zTo = P("to");
551 login_check_credentials();
552
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -541,11 +541,11 @@
541 }
542 }
543
544 /*
545 ** WEBPAGE: vpatch
546 ** URL vpatch?from=UUID&to=UUID
547 */
548 void vpatch_page(void){
549 const char *zFrom = P("from");
550 const char *zTo = P("to");
551 login_check_credentials();
552
+4 -4
--- src/event.c
+++ src/event.c
@@ -125,31 +125,31 @@
125125
zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
126126
style_submenu_element("Context", "Context", "%s/timeline?c=%T",
127127
g.zTop, zETime);
128128
if( g.perm.Hyperlink ){
129129
if( showDetail ){
130
- style_submenu_element("Plain", "Plain", "%s/event?name=%s&amp;aid=%s",
130
+ style_submenu_element("Plain", "Plain", "%s/event?name=%s&aid=%s",
131131
g.zTop, zEventId, zUuid);
132132
if( nextRid ){
133133
char *zNext;
134134
zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid);
135135
style_submenu_element("Next", "Next",
136
- "%s/event?name=%s&amp;aid=%s&amp;detail=1",
136
+ "%s/event?name=%s&aid=%s&detail=1",
137137
g.zTop, zEventId, zNext);
138138
free(zNext);
139139
}
140140
if( prevRid ){
141141
char *zPrev;
142142
zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid);
143143
style_submenu_element("Prev", "Prev",
144
- "%s/event?name=%s&amp;aid=%s&amp;detail=1",
144
+ "%s/event?name=%s&aid=%s&detail=1",
145145
g.zTop, zEventId, zPrev);
146146
free(zPrev);
147147
}
148148
}else{
149149
style_submenu_element("Detail", "Detail",
150
- "%s/event?name=%s&amp;aid=%s&amp;detail=1",
150
+ "%s/event?name=%s&aid=%s&detail=1",
151151
g.zTop, zEventId, zUuid);
152152
}
153153
}
154154
155155
if( showDetail && g.perm.Hyperlink ){
156156
--- src/event.c
+++ src/event.c
@@ -125,31 +125,31 @@
125 zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
126 style_submenu_element("Context", "Context", "%s/timeline?c=%T",
127 g.zTop, zETime);
128 if( g.perm.Hyperlink ){
129 if( showDetail ){
130 style_submenu_element("Plain", "Plain", "%s/event?name=%s&amp;aid=%s",
131 g.zTop, zEventId, zUuid);
132 if( nextRid ){
133 char *zNext;
134 zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid);
135 style_submenu_element("Next", "Next",
136 "%s/event?name=%s&amp;aid=%s&amp;detail=1",
137 g.zTop, zEventId, zNext);
138 free(zNext);
139 }
140 if( prevRid ){
141 char *zPrev;
142 zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid);
143 style_submenu_element("Prev", "Prev",
144 "%s/event?name=%s&amp;aid=%s&amp;detail=1",
145 g.zTop, zEventId, zPrev);
146 free(zPrev);
147 }
148 }else{
149 style_submenu_element("Detail", "Detail",
150 "%s/event?name=%s&amp;aid=%s&amp;detail=1",
151 g.zTop, zEventId, zUuid);
152 }
153 }
154
155 if( showDetail && g.perm.Hyperlink ){
156
--- src/event.c
+++ src/event.c
@@ -125,31 +125,31 @@
125 zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
126 style_submenu_element("Context", "Context", "%s/timeline?c=%T",
127 g.zTop, zETime);
128 if( g.perm.Hyperlink ){
129 if( showDetail ){
130 style_submenu_element("Plain", "Plain", "%s/event?name=%s&aid=%s",
131 g.zTop, zEventId, zUuid);
132 if( nextRid ){
133 char *zNext;
134 zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid);
135 style_submenu_element("Next", "Next",
136 "%s/event?name=%s&aid=%s&detail=1",
137 g.zTop, zEventId, zNext);
138 free(zNext);
139 }
140 if( prevRid ){
141 char *zPrev;
142 zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid);
143 style_submenu_element("Prev", "Prev",
144 "%s/event?name=%s&aid=%s&detail=1",
145 g.zTop, zEventId, zPrev);
146 free(zPrev);
147 }
148 }else{
149 style_submenu_element("Detail", "Detail",
150 "%s/event?name=%s&aid=%s&detail=1",
151 g.zTop, zEventId, zUuid);
152 }
153 }
154
155 if( showDetail && g.perm.Hyperlink ){
156
+3 -3
--- src/finfo.c
+++ src/finfo.c
@@ -323,16 +323,16 @@
323323
}
324324
hyperlink_to_uuid(zShortCkin);
325325
@ %h(zCom) (user:
326326
hyperlink_to_user(zUser, zDate, "");
327327
@ branch: %h(zBr))
328
- if( g.perm.History && zUuid ){
328
+ if( g.perm.Hyperlink && zUuid ){
329329
const char *z = zFilename;
330330
if( fpid ){
331
- @ %z(href("%R/fdiff?v1=%s&amp;v2=%s",zPUuid,zUuid))[diff]</a>
331
+ @ %z(href("%R/fdiff?v1=%s&v2=%s",zPUuid,zUuid))[diff]</a>
332332
}
333
- @ %z(href("%R/annotate?checkin=%S&amp;filename=%h",zCkin,z))
333
+ @ %z(href("%R/annotate?checkin=%S&filename=%h",zCkin,z))
334334
@ [annotate]</a>
335335
}
336336
@ </td></tr>
337337
}
338338
db_finalize(&q);
339339
--- src/finfo.c
+++ src/finfo.c
@@ -323,16 +323,16 @@
323 }
324 hyperlink_to_uuid(zShortCkin);
325 @ %h(zCom) (user:
326 hyperlink_to_user(zUser, zDate, "");
327 @ branch: %h(zBr))
328 if( g.perm.History && zUuid ){
329 const char *z = zFilename;
330 if( fpid ){
331 @ %z(href("%R/fdiff?v1=%s&amp;v2=%s",zPUuid,zUuid))[diff]</a>
332 }
333 @ %z(href("%R/annotate?checkin=%S&amp;filename=%h",zCkin,z))
334 @ [annotate]</a>
335 }
336 @ </td></tr>
337 }
338 db_finalize(&q);
339
--- src/finfo.c
+++ src/finfo.c
@@ -323,16 +323,16 @@
323 }
324 hyperlink_to_uuid(zShortCkin);
325 @ %h(zCom) (user:
326 hyperlink_to_user(zUser, zDate, "");
327 @ branch: %h(zBr))
328 if( g.perm.Hyperlink && zUuid ){
329 const char *z = zFilename;
330 if( fpid ){
331 @ %z(href("%R/fdiff?v1=%s&v2=%s",zPUuid,zUuid))[diff]</a>
332 }
333 @ %z(href("%R/annotate?checkin=%S&filename=%h",zCkin,z))
334 @ [annotate]</a>
335 }
336 @ </td></tr>
337 }
338 db_finalize(&q);
339
+7 -7
--- src/info.c
+++ src/info.c
@@ -378,11 +378,11 @@
378378
@ <pre style="white-space:pre;">
379379
append_diff(zOld, zNew, diffFlags);
380380
@ </pre>
381381
}else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
382382
@ &nbsp;&nbsp;
383
- @ %z(href("%R/fdiff?v1=%S&amp;v2=%S",zOld,zNew))[diff]</a>
383
+ @ %z(href("%R/fdiff?v1=%S&v2=%S",zOld,zNew))[diff]</a>
384384
}
385385
@ </p>
386386
}
387387
}
388388
@@ -622,11 +622,11 @@
622622
@ show&nbsp;unified&nbsp;diffs</a>
623623
@ %z(xhref("class='button'","%R/vinfo/%T?sbs=1",zName))
624624
@ show&nbsp;side-by-side&nbsp;diffs</a>
625625
}
626626
}
627
- @ %z(xhref("class='button'","%R/vpatch?from=%S&amp;to=%S",zParent,zUuid))
627
+ @ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid))
628628
@ patch</a></div>
629629
db_prepare(&q,
630630
"SELECT name,"
631631
" mperm,"
632632
" (SELECT uuid FROM blob WHERE rid=mlink.pid),"
@@ -792,11 +792,11 @@
792792
}
793793
794794
795795
/*
796796
** WEBPAGE: vdiff
797
-** URL: /vdiff?from=UUID&amp;to=UUID&amp;detail=BOOLEAN;sbs=BOOLEAN
797
+** URL: /vdiff?from=UUID&to=UUID&detail=BOOLEAN;sbs=BOOLEAN
798798
**
799799
** Show all differences between two checkins.
800800
*/
801801
void vdiff_page(void){
802802
int ridFrom, ridTo;
@@ -1258,11 +1258,11 @@
12581258
if( !g.perm.Read ){ login_needed(); return; }
12591259
if( rid==0 ) fossil_redirect_home();
12601260
if( g.perm.Admin ){
12611261
const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
12621262
if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1263
- style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
1263
+ style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1",
12641264
g.zTop, zUuid);
12651265
}else{
12661266
style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
12671267
g.zTop, zUuid);
12681268
}
@@ -1405,11 +1405,11 @@
14051405
if( !g.perm.Read ){ login_needed(); return; }
14061406
if( rid==0 ) fossil_redirect_home();
14071407
if( g.perm.Admin ){
14081408
const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
14091409
if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1410
- style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
1410
+ style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1",
14111411
g.zTop, zUuid);
14121412
}else{
14131413
style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
14141414
g.zTop, zUuid);
14151415
}
@@ -1464,11 +1464,11 @@
14641464
@ <pre>
14651465
@ %h(z)
14661466
@ </pre>
14671467
}
14681468
}else if( strncmp(zMime, "image/", 6)==0 ){
1469
- @ <img src="%s(g.zTop)/raw?name=%s(zUuid)&amp;m=%s(zMime)"></img>
1469
+ @ <img src="%s(g.zTop)/raw?name=%s(zUuid)&m=%s(zMime)"></img>
14701470
}else{
14711471
@ <i>(file is %d(blob_size(&content)) bytes of binary data)</i>
14721472
}
14731473
@ </blockquote>
14741474
}
@@ -1493,11 +1493,11 @@
14931493
rid = name_to_rid_www("name");
14941494
if( rid==0 ){ fossil_redirect_home(); }
14951495
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
14961496
if( g.perm.Admin ){
14971497
if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1498
- style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
1498
+ style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1",
14991499
g.zTop, zUuid);
15001500
}else{
15011501
style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
15021502
g.zTop, zUuid);
15031503
}
15041504
--- src/info.c
+++ src/info.c
@@ -378,11 +378,11 @@
378 @ <pre style="white-space:pre;">
379 append_diff(zOld, zNew, diffFlags);
380 @ </pre>
381 }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
382 @ &nbsp;&nbsp;
383 @ %z(href("%R/fdiff?v1=%S&amp;v2=%S",zOld,zNew))[diff]</a>
384 }
385 @ </p>
386 }
387 }
388
@@ -622,11 +622,11 @@
622 @ show&nbsp;unified&nbsp;diffs</a>
623 @ %z(xhref("class='button'","%R/vinfo/%T?sbs=1",zName))
624 @ show&nbsp;side-by-side&nbsp;diffs</a>
625 }
626 }
627 @ %z(xhref("class='button'","%R/vpatch?from=%S&amp;to=%S",zParent,zUuid))
628 @ patch</a></div>
629 db_prepare(&q,
630 "SELECT name,"
631 " mperm,"
632 " (SELECT uuid FROM blob WHERE rid=mlink.pid),"
@@ -792,11 +792,11 @@
792 }
793
794
795 /*
796 ** WEBPAGE: vdiff
797 ** URL: /vdiff?from=UUID&amp;to=UUID&amp;detail=BOOLEAN;sbs=BOOLEAN
798 **
799 ** Show all differences between two checkins.
800 */
801 void vdiff_page(void){
802 int ridFrom, ridTo;
@@ -1258,11 +1258,11 @@
1258 if( !g.perm.Read ){ login_needed(); return; }
1259 if( rid==0 ) fossil_redirect_home();
1260 if( g.perm.Admin ){
1261 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1262 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1263 style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
1264 g.zTop, zUuid);
1265 }else{
1266 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
1267 g.zTop, zUuid);
1268 }
@@ -1405,11 +1405,11 @@
1405 if( !g.perm.Read ){ login_needed(); return; }
1406 if( rid==0 ) fossil_redirect_home();
1407 if( g.perm.Admin ){
1408 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1409 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1410 style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
1411 g.zTop, zUuid);
1412 }else{
1413 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
1414 g.zTop, zUuid);
1415 }
@@ -1464,11 +1464,11 @@
1464 @ <pre>
1465 @ %h(z)
1466 @ </pre>
1467 }
1468 }else if( strncmp(zMime, "image/", 6)==0 ){
1469 @ <img src="%s(g.zTop)/raw?name=%s(zUuid)&amp;m=%s(zMime)"></img>
1470 }else{
1471 @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i>
1472 }
1473 @ </blockquote>
1474 }
@@ -1493,11 +1493,11 @@
1493 rid = name_to_rid_www("name");
1494 if( rid==0 ){ fossil_redirect_home(); }
1495 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1496 if( g.perm.Admin ){
1497 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1498 style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
1499 g.zTop, zUuid);
1500 }else{
1501 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
1502 g.zTop, zUuid);
1503 }
1504
--- src/info.c
+++ src/info.c
@@ -378,11 +378,11 @@
378 @ <pre style="white-space:pre;">
379 append_diff(zOld, zNew, diffFlags);
380 @ </pre>
381 }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
382 @ &nbsp;&nbsp;
383 @ %z(href("%R/fdiff?v1=%S&v2=%S",zOld,zNew))[diff]</a>
384 }
385 @ </p>
386 }
387 }
388
@@ -622,11 +622,11 @@
622 @ show&nbsp;unified&nbsp;diffs</a>
623 @ %z(xhref("class='button'","%R/vinfo/%T?sbs=1",zName))
624 @ show&nbsp;side-by-side&nbsp;diffs</a>
625 }
626 }
627 @ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid))
628 @ patch</a></div>
629 db_prepare(&q,
630 "SELECT name,"
631 " mperm,"
632 " (SELECT uuid FROM blob WHERE rid=mlink.pid),"
@@ -792,11 +792,11 @@
792 }
793
794
795 /*
796 ** WEBPAGE: vdiff
797 ** URL: /vdiff?from=UUID&to=UUID&detail=BOOLEAN;sbs=BOOLEAN
798 **
799 ** Show all differences between two checkins.
800 */
801 void vdiff_page(void){
802 int ridFrom, ridTo;
@@ -1258,11 +1258,11 @@
1258 if( !g.perm.Read ){ login_needed(); return; }
1259 if( rid==0 ) fossil_redirect_home();
1260 if( g.perm.Admin ){
1261 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1262 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1263 style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1",
1264 g.zTop, zUuid);
1265 }else{
1266 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
1267 g.zTop, zUuid);
1268 }
@@ -1405,11 +1405,11 @@
1405 if( !g.perm.Read ){ login_needed(); return; }
1406 if( rid==0 ) fossil_redirect_home();
1407 if( g.perm.Admin ){
1408 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1409 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1410 style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1",
1411 g.zTop, zUuid);
1412 }else{
1413 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
1414 g.zTop, zUuid);
1415 }
@@ -1464,11 +1464,11 @@
1464 @ <pre>
1465 @ %h(z)
1466 @ </pre>
1467 }
1468 }else if( strncmp(zMime, "image/", 6)==0 ){
1469 @ <img src="%s(g.zTop)/raw?name=%s(zUuid)&m=%s(zMime)"></img>
1470 }else{
1471 @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i>
1472 }
1473 @ </blockquote>
1474 }
@@ -1493,11 +1493,11 @@
1493 rid = name_to_rid_www("name");
1494 if( rid==0 ){ fossil_redirect_home(); }
1495 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1496 if( g.perm.Admin ){
1497 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1498 style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1",
1499 g.zTop, zUuid);
1500 }else{
1501 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
1502 g.zTop, zUuid);
1503 }
1504
+1 -1
--- src/json_dir.c
+++ src/json_dir.c
@@ -66,11 +66,11 @@
6666
char * zUuid = NULL;
6767
char const * zCI = NULL;
6868
Manifest * pM = NULL;
6969
Stmt q = empty_Stmt;
7070
int rid = 0;
71
- if( !g.perm.History ){
71
+ if( !g.perm.Hyperlink ){
7272
json_set_err(FSL_JSON_E_DENIED, "Requires 'h' permissions.");
7373
return NULL;
7474
}
7575
zCI = json_find_option_cstr("checkin",NULL,"ci" );
7676
7777
--- src/json_dir.c
+++ src/json_dir.c
@@ -66,11 +66,11 @@
66 char * zUuid = NULL;
67 char const * zCI = NULL;
68 Manifest * pM = NULL;
69 Stmt q = empty_Stmt;
70 int rid = 0;
71 if( !g.perm.History ){
72 json_set_err(FSL_JSON_E_DENIED, "Requires 'h' permissions.");
73 return NULL;
74 }
75 zCI = json_find_option_cstr("checkin",NULL,"ci" );
76
77
--- src/json_dir.c
+++ src/json_dir.c
@@ -66,11 +66,11 @@
66 char * zUuid = NULL;
67 char const * zCI = NULL;
68 Manifest * pM = NULL;
69 Stmt q = empty_Stmt;
70 int rid = 0;
71 if( !g.perm.Hyperlink ){
72 json_set_err(FSL_JSON_E_DENIED, "Requires 'h' permissions.");
73 return NULL;
74 }
75 zCI = json_find_option_cstr("checkin",NULL,"ci" );
76
77
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -53,11 +53,11 @@
5353
#if 0
5454
/* The original timeline code does not require 'h' access,
5555
but it arguably should. For JSON mode i think one could argue
5656
that History permissions are required.
5757
*/
58
- if(! g.perm.History && !g.perm.Read ){
58
+ if(! g.perm.Hyperlink && !g.perm.Read ){
5959
json_set_err(FSL_JSON_E_DENIED, "Timeline requires 'h' or 'o' access.");
6060
return NULL;
6161
}
6262
#endif
6363
return json_page_dispatch_helper(&JsonPageDefs_Timeline[0]);
@@ -426,11 +426,11 @@
426426
int check = 0;
427427
char showFiles = -1/*magic number*/;
428428
Stmt q = empty_Stmt;
429429
char warnRowToJsonFailed = 0;
430430
Blob sql = empty_blob;
431
- if( !g.perm.History ){
431
+ if( !g.perm.Hyperlink ){
432432
/* Reminder to self: HTML impl requires 'o' (Read)
433433
rights.
434434
*/
435435
json_set_err( FSL_JSON_E_DENIED, "Checkin timeline requires 'h' access." );
436436
return NULL;
437437
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -53,11 +53,11 @@
53 #if 0
54 /* The original timeline code does not require 'h' access,
55 but it arguably should. For JSON mode i think one could argue
56 that History permissions are required.
57 */
58 if(! g.perm.History && !g.perm.Read ){
59 json_set_err(FSL_JSON_E_DENIED, "Timeline requires 'h' or 'o' access.");
60 return NULL;
61 }
62 #endif
63 return json_page_dispatch_helper(&JsonPageDefs_Timeline[0]);
@@ -426,11 +426,11 @@
426 int check = 0;
427 char showFiles = -1/*magic number*/;
428 Stmt q = empty_Stmt;
429 char warnRowToJsonFailed = 0;
430 Blob sql = empty_blob;
431 if( !g.perm.History ){
432 /* Reminder to self: HTML impl requires 'o' (Read)
433 rights.
434 */
435 json_set_err( FSL_JSON_E_DENIED, "Checkin timeline requires 'h' access." );
436 return NULL;
437
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -53,11 +53,11 @@
53 #if 0
54 /* The original timeline code does not require 'h' access,
55 but it arguably should. For JSON mode i think one could argue
56 that History permissions are required.
57 */
58 if(! g.perm.Hyperlink && !g.perm.Read ){
59 json_set_err(FSL_JSON_E_DENIED, "Timeline requires 'h' or 'o' access.");
60 return NULL;
61 }
62 #endif
63 return json_page_dispatch_helper(&JsonPageDefs_Timeline[0]);
@@ -426,11 +426,11 @@
426 int check = 0;
427 char showFiles = -1/*magic number*/;
428 Stmt q = empty_Stmt;
429 char warnRowToJsonFailed = 0;
430 Blob sql = empty_blob;
431 if( !g.perm.Hyperlink ){
432 /* Reminder to self: HTML impl requires 'o' (Read)
433 rights.
434 */
435 json_set_err( FSL_JSON_E_DENIED, "Checkin timeline requires 'h' access." );
436 return NULL;
437
+1 -1
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -492,11 +492,11 @@
492492
Manifest * pW1 = NULL, *pW2 = NULL;
493493
Blob w1 = empty_blob, w2 = empty_blob, d = empty_blob;
494494
char const * zErrTag = NULL;
495495
int diffFlags;
496496
char * zUuid = NULL;
497
- if( !g.perm.History ){
497
+ if( !g.perm.Hyperlink ){
498498
json_set_err(FSL_JSON_E_DENIED,
499499
"Requires 'h' permissions.");
500500
return NULL;
501501
}
502502
503503
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -492,11 +492,11 @@
492 Manifest * pW1 = NULL, *pW2 = NULL;
493 Blob w1 = empty_blob, w2 = empty_blob, d = empty_blob;
494 char const * zErrTag = NULL;
495 int diffFlags;
496 char * zUuid = NULL;
497 if( !g.perm.History ){
498 json_set_err(FSL_JSON_E_DENIED,
499 "Requires 'h' permissions.");
500 return NULL;
501 }
502
503
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -492,11 +492,11 @@
492 Manifest * pW1 = NULL, *pW2 = NULL;
493 Blob w1 = empty_blob, w2 = empty_blob, d = empty_blob;
494 char const * zErrTag = NULL;
495 int diffFlags;
496 char * zUuid = NULL;
497 if( !g.perm.Hyperlink ){
498 json_set_err(FSL_JSON_E_DENIED,
499 "Requires 'h' permissions.");
500 return NULL;
501 }
502
503
+15 -16
--- src/login.c
+++ src/login.c
@@ -562,11 +562,11 @@
562562
redirect_to_g();
563563
}
564564
}
565565
style_header("Login/Logout");
566566
@ %s(zErrMsg)
567
- if( zGoto ){
567
+ if( zGoto && P("anon")==0 ){
568568
@ <p>A login is required for <a href="%h(zGoto)">%h(zGoto)</a>.</p>
569569
}
570570
@ <form action="login" method="post">
571571
if( zGoto ){
572572
@ <input type="hidden" name="g" value="%h(zGoto)" />
@@ -911,14 +911,15 @@
911911
}
912912
913913
/* Set the capabilities */
914914
login_replace_capabilities(zCap, 0);
915915
login_set_anon_nobody_capabilities();
916
- if( zCap[0] && !g.perm.History && !g.perm.Link
916
+ if( zCap[0] && !g.perm.Hyperlink
917917
&& db_get_boolean("auto-enable-hyperlinks",1)
918918
&& isHuman(P("HTTP_USER_AGENT")) ){
919
- g.perm.History = 1;
919
+ g.perm.Hyperlink = 1;
920
+ g.javascriptHyperlink = 1;
920921
}
921922
922923
/* If the public-pages glob pattern is defined and REQUEST_URI matches
923924
** one of the globs in public-pages, then also add in all default-perms
924925
** permissions.
@@ -974,22 +975,21 @@
974975
}
975976
for(i=0; zCap[i]; i++){
976977
switch( zCap[i] ){
977978
case 's': g.perm.Setup = 1; /* Fall thru into Admin */
978979
case 'a': g.perm.Admin = g.perm.RdTkt = g.perm.WrTkt = g.perm.Zip =
979
- g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki =
980
- g.perm.ApndWiki = g.perm.History = g.perm.Clone =
981
- g.perm.NewTkt = g.perm.Password = g.perm.RdAddr =
982
- g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt = 1;
983
- /* Fall thru into Read/Write */
980
+ g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki =
981
+ g.perm.ApndWiki = g.perm.Hyperlink = g.perm.Clone =
982
+ g.perm.NewTkt = g.perm.Password = g.perm.RdAddr =
983
+ g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt = 1;
984
+ /* Fall thru into Read/Write */
984985
case 'i': g.perm.Read = g.perm.Write = 1; break;
985986
case 'o': g.perm.Read = 1; break;
986987
case 'z': g.perm.Zip = 1; break;
987988
988989
case 'd': g.perm.Delete = 1; break;
989
- case 'h': g.perm.History = g.perm.Hyperlink = 1; break;
990
- case 'l': g.perm.Link = g.perm.Hyperlink = 1; break;
990
+ case 'h': g.perm.Hyperlink = 1; break;
991991
case 'g': g.perm.Clone = 1; break;
992992
case 'p': g.perm.Password = 1; break;
993993
994994
case 'j': g.perm.RdWiki = 1; break;
995995
case 'k': g.perm.WrWiki = g.perm.RdWiki = g.perm.ApndWiki =1; break;
@@ -1055,15 +1055,14 @@
10551055
case 'c': rc = g.perm.ApndTkt; break;
10561056
case 'd': rc = g.perm.Delete; break;
10571057
case 'e': rc = g.perm.RdAddr; break;
10581058
case 'f': rc = g.perm.NewWiki; break;
10591059
case 'g': rc = g.perm.Clone; break;
1060
- case 'h': rc = g.perm.History; break;
1060
+ case 'h': rc = g.perm.Hyperlink; break;
10611061
case 'i': rc = g.perm.Write; break;
10621062
case 'j': rc = g.perm.RdWiki; break;
10631063
case 'k': rc = g.perm.WrWiki; break;
1064
- case 'l': rc = g.perm.Link; break;
10651064
case 'm': rc = g.perm.ApndWiki; break;
10661065
case 'n': rc = g.perm.NewTkt; break;
10671066
case 'o': rc = g.perm.Read; break;
10681067
case 'p': rc = g.perm.Password; break;
10691068
/* case 'q': */
@@ -1131,23 +1130,23 @@
11311130
assert(0);
11321131
}
11331132
}
11341133
11351134
/*
1136
-** Call this routine if the user lacks okHistory permission. If
1137
-** the anonymous user has okHistory permission, then paint a mesage
1135
+** Call this routine if the user lacks g.perm.Hyperlink permission. If
1136
+** the anonymous user has Hyperlink permission, then paint a mesage
11381137
** to inform the user that much more information is available by
11391138
** logging in as anonymous.
11401139
*/
11411140
void login_anonymous_available(void){
1142
- if( !g.perm.History && !g.perm.Link &&
1141
+ if( !g.perm.Hyperlink &&
11431142
db_exists("SELECT 1 FROM user"
11441143
" WHERE login='anonymous'"
11451144
" AND cap LIKE '%%h%%'") ){
11461145
const char *zUrl = PD("REQUEST_URI", "index");
11471146
@ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
1148
- @ Use <a href="%s(g.zTop)/login?anon=1&amp;g=%T(zUrl)">anonymous login</a>
1147
+ @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a>
11491148
@ to enable hyperlinks.</p>
11501149
}
11511150
}
11521151
11531152
/*
11541153
--- src/login.c
+++ src/login.c
@@ -562,11 +562,11 @@
562 redirect_to_g();
563 }
564 }
565 style_header("Login/Logout");
566 @ %s(zErrMsg)
567 if( zGoto ){
568 @ <p>A login is required for <a href="%h(zGoto)">%h(zGoto)</a>.</p>
569 }
570 @ <form action="login" method="post">
571 if( zGoto ){
572 @ <input type="hidden" name="g" value="%h(zGoto)" />
@@ -911,14 +911,15 @@
911 }
912
913 /* Set the capabilities */
914 login_replace_capabilities(zCap, 0);
915 login_set_anon_nobody_capabilities();
916 if( zCap[0] && !g.perm.History && !g.perm.Link
917 && db_get_boolean("auto-enable-hyperlinks",1)
918 && isHuman(P("HTTP_USER_AGENT")) ){
919 g.perm.History = 1;
 
920 }
921
922 /* If the public-pages glob pattern is defined and REQUEST_URI matches
923 ** one of the globs in public-pages, then also add in all default-perms
924 ** permissions.
@@ -974,22 +975,21 @@
974 }
975 for(i=0; zCap[i]; i++){
976 switch( zCap[i] ){
977 case 's': g.perm.Setup = 1; /* Fall thru into Admin */
978 case 'a': g.perm.Admin = g.perm.RdTkt = g.perm.WrTkt = g.perm.Zip =
979 g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki =
980 g.perm.ApndWiki = g.perm.History = g.perm.Clone =
981 g.perm.NewTkt = g.perm.Password = g.perm.RdAddr =
982 g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt = 1;
983 /* Fall thru into Read/Write */
984 case 'i': g.perm.Read = g.perm.Write = 1; break;
985 case 'o': g.perm.Read = 1; break;
986 case 'z': g.perm.Zip = 1; break;
987
988 case 'd': g.perm.Delete = 1; break;
989 case 'h': g.perm.History = g.perm.Hyperlink = 1; break;
990 case 'l': g.perm.Link = g.perm.Hyperlink = 1; break;
991 case 'g': g.perm.Clone = 1; break;
992 case 'p': g.perm.Password = 1; break;
993
994 case 'j': g.perm.RdWiki = 1; break;
995 case 'k': g.perm.WrWiki = g.perm.RdWiki = g.perm.ApndWiki =1; break;
@@ -1055,15 +1055,14 @@
1055 case 'c': rc = g.perm.ApndTkt; break;
1056 case 'd': rc = g.perm.Delete; break;
1057 case 'e': rc = g.perm.RdAddr; break;
1058 case 'f': rc = g.perm.NewWiki; break;
1059 case 'g': rc = g.perm.Clone; break;
1060 case 'h': rc = g.perm.History; break;
1061 case 'i': rc = g.perm.Write; break;
1062 case 'j': rc = g.perm.RdWiki; break;
1063 case 'k': rc = g.perm.WrWiki; break;
1064 case 'l': rc = g.perm.Link; break;
1065 case 'm': rc = g.perm.ApndWiki; break;
1066 case 'n': rc = g.perm.NewTkt; break;
1067 case 'o': rc = g.perm.Read; break;
1068 case 'p': rc = g.perm.Password; break;
1069 /* case 'q': */
@@ -1131,23 +1130,23 @@
1131 assert(0);
1132 }
1133 }
1134
1135 /*
1136 ** Call this routine if the user lacks okHistory permission. If
1137 ** the anonymous user has okHistory permission, then paint a mesage
1138 ** to inform the user that much more information is available by
1139 ** logging in as anonymous.
1140 */
1141 void login_anonymous_available(void){
1142 if( !g.perm.History && !g.perm.Link &&
1143 db_exists("SELECT 1 FROM user"
1144 " WHERE login='anonymous'"
1145 " AND cap LIKE '%%h%%'") ){
1146 const char *zUrl = PD("REQUEST_URI", "index");
1147 @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
1148 @ Use <a href="%s(g.zTop)/login?anon=1&amp;g=%T(zUrl)">anonymous login</a>
1149 @ to enable hyperlinks.</p>
1150 }
1151 }
1152
1153 /*
1154
--- src/login.c
+++ src/login.c
@@ -562,11 +562,11 @@
562 redirect_to_g();
563 }
564 }
565 style_header("Login/Logout");
566 @ %s(zErrMsg)
567 if( zGoto && P("anon")==0 ){
568 @ <p>A login is required for <a href="%h(zGoto)">%h(zGoto)</a>.</p>
569 }
570 @ <form action="login" method="post">
571 if( zGoto ){
572 @ <input type="hidden" name="g" value="%h(zGoto)" />
@@ -911,14 +911,15 @@
911 }
912
913 /* Set the capabilities */
914 login_replace_capabilities(zCap, 0);
915 login_set_anon_nobody_capabilities();
916 if( zCap[0] && !g.perm.Hyperlink
917 && db_get_boolean("auto-enable-hyperlinks",1)
918 && isHuman(P("HTTP_USER_AGENT")) ){
919 g.perm.Hyperlink = 1;
920 g.javascriptHyperlink = 1;
921 }
922
923 /* If the public-pages glob pattern is defined and REQUEST_URI matches
924 ** one of the globs in public-pages, then also add in all default-perms
925 ** permissions.
@@ -974,22 +975,21 @@
975 }
976 for(i=0; zCap[i]; i++){
977 switch( zCap[i] ){
978 case 's': g.perm.Setup = 1; /* Fall thru into Admin */
979 case 'a': g.perm.Admin = g.perm.RdTkt = g.perm.WrTkt = g.perm.Zip =
980 g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki =
981 g.perm.ApndWiki = g.perm.Hyperlink = g.perm.Clone =
982 g.perm.NewTkt = g.perm.Password = g.perm.RdAddr =
983 g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt = 1;
984 /* Fall thru into Read/Write */
985 case 'i': g.perm.Read = g.perm.Write = 1; break;
986 case 'o': g.perm.Read = 1; break;
987 case 'z': g.perm.Zip = 1; break;
988
989 case 'd': g.perm.Delete = 1; break;
990 case 'h': g.perm.Hyperlink = 1; break;
 
991 case 'g': g.perm.Clone = 1; break;
992 case 'p': g.perm.Password = 1; break;
993
994 case 'j': g.perm.RdWiki = 1; break;
995 case 'k': g.perm.WrWiki = g.perm.RdWiki = g.perm.ApndWiki =1; break;
@@ -1055,15 +1055,14 @@
1055 case 'c': rc = g.perm.ApndTkt; break;
1056 case 'd': rc = g.perm.Delete; break;
1057 case 'e': rc = g.perm.RdAddr; break;
1058 case 'f': rc = g.perm.NewWiki; break;
1059 case 'g': rc = g.perm.Clone; break;
1060 case 'h': rc = g.perm.Hyperlink; break;
1061 case 'i': rc = g.perm.Write; break;
1062 case 'j': rc = g.perm.RdWiki; break;
1063 case 'k': rc = g.perm.WrWiki; break;
 
1064 case 'm': rc = g.perm.ApndWiki; break;
1065 case 'n': rc = g.perm.NewTkt; break;
1066 case 'o': rc = g.perm.Read; break;
1067 case 'p': rc = g.perm.Password; break;
1068 /* case 'q': */
@@ -1131,23 +1130,23 @@
1130 assert(0);
1131 }
1132 }
1133
1134 /*
1135 ** Call this routine if the user lacks g.perm.Hyperlink permission. If
1136 ** the anonymous user has Hyperlink permission, then paint a mesage
1137 ** to inform the user that much more information is available by
1138 ** logging in as anonymous.
1139 */
1140 void login_anonymous_available(void){
1141 if( !g.perm.Hyperlink &&
1142 db_exists("SELECT 1 FROM user"
1143 " WHERE login='anonymous'"
1144 " AND cap LIKE '%%h%%'") ){
1145 const char *zUrl = PD("REQUEST_URI", "index");
1146 @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
1147 @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a>
1148 @ to enable hyperlinks.</p>
1149 }
1150 }
1151
1152 /*
1153
+3 -11
--- src/main.c
+++ src/main.c
@@ -51,28 +51,20 @@
5151
*/
5252
#define MX_AUX 5
5353
5454
/*
5555
** Holds flags for fossil user permissions.
56
-**
57
-** History enables various hyperlinks directly, with an href= attribute
58
-** in the HTML. Link puts an id= attribute in HTML and then adds the
59
-** href= attribute using javascript. The Link option is designed to make
60
-** it harder for bots and spiders to follow hyperlinks, and yet give the
61
-** same experience to users. the Hyperlink permission is a composite which
62
-** is enabled if either History or Hyperlink is turned on.
6356
*/
6457
struct FossilUserPerms {
6558
char Setup; /* s: use Setup screens on web interface */
6659
char Admin; /* a: administrative permission */
6760
char Delete; /* d: delete wiki or tickets */
6861
char Password; /* p: change password */
6962
char Query; /* q: create new reports */
7063
char Write; /* i: xfer inbound. checkin */
7164
char Read; /* o: xfer outbound. checkout */
72
- char History; /* h: access historical information. */
73
- char Link; /* l: enable href= using javascript */
65
+ char Hyperlink; /* h: enable the display of hyperlinks */
7466
char Clone; /* g: clone */
7567
char RdWiki; /* j: view wiki via web */
7668
char NewWiki; /* f: create new wiki via web */
7769
char ApndWiki; /* m: append to wiki via web */
7870
char WrWiki; /* k: edit wiki via web */
@@ -83,11 +75,10 @@
8375
char Attach; /* b: add attachments */
8476
char TktFmt; /* t: create new ticket report formats */
8577
char RdAddr; /* e: read email addresses or other private data */
8678
char Zip; /* z: download zipped artifact via /zip URL */
8779
char Private; /* x: can send and receive private content */
88
- char Hyperlink; /* "h" or "l" */
8980
};
9081
9182
#ifdef FOSSIL_ENABLE_TCL
9283
/*
9384
** All Tcl related context information is in this structure. This structure
@@ -144,11 +135,12 @@
144135
int xlinkClusterOnly; /* Set when cloning. Only process clusters */
145136
int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */
146137
int *aCommitFile; /* Array of files to be committed */
147138
int markPrivate; /* All new artifacts are private if true */
148139
int clockSkewSeen; /* True if clocks on client and server out of sync */
149
- int isHTTP; /* True if running in server/CGI modes, else assume CLI. */
140
+ char isHTTP; /* True if erver/CGI modes, else assume CLI. */
141
+ char javascriptHyperlink; /* If true, set href= using script, not HTML */
150142
151143
int urlIsFile; /* True if a "file:" url */
152144
int urlIsHttps; /* True if a "https:" url */
153145
int urlIsSsh; /* True if an "ssh:" url */
154146
char *urlName; /* Hostname for http: or filename for file: */
155147
--- src/main.c
+++ src/main.c
@@ -51,28 +51,20 @@
51 */
52 #define MX_AUX 5
53
54 /*
55 ** Holds flags for fossil user permissions.
56 **
57 ** History enables various hyperlinks directly, with an href= attribute
58 ** in the HTML. Link puts an id= attribute in HTML and then adds the
59 ** href= attribute using javascript. The Link option is designed to make
60 ** it harder for bots and spiders to follow hyperlinks, and yet give the
61 ** same experience to users. the Hyperlink permission is a composite which
62 ** is enabled if either History or Hyperlink is turned on.
63 */
64 struct FossilUserPerms {
65 char Setup; /* s: use Setup screens on web interface */
66 char Admin; /* a: administrative permission */
67 char Delete; /* d: delete wiki or tickets */
68 char Password; /* p: change password */
69 char Query; /* q: create new reports */
70 char Write; /* i: xfer inbound. checkin */
71 char Read; /* o: xfer outbound. checkout */
72 char History; /* h: access historical information. */
73 char Link; /* l: enable href= using javascript */
74 char Clone; /* g: clone */
75 char RdWiki; /* j: view wiki via web */
76 char NewWiki; /* f: create new wiki via web */
77 char ApndWiki; /* m: append to wiki via web */
78 char WrWiki; /* k: edit wiki via web */
@@ -83,11 +75,10 @@
83 char Attach; /* b: add attachments */
84 char TktFmt; /* t: create new ticket report formats */
85 char RdAddr; /* e: read email addresses or other private data */
86 char Zip; /* z: download zipped artifact via /zip URL */
87 char Private; /* x: can send and receive private content */
88 char Hyperlink; /* "h" or "l" */
89 };
90
91 #ifdef FOSSIL_ENABLE_TCL
92 /*
93 ** All Tcl related context information is in this structure. This structure
@@ -144,11 +135,12 @@
144 int xlinkClusterOnly; /* Set when cloning. Only process clusters */
145 int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */
146 int *aCommitFile; /* Array of files to be committed */
147 int markPrivate; /* All new artifacts are private if true */
148 int clockSkewSeen; /* True if clocks on client and server out of sync */
149 int isHTTP; /* True if running in server/CGI modes, else assume CLI. */
 
150
151 int urlIsFile; /* True if a "file:" url */
152 int urlIsHttps; /* True if a "https:" url */
153 int urlIsSsh; /* True if an "ssh:" url */
154 char *urlName; /* Hostname for http: or filename for file: */
155
--- src/main.c
+++ src/main.c
@@ -51,28 +51,20 @@
51 */
52 #define MX_AUX 5
53
54 /*
55 ** Holds flags for fossil user permissions.
 
 
 
 
 
 
 
56 */
57 struct FossilUserPerms {
58 char Setup; /* s: use Setup screens on web interface */
59 char Admin; /* a: administrative permission */
60 char Delete; /* d: delete wiki or tickets */
61 char Password; /* p: change password */
62 char Query; /* q: create new reports */
63 char Write; /* i: xfer inbound. checkin */
64 char Read; /* o: xfer outbound. checkout */
65 char Hyperlink; /* h: enable the display of hyperlinks */
 
66 char Clone; /* g: clone */
67 char RdWiki; /* j: view wiki via web */
68 char NewWiki; /* f: create new wiki via web */
69 char ApndWiki; /* m: append to wiki via web */
70 char WrWiki; /* k: edit wiki via web */
@@ -83,11 +75,10 @@
75 char Attach; /* b: add attachments */
76 char TktFmt; /* t: create new ticket report formats */
77 char RdAddr; /* e: read email addresses or other private data */
78 char Zip; /* z: download zipped artifact via /zip URL */
79 char Private; /* x: can send and receive private content */
 
80 };
81
82 #ifdef FOSSIL_ENABLE_TCL
83 /*
84 ** All Tcl related context information is in this structure. This structure
@@ -144,11 +135,12 @@
135 int xlinkClusterOnly; /* Set when cloning. Only process clusters */
136 int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */
137 int *aCommitFile; /* Array of files to be committed */
138 int markPrivate; /* All new artifacts are private if true */
139 int clockSkewSeen; /* True if clocks on client and server out of sync */
140 char isHTTP; /* True if erver/CGI modes, else assume CLI. */
141 char javascriptHyperlink; /* If true, set href= using script, not HTML */
142
143 int urlIsFile; /* True if a "file:" url */
144 int urlIsHttps; /* True if a "https:" url */
145 int urlIsSsh; /* True if an "ssh:" url */
146 char *urlName; /* Hostname for http: or filename for file: */
147
+3 -3
--- src/report.c
+++ src/report.c
@@ -64,11 +64,11 @@
6464
if( g.perm.Write && zOwner && zOwner[0] ){
6565
blob_appendf(&ril, "(by <i>%h</i></i>) ", zOwner);
6666
}
6767
if( g.perm.TktFmt ){
6868
blob_appendf(&ril, "[%zcopy</a>] ",
69
- href("%R/rptedit?rn=%d&amp;copy=1", rn));
69
+ href("%R/rptedit?rn=%d&copy=1", rn));
7070
}
7171
if( g.perm.Admin
7272
|| (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0)
7373
){
7474
blob_appendf(&ril, "[%zedit</a>]",
@@ -419,11 +419,11 @@
419419
}
420420
}
421421
if( zOwner==0 ) zOwner = g.zLogin;
422422
style_submenu_element("Cancel", "Cancel", "reportlist");
423423
if( rn>0 ){
424
- style_submenu_element("Delete", "Delete", "rptedit?rn=%d&amp;del1=1", rn);
424
+ style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn);
425425
}
426426
style_header(rn>0 ? "Edit Report Format":"Create New Report Format");
427427
if( zErr ){
428428
@ <blockquote class="reportError">%h(zErr)</blockquote>
429429
}
@@ -948,11 +948,11 @@
948948
if( !tabs ){
949949
struct GenerateHTML sState;
950950
951951
db_multi_exec("PRAGMA empty_result_callbacks=ON");
952952
style_submenu_element("Raw", "Raw",
953
- "rptview?tablist=1&amp;%h", PD("QUERY_STRING",""));
953
+ "rptview?tablist=1&%h", PD("QUERY_STRING",""));
954954
if( g.perm.Admin
955955
|| (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
956956
style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn);
957957
}
958958
if( g.perm.TktFmt ){
959959
--- src/report.c
+++ src/report.c
@@ -64,11 +64,11 @@
64 if( g.perm.Write && zOwner && zOwner[0] ){
65 blob_appendf(&ril, "(by <i>%h</i></i>) ", zOwner);
66 }
67 if( g.perm.TktFmt ){
68 blob_appendf(&ril, "[%zcopy</a>] ",
69 href("%R/rptedit?rn=%d&amp;copy=1", rn));
70 }
71 if( g.perm.Admin
72 || (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0)
73 ){
74 blob_appendf(&ril, "[%zedit</a>]",
@@ -419,11 +419,11 @@
419 }
420 }
421 if( zOwner==0 ) zOwner = g.zLogin;
422 style_submenu_element("Cancel", "Cancel", "reportlist");
423 if( rn>0 ){
424 style_submenu_element("Delete", "Delete", "rptedit?rn=%d&amp;del1=1", rn);
425 }
426 style_header(rn>0 ? "Edit Report Format":"Create New Report Format");
427 if( zErr ){
428 @ <blockquote class="reportError">%h(zErr)</blockquote>
429 }
@@ -948,11 +948,11 @@
948 if( !tabs ){
949 struct GenerateHTML sState;
950
951 db_multi_exec("PRAGMA empty_result_callbacks=ON");
952 style_submenu_element("Raw", "Raw",
953 "rptview?tablist=1&amp;%h", PD("QUERY_STRING",""));
954 if( g.perm.Admin
955 || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
956 style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn);
957 }
958 if( g.perm.TktFmt ){
959
--- src/report.c
+++ src/report.c
@@ -64,11 +64,11 @@
64 if( g.perm.Write && zOwner && zOwner[0] ){
65 blob_appendf(&ril, "(by <i>%h</i></i>) ", zOwner);
66 }
67 if( g.perm.TktFmt ){
68 blob_appendf(&ril, "[%zcopy</a>] ",
69 href("%R/rptedit?rn=%d&copy=1", rn));
70 }
71 if( g.perm.Admin
72 || (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0)
73 ){
74 blob_appendf(&ril, "[%zedit</a>]",
@@ -419,11 +419,11 @@
419 }
420 }
421 if( zOwner==0 ) zOwner = g.zLogin;
422 style_submenu_element("Cancel", "Cancel", "reportlist");
423 if( rn>0 ){
424 style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn);
425 }
426 style_header(rn>0 ? "Edit Report Format":"Create New Report Format");
427 if( zErr ){
428 @ <blockquote class="reportError">%h(zErr)</blockquote>
429 }
@@ -948,11 +948,11 @@
948 if( !tabs ){
949 struct GenerateHTML sState;
950
951 db_multi_exec("PRAGMA empty_result_callbacks=ON");
952 style_submenu_element("Raw", "Raw",
953 "rptview?tablist=1&%h", PD("QUERY_STRING",""));
954 if( g.perm.Admin
955 || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){
956 style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn);
957 }
958 if( g.perm.TktFmt ){
959
+19 -20
--- src/setup.c
+++ src/setup.c
@@ -170,13 +170,10 @@
170170
@ <td><i>Check-In:</i> Commit new versions in the repository</td></tr>
171171
@ <tr><td valign="top"><b>j</b></td>
172172
@ <td><i>Read-Wiki:</i> View wiki pages</td></tr>
173173
@ <tr><td valign="top"><b>k</b></td>
174174
@ <td><i>Write-Wiki:</i> Edit wiki pages</td></tr>
175
- @ <tr><td valign="top"><b>l</b></td>
176
- @ <td><i>Link-Late:</i> Use javascript for hyperlinks to
177
- @ discourage bots</td></tr>
178175
@ <tr><td valign="top"><b>m</b></td>
179176
@ <td><i>Append-Wiki:</i> Append to wiki pages</td></tr>
180177
@ <tr><td valign="top"><b>n</b></td>
181178
@ <td><i>New-Tkt:</i> Create new tickets</td></tr>
182179
@ <tr><td valign="top"><b>o</b></td>
@@ -251,11 +248,11 @@
251248
** WEBPAGE: /setup_uedit
252249
*/
253250
void user_edit(void){
254251
const char *zId, *zLogin, *zInfo, *zCap, *zPw;
255252
char *oaa, *oas, *oar, *oaw, *oan, *oai, *oaj, *oao, *oap;
256
- char *oak, *oad, *oac, *oaf, *oam, *oah, *oal, *oag, *oae;
253
+ char *oak, *oad, *oac, *oaf, *oam, *oah, *oag, *oae;
257254
char *oat, *oau, *oav, *oab, *oax, *oaz;
258255
const char *zGroup;
259256
const char *zOldLogin;
260257
char *inherit[128];
261258
int doWrite;
@@ -307,11 +304,10 @@
307304
int aw = P("aw")!=0;
308305
int ac = P("ac")!=0;
309306
int af = P("af")!=0;
310307
int am = P("am")!=0;
311308
int ah = P("ah")!=0;
312
- int al = P("al")!=0;
313309
int ag = P("ag")!=0;
314310
int at = P("at")!=0;
315311
int au = P("au")!=0;
316312
int av = P("av")!=0;
317313
int ax = P("ax")!=0;
@@ -325,11 +321,10 @@
325321
if( ah ){ zCap[i++] = 'h'; }
326322
if( ag ){ zCap[i++] = 'g'; }
327323
if( ai ){ zCap[i++] = 'i'; }
328324
if( aj ){ zCap[i++] = 'j'; }
329325
if( ak ){ zCap[i++] = 'k'; }
330
- if( al ){ zCap[i++] = 'l'; }
331326
if( am ){ zCap[i++] = 'm'; }
332327
if( an ){ zCap[i++] = 'n'; }
333328
if( ao ){ zCap[i++] = 'o'; }
334329
if( ap ){ zCap[i++] = 'p'; }
335330
if( ar ){ zCap[i++] = 'r'; }
@@ -417,11 +412,11 @@
417412
*/
418413
zLogin = "";
419414
zInfo = "";
420415
zCap = "";
421416
zPw = "";
422
- oaa = oab = oac = oad = oae = oaf = oag = oah = oai = oaj = oak = oal = oam =
417
+ oaa = oab = oac = oad = oae = oaf = oag = oah = oai = oaj = oak = oam =
423418
oan = oao = oap = oar = oas = oat = oau = oav = oaw = oax = oaz = "";
424419
if( uid ){
425420
zLogin = db_text("", "SELECT login FROM user WHERE uid=%d", uid);
426421
zInfo = db_text("", "SELECT info FROM user WHERE uid=%d", uid);
427422
zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", uid);
@@ -435,11 +430,10 @@
435430
if( strchr(zCap, 'g') ) oag = " checked=\"checked\"";
436431
if( strchr(zCap, 'h') ) oah = " checked=\"checked\"";
437432
if( strchr(zCap, 'i') ) oai = " checked=\"checked\"";
438433
if( strchr(zCap, 'j') ) oaj = " checked=\"checked\"";
439434
if( strchr(zCap, 'k') ) oak = " checked=\"checked\"";
440
- if( strchr(zCap, 'l') ) oal = " checked=\"checked\"";
441435
if( strchr(zCap, 'm') ) oam = " checked=\"checked\"";
442436
if( strchr(zCap, 'n') ) oan = " checked=\"checked\"";
443437
if( strchr(zCap, 'o') ) oao = " checked=\"checked\"";
444438
if( strchr(zCap, 'p') ) oap = " checked=\"checked\"";
445439
if( strchr(zCap, 'r') ) oar = " checked=\"checked\"";
@@ -531,11 +525,10 @@
531525
@ <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br />
532526
@ <input type="checkbox" name="ap"%s(oap) />%s(B('p'))Password<br />
533527
@ <input type="checkbox" name="ai"%s(oai) />%s(B('i'))Check-In<br />
534528
@ <input type="checkbox" name="ao"%s(oao) />%s(B('o'))Check-Out<br />
535529
@ <input type="checkbox" name="ah"%s(oah) />%s(B('h'))Hyperlinks<br />
536
- @ <input type="checkbox" name="al"%s(oal) />%s(B('l'))Links-deferred<br />
537530
@ <input type="checkbox" name="au"%s(oau) />%s(B('u'))Reader<br />
538531
@ <input type="checkbox" name="av"%s(oav) />%s(B('v'))Developer<br />
539532
@ <input type="checkbox" name="ag"%s(oag) />%s(B('g'))Clone<br />
540533
@ <input type="checkbox" name="aj"%s(oaj) />%s(B('j'))Read Wiki<br />
541534
@ <input type="checkbox" name="af"%s(oaf) />%s(B('f'))New Wiki<br />
@@ -635,13 +628,11 @@
635628
@
636629
@ <li><p>
637630
@ The <span class="capability">Hyperlinks</span> privilege allows a user
638631
@ to see most hyperlinks. This is recommended ON for most logged-in users
639632
@ but OFF for user "nobody" to avoid problems with spiders trying to walk
640
- @ every historical version of every baseline and file. The
641
- @ <span class="capability">Link-deferred</span> privilege enables hyperlinks
642
- @ using javascript, which makes them harder for bots and spiders to find.
633
+ @ every diff and annotation of every historical check-in and file.
643634
@ </p></li>
644635
@
645636
@ <li><p>
646637
@ The <span class="capability">Zip</span> privilege allows a user to
647638
@ see the "download as ZIP"
@@ -900,19 +891,27 @@
900891
@ than this, then the client will issue multiple HTTP requests.
901892
@ Values below 1 million are not recommended. 5 million is a
902893
@ reasonable number.</p>
903894
904895
@ <hr />
905
- onoff_attribute("Enable hyperlinks for \"nobody\" based on User-Agent",
906
- "auto-enable-hyperlinks", "autohyperlink", 1);
896
+ onoff_attribute(
897
+ "Enable hyperlinks for \"nobody\" based on User-Agent and Javascript",
898
+ "auto-enable-hyperlinks", "autohyperlink", 1);
907899
@ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users
908
- @ including user "nobody", as long as the User-Agent string in the HTTP header
909
- @ indicates that the request is coming from an actual human being and not a
910
- @ a robot or script. Note: Bots can specify whatever User-Agent string they
911
- @ that want. So a bot that wants to impersonate a human can easily do so.
912
- @ Hence, this technique does not necessarily exclude malicious bots.
913
- @ </p>
900
+ @ including user "nobody", as long as (1) the User-Agent string in the
901
+ @ HTTP header indicates that the request is coming from an actual human
902
+ @ being and not a a robot or spider and (2) the user agent is able to
903
+ @ run Javascript in order to set the href= attribute of hyperlinks. Bots
904
+ @ and spiders can specify whatever User-Agent string they that want and
905
+ @ they can run javascript just like browsers. But most bots don't go to
906
+ @ that much trouble so this is normally an effective defense.</p>
907
+ @
908
+ @ <p>You do not normally want a bot to walk your entire repository because
909
+ @ if it does, your server will end up computing diffs and annotations for
910
+ @ every historical version of every file and creating ZIPs and tarballs of
911
+ @ every historical check-in, which can use a lot of CPU and bandwidth
912
+ @ even for relatively small projects.</p>
914913
915914
@ <hr />
916915
entry_attribute("Public pages", 30, "public-pages",
917916
"pubpage", "");
918917
@ <p>A comma-separated list of glob patterns for pages that are accessible
919918
--- src/setup.c
+++ src/setup.c
@@ -170,13 +170,10 @@
170 @ <td><i>Check-In:</i> Commit new versions in the repository</td></tr>
171 @ <tr><td valign="top"><b>j</b></td>
172 @ <td><i>Read-Wiki:</i> View wiki pages</td></tr>
173 @ <tr><td valign="top"><b>k</b></td>
174 @ <td><i>Write-Wiki:</i> Edit wiki pages</td></tr>
175 @ <tr><td valign="top"><b>l</b></td>
176 @ <td><i>Link-Late:</i> Use javascript for hyperlinks to
177 @ discourage bots</td></tr>
178 @ <tr><td valign="top"><b>m</b></td>
179 @ <td><i>Append-Wiki:</i> Append to wiki pages</td></tr>
180 @ <tr><td valign="top"><b>n</b></td>
181 @ <td><i>New-Tkt:</i> Create new tickets</td></tr>
182 @ <tr><td valign="top"><b>o</b></td>
@@ -251,11 +248,11 @@
251 ** WEBPAGE: /setup_uedit
252 */
253 void user_edit(void){
254 const char *zId, *zLogin, *zInfo, *zCap, *zPw;
255 char *oaa, *oas, *oar, *oaw, *oan, *oai, *oaj, *oao, *oap;
256 char *oak, *oad, *oac, *oaf, *oam, *oah, *oal, *oag, *oae;
257 char *oat, *oau, *oav, *oab, *oax, *oaz;
258 const char *zGroup;
259 const char *zOldLogin;
260 char *inherit[128];
261 int doWrite;
@@ -307,11 +304,10 @@
307 int aw = P("aw")!=0;
308 int ac = P("ac")!=0;
309 int af = P("af")!=0;
310 int am = P("am")!=0;
311 int ah = P("ah")!=0;
312 int al = P("al")!=0;
313 int ag = P("ag")!=0;
314 int at = P("at")!=0;
315 int au = P("au")!=0;
316 int av = P("av")!=0;
317 int ax = P("ax")!=0;
@@ -325,11 +321,10 @@
325 if( ah ){ zCap[i++] = 'h'; }
326 if( ag ){ zCap[i++] = 'g'; }
327 if( ai ){ zCap[i++] = 'i'; }
328 if( aj ){ zCap[i++] = 'j'; }
329 if( ak ){ zCap[i++] = 'k'; }
330 if( al ){ zCap[i++] = 'l'; }
331 if( am ){ zCap[i++] = 'm'; }
332 if( an ){ zCap[i++] = 'n'; }
333 if( ao ){ zCap[i++] = 'o'; }
334 if( ap ){ zCap[i++] = 'p'; }
335 if( ar ){ zCap[i++] = 'r'; }
@@ -417,11 +412,11 @@
417 */
418 zLogin = "";
419 zInfo = "";
420 zCap = "";
421 zPw = "";
422 oaa = oab = oac = oad = oae = oaf = oag = oah = oai = oaj = oak = oal = oam =
423 oan = oao = oap = oar = oas = oat = oau = oav = oaw = oax = oaz = "";
424 if( uid ){
425 zLogin = db_text("", "SELECT login FROM user WHERE uid=%d", uid);
426 zInfo = db_text("", "SELECT info FROM user WHERE uid=%d", uid);
427 zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", uid);
@@ -435,11 +430,10 @@
435 if( strchr(zCap, 'g') ) oag = " checked=\"checked\"";
436 if( strchr(zCap, 'h') ) oah = " checked=\"checked\"";
437 if( strchr(zCap, 'i') ) oai = " checked=\"checked\"";
438 if( strchr(zCap, 'j') ) oaj = " checked=\"checked\"";
439 if( strchr(zCap, 'k') ) oak = " checked=\"checked\"";
440 if( strchr(zCap, 'l') ) oal = " checked=\"checked\"";
441 if( strchr(zCap, 'm') ) oam = " checked=\"checked\"";
442 if( strchr(zCap, 'n') ) oan = " checked=\"checked\"";
443 if( strchr(zCap, 'o') ) oao = " checked=\"checked\"";
444 if( strchr(zCap, 'p') ) oap = " checked=\"checked\"";
445 if( strchr(zCap, 'r') ) oar = " checked=\"checked\"";
@@ -531,11 +525,10 @@
531 @ <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br />
532 @ <input type="checkbox" name="ap"%s(oap) />%s(B('p'))Password<br />
533 @ <input type="checkbox" name="ai"%s(oai) />%s(B('i'))Check-In<br />
534 @ <input type="checkbox" name="ao"%s(oao) />%s(B('o'))Check-Out<br />
535 @ <input type="checkbox" name="ah"%s(oah) />%s(B('h'))Hyperlinks<br />
536 @ <input type="checkbox" name="al"%s(oal) />%s(B('l'))Links-deferred<br />
537 @ <input type="checkbox" name="au"%s(oau) />%s(B('u'))Reader<br />
538 @ <input type="checkbox" name="av"%s(oav) />%s(B('v'))Developer<br />
539 @ <input type="checkbox" name="ag"%s(oag) />%s(B('g'))Clone<br />
540 @ <input type="checkbox" name="aj"%s(oaj) />%s(B('j'))Read Wiki<br />
541 @ <input type="checkbox" name="af"%s(oaf) />%s(B('f'))New Wiki<br />
@@ -635,13 +628,11 @@
635 @
636 @ <li><p>
637 @ The <span class="capability">Hyperlinks</span> privilege allows a user
638 @ to see most hyperlinks. This is recommended ON for most logged-in users
639 @ but OFF for user "nobody" to avoid problems with spiders trying to walk
640 @ every historical version of every baseline and file. The
641 @ <span class="capability">Link-deferred</span> privilege enables hyperlinks
642 @ using javascript, which makes them harder for bots and spiders to find.
643 @ </p></li>
644 @
645 @ <li><p>
646 @ The <span class="capability">Zip</span> privilege allows a user to
647 @ see the "download as ZIP"
@@ -900,19 +891,27 @@
900 @ than this, then the client will issue multiple HTTP requests.
901 @ Values below 1 million are not recommended. 5 million is a
902 @ reasonable number.</p>
903
904 @ <hr />
905 onoff_attribute("Enable hyperlinks for \"nobody\" based on User-Agent",
906 "auto-enable-hyperlinks", "autohyperlink", 1);
 
907 @ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users
908 @ including user "nobody", as long as the User-Agent string in the HTTP header
909 @ indicates that the request is coming from an actual human being and not a
910 @ a robot or script. Note: Bots can specify whatever User-Agent string they
911 @ that want. So a bot that wants to impersonate a human can easily do so.
912 @ Hence, this technique does not necessarily exclude malicious bots.
913 @ </p>
 
 
 
 
 
 
 
914
915 @ <hr />
916 entry_attribute("Public pages", 30, "public-pages",
917 "pubpage", "");
918 @ <p>A comma-separated list of glob patterns for pages that are accessible
919
--- src/setup.c
+++ src/setup.c
@@ -170,13 +170,10 @@
170 @ <td><i>Check-In:</i> Commit new versions in the repository</td></tr>
171 @ <tr><td valign="top"><b>j</b></td>
172 @ <td><i>Read-Wiki:</i> View wiki pages</td></tr>
173 @ <tr><td valign="top"><b>k</b></td>
174 @ <td><i>Write-Wiki:</i> Edit wiki pages</td></tr>
 
 
 
175 @ <tr><td valign="top"><b>m</b></td>
176 @ <td><i>Append-Wiki:</i> Append to wiki pages</td></tr>
177 @ <tr><td valign="top"><b>n</b></td>
178 @ <td><i>New-Tkt:</i> Create new tickets</td></tr>
179 @ <tr><td valign="top"><b>o</b></td>
@@ -251,11 +248,11 @@
248 ** WEBPAGE: /setup_uedit
249 */
250 void user_edit(void){
251 const char *zId, *zLogin, *zInfo, *zCap, *zPw;
252 char *oaa, *oas, *oar, *oaw, *oan, *oai, *oaj, *oao, *oap;
253 char *oak, *oad, *oac, *oaf, *oam, *oah, *oag, *oae;
254 char *oat, *oau, *oav, *oab, *oax, *oaz;
255 const char *zGroup;
256 const char *zOldLogin;
257 char *inherit[128];
258 int doWrite;
@@ -307,11 +304,10 @@
304 int aw = P("aw")!=0;
305 int ac = P("ac")!=0;
306 int af = P("af")!=0;
307 int am = P("am")!=0;
308 int ah = P("ah")!=0;
 
309 int ag = P("ag")!=0;
310 int at = P("at")!=0;
311 int au = P("au")!=0;
312 int av = P("av")!=0;
313 int ax = P("ax")!=0;
@@ -325,11 +321,10 @@
321 if( ah ){ zCap[i++] = 'h'; }
322 if( ag ){ zCap[i++] = 'g'; }
323 if( ai ){ zCap[i++] = 'i'; }
324 if( aj ){ zCap[i++] = 'j'; }
325 if( ak ){ zCap[i++] = 'k'; }
 
326 if( am ){ zCap[i++] = 'm'; }
327 if( an ){ zCap[i++] = 'n'; }
328 if( ao ){ zCap[i++] = 'o'; }
329 if( ap ){ zCap[i++] = 'p'; }
330 if( ar ){ zCap[i++] = 'r'; }
@@ -417,11 +412,11 @@
412 */
413 zLogin = "";
414 zInfo = "";
415 zCap = "";
416 zPw = "";
417 oaa = oab = oac = oad = oae = oaf = oag = oah = oai = oaj = oak = oam =
418 oan = oao = oap = oar = oas = oat = oau = oav = oaw = oax = oaz = "";
419 if( uid ){
420 zLogin = db_text("", "SELECT login FROM user WHERE uid=%d", uid);
421 zInfo = db_text("", "SELECT info FROM user WHERE uid=%d", uid);
422 zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", uid);
@@ -435,11 +430,10 @@
430 if( strchr(zCap, 'g') ) oag = " checked=\"checked\"";
431 if( strchr(zCap, 'h') ) oah = " checked=\"checked\"";
432 if( strchr(zCap, 'i') ) oai = " checked=\"checked\"";
433 if( strchr(zCap, 'j') ) oaj = " checked=\"checked\"";
434 if( strchr(zCap, 'k') ) oak = " checked=\"checked\"";
 
435 if( strchr(zCap, 'm') ) oam = " checked=\"checked\"";
436 if( strchr(zCap, 'n') ) oan = " checked=\"checked\"";
437 if( strchr(zCap, 'o') ) oao = " checked=\"checked\"";
438 if( strchr(zCap, 'p') ) oap = " checked=\"checked\"";
439 if( strchr(zCap, 'r') ) oar = " checked=\"checked\"";
@@ -531,11 +525,10 @@
525 @ <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br />
526 @ <input type="checkbox" name="ap"%s(oap) />%s(B('p'))Password<br />
527 @ <input type="checkbox" name="ai"%s(oai) />%s(B('i'))Check-In<br />
528 @ <input type="checkbox" name="ao"%s(oao) />%s(B('o'))Check-Out<br />
529 @ <input type="checkbox" name="ah"%s(oah) />%s(B('h'))Hyperlinks<br />
 
530 @ <input type="checkbox" name="au"%s(oau) />%s(B('u'))Reader<br />
531 @ <input type="checkbox" name="av"%s(oav) />%s(B('v'))Developer<br />
532 @ <input type="checkbox" name="ag"%s(oag) />%s(B('g'))Clone<br />
533 @ <input type="checkbox" name="aj"%s(oaj) />%s(B('j'))Read Wiki<br />
534 @ <input type="checkbox" name="af"%s(oaf) />%s(B('f'))New Wiki<br />
@@ -635,13 +628,11 @@
628 @
629 @ <li><p>
630 @ The <span class="capability">Hyperlinks</span> privilege allows a user
631 @ to see most hyperlinks. This is recommended ON for most logged-in users
632 @ but OFF for user "nobody" to avoid problems with spiders trying to walk
633 @ every diff and annotation of every historical check-in and file.
 
 
634 @ </p></li>
635 @
636 @ <li><p>
637 @ The <span class="capability">Zip</span> privilege allows a user to
638 @ see the "download as ZIP"
@@ -900,19 +891,27 @@
891 @ than this, then the client will issue multiple HTTP requests.
892 @ Values below 1 million are not recommended. 5 million is a
893 @ reasonable number.</p>
894
895 @ <hr />
896 onoff_attribute(
897 "Enable hyperlinks for \"nobody\" based on User-Agent and Javascript",
898 "auto-enable-hyperlinks", "autohyperlink", 1);
899 @ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users
900 @ including user "nobody", as long as (1) the User-Agent string in the
901 @ HTTP header indicates that the request is coming from an actual human
902 @ being and not a a robot or spider and (2) the user agent is able to
903 @ run Javascript in order to set the href= attribute of hyperlinks. Bots
904 @ and spiders can specify whatever User-Agent string they that want and
905 @ they can run javascript just like browsers. But most bots don't go to
906 @ that much trouble so this is normally an effective defense.</p>
907 @
908 @ <p>You do not normally want a bot to walk your entire repository because
909 @ if it does, your server will end up computing diffs and annotations for
910 @ every historical version of every file and creating ZIPs and tarballs of
911 @ every historical check-in, which can use a lot of CPU and bandwidth
912 @ even for relatively small projects.</p>
913
914 @ <hr />
915 entry_attribute("Public pages", 30, "public-pages",
916 "pubpage", "");
917 @ <p>A comma-separated list of glob patterns for pages that are accessible
918
+13 -12
--- src/style.c
+++ src/style.c
@@ -60,39 +60,40 @@
6060
** Generate and return a anchor tag like this:
6161
**
6262
** <a href="URL">
6363
** or <a id="ID">
6464
**
65
-** The form of the anchor tag is determined by the g.perm.History
66
-** variable. The href="URL" form is used if g.perm.History is true.
67
-** If g.perm.History is false and g.perm.Link is true then the
65
+** The form of the anchor tag is determined by the g.javascriptHyperlink
66
+** variable. The href="URL" form is used if g.javascriptHyperlink is false.
67
+** If g.javascriptHyperlink is true then the
6868
** id="ID" form is used and javascript is generated in the footer to cause
69
-** href values to be inserted after the page has loaded. If both
70
-** g.perm.History and g.perm.Link are false, then the <a id="ID"> form is
69
+** href values to be inserted after the page has loaded. If
70
+** g.perm.History is false, then the <a id="ID"> form is still
7171
** generated but the javascript is not generated so the links never
7272
** activate.
7373
**
74
-** Handling the href="URL" using javascript is a defense against bots.
74
+** Filling in the href="URL" using javascript is a defense against bots.
7575
**
7676
** The name of this routine is deliberately kept short so that can be
7777
** easily used within @-lines. Example:
7878
**
79
-** @ %z(href("%s/artifact/%s",g.zTop,zUuid))%h(zFN)</a>
79
+** @ %z(href("%R/artifact/%s",zUuid))%h(zFN)</a>
8080
**
8181
** Note %z format. The string returned by this function is always
82
-** obtained from fossil_malloc().
82
+** obtained from fossil_malloc() so rendering it with %z will reclaim
83
+** that memory space.
8384
**
84
-** There are two versions of this routine href() does a plain hyperlink
85
+** There are two versions of this routine: href() does a plain hyperlink
8586
** and xhref() adds extra attribute text.
8687
*/
8788
char *xhref(const char *zExtra, const char *zFormat, ...){
8889
char *zUrl;
8990
va_list ap;
9091
va_start(ap, zFormat);
9192
zUrl = vmprintf(zFormat, ap);
9293
va_end(ap);
93
- if( g.perm.History ){
94
+ if( g.perm.Hyperlink && !g.javascriptHyperlink ){
9495
return mprintf("<a %s href=\"%z\">", zExtra, zUrl);
9596
}
9697
if( nHref>=nHrefAlloc ){
9798
nHrefAlloc = nHrefAlloc*2 + 10;
9899
aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0]));
@@ -104,11 +105,11 @@
104105
char *zUrl;
105106
va_list ap;
106107
va_start(ap, zFormat);
107108
zUrl = vmprintf(zFormat, ap);
108109
va_end(ap);
109
- if( g.perm.History ){
110
+ if( g.perm.Hyperlink && !g.javascriptHyperlink ){
110111
return mprintf("<a href=\"%z\">", zUrl);
111112
}
112113
if( nHref>=nHrefAlloc ){
113114
nHrefAlloc = nHrefAlloc*2 + 10;
114115
aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0]));
@@ -120,11 +121,11 @@
120121
/*
121122
** Generate javascript that will set the href= attribute on all anchors.
122123
*/
123124
void style_resolve_href(void){
124125
int i;
125
- if( !g.perm.Link || nHref==0 ) return;
126
+ if( !g.perm.Hyperlink || !g.javascriptHyperlink || nHref==0 ) return;
126127
@ <script>
127128
for(i=0; i<nHref; i++){
128129
@ document.getElementById(%d(i+1)).href="%s(aHref[i])";
129130
}
130131
@ </script>
131132
--- src/style.c
+++ src/style.c
@@ -60,39 +60,40 @@
60 ** Generate and return a anchor tag like this:
61 **
62 ** <a href="URL">
63 ** or <a id="ID">
64 **
65 ** The form of the anchor tag is determined by the g.perm.History
66 ** variable. The href="URL" form is used if g.perm.History is true.
67 ** If g.perm.History is false and g.perm.Link is true then the
68 ** id="ID" form is used and javascript is generated in the footer to cause
69 ** href values to be inserted after the page has loaded. If both
70 ** g.perm.History and g.perm.Link are false, then the <a id="ID"> form is
71 ** generated but the javascript is not generated so the links never
72 ** activate.
73 **
74 ** Handling the href="URL" using javascript is a defense against bots.
75 **
76 ** The name of this routine is deliberately kept short so that can be
77 ** easily used within @-lines. Example:
78 **
79 ** @ %z(href("%s/artifact/%s",g.zTop,zUuid))%h(zFN)</a>
80 **
81 ** Note %z format. The string returned by this function is always
82 ** obtained from fossil_malloc().
 
83 **
84 ** There are two versions of this routine href() does a plain hyperlink
85 ** and xhref() adds extra attribute text.
86 */
87 char *xhref(const char *zExtra, const char *zFormat, ...){
88 char *zUrl;
89 va_list ap;
90 va_start(ap, zFormat);
91 zUrl = vmprintf(zFormat, ap);
92 va_end(ap);
93 if( g.perm.History ){
94 return mprintf("<a %s href=\"%z\">", zExtra, zUrl);
95 }
96 if( nHref>=nHrefAlloc ){
97 nHrefAlloc = nHrefAlloc*2 + 10;
98 aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0]));
@@ -104,11 +105,11 @@
104 char *zUrl;
105 va_list ap;
106 va_start(ap, zFormat);
107 zUrl = vmprintf(zFormat, ap);
108 va_end(ap);
109 if( g.perm.History ){
110 return mprintf("<a href=\"%z\">", zUrl);
111 }
112 if( nHref>=nHrefAlloc ){
113 nHrefAlloc = nHrefAlloc*2 + 10;
114 aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0]));
@@ -120,11 +121,11 @@
120 /*
121 ** Generate javascript that will set the href= attribute on all anchors.
122 */
123 void style_resolve_href(void){
124 int i;
125 if( !g.perm.Link || nHref==0 ) return;
126 @ <script>
127 for(i=0; i<nHref; i++){
128 @ document.getElementById(%d(i+1)).href="%s(aHref[i])";
129 }
130 @ </script>
131
--- src/style.c
+++ src/style.c
@@ -60,39 +60,40 @@
60 ** Generate and return a anchor tag like this:
61 **
62 ** <a href="URL">
63 ** or <a id="ID">
64 **
65 ** The form of the anchor tag is determined by the g.javascriptHyperlink
66 ** variable. The href="URL" form is used if g.javascriptHyperlink is false.
67 ** If g.javascriptHyperlink is true then the
68 ** id="ID" form is used and javascript is generated in the footer to cause
69 ** href values to be inserted after the page has loaded. If
70 ** g.perm.History is false, then the <a id="ID"> form is still
71 ** generated but the javascript is not generated so the links never
72 ** activate.
73 **
74 ** Filling in the href="URL" using javascript is a defense against bots.
75 **
76 ** The name of this routine is deliberately kept short so that can be
77 ** easily used within @-lines. Example:
78 **
79 ** @ %z(href("%R/artifact/%s",zUuid))%h(zFN)</a>
80 **
81 ** Note %z format. The string returned by this function is always
82 ** obtained from fossil_malloc() so rendering it with %z will reclaim
83 ** that memory space.
84 **
85 ** There are two versions of this routine: href() does a plain hyperlink
86 ** and xhref() adds extra attribute text.
87 */
88 char *xhref(const char *zExtra, const char *zFormat, ...){
89 char *zUrl;
90 va_list ap;
91 va_start(ap, zFormat);
92 zUrl = vmprintf(zFormat, ap);
93 va_end(ap);
94 if( g.perm.Hyperlink && !g.javascriptHyperlink ){
95 return mprintf("<a %s href=\"%z\">", zExtra, zUrl);
96 }
97 if( nHref>=nHrefAlloc ){
98 nHrefAlloc = nHrefAlloc*2 + 10;
99 aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0]));
@@ -104,11 +105,11 @@
105 char *zUrl;
106 va_list ap;
107 va_start(ap, zFormat);
108 zUrl = vmprintf(zFormat, ap);
109 va_end(ap);
110 if( g.perm.Hyperlink && !g.javascriptHyperlink ){
111 return mprintf("<a href=\"%z\">", zUrl);
112 }
113 if( nHref>=nHrefAlloc ){
114 nHrefAlloc = nHrefAlloc*2 + 10;
115 aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0]));
@@ -120,11 +121,11 @@
121 /*
122 ** Generate javascript that will set the href= attribute on all anchors.
123 */
124 void style_resolve_href(void){
125 int i;
126 if( !g.perm.Hyperlink || !g.javascriptHyperlink || nHref==0 ) return;
127 @ <script>
128 for(i=0; i<nHref; i++){
129 @ document.getElementById(%d(i+1)).href="%s(aHref[i])";
130 }
131 @ </script>
132
+3 -3
--- src/timeline.c
+++ src/timeline.c
@@ -62,11 +62,11 @@
6262
void hyperlink_to_diff(const char *zV1, const char *zV2){
6363
if( g.perm.Hyperlink ){
6464
if( zV2==0 ){
6565
@ %z(href("%R/diff?v2=%s",zV1))[diff]</a>
6666
}else{
67
- @ %z(href("%R/diff?v1=%s&amp;v2=%s",zV1,zV2))[diff]</a>
67
+ @ %z(href("%R/diff?v1=%s&v2=%s",zV1,zV2))[diff]</a>
6868
}
6969
}
7070
}
7171
7272
/*
@@ -88,11 +88,11 @@
8888
*/
8989
void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){
9090
if( zSuf==0 ) zSuf = "";
9191
if( g.perm.Hyperlink ){
9292
if( zD && zD[0] ){
93
- @ %z(href("%R/timeline?c=%T&amp;u=%T",zD,zU))%h(zU)</a>%s(zSuf)
93
+ @ %z(href("%R/timeline?c=%T&u=%T",zD,zU))%h(zU)</a>%s(zSuf)
9494
}else{
9595
@ %z(href("%R/timeline?u=%T",zU))%h(zU)</a>%s(zSuf)
9696
}
9797
}else{
9898
@ %s(zU)
@@ -1616,10 +1616,10 @@
16161616
" AND blob.rid=c.cid"
16171617
);
16181618
while( db_step(&q)==SQLITE_ROW ){
16191619
const char *zUuid = db_column_text(&q, 0);
16201620
@ <li>
1621
- @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&amp;d=%S(zUuid)">%S(zUuid)</a>
1621
+ @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&d=%S(zUuid)">%S(zUuid)</a>
16221622
}
16231623
db_finalize(&q);
16241624
style_footer();
16251625
}
16261626
--- src/timeline.c
+++ src/timeline.c
@@ -62,11 +62,11 @@
62 void hyperlink_to_diff(const char *zV1, const char *zV2){
63 if( g.perm.Hyperlink ){
64 if( zV2==0 ){
65 @ %z(href("%R/diff?v2=%s",zV1))[diff]</a>
66 }else{
67 @ %z(href("%R/diff?v1=%s&amp;v2=%s",zV1,zV2))[diff]</a>
68 }
69 }
70 }
71
72 /*
@@ -88,11 +88,11 @@
88 */
89 void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){
90 if( zSuf==0 ) zSuf = "";
91 if( g.perm.Hyperlink ){
92 if( zD && zD[0] ){
93 @ %z(href("%R/timeline?c=%T&amp;u=%T",zD,zU))%h(zU)</a>%s(zSuf)
94 }else{
95 @ %z(href("%R/timeline?u=%T",zU))%h(zU)</a>%s(zSuf)
96 }
97 }else{
98 @ %s(zU)
@@ -1616,10 +1616,10 @@
1616 " AND blob.rid=c.cid"
1617 );
1618 while( db_step(&q)==SQLITE_ROW ){
1619 const char *zUuid = db_column_text(&q, 0);
1620 @ <li>
1621 @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&amp;d=%S(zUuid)">%S(zUuid)</a>
1622 }
1623 db_finalize(&q);
1624 style_footer();
1625 }
1626
--- src/timeline.c
+++ src/timeline.c
@@ -62,11 +62,11 @@
62 void hyperlink_to_diff(const char *zV1, const char *zV2){
63 if( g.perm.Hyperlink ){
64 if( zV2==0 ){
65 @ %z(href("%R/diff?v2=%s",zV1))[diff]</a>
66 }else{
67 @ %z(href("%R/diff?v1=%s&v2=%s",zV1,zV2))[diff]</a>
68 }
69 }
70 }
71
72 /*
@@ -88,11 +88,11 @@
88 */
89 void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){
90 if( zSuf==0 ) zSuf = "";
91 if( g.perm.Hyperlink ){
92 if( zD && zD[0] ){
93 @ %z(href("%R/timeline?c=%T&u=%T",zD,zU))%h(zU)</a>%s(zSuf)
94 }else{
95 @ %z(href("%R/timeline?u=%T",zU))%h(zU)</a>%s(zSuf)
96 }
97 }else{
98 @ %s(zU)
@@ -1616,10 +1616,10 @@
1616 " AND blob.rid=c.cid"
1617 );
1618 while( db_step(&q)==SQLITE_ROW ){
1619 const char *zUuid = db_column_text(&q, 0);
1620 @ <li>
1621 @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&d=%S(zUuid)">%S(zUuid)</a>
1622 }
1623 db_finalize(&q);
1624 style_footer();
1625 }
1626
+6 -6
--- src/tkt.c
+++ src/tkt.c
@@ -319,11 +319,11 @@
319319
style_submenu_element("New Ticket", "Create a new ticket",
320320
"%s/tktnew", g.zTop);
321321
}
322322
if( g.perm.ApndTkt && g.perm.Attach ){
323323
style_submenu_element("Attach", "Add An Attachment",
324
- "%s/attachadd?tkt=%T&amp;from=%s/tktview/%t",
324
+ "%s/attachadd?tkt=%T&from=%s/tktview/%t",
325325
g.zTop, zUuid, g.zTop, zUuid);
326326
}
327327
style_header("View Ticket");
328328
if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1);
329329
ticket_init();
@@ -354,19 +354,19 @@
354354
@ <ul>
355355
}
356356
cnt++;
357357
@ <li>
358358
if( g.perm.Read && g.perm.Hyperlink ){
359
- @ %z(href("%R/attachview?tkt=%s&amp;file=%t",zFullName,zFile))
359
+ @ %z(href("%R/attachview?tkt=%s&file=%t",zFullName,zFile))
360360
@ %h(zFile)</a>
361361
}else{
362362
@ %h(zFile)
363363
}
364364
@ added by %h(zUser) on
365365
hyperlink_to_date(zDate, ".");
366366
if( g.perm.WrTkt && g.perm.Attach ){
367
- @ [%z(href("%R/attachdelete?tkt=%s&amp;file=%t&amp;from=%R/tktview%%3fname=%s",zFullName,zFile,zFullName))delete</a>]
367
+ @ [%z(href("%R/attachdelete?tkt=%s&file=%t&from=%R/tktview%%3fname=%s",zFullName,zFile,zFullName))delete</a>]
368368
}
369369
@ </li>
370370
}
371371
if( cnt ){
372372
@ </ul>
@@ -647,11 +647,11 @@
647647
return 0;
648648
}
649649
650650
/*
651651
** WEBPAGE: tkttimeline
652
-** URL: /tkttimeline?name=TICKETUUID&amp;y=TYPE
652
+** URL: /tkttimeline?name=TICKETUUID&y=TYPE
653653
**
654654
** Show the change history for a single ticket in timeline format.
655655
*/
656656
void tkttimeline_page(void){
657657
Stmt q;
@@ -667,11 +667,11 @@
667667
if( !g.perm.Hyperlink || !g.perm.RdTkt ){ login_needed(); return; }
668668
zUuid = PD("name","");
669669
zType = PD("y","a");
670670
if( zType[0]!='c' ){
671671
style_submenu_element("Check-ins", "Check-ins",
672
- "%s/tkttimeline?name=%T&amp;y=ci", g.zTop, zUuid);
672
+ "%s/tkttimeline?name=%T&y=ci", g.zTop, zUuid);
673673
}else{
674674
style_submenu_element("Timeline", "Timeline",
675675
"%s/tkttimeline?name=%T", g.zTop, zUuid);
676676
}
677677
style_submenu_element("History", "History",
@@ -742,11 +742,11 @@
742742
zUuid = PD("name","");
743743
zTitle = mprintf("History Of Ticket %h", zUuid);
744744
style_submenu_element("Status", "Status",
745745
"%s/info/%s", g.zTop, zUuid);
746746
style_submenu_element("Check-ins", "Check-ins",
747
- "%s/tkttimeline?name=%s&amp;y=ci", g.zTop, zUuid);
747
+ "%s/tkttimeline?name=%s&y=ci", g.zTop, zUuid);
748748
style_submenu_element("Timeline", "Timeline",
749749
"%s/tkttimeline?name=%s", g.zTop, zUuid);
750750
style_header(zTitle);
751751
free(zTitle);
752752
753753
--- src/tkt.c
+++ src/tkt.c
@@ -319,11 +319,11 @@
319 style_submenu_element("New Ticket", "Create a new ticket",
320 "%s/tktnew", g.zTop);
321 }
322 if( g.perm.ApndTkt && g.perm.Attach ){
323 style_submenu_element("Attach", "Add An Attachment",
324 "%s/attachadd?tkt=%T&amp;from=%s/tktview/%t",
325 g.zTop, zUuid, g.zTop, zUuid);
326 }
327 style_header("View Ticket");
328 if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1);
329 ticket_init();
@@ -354,19 +354,19 @@
354 @ <ul>
355 }
356 cnt++;
357 @ <li>
358 if( g.perm.Read && g.perm.Hyperlink ){
359 @ %z(href("%R/attachview?tkt=%s&amp;file=%t",zFullName,zFile))
360 @ %h(zFile)</a>
361 }else{
362 @ %h(zFile)
363 }
364 @ added by %h(zUser) on
365 hyperlink_to_date(zDate, ".");
366 if( g.perm.WrTkt && g.perm.Attach ){
367 @ [%z(href("%R/attachdelete?tkt=%s&amp;file=%t&amp;from=%R/tktview%%3fname=%s",zFullName,zFile,zFullName))delete</a>]
368 }
369 @ </li>
370 }
371 if( cnt ){
372 @ </ul>
@@ -647,11 +647,11 @@
647 return 0;
648 }
649
650 /*
651 ** WEBPAGE: tkttimeline
652 ** URL: /tkttimeline?name=TICKETUUID&amp;y=TYPE
653 **
654 ** Show the change history for a single ticket in timeline format.
655 */
656 void tkttimeline_page(void){
657 Stmt q;
@@ -667,11 +667,11 @@
667 if( !g.perm.Hyperlink || !g.perm.RdTkt ){ login_needed(); return; }
668 zUuid = PD("name","");
669 zType = PD("y","a");
670 if( zType[0]!='c' ){
671 style_submenu_element("Check-ins", "Check-ins",
672 "%s/tkttimeline?name=%T&amp;y=ci", g.zTop, zUuid);
673 }else{
674 style_submenu_element("Timeline", "Timeline",
675 "%s/tkttimeline?name=%T", g.zTop, zUuid);
676 }
677 style_submenu_element("History", "History",
@@ -742,11 +742,11 @@
742 zUuid = PD("name","");
743 zTitle = mprintf("History Of Ticket %h", zUuid);
744 style_submenu_element("Status", "Status",
745 "%s/info/%s", g.zTop, zUuid);
746 style_submenu_element("Check-ins", "Check-ins",
747 "%s/tkttimeline?name=%s&amp;y=ci", g.zTop, zUuid);
748 style_submenu_element("Timeline", "Timeline",
749 "%s/tkttimeline?name=%s", g.zTop, zUuid);
750 style_header(zTitle);
751 free(zTitle);
752
753
--- src/tkt.c
+++ src/tkt.c
@@ -319,11 +319,11 @@
319 style_submenu_element("New Ticket", "Create a new ticket",
320 "%s/tktnew", g.zTop);
321 }
322 if( g.perm.ApndTkt && g.perm.Attach ){
323 style_submenu_element("Attach", "Add An Attachment",
324 "%s/attachadd?tkt=%T&from=%s/tktview/%t",
325 g.zTop, zUuid, g.zTop, zUuid);
326 }
327 style_header("View Ticket");
328 if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1);
329 ticket_init();
@@ -354,19 +354,19 @@
354 @ <ul>
355 }
356 cnt++;
357 @ <li>
358 if( g.perm.Read && g.perm.Hyperlink ){
359 @ %z(href("%R/attachview?tkt=%s&file=%t",zFullName,zFile))
360 @ %h(zFile)</a>
361 }else{
362 @ %h(zFile)
363 }
364 @ added by %h(zUser) on
365 hyperlink_to_date(zDate, ".");
366 if( g.perm.WrTkt && g.perm.Attach ){
367 @ [%z(href("%R/attachdelete?tkt=%s&file=%t&from=%R/tktview%%3fname=%s",zFullName,zFile,zFullName))delete</a>]
368 }
369 @ </li>
370 }
371 if( cnt ){
372 @ </ul>
@@ -647,11 +647,11 @@
647 return 0;
648 }
649
650 /*
651 ** WEBPAGE: tkttimeline
652 ** URL: /tkttimeline?name=TICKETUUID&y=TYPE
653 **
654 ** Show the change history for a single ticket in timeline format.
655 */
656 void tkttimeline_page(void){
657 Stmt q;
@@ -667,11 +667,11 @@
667 if( !g.perm.Hyperlink || !g.perm.RdTkt ){ login_needed(); return; }
668 zUuid = PD("name","");
669 zType = PD("y","a");
670 if( zType[0]!='c' ){
671 style_submenu_element("Check-ins", "Check-ins",
672 "%s/tkttimeline?name=%T&y=ci", g.zTop, zUuid);
673 }else{
674 style_submenu_element("Timeline", "Timeline",
675 "%s/tkttimeline?name=%T", g.zTop, zUuid);
676 }
677 style_submenu_element("History", "History",
@@ -742,11 +742,11 @@
742 zUuid = PD("name","");
743 zTitle = mprintf("History Of Ticket %h", zUuid);
744 style_submenu_element("Status", "Status",
745 "%s/info/%s", g.zTop, zUuid);
746 style_submenu_element("Check-ins", "Check-ins",
747 "%s/tkttimeline?name=%s&y=ci", g.zTop, zUuid);
748 style_submenu_element("Timeline", "Timeline",
749 "%s/tkttimeline?name=%s", g.zTop, zUuid);
750 style_header(zTitle);
751 free(zTitle);
752
753
+4 -4
--- src/wiki.c
+++ src/wiki.c
@@ -190,11 +190,11 @@
190190
style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T",
191191
g.zTop, zPageName);
192192
}
193193
if( rid && g.perm.ApndWiki && g.perm.Attach ){
194194
style_submenu_element("Attach", "Add An Attachment",
195
- "%s/attachadd?page=%T&amp;from=%s/wiki%%3fname=%T",
195
+ "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T",
196196
g.zTop, zPageName, g.zTop, zPageName);
197197
}
198198
if( rid && g.perm.ApndWiki ){
199199
style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T",
200200
g.zTop, zPageName);
@@ -224,19 +224,19 @@
224224
@ <ul>
225225
}
226226
cnt++;
227227
@ <li>
228228
if( g.perm.Hyperlink && g.perm.Read ){
229
- @ %z(href("%R/attachview?page=%T&amp;file=%t",zPageName,zFile))
229
+ @ %z(href("%R/attachview?page=%T&file=%t",zPageName,zFile))
230230
@ %h(zFile)</a>
231231
}else{
232232
@ %h(zFile)
233233
}
234234
@ added by %h(zUser) on
235235
hyperlink_to_date(zDate, ".");
236236
if( g.perm.WrWiki && g.perm.Attach ){
237
- @ [%z(href("%R/attachdelete?page=%t&amp;file=%t&amp;from=%R/wiki%%3fname=%f",zPageName,zFile,zPageName))delete</a>]
237
+ @ [%z(href("%R/attachdelete?page=%t&file=%t&from=%R/wiki%%3fname=%f",zPageName,zFile,zPageName))delete</a>]
238238
}
239239
@ </li>
240240
}
241241
if( cnt ){
242242
@ </ul>
@@ -542,11 +542,11 @@
542542
** Function called to output extra text at the end of each line in
543543
** a wiki history listing.
544544
*/
545545
static void wiki_history_extra(int rid){
546546
if( db_exists("SELECT 1 FROM tagxref WHERE rid=%d", rid) ){
547
- @ %z(href("%R/wdiff?name=%t&amp;a=%d",zWikiPageName,rid))[diff]</a>
547
+ @ %z(href("%R/wdiff?name=%t&a=%d",zWikiPageName,rid))[diff]</a>
548548
}
549549
}
550550
551551
/*
552552
** WEBPAGE: whistory
553553
--- src/wiki.c
+++ src/wiki.c
@@ -190,11 +190,11 @@
190 style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T",
191 g.zTop, zPageName);
192 }
193 if( rid && g.perm.ApndWiki && g.perm.Attach ){
194 style_submenu_element("Attach", "Add An Attachment",
195 "%s/attachadd?page=%T&amp;from=%s/wiki%%3fname=%T",
196 g.zTop, zPageName, g.zTop, zPageName);
197 }
198 if( rid && g.perm.ApndWiki ){
199 style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T",
200 g.zTop, zPageName);
@@ -224,19 +224,19 @@
224 @ <ul>
225 }
226 cnt++;
227 @ <li>
228 if( g.perm.Hyperlink && g.perm.Read ){
229 @ %z(href("%R/attachview?page=%T&amp;file=%t",zPageName,zFile))
230 @ %h(zFile)</a>
231 }else{
232 @ %h(zFile)
233 }
234 @ added by %h(zUser) on
235 hyperlink_to_date(zDate, ".");
236 if( g.perm.WrWiki && g.perm.Attach ){
237 @ [%z(href("%R/attachdelete?page=%t&amp;file=%t&amp;from=%R/wiki%%3fname=%f",zPageName,zFile,zPageName))delete</a>]
238 }
239 @ </li>
240 }
241 if( cnt ){
242 @ </ul>
@@ -542,11 +542,11 @@
542 ** Function called to output extra text at the end of each line in
543 ** a wiki history listing.
544 */
545 static void wiki_history_extra(int rid){
546 if( db_exists("SELECT 1 FROM tagxref WHERE rid=%d", rid) ){
547 @ %z(href("%R/wdiff?name=%t&amp;a=%d",zWikiPageName,rid))[diff]</a>
548 }
549 }
550
551 /*
552 ** WEBPAGE: whistory
553
--- src/wiki.c
+++ src/wiki.c
@@ -190,11 +190,11 @@
190 style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T",
191 g.zTop, zPageName);
192 }
193 if( rid && g.perm.ApndWiki && g.perm.Attach ){
194 style_submenu_element("Attach", "Add An Attachment",
195 "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T",
196 g.zTop, zPageName, g.zTop, zPageName);
197 }
198 if( rid && g.perm.ApndWiki ){
199 style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T",
200 g.zTop, zPageName);
@@ -224,19 +224,19 @@
224 @ <ul>
225 }
226 cnt++;
227 @ <li>
228 if( g.perm.Hyperlink && g.perm.Read ){
229 @ %z(href("%R/attachview?page=%T&file=%t",zPageName,zFile))
230 @ %h(zFile)</a>
231 }else{
232 @ %h(zFile)
233 }
234 @ added by %h(zUser) on
235 hyperlink_to_date(zDate, ".");
236 if( g.perm.WrWiki && g.perm.Attach ){
237 @ [%z(href("%R/attachdelete?page=%t&file=%t&from=%R/wiki%%3fname=%f",zPageName,zFile,zPageName))delete</a>]
238 }
239 @ </li>
240 }
241 if( cnt ){
242 @ </ul>
@@ -542,11 +542,11 @@
542 ** Function called to output extra text at the end of each line in
543 ** a wiki history listing.
544 */
545 static void wiki_history_extra(int rid){
546 if( db_exists("SELECT 1 FROM tagxref WHERE rid=%d", rid) ){
547 @ %z(href("%R/wdiff?name=%t&a=%d",zWikiPageName,rid))[diff]</a>
548 }
549 }
550
551 /*
552 ** WEBPAGE: whistory
553
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1043,15 +1043,11 @@
10431043
|| strncmp(zTarget, "mailto:", 7)==0
10441044
){
10451045
blob_appendf(p->pOut, "<a href=\"%s\">", zTarget);
10461046
/* zTerm = "&#x27FE;</a>"; // doesn't work on windows */
10471047
}else if( zTarget[0]=='/' ){
1048
- if( 1 /* g.perm.History */ ){
1049
- blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zTop, zTarget);
1050
- }else{
1051
- zTerm = "";
1052
- }
1048
+ blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zTop, zTarget);
10531049
}else if( zTarget[0]=='.' || zTarget[0]=='#' ){
10541050
if( 1 ){
10551051
blob_appendf(p->pOut, "<a href=\"%h\">", zTarget);
10561052
}else{
10571053
zTerm = "";
10581054
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1043,15 +1043,11 @@
1043 || strncmp(zTarget, "mailto:", 7)==0
1044 ){
1045 blob_appendf(p->pOut, "<a href=\"%s\">", zTarget);
1046 /* zTerm = "&#x27FE;</a>"; // doesn't work on windows */
1047 }else if( zTarget[0]=='/' ){
1048 if( 1 /* g.perm.History */ ){
1049 blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zTop, zTarget);
1050 }else{
1051 zTerm = "";
1052 }
1053 }else if( zTarget[0]=='.' || zTarget[0]=='#' ){
1054 if( 1 ){
1055 blob_appendf(p->pOut, "<a href=\"%h\">", zTarget);
1056 }else{
1057 zTerm = "";
1058
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1043,15 +1043,11 @@
1043 || strncmp(zTarget, "mailto:", 7)==0
1044 ){
1045 blob_appendf(p->pOut, "<a href=\"%s\">", zTarget);
1046 /* zTerm = "&#x27FE;</a>"; // doesn't work on windows */
1047 }else if( zTarget[0]=='/' ){
1048 blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zTop, zTarget);
 
 
 
 
1049 }else if( zTarget[0]=='.' || zTarget[0]=='#' ){
1050 if( 1 ){
1051 blob_appendf(p->pOut, "<a href=\"%h\">", zTarget);
1052 }else{
1053 zTerm = "";
1054

Keyboard Shortcuts

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