Fossil SCM

Changes anchor tags (<a&gt) so that the href= attribute can be set by javascript rather than by HTML. This is to make it harder for spiders to follow the hyperlinks to every diff and annotation in the project history. It all seems to work, but it needs further testing and review before going live.

drh 2012-04-28 07:15 UTC trunk
Commit 8ae52fc4183f3100ce47ca69f1545e3425001f28
+7 -9
--- src/branch.c
+++ src/branch.c
@@ -321,18 +321,18 @@
321321
style_submenu_element("All", "All", "brlist?all");
322322
}
323323
login_anonymous_available();
324324
style_sidebox_begin("Nomenclature:", "33%");
325325
@ <ol>
326
- @ <li> An <div class="sideboxDescribed"><a href="brlist">
326
+ @ <li> An <div class="sideboxDescribed">%z(href("brlist"))
327327
@ open branch</a></div> is a branch that has one or
328
- @ more <a href="leaves">open leaves.</a>
328
+ @ more %z(href("leaves"))open leaves.</a>
329329
@ The presence of open leaves presumably means
330330
@ that the branch is still being extended with new check-ins.</li>
331
- @ <li> A <div class="sideboxDescribed"><a href="brlist?closed">
331
+ @ <li> A <div class="sideboxDescribed">%z(href("brlist?closed"))
332332
@ closed branch</a></div> is a branch with only
333
- @ <div class="sideboxDescribed"><a href="leaves?closed">
333
+ @ <div class="sideboxDescribed">%z(href("leaves?closed"))
334334
@ closed leaves</a></div>.
335335
@ Closed branches are fixed and do not change (unless they are first
336336
@ reopened)</li>
337337
@ </ol>
338338
style_sidebox_end();
@@ -356,14 +356,12 @@
356356
}
357357
if( colorTest ){
358358
const char *zColor = hash_color(zBr);
359359
@ <li><span style="background-color: %s(zColor)">
360360
@ %h(zBr) &rarr; %s(zColor)</span></li>
361
- }else if( g.perm.History ){
362
- @ <li><a href="%s(g.zTop)/timeline?r=%T(zBr)")>%h(zBr)</a></li>
363361
}else{
364
- @ <li><b>%h(zBr)</b></li>
362
+ @ <li>%z(href("%R/timeline?r=%T",zBr))%h(zBr)</a></li>
365363
}
366364
}
367365
if( cnt ){
368366
@ </ul>
369367
}
@@ -382,11 +380,11 @@
382380
** the timeline of a "brlist" page. Add some additional hyperlinks
383381
** to the end of the line.
384382
*/
385383
static void brtimeline_extra(int rid){
386384
Stmt q;
387
- if( !g.perm.History ) return;
385
+ if( !g.perm.Hyperlink ) return;
388386
db_prepare(&q,
389387
"SELECT substr(tagname,5) FROM tagxref, tag"
390388
" WHERE tagxref.rid=%d"
391389
" AND tagxref.tagid=tag.tagid"
392390
" AND tagxref.tagtype>0"
@@ -393,11 +391,11 @@
393391
" AND tag.tagname GLOB 'sym-*'",
394392
rid
395393
);
396394
while( db_step(&q)==SQLITE_ROW ){
397395
const char *zTagName = db_column_text(&q, 0);
398
- @ <a href="%s(g.zTop)/timeline?r=%T(zTagName)">[timeline]</a>
396
+ @ %z(href("%R/timeline?r=%T",zTagName))[timeline]</a>
399397
}
400398
db_finalize(&q);
401399
}
402400
403401
/*
404402
--- src/branch.c
+++ src/branch.c
@@ -321,18 +321,18 @@
321 style_submenu_element("All", "All", "brlist?all");
322 }
323 login_anonymous_available();
324 style_sidebox_begin("Nomenclature:", "33%");
325 @ <ol>
326 @ <li> An <div class="sideboxDescribed"><a href="brlist">
327 @ open branch</a></div> is a branch that has one or
328 @ more <a href="leaves">open leaves.</a>
329 @ The presence of open leaves presumably means
330 @ that the branch is still being extended with new check-ins.</li>
331 @ <li> A <div class="sideboxDescribed"><a href="brlist?closed">
332 @ closed branch</a></div> is a branch with only
333 @ <div class="sideboxDescribed"><a href="leaves?closed">
334 @ closed leaves</a></div>.
335 @ Closed branches are fixed and do not change (unless they are first
336 @ reopened)</li>
337 @ </ol>
338 style_sidebox_end();
@@ -356,14 +356,12 @@
356 }
357 if( colorTest ){
358 const char *zColor = hash_color(zBr);
359 @ <li><span style="background-color: %s(zColor)">
360 @ %h(zBr) &rarr; %s(zColor)</span></li>
361 }else if( g.perm.History ){
362 @ <li><a href="%s(g.zTop)/timeline?r=%T(zBr)")>%h(zBr)</a></li>
363 }else{
364 @ <li><b>%h(zBr)</b></li>
365 }
366 }
367 if( cnt ){
368 @ </ul>
369 }
@@ -382,11 +380,11 @@
382 ** the timeline of a "brlist" page. Add some additional hyperlinks
383 ** to the end of the line.
384 */
385 static void brtimeline_extra(int rid){
386 Stmt q;
387 if( !g.perm.History ) return;
388 db_prepare(&q,
389 "SELECT substr(tagname,5) FROM tagxref, tag"
390 " WHERE tagxref.rid=%d"
391 " AND tagxref.tagid=tag.tagid"
392 " AND tagxref.tagtype>0"
@@ -393,11 +391,11 @@
393 " AND tag.tagname GLOB 'sym-*'",
394 rid
395 );
396 while( db_step(&q)==SQLITE_ROW ){
397 const char *zTagName = db_column_text(&q, 0);
398 @ <a href="%s(g.zTop)/timeline?r=%T(zTagName)">[timeline]</a>
399 }
400 db_finalize(&q);
401 }
402
403 /*
404
--- src/branch.c
+++ src/branch.c
@@ -321,18 +321,18 @@
321 style_submenu_element("All", "All", "brlist?all");
322 }
323 login_anonymous_available();
324 style_sidebox_begin("Nomenclature:", "33%");
325 @ <ol>
326 @ <li> An <div class="sideboxDescribed">%z(href("brlist"))
327 @ open branch</a></div> is a branch that has one or
328 @ more %z(href("leaves"))open leaves.</a>
329 @ The presence of open leaves presumably means
330 @ that the branch is still being extended with new check-ins.</li>
331 @ <li> A <div class="sideboxDescribed">%z(href("brlist?closed"))
332 @ closed branch</a></div> is a branch with only
333 @ <div class="sideboxDescribed">%z(href("leaves?closed"))
334 @ closed leaves</a></div>.
335 @ Closed branches are fixed and do not change (unless they are first
336 @ reopened)</li>
337 @ </ol>
338 style_sidebox_end();
@@ -356,14 +356,12 @@
356 }
357 if( colorTest ){
358 const char *zColor = hash_color(zBr);
359 @ <li><span style="background-color: %s(zColor)">
360 @ %h(zBr) &rarr; %s(zColor)</span></li>
 
 
361 }else{
362 @ <li>%z(href("%R/timeline?r=%T",zBr))%h(zBr)</a></li>
363 }
364 }
365 if( cnt ){
366 @ </ul>
367 }
@@ -382,11 +380,11 @@
380 ** the timeline of a "brlist" page. Add some additional hyperlinks
381 ** to the end of the line.
382 */
383 static void brtimeline_extra(int rid){
384 Stmt q;
385 if( !g.perm.Hyperlink ) return;
386 db_prepare(&q,
387 "SELECT substr(tagname,5) FROM tagxref, tag"
388 " WHERE tagxref.rid=%d"
389 " AND tagxref.tagid=tag.tagid"
390 " AND tagxref.tagtype>0"
@@ -393,11 +391,11 @@
391 " AND tag.tagname GLOB 'sym-*'",
392 rid
393 );
394 while( db_step(&q)==SQLITE_ROW ){
395 const char *zTagName = db_column_text(&q, 0);
396 @ %z(href("%R/timeline?r=%T",zTagName))[timeline]</a>
397 }
398 db_finalize(&q);
399 }
400
401 /*
402
+21 -20
--- src/browse.c
+++ src/browse.c
@@ -79,15 +79,17 @@
7979
8080
for(i=0; zPath[i]; i=j){
8181
for(j=i; zPath[j] && zPath[j]!='/'; j++){}
8282
if( zPath[j] && g.perm.History ){
8383
if( zCI ){
84
- blob_appendf(pOut, "%s<a href=\"%s/dir?ci=%S&amp;name=%#T\">%#h</a>",
85
- zSep, g.zTop, zCI, j, zPath, j-i, &zPath[i]);
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]);
8687
}else{
87
- blob_appendf(pOut, "%s<a href=\"%s/dir?name=%#T\">%#h</a>",
88
- zSep, g.zTop, j, zPath, j-i, &zPath[i]);
88
+ char *zLink = href("%R/dir?name=%#T", j, zPath);
89
+ blob_appendf(pOut, "%s%z%#h</a>",
90
+ zSep, zLink, j-i, &zPath[i]);
8991
}
9092
}else{
9193
blob_appendf(pOut, "%s%#h", zSep, j-i, &zPath[i]);
9294
}
9395
zSep = "/";
@@ -155,39 +157,38 @@
155157
}
156158
if( zCI ){
157159
char zShort[20];
158160
memcpy(zShort, zUuid, 10);
159161
zShort[10] = 0;
160
- @ <h2>Files of check-in [<a href="vinfo?name=%T(zUuid)">%s(zShort)</a>]
162
+ @ <h2>Files of check-in [%z(href("vinfo?name=%T",zUuid))%s(zShort)</a>]
161163
@ %s(blob_str(&dirname))</h2>
162
- zSubdirLink = mprintf("%s/dir?ci=%S&amp;name=%T", g.zTop, zUuid, zPrefix);
164
+ zSubdirLink = mprintf("%R/dir?ci=%S&amp;name=%T", zUuid, zPrefix);
163165
if( zD ){
164
- style_submenu_element("Top", "Top", "%s/dir?ci=%S", g.zTop, zUuid);
165
- style_submenu_element("All", "All", "%s/dir?name=%t", g.zTop, zD);
166
+ style_submenu_element("Top", "Top", "%R/dir?ci=%S", zUuid);
167
+ style_submenu_element("All", "All", "%R/dir?name=%t", zD);
166168
}else{
167
- style_submenu_element("All", "All", "%s/dir", g.zTop);
169
+ style_submenu_element("All", "All", "%R/dir");
168170
}
169171
}else{
170172
int hasTrunk;
171173
@ <h2>The union of all files from all check-ins
172174
@ %s(blob_str(&dirname))</h2>
173175
hasTrunk = db_exists(
174176
"SELECT 1 FROM tagxref WHERE tagid=%d AND value='trunk'",
175177
TAG_BRANCH);
176
- zSubdirLink = mprintf("%s/dir?name=%T", g.zTop, zPrefix);
178
+ zSubdirLink = mprintf("%R/dir?name=%T", zPrefix);
177179
if( zD ){
178
- style_submenu_element("Top", "Top", "%s/dir", g.zTop);
179
- style_submenu_element("Tip", "Tip", "%s/dir?name=%t&amp;ci=tip",
180
- g.zTop, zD);
180
+ style_submenu_element("Top", "Top", "%R/dir");
181
+ style_submenu_element("Tip", "Tip", "%R/dir?name=%t&amp;ci=tip", zD);
181182
if( hasTrunk ){
182
- style_submenu_element("Trunk", "Trunk", "%s/dir?name=%t&amp;ci=trunk",
183
- g.zTop,zD);
183
+ style_submenu_element("Trunk", "Trunk", "%R/dir?name=%t&amp;ci=trunk",
184
+ zD);
184185
}
185186
}else{
186
- style_submenu_element("Tip", "Tip", "%s/dir?ci=tip", g.zTop);
187
+ style_submenu_element("Tip", "Tip", "%R/dir?ci=tip");
187188
if( hasTrunk ){
188
- style_submenu_element("Trunk", "Trunk", "%s/dir?ci=trunk", g.zTop);
189
+ style_submenu_element("Trunk", "Trunk", "%R/dir?ci=trunk");
189190
}
190191
}
191192
}
192193
193194
/* Compute the temporary table "localfiles" containing the names
@@ -278,19 +279,19 @@
278279
}
279280
i++;
280281
zFN = db_column_text(&q, 0);
281282
if( zFN[0]=='/' ){
282283
zFN++;
283
- @ <li><a href="%s(zSubdirLink)%T(zFN)">%h(zFN)/</a></li>
284
+ @ <li>%z(href("%s%T",zSubdirLink,zFN))%h(zFN)</a></li>
284285
}else if( zCI ){
285286
const char *zUuid = db_column_text(&q, 1);
286
- @ <li><a href="%s(g.zTop)/artifact/%s(zUuid)">%h(zFN)</a></li>
287
+ @ <li>%z(href("%R/artifact/%s",zUuid))%h(zFN)</a></li>
287288
}else{
288
- @ <li><a href="%s(g.zTop)/finfo?name=%T(zPrefix)%T(zFN)">%h(zFN)
289
+ @ <li>%z(href("%R/finfo?name=%T%T",zPrefix,zFN))%h(zFN)
289290
@ </a></li>
290291
}
291292
}
292293
db_finalize(&q);
293294
manifest_destroy(pM);
294295
@ </ul></td></tr></table>
295296
style_footer();
296297
}
297298
--- src/browse.c
+++ src/browse.c
@@ -79,15 +79,17 @@
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 blob_appendf(pOut, "%s<a href=\"%s/dir?ci=%S&amp;name=%#T\">%#h</a>",
85 zSep, g.zTop, zCI, j, zPath, j-i, &zPath[i]);
 
86 }else{
87 blob_appendf(pOut, "%s<a href=\"%s/dir?name=%#T\">%#h</a>",
88 zSep, g.zTop, j, zPath, j-i, &zPath[i]);
 
89 }
90 }else{
91 blob_appendf(pOut, "%s%#h", zSep, j-i, &zPath[i]);
92 }
93 zSep = "/";
@@ -155,39 +157,38 @@
155 }
156 if( zCI ){
157 char zShort[20];
158 memcpy(zShort, zUuid, 10);
159 zShort[10] = 0;
160 @ <h2>Files of check-in [<a href="vinfo?name=%T(zUuid)">%s(zShort)</a>]
161 @ %s(blob_str(&dirname))</h2>
162 zSubdirLink = mprintf("%s/dir?ci=%S&amp;name=%T", g.zTop, zUuid, zPrefix);
163 if( zD ){
164 style_submenu_element("Top", "Top", "%s/dir?ci=%S", g.zTop, zUuid);
165 style_submenu_element("All", "All", "%s/dir?name=%t", g.zTop, zD);
166 }else{
167 style_submenu_element("All", "All", "%s/dir", g.zTop);
168 }
169 }else{
170 int hasTrunk;
171 @ <h2>The union of all files from all check-ins
172 @ %s(blob_str(&dirname))</h2>
173 hasTrunk = db_exists(
174 "SELECT 1 FROM tagxref WHERE tagid=%d AND value='trunk'",
175 TAG_BRANCH);
176 zSubdirLink = mprintf("%s/dir?name=%T", g.zTop, zPrefix);
177 if( zD ){
178 style_submenu_element("Top", "Top", "%s/dir", g.zTop);
179 style_submenu_element("Tip", "Tip", "%s/dir?name=%t&amp;ci=tip",
180 g.zTop, zD);
181 if( hasTrunk ){
182 style_submenu_element("Trunk", "Trunk", "%s/dir?name=%t&amp;ci=trunk",
183 g.zTop,zD);
184 }
185 }else{
186 style_submenu_element("Tip", "Tip", "%s/dir?ci=tip", g.zTop);
187 if( hasTrunk ){
188 style_submenu_element("Trunk", "Trunk", "%s/dir?ci=trunk", g.zTop);
189 }
190 }
191 }
192
193 /* Compute the temporary table "localfiles" containing the names
@@ -278,19 +279,19 @@
278 }
279 i++;
280 zFN = db_column_text(&q, 0);
281 if( zFN[0]=='/' ){
282 zFN++;
283 @ <li><a href="%s(zSubdirLink)%T(zFN)">%h(zFN)/</a></li>
284 }else if( zCI ){
285 const char *zUuid = db_column_text(&q, 1);
286 @ <li><a href="%s(g.zTop)/artifact/%s(zUuid)">%h(zFN)</a></li>
287 }else{
288 @ <li><a href="%s(g.zTop)/finfo?name=%T(zPrefix)%T(zFN)">%h(zFN)
289 @ </a></li>
290 }
291 }
292 db_finalize(&q);
293 manifest_destroy(pM);
294 @ </ul></td></tr></table>
295 style_footer();
296 }
297
--- src/browse.c
+++ src/browse.c
@@ -79,15 +79,17 @@
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>",
90 zSep, zLink, j-i, &zPath[i]);
91 }
92 }else{
93 blob_appendf(pOut, "%s%#h", zSep, j-i, &zPath[i]);
94 }
95 zSep = "/";
@@ -155,39 +157,38 @@
157 }
158 if( zCI ){
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");
170 }
171 }else{
172 int hasTrunk;
173 @ <h2>The union of all files from all check-ins
174 @ %s(blob_str(&dirname))</h2>
175 hasTrunk = db_exists(
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 style_submenu_element("Trunk", "Trunk", "%R/dir?ci=trunk");
190 }
191 }
192 }
193
194 /* Compute the temporary table "localfiles" containing the names
@@ -278,19 +279,19 @@
279 }
280 i++;
281 zFN = db_column_text(&q, 0);
282 if( zFN[0]=='/' ){
283 zFN++;
284 @ <li>%z(href("%s%T",zSubdirLink,zFN))%h(zFN)</a></li>
285 }else if( zCI ){
286 const char *zUuid = db_column_text(&q, 1);
287 @ <li>%z(href("%R/artifact/%s",zUuid))%h(zFN)</a></li>
288 }else{
289 @ <li>%z(href("%R/finfo?name=%T%T",zPrefix,zFN))%h(zFN)
290 @ </a></li>
291 }
292 }
293 db_finalize(&q);
294 manifest_destroy(pM);
295 @ </ul></td></tr></table>
296 style_footer();
297 }
298
+3 -3
--- src/diff.c
+++ src/diff.c
@@ -1778,12 +1778,12 @@
17781778
const char *zUuid = db_column_text(&q, 1);
17791779
const char *zDate = db_column_text(&q, 2);
17801780
const char *zUser = db_column_text(&q, 3);
17811781
if( webLabel ){
17821782
zLabel = mprintf(
1783
- "<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %13.13s",
1784
- g.zTop, zUuid, zUuid, zDate, zUser
1783
+ "<a href='%R/info/%s' target='infowindow'>%.10s</a> %s %13.13s",
1784
+ zUuid, zUuid, zDate, zUser
17851785
);
17861786
}else{
17871787
zLabel = mprintf("%.10s %s %13.13s", zUuid, zDate, zUser);
17881788
}
17891789
p->nVers++;
@@ -1821,11 +1821,11 @@
18211821
if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
18221822
fossil_redirect_home();
18231823
}
18241824
style_header("File Annotation");
18251825
if( P("filevers") ) annFlags |= ANN_FILE_VERS;
1826
- annotate_file(&ann, fnid, mid, g.perm.History, iLimit, annFlags);
1826
+ annotate_file(&ann, fnid, mid, g.perm.Hyperlink, iLimit, annFlags);
18271827
if( P("log") ){
18281828
int i;
18291829
@ <h2>Versions analyzed:</h2>
18301830
@ <ol>
18311831
for(i=0; i<ann.nVers; i++){
18321832
--- src/diff.c
+++ src/diff.c
@@ -1778,12 +1778,12 @@
1778 const char *zUuid = db_column_text(&q, 1);
1779 const char *zDate = db_column_text(&q, 2);
1780 const char *zUser = db_column_text(&q, 3);
1781 if( webLabel ){
1782 zLabel = mprintf(
1783 "<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %13.13s",
1784 g.zTop, zUuid, zUuid, zDate, zUser
1785 );
1786 }else{
1787 zLabel = mprintf("%.10s %s %13.13s", zUuid, zDate, zUser);
1788 }
1789 p->nVers++;
@@ -1821,11 +1821,11 @@
1821 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
1822 fossil_redirect_home();
1823 }
1824 style_header("File Annotation");
1825 if( P("filevers") ) annFlags |= ANN_FILE_VERS;
1826 annotate_file(&ann, fnid, mid, g.perm.History, iLimit, annFlags);
1827 if( P("log") ){
1828 int i;
1829 @ <h2>Versions analyzed:</h2>
1830 @ <ol>
1831 for(i=0; i<ann.nVers; i++){
1832
--- src/diff.c
+++ src/diff.c
@@ -1778,12 +1778,12 @@
1778 const char *zUuid = db_column_text(&q, 1);
1779 const char *zDate = db_column_text(&q, 2);
1780 const char *zUser = db_column_text(&q, 3);
1781 if( webLabel ){
1782 zLabel = mprintf(
1783 "<a href='%R/info/%s' target='infowindow'>%.10s</a> %s %13.13s",
1784 zUuid, zUuid, zDate, zUser
1785 );
1786 }else{
1787 zLabel = mprintf("%.10s %s %13.13s", zUuid, zDate, zUser);
1788 }
1789 p->nVers++;
@@ -1821,11 +1821,11 @@
1821 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
1822 fossil_redirect_home();
1823 }
1824 style_header("File Annotation");
1825 if( P("filevers") ) annFlags |= ANN_FILE_VERS;
1826 annotate_file(&ann, fnid, mid, g.perm.Hyperlink, iLimit, annFlags);
1827 if( P("log") ){
1828 int i;
1829 @ <h2>Versions analyzed:</h2>
1830 @ <ol>
1831 for(i=0; i<ann.nVers; i++){
1832
+6 -13
--- src/event.c
+++ src/event.c
@@ -31,20 +31,13 @@
3131
/*
3232
** Output a hyperlink to an event given its tagid.
3333
*/
3434
void hyperlink_to_event_tagid(int tagid){
3535
char *zEventId;
36
- char zShort[12];
37
-
3836
zEventId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d",
3937
tagid);
40
- sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zEventId);
41
- if( g.perm.History ){
42
- @ [<a href="%s(g.zTop)/event?name=%s(zEventId)">%s(zShort)</a>]
43
- }else{
44
- @ [%s(zShort)]
45
- }
38
+ @ [%z(href("%R/event/%s",zEventId))%S(zEventId)</a>]
4639
free(zEventId);
4740
}
4841
4942
/*
5043
** WEBPAGE: event
@@ -130,11 +123,11 @@
130123
g.zTop, zEventId);
131124
}
132125
zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
133126
style_submenu_element("Context", "Context", "%s/timeline?c=%T",
134127
g.zTop, zETime);
135
- if( g.perm.History ){
128
+ if( g.perm.Hyperlink ){
136129
if( showDetail ){
137130
style_submenu_element("Plain", "Plain", "%s/event?name=%s&amp;aid=%s",
138131
g.zTop, zEventId, zUuid);
139132
if( nextRid ){
140133
char *zNext;
@@ -157,20 +150,20 @@
157150
"%s/event?name=%s&amp;aid=%s&amp;detail=1",
158151
g.zTop, zEventId, zUuid);
159152
}
160153
}
161154
162
- if( showDetail && g.perm.History ){
155
+ if( showDetail && g.perm.Hyperlink ){
163156
int i;
164157
const char *zClr = 0;
165158
Blob comment;
166159
167160
zATime = db_text(0, "SELECT datetime(%.17g)", pEvent->rDate);
168
- @ <p>Event [<a href="%s(g.zTop)/artifact/%s(zUuid)">%S(zUuid)</a>] at
169
- @ [<a href="%s(g.zTop)/timeline?c=%T(zETime)">%s(zETime)</a>]
161
+ @ <p>Event [%z(href("%R/artifact/%s",zUuid))%S(zUuid)</a>] at
162
+ @ [%z(href("%R/timeline?c=%T",zETime))%s(zETime)</a>]
170163
@ entered by user <b>%h(pEvent->zUser)</b> on
171
- @ [<a href="%s(g.zTop)/timeline?c=%T(zATime)">%s(zATime)</a>]:</p>
164
+ @ [%z(href("%R/timeline?c=%T",zATime))%s(zATime)</a>]:</p>
172165
@ <blockquote>
173166
for(i=0; i<pEvent->nTag; i++){
174167
if( fossil_strcmp(pEvent->aTag[i].zName,"+bgcolor")==0 ){
175168
zClr = pEvent->aTag[i].zValue;
176169
}
177170
--- src/event.c
+++ src/event.c
@@ -31,20 +31,13 @@
31 /*
32 ** Output a hyperlink to an event given its tagid.
33 */
34 void hyperlink_to_event_tagid(int tagid){
35 char *zEventId;
36 char zShort[12];
37
38 zEventId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d",
39 tagid);
40 sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zEventId);
41 if( g.perm.History ){
42 @ [<a href="%s(g.zTop)/event?name=%s(zEventId)">%s(zShort)</a>]
43 }else{
44 @ [%s(zShort)]
45 }
46 free(zEventId);
47 }
48
49 /*
50 ** WEBPAGE: event
@@ -130,11 +123,11 @@
130 g.zTop, zEventId);
131 }
132 zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate);
133 style_submenu_element("Context", "Context", "%s/timeline?c=%T",
134 g.zTop, zETime);
135 if( g.perm.History ){
136 if( showDetail ){
137 style_submenu_element("Plain", "Plain", "%s/event?name=%s&amp;aid=%s",
138 g.zTop, zEventId, zUuid);
139 if( nextRid ){
140 char *zNext;
@@ -157,20 +150,20 @@
157 "%s/event?name=%s&amp;aid=%s&amp;detail=1",
158 g.zTop, zEventId, zUuid);
159 }
160 }
161
162 if( showDetail && g.perm.History ){
163 int i;
164 const char *zClr = 0;
165 Blob comment;
166
167 zATime = db_text(0, "SELECT datetime(%.17g)", pEvent->rDate);
168 @ <p>Event [<a href="%s(g.zTop)/artifact/%s(zUuid)">%S(zUuid)</a>] at
169 @ [<a href="%s(g.zTop)/timeline?c=%T(zETime)">%s(zETime)</a>]
170 @ entered by user <b>%h(pEvent->zUser)</b> on
171 @ [<a href="%s(g.zTop)/timeline?c=%T(zATime)">%s(zATime)</a>]:</p>
172 @ <blockquote>
173 for(i=0; i<pEvent->nTag; i++){
174 if( fossil_strcmp(pEvent->aTag[i].zName,"+bgcolor")==0 ){
175 zClr = pEvent->aTag[i].zValue;
176 }
177
--- src/event.c
+++ src/event.c
@@ -31,20 +31,13 @@
31 /*
32 ** Output a hyperlink to an event given its tagid.
33 */
34 void hyperlink_to_event_tagid(int tagid){
35 char *zEventId;
 
 
36 zEventId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d",
37 tagid);
38 @ [%z(href("%R/event/%s",zEventId))%S(zEventId)</a>]
 
 
 
 
 
39 free(zEventId);
40 }
41
42 /*
43 ** WEBPAGE: event
@@ -130,11 +123,11 @@
123 g.zTop, zEventId);
124 }
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;
@@ -157,20 +150,20 @@
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 int i;
157 const char *zClr = 0;
158 Blob comment;
159
160 zATime = db_text(0, "SELECT datetime(%.17g)", pEvent->rDate);
161 @ <p>Event [%z(href("%R/artifact/%s",zUuid))%S(zUuid)</a>] at
162 @ [%z(href("%R/timeline?c=%T",zETime))%s(zETime)</a>]
163 @ entered by user <b>%h(pEvent->zUser)</b> on
164 @ [%z(href("%R/timeline?c=%T",zATime))%s(zATime)</a>]:</p>
165 @ <blockquote>
166 for(i=0; i<pEvent->nTag; i++){
167 if( fossil_strcmp(pEvent->aTag[i].zName,"+bgcolor")==0 ){
168 zClr = pEvent->aTag[i].zValue;
169 }
170
+4 -9
--- src/finfo.c
+++ src/finfo.c
@@ -305,26 +305,21 @@
305305
@ </td></tr>
306306
}
307307
memcpy(zTime, &zDate[11], 5);
308308
zTime[5] = 0;
309309
@ <tr><td class="timelineTime">
310
- @ <a href="%s(g.zTop)/timeline?c=%t(zDate)">%s(zTime)</a></td>
310
+ @ %z(href("%R/timeline?c=%t",zDate))%s(zTime)</a></td>
311311
@ <td class="timelineGraph"><div id="m%d(gidx)"></div></td>
312312
if( zBgClr && zBgClr[0] ){
313313
@ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
314314
}else{
315315
@ <td class="timelineTableCell">
316316
}
317317
sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid);
318318
sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin);
319319
if( zUuid ){
320
- if( g.perm.History ){
321
- @ <a href="%s(g.zTop)/artifact/%s(zUuid)">[%S(zUuid)]</a>
322
- }else{
323
- @ [%S(zUuid)]
324
- }
325
- @ part of check-in
320
+ @ %z(href("%R/artifact/%s",zUuid))[%S(zUuid)]</a> part of check-in
326321
}else{
327322
@ <b>Deleted</b> by check-in
328323
}
329324
hyperlink_to_uuid(zShortCkin);
330325
@ %h(zCom) (user:
@@ -331,13 +326,13 @@
331326
hyperlink_to_user(zUser, zDate, "");
332327
@ branch: %h(zBr))
333328
if( g.perm.History && zUuid ){
334329
const char *z = zFilename;
335330
if( fpid ){
336
- @ <a href="%s(g.zTop)/fdiff?v1=%s(zPUuid)&amp;v2=%s(zUuid)">[diff]</a>
331
+ @ %z(href("%R/fdiff?v1=%s&amp;v2=%s",zPUuid,zUuid))[diff]</a>
337332
}
338
- @ <a href="%s(g.zTop)/annotate?checkin=%S(zCkin)&amp;filename=%h(z)">
333
+ @ %z(href("%R/annotate?checkin=%S&amp;filename=%h",zCkin,z))
339334
@ [annotate]</a>
340335
}
341336
@ </td></tr>
342337
}
343338
db_finalize(&q);
344339
--- src/finfo.c
+++ src/finfo.c
@@ -305,26 +305,21 @@
305 @ </td></tr>
306 }
307 memcpy(zTime, &zDate[11], 5);
308 zTime[5] = 0;
309 @ <tr><td class="timelineTime">
310 @ <a href="%s(g.zTop)/timeline?c=%t(zDate)">%s(zTime)</a></td>
311 @ <td class="timelineGraph"><div id="m%d(gidx)"></div></td>
312 if( zBgClr && zBgClr[0] ){
313 @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
314 }else{
315 @ <td class="timelineTableCell">
316 }
317 sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid);
318 sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin);
319 if( zUuid ){
320 if( g.perm.History ){
321 @ <a href="%s(g.zTop)/artifact/%s(zUuid)">[%S(zUuid)]</a>
322 }else{
323 @ [%S(zUuid)]
324 }
325 @ part of check-in
326 }else{
327 @ <b>Deleted</b> by check-in
328 }
329 hyperlink_to_uuid(zShortCkin);
330 @ %h(zCom) (user:
@@ -331,13 +326,13 @@
331 hyperlink_to_user(zUser, zDate, "");
332 @ branch: %h(zBr))
333 if( g.perm.History && zUuid ){
334 const char *z = zFilename;
335 if( fpid ){
336 @ <a href="%s(g.zTop)/fdiff?v1=%s(zPUuid)&amp;v2=%s(zUuid)">[diff]</a>
337 }
338 @ <a href="%s(g.zTop)/annotate?checkin=%S(zCkin)&amp;filename=%h(z)">
339 @ [annotate]</a>
340 }
341 @ </td></tr>
342 }
343 db_finalize(&q);
344
--- src/finfo.c
+++ src/finfo.c
@@ -305,26 +305,21 @@
305 @ </td></tr>
306 }
307 memcpy(zTime, &zDate[11], 5);
308 zTime[5] = 0;
309 @ <tr><td class="timelineTime">
310 @ %z(href("%R/timeline?c=%t",zDate))%s(zTime)</a></td>
311 @ <td class="timelineGraph"><div id="m%d(gidx)"></div></td>
312 if( zBgClr && zBgClr[0] ){
313 @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
314 }else{
315 @ <td class="timelineTableCell">
316 }
317 sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid);
318 sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin);
319 if( zUuid ){
320 @ %z(href("%R/artifact/%s",zUuid))[%S(zUuid)]</a> part of check-in
 
 
 
 
 
321 }else{
322 @ <b>Deleted</b> by check-in
323 }
324 hyperlink_to_uuid(zShortCkin);
325 @ %h(zCom) (user:
@@ -331,13 +326,13 @@
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
+60 -75
--- src/info.c
+++ src/info.c
@@ -261,11 +261,11 @@
261261
@ propagates to descendants
262262
}
263263
#if 0
264264
if( zValue && fossil_strcmp(zTagname,"branch")==0 ){
265265
@ &nbsp;&nbsp;
266
- @ <a href="%s(g.zTop)/timeline?r=%T(zValue)">branch timeline</a>
266
+ @ %z(href("%R/timeline?r=%T",zValue))branch timeline</a>
267267
}
268268
#endif
269269
}
270270
if( zSrcUuid && zSrcUuid[0] ){
271271
if( tagtype==0 ){
@@ -333,11 +333,11 @@
333333
const char *zNew, /* blob.uuid after change. NULL for deletes */
334334
const char *zOldName, /* Prior name. NULL if no name change. */
335335
int diffFlags, /* Flags for text_diff(). Zero to omit diffs */
336336
int mperm /* executable or symlink permission for zNew */
337337
){
338
- if( !g.perm.History ){
338
+ if( !g.perm.Hyperlink ){
339339
if( zNew==0 ){
340340
@ <p>Deleted %h(zName)</p>
341341
}else if( zOld==0 ){
342342
@ <p>Added %h(zName)</p>
343343
}else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
@@ -354,35 +354,35 @@
354354
@ </pre>
355355
}
356356
}else{
357357
if( zOld && zNew ){
358358
if( fossil_strcmp(zOld, zNew)!=0 ){
359
- @ <p>Modified <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
360
- @ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
361
- @ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a>
359
+ @ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
360
+ @ from %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a>
361
+ @ to %z(href("%R/artifact/%s",zNew))[%S(zNew)].</a>
362362
}else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
363363
@ <p>Name change from
364
- @ from <a href="%s(g.zTop)/finfo?name=%T(zOldName)">%h(zOldName)</a>
365
- @ to <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>.
364
+ @ from %z(href("%R/finfo?name=%T",zOldName))%h(zOldName)</a>
365
+ @ to %z(href("%R/finfo?name=%T",zName))%h(zName)</a>.
366366
}else{
367367
@ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for
368
- @ <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
368
+ @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
369369
}
370370
}else if( zOld ){
371
- @ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
372
- @ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
371
+ @ <p>Deleted %z(href("%s/finfo?name=%T",g.zTop,zName))%h(zName)</a>
372
+ @ version %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a>
373373
}else{
374
- @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
375
- @ version <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)]</a>
374
+ @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
375
+ @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a>
376376
}
377377
if( diffFlags ){
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
- @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&amp;v2=%S(zNew)">[diff]</a>
383
+ @ %z(href("%R/fdiff?v1=%S&amp;v2=%S",zOld,zNew))[diff]</a>
384384
}
385385
@ </p>
386386
}
387387
}
388388
@@ -535,47 +535,47 @@
535535
@ <tr><th>Received&nbsp;From:</th>
536536
@ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr>
537537
}
538538
db_finalize(&q);
539539
}
540
- if( g.perm.History ){
540
+ if( g.perm.Hyperlink ){
541541
const char *zProjName = db_get("project-name", "unnamed");
542542
@ <tr><th>Timelines:</th><td>
543
- @ <a href="%s(g.zTop)/timeline?f=%S(zUuid)">family</a>
543
+ @ %z(href("%R/timeline?f=%S",zUuid))family</a>
544544
if( zParent ){
545
- @ | <a href="%s(g.zTop)/timeline?p=%S(zUuid)">ancestors</a>
545
+ @ | %z(href("%R/timeline?p=%S",zUuid))ancestors</a>
546546
}
547547
if( !isLeaf ){
548
- @ | <a href="%s(g.zTop)/timeline?d=%S(zUuid)">descendants</a>
548
+ @ | %z(href("%R/timeline?d=%S",zUuid))descendants</a>
549549
}
550550
if( zParent && !isLeaf ){
551
- @ | <a href="%s(g.zTop)/timeline?dp=%S(zUuid)">both</a>
551
+ @ | %z(href("%R/timeline?dp=%S",zUuid))both</a>
552552
}
553553
db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag "
554554
" WHERE rid=%d AND tagtype>0 "
555555
" AND tag.tagid=tagxref.tagid "
556556
" AND +tag.tagname GLOB 'sym-*'", rid);
557557
while( db_step(&q)==SQLITE_ROW ){
558558
const char *zTagName = db_column_text(&q, 0);
559
- @ | <a href="%s(g.zTop)/timeline?r=%T(zTagName)">%h(zTagName)</a>
559
+ @ | %z(href("%R/timeline?r=%T",zTagName))%h(zTagName)</a>
560560
}
561561
db_finalize(&q);
562562
@ </td></tr>
563563
@ <tr><th>Other&nbsp;Links:</th>
564564
@ <td>
565
- @ <a href="%s(g.zTop)/dir?ci=%S(zUuid)">files</a>
565
+ @ %z(href("%R/dir?ci=%S",zUuid))files</a>
566566
if( g.perm.Zip ){
567
- char *zUrl = mprintf("%s/tarball/%s-%S.tar.gz?uuid=%s",
568
- g.zTop, zProjName, zUuid, zUuid);
569
- @ | <a href="%s(zUrl)">Tarball</a>
570
- @ | <a href="%s(g.zTop)/zip/%s(zProjName)-%S(zUuid).zip?uuid=%s(zUuid)">
567
+ char *zUrl = mprintf("%R/tarball/%s-%S.tar.gz?uuid=%s",
568
+ zProjName, zUuid, zUuid);
569
+ @ | %z(href("%s",zUrl))Tarball</a>
570
+ @ | %z(href("%R/zip/%s-%S.zip?uuid=%s",zProjName,zUuid,zUuid))
571571
@ ZIP archive</a>
572572
fossil_free(zUrl);
573573
}
574
- @ | <a href="%s(g.zTop)/artifact/%S(zUuid)">manifest</a>
574
+ @ | %z(href("%R/artifact/%S",zUuid))manifest</a>
575575
if( g.perm.Write ){
576
- @ | <a href="%s(g.zTop)/ci_edit?r=%S(zUuid)">edit</a>
576
+ @ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a>
577577
}
578578
@ </td>
579579
@ </tr>
580580
}
581581
@ </table>
@@ -590,43 +590,43 @@
590590
@ <div class="sectionmenu">
591591
showDiff = g.zPath[0]!='c';
592592
if( db_get_boolean("show-version-diffs", 0)==0 ){
593593
showDiff = !showDiff;
594594
if( showDiff ){
595
- @ <a class="button" href="%s(g.zTop)/vinfo/%T(zName)">
595
+ @ %z(xhref("class='button'","%R/vinfo/%T",zName)))
596596
@ hide&nbsp;diffs</a>
597597
if( sideBySide ){
598
- @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=0">
598
+ @ %z(xhref("class='button'","%R/ci/%T?sbs=0",zName))
599599
@ unified&nbsp;diffs</a>
600600
}else{
601
- @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=1">
601
+ @ %z(xhref("class='button'","%R/ci/%T?sbs=1",zName))
602602
@ side-by-side&nbsp;diffs</a>
603603
}
604604
}else{
605
- @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=0">
605
+ @ %z(xhref("class='button'","%R/ci/%T?sbs=0",zName))
606606
@ show&nbsp;unified&nbsp;diffs</a>
607
- @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=1">
607
+ @ %z(xhref("class='button'","%R/ci/%T?sbs=1",zName))
608608
@ show&nbsp;side-by-side&nbsp;diffs</a>
609609
}
610610
}else{
611611
if( showDiff ){
612
- @ <a class="button" href="%s(g.zTop)/ci/%T(zName)">hide&nbsp;diffs</a>
612
+ @ %z(xhref("class='button'","%R/ci/%T",zName))hide&nbsp;diffs</a>
613613
if( sideBySide ){
614
- @ <a class="button" href="%s(g.zTop)/info/%T(zName)?sbs=0">
614
+ @ %z(xhref("class='button'","%R/info/%T?sbs=0",zName))
615615
@ unified&nbsp;diffs</a>
616616
}else{
617
- @ <a class="button" href="%s(g.zTop)/info/%T(zName)?sbs=1">
617
+ @ %z(xhref("class='button'","%R/info/%T?sbs=1",zName))
618618
@ side-by-side&nbsp;diffs</a>
619619
}
620620
}else{
621
- @ <a class="button" href="%s(g.zTop)/vinfo/%T(zName)?sbs=0">
621
+ @ %z(xhref("class='button'","%R/vinfo/%T?sbs=0",zName))
622622
@ show&nbsp;unified&nbsp;diffs</a>
623
- @ <a class="button" href="%s(g.zTop)/vinfo/%T(zName)?sbs=1">
623
+ @ %z(xhref("class='button'","%R/vinfo/%T?sbs=1",zName))
624624
@ show&nbsp;side-by-side&nbsp;diffs</a>
625625
}
626626
}
627
- @ <a class="button" href="%s(g.zTop)/vpatch?from=%S(zParent)&to=%S(zUuid)">
627
+ @ %z(xhref("class='button'","%R/vpatch?from=%S&amp;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),"
@@ -698,15 +698,15 @@
698698
if( g.perm.Setup ){
699699
@ <tr><th>Record ID:</th><td>%d(rid)</td></tr>
700700
}
701701
@ <tr><th>Original&nbsp;User:</th><td>
702702
hyperlink_to_user(zUser, zDate, "</td></tr>");
703
- if( g.perm.History ){
703
+ if( g.perm.Hyperlink ){
704704
@ <tr><th>Commands:</th>
705705
@ <td>
706
- @ <a href="%s(g.zTop)/whistory?name=%t(zName)">history</a>
707
- @ | <a href="%s(g.zTop)/artifact/%S(zUuid)">raw-text</a>
706
+ @ &z(href("%R/whistory?name=%t",zName))history</a>
707
+ @ | %z(href("%R/artifact/%S",zUuid))raw-text</a>
708708
@ </td>
709709
@ </tr>
710710
}
711711
@ </table></p>
712712
}else{
@@ -936,34 +936,26 @@
936936
}else if( mPerm==PERM_EXE ){
937937
@ <li>Executable file
938938
}else{
939939
@ <li>File
940940
}
941
- if( g.perm.History ){
942
- @ <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
943
- }else{
944
- @ %h(zName)
945
- }
941
+ @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
946942
@ <ul>
947943
prevName = fossil_strdup(zName);
948944
}
949945
@ <li>
950946
hyperlink_to_date(zDate,"");
951947
@ - part of checkin
952948
hyperlink_to_uuid(zVers);
953949
if( zBr && zBr[0] ){
954
- if( g.perm.History ){
955
- @ on branch <a href="%s(g.zTop)/timeline?r=%T(zBr)">%h(zBr)</a>
956
- }else{
957
- @ on branch %h(zBr)
958
- }
950
+ @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a>
959951
}
960952
@ - %w(zCom) (user:
961953
hyperlink_to_user(zUser,zDate,"");
962954
@ )
963
- if( g.perm.History ){
964
- @ <a href="%s(g.zTop)/annotate?checkin=%S(zVers)&filename=%T(zName)">
955
+ if( g.perm.Hyperlink ){
956
+ @ %z(href("%R/annotate?checkin=%S&filename=%T",zVers,zName))
965957
@ [annotate]</a>
966958
}
967959
cnt++;
968960
if( pDownloadName && blob_size(pDownloadName)==0 ){
969961
blob_append(pDownloadName, zName, -1);
@@ -989,16 +981,11 @@
989981
if( cnt>0 ){
990982
@ Also wiki page
991983
}else{
992984
@ Wiki page
993985
}
994
- if( g.perm.History ){
995
- @ [<a href="%s(g.zTop)/wiki?name=%t(zPagename)">%h(zPagename)</a>]
996
- }else{
997
- @ [%h(zPagename)]
998
- }
999
- @ by
986
+ @ [%z(href("%R/wiki?name=%t",zPagename))%h(zPagename)</a>] by
1000987
hyperlink_to_user(zUser,zDate," on");
1001988
hyperlink_to_date(zDate,".");
1002989
nWiki++;
1003990
cnt++;
1004991
if( pDownloadName && blob_size(pDownloadName)==0 ){
@@ -1065,18 +1052,18 @@
10651052
@ Also attachment "%h(zFilename)" to
10661053
}else{
10671054
@ Attachment "%h(zFilename)" to
10681055
}
10691056
if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
1070
- if( g.perm.History && g.perm.RdTkt ){
1071
- @ ticket [<a href="%s(g.zTop)/tktview?name=%S(zTarget)">%S(zTarget)</a>]
1057
+ if( g.perm.Hyperlink && g.perm.RdTkt ){
1058
+ @ ticket [%z(href("%R/tktview?name=%S",zTarget))%S(zTarget)</a>]
10721059
}else{
10731060
@ ticket [%S(zTarget)]
10741061
}
10751062
}else{
1076
- if( g.perm.History && g.perm.RdWiki ){
1077
- @ wiki page [<a href="%s(g.zTop)/wiki?name=%t(zTarget)">%h(zTarget)</a>]
1063
+ if( g.perm.Hyperlink && g.perm.RdWiki ){
1064
+ @ wiki page [%z(href("%R/wiki?name=%t",zTarget)))%h(zTarget)</a>]
10781065
}else{
10791066
@ wiki page [%h(zTarget)]
10801067
}
10811068
}
10821069
@ added by
@@ -1091,12 +1078,12 @@
10911078
if( cnt==0 ){
10921079
@ Control artifact.
10931080
if( pDownloadName && blob_size(pDownloadName)==0 ){
10941081
blob_appendf(pDownloadName, "%.10s.txt", zUuid);
10951082
}
1096
- }else if( linkToView && g.perm.History ){
1097
- @ <a href="%s(g.zTop)/artifact/%S(zUuid)">[view]</a>
1083
+ }else if( linkToView && g.perm.Hyperlink ){
1084
+ @ %z(href("%R/artifact/%S",zUuid))[view]</a>
10981085
}
10991086
}
11001087
11011088
11021089
/*
@@ -1160,18 +1147,17 @@
11601147
g.zTop, P("v1"), P("v2"));
11611148
}
11621149
11631150
if( P("smhdr")!=0 ){
11641151
@ <h2>Differences From Artifact
1165
- @ <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a> To
1166
- @ <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>.</h2>
1152
+ @ %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a> To
1153
+ @ %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>.</h2>
11671154
}else{
11681155
@ <h2>Differences From
1169
- @ Artifact <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a>:</h2>
1156
+ @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2>
11701157
object_description(v1, 0, 0);
1171
- @ <h2>To Artifact
1172
- @ <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>:</h2>
1158
+ @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2>
11731159
object_description(v2, 0, 0);
11741160
}
11751161
@ <hr />
11761162
@ <div class="%s(zStyle)">
11771163
@ %s(blob_str(&diff))
@@ -1522,18 +1508,17 @@
15221508
}
15231509
style_header("Ticket Change Details");
15241510
zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
15251511
memcpy(zTktName, pTktChng->zTicketUuid, 10);
15261512
zTktName[10] = 0;
1527
- if( g.perm.History ){
1513
+ if( g.perm.Hyperlink ){
15281514
@ <h2>Changes to ticket
1529
- @ <a href="%s(pTktChng->zTicketUuid)">%s(zTktName)</a></h2>
1515
+ @ %z(href("%R/tktview/%s",pTktChng->zTicketUuid)))%s(zTktName)</a></h2>
15301516
@
15311517
@ <p>By %h(pTktChng->zUser) on %s(zDate). See also:
1532
- @ <a href="%s(g.zTop)/artifact/%T(zUuid)">artifact content</a>, and
1533
- @ <a href="%s(g.zTop)/tkthistory/%s(pTktChng->zTicketUuid)">ticket
1534
- @ history</a></p>
1518
+ @ %z(href("%R/artifact/%T",zUuid))artifact content</a>, and
1519
+ @ %z(href("%R/tkthistory/%s",pTktChng->zTicketUuid))ticket history</a></p>
15351520
}else{
15361521
@ <h2>Changes to ticket %s(zTktName)</h2>
15371522
@
15381523
@ <p>By %h(pTktChng->zUser) on %s(zDate).
15391524
@ </p>
@@ -1965,11 +1950,11 @@
19651950
@ </blockquote>
19661951
@ <hr />
19671952
blob_reset(&suffix);
19681953
}
19691954
@ <p>Make changes to attributes of check-in
1970
- @ [<a href="ci?name=%s(zUuid)">%s(zUuid)</a>]:</p>
1955
+ @ [%z(href("%R/ci/%s",zUuid))%s(zUuid)</a>]:</p>
19711956
@ <form action="%s(g.zTop)/ci_edit" method="post"><div>
19721957
login_insert_csrf_secret();
19731958
@ <input type="hidden" name="r" value="%S(zUuid)" />
19741959
@ <table border="0" cellspacing="10">
19751960
19761961
--- src/info.c
+++ src/info.c
@@ -261,11 +261,11 @@
261 @ propagates to descendants
262 }
263 #if 0
264 if( zValue && fossil_strcmp(zTagname,"branch")==0 ){
265 @ &nbsp;&nbsp;
266 @ <a href="%s(g.zTop)/timeline?r=%T(zValue)">branch timeline</a>
267 }
268 #endif
269 }
270 if( zSrcUuid && zSrcUuid[0] ){
271 if( tagtype==0 ){
@@ -333,11 +333,11 @@
333 const char *zNew, /* blob.uuid after change. NULL for deletes */
334 const char *zOldName, /* Prior name. NULL if no name change. */
335 int diffFlags, /* Flags for text_diff(). Zero to omit diffs */
336 int mperm /* executable or symlink permission for zNew */
337 ){
338 if( !g.perm.History ){
339 if( zNew==0 ){
340 @ <p>Deleted %h(zName)</p>
341 }else if( zOld==0 ){
342 @ <p>Added %h(zName)</p>
343 }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
@@ -354,35 +354,35 @@
354 @ </pre>
355 }
356 }else{
357 if( zOld && zNew ){
358 if( fossil_strcmp(zOld, zNew)!=0 ){
359 @ <p>Modified <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
360 @ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
361 @ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a>
362 }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
363 @ <p>Name change from
364 @ from <a href="%s(g.zTop)/finfo?name=%T(zOldName)">%h(zOldName)</a>
365 @ to <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>.
366 }else{
367 @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for
368 @ <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
369 }
370 }else if( zOld ){
371 @ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
372 @ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
373 }else{
374 @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
375 @ version <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)]</a>
376 }
377 if( diffFlags ){
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 @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&amp;v2=%S(zNew)">[diff]</a>
384 }
385 @ </p>
386 }
387 }
388
@@ -535,47 +535,47 @@
535 @ <tr><th>Received&nbsp;From:</th>
536 @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr>
537 }
538 db_finalize(&q);
539 }
540 if( g.perm.History ){
541 const char *zProjName = db_get("project-name", "unnamed");
542 @ <tr><th>Timelines:</th><td>
543 @ <a href="%s(g.zTop)/timeline?f=%S(zUuid)">family</a>
544 if( zParent ){
545 @ | <a href="%s(g.zTop)/timeline?p=%S(zUuid)">ancestors</a>
546 }
547 if( !isLeaf ){
548 @ | <a href="%s(g.zTop)/timeline?d=%S(zUuid)">descendants</a>
549 }
550 if( zParent && !isLeaf ){
551 @ | <a href="%s(g.zTop)/timeline?dp=%S(zUuid)">both</a>
552 }
553 db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag "
554 " WHERE rid=%d AND tagtype>0 "
555 " AND tag.tagid=tagxref.tagid "
556 " AND +tag.tagname GLOB 'sym-*'", rid);
557 while( db_step(&q)==SQLITE_ROW ){
558 const char *zTagName = db_column_text(&q, 0);
559 @ | <a href="%s(g.zTop)/timeline?r=%T(zTagName)">%h(zTagName)</a>
560 }
561 db_finalize(&q);
562 @ </td></tr>
563 @ <tr><th>Other&nbsp;Links:</th>
564 @ <td>
565 @ <a href="%s(g.zTop)/dir?ci=%S(zUuid)">files</a>
566 if( g.perm.Zip ){
567 char *zUrl = mprintf("%s/tarball/%s-%S.tar.gz?uuid=%s",
568 g.zTop, zProjName, zUuid, zUuid);
569 @ | <a href="%s(zUrl)">Tarball</a>
570 @ | <a href="%s(g.zTop)/zip/%s(zProjName)-%S(zUuid).zip?uuid=%s(zUuid)">
571 @ ZIP archive</a>
572 fossil_free(zUrl);
573 }
574 @ | <a href="%s(g.zTop)/artifact/%S(zUuid)">manifest</a>
575 if( g.perm.Write ){
576 @ | <a href="%s(g.zTop)/ci_edit?r=%S(zUuid)">edit</a>
577 }
578 @ </td>
579 @ </tr>
580 }
581 @ </table>
@@ -590,43 +590,43 @@
590 @ <div class="sectionmenu">
591 showDiff = g.zPath[0]!='c';
592 if( db_get_boolean("show-version-diffs", 0)==0 ){
593 showDiff = !showDiff;
594 if( showDiff ){
595 @ <a class="button" href="%s(g.zTop)/vinfo/%T(zName)">
596 @ hide&nbsp;diffs</a>
597 if( sideBySide ){
598 @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=0">
599 @ unified&nbsp;diffs</a>
600 }else{
601 @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=1">
602 @ side-by-side&nbsp;diffs</a>
603 }
604 }else{
605 @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=0">
606 @ show&nbsp;unified&nbsp;diffs</a>
607 @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=1">
608 @ show&nbsp;side-by-side&nbsp;diffs</a>
609 }
610 }else{
611 if( showDiff ){
612 @ <a class="button" href="%s(g.zTop)/ci/%T(zName)">hide&nbsp;diffs</a>
613 if( sideBySide ){
614 @ <a class="button" href="%s(g.zTop)/info/%T(zName)?sbs=0">
615 @ unified&nbsp;diffs</a>
616 }else{
617 @ <a class="button" href="%s(g.zTop)/info/%T(zName)?sbs=1">
618 @ side-by-side&nbsp;diffs</a>
619 }
620 }else{
621 @ <a class="button" href="%s(g.zTop)/vinfo/%T(zName)?sbs=0">
622 @ show&nbsp;unified&nbsp;diffs</a>
623 @ <a class="button" href="%s(g.zTop)/vinfo/%T(zName)?sbs=1">
624 @ show&nbsp;side-by-side&nbsp;diffs</a>
625 }
626 }
627 @ <a class="button" href="%s(g.zTop)/vpatch?from=%S(zParent)&to=%S(zUuid)">
628 @ patch</a></div>
629 db_prepare(&q,
630 "SELECT name,"
631 " mperm,"
632 " (SELECT uuid FROM blob WHERE rid=mlink.pid),"
@@ -698,15 +698,15 @@
698 if( g.perm.Setup ){
699 @ <tr><th>Record ID:</th><td>%d(rid)</td></tr>
700 }
701 @ <tr><th>Original&nbsp;User:</th><td>
702 hyperlink_to_user(zUser, zDate, "</td></tr>");
703 if( g.perm.History ){
704 @ <tr><th>Commands:</th>
705 @ <td>
706 @ <a href="%s(g.zTop)/whistory?name=%t(zName)">history</a>
707 @ | <a href="%s(g.zTop)/artifact/%S(zUuid)">raw-text</a>
708 @ </td>
709 @ </tr>
710 }
711 @ </table></p>
712 }else{
@@ -936,34 +936,26 @@
936 }else if( mPerm==PERM_EXE ){
937 @ <li>Executable file
938 }else{
939 @ <li>File
940 }
941 if( g.perm.History ){
942 @ <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
943 }else{
944 @ %h(zName)
945 }
946 @ <ul>
947 prevName = fossil_strdup(zName);
948 }
949 @ <li>
950 hyperlink_to_date(zDate,"");
951 @ - part of checkin
952 hyperlink_to_uuid(zVers);
953 if( zBr && zBr[0] ){
954 if( g.perm.History ){
955 @ on branch <a href="%s(g.zTop)/timeline?r=%T(zBr)">%h(zBr)</a>
956 }else{
957 @ on branch %h(zBr)
958 }
959 }
960 @ - %w(zCom) (user:
961 hyperlink_to_user(zUser,zDate,"");
962 @ )
963 if( g.perm.History ){
964 @ <a href="%s(g.zTop)/annotate?checkin=%S(zVers)&filename=%T(zName)">
965 @ [annotate]</a>
966 }
967 cnt++;
968 if( pDownloadName && blob_size(pDownloadName)==0 ){
969 blob_append(pDownloadName, zName, -1);
@@ -989,16 +981,11 @@
989 if( cnt>0 ){
990 @ Also wiki page
991 }else{
992 @ Wiki page
993 }
994 if( g.perm.History ){
995 @ [<a href="%s(g.zTop)/wiki?name=%t(zPagename)">%h(zPagename)</a>]
996 }else{
997 @ [%h(zPagename)]
998 }
999 @ by
1000 hyperlink_to_user(zUser,zDate," on");
1001 hyperlink_to_date(zDate,".");
1002 nWiki++;
1003 cnt++;
1004 if( pDownloadName && blob_size(pDownloadName)==0 ){
@@ -1065,18 +1052,18 @@
1065 @ Also attachment "%h(zFilename)" to
1066 }else{
1067 @ Attachment "%h(zFilename)" to
1068 }
1069 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
1070 if( g.perm.History && g.perm.RdTkt ){
1071 @ ticket [<a href="%s(g.zTop)/tktview?name=%S(zTarget)">%S(zTarget)</a>]
1072 }else{
1073 @ ticket [%S(zTarget)]
1074 }
1075 }else{
1076 if( g.perm.History && g.perm.RdWiki ){
1077 @ wiki page [<a href="%s(g.zTop)/wiki?name=%t(zTarget)">%h(zTarget)</a>]
1078 }else{
1079 @ wiki page [%h(zTarget)]
1080 }
1081 }
1082 @ added by
@@ -1091,12 +1078,12 @@
1091 if( cnt==0 ){
1092 @ Control artifact.
1093 if( pDownloadName && blob_size(pDownloadName)==0 ){
1094 blob_appendf(pDownloadName, "%.10s.txt", zUuid);
1095 }
1096 }else if( linkToView && g.perm.History ){
1097 @ <a href="%s(g.zTop)/artifact/%S(zUuid)">[view]</a>
1098 }
1099 }
1100
1101
1102 /*
@@ -1160,18 +1147,17 @@
1160 g.zTop, P("v1"), P("v2"));
1161 }
1162
1163 if( P("smhdr")!=0 ){
1164 @ <h2>Differences From Artifact
1165 @ <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a> To
1166 @ <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>.</h2>
1167 }else{
1168 @ <h2>Differences From
1169 @ Artifact <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a>:</h2>
1170 object_description(v1, 0, 0);
1171 @ <h2>To Artifact
1172 @ <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>:</h2>
1173 object_description(v2, 0, 0);
1174 }
1175 @ <hr />
1176 @ <div class="%s(zStyle)">
1177 @ %s(blob_str(&diff))
@@ -1522,18 +1508,17 @@
1522 }
1523 style_header("Ticket Change Details");
1524 zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
1525 memcpy(zTktName, pTktChng->zTicketUuid, 10);
1526 zTktName[10] = 0;
1527 if( g.perm.History ){
1528 @ <h2>Changes to ticket
1529 @ <a href="%s(pTktChng->zTicketUuid)">%s(zTktName)</a></h2>
1530 @
1531 @ <p>By %h(pTktChng->zUser) on %s(zDate). See also:
1532 @ <a href="%s(g.zTop)/artifact/%T(zUuid)">artifact content</a>, and
1533 @ <a href="%s(g.zTop)/tkthistory/%s(pTktChng->zTicketUuid)">ticket
1534 @ history</a></p>
1535 }else{
1536 @ <h2>Changes to ticket %s(zTktName)</h2>
1537 @
1538 @ <p>By %h(pTktChng->zUser) on %s(zDate).
1539 @ </p>
@@ -1965,11 +1950,11 @@
1965 @ </blockquote>
1966 @ <hr />
1967 blob_reset(&suffix);
1968 }
1969 @ <p>Make changes to attributes of check-in
1970 @ [<a href="ci?name=%s(zUuid)">%s(zUuid)</a>]:</p>
1971 @ <form action="%s(g.zTop)/ci_edit" method="post"><div>
1972 login_insert_csrf_secret();
1973 @ <input type="hidden" name="r" value="%S(zUuid)" />
1974 @ <table border="0" cellspacing="10">
1975
1976
--- src/info.c
+++ src/info.c
@@ -261,11 +261,11 @@
261 @ propagates to descendants
262 }
263 #if 0
264 if( zValue && fossil_strcmp(zTagname,"branch")==0 ){
265 @ &nbsp;&nbsp;
266 @ %z(href("%R/timeline?r=%T",zValue))branch timeline</a>
267 }
268 #endif
269 }
270 if( zSrcUuid && zSrcUuid[0] ){
271 if( tagtype==0 ){
@@ -333,11 +333,11 @@
333 const char *zNew, /* blob.uuid after change. NULL for deletes */
334 const char *zOldName, /* Prior name. NULL if no name change. */
335 int diffFlags, /* Flags for text_diff(). Zero to omit diffs */
336 int mperm /* executable or symlink permission for zNew */
337 ){
338 if( !g.perm.Hyperlink ){
339 if( zNew==0 ){
340 @ <p>Deleted %h(zName)</p>
341 }else if( zOld==0 ){
342 @ <p>Added %h(zName)</p>
343 }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
@@ -354,35 +354,35 @@
354 @ </pre>
355 }
356 }else{
357 if( zOld && zNew ){
358 if( fossil_strcmp(zOld, zNew)!=0 ){
359 @ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
360 @ from %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a>
361 @ to %z(href("%R/artifact/%s",zNew))[%S(zNew)].</a>
362 }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
363 @ <p>Name change from
364 @ from %z(href("%R/finfo?name=%T",zOldName))%h(zOldName)</a>
365 @ to %z(href("%R/finfo?name=%T",zName))%h(zName)</a>.
366 }else{
367 @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for
368 @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
369 }
370 }else if( zOld ){
371 @ <p>Deleted %z(href("%s/finfo?name=%T",g.zTop,zName))%h(zName)</a>
372 @ version %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a>
373 }else{
374 @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
375 @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a>
376 }
377 if( diffFlags ){
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
@@ -535,47 +535,47 @@
535 @ <tr><th>Received&nbsp;From:</th>
536 @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr>
537 }
538 db_finalize(&q);
539 }
540 if( g.perm.Hyperlink ){
541 const char *zProjName = db_get("project-name", "unnamed");
542 @ <tr><th>Timelines:</th><td>
543 @ %z(href("%R/timeline?f=%S",zUuid))family</a>
544 if( zParent ){
545 @ | %z(href("%R/timeline?p=%S",zUuid))ancestors</a>
546 }
547 if( !isLeaf ){
548 @ | %z(href("%R/timeline?d=%S",zUuid))descendants</a>
549 }
550 if( zParent && !isLeaf ){
551 @ | %z(href("%R/timeline?dp=%S",zUuid))both</a>
552 }
553 db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag "
554 " WHERE rid=%d AND tagtype>0 "
555 " AND tag.tagid=tagxref.tagid "
556 " AND +tag.tagname GLOB 'sym-*'", rid);
557 while( db_step(&q)==SQLITE_ROW ){
558 const char *zTagName = db_column_text(&q, 0);
559 @ | %z(href("%R/timeline?r=%T",zTagName))%h(zTagName)</a>
560 }
561 db_finalize(&q);
562 @ </td></tr>
563 @ <tr><th>Other&nbsp;Links:</th>
564 @ <td>
565 @ %z(href("%R/dir?ci=%S",zUuid))files</a>
566 if( g.perm.Zip ){
567 char *zUrl = mprintf("%R/tarball/%s-%S.tar.gz?uuid=%s",
568 zProjName, zUuid, zUuid);
569 @ | %z(href("%s",zUrl))Tarball</a>
570 @ | %z(href("%R/zip/%s-%S.zip?uuid=%s",zProjName,zUuid,zUuid))
571 @ ZIP archive</a>
572 fossil_free(zUrl);
573 }
574 @ | %z(href("%R/artifact/%S",zUuid))manifest</a>
575 if( g.perm.Write ){
576 @ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a>
577 }
578 @ </td>
579 @ </tr>
580 }
581 @ </table>
@@ -590,43 +590,43 @@
590 @ <div class="sectionmenu">
591 showDiff = g.zPath[0]!='c';
592 if( db_get_boolean("show-version-diffs", 0)==0 ){
593 showDiff = !showDiff;
594 if( showDiff ){
595 @ %z(xhref("class='button'","%R/vinfo/%T",zName)))
596 @ hide&nbsp;diffs</a>
597 if( sideBySide ){
598 @ %z(xhref("class='button'","%R/ci/%T?sbs=0",zName))
599 @ unified&nbsp;diffs</a>
600 }else{
601 @ %z(xhref("class='button'","%R/ci/%T?sbs=1",zName))
602 @ side-by-side&nbsp;diffs</a>
603 }
604 }else{
605 @ %z(xhref("class='button'","%R/ci/%T?sbs=0",zName))
606 @ show&nbsp;unified&nbsp;diffs</a>
607 @ %z(xhref("class='button'","%R/ci/%T?sbs=1",zName))
608 @ show&nbsp;side-by-side&nbsp;diffs</a>
609 }
610 }else{
611 if( showDiff ){
612 @ %z(xhref("class='button'","%R/ci/%T",zName))hide&nbsp;diffs</a>
613 if( sideBySide ){
614 @ %z(xhref("class='button'","%R/info/%T?sbs=0",zName))
615 @ unified&nbsp;diffs</a>
616 }else{
617 @ %z(xhref("class='button'","%R/info/%T?sbs=1",zName))
618 @ side-by-side&nbsp;diffs</a>
619 }
620 }else{
621 @ %z(xhref("class='button'","%R/vinfo/%T?sbs=0",zName))
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),"
@@ -698,15 +698,15 @@
698 if( g.perm.Setup ){
699 @ <tr><th>Record ID:</th><td>%d(rid)</td></tr>
700 }
701 @ <tr><th>Original&nbsp;User:</th><td>
702 hyperlink_to_user(zUser, zDate, "</td></tr>");
703 if( g.perm.Hyperlink ){
704 @ <tr><th>Commands:</th>
705 @ <td>
706 @ &z(href("%R/whistory?name=%t",zName))history</a>
707 @ | %z(href("%R/artifact/%S",zUuid))raw-text</a>
708 @ </td>
709 @ </tr>
710 }
711 @ </table></p>
712 }else{
@@ -936,34 +936,26 @@
936 }else if( mPerm==PERM_EXE ){
937 @ <li>Executable file
938 }else{
939 @ <li>File
940 }
941 @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
 
 
 
 
942 @ <ul>
943 prevName = fossil_strdup(zName);
944 }
945 @ <li>
946 hyperlink_to_date(zDate,"");
947 @ - part of checkin
948 hyperlink_to_uuid(zVers);
949 if( zBr && zBr[0] ){
950 @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a>
 
 
 
 
951 }
952 @ - %w(zCom) (user:
953 hyperlink_to_user(zUser,zDate,"");
954 @ )
955 if( g.perm.Hyperlink ){
956 @ %z(href("%R/annotate?checkin=%S&filename=%T",zVers,zName))
957 @ [annotate]</a>
958 }
959 cnt++;
960 if( pDownloadName && blob_size(pDownloadName)==0 ){
961 blob_append(pDownloadName, zName, -1);
@@ -989,16 +981,11 @@
981 if( cnt>0 ){
982 @ Also wiki page
983 }else{
984 @ Wiki page
985 }
986 @ [%z(href("%R/wiki?name=%t",zPagename))%h(zPagename)</a>] by
 
 
 
 
 
987 hyperlink_to_user(zUser,zDate," on");
988 hyperlink_to_date(zDate,".");
989 nWiki++;
990 cnt++;
991 if( pDownloadName && blob_size(pDownloadName)==0 ){
@@ -1065,18 +1052,18 @@
1052 @ Also attachment "%h(zFilename)" to
1053 }else{
1054 @ Attachment "%h(zFilename)" to
1055 }
1056 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
1057 if( g.perm.Hyperlink && g.perm.RdTkt ){
1058 @ ticket [%z(href("%R/tktview?name=%S",zTarget))%S(zTarget)</a>]
1059 }else{
1060 @ ticket [%S(zTarget)]
1061 }
1062 }else{
1063 if( g.perm.Hyperlink && g.perm.RdWiki ){
1064 @ wiki page [%z(href("%R/wiki?name=%t",zTarget)))%h(zTarget)</a>]
1065 }else{
1066 @ wiki page [%h(zTarget)]
1067 }
1068 }
1069 @ added by
@@ -1091,12 +1078,12 @@
1078 if( cnt==0 ){
1079 @ Control artifact.
1080 if( pDownloadName && blob_size(pDownloadName)==0 ){
1081 blob_appendf(pDownloadName, "%.10s.txt", zUuid);
1082 }
1083 }else if( linkToView && g.perm.Hyperlink ){
1084 @ %z(href("%R/artifact/%S",zUuid))[view]</a>
1085 }
1086 }
1087
1088
1089 /*
@@ -1160,18 +1147,17 @@
1147 g.zTop, P("v1"), P("v2"));
1148 }
1149
1150 if( P("smhdr")!=0 ){
1151 @ <h2>Differences From Artifact
1152 @ %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a> To
1153 @ %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>.</h2>
1154 }else{
1155 @ <h2>Differences From
1156 @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2>
1157 object_description(v1, 0, 0);
1158 @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2>
 
1159 object_description(v2, 0, 0);
1160 }
1161 @ <hr />
1162 @ <div class="%s(zStyle)">
1163 @ %s(blob_str(&diff))
@@ -1522,18 +1508,17 @@
1508 }
1509 style_header("Ticket Change Details");
1510 zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
1511 memcpy(zTktName, pTktChng->zTicketUuid, 10);
1512 zTktName[10] = 0;
1513 if( g.perm.Hyperlink ){
1514 @ <h2>Changes to ticket
1515 @ %z(href("%R/tktview/%s",pTktChng->zTicketUuid)))%s(zTktName)</a></h2>
1516 @
1517 @ <p>By %h(pTktChng->zUser) on %s(zDate). See also:
1518 @ %z(href("%R/artifact/%T",zUuid))artifact content</a>, and
1519 @ %z(href("%R/tkthistory/%s",pTktChng->zTicketUuid))ticket history</a></p>
 
1520 }else{
1521 @ <h2>Changes to ticket %s(zTktName)</h2>
1522 @
1523 @ <p>By %h(pTktChng->zUser) on %s(zDate).
1524 @ </p>
@@ -1965,11 +1950,11 @@
1950 @ </blockquote>
1951 @ <hr />
1952 blob_reset(&suffix);
1953 }
1954 @ <p>Make changes to attributes of check-in
1955 @ [%z(href("%R/ci/%s",zUuid))%s(zUuid)</a>]:</p>
1956 @ <form action="%s(g.zTop)/ci_edit" method="post"><div>
1957 login_insert_csrf_secret();
1958 @ <input type="hidden" name="r" value="%S(zUuid)" />
1959 @ <table border="0" cellspacing="10">
1960
1961
+6 -4
--- src/login.c
+++ src/login.c
@@ -911,11 +911,12 @@
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 && db_get_boolean("auto-enable-hyperlinks",1)
916
+ if( zCap[0] && !g.perm.History && !g.perm.Link
917
+ && db_get_boolean("auto-enable-hyperlinks",1)
917918
&& isHuman(P("HTTP_USER_AGENT")) ){
918919
g.perm.History = 1;
919920
}
920921
921922
/* If the public-pages glob pattern is defined and REQUEST_URI matches
@@ -983,11 +984,12 @@
983984
case 'i': g.perm.Read = g.perm.Write = 1; break;
984985
case 'o': g.perm.Read = 1; break;
985986
case 'z': g.perm.Zip = 1; break;
986987
987988
case 'd': g.perm.Delete = 1; break;
988
- case 'h': g.perm.History = 1; break;
989
+ case 'h': g.perm.History = g.perm.Hyperlink = 1; break;
990
+ case 'l': g.perm.Link = g.perm.Hyperlink = 1; break;
989991
case 'g': g.perm.Clone = 1; break;
990992
case 'p': g.perm.Password = 1; break;
991993
992994
case 'j': g.perm.RdWiki = 1; break;
993995
case 'k': g.perm.WrWiki = g.perm.RdWiki = g.perm.ApndWiki =1; break;
@@ -1057,11 +1059,11 @@
10571059
case 'g': rc = g.perm.Clone; break;
10581060
case 'h': rc = g.perm.History; break;
10591061
case 'i': rc = g.perm.Write; break;
10601062
case 'j': rc = g.perm.RdWiki; break;
10611063
case 'k': rc = g.perm.WrWiki; break;
1062
- /* case 'l': */
1064
+ case 'l': rc = g.perm.Link; break;
10631065
case 'm': rc = g.perm.ApndWiki; break;
10641066
case 'n': rc = g.perm.NewTkt; break;
10651067
case 'o': rc = g.perm.Read; break;
10661068
case 'p': rc = g.perm.Password; break;
10671069
/* case 'q': */
@@ -1135,11 +1137,11 @@
11351137
** the anonymous user has okHistory permission, then paint a mesage
11361138
** to inform the user that much more information is available by
11371139
** logging in as anonymous.
11381140
*/
11391141
void login_anonymous_available(void){
1140
- if( !g.perm.History &&
1142
+ if( !g.perm.History && !g.perm.Link &&
11411143
db_exists("SELECT 1 FROM user"
11421144
" WHERE login='anonymous'"
11431145
" AND cap LIKE '%%h%%'") ){
11441146
const char *zUrl = PD("REQUEST_URI", "index");
11451147
@ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
11461148
--- src/login.c
+++ src/login.c
@@ -911,11 +911,12 @@
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 && db_get_boolean("auto-enable-hyperlinks",1)
 
917 && isHuman(P("HTTP_USER_AGENT")) ){
918 g.perm.History = 1;
919 }
920
921 /* If the public-pages glob pattern is defined and REQUEST_URI matches
@@ -983,11 +984,12 @@
983 case 'i': g.perm.Read = g.perm.Write = 1; break;
984 case 'o': g.perm.Read = 1; break;
985 case 'z': g.perm.Zip = 1; break;
986
987 case 'd': g.perm.Delete = 1; break;
988 case 'h': g.perm.History = 1; break;
 
989 case 'g': g.perm.Clone = 1; break;
990 case 'p': g.perm.Password = 1; break;
991
992 case 'j': g.perm.RdWiki = 1; break;
993 case 'k': g.perm.WrWiki = g.perm.RdWiki = g.perm.ApndWiki =1; break;
@@ -1057,11 +1059,11 @@
1057 case 'g': rc = g.perm.Clone; break;
1058 case 'h': rc = g.perm.History; break;
1059 case 'i': rc = g.perm.Write; break;
1060 case 'j': rc = g.perm.RdWiki; break;
1061 case 'k': rc = g.perm.WrWiki; break;
1062 /* case 'l': */
1063 case 'm': rc = g.perm.ApndWiki; break;
1064 case 'n': rc = g.perm.NewTkt; break;
1065 case 'o': rc = g.perm.Read; break;
1066 case 'p': rc = g.perm.Password; break;
1067 /* case 'q': */
@@ -1135,11 +1137,11 @@
1135 ** the anonymous user has okHistory permission, then paint a mesage
1136 ** to inform the user that much more information is available by
1137 ** logging in as anonymous.
1138 */
1139 void login_anonymous_available(void){
1140 if( !g.perm.History &&
1141 db_exists("SELECT 1 FROM user"
1142 " WHERE login='anonymous'"
1143 " AND cap LIKE '%%h%%'") ){
1144 const char *zUrl = PD("REQUEST_URI", "index");
1145 @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
1146
--- src/login.c
+++ src/login.c
@@ -911,11 +911,12 @@
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
@@ -983,11 +984,12 @@
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;
@@ -1057,11 +1059,11 @@
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': */
@@ -1135,11 +1137,11 @@
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
+9
--- src/main.c
+++ src/main.c
@@ -51,10 +51,17 @@
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.
5663
*/
5764
struct FossilUserPerms {
5865
char Setup; /* s: use Setup screens on web interface */
5966
char Admin; /* a: administrative permission */
6067
char Delete; /* d: delete wiki or tickets */
@@ -61,10 +68,11 @@
6168
char Password; /* p: change password */
6269
char Query; /* q: create new reports */
6370
char Write; /* i: xfer inbound. checkin */
6471
char Read; /* o: xfer outbound. checkout */
6572
char History; /* h: access historical information. */
73
+ char Link; /* l: enable href= using javascript */
6674
char Clone; /* g: clone */
6775
char RdWiki; /* j: view wiki via web */
6876
char NewWiki; /* f: create new wiki via web */
6977
char ApndWiki; /* m: append to wiki via web */
7078
char WrWiki; /* k: edit wiki via web */
@@ -75,10 +83,11 @@
7583
char Attach; /* b: add attachments */
7684
char TktFmt; /* t: create new ticket report formats */
7785
char RdAddr; /* e: read email addresses or other private data */
7886
char Zip; /* z: download zipped artifact via /zip URL */
7987
char Private; /* x: can send and receive private content */
88
+ char Hyperlink; /* "h" or "l" */
8089
};
8190
8291
#ifdef FOSSIL_ENABLE_TCL
8392
/*
8493
** All Tcl related context information is in this structure. This structure
8594
--- src/main.c
+++ src/main.c
@@ -51,10 +51,17 @@
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,10 +68,11 @@
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 History; /* h: access historical information. */
 
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 */
@@ -75,10 +83,11 @@
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
85
--- src/main.c
+++ src/main.c
@@ -51,10 +51,17 @@
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 */
@@ -61,10 +68,11 @@
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 */
@@ -75,10 +83,11 @@
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
94
--- src/printf.c
+++ src/printf.c
@@ -47,10 +47,11 @@
4747
#define etFOSSILIZE 19 /* The fossil header encoding format. */
4848
#define etPATH 20 /* Path type */
4949
#define etWIKISTR 21 /* Wiki text rendered from a char*: %w */
5050
#define etWIKIBLOB 22 /* Wiki text rendered from a Blob*: %W */
5151
#define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */
52
+#define etROOT 24 /* String value of g.zTop: % */
5253
5354
5455
/*
5556
** An "etByte" is an 8-bit unsigned value.
5657
*/
@@ -93,10 +94,11 @@
9394
{ 'b', 0, 2, etBLOB, 0, 0 },
9495
{ 'B', 0, 2, etBLOBSQL, 0, 0 },
9596
{ 'w', 0, 2, etWIKISTR, 0, 0 },
9697
{ 'W', 0, 2, etWIKIBLOB, 0, 0 },
9798
{ 'h', 0, 4, etHTMLIZE, 0, 0 },
99
+ { 'R', 0, 0, etROOT, 0, 0 },
98100
{ 't', 0, 4, etHTTPIZE, 0, 0 }, /* "/" -> "%2F" */
99101
{ 'T', 0, 4, etURLIZE, 0, 0 }, /* "/" unchanged */
100102
{ 'F', 0, 4, etFOSSILIZE, 0, 0 },
101103
{ 'S', 0, 4, etSTRINGID, 0, 0 },
102104
{ 'c', 0, 0, etCHARX, 0, 0 },
@@ -570,10 +572,15 @@
570572
bufpt[i]=e[i];
571573
}
572574
}
573575
bufpt[length]='\0';
574576
break;
577
+ }
578
+ case etROOT: {
579
+ bufpt = g.zTop;
580
+ length = (int)strlen(bufpt);
581
+ break;
575582
}
576583
case etSTRINGID: {
577584
precision = 16;
578585
/* Fall through */
579586
}
580587
--- src/printf.c
+++ src/printf.c
@@ -47,10 +47,11 @@
47 #define etFOSSILIZE 19 /* The fossil header encoding format. */
48 #define etPATH 20 /* Path type */
49 #define etWIKISTR 21 /* Wiki text rendered from a char*: %w */
50 #define etWIKIBLOB 22 /* Wiki text rendered from a Blob*: %W */
51 #define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */
 
52
53
54 /*
55 ** An "etByte" is an 8-bit unsigned value.
56 */
@@ -93,10 +94,11 @@
93 { 'b', 0, 2, etBLOB, 0, 0 },
94 { 'B', 0, 2, etBLOBSQL, 0, 0 },
95 { 'w', 0, 2, etWIKISTR, 0, 0 },
96 { 'W', 0, 2, etWIKIBLOB, 0, 0 },
97 { 'h', 0, 4, etHTMLIZE, 0, 0 },
 
98 { 't', 0, 4, etHTTPIZE, 0, 0 }, /* "/" -> "%2F" */
99 { 'T', 0, 4, etURLIZE, 0, 0 }, /* "/" unchanged */
100 { 'F', 0, 4, etFOSSILIZE, 0, 0 },
101 { 'S', 0, 4, etSTRINGID, 0, 0 },
102 { 'c', 0, 0, etCHARX, 0, 0 },
@@ -570,10 +572,15 @@
570 bufpt[i]=e[i];
571 }
572 }
573 bufpt[length]='\0';
574 break;
 
 
 
 
 
575 }
576 case etSTRINGID: {
577 precision = 16;
578 /* Fall through */
579 }
580
--- src/printf.c
+++ src/printf.c
@@ -47,10 +47,11 @@
47 #define etFOSSILIZE 19 /* The fossil header encoding format. */
48 #define etPATH 20 /* Path type */
49 #define etWIKISTR 21 /* Wiki text rendered from a char*: %w */
50 #define etWIKIBLOB 22 /* Wiki text rendered from a Blob*: %W */
51 #define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */
52 #define etROOT 24 /* String value of g.zTop: % */
53
54
55 /*
56 ** An "etByte" is an 8-bit unsigned value.
57 */
@@ -93,10 +94,11 @@
94 { 'b', 0, 2, etBLOB, 0, 0 },
95 { 'B', 0, 2, etBLOBSQL, 0, 0 },
96 { 'w', 0, 2, etWIKISTR, 0, 0 },
97 { 'W', 0, 2, etWIKIBLOB, 0, 0 },
98 { 'h', 0, 4, etHTMLIZE, 0, 0 },
99 { 'R', 0, 0, etROOT, 0, 0 },
100 { 't', 0, 4, etHTTPIZE, 0, 0 }, /* "/" -> "%2F" */
101 { 'T', 0, 4, etURLIZE, 0, 0 }, /* "/" unchanged */
102 { 'F', 0, 4, etFOSSILIZE, 0, 0 },
103 { 'S', 0, 4, etSTRINGID, 0, 0 },
104 { 'c', 0, 0, etCHARX, 0, 0 },
@@ -570,10 +572,15 @@
572 bufpt[i]=e[i];
573 }
574 }
575 bufpt[length]='\0';
576 break;
577 }
578 case etROOT: {
579 bufpt = g.zTop;
580 length = (int)strlen(bufpt);
581 break;
582 }
583 case etSTRINGID: {
584 precision = 16;
585 /* Fall through */
586 }
587
+10 -11
--- src/report.c
+++ src/report.c
@@ -56,26 +56,29 @@
5656
cnt++;
5757
blob_appendf(&ril, "<li>");
5858
if( zTitle[0] == '_' ){
5959
blob_appendf(&ril, "%s", zTitle);
6060
} else {
61
- blob_appendf(&ril, "<a href=\"rptview?rn=%d\" rel=\"nofollow\">%h</a>", rn, zTitle);
61
+ blob_appendf(&ril, "%z%h</a>", href("%R/rptview?rn=%d", rn), zTitle);
6262
}
6363
blob_appendf(&ril, "&nbsp;&nbsp;&nbsp;");
6464
if( g.perm.Write && zOwner && zOwner[0] ){
6565
blob_appendf(&ril, "(by <i>%h</i></i>) ", zOwner);
6666
}
6767
if( g.perm.TktFmt ){
68
- blob_appendf(&ril, "[<a href=\"rptedit?rn=%d&amp;copy=1\" rel=\"nofollow\">copy</a>] ", rn);
68
+ blob_appendf(&ril, "[%zcopy</a>] ",
69
+ href("%R/rptedit?rn=%d&amp;copy=1", rn));
6970
}
7071
if( g.perm.Admin
7172
|| (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0)
7273
){
73
- blob_appendf(&ril, "[<a href=\"rptedit?rn=%d\" rel=\"nofollow\">edit</a>] ", rn);
74
+ blob_appendf(&ril, "[%zedit</a>]",
75
+ href("%R/rptedit?rn=%d", rn));
7476
}
7577
if( g.perm.TktFmt ){
76
- blob_appendf(&ril, "[<a href=\"rptsql?rn=%d\" rel=\"nofollow\">sql</a>] ", rn);
78
+ blob_appendf(&ril, "[%zsql</a>]",
79
+ href("%R/rptsql?rn=%d", rn));
7780
}
7881
blob_appendf(&ril, "</li>\n");
7982
}
8083
8184
Th_Store("report_items", blob_str(&ril));
@@ -720,11 +723,11 @@
720723
if( i==pState->iBg ) continue;
721724
zData = azArg[i];
722725
if( zData==0 ) zData = "";
723726
if( pState->iNewRow>=0 && i>=pState->iNewRow ){
724727
if( zTid && g.perm.Write ){
725
- @ <td valign="top"><a href="tktedit/%h(zTid)">edit</a></td>
728
+ @ <td valign="top">%z(href("%R/tktedit/%h",zTid))edit</a></td>
726729
zTid = 0;
727730
}
728731
if( zData[0] ){
729732
Blob content;
730733
@ </tr><tr style="background-color:%h(zBg)"><td colspan=%d(pState->nCol)>
@@ -732,25 +735,21 @@
732735
wiki_convert(&content, 0, 0);
733736
blob_reset(&content);
734737
}
735738
}else if( azName[i][0]=='#' ){
736739
zTid = zData;
737
- if( g.perm.History ){
738
- @ <td valign="top"><a href="tktview?name=%h(zData)">%h(zData)</a></td>
739
- }else{
740
- @ <td valign="top">%h(zData)</td>
741
- }
740
+ @ <td valign="top">%z(href("%R/tktview?name=%h",zData))%h(zData)</a></td>
742741
}else if( zData[0]==0 ){
743742
@ <td valign="top">&nbsp;</td>
744743
}else{
745744
@ <td valign="top">
746745
@ %h(zData)
747746
@ </td>
748747
}
749748
}
750749
if( zTid && g.perm.Write ){
751
- @ <td valign="top"><a href="tktedit/%h(zTid)">edit</a></td>
750
+ @ <td valign="top">%z(href("%R/tktedit/%h",zTid))edit</a></td>
752751
}
753752
@ </tr>
754753
return 0;
755754
}
756755
757756
--- src/report.c
+++ src/report.c
@@ -56,26 +56,29 @@
56 cnt++;
57 blob_appendf(&ril, "<li>");
58 if( zTitle[0] == '_' ){
59 blob_appendf(&ril, "%s", zTitle);
60 } else {
61 blob_appendf(&ril, "<a href=\"rptview?rn=%d\" rel=\"nofollow\">%h</a>", rn, zTitle);
62 }
63 blob_appendf(&ril, "&nbsp;&nbsp;&nbsp;");
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, "[<a href=\"rptedit?rn=%d&amp;copy=1\" rel=\"nofollow\">copy</a>] ", rn);
 
69 }
70 if( g.perm.Admin
71 || (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0)
72 ){
73 blob_appendf(&ril, "[<a href=\"rptedit?rn=%d\" rel=\"nofollow\">edit</a>] ", rn);
 
74 }
75 if( g.perm.TktFmt ){
76 blob_appendf(&ril, "[<a href=\"rptsql?rn=%d\" rel=\"nofollow\">sql</a>] ", rn);
 
77 }
78 blob_appendf(&ril, "</li>\n");
79 }
80
81 Th_Store("report_items", blob_str(&ril));
@@ -720,11 +723,11 @@
720 if( i==pState->iBg ) continue;
721 zData = azArg[i];
722 if( zData==0 ) zData = "";
723 if( pState->iNewRow>=0 && i>=pState->iNewRow ){
724 if( zTid && g.perm.Write ){
725 @ <td valign="top"><a href="tktedit/%h(zTid)">edit</a></td>
726 zTid = 0;
727 }
728 if( zData[0] ){
729 Blob content;
730 @ </tr><tr style="background-color:%h(zBg)"><td colspan=%d(pState->nCol)>
@@ -732,25 +735,21 @@
732 wiki_convert(&content, 0, 0);
733 blob_reset(&content);
734 }
735 }else if( azName[i][0]=='#' ){
736 zTid = zData;
737 if( g.perm.History ){
738 @ <td valign="top"><a href="tktview?name=%h(zData)">%h(zData)</a></td>
739 }else{
740 @ <td valign="top">%h(zData)</td>
741 }
742 }else if( zData[0]==0 ){
743 @ <td valign="top">&nbsp;</td>
744 }else{
745 @ <td valign="top">
746 @ %h(zData)
747 @ </td>
748 }
749 }
750 if( zTid && g.perm.Write ){
751 @ <td valign="top"><a href="tktedit/%h(zTid)">edit</a></td>
752 }
753 @ </tr>
754 return 0;
755 }
756
757
--- src/report.c
+++ src/report.c
@@ -56,26 +56,29 @@
56 cnt++;
57 blob_appendf(&ril, "<li>");
58 if( zTitle[0] == '_' ){
59 blob_appendf(&ril, "%s", zTitle);
60 } else {
61 blob_appendf(&ril, "%z%h</a>", href("%R/rptview?rn=%d", rn), zTitle);
62 }
63 blob_appendf(&ril, "&nbsp;&nbsp;&nbsp;");
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>]",
75 href("%R/rptedit?rn=%d", rn));
76 }
77 if( g.perm.TktFmt ){
78 blob_appendf(&ril, "[%zsql</a>]",
79 href("%R/rptsql?rn=%d", rn));
80 }
81 blob_appendf(&ril, "</li>\n");
82 }
83
84 Th_Store("report_items", blob_str(&ril));
@@ -720,11 +723,11 @@
723 if( i==pState->iBg ) continue;
724 zData = azArg[i];
725 if( zData==0 ) zData = "";
726 if( pState->iNewRow>=0 && i>=pState->iNewRow ){
727 if( zTid && g.perm.Write ){
728 @ <td valign="top">%z(href("%R/tktedit/%h",zTid))edit</a></td>
729 zTid = 0;
730 }
731 if( zData[0] ){
732 Blob content;
733 @ </tr><tr style="background-color:%h(zBg)"><td colspan=%d(pState->nCol)>
@@ -732,25 +735,21 @@
735 wiki_convert(&content, 0, 0);
736 blob_reset(&content);
737 }
738 }else if( azName[i][0]=='#' ){
739 zTid = zData;
740 @ <td valign="top">%z(href("%R/tktview?name=%h",zData))%h(zData)</a></td>
 
 
 
 
741 }else if( zData[0]==0 ){
742 @ <td valign="top">&nbsp;</td>
743 }else{
744 @ <td valign="top">
745 @ %h(zData)
746 @ </td>
747 }
748 }
749 if( zTid && g.perm.Write ){
750 @ <td valign="top">%z(href("%R/tktedit/%h",zTid))edit</a></td>
751 }
752 @ </tr>
753 return 0;
754 }
755
756
+18 -9
--- src/setup.c
+++ src/setup.c
@@ -170,10 +170,13 @@
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>
175178
@ <tr><td valign="top"><b>m</b></td>
176179
@ <td><i>Append-Wiki:</i> Append to wiki pages</td></tr>
177180
@ <tr><td valign="top"><b>n</b></td>
178181
@ <td><i>New-Tkt:</i> Create new tickets</td></tr>
179182
@ <tr><td valign="top"><b>o</b></td>
@@ -248,11 +251,11 @@
248251
** WEBPAGE: /setup_uedit
249252
*/
250253
void user_edit(void){
251254
const char *zId, *zLogin, *zInfo, *zCap, *zPw;
252255
char *oaa, *oas, *oar, *oaw, *oan, *oai, *oaj, *oao, *oap;
253
- char *oak, *oad, *oac, *oaf, *oam, *oah, *oag, *oae;
256
+ char *oak, *oad, *oac, *oaf, *oam, *oah, *oal, *oag, *oae;
254257
char *oat, *oau, *oav, *oab, *oax, *oaz;
255258
const char *zGroup;
256259
const char *zOldLogin;
257260
char *inherit[128];
258261
int doWrite;
@@ -304,10 +307,11 @@
304307
int aw = P("aw")!=0;
305308
int ac = P("ac")!=0;
306309
int af = P("af")!=0;
307310
int am = P("am")!=0;
308311
int ah = P("ah")!=0;
312
+ int al = P("al")!=0;
309313
int ag = P("ag")!=0;
310314
int at = P("at")!=0;
311315
int au = P("au")!=0;
312316
int av = P("av")!=0;
313317
int ax = P("ax")!=0;
@@ -321,10 +325,11 @@
321325
if( ah ){ zCap[i++] = 'h'; }
322326
if( ag ){ zCap[i++] = 'g'; }
323327
if( ai ){ zCap[i++] = 'i'; }
324328
if( aj ){ zCap[i++] = 'j'; }
325329
if( ak ){ zCap[i++] = 'k'; }
330
+ if( al ){ zCap[i++] = 'l'; }
326331
if( am ){ zCap[i++] = 'm'; }
327332
if( an ){ zCap[i++] = 'n'; }
328333
if( ao ){ zCap[i++] = 'o'; }
329334
if( ap ){ zCap[i++] = 'p'; }
330335
if( ar ){ zCap[i++] = 'r'; }
@@ -412,11 +417,11 @@
412417
*/
413418
zLogin = "";
414419
zInfo = "";
415420
zCap = "";
416421
zPw = "";
417
- oaa = oab = oac = oad = oae = oaf = oag = oah = oai = oaj = oak = oam =
422
+ oaa = oab = oac = oad = oae = oaf = oag = oah = oai = oaj = oak = oal = oam =
418423
oan = oao = oap = oar = oas = oat = oau = oav = oaw = oax = oaz = "";
419424
if( uid ){
420425
zLogin = db_text("", "SELECT login FROM user WHERE uid=%d", uid);
421426
zInfo = db_text("", "SELECT info FROM user WHERE uid=%d", uid);
422427
zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", uid);
@@ -430,10 +435,11 @@
430435
if( strchr(zCap, 'g') ) oag = " checked=\"checked\"";
431436
if( strchr(zCap, 'h') ) oah = " checked=\"checked\"";
432437
if( strchr(zCap, 'i') ) oai = " checked=\"checked\"";
433438
if( strchr(zCap, 'j') ) oaj = " checked=\"checked\"";
434439
if( strchr(zCap, 'k') ) oak = " checked=\"checked\"";
440
+ if( strchr(zCap, 'l') ) oal = " checked=\"checked\"";
435441
if( strchr(zCap, 'm') ) oam = " checked=\"checked\"";
436442
if( strchr(zCap, 'n') ) oan = " checked=\"checked\"";
437443
if( strchr(zCap, 'o') ) oao = " checked=\"checked\"";
438444
if( strchr(zCap, 'p') ) oap = " checked=\"checked\"";
439445
if( strchr(zCap, 'r') ) oar = " checked=\"checked\"";
@@ -524,11 +530,12 @@
524530
@ <input type="checkbox" name="ad"%s(oad) />%s(B('d'))Delete<br />
525531
@ <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br />
526532
@ <input type="checkbox" name="ap"%s(oap) />%s(B('p'))Password<br />
527533
@ <input type="checkbox" name="ai"%s(oai) />%s(B('i'))Check-In<br />
528534
@ <input type="checkbox" name="ao"%s(oao) />%s(B('o'))Check-Out<br />
529
- @ <input type="checkbox" name="ah"%s(oah) />%s(B('h'))History<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 />
530537
@ <input type="checkbox" name="au"%s(oau) />%s(B('u'))Reader<br />
531538
@ <input type="checkbox" name="av"%s(oav) />%s(B('v'))Developer<br />
532539
@ <input type="checkbox" name="ag"%s(oag) />%s(B('g'))Clone<br />
533540
@ <input type="checkbox" name="aj"%s(oaj) />%s(B('j'))Read Wiki<br />
534541
@ <input type="checkbox" name="af"%s(oaf) />%s(B('f'))New Wiki<br />
@@ -625,24 +632,26 @@
625632
@ is first posted. The <span class="usertype">Setup</span> user can
626633
@ delete anything at any time.
627634
@ </p></li>
628635
@
629636
@ <li><p>
630
- @ The <span class="capability">History</span> privilege allows a user
637
+ @ The <span class="capability">Hyperlinks</span> privilege allows a user
631638
@ to see most hyperlinks. This is recommended ON for most logged-in users
632639
@ but OFF for user "nobody" to avoid problems with spiders trying to walk
633
- @ every historical version of every baseline and file.
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.
634643
@ </p></li>
635644
@
636645
@ <li><p>
637646
@ The <span class="capability">Zip</span> privilege allows a user to
638647
@ see the "download as ZIP"
639648
@ hyperlink and permits access to the <tt>/zip</tt> page. This allows
640649
@ users to download ZIP archives without granting other rights like
641650
@ <span class="capability">Read</span> or
642
- @ <span class="capability">History</span>. This privilege is recommended for
643
- @ user <span class="usertype">nobody</span> so that automatic package
651
+ @ <span class="capability">Hyperlink</span>. The "z" privilege is recommended
652
+ @ for user <span class="usertype">nobody</span> so that automatic package
644653
@ downloaders can obtain the sources without going through the login
645654
@ procedure.
646655
@ </p></li>
647656
@
648657
@ <li><p>
@@ -704,12 +713,12 @@
704713
@ To disable universal access to the repository, make sure no user named
705714
@ <span class="usertype">nobody</span> exists or that the
706715
@ <span class="usertype">nobody</span> user has no capabilities
707716
@ enabled. The password for <span class="usertype">nobody</span> is ignore.
708717
@ To avoid problems with spiders overloading the server, it is recommended
709
- @ that the <span class="capability">h</span> (History) capability be turned
710
- @ off for the <span class="usertype">nobody</span> user.
718
+ @ that the <span class="capability">h</span> (Hyperlinks) capability be
719
+ @ turned off for the <span class="usertype">nobody</span> user.
711720
@ </p></li>
712721
@
713722
@ <li><p>
714723
@ Login is required for user <span class="usertype">anonymous</span> but the
715724
@ password is displayed on the login screen beside the password entry box
716725
--- src/setup.c
+++ src/setup.c
@@ -170,10 +170,13 @@
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>
@@ -248,11 +251,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;
@@ -304,10 +307,11 @@
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;
@@ -321,10 +325,11 @@
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'; }
@@ -412,11 +417,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);
@@ -430,10 +435,11 @@
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\"";
@@ -524,11 +530,12 @@
524 @ <input type="checkbox" name="ad"%s(oad) />%s(B('d'))Delete<br />
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'))History<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 />
@@ -625,24 +632,26 @@
625 @ is first posted. The <span class="usertype">Setup</span> user can
626 @ delete anything at any time.
627 @ </p></li>
628 @
629 @ <li><p>
630 @ The <span class="capability">History</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 historical version of every baseline 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"
639 @ hyperlink and permits access to the <tt>/zip</tt> page. This allows
640 @ users to download ZIP archives without granting other rights like
641 @ <span class="capability">Read</span> or
642 @ <span class="capability">History</span>. This privilege is recommended for
643 @ user <span class="usertype">nobody</span> so that automatic package
644 @ downloaders can obtain the sources without going through the login
645 @ procedure.
646 @ </p></li>
647 @
648 @ <li><p>
@@ -704,12 +713,12 @@
704 @ To disable universal access to the repository, make sure no user named
705 @ <span class="usertype">nobody</span> exists or that the
706 @ <span class="usertype">nobody</span> user has no capabilities
707 @ enabled. The password for <span class="usertype">nobody</span> is ignore.
708 @ To avoid problems with spiders overloading the server, it is recommended
709 @ that the <span class="capability">h</span> (History) capability be turned
710 @ off for the <span class="usertype">nobody</span> user.
711 @ </p></li>
712 @
713 @ <li><p>
714 @ Login is required for user <span class="usertype">anonymous</span> but the
715 @ password is displayed on the login screen beside the password entry box
716
--- src/setup.c
+++ src/setup.c
@@ -170,10 +170,13 @@
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>
@@ -248,11 +251,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;
@@ -304,10 +307,11 @@
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;
@@ -321,10 +325,11 @@
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'; }
@@ -412,11 +417,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);
@@ -430,10 +435,11 @@
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\"";
@@ -524,11 +530,12 @@
530 @ <input type="checkbox" name="ad"%s(oad) />%s(B('d'))Delete<br />
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 />
@@ -625,24 +632,26 @@
632 @ is first posted. The <span class="usertype">Setup</span> user can
633 @ delete anything at any time.
634 @ </p></li>
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"
648 @ hyperlink and permits access to the <tt>/zip</tt> page. This allows
649 @ users to download ZIP archives without granting other rights like
650 @ <span class="capability">Read</span> or
651 @ <span class="capability">Hyperlink</span>. The "z" privilege is recommended
652 @ for user <span class="usertype">nobody</span> so that automatic package
653 @ downloaders can obtain the sources without going through the login
654 @ procedure.
655 @ </p></li>
656 @
657 @ <li><p>
@@ -704,12 +713,12 @@
713 @ To disable universal access to the repository, make sure no user named
714 @ <span class="usertype">nobody</span> exists or that the
715 @ <span class="usertype">nobody</span> user has no capabilities
716 @ enabled. The password for <span class="usertype">nobody</span> is ignore.
717 @ To avoid problems with spiders overloading the server, it is recommended
718 @ that the <span class="capability">h</span> (Hyperlinks) capability be
719 @ turned off for the <span class="usertype">nobody</span> user.
720 @ </p></li>
721 @
722 @ <li><p>
723 @ Login is required for user <span class="usertype">anonymous</span> but the
724 @ password is displayed on the login screen beside the password entry box
725
+86
--- src/style.c
+++ src/style.c
@@ -45,10 +45,93 @@
4545
/*
4646
** remember, if a sidebox was used
4747
*/
4848
static int sideboxUsed = 0;
4949
50
+
51
+/*
52
+** List of hyperlinks that need to be resolved by javascript in
53
+** the footer.
54
+*/
55
+char **aHref = 0;
56
+int nHref = 0;
57
+int nHrefAlloc = 0;
58
+
59
+/*
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]));
99
+ }
100
+ aHref[nHref++] = zUrl;
101
+ return mprintf("<a %s id=%d>", zExtra, nHref);
102
+}
103
+char *href(const char *zFormat, ...){
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]));
115
+ }
116
+ aHref[nHref++] = zUrl;
117
+ return mprintf("<a id=%d>", nHref);
118
+}
119
+
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
+}
132
+
50133
/*
51134
** Add a new element to the submenu
52135
*/
53136
void style_submenu_element(
54137
const char *zLabel,
@@ -164,10 +247,13 @@
164247
if( g.thTrace ){
165248
cgi_append_content("<span class=\"thTrace\"><hr />\n", -1);
166249
cgi_append_content(blob_str(&g.thLog), blob_size(&g.thLog));
167250
cgi_append_content("</span>\n", -1);
168251
}
252
+
253
+ /* Set the href= field on hyperlinks */
254
+ style_resolve_href();
169255
}
170256
171257
/*
172258
** Begin a side-box on the right-hand side of a page. The title and
173259
** the width of the box are given as arguments. The width is usually
174260
--- src/style.c
+++ src/style.c
@@ -45,10 +45,93 @@
45 /*
46 ** remember, if a sidebox was used
47 */
48 static int sideboxUsed = 0;
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50 /*
51 ** Add a new element to the submenu
52 */
53 void style_submenu_element(
54 const char *zLabel,
@@ -164,10 +247,13 @@
164 if( g.thTrace ){
165 cgi_append_content("<span class=\"thTrace\"><hr />\n", -1);
166 cgi_append_content(blob_str(&g.thLog), blob_size(&g.thLog));
167 cgi_append_content("</span>\n", -1);
168 }
 
 
 
169 }
170
171 /*
172 ** Begin a side-box on the right-hand side of a page. The title and
173 ** the width of the box are given as arguments. The width is usually
174
--- src/style.c
+++ src/style.c
@@ -45,10 +45,93 @@
45 /*
46 ** remember, if a sidebox was used
47 */
48 static int sideboxUsed = 0;
49
50
51 /*
52 ** List of hyperlinks that need to be resolved by javascript in
53 ** the footer.
54 */
55 char **aHref = 0;
56 int nHref = 0;
57 int nHrefAlloc = 0;
58
59 /*
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]));
99 }
100 aHref[nHref++] = zUrl;
101 return mprintf("<a %s id=%d>", zExtra, nHref);
102 }
103 char *href(const char *zFormat, ...){
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]));
115 }
116 aHref[nHref++] = zUrl;
117 return mprintf("<a id=%d>", nHref);
118 }
119
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 }
132
133 /*
134 ** Add a new element to the submenu
135 */
136 void style_submenu_element(
137 const char *zLabel,
@@ -164,10 +247,13 @@
247 if( g.thTrace ){
248 cgi_append_content("<span class=\"thTrace\"><hr />\n", -1);
249 cgi_append_content(blob_str(&g.thLog), blob_size(&g.thLog));
250 cgi_append_content("</span>\n", -1);
251 }
252
253 /* Set the href= field on hyperlinks */
254 style_resolve_href();
255 }
256
257 /*
258 ** Begin a side-box on the right-hand side of a page. The title and
259 ** the width of the box are given as arguments. The width is usually
260
+2 -2
--- src/tag.c
+++ src/tag.c
@@ -548,12 +548,12 @@
548548
" ORDER BY tagname"
549549
);
550550
@ <ul>
551551
while( db_step(&q)==SQLITE_ROW ){
552552
const char *zName = db_column_text(&q, 0);
553
- if( g.perm.History ){
554
- @ <li><a class="tagLink" href="%s(g.zTop)/timeline?t=%T(zName)">
553
+ if( g.perm.Hyperlink ){
554
+ @ <li>%z(xhref("class='taglink'","%R/timeline?t=%T",zName))
555555
@ %h(zName)</a></li>
556556
}else{
557557
@ <li><span class="tagDsp">%h(zName)</span></li>
558558
}
559559
}
560560
--- src/tag.c
+++ src/tag.c
@@ -548,12 +548,12 @@
548 " ORDER BY tagname"
549 );
550 @ <ul>
551 while( db_step(&q)==SQLITE_ROW ){
552 const char *zName = db_column_text(&q, 0);
553 if( g.perm.History ){
554 @ <li><a class="tagLink" href="%s(g.zTop)/timeline?t=%T(zName)">
555 @ %h(zName)</a></li>
556 }else{
557 @ <li><span class="tagDsp">%h(zName)</span></li>
558 }
559 }
560
--- src/tag.c
+++ src/tag.c
@@ -548,12 +548,12 @@
548 " ORDER BY tagname"
549 );
550 @ <ul>
551 while( db_step(&q)==SQLITE_ROW ){
552 const char *zName = db_column_text(&q, 0);
553 if( g.perm.Hyperlink ){
554 @ <li>%z(xhref("class='taglink'","%R/timeline?t=%T",zName))
555 @ %h(zName)</a></li>
556 }else{
557 @ <li><span class="tagDsp">%h(zName)</span></li>
558 }
559 }
560
+32 -51
--- src/timeline.c
+++ src/timeline.c
@@ -47,37 +47,37 @@
4747
** Generate a hyperlink to a version.
4848
*/
4949
void hyperlink_to_uuid(const char *zUuid){
5050
char z[UUID_SIZE+1];
5151
shorten_uuid(z, zUuid);
52
- if( g.perm.History ){
53
- @ <a class="timelineHistLink" href="%s(g.zTop)/info/%s(z)">[%s(z)]</a>
52
+ if( g.perm.Hyperlink ){
53
+ @ %z(xhref("class='timelineHistLink'","%R/info/%s",z))[%s(z)]</a>
5454
}else{
5555
@ <span class="timelineHistDsp">[%s(z)]</span>
5656
}
5757
}
5858
5959
/*
6060
** Generate a hyperlink to a diff between two versions.
6161
*/
6262
void hyperlink_to_diff(const char *zV1, const char *zV2){
63
- if( g.perm.History ){
63
+ if( g.perm.Hyperlink ){
6464
if( zV2==0 ){
65
- @ <a href="%s(g.zTop)/diff?v2=%s(zV1)">[diff]</a>
65
+ @ %z(href("%R/diff?v2=%s",zV1))[diff]</a>
6666
}else{
67
- @ <a href="%s(g.zTop)/diff?v1=%s(zV1)&amp;v2=%s(zV2)">[diff]</a>
67
+ @ %z(href("%R/diff?v1=%s&amp;v2=%s",zV1,zV2))[diff]</a>
6868
}
6969
}
7070
}
7171
7272
/*
7373
** Generate a hyperlink to a date & time.
7474
*/
7575
void hyperlink_to_date(const char *zDate, const char *zSuffix){
7676
if( zSuffix==0 ) zSuffix = "";
77
- if( g.perm.History ){
78
- @ <a href="%s(g.zTop)/timeline?c=%T(zDate)">%s(zDate)</a>%s(zSuffix)
77
+ if( g.perm.Hyperlink ){
78
+ @ %z(href("%R/timeline?c=%T",zDate))%s(zDate)</a>%s(zSuffix)
7979
}else{
8080
@ %s(zDate)%s(zSuffix)
8181
}
8282
}
8383
@@ -86,15 +86,15 @@
8686
** events by that user. If the date+time is specified, then the timeline
8787
** is centered on that date+time.
8888
*/
8989
void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){
9090
if( zSuf==0 ) zSuf = "";
91
- if( g.perm.History ){
91
+ if( g.perm.Hyperlink ){
9292
if( zD && zD[0] ){
93
- @ <a href="%s(g.zTop)/timeline?c=%T(zD)&amp;u=%T(zU)">%h(zU)</a>%s(zSuf)
93
+ @ %z(href("%R/timeline?c=%T&amp;u=%T",zD,zU))%h(zU)</a>%s(zSuf)
9494
}else{
95
- @ <a href="%s(g.zTop)/timeline?u=%T(zU)">%h(zU)</a>%s(zSuf)
95
+ @ %z(href("%R/timeline?u=%T",zU))%h(zU)</a>%s(zSuf)
9696
}
9797
}else{
9898
@ %s(zU)
9999
}
100100
}
@@ -353,39 +353,37 @@
353353
354354
/* Generate the "user: USERNAME" at the end of the comment, together
355355
** with a hyperlink to another timeline for that user.
356356
*/
357357
if( zTagList && zTagList[0]==0 ) zTagList = 0;
358
- if( g.perm.History && fossil_strcmp(zUser, zThisUser)!=0 ){
359
- char *zLink = mprintf("%s/timeline?u=%h&c=%t&nd",
360
- g.zTop, zUser, zDate);
361
- @ (user: <a href="%s(zLink)">%h(zUser)</a>%s(zTagList?",":"\051")
362
- fossil_free(zLink);
358
+ if( g.perm.Hyperlink && fossil_strcmp(zUser, zThisUser)!=0 ){
359
+ char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd", zUser, zDate);
360
+ @ (user: %z(href("%z",zLink))%h(zUser)</a>%s(zTagList?",":"\051")
363361
}else{
364362
@ (user: %h(zUser)%s(zTagList?",":"\051")
365363
}
366364
367365
/* Generate a "detail" link for tags. */
368
- if( zType[0]=='g' && g.perm.History ){
369
- @ [<a href="%s(g.zTop)/info/%S(zUuid)">details</a>]
366
+ if( zType[0]=='g' && g.perm.Hyperlink ){
367
+ @ [%z(href("%R/info/%S",zUuid))details</a>]
370368
}
371369
372370
/* Generate the "tags: TAGLIST" at the end of the comment, together
373371
** with hyperlinks to the tag list.
374372
*/
375373
if( zTagList ){
376
- if( g.perm.History ){
374
+ if( g.perm.Hyperlink ){
377375
int i;
378376
const char *z = zTagList;
379377
Blob links;
380378
blob_zero(&links);
381379
while( z && z[0] ){
382380
for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){}
383381
if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){
384382
blob_appendf(&links,
385
- "<a href=\"%s/timeline?r=%#t&nd&c=%s\">%#h</a>%.2s",
386
- g.zTop, i, z, zDate, i, z, &z[i]
383
+ "%z%#h</a>%.2s",
384
+ href("%R/timeline?r=%#t&nd&c=%s",i,z,zDate), i,z, &z[i]
387385
);
388386
}else{
389387
blob_appendf(&links, "%#h", i+2, z);
390388
}
391389
if( z[i]==0 ) break;
@@ -403,11 +401,11 @@
403401
if( xExtra ){
404402
xExtra(rid);
405403
}
406404
407405
/* Generate the file-change list if requested */
408
- if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' && g.perm.History ){
406
+ if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' && g.perm.Hyperlink ){
409407
int inUl = 0;
410408
if( !fchngQueryInit ){
411409
db_prepare(&fchngQuery,
412410
"SELECT (pid==0) AS isnew,"
413411
" (fid==0) AS isdel,"
@@ -433,26 +431,26 @@
433431
@ <ul class="filelist">
434432
inUl = 1;
435433
}
436434
if( isNew ){
437435
@ <li> %h(zFilename) (new file) &nbsp;
438
- @ <a href="%s(g.zTop)/artifact/%S(zNew)"
439
- @ target="diffwindow">[view]</a></li>
436
+ @ %z(xhref("target='diffwindow'","%R/artifact/%S",zNew))
437
+ @ [view]</a></li>
440438
}else if( isDel ){
441439
@ <li> %h(zFilename) (deleted)</li>
442440
}else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){
443441
@ <li> %h(zOldName) &rarr; %h(zFilename)
444
- @ <a href="%s(g.zTop)/artifact/%S(zNew)"
445
- @ target="diffwindow">[view]</a></li>
442
+ @ %z(xhref("target='diffwindow'","%R/artifact/%S",zNew))
443
+ @ [view]</a></li>
446444
}else{
447445
if( zOldName!=0 ){
448446
@ <li> %h(zOldName) &rarr; %h(zFilename)
449447
}else{
450448
@ <li> %h(zFilename) &nbsp;
451449
}
452
- @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)"
453
- @ target="diffwindow">[diff]</a></li>
450
+ @ %z(xhref("target='diffwindow'","%R/fdiff?v1=%S&v2=%S",zOld,zNew))
451
+ @ [diff]</a></li>
454452
}
455453
}
456454
db_reset(&fchngQuery);
457455
if( inUl ){
458456
@ </ul>
@@ -974,21 +972,13 @@
974972
p = p->u.pTo;
975973
}
976974
blob_append(&sql, ")", -1);
977975
path_reset();
978976
blob_append(&desc, "All nodes on the path from ", -1);
979
- if( g.perm.History ){
980
- blob_appendf(&desc, "<a href='%s/info/%h'>[%h]</a>", g.zTop,zFrom,zFrom);
981
- }else{
982
- blob_appendf(&desc, "[%h]", zFrom);
983
- }
977
+ blob_appendf(&desc, "%z%h</a>", href("%R/info/%h", zFrom), zFrom);
984978
blob_append(&desc, " and ", -1);
985
- if( g.perm.History ){
986
- blob_appendf(&desc, "<a href='%s/info/%h'>[%h]</a>.", g.zTop, zTo, zTo);
987
- }else{
988
- blob_appendf(&desc, "[%h].", zTo);
989
- }
979
+ blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h",zTo), zTo);
990980
tmFlags |= TIMELINE_DISJOINT;
991981
db_multi_exec("%s", blob_str(&sql));
992982
}else if( (p_rid || d_rid) && g.perm.Read ){
993983
/* If p= or d= is present, ignore all other parameters other than n= */
994984
char *zUuid;
@@ -1021,16 +1011,12 @@
10211011
blob_appendf(&desc, "%d ancestors", np);
10221012
db_multi_exec("%s", blob_str(&sql));
10231013
}
10241014
if( d_rid==0 && useDividers ) timeline_add_dividers(0, p_rid);
10251015
}
1026
- if( g.perm.History ){
1027
- blob_appendf(&desc, " of <a href='%s/info/%s'>[%.10s]</a>",
1028
- g.zTop, zUuid, zUuid);
1029
- }else{
1030
- blob_appendf(&desc, " of check-in [%.10s]", zUuid);
1031
- }
1016
+ blob_appendf(&desc, " of %z[%.10s]</a>",
1017
+ href("%R/info/%s", zUuid), zUuid);
10321018
}else if( f_rid && g.perm.Read ){
10331019
/* If f= is present, ignore all other parameters other than n= */
10341020
char *zUuid;
10351021
db_multi_exec(
10361022
"CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
@@ -1042,16 +1028,11 @@
10421028
blob_appendf(&sql, " AND event.objid IN ok");
10431029
db_multi_exec("%s", blob_str(&sql));
10441030
if( useDividers ) timeline_add_dividers(0, f_rid);
10451031
blob_appendf(&desc, "Parents and children of check-in ");
10461032
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
1047
- if( g.perm.History ){
1048
- blob_appendf(&desc, "<a href='%s/info/%s'>[%.10s]</a>",
1049
- g.zTop, zUuid, zUuid);
1050
- }else{
1051
- blob_appendf(&desc, "[%.10s]", zUuid);
1052
- }
1033
+ blob_appendf(&desc, "%z[%.10s]</a>", href("%R/info/%s", zUuid), zUuid);
10531034
}else{
10541035
/* Otherwise, a timeline based on a span of time */
10551036
int n;
10561037
const char *zEType = "timeline item";
10571038
char *zDate;
@@ -1219,11 +1200,11 @@
12191200
blob_appendf(&desc, " occurring around %h.<br />", zCirca);
12201201
}
12211202
if( zSearch ){
12221203
blob_appendf(&desc, " matching \"%h\"", zSearch);
12231204
}
1224
- if( g.perm.History ){
1205
+ if( g.perm.Hyperlink ){
12251206
if( zAfter || n==nEntry ){
12261207
zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
12271208
timeline_submenu(&url, "Older", "b", zDate, "a");
12281209
free(zDate);
12291210
}
@@ -1623,11 +1604,11 @@
16231604
*/
16241605
void test_timewarp_page(void){
16251606
Stmt q;
16261607
16271608
login_check_credentials();
1628
- if( !g.perm.Read || !g.perm.History ){ login_needed(); return; }
1609
+ if( !g.perm.Read || !g.perm.Hyperlink ){ login_needed(); return; }
16291610
style_header("Instances of timewarp");
16301611
@ <ul>
16311612
db_prepare(&q,
16321613
"SELECT blob.uuid "
16331614
" FROM plink p, plink c, blob"
16341615
--- src/timeline.c
+++ src/timeline.c
@@ -47,37 +47,37 @@
47 ** Generate a hyperlink to a version.
48 */
49 void hyperlink_to_uuid(const char *zUuid){
50 char z[UUID_SIZE+1];
51 shorten_uuid(z, zUuid);
52 if( g.perm.History ){
53 @ <a class="timelineHistLink" href="%s(g.zTop)/info/%s(z)">[%s(z)]</a>
54 }else{
55 @ <span class="timelineHistDsp">[%s(z)]</span>
56 }
57 }
58
59 /*
60 ** Generate a hyperlink to a diff between two versions.
61 */
62 void hyperlink_to_diff(const char *zV1, const char *zV2){
63 if( g.perm.History ){
64 if( zV2==0 ){
65 @ <a href="%s(g.zTop)/diff?v2=%s(zV1)">[diff]</a>
66 }else{
67 @ <a href="%s(g.zTop)/diff?v1=%s(zV1)&amp;v2=%s(zV2)">[diff]</a>
68 }
69 }
70 }
71
72 /*
73 ** Generate a hyperlink to a date & time.
74 */
75 void hyperlink_to_date(const char *zDate, const char *zSuffix){
76 if( zSuffix==0 ) zSuffix = "";
77 if( g.perm.History ){
78 @ <a href="%s(g.zTop)/timeline?c=%T(zDate)">%s(zDate)</a>%s(zSuffix)
79 }else{
80 @ %s(zDate)%s(zSuffix)
81 }
82 }
83
@@ -86,15 +86,15 @@
86 ** events by that user. If the date+time is specified, then the timeline
87 ** is centered on that date+time.
88 */
89 void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){
90 if( zSuf==0 ) zSuf = "";
91 if( g.perm.History ){
92 if( zD && zD[0] ){
93 @ <a href="%s(g.zTop)/timeline?c=%T(zD)&amp;u=%T(zU)">%h(zU)</a>%s(zSuf)
94 }else{
95 @ <a href="%s(g.zTop)/timeline?u=%T(zU)">%h(zU)</a>%s(zSuf)
96 }
97 }else{
98 @ %s(zU)
99 }
100 }
@@ -353,39 +353,37 @@
353
354 /* Generate the "user: USERNAME" at the end of the comment, together
355 ** with a hyperlink to another timeline for that user.
356 */
357 if( zTagList && zTagList[0]==0 ) zTagList = 0;
358 if( g.perm.History && fossil_strcmp(zUser, zThisUser)!=0 ){
359 char *zLink = mprintf("%s/timeline?u=%h&c=%t&nd",
360 g.zTop, zUser, zDate);
361 @ (user: <a href="%s(zLink)">%h(zUser)</a>%s(zTagList?",":"\051")
362 fossil_free(zLink);
363 }else{
364 @ (user: %h(zUser)%s(zTagList?",":"\051")
365 }
366
367 /* Generate a "detail" link for tags. */
368 if( zType[0]=='g' && g.perm.History ){
369 @ [<a href="%s(g.zTop)/info/%S(zUuid)">details</a>]
370 }
371
372 /* Generate the "tags: TAGLIST" at the end of the comment, together
373 ** with hyperlinks to the tag list.
374 */
375 if( zTagList ){
376 if( g.perm.History ){
377 int i;
378 const char *z = zTagList;
379 Blob links;
380 blob_zero(&links);
381 while( z && z[0] ){
382 for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){}
383 if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){
384 blob_appendf(&links,
385 "<a href=\"%s/timeline?r=%#t&nd&c=%s\">%#h</a>%.2s",
386 g.zTop, i, z, zDate, i, z, &z[i]
387 );
388 }else{
389 blob_appendf(&links, "%#h", i+2, z);
390 }
391 if( z[i]==0 ) break;
@@ -403,11 +401,11 @@
403 if( xExtra ){
404 xExtra(rid);
405 }
406
407 /* Generate the file-change list if requested */
408 if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' && g.perm.History ){
409 int inUl = 0;
410 if( !fchngQueryInit ){
411 db_prepare(&fchngQuery,
412 "SELECT (pid==0) AS isnew,"
413 " (fid==0) AS isdel,"
@@ -433,26 +431,26 @@
433 @ <ul class="filelist">
434 inUl = 1;
435 }
436 if( isNew ){
437 @ <li> %h(zFilename) (new file) &nbsp;
438 @ <a href="%s(g.zTop)/artifact/%S(zNew)"
439 @ target="diffwindow">[view]</a></li>
440 }else if( isDel ){
441 @ <li> %h(zFilename) (deleted)</li>
442 }else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){
443 @ <li> %h(zOldName) &rarr; %h(zFilename)
444 @ <a href="%s(g.zTop)/artifact/%S(zNew)"
445 @ target="diffwindow">[view]</a></li>
446 }else{
447 if( zOldName!=0 ){
448 @ <li> %h(zOldName) &rarr; %h(zFilename)
449 }else{
450 @ <li> %h(zFilename) &nbsp;
451 }
452 @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)"
453 @ target="diffwindow">[diff]</a></li>
454 }
455 }
456 db_reset(&fchngQuery);
457 if( inUl ){
458 @ </ul>
@@ -974,21 +972,13 @@
974 p = p->u.pTo;
975 }
976 blob_append(&sql, ")", -1);
977 path_reset();
978 blob_append(&desc, "All nodes on the path from ", -1);
979 if( g.perm.History ){
980 blob_appendf(&desc, "<a href='%s/info/%h'>[%h]</a>", g.zTop,zFrom,zFrom);
981 }else{
982 blob_appendf(&desc, "[%h]", zFrom);
983 }
984 blob_append(&desc, " and ", -1);
985 if( g.perm.History ){
986 blob_appendf(&desc, "<a href='%s/info/%h'>[%h]</a>.", g.zTop, zTo, zTo);
987 }else{
988 blob_appendf(&desc, "[%h].", zTo);
989 }
990 tmFlags |= TIMELINE_DISJOINT;
991 db_multi_exec("%s", blob_str(&sql));
992 }else if( (p_rid || d_rid) && g.perm.Read ){
993 /* If p= or d= is present, ignore all other parameters other than n= */
994 char *zUuid;
@@ -1021,16 +1011,12 @@
1021 blob_appendf(&desc, "%d ancestors", np);
1022 db_multi_exec("%s", blob_str(&sql));
1023 }
1024 if( d_rid==0 && useDividers ) timeline_add_dividers(0, p_rid);
1025 }
1026 if( g.perm.History ){
1027 blob_appendf(&desc, " of <a href='%s/info/%s'>[%.10s]</a>",
1028 g.zTop, zUuid, zUuid);
1029 }else{
1030 blob_appendf(&desc, " of check-in [%.10s]", zUuid);
1031 }
1032 }else if( f_rid && g.perm.Read ){
1033 /* If f= is present, ignore all other parameters other than n= */
1034 char *zUuid;
1035 db_multi_exec(
1036 "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
@@ -1042,16 +1028,11 @@
1042 blob_appendf(&sql, " AND event.objid IN ok");
1043 db_multi_exec("%s", blob_str(&sql));
1044 if( useDividers ) timeline_add_dividers(0, f_rid);
1045 blob_appendf(&desc, "Parents and children of check-in ");
1046 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
1047 if( g.perm.History ){
1048 blob_appendf(&desc, "<a href='%s/info/%s'>[%.10s]</a>",
1049 g.zTop, zUuid, zUuid);
1050 }else{
1051 blob_appendf(&desc, "[%.10s]", zUuid);
1052 }
1053 }else{
1054 /* Otherwise, a timeline based on a span of time */
1055 int n;
1056 const char *zEType = "timeline item";
1057 char *zDate;
@@ -1219,11 +1200,11 @@
1219 blob_appendf(&desc, " occurring around %h.<br />", zCirca);
1220 }
1221 if( zSearch ){
1222 blob_appendf(&desc, " matching \"%h\"", zSearch);
1223 }
1224 if( g.perm.History ){
1225 if( zAfter || n==nEntry ){
1226 zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
1227 timeline_submenu(&url, "Older", "b", zDate, "a");
1228 free(zDate);
1229 }
@@ -1623,11 +1604,11 @@
1623 */
1624 void test_timewarp_page(void){
1625 Stmt q;
1626
1627 login_check_credentials();
1628 if( !g.perm.Read || !g.perm.History ){ login_needed(); return; }
1629 style_header("Instances of timewarp");
1630 @ <ul>
1631 db_prepare(&q,
1632 "SELECT blob.uuid "
1633 " FROM plink p, plink c, blob"
1634
--- src/timeline.c
+++ src/timeline.c
@@ -47,37 +47,37 @@
47 ** Generate a hyperlink to a version.
48 */
49 void hyperlink_to_uuid(const char *zUuid){
50 char z[UUID_SIZE+1];
51 shorten_uuid(z, zUuid);
52 if( g.perm.Hyperlink ){
53 @ %z(xhref("class='timelineHistLink'","%R/info/%s",z))[%s(z)]</a>
54 }else{
55 @ <span class="timelineHistDsp">[%s(z)]</span>
56 }
57 }
58
59 /*
60 ** Generate a hyperlink to a diff between two versions.
61 */
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 /*
73 ** Generate a hyperlink to a date & time.
74 */
75 void hyperlink_to_date(const char *zDate, const char *zSuffix){
76 if( zSuffix==0 ) zSuffix = "";
77 if( g.perm.Hyperlink ){
78 @ %z(href("%R/timeline?c=%T",zDate))%s(zDate)</a>%s(zSuffix)
79 }else{
80 @ %s(zDate)%s(zSuffix)
81 }
82 }
83
@@ -86,15 +86,15 @@
86 ** events by that user. If the date+time is specified, then the timeline
87 ** is centered on that date+time.
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)
99 }
100 }
@@ -353,39 +353,37 @@
353
354 /* Generate the "user: USERNAME" at the end of the comment, together
355 ** with a hyperlink to another timeline for that user.
356 */
357 if( zTagList && zTagList[0]==0 ) zTagList = 0;
358 if( g.perm.Hyperlink && fossil_strcmp(zUser, zThisUser)!=0 ){
359 char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd", zUser, zDate);
360 @ (user: %z(href("%z",zLink))%h(zUser)</a>%s(zTagList?",":"\051")
 
 
361 }else{
362 @ (user: %h(zUser)%s(zTagList?",":"\051")
363 }
364
365 /* Generate a "detail" link for tags. */
366 if( zType[0]=='g' && g.perm.Hyperlink ){
367 @ [%z(href("%R/info/%S",zUuid))details</a>]
368 }
369
370 /* Generate the "tags: TAGLIST" at the end of the comment, together
371 ** with hyperlinks to the tag list.
372 */
373 if( zTagList ){
374 if( g.perm.Hyperlink ){
375 int i;
376 const char *z = zTagList;
377 Blob links;
378 blob_zero(&links);
379 while( z && z[0] ){
380 for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){}
381 if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){
382 blob_appendf(&links,
383 "%z%#h</a>%.2s",
384 href("%R/timeline?r=%#t&nd&c=%s",i,z,zDate), i,z, &z[i]
385 );
386 }else{
387 blob_appendf(&links, "%#h", i+2, z);
388 }
389 if( z[i]==0 ) break;
@@ -403,11 +401,11 @@
401 if( xExtra ){
402 xExtra(rid);
403 }
404
405 /* Generate the file-change list if requested */
406 if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' && g.perm.Hyperlink ){
407 int inUl = 0;
408 if( !fchngQueryInit ){
409 db_prepare(&fchngQuery,
410 "SELECT (pid==0) AS isnew,"
411 " (fid==0) AS isdel,"
@@ -433,26 +431,26 @@
431 @ <ul class="filelist">
432 inUl = 1;
433 }
434 if( isNew ){
435 @ <li> %h(zFilename) (new file) &nbsp;
436 @ %z(xhref("target='diffwindow'","%R/artifact/%S",zNew))
437 @ [view]</a></li>
438 }else if( isDel ){
439 @ <li> %h(zFilename) (deleted)</li>
440 }else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){
441 @ <li> %h(zOldName) &rarr; %h(zFilename)
442 @ %z(xhref("target='diffwindow'","%R/artifact/%S",zNew))
443 @ [view]</a></li>
444 }else{
445 if( zOldName!=0 ){
446 @ <li> %h(zOldName) &rarr; %h(zFilename)
447 }else{
448 @ <li> %h(zFilename) &nbsp;
449 }
450 @ %z(xhref("target='diffwindow'","%R/fdiff?v1=%S&v2=%S",zOld,zNew))
451 @ [diff]</a></li>
452 }
453 }
454 db_reset(&fchngQuery);
455 if( inUl ){
456 @ </ul>
@@ -974,21 +972,13 @@
972 p = p->u.pTo;
973 }
974 blob_append(&sql, ")", -1);
975 path_reset();
976 blob_append(&desc, "All nodes on the path from ", -1);
977 blob_appendf(&desc, "%z%h</a>", href("%R/info/%h", zFrom), zFrom);
 
 
 
 
978 blob_append(&desc, " and ", -1);
979 blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h",zTo), zTo);
 
 
 
 
980 tmFlags |= TIMELINE_DISJOINT;
981 db_multi_exec("%s", blob_str(&sql));
982 }else if( (p_rid || d_rid) && g.perm.Read ){
983 /* If p= or d= is present, ignore all other parameters other than n= */
984 char *zUuid;
@@ -1021,16 +1011,12 @@
1011 blob_appendf(&desc, "%d ancestors", np);
1012 db_multi_exec("%s", blob_str(&sql));
1013 }
1014 if( d_rid==0 && useDividers ) timeline_add_dividers(0, p_rid);
1015 }
1016 blob_appendf(&desc, " of %z[%.10s]</a>",
1017 href("%R/info/%s", zUuid), zUuid);
 
 
 
 
1018 }else if( f_rid && g.perm.Read ){
1019 /* If f= is present, ignore all other parameters other than n= */
1020 char *zUuid;
1021 db_multi_exec(
1022 "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);"
@@ -1042,16 +1028,11 @@
1028 blob_appendf(&sql, " AND event.objid IN ok");
1029 db_multi_exec("%s", blob_str(&sql));
1030 if( useDividers ) timeline_add_dividers(0, f_rid);
1031 blob_appendf(&desc, "Parents and children of check-in ");
1032 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid);
1033 blob_appendf(&desc, "%z[%.10s]</a>", href("%R/info/%s", zUuid), zUuid);
 
 
 
 
 
1034 }else{
1035 /* Otherwise, a timeline based on a span of time */
1036 int n;
1037 const char *zEType = "timeline item";
1038 char *zDate;
@@ -1219,11 +1200,11 @@
1200 blob_appendf(&desc, " occurring around %h.<br />", zCirca);
1201 }
1202 if( zSearch ){
1203 blob_appendf(&desc, " matching \"%h\"", zSearch);
1204 }
1205 if( g.perm.Hyperlink ){
1206 if( zAfter || n==nEntry ){
1207 zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
1208 timeline_submenu(&url, "Older", "b", zDate, "a");
1209 free(zDate);
1210 }
@@ -1623,11 +1604,11 @@
1604 */
1605 void test_timewarp_page(void){
1606 Stmt q;
1607
1608 login_check_credentials();
1609 if( !g.perm.Read || !g.perm.Hyperlink ){ login_needed(); return; }
1610 style_header("Instances of timewarp");
1611 @ <ul>
1612 db_prepare(&q,
1613 "SELECT blob.uuid "
1614 " FROM plink p, plink c, blob"
1615
+8 -8
--- src/tkt.c
+++ src/tkt.c
@@ -305,11 +305,11 @@
305305
if( !g.perm.RdTkt ){ login_needed(); return; }
306306
if( g.perm.WrTkt || g.perm.ApndTkt ){
307307
style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T",
308308
g.zTop, PD("name",""));
309309
}
310
- if( g.perm.History ){
310
+ if( g.perm.Hyperlink ){
311311
style_submenu_element("History", "History Of This Ticket",
312312
"%s/tkthistory/%T", g.zTop, zUuid);
313313
style_submenu_element("Timeline", "Timeline Of This Ticket",
314314
"%s/tkttimeline/%T", g.zTop, zUuid);
315315
style_submenu_element("Check-ins", "Check-ins Of This Ticket",
@@ -353,20 +353,20 @@
353353
@ <hr /><h2>Attachments:</h2>
354354
@ <ul>
355355
}
356356
cnt++;
357357
@ <li>
358
- if( g.perm.Read && g.perm.History ){
359
- @ <a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&amp;file=%t(zFile)">
358
+ if( g.perm.Read && g.perm.Hyperlink ){
359
+ @ %z(href("%R/attachview?tkt=%s&amp;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
- @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&amp;file=%t(zFile)&amp;from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>]
367
+ @ [%z(href("%R/attachdelete?tkt=%s&amp;file=%t&amp;from=%R/tktview%%3fname=%s",zFullName,zFile,zFullName))delete</a>]
368368
}
369369
@ </li>
370370
}
371371
if( cnt ){
372372
@ </ul>
@@ -662,11 +662,11 @@
662662
int tagid;
663663
char zGlobPattern[50];
664664
const char *zType;
665665
666666
login_check_credentials();
667
- if( !g.perm.History || !g.perm.RdTkt ){ login_needed(); return; }
667
+ 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",
672672
"%s/tkttimeline?name=%T&amp;y=ci", g.zTop, zUuid);
@@ -736,11 +736,11 @@
736736
char *zTitle;
737737
const char *zUuid;
738738
int tagid;
739739
740740
login_check_credentials();
741
- if( !g.perm.History || !g.perm.RdTkt ){ login_needed(); return; }
741
+ if( !g.perm.Hyperlink || !g.perm.RdTkt ){ login_needed(); return; }
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",
@@ -786,20 +786,20 @@
786786
@ <p>Delete attachment "%h(zFile)"
787787
}else{
788788
@
789789
@ <p>Add attachment "%h(zFile)"
790790
}
791
- @ [<a href="%s(g.zTop)/artifact/%T(zChngUuid)">%s(zShort)</a>]
791
+ @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>]
792792
@ (rid %d(rid)) by
793793
hyperlink_to_user(zUser,zDate," on");
794794
hyperlink_to_date(zDate, ".</p>");
795795
}else{
796796
pTicket = manifest_get(rid, CFTYPE_TICKET);
797797
if( pTicket ){
798798
@
799799
@ <p>Ticket change
800
- @ [<a href="%s(g.zTop)/artifact/%T(zChngUuid)">%s(zShort)</a>]
800
+ @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>]
801801
@ (rid %d(rid)) by
802802
hyperlink_to_user(pTicket->zUser,zDate," on");
803803
hyperlink_to_date(zDate, ":");
804804
@ </p>
805805
ticket_output_change_artifact(pTicket);
806806
--- src/tkt.c
+++ src/tkt.c
@@ -305,11 +305,11 @@
305 if( !g.perm.RdTkt ){ login_needed(); return; }
306 if( g.perm.WrTkt || g.perm.ApndTkt ){
307 style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T",
308 g.zTop, PD("name",""));
309 }
310 if( g.perm.History ){
311 style_submenu_element("History", "History Of This Ticket",
312 "%s/tkthistory/%T", g.zTop, zUuid);
313 style_submenu_element("Timeline", "Timeline Of This Ticket",
314 "%s/tkttimeline/%T", g.zTop, zUuid);
315 style_submenu_element("Check-ins", "Check-ins Of This Ticket",
@@ -353,20 +353,20 @@
353 @ <hr /><h2>Attachments:</h2>
354 @ <ul>
355 }
356 cnt++;
357 @ <li>
358 if( g.perm.Read && g.perm.History ){
359 @ <a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&amp;file=%t(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 @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&amp;file=%t(zFile)&amp;from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>]
368 }
369 @ </li>
370 }
371 if( cnt ){
372 @ </ul>
@@ -662,11 +662,11 @@
662 int tagid;
663 char zGlobPattern[50];
664 const char *zType;
665
666 login_check_credentials();
667 if( !g.perm.History || !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);
@@ -736,11 +736,11 @@
736 char *zTitle;
737 const char *zUuid;
738 int tagid;
739
740 login_check_credentials();
741 if( !g.perm.History || !g.perm.RdTkt ){ login_needed(); return; }
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",
@@ -786,20 +786,20 @@
786 @ <p>Delete attachment "%h(zFile)"
787 }else{
788 @
789 @ <p>Add attachment "%h(zFile)"
790 }
791 @ [<a href="%s(g.zTop)/artifact/%T(zChngUuid)">%s(zShort)</a>]
792 @ (rid %d(rid)) by
793 hyperlink_to_user(zUser,zDate," on");
794 hyperlink_to_date(zDate, ".</p>");
795 }else{
796 pTicket = manifest_get(rid, CFTYPE_TICKET);
797 if( pTicket ){
798 @
799 @ <p>Ticket change
800 @ [<a href="%s(g.zTop)/artifact/%T(zChngUuid)">%s(zShort)</a>]
801 @ (rid %d(rid)) by
802 hyperlink_to_user(pTicket->zUser,zDate," on");
803 hyperlink_to_date(zDate, ":");
804 @ </p>
805 ticket_output_change_artifact(pTicket);
806
--- src/tkt.c
+++ src/tkt.c
@@ -305,11 +305,11 @@
305 if( !g.perm.RdTkt ){ login_needed(); return; }
306 if( g.perm.WrTkt || g.perm.ApndTkt ){
307 style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T",
308 g.zTop, PD("name",""));
309 }
310 if( g.perm.Hyperlink ){
311 style_submenu_element("History", "History Of This Ticket",
312 "%s/tkthistory/%T", g.zTop, zUuid);
313 style_submenu_element("Timeline", "Timeline Of This Ticket",
314 "%s/tkttimeline/%T", g.zTop, zUuid);
315 style_submenu_element("Check-ins", "Check-ins Of This Ticket",
@@ -353,20 +353,20 @@
353 @ <hr /><h2>Attachments:</h2>
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>
@@ -662,11 +662,11 @@
662 int tagid;
663 char zGlobPattern[50];
664 const char *zType;
665
666 login_check_credentials();
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);
@@ -736,11 +736,11 @@
736 char *zTitle;
737 const char *zUuid;
738 int tagid;
739
740 login_check_credentials();
741 if( !g.perm.Hyperlink || !g.perm.RdTkt ){ login_needed(); return; }
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",
@@ -786,20 +786,20 @@
786 @ <p>Delete attachment "%h(zFile)"
787 }else{
788 @
789 @ <p>Add attachment "%h(zFile)"
790 }
791 @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>]
792 @ (rid %d(rid)) by
793 hyperlink_to_user(zUser,zDate," on");
794 hyperlink_to_date(zDate, ".</p>");
795 }else{
796 pTicket = manifest_get(rid, CFTYPE_TICKET);
797 if( pTicket ){
798 @
799 @ <p>Ticket change
800 @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>]
801 @ (rid %d(rid)) by
802 hyperlink_to_user(pTicket->zUser,zDate," on");
803 hyperlink_to_date(zDate, ":");
804 @ </p>
805 ticket_output_change_artifact(pTicket);
806
+18 -20
--- src/wiki.c
+++ src/wiki.c
@@ -104,11 +104,11 @@
104104
return;
105105
}
106106
style_header("Home");
107107
@ <p>This is a stub home-page for the project.
108108
@ To fill in this page, first go to
109
- @ <a href="%s(g.zTop)/setup_config">setup/config</a>
109
+ @ %z(href("%R/setup_config"))setup/config</a>
110110
@ and establish a "Project Name". Then create a
111111
@ wiki page with that name. The content of that wiki page
112112
@ will be displayed in place of this message.</p>
113113
style_footer();
114114
}
@@ -142,27 +142,25 @@
142142
if( zPageName==0 ){
143143
style_header("Wiki");
144144
@ <ul>
145145
{ char *zHomePageName = db_get("project-name",0);
146146
if( zHomePageName ){
147
- @ <li> <a href="%s(g.zTop)/wiki?name=%t(zHomePageName)">
147
+ @ <li> %z(href("%R/wiki?name=%t",zHomePageName))
148148
@ %h(zHomePageName)</a> wiki home page.</li>
149149
}
150150
}
151
- @ <li> <a href="%s(g.zTop)/timeline?y=w">Recent changes</a> to wiki
152
- @ pages. </li>
153
- @ <li> <a href="%s(g.zTop)/wiki_rules">Formatting rules</a> for
154
- @ wiki.</li>
155
- @ <li> Use the <a href="%s(g.zTop)/wiki?name=Sandbox">Sandbox</a>
151
+ @ <li> %z(href("%R/timeline?y=w"))Recent changes</a> to wiki pages.</li>
152
+ @ <li> %z(href("%R/wiki_rules"))Formatting rules</a> for wiki.</li>
153
+ @ <li> Use the %z(href("%R/wiki?name=Sandbox"))Sandbox</a>
156154
@ to experiment.</li>
157155
if( g.perm.NewWiki ){
158
- @ <li> Create a <a href="%s(g.zTop)/wikinew">new wiki page</a>.</li>
156
+ @ <li> Create a %z(href("%R/wikinew"))new wiki page</a>.</li>
159157
if( g.perm.Write ){
160
- @ <li> Create a <a href="%s(g.zTop)/eventedit">new event</a>.</li>
158
+ @ <li> Create a %z(href("%R/eventedit"))new event</a>.</li>
161159
}
162160
}
163
- @ <li> <a href="%s(g.zTop)/wcontent">List of All Wiki Pages</a>
161
+ @ <li> %z(href("%R/wcontent"))List of All Wiki Pages</a>
164162
@ available on this server.</li>
165163
@ <li> <form method="get" action="%s(g.zTop)/wfind"><div>
166164
@ Search wiki titles: <input type="text" name="title"/>
167165
@ &nbsp; <input type="submit" /></div></form>
168166
@ </li>
@@ -199,11 +197,11 @@
199197
}
200198
if( rid && g.perm.ApndWiki ){
201199
style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T",
202200
g.zTop, zPageName);
203201
}
204
- if( g.perm.History ){
202
+ if( g.perm.Hyperlink ){
205203
style_submenu_element("History", "History", "%s/whistory?name=%T",
206204
g.zTop, zPageName);
207205
}
208206
}
209207
style_header(zPageName);
@@ -225,20 +223,20 @@
225223
@ <hr /><h2>Attachments:</h2>
226224
@ <ul>
227225
}
228226
cnt++;
229227
@ <li>
230
- if( g.perm.History && g.perm.Read ){
231
- @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&amp;file=%t(zFile)">
228
+ if( g.perm.Hyperlink && g.perm.Read ){
229
+ @ %z(href("%R/attachview?page=%T&amp;file=%t",zPageName,zFile))
232230
@ %h(zFile)</a>
233231
}else{
234232
@ %h(zFile)
235233
}
236234
@ added by %h(zUser) on
237235
hyperlink_to_date(zDate, ".");
238236
if( g.perm.WrWiki && g.perm.Attach ){
239
- @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&amp;file=%t(zFile)&amp;from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>]
237
+ @ [%z(href("%R/attachdelete?page=%t&amp;file=%t&amp;from=%R/wiki%%3fname=%f",zPageName,zFile,zPageName))delete</a>]
240238
}
241239
@ </li>
242240
}
243241
if( cnt ){
244242
@ </ul>
@@ -544,11 +542,11 @@
544542
** Function called to output extra text at the end of each line in
545543
** a wiki history listing.
546544
*/
547545
static void wiki_history_extra(int rid){
548546
if( db_exists("SELECT 1 FROM tagxref WHERE rid=%d", rid) ){
549
- @ <a href="%s(g.zTop)/wdiff?name=%t(zWikiPageName)&amp;a=%d(rid)">[diff]</a>
547
+ @ %z(href("%R/wdiff?name=%t&amp;a=%d",zWikiPageName,rid))[diff]</a>
550548
}
551549
}
552550
553551
/*
554552
** WEBPAGE: whistory
@@ -560,11 +558,11 @@
560558
Stmt q;
561559
char *zTitle;
562560
char *zSQL;
563561
const char *zPageName;
564562
login_check_credentials();
565
- if( !g.perm.History ){ login_needed(); return; }
563
+ if( !g.perm.Hyperlink ){ login_needed(); return; }
566564
zPageName = PD("name","");
567565
zTitle = mprintf("History Of %s", zPageName);
568566
style_header(zTitle);
569567
free(zTitle);
570568
@@ -597,11 +595,11 @@
597595
Blob w1, w2, d;
598596
int diffFlags;
599597
600598
login_check_credentials();
601599
rid1 = atoi(PD("a","0"));
602
- if( !g.perm.History ){ login_needed(); return; }
600
+ if( !g.perm.Hyperlink ){ login_needed(); return; }
603601
if( rid1==0 ) fossil_redirect_home();
604602
rid2 = atoi(PD("b","0"));
605603
zPageName = PD("name","");
606604
zTitle = mprintf("Changes To %s", zPageName);
607605
style_header(zTitle);
@@ -674,13 +672,13 @@
674672
wiki_prepare_page_list(&q);
675673
while( db_step(&q)==SQLITE_ROW ){
676674
const char *zName = db_column_text(&q, 0);
677675
int size = db_column_int(&q, 1);
678676
if( size>0 ){
679
- @ <li><a href="%s(g.zTop)/wiki?name=%T(zName)">%h(zName)</a></li>
677
+ @ <li>%z(href("%R/wiki?name=%T",zName))%h(zName)</a></li>
680678
}else if( showAll ){
681
- @ <li><a href="%s(g.zTop)/wiki?name=%T(zName)"><s>%h(zName)</s></a></li>
679
+ @ <li>%z(href("%R/wiki?name=%T",zName))<s>%h(zName)</s></a></li>
682680
}
683681
}
684682
db_finalize(&q);
685683
@ </ul>
686684
style_footer();
@@ -704,11 +702,11 @@
704702
"SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'"
705703
" ORDER BY lower(tagname) /*sort*/" ,
706704
zTitle);
707705
while( db_step(&q)==SQLITE_ROW ){
708706
const char *zName = db_column_text(&q, 0);
709
- @ <li><a href="%s(g.zTop)/wiki?name=%T(zName)">%h(zName)</a></li>
707
+ @ <li>%z(href("%R/wiki?name=%T",zName))%h(zName)</a></li>
710708
}
711709
db_finalize(&q);
712710
@ </ul>
713711
style_footer();
714712
}
715713
--- src/wiki.c
+++ src/wiki.c
@@ -104,11 +104,11 @@
104 return;
105 }
106 style_header("Home");
107 @ <p>This is a stub home-page for the project.
108 @ To fill in this page, first go to
109 @ <a href="%s(g.zTop)/setup_config">setup/config</a>
110 @ and establish a "Project Name". Then create a
111 @ wiki page with that name. The content of that wiki page
112 @ will be displayed in place of this message.</p>
113 style_footer();
114 }
@@ -142,27 +142,25 @@
142 if( zPageName==0 ){
143 style_header("Wiki");
144 @ <ul>
145 { char *zHomePageName = db_get("project-name",0);
146 if( zHomePageName ){
147 @ <li> <a href="%s(g.zTop)/wiki?name=%t(zHomePageName)">
148 @ %h(zHomePageName)</a> wiki home page.</li>
149 }
150 }
151 @ <li> <a href="%s(g.zTop)/timeline?y=w">Recent changes</a> to wiki
152 @ pages. </li>
153 @ <li> <a href="%s(g.zTop)/wiki_rules">Formatting rules</a> for
154 @ wiki.</li>
155 @ <li> Use the <a href="%s(g.zTop)/wiki?name=Sandbox">Sandbox</a>
156 @ to experiment.</li>
157 if( g.perm.NewWiki ){
158 @ <li> Create a <a href="%s(g.zTop)/wikinew">new wiki page</a>.</li>
159 if( g.perm.Write ){
160 @ <li> Create a <a href="%s(g.zTop)/eventedit">new event</a>.</li>
161 }
162 }
163 @ <li> <a href="%s(g.zTop)/wcontent">List of All Wiki Pages</a>
164 @ available on this server.</li>
165 @ <li> <form method="get" action="%s(g.zTop)/wfind"><div>
166 @ Search wiki titles: <input type="text" name="title"/>
167 @ &nbsp; <input type="submit" /></div></form>
168 @ </li>
@@ -199,11 +197,11 @@
199 }
200 if( rid && g.perm.ApndWiki ){
201 style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T",
202 g.zTop, zPageName);
203 }
204 if( g.perm.History ){
205 style_submenu_element("History", "History", "%s/whistory?name=%T",
206 g.zTop, zPageName);
207 }
208 }
209 style_header(zPageName);
@@ -225,20 +223,20 @@
225 @ <hr /><h2>Attachments:</h2>
226 @ <ul>
227 }
228 cnt++;
229 @ <li>
230 if( g.perm.History && g.perm.Read ){
231 @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&amp;file=%t(zFile)">
232 @ %h(zFile)</a>
233 }else{
234 @ %h(zFile)
235 }
236 @ added by %h(zUser) on
237 hyperlink_to_date(zDate, ".");
238 if( g.perm.WrWiki && g.perm.Attach ){
239 @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&amp;file=%t(zFile)&amp;from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>]
240 }
241 @ </li>
242 }
243 if( cnt ){
244 @ </ul>
@@ -544,11 +542,11 @@
544 ** Function called to output extra text at the end of each line in
545 ** a wiki history listing.
546 */
547 static void wiki_history_extra(int rid){
548 if( db_exists("SELECT 1 FROM tagxref WHERE rid=%d", rid) ){
549 @ <a href="%s(g.zTop)/wdiff?name=%t(zWikiPageName)&amp;a=%d(rid)">[diff]</a>
550 }
551 }
552
553 /*
554 ** WEBPAGE: whistory
@@ -560,11 +558,11 @@
560 Stmt q;
561 char *zTitle;
562 char *zSQL;
563 const char *zPageName;
564 login_check_credentials();
565 if( !g.perm.History ){ login_needed(); return; }
566 zPageName = PD("name","");
567 zTitle = mprintf("History Of %s", zPageName);
568 style_header(zTitle);
569 free(zTitle);
570
@@ -597,11 +595,11 @@
597 Blob w1, w2, d;
598 int diffFlags;
599
600 login_check_credentials();
601 rid1 = atoi(PD("a","0"));
602 if( !g.perm.History ){ login_needed(); return; }
603 if( rid1==0 ) fossil_redirect_home();
604 rid2 = atoi(PD("b","0"));
605 zPageName = PD("name","");
606 zTitle = mprintf("Changes To %s", zPageName);
607 style_header(zTitle);
@@ -674,13 +672,13 @@
674 wiki_prepare_page_list(&q);
675 while( db_step(&q)==SQLITE_ROW ){
676 const char *zName = db_column_text(&q, 0);
677 int size = db_column_int(&q, 1);
678 if( size>0 ){
679 @ <li><a href="%s(g.zTop)/wiki?name=%T(zName)">%h(zName)</a></li>
680 }else if( showAll ){
681 @ <li><a href="%s(g.zTop)/wiki?name=%T(zName)"><s>%h(zName)</s></a></li>
682 }
683 }
684 db_finalize(&q);
685 @ </ul>
686 style_footer();
@@ -704,11 +702,11 @@
704 "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'"
705 " ORDER BY lower(tagname) /*sort*/" ,
706 zTitle);
707 while( db_step(&q)==SQLITE_ROW ){
708 const char *zName = db_column_text(&q, 0);
709 @ <li><a href="%s(g.zTop)/wiki?name=%T(zName)">%h(zName)</a></li>
710 }
711 db_finalize(&q);
712 @ </ul>
713 style_footer();
714 }
715
--- src/wiki.c
+++ src/wiki.c
@@ -104,11 +104,11 @@
104 return;
105 }
106 style_header("Home");
107 @ <p>This is a stub home-page for the project.
108 @ To fill in this page, first go to
109 @ %z(href("%R/setup_config"))setup/config</a>
110 @ and establish a "Project Name". Then create a
111 @ wiki page with that name. The content of that wiki page
112 @ will be displayed in place of this message.</p>
113 style_footer();
114 }
@@ -142,27 +142,25 @@
142 if( zPageName==0 ){
143 style_header("Wiki");
144 @ <ul>
145 { char *zHomePageName = db_get("project-name",0);
146 if( zHomePageName ){
147 @ <li> %z(href("%R/wiki?name=%t",zHomePageName))
148 @ %h(zHomePageName)</a> wiki home page.</li>
149 }
150 }
151 @ <li> %z(href("%R/timeline?y=w"))Recent changes</a> to wiki pages.</li>
152 @ <li> %z(href("%R/wiki_rules"))Formatting rules</a> for wiki.</li>
153 @ <li> Use the %z(href("%R/wiki?name=Sandbox"))Sandbox</a>
 
 
154 @ to experiment.</li>
155 if( g.perm.NewWiki ){
156 @ <li> Create a %z(href("%R/wikinew"))new wiki page</a>.</li>
157 if( g.perm.Write ){
158 @ <li> Create a %z(href("%R/eventedit"))new event</a>.</li>
159 }
160 }
161 @ <li> %z(href("%R/wcontent"))List of All Wiki Pages</a>
162 @ available on this server.</li>
163 @ <li> <form method="get" action="%s(g.zTop)/wfind"><div>
164 @ Search wiki titles: <input type="text" name="title"/>
165 @ &nbsp; <input type="submit" /></div></form>
166 @ </li>
@@ -199,11 +197,11 @@
197 }
198 if( rid && g.perm.ApndWiki ){
199 style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T",
200 g.zTop, zPageName);
201 }
202 if( g.perm.Hyperlink ){
203 style_submenu_element("History", "History", "%s/whistory?name=%T",
204 g.zTop, zPageName);
205 }
206 }
207 style_header(zPageName);
@@ -225,20 +223,20 @@
223 @ <hr /><h2>Attachments:</h2>
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>
@@ -544,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
@@ -560,11 +558,11 @@
558 Stmt q;
559 char *zTitle;
560 char *zSQL;
561 const char *zPageName;
562 login_check_credentials();
563 if( !g.perm.Hyperlink ){ login_needed(); return; }
564 zPageName = PD("name","");
565 zTitle = mprintf("History Of %s", zPageName);
566 style_header(zTitle);
567 free(zTitle);
568
@@ -597,11 +595,11 @@
595 Blob w1, w2, d;
596 int diffFlags;
597
598 login_check_credentials();
599 rid1 = atoi(PD("a","0"));
600 if( !g.perm.Hyperlink ){ login_needed(); return; }
601 if( rid1==0 ) fossil_redirect_home();
602 rid2 = atoi(PD("b","0"));
603 zPageName = PD("name","");
604 zTitle = mprintf("Changes To %s", zPageName);
605 style_header(zTitle);
@@ -674,13 +672,13 @@
672 wiki_prepare_page_list(&q);
673 while( db_step(&q)==SQLITE_ROW ){
674 const char *zName = db_column_text(&q, 0);
675 int size = db_column_int(&q, 1);
676 if( size>0 ){
677 @ <li>%z(href("%R/wiki?name=%T",zName))%h(zName)</a></li>
678 }else if( showAll ){
679 @ <li>%z(href("%R/wiki?name=%T",zName))<s>%h(zName)</s></a></li>
680 }
681 }
682 db_finalize(&q);
683 @ </ul>
684 style_footer();
@@ -704,11 +702,11 @@
702 "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'"
703 " ORDER BY lower(tagname) /*sort*/" ,
704 zTitle);
705 while( db_step(&q)==SQLITE_ROW ){
706 const char *zName = db_column_text(&q, 0);
707 @ <li>%z(href("%R/wiki?name=%T",zName))%h(zName)</a></li>
708 }
709 db_finalize(&q);
710 @ </ul>
711 style_footer();
712 }
713
+8 -10
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1049,11 +1049,11 @@
10491049
blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zTop, zTarget);
10501050
}else{
10511051
zTerm = "";
10521052
}
10531053
}else if( zTarget[0]=='.' || zTarget[0]=='#' ){
1054
- if( 1 /* g.perm.History */ ){
1054
+ if( 1 ){
10551055
blob_appendf(p->pOut, "<a href=\"%h\">", zTarget);
10561056
}else{
10571057
zTerm = "";
10581058
}
10591059
}else if( is_valid_uuid(zTarget) ){
@@ -1061,36 +1061,34 @@
10611061
if( is_ticket(zTarget, &isClosed) ){
10621062
/* Special display processing for tickets. Display the hyperlink
10631063
** as crossed out if the ticket is closed.
10641064
*/
10651065
if( isClosed ){
1066
- if( g.perm.History ){
1066
+ if( g.perm.Hyperlink ){
10671067
blob_appendf(p->pOut,
1068
- "<a href=\"%s/info/%s\"><span class=\"wikiTagCancelled\">[",
1069
- g.zTop, zTarget
1068
+ "%z<span class=\"wikiTagCancelled\">[",
1069
+ href("%R/info/%s",zTarget)
10701070
);
10711071
zTerm = "]</span></a>";
10721072
}else{
10731073
blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">[");
10741074
zTerm = "]</span>";
10751075
}
10761076
}else{
1077
- if( g.perm.History ){
1078
- blob_appendf(p->pOut,"<a href=\"%s/info/%s\">[",
1079
- g.zTop, zTarget
1080
- );
1077
+ if( g.perm.Hyperlink ){
1078
+ blob_appendf(p->pOut,"%z[", href("%R/info/%s", zTarget));
10811079
zTerm = "]</a>";
10821080
}else{
10831081
blob_appendf(p->pOut, "[");
10841082
zTerm = "]";
10851083
}
10861084
}
10871085
}else if( !in_this_repo(zTarget) ){
10881086
blob_appendf(p->pOut, "<span class=\"brokenlink\">[", zTarget);
10891087
zTerm = "]</span>";
1090
- }else if( g.perm.History ){
1091
- blob_appendf(p->pOut, "<a href=\"%s/info/%s\">[", g.zTop, zTarget);
1088
+ }else if( g.perm.Hyperlink ){
1089
+ blob_appendf(p->pOut, "%z[",href("%R/info/%s", zTarget));
10921090
zTerm = "]</a>";
10931091
}
10941092
}else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-'
10951093
&& db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){
10961094
blob_appendf(p->pOut, "<a href=\"%s/timeline?c=%T\">", g.zTop, zTarget);
10971095
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1049,11 +1049,11 @@
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 /* g.perm.History */ ){
1055 blob_appendf(p->pOut, "<a href=\"%h\">", zTarget);
1056 }else{
1057 zTerm = "";
1058 }
1059 }else if( is_valid_uuid(zTarget) ){
@@ -1061,36 +1061,34 @@
1061 if( is_ticket(zTarget, &isClosed) ){
1062 /* Special display processing for tickets. Display the hyperlink
1063 ** as crossed out if the ticket is closed.
1064 */
1065 if( isClosed ){
1066 if( g.perm.History ){
1067 blob_appendf(p->pOut,
1068 "<a href=\"%s/info/%s\"><span class=\"wikiTagCancelled\">[",
1069 g.zTop, zTarget
1070 );
1071 zTerm = "]</span></a>";
1072 }else{
1073 blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">[");
1074 zTerm = "]</span>";
1075 }
1076 }else{
1077 if( g.perm.History ){
1078 blob_appendf(p->pOut,"<a href=\"%s/info/%s\">[",
1079 g.zTop, zTarget
1080 );
1081 zTerm = "]</a>";
1082 }else{
1083 blob_appendf(p->pOut, "[");
1084 zTerm = "]";
1085 }
1086 }
1087 }else if( !in_this_repo(zTarget) ){
1088 blob_appendf(p->pOut, "<span class=\"brokenlink\">[", zTarget);
1089 zTerm = "]</span>";
1090 }else if( g.perm.History ){
1091 blob_appendf(p->pOut, "<a href=\"%s/info/%s\">[", g.zTop, zTarget);
1092 zTerm = "]</a>";
1093 }
1094 }else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-'
1095 && db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){
1096 blob_appendf(p->pOut, "<a href=\"%s/timeline?c=%T\">", g.zTop, zTarget);
1097
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -1049,11 +1049,11 @@
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 }
1059 }else if( is_valid_uuid(zTarget) ){
@@ -1061,36 +1061,34 @@
1061 if( is_ticket(zTarget, &isClosed) ){
1062 /* Special display processing for tickets. Display the hyperlink
1063 ** as crossed out if the ticket is closed.
1064 */
1065 if( isClosed ){
1066 if( g.perm.Hyperlink ){
1067 blob_appendf(p->pOut,
1068 "%z<span class=\"wikiTagCancelled\">[",
1069 href("%R/info/%s",zTarget)
1070 );
1071 zTerm = "]</span></a>";
1072 }else{
1073 blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">[");
1074 zTerm = "]</span>";
1075 }
1076 }else{
1077 if( g.perm.Hyperlink ){
1078 blob_appendf(p->pOut,"%z[", href("%R/info/%s", zTarget));
 
 
1079 zTerm = "]</a>";
1080 }else{
1081 blob_appendf(p->pOut, "[");
1082 zTerm = "]";
1083 }
1084 }
1085 }else if( !in_this_repo(zTarget) ){
1086 blob_appendf(p->pOut, "<span class=\"brokenlink\">[", zTarget);
1087 zTerm = "]</span>";
1088 }else if( g.perm.Hyperlink ){
1089 blob_appendf(p->pOut, "%z[",href("%R/info/%s", zTarget));
1090 zTerm = "]</a>";
1091 }
1092 }else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-'
1093 && db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){
1094 blob_appendf(p->pOut, "<a href=\"%s/timeline?c=%T\">", g.zTop, zTarget);
1095

Keyboard Shortcuts

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