Fossil SCM

Merge the CSS and XHTML fixes from the wolfgangFormat2CSS branch into the trunk.

drh 2010-09-13 23:40 trunk merge
Commit 3243e63bba43c3dd5ca2fde9eaaf7642af389061
+8 -8
--- src/attach.c
+++ src/attach.c
@@ -75,20 +75,20 @@
7575
zFilename = &zFilename[i+1];
7676
i = -1;
7777
}
7878
}
7979
if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
80
- zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
80
+ zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
8181
}else{
82
- zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename);
82
+ zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename);
8383
}
8484
@
8585
@ <p><a href="/attachview?%s(zUrlTail)">%h(zFilename)</a>
86
- @ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br>
86
+ @ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br />
8787
if( zComment ) while( isspace(zComment[0]) ) zComment++;
8888
if( zComment && zComment[0] ){
89
- @ %w(zComment)<br>
89
+ @ %w(zComment)<br />
9090
}
9191
if( zPage==0 && zTkt==0 ){
9292
if( zSrc==0 || zSrc[0]==0 ){
9393
zSrc = "Deleted from";
9494
}else {
@@ -273,13 +273,13 @@
273273
style_header("Add Attachment");
274274
@ <h2>Add Attachment To %s(zTargetType)</h2>
275275
@ <form action="%s(g.zBaseURL)/attachadd" method="POST"
276276
@ enctype="multipart/form-data">
277277
@ File to Attach:
278
- @ <input type="file" name="f" size="60"><br>
279
- @ Description:<br>
280
- @ <textarea name="comment" cols=80 rows=5 wrap="virtual"></textarea><br>
278
+ @ <input type="file" name="f" size="60"><br />
279
+ @ Description:<br />
280
+ @ <textarea name="comment" cols=80 rows=5 wrap="virtual"></textarea><br />
281281
if( zTkt ){
282282
@ <input type="hidden" name="tkt" value="%h(zTkt)">
283283
}else{
284284
@ <input type="hidden" name="page" value="%h(zPage)">
285285
}
@@ -351,11 +351,11 @@
351351
cgi_redirect(zFrom);
352352
}
353353
style_header("Delete Attachment");
354354
@ <form action="%s(g.zBaseURL)/attachdelete" method="POST">
355355
@ <p>Confirm that you want to delete the attachment named
356
- @ "%h(zFile)" on %s(zTkt?"ticket":"wiki page") %h(zTarget):<br>
356
+ @ "%h(zFile)" on %s(zTkt?"ticket":"wiki page") %h(zTarget):<br />
357357
if( zTkt ){
358358
@ <input type="hidden" name="tkt" value="%h(zTkt)">
359359
}else{
360360
@ <input type="hidden" name="page" value="%h(zPage)">
361361
}
362362
--- src/attach.c
+++ src/attach.c
@@ -75,20 +75,20 @@
75 zFilename = &zFilename[i+1];
76 i = -1;
77 }
78 }
79 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
80 zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
81 }else{
82 zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename);
83 }
84 @
85 @ <p><a href="/attachview?%s(zUrlTail)">%h(zFilename)</a>
86 @ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br>
87 if( zComment ) while( isspace(zComment[0]) ) zComment++;
88 if( zComment && zComment[0] ){
89 @ %w(zComment)<br>
90 }
91 if( zPage==0 && zTkt==0 ){
92 if( zSrc==0 || zSrc[0]==0 ){
93 zSrc = "Deleted from";
94 }else {
@@ -273,13 +273,13 @@
273 style_header("Add Attachment");
274 @ <h2>Add Attachment To %s(zTargetType)</h2>
275 @ <form action="%s(g.zBaseURL)/attachadd" method="POST"
276 @ enctype="multipart/form-data">
277 @ File to Attach:
278 @ <input type="file" name="f" size="60"><br>
279 @ Description:<br>
280 @ <textarea name="comment" cols=80 rows=5 wrap="virtual"></textarea><br>
281 if( zTkt ){
282 @ <input type="hidden" name="tkt" value="%h(zTkt)">
283 }else{
284 @ <input type="hidden" name="page" value="%h(zPage)">
285 }
@@ -351,11 +351,11 @@
351 cgi_redirect(zFrom);
352 }
353 style_header("Delete Attachment");
354 @ <form action="%s(g.zBaseURL)/attachdelete" method="POST">
355 @ <p>Confirm that you want to delete the attachment named
356 @ "%h(zFile)" on %s(zTkt?"ticket":"wiki page") %h(zTarget):<br>
357 if( zTkt ){
358 @ <input type="hidden" name="tkt" value="%h(zTkt)">
359 }else{
360 @ <input type="hidden" name="page" value="%h(zPage)">
361 }
362
--- src/attach.c
+++ src/attach.c
@@ -75,20 +75,20 @@
75 zFilename = &zFilename[i+1];
76 i = -1;
77 }
78 }
79 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
80 zUrlTail = mprintf("tkt=%s&amp;file=%t", zTarget, zFilename);
81 }else{
82 zUrlTail = mprintf("page=%t&amp;file=%t", zTarget, zFilename);
83 }
84 @
85 @ <p><a href="/attachview?%s(zUrlTail)">%h(zFilename)</a>
86 @ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br />
87 if( zComment ) while( isspace(zComment[0]) ) zComment++;
88 if( zComment && zComment[0] ){
89 @ %w(zComment)<br />
90 }
91 if( zPage==0 && zTkt==0 ){
92 if( zSrc==0 || zSrc[0]==0 ){
93 zSrc = "Deleted from";
94 }else {
@@ -273,13 +273,13 @@
273 style_header("Add Attachment");
274 @ <h2>Add Attachment To %s(zTargetType)</h2>
275 @ <form action="%s(g.zBaseURL)/attachadd" method="POST"
276 @ enctype="multipart/form-data">
277 @ File to Attach:
278 @ <input type="file" name="f" size="60"><br />
279 @ Description:<br />
280 @ <textarea name="comment" cols=80 rows=5 wrap="virtual"></textarea><br />
281 if( zTkt ){
282 @ <input type="hidden" name="tkt" value="%h(zTkt)">
283 }else{
284 @ <input type="hidden" name="page" value="%h(zPage)">
285 }
@@ -351,11 +351,11 @@
351 cgi_redirect(zFrom);
352 }
353 style_header("Delete Attachment");
354 @ <form action="%s(g.zBaseURL)/attachdelete" method="POST">
355 @ <p>Confirm that you want to delete the attachment named
356 @ "%h(zFile)" on %s(zTkt?"ticket":"wiki page") %h(zTarget):<br />
357 if( zTkt ){
358 @ <input type="hidden" name="tkt" value="%h(zTkt)">
359 }else{
360 @ <input type="hidden" name="page" value="%h(zPage)">
361 }
362
+8 -8
--- src/branch.c
+++ src/branch.c
@@ -231,16 +231,19 @@
231231
}
232232
login_anonymous_available();
233233
compute_leaves(0, 1);
234234
style_sidebox_begin("Nomenclature:", "33%");
235235
@ <ol>
236
- @ <li> An <a href="brlist">open branch</a> is a branch that has one or
236
+ @ <li> An <div class="sideboxDescribed"><a href="brlist">
237
+ @ open branch</a></div> is a branch that has one or
237238
@ more <a href="leaves">open leaves.</a>
238239
@ The presence of open leaves presumably means
239240
@ that the branch is still being extended with new check-ins.</li>
240
- @ <li> A <a href="brlist?closed">closed branch</a> is a branch with only
241
- @ <a href="leaves?closed">closed leaves</a>.
241
+ @ <li> A <div class="sideboxDescribed"><a href="brlist?closed">
242
+ @ closed branch</a></div> is a branch with only
243
+ @ <div class="sideboxDescribed"><a href="leaves?closed">
244
+ @ closed leaves</a></div>.
242245
@ Closed branches are fixed and do not change (unless they are first
243246
@ reopened)</li>
244247
@ </ol>
245248
style_sidebox_end();
246249
@@ -284,13 +287,11 @@
284287
}
285288
if( cnt ){
286289
@ </ul>
287290
}
288291
db_finalize(&q);
289
- @ </ul>
290
- @ <br clear="both">
291
- @ <script>
292
+ @ <script type="text/JavaScript">
292293
@ function xin(id){
293294
@ }
294295
@ function xout(id){
295296
@ }
296297
@ </script>
@@ -341,14 +342,13 @@
341342
" ORDER BY event.mtime DESC",
342343
timeline_query_for_www(), TAG_BRANCH
343344
);
344345
www_print_timeline(&q, 0, brtimeline_extra);
345346
db_finalize(&q);
346
- @ <br clear="both">
347
- @ <script>
347
+ @ <script type="text/JavaScript">
348348
@ function xin(id){
349349
@ }
350350
@ function xout(id){
351351
@ }
352352
@ </script>
353353
style_footer();
354354
}
355355
--- src/branch.c
+++ src/branch.c
@@ -231,16 +231,19 @@
231 }
232 login_anonymous_available();
233 compute_leaves(0, 1);
234 style_sidebox_begin("Nomenclature:", "33%");
235 @ <ol>
236 @ <li> An <a href="brlist">open branch</a> is a branch that has one or
 
237 @ more <a href="leaves">open leaves.</a>
238 @ The presence of open leaves presumably means
239 @ that the branch is still being extended with new check-ins.</li>
240 @ <li> A <a href="brlist?closed">closed branch</a> is a branch with only
241 @ <a href="leaves?closed">closed leaves</a>.
 
 
242 @ Closed branches are fixed and do not change (unless they are first
243 @ reopened)</li>
244 @ </ol>
245 style_sidebox_end();
246
@@ -284,13 +287,11 @@
284 }
285 if( cnt ){
286 @ </ul>
287 }
288 db_finalize(&q);
289 @ </ul>
290 @ <br clear="both">
291 @ <script>
292 @ function xin(id){
293 @ }
294 @ function xout(id){
295 @ }
296 @ </script>
@@ -341,14 +342,13 @@
341 " ORDER BY event.mtime DESC",
342 timeline_query_for_www(), TAG_BRANCH
343 );
344 www_print_timeline(&q, 0, brtimeline_extra);
345 db_finalize(&q);
346 @ <br clear="both">
347 @ <script>
348 @ function xin(id){
349 @ }
350 @ function xout(id){
351 @ }
352 @ </script>
353 style_footer();
354 }
355
--- src/branch.c
+++ src/branch.c
@@ -231,16 +231,19 @@
231 }
232 login_anonymous_available();
233 compute_leaves(0, 1);
234 style_sidebox_begin("Nomenclature:", "33%");
235 @ <ol>
236 @ <li> An <div class="sideboxDescribed"><a href="brlist">
237 @ open branch</a></div> is a branch that has one or
238 @ more <a href="leaves">open leaves.</a>
239 @ The presence of open leaves presumably means
240 @ that the branch is still being extended with new check-ins.</li>
241 @ <li> A <div class="sideboxDescribed"><a href="brlist?closed">
242 @ closed branch</a></div> is a branch with only
243 @ <div class="sideboxDescribed"><a href="leaves?closed">
244 @ closed leaves</a></div>.
245 @ Closed branches are fixed and do not change (unless they are first
246 @ reopened)</li>
247 @ </ol>
248 style_sidebox_end();
249
@@ -284,13 +287,11 @@
287 }
288 if( cnt ){
289 @ </ul>
290 }
291 db_finalize(&q);
292 @ <script type="text/JavaScript">
 
 
293 @ function xin(id){
294 @ }
295 @ function xout(id){
296 @ }
297 @ </script>
@@ -341,14 +342,13 @@
342 " ORDER BY event.mtime DESC",
343 timeline_query_for_www(), TAG_BRANCH
344 );
345 www_print_timeline(&q, 0, brtimeline_extra);
346 db_finalize(&q);
347 @ <script type="text/JavaScript">
 
348 @ function xin(id){
349 @ }
350 @ function xout(id){
351 @ }
352 @ </script>
353 style_footer();
354 }
355
+9 -8
--- src/browse.c
+++ src/browse.c
@@ -144,11 +144,11 @@
144144
char zShort[20];
145145
memcpy(zShort, zUuid, 10);
146146
zShort[10] = 0;
147147
@ <h2>Files of check-in [<a href="vinfo?name=%T(zUuid)">%s(zShort)</a>]
148148
@ %s(blob_str(&dirname))</h2>
149
- zSubdirLink = mprintf("%s/dir?ci=%S&name=%T", g.zTop, zUuid, zPrefix);
149
+ zSubdirLink = mprintf("%s/dir?ci=%S&amp;name=%T", g.zTop, zUuid, zPrefix);
150150
if( zD ){
151151
style_submenu_element("Top", "Top", "%s/dir?ci=%S", g.zTop, zUuid);
152152
style_submenu_element("All", "All", "%s/dir?name=%t", g.zTop, zD);
153153
}else{
154154
style_submenu_element("All", "All", "%s/dir", g.zBaseURL);
@@ -157,13 +157,13 @@
157157
@ <h2>The union of all files from all check-ins
158158
@ %s(blob_str(&dirname))</h2>
159159
zSubdirLink = mprintf("%s/dir?name=%T", g.zBaseURL, zPrefix);
160160
if( zD ){
161161
style_submenu_element("Top", "Top", "%s/dir", g.zBaseURL);
162
- style_submenu_element("Tip", "Tip", "%s/dir?name=%t&ci=tip",
162
+ style_submenu_element("Tip", "Tip", "%s/dir?name=%t&amp;ci=tip",
163163
g.zBaseURL, zD);
164
- style_submenu_element("Trunk", "Trunk", "%s/dir?name=%t&ci=trunk",
164
+ style_submenu_element("Trunk", "Trunk", "%s/dir?name=%t&amp;ci=trunk",
165165
g.zBaseURL,zD);
166166
}else{
167167
style_submenu_element("Tip", "Tip", "%s/dir?ci=tip", g.zBaseURL);
168168
style_submenu_element("Trunk", "Trunk", "%s/dir?ci=trunk", g.zBaseURL);
169169
}
@@ -216,29 +216,30 @@
216216
mxLen = db_int(12, "SELECT max(length(x)) FROM localfiles /*scan*/");
217217
cnt = db_int(0, "SELECT count(*) FROM localfiles /*scan*/");
218218
nCol = 4;
219219
nRow = (cnt+nCol-1)/nCol;
220220
db_prepare(&q, "SELECT x, u FROM localfiles ORDER BY x /*scan*/");
221
- @ <table border="0" width="100%%"><tr><td valign="top" width="25%%">
221
+ @ <table class="browser"><tr><td class="browser"><ul class="browser">
222222
i = 0;
223223
while( db_step(&q)==SQLITE_ROW ){
224224
const char *zFN;
225225
if( i==nRow ){
226
- @ </td><td valign="top" width="25%%">
226
+ @ </ul></td><td class="browser"><ul class="browser">
227227
i = 0;
228228
}
229229
i++;
230230
zFN = db_column_text(&q, 0);
231231
if( zFN[0]=='/' ){
232232
zFN++;
233233
@ <li><a href="%s(zSubdirLink)%T(zFN)">%h(zFN)/</a></li>
234234
}else if( zCI ){
235235
const char *zUuid = db_column_text(&q, 1);
236
- @ <li><a href="%s(g.zBaseURL)/artifact?name=%s(zUuid)">%h(zFN)</a>
236
+ @ <li><a href="%s(g.zBaseURL)/artifact?name=%s(zUuid)">%h(zFN)</a></li>
237237
}else{
238
- @ <li><a href="%s(g.zBaseURL)/finfo?name=%T(zPrefix)%T(zFN)">%h(zFN)</a>
238
+ @ <li><a href="%s(g.zBaseURL)/finfo?name=%T(zPrefix)%T(zFN)">%h(zFN)
239
+ @ </a></li>
239240
}
240241
}
241242
db_finalize(&q);
242
- @ </td></tr></table>
243
+ @ </ul></td></tr></table>
243244
style_footer();
244245
}
245246
--- src/browse.c
+++ src/browse.c
@@ -144,11 +144,11 @@
144 char zShort[20];
145 memcpy(zShort, zUuid, 10);
146 zShort[10] = 0;
147 @ <h2>Files of check-in [<a href="vinfo?name=%T(zUuid)">%s(zShort)</a>]
148 @ %s(blob_str(&dirname))</h2>
149 zSubdirLink = mprintf("%s/dir?ci=%S&name=%T", g.zTop, zUuid, zPrefix);
150 if( zD ){
151 style_submenu_element("Top", "Top", "%s/dir?ci=%S", g.zTop, zUuid);
152 style_submenu_element("All", "All", "%s/dir?name=%t", g.zTop, zD);
153 }else{
154 style_submenu_element("All", "All", "%s/dir", g.zBaseURL);
@@ -157,13 +157,13 @@
157 @ <h2>The union of all files from all check-ins
158 @ %s(blob_str(&dirname))</h2>
159 zSubdirLink = mprintf("%s/dir?name=%T", g.zBaseURL, zPrefix);
160 if( zD ){
161 style_submenu_element("Top", "Top", "%s/dir", g.zBaseURL);
162 style_submenu_element("Tip", "Tip", "%s/dir?name=%t&ci=tip",
163 g.zBaseURL, zD);
164 style_submenu_element("Trunk", "Trunk", "%s/dir?name=%t&ci=trunk",
165 g.zBaseURL,zD);
166 }else{
167 style_submenu_element("Tip", "Tip", "%s/dir?ci=tip", g.zBaseURL);
168 style_submenu_element("Trunk", "Trunk", "%s/dir?ci=trunk", g.zBaseURL);
169 }
@@ -216,29 +216,30 @@
216 mxLen = db_int(12, "SELECT max(length(x)) FROM localfiles /*scan*/");
217 cnt = db_int(0, "SELECT count(*) FROM localfiles /*scan*/");
218 nCol = 4;
219 nRow = (cnt+nCol-1)/nCol;
220 db_prepare(&q, "SELECT x, u FROM localfiles ORDER BY x /*scan*/");
221 @ <table border="0" width="100%%"><tr><td valign="top" width="25%%">
222 i = 0;
223 while( db_step(&q)==SQLITE_ROW ){
224 const char *zFN;
225 if( i==nRow ){
226 @ </td><td valign="top" width="25%%">
227 i = 0;
228 }
229 i++;
230 zFN = db_column_text(&q, 0);
231 if( zFN[0]=='/' ){
232 zFN++;
233 @ <li><a href="%s(zSubdirLink)%T(zFN)">%h(zFN)/</a></li>
234 }else if( zCI ){
235 const char *zUuid = db_column_text(&q, 1);
236 @ <li><a href="%s(g.zBaseURL)/artifact?name=%s(zUuid)">%h(zFN)</a>
237 }else{
238 @ <li><a href="%s(g.zBaseURL)/finfo?name=%T(zPrefix)%T(zFN)">%h(zFN)</a>
 
239 }
240 }
241 db_finalize(&q);
242 @ </td></tr></table>
243 style_footer();
244 }
245
--- src/browse.c
+++ src/browse.c
@@ -144,11 +144,11 @@
144 char zShort[20];
145 memcpy(zShort, zUuid, 10);
146 zShort[10] = 0;
147 @ <h2>Files of check-in [<a href="vinfo?name=%T(zUuid)">%s(zShort)</a>]
148 @ %s(blob_str(&dirname))</h2>
149 zSubdirLink = mprintf("%s/dir?ci=%S&amp;name=%T", g.zTop, zUuid, zPrefix);
150 if( zD ){
151 style_submenu_element("Top", "Top", "%s/dir?ci=%S", g.zTop, zUuid);
152 style_submenu_element("All", "All", "%s/dir?name=%t", g.zTop, zD);
153 }else{
154 style_submenu_element("All", "All", "%s/dir", g.zBaseURL);
@@ -157,13 +157,13 @@
157 @ <h2>The union of all files from all check-ins
158 @ %s(blob_str(&dirname))</h2>
159 zSubdirLink = mprintf("%s/dir?name=%T", g.zBaseURL, zPrefix);
160 if( zD ){
161 style_submenu_element("Top", "Top", "%s/dir", g.zBaseURL);
162 style_submenu_element("Tip", "Tip", "%s/dir?name=%t&amp;ci=tip",
163 g.zBaseURL, zD);
164 style_submenu_element("Trunk", "Trunk", "%s/dir?name=%t&amp;ci=trunk",
165 g.zBaseURL,zD);
166 }else{
167 style_submenu_element("Tip", "Tip", "%s/dir?ci=tip", g.zBaseURL);
168 style_submenu_element("Trunk", "Trunk", "%s/dir?ci=trunk", g.zBaseURL);
169 }
@@ -216,29 +216,30 @@
216 mxLen = db_int(12, "SELECT max(length(x)) FROM localfiles /*scan*/");
217 cnt = db_int(0, "SELECT count(*) FROM localfiles /*scan*/");
218 nCol = 4;
219 nRow = (cnt+nCol-1)/nCol;
220 db_prepare(&q, "SELECT x, u FROM localfiles ORDER BY x /*scan*/");
221 @ <table class="browser"><tr><td class="browser"><ul class="browser">
222 i = 0;
223 while( db_step(&q)==SQLITE_ROW ){
224 const char *zFN;
225 if( i==nRow ){
226 @ </ul></td><td class="browser"><ul class="browser">
227 i = 0;
228 }
229 i++;
230 zFN = db_column_text(&q, 0);
231 if( zFN[0]=='/' ){
232 zFN++;
233 @ <li><a href="%s(zSubdirLink)%T(zFN)">%h(zFN)/</a></li>
234 }else if( zCI ){
235 const char *zUuid = db_column_text(&q, 1);
236 @ <li><a href="%s(g.zBaseURL)/artifact?name=%s(zUuid)">%h(zFN)</a></li>
237 }else{
238 @ <li><a href="%s(g.zBaseURL)/finfo?name=%T(zPrefix)%T(zFN)">%h(zFN)
239 @ </a></li>
240 }
241 }
242 db_finalize(&q);
243 @ </ul></td></tr></table>
244 style_footer();
245 }
246
+1 -1
--- src/db.c
+++ src/db.c
@@ -664,11 +664,11 @@
664664
}
665665
#endif
666666
if( file_isdir(zHome)!=1 ){
667667
fossil_fatal("invalid home directory: %s", zHome);
668668
}
669
-#ifndef __MINGW32__
669
+#ifndef _WIN32
670670
if( access(zHome, W_OK) ){
671671
fossil_fatal("home directory %s must be writeable", zHome);
672672
}
673673
#endif
674674
g.zHome = mprintf("%/", zHome);
675675
--- src/db.c
+++ src/db.c
@@ -664,11 +664,11 @@
664 }
665 #endif
666 if( file_isdir(zHome)!=1 ){
667 fossil_fatal("invalid home directory: %s", zHome);
668 }
669 #ifndef __MINGW32__
670 if( access(zHome, W_OK) ){
671 fossil_fatal("home directory %s must be writeable", zHome);
672 }
673 #endif
674 g.zHome = mprintf("%/", zHome);
675
--- src/db.c
+++ src/db.c
@@ -664,11 +664,11 @@
664 }
665 #endif
666 if( file_isdir(zHome)!=1 ){
667 fossil_fatal("invalid home directory: %s", zHome);
668 }
669 #ifndef _WIN32
670 if( access(zHome, W_OK) ){
671 fossil_fatal("home directory %s must be writeable", zHome);
672 }
673 #endif
674 g.zHome = mprintf("%/", zHome);
675
--- src/descendants.c
+++ src/descendants.c
@@ -318,14 +318,17 @@
318318
style_header("Leaves");
319319
login_anonymous_available();
320320
compute_leaves(0, showAll ? 0 : showClosed ? 2 : 1);
321321
style_sidebox_begin("Nomenclature:", "33%");
322322
@ <ol>
323
- @ <li> A <b>leaf</b> is a check-in with no descendants.</li>
324
- @ <li> An <b>open leaf</b> is a leaf that does not have a "closed" tag
323
+ @ <li> A <div class="sideboxDescribed">leaf</div>
324
+ @ is a check-in with no descendants.</li>
325
+ @ <li> An <div class="sideboxDescribed">open leaf</div>
326
+ @ is a leaf that does not have a "closed" tag
325327
@ and is thus assumed to still be in use.</li>
326
- @ <li> A <b>closed leaf</b> has a "closed" tag and is thus assumed to
328
+ @ <li> A <div class="sideboxDescribed">closed leaf</div>
329
+ @ has a "closed" tag and is thus assumed to
327330
@ be historical and no longer in active use.</li>
328331
@ </ol>
329332
style_sidebox_end();
330333
331334
if( showAll ){
@@ -341,14 +344,14 @@
341344
" ORDER BY event.mtime DESC",
342345
timeline_query_for_www()
343346
);
344347
www_print_timeline(&q, TIMELINE_LEAFONLY, leaves_extra);
345348
db_finalize(&q);
346
- @ <br clear="both">
347
- @ <script>
349
+ @ <br />
350
+ @ <script type="text/JavaScript">
348351
@ function xin(id){
349352
@ }
350353
@ function xout(id){
351354
@ }
352355
@ </script>
353356
style_footer();
354357
}
355358
--- src/descendants.c
+++ src/descendants.c
@@ -318,14 +318,17 @@
318 style_header("Leaves");
319 login_anonymous_available();
320 compute_leaves(0, showAll ? 0 : showClosed ? 2 : 1);
321 style_sidebox_begin("Nomenclature:", "33%");
322 @ <ol>
323 @ <li> A <b>leaf</b> is a check-in with no descendants.</li>
324 @ <li> An <b>open leaf</b> is a leaf that does not have a "closed" tag
 
 
325 @ and is thus assumed to still be in use.</li>
326 @ <li> A <b>closed leaf</b> has a "closed" tag and is thus assumed to
 
327 @ be historical and no longer in active use.</li>
328 @ </ol>
329 style_sidebox_end();
330
331 if( showAll ){
@@ -341,14 +344,14 @@
341 " ORDER BY event.mtime DESC",
342 timeline_query_for_www()
343 );
344 www_print_timeline(&q, TIMELINE_LEAFONLY, leaves_extra);
345 db_finalize(&q);
346 @ <br clear="both">
347 @ <script>
348 @ function xin(id){
349 @ }
350 @ function xout(id){
351 @ }
352 @ </script>
353 style_footer();
354 }
355
--- src/descendants.c
+++ src/descendants.c
@@ -318,14 +318,17 @@
318 style_header("Leaves");
319 login_anonymous_available();
320 compute_leaves(0, showAll ? 0 : showClosed ? 2 : 1);
321 style_sidebox_begin("Nomenclature:", "33%");
322 @ <ol>
323 @ <li> A <div class="sideboxDescribed">leaf</div>
324 @ is a check-in with no descendants.</li>
325 @ <li> An <div class="sideboxDescribed">open leaf</div>
326 @ is a leaf that does not have a "closed" tag
327 @ and is thus assumed to still be in use.</li>
328 @ <li> A <div class="sideboxDescribed">closed leaf</div>
329 @ has a "closed" tag and is thus assumed to
330 @ be historical and no longer in active use.</li>
331 @ </ol>
332 style_sidebox_end();
333
334 if( showAll ){
@@ -341,14 +344,14 @@
344 " ORDER BY event.mtime DESC",
345 timeline_query_for_www()
346 );
347 www_print_timeline(&q, TIMELINE_LEAFONLY, leaves_extra);
348 db_finalize(&q);
349 @ <br />
350 @ <script type="text/JavaScript">
351 @ function xin(id){
352 @ }
353 @ function xout(id){
354 @ }
355 @ </script>
356 style_footer();
357 }
358
+11 -9
--- src/finfo.c
+++ src/finfo.c
@@ -136,11 +136,11 @@
136136
hyperlinked_path(zFilename, &title);
137137
@ <h2>%b(&title)</h2>
138138
blob_reset(&title);
139139
pGraph = graph_init();
140140
@ <div id="canvas" style="position:relative;width:1px;height:1px;"></div>
141
- @ <table cellspacing=0 border=0 cellpadding=0>
141
+ @ <table class="timelineTable">
142142
while( db_step(&q)==SQLITE_ROW ){
143143
const char *zDate = db_column_text(&q, 0);
144144
const char *zCom = db_column_text(&q, 1);
145145
const char *zUser = db_column_text(&q, 2);
146146
int fpid = db_column_int(&q, 3);
@@ -157,22 +157,22 @@
157157
if( zBr==0 ) zBr = "trunk";
158158
gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr);
159159
if( memcmp(zDate, zPrevDate, 10) ){
160160
sprintf(zPrevDate, "%.10s", zDate);
161161
@ <tr><td>
162
- @ <div class="divider"><nobr>%s(zPrevDate)</nobr></div>
162
+ @ <div class="divider">%s(zPrevDate)</div>
163163
@ </td></tr>
164164
}
165165
memcpy(zTime, &zDate[11], 5);
166166
zTime[5] = 0;
167
- @ <tr><td valign="top" align="right">
167
+ @ <tr><td class="timelineTime">
168168
@ <a href="%s(g.zTop)/timeline?c=%t(zDate)">%s(zTime)</a></td>
169
- @ <td width="20" align="left" valign="top"><div id="m%d(gidx)"></div></td>
169
+ @ <td class="timelineGraph"><div id="m%d(gidx)"></div></td>
170170
if( zBgClr && zBgClr[0] ){
171
- @ <td valign="top" align="left" bgcolor="%h(zBgClr)">
171
+ @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
172172
}else{
173
- @ <td valign="top" align="left">
173
+ @ <td class="timelineTableCell">
174174
}
175175
sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid);
176176
sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin);
177177
if( zUuid ){
178178
if( g.okHistory ){
@@ -187,27 +187,29 @@
187187
hyperlink_to_uuid(zShortCkin);
188188
@ %h(zCom) (user:
189189
hyperlink_to_user(zUser, zDate, "");
190190
@ branch: %h(zBr))
191191
if( g.okHistory && zUuid ){
192
+ const char *z = zFilename;
192193
if( fpid ){
193194
@ <a href="%s(g.zTop)/fdiff?v1=%s(zPUuid)&amp;v2=%s(zUuid)">[diff]</a>
194195
}
195
- @ <a href="%s(g.zTop)/annotate?checkin=%S(zCkin)&amp;filename=%h(zFilename)">
196
+ @ <a href="%s(g.zTop)/annotate?checkin=%S(zCkin)&amp;filename=%h(z)">
196197
@ [annotate]</a>
197198
}
198
- @ </td>
199
+ @ </td></tr>
199200
}
200201
db_finalize(&q);
201202
if( pGraph ){
202203
graph_finish(pGraph, 1);
203204
if( pGraph->nErr ){
204205
graph_free(pGraph);
205206
pGraph = 0;
206207
}else{
207
- @ <tr><td><td><div style="width:%d(pGraph->mxRail*20+30)px;"></div>
208
+ @ <tr><td></td><td><div style="width:%d(pGraph->mxRail*20+30)px;"></div>
209
+ @ </td></tr>
208210
}
209211
}
210212
@ </table>
211213
timeline_output_graph_javascript(pGraph);
212214
style_footer();
213215
}
214216
--- src/finfo.c
+++ src/finfo.c
@@ -136,11 +136,11 @@
136 hyperlinked_path(zFilename, &title);
137 @ <h2>%b(&title)</h2>
138 blob_reset(&title);
139 pGraph = graph_init();
140 @ <div id="canvas" style="position:relative;width:1px;height:1px;"></div>
141 @ <table cellspacing=0 border=0 cellpadding=0>
142 while( db_step(&q)==SQLITE_ROW ){
143 const char *zDate = db_column_text(&q, 0);
144 const char *zCom = db_column_text(&q, 1);
145 const char *zUser = db_column_text(&q, 2);
146 int fpid = db_column_int(&q, 3);
@@ -157,22 +157,22 @@
157 if( zBr==0 ) zBr = "trunk";
158 gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr);
159 if( memcmp(zDate, zPrevDate, 10) ){
160 sprintf(zPrevDate, "%.10s", zDate);
161 @ <tr><td>
162 @ <div class="divider"><nobr>%s(zPrevDate)</nobr></div>
163 @ </td></tr>
164 }
165 memcpy(zTime, &zDate[11], 5);
166 zTime[5] = 0;
167 @ <tr><td valign="top" align="right">
168 @ <a href="%s(g.zTop)/timeline?c=%t(zDate)">%s(zTime)</a></td>
169 @ <td width="20" align="left" valign="top"><div id="m%d(gidx)"></div></td>
170 if( zBgClr && zBgClr[0] ){
171 @ <td valign="top" align="left" bgcolor="%h(zBgClr)">
172 }else{
173 @ <td valign="top" align="left">
174 }
175 sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid);
176 sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin);
177 if( zUuid ){
178 if( g.okHistory ){
@@ -187,27 +187,29 @@
187 hyperlink_to_uuid(zShortCkin);
188 @ %h(zCom) (user:
189 hyperlink_to_user(zUser, zDate, "");
190 @ branch: %h(zBr))
191 if( g.okHistory && zUuid ){
 
192 if( fpid ){
193 @ <a href="%s(g.zTop)/fdiff?v1=%s(zPUuid)&amp;v2=%s(zUuid)">[diff]</a>
194 }
195 @ <a href="%s(g.zTop)/annotate?checkin=%S(zCkin)&amp;filename=%h(zFilename)">
196 @ [annotate]</a>
197 }
198 @ </td>
199 }
200 db_finalize(&q);
201 if( pGraph ){
202 graph_finish(pGraph, 1);
203 if( pGraph->nErr ){
204 graph_free(pGraph);
205 pGraph = 0;
206 }else{
207 @ <tr><td><td><div style="width:%d(pGraph->mxRail*20+30)px;"></div>
 
208 }
209 }
210 @ </table>
211 timeline_output_graph_javascript(pGraph);
212 style_footer();
213 }
214
--- src/finfo.c
+++ src/finfo.c
@@ -136,11 +136,11 @@
136 hyperlinked_path(zFilename, &title);
137 @ <h2>%b(&title)</h2>
138 blob_reset(&title);
139 pGraph = graph_init();
140 @ <div id="canvas" style="position:relative;width:1px;height:1px;"></div>
141 @ <table class="timelineTable">
142 while( db_step(&q)==SQLITE_ROW ){
143 const char *zDate = db_column_text(&q, 0);
144 const char *zCom = db_column_text(&q, 1);
145 const char *zUser = db_column_text(&q, 2);
146 int fpid = db_column_int(&q, 3);
@@ -157,22 +157,22 @@
157 if( zBr==0 ) zBr = "trunk";
158 gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr);
159 if( memcmp(zDate, zPrevDate, 10) ){
160 sprintf(zPrevDate, "%.10s", zDate);
161 @ <tr><td>
162 @ <div class="divider">%s(zPrevDate)</div>
163 @ </td></tr>
164 }
165 memcpy(zTime, &zDate[11], 5);
166 zTime[5] = 0;
167 @ <tr><td class="timelineTime">
168 @ <a href="%s(g.zTop)/timeline?c=%t(zDate)">%s(zTime)</a></td>
169 @ <td class="timelineGraph"><div id="m%d(gidx)"></div></td>
170 if( zBgClr && zBgClr[0] ){
171 @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
172 }else{
173 @ <td class="timelineTableCell">
174 }
175 sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid);
176 sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin);
177 if( zUuid ){
178 if( g.okHistory ){
@@ -187,27 +187,29 @@
187 hyperlink_to_uuid(zShortCkin);
188 @ %h(zCom) (user:
189 hyperlink_to_user(zUser, zDate, "");
190 @ branch: %h(zBr))
191 if( g.okHistory && zUuid ){
192 const char *z = zFilename;
193 if( fpid ){
194 @ <a href="%s(g.zTop)/fdiff?v1=%s(zPUuid)&amp;v2=%s(zUuid)">[diff]</a>
195 }
196 @ <a href="%s(g.zTop)/annotate?checkin=%S(zCkin)&amp;filename=%h(z)">
197 @ [annotate]</a>
198 }
199 @ </td></tr>
200 }
201 db_finalize(&q);
202 if( pGraph ){
203 graph_finish(pGraph, 1);
204 if( pGraph->nErr ){
205 graph_free(pGraph);
206 pGraph = 0;
207 }else{
208 @ <tr><td></td><td><div style="width:%d(pGraph->mxRail*20+30)px;"></div>
209 @ </td></tr>
210 }
211 }
212 @ </table>
213 timeline_output_graph_javascript(pGraph);
214 style_footer();
215 }
216
+35 -33
--- src/info.c
+++ src/info.c
@@ -194,15 +194,15 @@
194194
@ <div class="section">Tags And Properties</div>
195195
@ <ul>
196196
}
197197
@ <li>
198198
if( tagtype==0 ){
199
- @ <b><s>%h(zTagname)</s></b> cancelled
199
+ @ <span class="infoTagCancelled">%h(zTagname)</span> cancelled
200200
}else if( zValue ){
201
- @ <b>%h(zTagname)=%h(zValue)</b>
201
+ @ <span class="infoTag">%h(zTagname)=%h(zValue)</span>
202202
}else {
203
- @ <b>%h(zTagname)</b>
203
+ @ <span class="infoTag">%h(zTagname)</span>
204204
}
205205
if( tagtype==2 ){
206206
if( zOrigUuid && zOrigUuid[0] ){
207207
@ inherited from
208208
hyperlink_to_uuid(zOrigUuid);
@@ -222,10 +222,11 @@
222222
}
223223
hyperlink_to_uuid(zSrcUuid);
224224
@ on
225225
hyperlink_to_date(zDate,0);
226226
}
227
+ @ </li>
227228
}
228229
db_finalize(&q);
229230
if( cnt ){
230231
@ </ul>
231232
}
@@ -276,18 +277,19 @@
276277
@ <p>Modified <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
277278
@ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
278279
@ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a>
279280
if( !showDiff ){
280281
@ &nbsp;&nbsp;
281
- @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)">[diff]</a>
282
+ @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&amp;v2=%S(zNew)">[diff]</a>
282283
}else{
283284
int rid1 = uuid_to_rid(zOld, 0);
284285
int rid2 = uuid_to_rid(zNew, 0);
285286
@ <blockquote><pre>
286287
append_diff(rid1, rid2);
287288
@ </pre></blockquote>
288289
}
290
+ @ </p>
289291
}else if( zOld ){
290292
@ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
291293
@ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a></p>
292294
}else{
293295
@ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
@@ -354,11 +356,11 @@
354356
TAG_COMMENT, rid);
355357
zUser = db_column_text(&q, 2);
356358
zComment = db_column_text(&q, 3);
357359
zDate = db_column_text(&q,1);
358360
@ <div class="section">Overview</div>
359
- @ <p><table class="label-value">
361
+ @ <table class="label-value">
360362
@ <tr><th>SHA1&nbsp;Hash:</th><td>%s(zUuid)
361363
if( g.okSetup ){
362364
@ (Record ID: %d(rid))
363365
}
364366
@ </td></tr>
@@ -397,13 +399,13 @@
397399
db_finalize(&q);
398400
}
399401
if( g.okHistory ){
400402
const char *zProjName = db_get("project-name", "unnamed");
401403
@ <tr><th>Timelines:</th><td>
402
- @ <a href="%s(g.zBaseURL)/timeline?p=%S(zUuid)">ancestors</a>
403
- @ | <a href="%s(g.zBaseURL)/timeline?d=%S(zUuid)">descendants</a>
404
- @ | <a href="%s(g.zBaseURL)/timeline?d=%S(zUuid)&p=%S(zUuid)">both</a>
404
+ @ <a href="%s(g.zBaseURL)/timeline?p=%S(zUuid)">ancestors</a>
405
+ @ | <a href="%s(g.zBaseURL)/timeline?d=%S(zUuid)">descendants</a>
406
+ @ | <a href="%s(g.zBaseURL)/timeline?d=%S(zUuid)&amp;p=%S(zUuid)">both</a>
405407
db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag "
406408
" WHERE rid=%d AND tagtype>0 "
407409
" AND tag.tagid=tagxref.tagid "
408410
" AND +tag.tagname GLOB 'sym-*'", rid);
409411
while( db_step(&q)==SQLITE_ROW ){
@@ -424,11 +426,11 @@
424426
@ | <a href="%s(g.zTop)/ci_edit?r=%S(zUuid)">edit</a>
425427
}
426428
@ </td>
427429
@ </tr>
428430
}
429
- @ </table></p>
431
+ @ </table>
430432
}else{
431433
style_header("Check-in Information");
432434
login_anonymous_available();
433435
}
434436
db_finalize(&q);
@@ -616,11 +618,11 @@
616618
}
617619
618620
619621
/*
620622
** WEBPAGE: vdiff
621
-** URL: /vdiff?from=UUID&to=UUID&detail=BOOLEAN
623
+** URL: /vdiff?from=UUID&amp;to=UUID&amp;detail=BOOLEAN
622624
**
623625
** Show all differences between two checkins.
624626
*/
625627
void vdiff_page(void){
626628
int ridFrom, ridTo;
@@ -638,11 +640,11 @@
638640
style_header("Check-in Differences");
639641
@ <h2>Difference From:</h2><blockquote>
640642
checkin_description(ridFrom);
641643
@ </blockquote><h2>To:</h2><blockquote>
642644
checkin_description(ridTo);
643
- @ </blockquote><hr><p>
645
+ @ </blockquote><hr /><p>
644646
645647
iFrom = iTo = 0;
646648
while( iFrom<mFrom.nFile && iTo<mTo.nFile ){
647649
int cmp;
648650
if( iFrom>=mFrom.nFile ){
@@ -880,18 +882,18 @@
880882
v1 = name_to_rid_www("v1");
881883
v2 = name_to_rid_www("v2");
882884
if( v1==0 || v2==0 ) fossil_redirect_home();
883885
style_header("Diff");
884886
@ <h2>Differences From:</h2>
885
- @ <blockquote>
887
+ @ <blockquote><p>
886888
object_description(v1, 1, 0);
887
- @ </blockquote>
889
+ @ </p></blockquote>
888890
@ <h2>To:</h2>
889
- @ <blockquote>
891
+ @ <blockquote><p>
890892
object_description(v2, 1, 0);
891
- @ </blockquote>
892
- @ <hr>
893
+ @ </p></blockquote>
894
+ @ <hr />
893895
@ <blockquote><pre>
894896
content_get(v1, &c1);
895897
content_get(v2, &c2);
896898
blob_zero(&diff);
897899
text_diff(&c1, &c2, &diff, 4, 1);
@@ -994,27 +996,27 @@
994996
if( !g.okRead ){ login_needed(); return; }
995997
if( rid==0 ) fossil_redirect_home();
996998
if( g.okAdmin ){
997999
const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
9981000
if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
999
- style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1",
1001
+ style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
10001002
g.zTop, zUuid);
10011003
}else{
10021004
style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
10031005
g.zTop, zUuid);
10041006
}
10051007
}
10061008
style_header("Hex Artifact Content");
10071009
zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid);
10081010
@ <h2>Artifact %s(zUuid):</h2>
1009
- @ <blockquote>
1011
+ @ <blockquote><p>
10101012
blob_zero(&downloadName);
10111013
object_description(rid, 0, &downloadName);
10121014
style_submenu_element("Download", "Download",
10131015
"%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid);
1014
- @ </blockquote>
1015
- @ <hr>
1016
+ @ </p></blockquote>
1017
+ @ <hr />
10161018
content_get(rid, &content);
10171019
@ <blockquote><pre>
10181020
hexdump(&content);
10191021
@ </pre></blockquote>
10201022
style_footer();
@@ -1076,21 +1078,21 @@
10761078
if( !g.okRead ){ login_needed(); return; }
10771079
if( rid==0 ) fossil_redirect_home();
10781080
if( g.okAdmin ){
10791081
const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
10801082
if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1081
- style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1",
1083
+ style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
10821084
g.zTop, zUuid);
10831085
}else{
10841086
style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
10851087
g.zTop, zUuid);
10861088
}
10871089
}
10881090
style_header("Artifact Content");
10891091
zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
10901092
@ <h2>Artifact %s(zUuid)</h2>
1091
- @ <blockquote>
1093
+ @ <blockquote><p>
10921094
blob_zero(&downloadName);
10931095
object_description(rid, 0, &downloadName);
10941096
style_submenu_element("Download", "Download",
10951097
"%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid);
10961098
zMime = mimetype_from_name(blob_str(&downloadName));
@@ -1100,25 +1102,25 @@
11001102
style_submenu_element("Html", "Html",
11011103
"%s/artifact?name=%s", g.zTop, zUuid);
11021104
}else{
11031105
renderAsHtml = 1;
11041106
style_submenu_element("Text", "Text",
1105
- "%s/artifact?name=%s&txt=1", g.zTop, zUuid);
1107
+ "%s/artifact?name=%s&amp;txt=1", g.zTop, zUuid);
11061108
}
11071109
}else if( strcmp(zMime, "application/x-fossil-wiki")==0 ){
11081110
if( P("txt") ){
11091111
style_submenu_element("Wiki", "Wiki",
11101112
"%s/artifact?name=%s", g.zTop, zUuid);
11111113
}else{
11121114
renderAsWiki = 1;
11131115
style_submenu_element("Text", "Text",
1114
- "%s/artifact?name=%s&txt=1", g.zTop, zUuid);
1116
+ "%s/artifact?name=%s&amp;txt=1", g.zTop, zUuid);
11151117
}
11161118
}
11171119
}
1118
- @ </blockquote>
1119
- @ <hr>
1120
+ @ </p></blockquote>
1121
+ @ <hr />
11201122
content_get(rid, &content);
11211123
if( renderAsWiki ){
11221124
wiki_convert(&content, 0, 0);
11231125
}else if( renderAsHtml ){
11241126
@ <div>
@@ -1131,11 +1133,11 @@
11311133
@ <pre>
11321134
@ %h(blob_str(&content))
11331135
@ </pre>
11341136
style_submenu_element("Hex","Hex", "%s/hexdump?name=%s", g.zTop, zUuid);
11351137
}else if( strncmp(zMime, "image/", 6)==0 ){
1136
- @ <img src="%s(g.zBaseURL)/raw?name=%s(zUuid)&m=%s(zMime)"></img>
1138
+ @ <img src="%s(g.zBaseURL)/raw?name=%s(zUuid)&amp;m=%s(zMime)"></img>
11371139
style_submenu_element("Hex","Hex", "%s/hexdump?name=%s", g.zTop, zUuid);
11381140
}else{
11391141
@ <pre>
11401142
hexdump(&content);
11411143
@ </pre>
@@ -1164,11 +1166,11 @@
11641166
rid = name_to_rid_www("name");
11651167
if( rid==0 ){ fossil_redirect_home(); }
11661168
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
11671169
if( g.okAdmin ){
11681170
if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1169
- style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1",
1171
+ style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
11701172
g.zTop, zUuid);
11711173
}else{
11721174
style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
11731175
g.zTop, zUuid);
11741176
}
@@ -1442,11 +1444,11 @@
14421444
int nTag = 0;
14431445
@ <b>Preview:</b>
14441446
@ <blockquote>
14451447
@ <table border=0>
14461448
if( zNewColor && zNewColor[0] ){
1447
- @ <tr><td bgcolor="%h(zNewColor)">
1449
+ @ <tr><td style="background-color: %h(zNewColor);">
14481450
}else{
14491451
@ <tr><td>
14501452
}
14511453
wiki_convert(&comment, 0, WIKI_INLINE);
14521454
blob_zero(&suffix);
@@ -1467,11 +1469,11 @@
14671469
db_finalize(&q);
14681470
blob_appendf(&suffix, ")");
14691471
@ %s(blob_str(&suffix))
14701472
@ </td></tr></table>
14711473
@ </blockquote>
1472
- @ <hr>
1474
+ @ <hr />
14731475
blob_reset(&suffix);
14741476
}
14751477
@ <p>Make changes to attributes of check-in
14761478
@ [<a href="ci?name=%s(zUuid)">%s(zUuid)</a>]:</p>
14771479
@ <form action="%s(g.zBaseURL)/ci_edit" method="POST">
@@ -1505,11 +1507,11 @@
15051507
}
15061508
@ Propagate color to descendants</input></td></tr>
15071509
@ <tr>
15081510
for(i=0; i<nColor; i++){
15091511
if( aColor[i].zColor[0] ){
1510
- @ <td bgcolor="%h(aColor[i].zColor)">
1512
+ @ <td style="background-color: %h(aColor[i].zColor);">
15111513
}else{
15121514
@ <td>
15131515
}
15141516
if( strcmp(zNewColor, aColor[i].zColor)==0 ){
15151517
@ <input type="radio" name="clr" value="%h(aColor[i].zColor)" checked>
@@ -1541,13 +1543,13 @@
15411543
int tagid = db_column_int(&q, 0);
15421544
const char *zTagName = db_column_text(&q, 1);
15431545
char zLabel[30];
15441546
sprintf(zLabel, "c%d", tagid);
15451547
if( P(zLabel) ){
1546
- @ <br><input type="checkbox" name="c%d(tagid)" checked>
1548
+ @ <br /><input type="checkbox" name="c%d(tagid)" checked>
15471549
}else{
1548
- @ <br><input type="checkbox" name="c%d(tagid)">
1550
+ @ <br /><input type="checkbox" name="c%d(tagid)">
15491551
}
15501552
if( strncmp(zTagName, "sym-", 4)==0 ){
15511553
@ Cancel tag <b>%h(&zTagName[4])</b>
15521554
}else{
15531555
@ Cancel special tag <b>%h(zTagName)</b>
15541556
--- src/info.c
+++ src/info.c
@@ -194,15 +194,15 @@
194 @ <div class="section">Tags And Properties</div>
195 @ <ul>
196 }
197 @ <li>
198 if( tagtype==0 ){
199 @ <b><s>%h(zTagname)</s></b> cancelled
200 }else if( zValue ){
201 @ <b>%h(zTagname)=%h(zValue)</b>
202 }else {
203 @ <b>%h(zTagname)</b>
204 }
205 if( tagtype==2 ){
206 if( zOrigUuid && zOrigUuid[0] ){
207 @ inherited from
208 hyperlink_to_uuid(zOrigUuid);
@@ -222,10 +222,11 @@
222 }
223 hyperlink_to_uuid(zSrcUuid);
224 @ on
225 hyperlink_to_date(zDate,0);
226 }
 
227 }
228 db_finalize(&q);
229 if( cnt ){
230 @ </ul>
231 }
@@ -276,18 +277,19 @@
276 @ <p>Modified <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
277 @ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
278 @ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a>
279 if( !showDiff ){
280 @ &nbsp;&nbsp;
281 @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)">[diff]</a>
282 }else{
283 int rid1 = uuid_to_rid(zOld, 0);
284 int rid2 = uuid_to_rid(zNew, 0);
285 @ <blockquote><pre>
286 append_diff(rid1, rid2);
287 @ </pre></blockquote>
288 }
 
289 }else if( zOld ){
290 @ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
291 @ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a></p>
292 }else{
293 @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
@@ -354,11 +356,11 @@
354 TAG_COMMENT, rid);
355 zUser = db_column_text(&q, 2);
356 zComment = db_column_text(&q, 3);
357 zDate = db_column_text(&q,1);
358 @ <div class="section">Overview</div>
359 @ <p><table class="label-value">
360 @ <tr><th>SHA1&nbsp;Hash:</th><td>%s(zUuid)
361 if( g.okSetup ){
362 @ (Record ID: %d(rid))
363 }
364 @ </td></tr>
@@ -397,13 +399,13 @@
397 db_finalize(&q);
398 }
399 if( g.okHistory ){
400 const char *zProjName = db_get("project-name", "unnamed");
401 @ <tr><th>Timelines:</th><td>
402 @ <a href="%s(g.zBaseURL)/timeline?p=%S(zUuid)">ancestors</a>
403 @ | <a href="%s(g.zBaseURL)/timeline?d=%S(zUuid)">descendants</a>
404 @ | <a href="%s(g.zBaseURL)/timeline?d=%S(zUuid)&p=%S(zUuid)">both</a>
405 db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag "
406 " WHERE rid=%d AND tagtype>0 "
407 " AND tag.tagid=tagxref.tagid "
408 " AND +tag.tagname GLOB 'sym-*'", rid);
409 while( db_step(&q)==SQLITE_ROW ){
@@ -424,11 +426,11 @@
424 @ | <a href="%s(g.zTop)/ci_edit?r=%S(zUuid)">edit</a>
425 }
426 @ </td>
427 @ </tr>
428 }
429 @ </table></p>
430 }else{
431 style_header("Check-in Information");
432 login_anonymous_available();
433 }
434 db_finalize(&q);
@@ -616,11 +618,11 @@
616 }
617
618
619 /*
620 ** WEBPAGE: vdiff
621 ** URL: /vdiff?from=UUID&to=UUID&detail=BOOLEAN
622 **
623 ** Show all differences between two checkins.
624 */
625 void vdiff_page(void){
626 int ridFrom, ridTo;
@@ -638,11 +640,11 @@
638 style_header("Check-in Differences");
639 @ <h2>Difference From:</h2><blockquote>
640 checkin_description(ridFrom);
641 @ </blockquote><h2>To:</h2><blockquote>
642 checkin_description(ridTo);
643 @ </blockquote><hr><p>
644
645 iFrom = iTo = 0;
646 while( iFrom<mFrom.nFile && iTo<mTo.nFile ){
647 int cmp;
648 if( iFrom>=mFrom.nFile ){
@@ -880,18 +882,18 @@
880 v1 = name_to_rid_www("v1");
881 v2 = name_to_rid_www("v2");
882 if( v1==0 || v2==0 ) fossil_redirect_home();
883 style_header("Diff");
884 @ <h2>Differences From:</h2>
885 @ <blockquote>
886 object_description(v1, 1, 0);
887 @ </blockquote>
888 @ <h2>To:</h2>
889 @ <blockquote>
890 object_description(v2, 1, 0);
891 @ </blockquote>
892 @ <hr>
893 @ <blockquote><pre>
894 content_get(v1, &c1);
895 content_get(v2, &c2);
896 blob_zero(&diff);
897 text_diff(&c1, &c2, &diff, 4, 1);
@@ -994,27 +996,27 @@
994 if( !g.okRead ){ login_needed(); return; }
995 if( rid==0 ) fossil_redirect_home();
996 if( g.okAdmin ){
997 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
998 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
999 style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1",
1000 g.zTop, zUuid);
1001 }else{
1002 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
1003 g.zTop, zUuid);
1004 }
1005 }
1006 style_header("Hex Artifact Content");
1007 zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid);
1008 @ <h2>Artifact %s(zUuid):</h2>
1009 @ <blockquote>
1010 blob_zero(&downloadName);
1011 object_description(rid, 0, &downloadName);
1012 style_submenu_element("Download", "Download",
1013 "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid);
1014 @ </blockquote>
1015 @ <hr>
1016 content_get(rid, &content);
1017 @ <blockquote><pre>
1018 hexdump(&content);
1019 @ </pre></blockquote>
1020 style_footer();
@@ -1076,21 +1078,21 @@
1076 if( !g.okRead ){ login_needed(); return; }
1077 if( rid==0 ) fossil_redirect_home();
1078 if( g.okAdmin ){
1079 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1080 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1081 style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1",
1082 g.zTop, zUuid);
1083 }else{
1084 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
1085 g.zTop, zUuid);
1086 }
1087 }
1088 style_header("Artifact Content");
1089 zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
1090 @ <h2>Artifact %s(zUuid)</h2>
1091 @ <blockquote>
1092 blob_zero(&downloadName);
1093 object_description(rid, 0, &downloadName);
1094 style_submenu_element("Download", "Download",
1095 "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid);
1096 zMime = mimetype_from_name(blob_str(&downloadName));
@@ -1100,25 +1102,25 @@
1100 style_submenu_element("Html", "Html",
1101 "%s/artifact?name=%s", g.zTop, zUuid);
1102 }else{
1103 renderAsHtml = 1;
1104 style_submenu_element("Text", "Text",
1105 "%s/artifact?name=%s&txt=1", g.zTop, zUuid);
1106 }
1107 }else if( strcmp(zMime, "application/x-fossil-wiki")==0 ){
1108 if( P("txt") ){
1109 style_submenu_element("Wiki", "Wiki",
1110 "%s/artifact?name=%s", g.zTop, zUuid);
1111 }else{
1112 renderAsWiki = 1;
1113 style_submenu_element("Text", "Text",
1114 "%s/artifact?name=%s&txt=1", g.zTop, zUuid);
1115 }
1116 }
1117 }
1118 @ </blockquote>
1119 @ <hr>
1120 content_get(rid, &content);
1121 if( renderAsWiki ){
1122 wiki_convert(&content, 0, 0);
1123 }else if( renderAsHtml ){
1124 @ <div>
@@ -1131,11 +1133,11 @@
1131 @ <pre>
1132 @ %h(blob_str(&content))
1133 @ </pre>
1134 style_submenu_element("Hex","Hex", "%s/hexdump?name=%s", g.zTop, zUuid);
1135 }else if( strncmp(zMime, "image/", 6)==0 ){
1136 @ <img src="%s(g.zBaseURL)/raw?name=%s(zUuid)&m=%s(zMime)"></img>
1137 style_submenu_element("Hex","Hex", "%s/hexdump?name=%s", g.zTop, zUuid);
1138 }else{
1139 @ <pre>
1140 hexdump(&content);
1141 @ </pre>
@@ -1164,11 +1166,11 @@
1164 rid = name_to_rid_www("name");
1165 if( rid==0 ){ fossil_redirect_home(); }
1166 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1167 if( g.okAdmin ){
1168 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1169 style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1",
1170 g.zTop, zUuid);
1171 }else{
1172 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
1173 g.zTop, zUuid);
1174 }
@@ -1442,11 +1444,11 @@
1442 int nTag = 0;
1443 @ <b>Preview:</b>
1444 @ <blockquote>
1445 @ <table border=0>
1446 if( zNewColor && zNewColor[0] ){
1447 @ <tr><td bgcolor="%h(zNewColor)">
1448 }else{
1449 @ <tr><td>
1450 }
1451 wiki_convert(&comment, 0, WIKI_INLINE);
1452 blob_zero(&suffix);
@@ -1467,11 +1469,11 @@
1467 db_finalize(&q);
1468 blob_appendf(&suffix, ")");
1469 @ %s(blob_str(&suffix))
1470 @ </td></tr></table>
1471 @ </blockquote>
1472 @ <hr>
1473 blob_reset(&suffix);
1474 }
1475 @ <p>Make changes to attributes of check-in
1476 @ [<a href="ci?name=%s(zUuid)">%s(zUuid)</a>]:</p>
1477 @ <form action="%s(g.zBaseURL)/ci_edit" method="POST">
@@ -1505,11 +1507,11 @@
1505 }
1506 @ Propagate color to descendants</input></td></tr>
1507 @ <tr>
1508 for(i=0; i<nColor; i++){
1509 if( aColor[i].zColor[0] ){
1510 @ <td bgcolor="%h(aColor[i].zColor)">
1511 }else{
1512 @ <td>
1513 }
1514 if( strcmp(zNewColor, aColor[i].zColor)==0 ){
1515 @ <input type="radio" name="clr" value="%h(aColor[i].zColor)" checked>
@@ -1541,13 +1543,13 @@
1541 int tagid = db_column_int(&q, 0);
1542 const char *zTagName = db_column_text(&q, 1);
1543 char zLabel[30];
1544 sprintf(zLabel, "c%d", tagid);
1545 if( P(zLabel) ){
1546 @ <br><input type="checkbox" name="c%d(tagid)" checked>
1547 }else{
1548 @ <br><input type="checkbox" name="c%d(tagid)">
1549 }
1550 if( strncmp(zTagName, "sym-", 4)==0 ){
1551 @ Cancel tag <b>%h(&zTagName[4])</b>
1552 }else{
1553 @ Cancel special tag <b>%h(zTagName)</b>
1554
--- src/info.c
+++ src/info.c
@@ -194,15 +194,15 @@
194 @ <div class="section">Tags And Properties</div>
195 @ <ul>
196 }
197 @ <li>
198 if( tagtype==0 ){
199 @ <span class="infoTagCancelled">%h(zTagname)</span> cancelled
200 }else if( zValue ){
201 @ <span class="infoTag">%h(zTagname)=%h(zValue)</span>
202 }else {
203 @ <span class="infoTag">%h(zTagname)</span>
204 }
205 if( tagtype==2 ){
206 if( zOrigUuid && zOrigUuid[0] ){
207 @ inherited from
208 hyperlink_to_uuid(zOrigUuid);
@@ -222,10 +222,11 @@
222 }
223 hyperlink_to_uuid(zSrcUuid);
224 @ on
225 hyperlink_to_date(zDate,0);
226 }
227 @ </li>
228 }
229 db_finalize(&q);
230 if( cnt ){
231 @ </ul>
232 }
@@ -276,18 +277,19 @@
277 @ <p>Modified <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
278 @ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a>
279 @ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a>
280 if( !showDiff ){
281 @ &nbsp;&nbsp;
282 @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&amp;v2=%S(zNew)">[diff]</a>
283 }else{
284 int rid1 = uuid_to_rid(zOld, 0);
285 int rid2 = uuid_to_rid(zNew, 0);
286 @ <blockquote><pre>
287 append_diff(rid1, rid2);
288 @ </pre></blockquote>
289 }
290 @ </p>
291 }else if( zOld ){
292 @ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
293 @ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a></p>
294 }else{
295 @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>
@@ -354,11 +356,11 @@
356 TAG_COMMENT, rid);
357 zUser = db_column_text(&q, 2);
358 zComment = db_column_text(&q, 3);
359 zDate = db_column_text(&q,1);
360 @ <div class="section">Overview</div>
361 @ <table class="label-value">
362 @ <tr><th>SHA1&nbsp;Hash:</th><td>%s(zUuid)
363 if( g.okSetup ){
364 @ (Record ID: %d(rid))
365 }
366 @ </td></tr>
@@ -397,13 +399,13 @@
399 db_finalize(&q);
400 }
401 if( g.okHistory ){
402 const char *zProjName = db_get("project-name", "unnamed");
403 @ <tr><th>Timelines:</th><td>
404 @ <a href="%s(g.zBaseURL)/timeline?p=%S(zUuid)">ancestors</a>
405 @ | <a href="%s(g.zBaseURL)/timeline?d=%S(zUuid)">descendants</a>
406 @ | <a href="%s(g.zBaseURL)/timeline?d=%S(zUuid)&amp;p=%S(zUuid)">both</a>
407 db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag "
408 " WHERE rid=%d AND tagtype>0 "
409 " AND tag.tagid=tagxref.tagid "
410 " AND +tag.tagname GLOB 'sym-*'", rid);
411 while( db_step(&q)==SQLITE_ROW ){
@@ -424,11 +426,11 @@
426 @ | <a href="%s(g.zTop)/ci_edit?r=%S(zUuid)">edit</a>
427 }
428 @ </td>
429 @ </tr>
430 }
431 @ </table>
432 }else{
433 style_header("Check-in Information");
434 login_anonymous_available();
435 }
436 db_finalize(&q);
@@ -616,11 +618,11 @@
618 }
619
620
621 /*
622 ** WEBPAGE: vdiff
623 ** URL: /vdiff?from=UUID&amp;to=UUID&amp;detail=BOOLEAN
624 **
625 ** Show all differences between two checkins.
626 */
627 void vdiff_page(void){
628 int ridFrom, ridTo;
@@ -638,11 +640,11 @@
640 style_header("Check-in Differences");
641 @ <h2>Difference From:</h2><blockquote>
642 checkin_description(ridFrom);
643 @ </blockquote><h2>To:</h2><blockquote>
644 checkin_description(ridTo);
645 @ </blockquote><hr /><p>
646
647 iFrom = iTo = 0;
648 while( iFrom<mFrom.nFile && iTo<mTo.nFile ){
649 int cmp;
650 if( iFrom>=mFrom.nFile ){
@@ -880,18 +882,18 @@
882 v1 = name_to_rid_www("v1");
883 v2 = name_to_rid_www("v2");
884 if( v1==0 || v2==0 ) fossil_redirect_home();
885 style_header("Diff");
886 @ <h2>Differences From:</h2>
887 @ <blockquote><p>
888 object_description(v1, 1, 0);
889 @ </p></blockquote>
890 @ <h2>To:</h2>
891 @ <blockquote><p>
892 object_description(v2, 1, 0);
893 @ </p></blockquote>
894 @ <hr />
895 @ <blockquote><pre>
896 content_get(v1, &c1);
897 content_get(v2, &c2);
898 blob_zero(&diff);
899 text_diff(&c1, &c2, &diff, 4, 1);
@@ -994,27 +996,27 @@
996 if( !g.okRead ){ login_needed(); return; }
997 if( rid==0 ) fossil_redirect_home();
998 if( g.okAdmin ){
999 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1000 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1001 style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
1002 g.zTop, zUuid);
1003 }else{
1004 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
1005 g.zTop, zUuid);
1006 }
1007 }
1008 style_header("Hex Artifact Content");
1009 zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid);
1010 @ <h2>Artifact %s(zUuid):</h2>
1011 @ <blockquote><p>
1012 blob_zero(&downloadName);
1013 object_description(rid, 0, &downloadName);
1014 style_submenu_element("Download", "Download",
1015 "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid);
1016 @ </p></blockquote>
1017 @ <hr />
1018 content_get(rid, &content);
1019 @ <blockquote><pre>
1020 hexdump(&content);
1021 @ </pre></blockquote>
1022 style_footer();
@@ -1076,21 +1078,21 @@
1078 if( !g.okRead ){ login_needed(); return; }
1079 if( rid==0 ) fossil_redirect_home();
1080 if( g.okAdmin ){
1081 const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1082 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1083 style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
1084 g.zTop, zUuid);
1085 }else{
1086 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
1087 g.zTop, zUuid);
1088 }
1089 }
1090 style_header("Artifact Content");
1091 zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid);
1092 @ <h2>Artifact %s(zUuid)</h2>
1093 @ <blockquote><p>
1094 blob_zero(&downloadName);
1095 object_description(rid, 0, &downloadName);
1096 style_submenu_element("Download", "Download",
1097 "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid);
1098 zMime = mimetype_from_name(blob_str(&downloadName));
@@ -1100,25 +1102,25 @@
1102 style_submenu_element("Html", "Html",
1103 "%s/artifact?name=%s", g.zTop, zUuid);
1104 }else{
1105 renderAsHtml = 1;
1106 style_submenu_element("Text", "Text",
1107 "%s/artifact?name=%s&amp;txt=1", g.zTop, zUuid);
1108 }
1109 }else if( strcmp(zMime, "application/x-fossil-wiki")==0 ){
1110 if( P("txt") ){
1111 style_submenu_element("Wiki", "Wiki",
1112 "%s/artifact?name=%s", g.zTop, zUuid);
1113 }else{
1114 renderAsWiki = 1;
1115 style_submenu_element("Text", "Text",
1116 "%s/artifact?name=%s&amp;txt=1", g.zTop, zUuid);
1117 }
1118 }
1119 }
1120 @ </p></blockquote>
1121 @ <hr />
1122 content_get(rid, &content);
1123 if( renderAsWiki ){
1124 wiki_convert(&content, 0, 0);
1125 }else if( renderAsHtml ){
1126 @ <div>
@@ -1131,11 +1133,11 @@
1133 @ <pre>
1134 @ %h(blob_str(&content))
1135 @ </pre>
1136 style_submenu_element("Hex","Hex", "%s/hexdump?name=%s", g.zTop, zUuid);
1137 }else if( strncmp(zMime, "image/", 6)==0 ){
1138 @ <img src="%s(g.zBaseURL)/raw?name=%s(zUuid)&amp;m=%s(zMime)"></img>
1139 style_submenu_element("Hex","Hex", "%s/hexdump?name=%s", g.zTop, zUuid);
1140 }else{
1141 @ <pre>
1142 hexdump(&content);
1143 @ </pre>
@@ -1164,11 +1166,11 @@
1166 rid = name_to_rid_www("name");
1167 if( rid==0 ){ fossil_redirect_home(); }
1168 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
1169 if( g.okAdmin ){
1170 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){
1171 style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&amp;sub=1",
1172 g.zTop, zUuid);
1173 }else{
1174 style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun",
1175 g.zTop, zUuid);
1176 }
@@ -1442,11 +1444,11 @@
1444 int nTag = 0;
1445 @ <b>Preview:</b>
1446 @ <blockquote>
1447 @ <table border=0>
1448 if( zNewColor && zNewColor[0] ){
1449 @ <tr><td style="background-color: %h(zNewColor);">
1450 }else{
1451 @ <tr><td>
1452 }
1453 wiki_convert(&comment, 0, WIKI_INLINE);
1454 blob_zero(&suffix);
@@ -1467,11 +1469,11 @@
1469 db_finalize(&q);
1470 blob_appendf(&suffix, ")");
1471 @ %s(blob_str(&suffix))
1472 @ </td></tr></table>
1473 @ </blockquote>
1474 @ <hr />
1475 blob_reset(&suffix);
1476 }
1477 @ <p>Make changes to attributes of check-in
1478 @ [<a href="ci?name=%s(zUuid)">%s(zUuid)</a>]:</p>
1479 @ <form action="%s(g.zBaseURL)/ci_edit" method="POST">
@@ -1505,11 +1507,11 @@
1507 }
1508 @ Propagate color to descendants</input></td></tr>
1509 @ <tr>
1510 for(i=0; i<nColor; i++){
1511 if( aColor[i].zColor[0] ){
1512 @ <td style="background-color: %h(aColor[i].zColor);">
1513 }else{
1514 @ <td>
1515 }
1516 if( strcmp(zNewColor, aColor[i].zColor)==0 ){
1517 @ <input type="radio" name="clr" value="%h(aColor[i].zColor)" checked>
@@ -1541,13 +1543,13 @@
1543 int tagid = db_column_int(&q, 0);
1544 const char *zTagName = db_column_text(&q, 1);
1545 char zLabel[30];
1546 sprintf(zLabel, "c%d", tagid);
1547 if( P(zLabel) ){
1548 @ <br /><input type="checkbox" name="c%d(tagid)" checked>
1549 }else{
1550 @ <br /><input type="checkbox" name="c%d(tagid)">
1551 }
1552 if( strncmp(zTagName, "sym-", 4)==0 ){
1553 @ Cancel tag <b>%h(&zTagName[4])</b>
1554 }else{
1555 @ Cancel special tag <b>%h(zTagName)</b>
1556
+36 -36
--- src/login.c
+++ src/login.c
@@ -153,21 +153,21 @@
153153
if( db_int(1, "SELECT 0 FROM user"
154154
" WHERE uid=%d AND (pw=%Q OR pw=%Q)",
155155
g.userUid, zPasswd, zSha1Pw) ){
156156
sleep(1);
157157
zErrMsg =
158
- @ <p><font color="red">
158
+ @ <p><span class="loginError">
159159
@ You entered an incorrect old password while attempting to change
160160
@ your password. Your password is unchanged.
161
- @ </font></p>
161
+ @ </span></p>
162162
;
163163
}else if( strcmp(zNew1,zNew2)!=0 ){
164164
zErrMsg =
165
- @ <p><font color="red">
165
+ @ <p><span class="loginError">
166166
@ The two copies of your new passwords do not match.
167167
@ Your password is unchanged.
168
- @ </font></p>
168
+ @ </span></p>
169169
;
170170
}else{
171171
char *zNewPw = sha1_shared_secret(zNew1, g.zLogin);
172172
db_multi_exec(
173173
"UPDATE user SET pw=%Q WHERE uid=%d", zNewPw, g.userUid
@@ -206,13 +206,13 @@
206206
zUsername, zPasswd, zSha1Pw
207207
);
208208
if( uid<=0 ){
209209
sleep(1);
210210
zErrMsg =
211
- @ <p><font color="red">
211
+ @ <p><span class="loginError">
212212
@ You entered an unknown user or an incorrect password.
213
- @ </font></p>
213
+ @ </span></p>
214214
;
215215
}else{
216216
char *zCookie;
217217
const char *zCookieName = login_cookie_name();
218218
const char *zExpire = db_get("cookie-expire","8766");
@@ -229,38 +229,38 @@
229229
redirect_to_g();
230230
}
231231
}
232232
style_header("Login/Logout");
233233
@ %s(zErrMsg)
234
- @ <form action="login" method="POST">
234
+ @ <form action="login" method="post">
235235
if( P("g") ){
236
- @ <input type="hidden" name="g" value="%h(P("g"))">
236
+ @ <input type="hidden" name="g" value="%h(P("g"))" />
237237
}
238
- @ <table align="left" hspace="10">
238
+ @ <table class="login_out">
239239
@ <tr>
240
- @ <td align="right">User ID:</td>
240
+ @ <td class="login_out_label">User ID:</td>
241241
if( anonFlag ){
242
- @ <td><input type="text" id="u" name="u" value="anonymous" size=30></td>
242
+ @ <td><input type="text" id="u" name="u" value="anonymous" size="30" /></td>
243243
}else{
244
- @ <td><input type="text" id="u" name="u" value="" size=30></td>
244
+ @ <td><input type="text" id="u" name="u" value="" size="30" /></td>
245245
}
246246
@ </tr>
247247
@ <tr>
248
- @ <td align="right">Password:</td>
249
- @ <td><input type="password" id="p" name="p" value="" size=30></td>
248
+ @ <td class="login_out_label">Password:</td>
249
+ @ <td><input type="password" id="p" name="p" value="" size="30" /></td>
250250
@ </tr>
251251
if( g.zLogin==0 ){
252252
zAnonPw = db_text(0, "SELECT pw FROM user"
253253
" WHERE login='anonymous'"
254254
" AND cap!=''");
255255
}
256256
@ <tr>
257257
@ <td></td>
258
- @ <td><input type="submit" name="in" value="Login"></td>
258
+ @ <td><input type="submit" name="in" value="Login" /></td>
259259
@ </tr>
260260
@ </table>
261
- @ <script>document.getElementById('u').focus()</script>
261
+ @ <script type="text/JavaScript">document.getElementById('u').focus()</script>
262262
if( g.zLogin==0 ){
263263
@ <p>Enter
264264
}else{
265265
@ <p>You are currently logged in as <b>%h(g.zLogin)</b></p>
266266
@ <p>To change your login to a different user, enter
@@ -273,46 +273,46 @@
273273
unsigned int uSeed = captcha_seed();
274274
char const *zDecoded = captcha_decode(uSeed);
275275
int bAutoCaptcha = db_get_boolean("auto-captcha", 1);
276276
char *zCaptcha = captcha_render(zDecoded);
277277
278
- @ <input type="hidden" name="cs" value="%u(uSeed)"/>
279
- @ <p>Visitors may enter <b>anonymous</b> as the user-ID with
278
+ @ <p><input type="hidden" name="cs" value="%u(uSeed)" />
279
+ @ Visitors may enter <b>anonymous</b> as the user-ID with
280280
@ the 8-character hexadecimal password shown below:</p>
281
- @ <center><table border="1" cellpadding="10"><tr><td><pre>
281
+ @ <div class="captcha"><table class="captcha"><tr><td><pre>
282282
@ %s(zCaptcha)
283283
@ </pre></td></tr></table>
284284
if( bAutoCaptcha ) {
285285
@ <input type="button" value="Fill out captcha"
286286
@ onclick="document.getElementById('u').value='anonymous';
287
- @ document.getElementById('p').value='%s(zDecoded)';"/>
287
+ @ document.getElementById('p').value='%s(zDecoded)';" />
288288
}
289
- @ </center>
289
+ @ </div>
290290
free(zCaptcha);
291291
}
292292
if( g.zLogin ){
293
- @ <br clear="both"><hr>
293
+ @ <hr />
294294
@ <p>To log off the system (and delete your login cookie)
295
- @ press the following button:<br>
296
- @ <input type="submit" name="out" value="Logout"></p>
295
+ @ press the following button:<br />
296
+ @ <input type="submit" name="out" value="Logout" /></p>
297297
}
298298
@ </form>
299299
if( g.okPassword ){
300
- @ <br clear="both"><hr>
300
+ @ <hr />
301301
@ <p>To change your password, enter your old password and your
302302
@ new password twice below then press the "Change Password"
303303
@ button.</p>
304
- @ <form action="login" method="POST">
304
+ @ <form action="login" method="post">
305305
@ <table>
306
- @ <tr><td align="right">Old Password:</td>
307
- @ <td><input type="password" name="p" size=30></td></tr>
308
- @ <tr><td align="right">New Password:</td>
309
- @ <td><input type="password" name="n1" size=30></td></tr>
310
- @ <tr><td align="right">Repeat New Password:</td>
311
- @ <td><input type="password" name="n2" size=30></td></tr>
306
+ @ <tr><td class="login_out_label">Old Password:</td>
307
+ @ <td><input type="password" name="p" size="30" /></td></tr>
308
+ @ <tr><td class="login_out_label">New Password:</td>
309
+ @ <td><input type="password" name="n1" size="30" /></td></tr>
310
+ @ <tr><td class="login_out_label">Repeat New Password:</td>
311
+ @ <td><input type="password" name="n2" size="30" /></td></tr>
312312
@ <tr><td></td>
313
- @ <td><input type="submit" value="Change Password"></td></tr>
313
+ @ <td><input type="submit" value="Change Password" /></td></tr>
314314
@ </table>
315315
@ </form>
316316
}
317317
style_footer();
318318
}
@@ -596,22 +596,22 @@
596596
if( !g.okHistory &&
597597
db_exists("SELECT 1 FROM user"
598598
" WHERE login='anonymous'"
599599
" AND cap LIKE '%%h%%'") ){
600600
const char *zUrl = PD("REQUEST_URI", "index");
601
- @ <p>Many <font color="red">hyperlinks are disabled.</font><br />
602
- @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a>
601
+ @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
602
+ @ Use <a href="%s(g.zTop)/login?anon=1&amp;g=%T(zUrl)">anonymous login</a>
603603
@ to enable hyperlinks.</p>
604604
}
605605
}
606606
607607
/*
608608
** While rendering a form, call this routine to add the Anti-CSRF token
609609
** as a hidden element of the form.
610610
*/
611611
void login_insert_csrf_secret(void){
612
- @ <input type="hidden" name="csrf" value="%s(g.zCsrfToken)">
612
+ @ <input type="hidden" name="csrf" value="%s(g.zCsrfToken)" />
613613
}
614614
615615
/*
616616
** Before using the results of a form, first call this routine to verify
617617
** that ths Anti-CSRF token is present and is valid. If the Anti-CSRF token
618618
--- src/login.c
+++ src/login.c
@@ -153,21 +153,21 @@
153 if( db_int(1, "SELECT 0 FROM user"
154 " WHERE uid=%d AND (pw=%Q OR pw=%Q)",
155 g.userUid, zPasswd, zSha1Pw) ){
156 sleep(1);
157 zErrMsg =
158 @ <p><font color="red">
159 @ You entered an incorrect old password while attempting to change
160 @ your password. Your password is unchanged.
161 @ </font></p>
162 ;
163 }else if( strcmp(zNew1,zNew2)!=0 ){
164 zErrMsg =
165 @ <p><font color="red">
166 @ The two copies of your new passwords do not match.
167 @ Your password is unchanged.
168 @ </font></p>
169 ;
170 }else{
171 char *zNewPw = sha1_shared_secret(zNew1, g.zLogin);
172 db_multi_exec(
173 "UPDATE user SET pw=%Q WHERE uid=%d", zNewPw, g.userUid
@@ -206,13 +206,13 @@
206 zUsername, zPasswd, zSha1Pw
207 );
208 if( uid<=0 ){
209 sleep(1);
210 zErrMsg =
211 @ <p><font color="red">
212 @ You entered an unknown user or an incorrect password.
213 @ </font></p>
214 ;
215 }else{
216 char *zCookie;
217 const char *zCookieName = login_cookie_name();
218 const char *zExpire = db_get("cookie-expire","8766");
@@ -229,38 +229,38 @@
229 redirect_to_g();
230 }
231 }
232 style_header("Login/Logout");
233 @ %s(zErrMsg)
234 @ <form action="login" method="POST">
235 if( P("g") ){
236 @ <input type="hidden" name="g" value="%h(P("g"))">
237 }
238 @ <table align="left" hspace="10">
239 @ <tr>
240 @ <td align="right">User ID:</td>
241 if( anonFlag ){
242 @ <td><input type="text" id="u" name="u" value="anonymous" size=30></td>
243 }else{
244 @ <td><input type="text" id="u" name="u" value="" size=30></td>
245 }
246 @ </tr>
247 @ <tr>
248 @ <td align="right">Password:</td>
249 @ <td><input type="password" id="p" name="p" value="" size=30></td>
250 @ </tr>
251 if( g.zLogin==0 ){
252 zAnonPw = db_text(0, "SELECT pw FROM user"
253 " WHERE login='anonymous'"
254 " AND cap!=''");
255 }
256 @ <tr>
257 @ <td></td>
258 @ <td><input type="submit" name="in" value="Login"></td>
259 @ </tr>
260 @ </table>
261 @ <script>document.getElementById('u').focus()</script>
262 if( g.zLogin==0 ){
263 @ <p>Enter
264 }else{
265 @ <p>You are currently logged in as <b>%h(g.zLogin)</b></p>
266 @ <p>To change your login to a different user, enter
@@ -273,46 +273,46 @@
273 unsigned int uSeed = captcha_seed();
274 char const *zDecoded = captcha_decode(uSeed);
275 int bAutoCaptcha = db_get_boolean("auto-captcha", 1);
276 char *zCaptcha = captcha_render(zDecoded);
277
278 @ <input type="hidden" name="cs" value="%u(uSeed)"/>
279 @ <p>Visitors may enter <b>anonymous</b> as the user-ID with
280 @ the 8-character hexadecimal password shown below:</p>
281 @ <center><table border="1" cellpadding="10"><tr><td><pre>
282 @ %s(zCaptcha)
283 @ </pre></td></tr></table>
284 if( bAutoCaptcha ) {
285 @ <input type="button" value="Fill out captcha"
286 @ onclick="document.getElementById('u').value='anonymous';
287 @ document.getElementById('p').value='%s(zDecoded)';"/>
288 }
289 @ </center>
290 free(zCaptcha);
291 }
292 if( g.zLogin ){
293 @ <br clear="both"><hr>
294 @ <p>To log off the system (and delete your login cookie)
295 @ press the following button:<br>
296 @ <input type="submit" name="out" value="Logout"></p>
297 }
298 @ </form>
299 if( g.okPassword ){
300 @ <br clear="both"><hr>
301 @ <p>To change your password, enter your old password and your
302 @ new password twice below then press the "Change Password"
303 @ button.</p>
304 @ <form action="login" method="POST">
305 @ <table>
306 @ <tr><td align="right">Old Password:</td>
307 @ <td><input type="password" name="p" size=30></td></tr>
308 @ <tr><td align="right">New Password:</td>
309 @ <td><input type="password" name="n1" size=30></td></tr>
310 @ <tr><td align="right">Repeat New Password:</td>
311 @ <td><input type="password" name="n2" size=30></td></tr>
312 @ <tr><td></td>
313 @ <td><input type="submit" value="Change Password"></td></tr>
314 @ </table>
315 @ </form>
316 }
317 style_footer();
318 }
@@ -596,22 +596,22 @@
596 if( !g.okHistory &&
597 db_exists("SELECT 1 FROM user"
598 " WHERE login='anonymous'"
599 " AND cap LIKE '%%h%%'") ){
600 const char *zUrl = PD("REQUEST_URI", "index");
601 @ <p>Many <font color="red">hyperlinks are disabled.</font><br />
602 @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a>
603 @ to enable hyperlinks.</p>
604 }
605 }
606
607 /*
608 ** While rendering a form, call this routine to add the Anti-CSRF token
609 ** as a hidden element of the form.
610 */
611 void login_insert_csrf_secret(void){
612 @ <input type="hidden" name="csrf" value="%s(g.zCsrfToken)">
613 }
614
615 /*
616 ** Before using the results of a form, first call this routine to verify
617 ** that ths Anti-CSRF token is present and is valid. If the Anti-CSRF token
618
--- src/login.c
+++ src/login.c
@@ -153,21 +153,21 @@
153 if( db_int(1, "SELECT 0 FROM user"
154 " WHERE uid=%d AND (pw=%Q OR pw=%Q)",
155 g.userUid, zPasswd, zSha1Pw) ){
156 sleep(1);
157 zErrMsg =
158 @ <p><span class="loginError">
159 @ You entered an incorrect old password while attempting to change
160 @ your password. Your password is unchanged.
161 @ </span></p>
162 ;
163 }else if( strcmp(zNew1,zNew2)!=0 ){
164 zErrMsg =
165 @ <p><span class="loginError">
166 @ The two copies of your new passwords do not match.
167 @ Your password is unchanged.
168 @ </span></p>
169 ;
170 }else{
171 char *zNewPw = sha1_shared_secret(zNew1, g.zLogin);
172 db_multi_exec(
173 "UPDATE user SET pw=%Q WHERE uid=%d", zNewPw, g.userUid
@@ -206,13 +206,13 @@
206 zUsername, zPasswd, zSha1Pw
207 );
208 if( uid<=0 ){
209 sleep(1);
210 zErrMsg =
211 @ <p><span class="loginError">
212 @ You entered an unknown user or an incorrect password.
213 @ </span></p>
214 ;
215 }else{
216 char *zCookie;
217 const char *zCookieName = login_cookie_name();
218 const char *zExpire = db_get("cookie-expire","8766");
@@ -229,38 +229,38 @@
229 redirect_to_g();
230 }
231 }
232 style_header("Login/Logout");
233 @ %s(zErrMsg)
234 @ <form action="login" method="post">
235 if( P("g") ){
236 @ <input type="hidden" name="g" value="%h(P("g"))" />
237 }
238 @ <table class="login_out">
239 @ <tr>
240 @ <td class="login_out_label">User ID:</td>
241 if( anonFlag ){
242 @ <td><input type="text" id="u" name="u" value="anonymous" size="30" /></td>
243 }else{
244 @ <td><input type="text" id="u" name="u" value="" size="30" /></td>
245 }
246 @ </tr>
247 @ <tr>
248 @ <td class="login_out_label">Password:</td>
249 @ <td><input type="password" id="p" name="p" value="" size="30" /></td>
250 @ </tr>
251 if( g.zLogin==0 ){
252 zAnonPw = db_text(0, "SELECT pw FROM user"
253 " WHERE login='anonymous'"
254 " AND cap!=''");
255 }
256 @ <tr>
257 @ <td></td>
258 @ <td><input type="submit" name="in" value="Login" /></td>
259 @ </tr>
260 @ </table>
261 @ <script type="text/JavaScript">document.getElementById('u').focus()</script>
262 if( g.zLogin==0 ){
263 @ <p>Enter
264 }else{
265 @ <p>You are currently logged in as <b>%h(g.zLogin)</b></p>
266 @ <p>To change your login to a different user, enter
@@ -273,46 +273,46 @@
273 unsigned int uSeed = captcha_seed();
274 char const *zDecoded = captcha_decode(uSeed);
275 int bAutoCaptcha = db_get_boolean("auto-captcha", 1);
276 char *zCaptcha = captcha_render(zDecoded);
277
278 @ <p><input type="hidden" name="cs" value="%u(uSeed)" />
279 @ Visitors may enter <b>anonymous</b> as the user-ID with
280 @ the 8-character hexadecimal password shown below:</p>
281 @ <div class="captcha"><table class="captcha"><tr><td><pre>
282 @ %s(zCaptcha)
283 @ </pre></td></tr></table>
284 if( bAutoCaptcha ) {
285 @ <input type="button" value="Fill out captcha"
286 @ onclick="document.getElementById('u').value='anonymous';
287 @ document.getElementById('p').value='%s(zDecoded)';" />
288 }
289 @ </div>
290 free(zCaptcha);
291 }
292 if( g.zLogin ){
293 @ <hr />
294 @ <p>To log off the system (and delete your login cookie)
295 @ press the following button:<br />
296 @ <input type="submit" name="out" value="Logout" /></p>
297 }
298 @ </form>
299 if( g.okPassword ){
300 @ <hr />
301 @ <p>To change your password, enter your old password and your
302 @ new password twice below then press the "Change Password"
303 @ button.</p>
304 @ <form action="login" method="post">
305 @ <table>
306 @ <tr><td class="login_out_label">Old Password:</td>
307 @ <td><input type="password" name="p" size="30" /></td></tr>
308 @ <tr><td class="login_out_label">New Password:</td>
309 @ <td><input type="password" name="n1" size="30" /></td></tr>
310 @ <tr><td class="login_out_label">Repeat New Password:</td>
311 @ <td><input type="password" name="n2" size="30" /></td></tr>
312 @ <tr><td></td>
313 @ <td><input type="submit" value="Change Password" /></td></tr>
314 @ </table>
315 @ </form>
316 }
317 style_footer();
318 }
@@ -596,22 +596,22 @@
596 if( !g.okHistory &&
597 db_exists("SELECT 1 FROM user"
598 " WHERE login='anonymous'"
599 " AND cap LIKE '%%h%%'") ){
600 const char *zUrl = PD("REQUEST_URI", "index");
601 @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br />
602 @ Use <a href="%s(g.zTop)/login?anon=1&amp;g=%T(zUrl)">anonymous login</a>
603 @ to enable hyperlinks.</p>
604 }
605 }
606
607 /*
608 ** While rendering a form, call this routine to add the Anti-CSRF token
609 ** as a hidden element of the form.
610 */
611 void login_insert_csrf_secret(void){
612 @ <input type="hidden" name="csrf" value="%s(g.zCsrfToken)" />
613 }
614
615 /*
616 ** Before using the results of a form, first call this routine to verify
617 ** that ths Anti-CSRF token is present and is valid. If the Anti-CSRF token
618
+12 -12
--- src/report.c
+++ src/report.c
@@ -277,13 +277,13 @@
277277
zSQL = db_column_text(&q, 1);
278278
zOwner = db_column_text(&q, 2);
279279
zClrKey = db_column_text(&q, 3);
280280
@ <table cellpadding=0 cellspacing=0 border=0>
281281
@ <tr><td valign="top" align="right">Title:</td><td width=15></td>
282
- @ <td colspan=3>%h(zTitle)</td></tr>
282
+ @ <td colspan="3">%h(zTitle)</td></tr>
283283
@ <tr><td valign="top" align="right">Owner:</td><td></td>
284
- @ <td colspan=3>%h(zOwner)</td></tr>
284
+ @ <td colspan="3">%h(zOwner)</td></tr>
285285
@ <tr><td valign="top" align="right">SQL:</td><td></td>
286286
@ <td valign="top"><pre>
287287
@ %h(zSQL)
288288
@ </pre></td>
289289
@ <td width=15></td><td valign="top">
@@ -393,21 +393,21 @@
393393
}
394394
}
395395
if( zOwner==0 ) zOwner = g.zLogin;
396396
style_submenu_element("Cancel", "Cancel", "reportlist");
397397
if( rn>0 ){
398
- style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn);
398
+ style_submenu_element("Delete", "Delete", "rptedit?rn=%d&amp;del1=1", rn);
399399
}
400400
style_header(rn>0 ? "Edit Report Format":"Create New Report Format");
401401
if( zErr ){
402402
@ <blockquote><font color="#ff0000"><b>%h(zErr)</b></font></blockquote>
403403
}
404404
@ <form action="rptedit" method="POST">
405405
@ <input type="hidden" name="rn" value="%d(rn)">
406
- @ <p>Report Title:<br>
406
+ @ <p>Report Title:<br />
407407
@ <input type="text" name="t" value="%h(zTitle)" size="60"></p>
408
- @ <p>Enter a complete SQL query statement against the "TICKET" table:<br>
408
+ @ <p>Enter a complete SQL query statement against the "TICKET" table:<br />
409409
@ <textarea name="s" rows="20" cols="80">%h(zSQL)</textarea>
410410
@ </p>
411411
login_insert_csrf_secret();
412412
if( g.okAdmin ){
413413
@ <p>Report owner:
@@ -417,11 +417,11 @@
417417
@ <input type="hidden" name="w" value="%h(zOwner)">
418418
}
419419
@ <p>Enter an optional color key in the following box. (If blank, no
420420
@ color key is displayed.) Each line contains the text for a single
421421
@ entry in the key. The first token of each line is the background
422
- @ color for that line.<br>
422
+ @ color for that line.<br />
423423
@ <textarea name="k" rows="8" cols="50">%h(zClrKey)</textarea>
424424
@ </p>
425425
if( !g.okAdmin && strcmp(zOwner,g.zLogin)!=0 ){
426426
@ <p>This report format is owned by %h(zOwner). You are not allowed
427427
@ to change it.</p>
@@ -448,11 +448,11 @@
448448
zSchema = db_text(0,"SELECT sql FROM sqlite_master WHERE name='ticket'");
449449
if( zSchema==0 ){
450450
zSchema = db_text(0,"SELECT sql FROM repository.sqlite_master"
451451
" WHERE name='ticket'");
452452
}
453
- @ <hr><h3>TICKET Schema</h3>
453
+ @ <hr /><h3>TICKET Schema</h3>
454454
@ <blockquote><pre>
455455
@ %h(zSchema)
456456
@ </pre></blockquote>
457457
@ <h3>Notes</h3>
458458
@ <ul>
@@ -829,14 +829,14 @@
829829
while( isspace(*zSafeKey) ) zSafeKey++;
830830
for(i=0; zSafeKey[i] && !isspace(zSafeKey[i]); i++){}
831831
for(j=i; isspace(zSafeKey[j]); j++){}
832832
for(k=j; zSafeKey[k] && zSafeKey[k]!='\n' && zSafeKey[k]!='\r'; k++){}
833833
if( !horiz ){
834
- cgi_printf("<tr bgcolor=\"%.*s\"><td>%.*s</td></tr>\n",
834
+ cgi_printf("<tr style=\"background-color: %.*s;\"><td>%.*s</td></tr>\n",
835835
i, zSafeKey, k-j, &zSafeKey[j]);
836836
}else{
837
- cgi_printf("<td bgcolor=\"%.*s\">%.*s</td>\n",
837
+ cgi_printf("<td style=\"background-color: %.*s;\">%.*s</td>\n",
838838
i, zSafeKey, k-j, &zSafeKey[j]);
839839
}
840840
zSafeKey += k;
841841
}
842842
free(zToFree);
@@ -907,11 +907,11 @@
907907
if( !tabs ){
908908
struct GenerateHTML sState;
909909
910910
db_multi_exec("PRAGMA empty_result_callbacks=ON");
911911
style_submenu_element("Raw", "Raw",
912
- "rptview?tablist=1&%s", PD("QUERY_STRING",""));
912
+ "rptview?tablist=1&amp;%s", PD("QUERY_STRING",""));
913913
if( g.okAdmin
914914
|| (g.okTktFmt && g.zLogin && zOwner && strcmp(g.zLogin,zOwner)==0) ){
915915
style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn);
916916
}
917917
if( g.okTktFmt ){
@@ -921,12 +921,12 @@
921921
style_submenu_element("New Ticket", "Create a new ticket",
922922
"%s/tktnew", g.zTop);
923923
}
924924
style_header(zTitle);
925925
output_color_key(zClrKey, 1,
926
- "border=0 cellpadding=3 cellspacing=0 class=\"report\"");
927
- @ <table border=1 cellpadding=2 cellspacing=0 class="report">
926
+ "border=\"0\" cellpadding=\"3\" cellspacing=\"0\" class=\"report\"");
927
+ @ <table border="1" cellpadding="2" cellspacing="0" class="report">
928928
sState.rn = rn;
929929
sState.nCount = 0;
930930
sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)&zErr1);
931931
sqlite3_exec(g.db, zSql, generate_html, &sState, &zErr2);
932932
sqlite3_set_authorizer(g.db, 0, 0);
933933
--- src/report.c
+++ src/report.c
@@ -277,13 +277,13 @@
277 zSQL = db_column_text(&q, 1);
278 zOwner = db_column_text(&q, 2);
279 zClrKey = db_column_text(&q, 3);
280 @ <table cellpadding=0 cellspacing=0 border=0>
281 @ <tr><td valign="top" align="right">Title:</td><td width=15></td>
282 @ <td colspan=3>%h(zTitle)</td></tr>
283 @ <tr><td valign="top" align="right">Owner:</td><td></td>
284 @ <td colspan=3>%h(zOwner)</td></tr>
285 @ <tr><td valign="top" align="right">SQL:</td><td></td>
286 @ <td valign="top"><pre>
287 @ %h(zSQL)
288 @ </pre></td>
289 @ <td width=15></td><td valign="top">
@@ -393,21 +393,21 @@
393 }
394 }
395 if( zOwner==0 ) zOwner = g.zLogin;
396 style_submenu_element("Cancel", "Cancel", "reportlist");
397 if( rn>0 ){
398 style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn);
399 }
400 style_header(rn>0 ? "Edit Report Format":"Create New Report Format");
401 if( zErr ){
402 @ <blockquote><font color="#ff0000"><b>%h(zErr)</b></font></blockquote>
403 }
404 @ <form action="rptedit" method="POST">
405 @ <input type="hidden" name="rn" value="%d(rn)">
406 @ <p>Report Title:<br>
407 @ <input type="text" name="t" value="%h(zTitle)" size="60"></p>
408 @ <p>Enter a complete SQL query statement against the "TICKET" table:<br>
409 @ <textarea name="s" rows="20" cols="80">%h(zSQL)</textarea>
410 @ </p>
411 login_insert_csrf_secret();
412 if( g.okAdmin ){
413 @ <p>Report owner:
@@ -417,11 +417,11 @@
417 @ <input type="hidden" name="w" value="%h(zOwner)">
418 }
419 @ <p>Enter an optional color key in the following box. (If blank, no
420 @ color key is displayed.) Each line contains the text for a single
421 @ entry in the key. The first token of each line is the background
422 @ color for that line.<br>
423 @ <textarea name="k" rows="8" cols="50">%h(zClrKey)</textarea>
424 @ </p>
425 if( !g.okAdmin && strcmp(zOwner,g.zLogin)!=0 ){
426 @ <p>This report format is owned by %h(zOwner). You are not allowed
427 @ to change it.</p>
@@ -448,11 +448,11 @@
448 zSchema = db_text(0,"SELECT sql FROM sqlite_master WHERE name='ticket'");
449 if( zSchema==0 ){
450 zSchema = db_text(0,"SELECT sql FROM repository.sqlite_master"
451 " WHERE name='ticket'");
452 }
453 @ <hr><h3>TICKET Schema</h3>
454 @ <blockquote><pre>
455 @ %h(zSchema)
456 @ </pre></blockquote>
457 @ <h3>Notes</h3>
458 @ <ul>
@@ -829,14 +829,14 @@
829 while( isspace(*zSafeKey) ) zSafeKey++;
830 for(i=0; zSafeKey[i] && !isspace(zSafeKey[i]); i++){}
831 for(j=i; isspace(zSafeKey[j]); j++){}
832 for(k=j; zSafeKey[k] && zSafeKey[k]!='\n' && zSafeKey[k]!='\r'; k++){}
833 if( !horiz ){
834 cgi_printf("<tr bgcolor=\"%.*s\"><td>%.*s</td></tr>\n",
835 i, zSafeKey, k-j, &zSafeKey[j]);
836 }else{
837 cgi_printf("<td bgcolor=\"%.*s\">%.*s</td>\n",
838 i, zSafeKey, k-j, &zSafeKey[j]);
839 }
840 zSafeKey += k;
841 }
842 free(zToFree);
@@ -907,11 +907,11 @@
907 if( !tabs ){
908 struct GenerateHTML sState;
909
910 db_multi_exec("PRAGMA empty_result_callbacks=ON");
911 style_submenu_element("Raw", "Raw",
912 "rptview?tablist=1&%s", PD("QUERY_STRING",""));
913 if( g.okAdmin
914 || (g.okTktFmt && g.zLogin && zOwner && strcmp(g.zLogin,zOwner)==0) ){
915 style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn);
916 }
917 if( g.okTktFmt ){
@@ -921,12 +921,12 @@
921 style_submenu_element("New Ticket", "Create a new ticket",
922 "%s/tktnew", g.zTop);
923 }
924 style_header(zTitle);
925 output_color_key(zClrKey, 1,
926 "border=0 cellpadding=3 cellspacing=0 class=\"report\"");
927 @ <table border=1 cellpadding=2 cellspacing=0 class="report">
928 sState.rn = rn;
929 sState.nCount = 0;
930 sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)&zErr1);
931 sqlite3_exec(g.db, zSql, generate_html, &sState, &zErr2);
932 sqlite3_set_authorizer(g.db, 0, 0);
933
--- src/report.c
+++ src/report.c
@@ -277,13 +277,13 @@
277 zSQL = db_column_text(&q, 1);
278 zOwner = db_column_text(&q, 2);
279 zClrKey = db_column_text(&q, 3);
280 @ <table cellpadding=0 cellspacing=0 border=0>
281 @ <tr><td valign="top" align="right">Title:</td><td width=15></td>
282 @ <td colspan="3">%h(zTitle)</td></tr>
283 @ <tr><td valign="top" align="right">Owner:</td><td></td>
284 @ <td colspan="3">%h(zOwner)</td></tr>
285 @ <tr><td valign="top" align="right">SQL:</td><td></td>
286 @ <td valign="top"><pre>
287 @ %h(zSQL)
288 @ </pre></td>
289 @ <td width=15></td><td valign="top">
@@ -393,21 +393,21 @@
393 }
394 }
395 if( zOwner==0 ) zOwner = g.zLogin;
396 style_submenu_element("Cancel", "Cancel", "reportlist");
397 if( rn>0 ){
398 style_submenu_element("Delete", "Delete", "rptedit?rn=%d&amp;del1=1", rn);
399 }
400 style_header(rn>0 ? "Edit Report Format":"Create New Report Format");
401 if( zErr ){
402 @ <blockquote><font color="#ff0000"><b>%h(zErr)</b></font></blockquote>
403 }
404 @ <form action="rptedit" method="POST">
405 @ <input type="hidden" name="rn" value="%d(rn)">
406 @ <p>Report Title:<br />
407 @ <input type="text" name="t" value="%h(zTitle)" size="60"></p>
408 @ <p>Enter a complete SQL query statement against the "TICKET" table:<br />
409 @ <textarea name="s" rows="20" cols="80">%h(zSQL)</textarea>
410 @ </p>
411 login_insert_csrf_secret();
412 if( g.okAdmin ){
413 @ <p>Report owner:
@@ -417,11 +417,11 @@
417 @ <input type="hidden" name="w" value="%h(zOwner)">
418 }
419 @ <p>Enter an optional color key in the following box. (If blank, no
420 @ color key is displayed.) Each line contains the text for a single
421 @ entry in the key. The first token of each line is the background
422 @ color for that line.<br />
423 @ <textarea name="k" rows="8" cols="50">%h(zClrKey)</textarea>
424 @ </p>
425 if( !g.okAdmin && strcmp(zOwner,g.zLogin)!=0 ){
426 @ <p>This report format is owned by %h(zOwner). You are not allowed
427 @ to change it.</p>
@@ -448,11 +448,11 @@
448 zSchema = db_text(0,"SELECT sql FROM sqlite_master WHERE name='ticket'");
449 if( zSchema==0 ){
450 zSchema = db_text(0,"SELECT sql FROM repository.sqlite_master"
451 " WHERE name='ticket'");
452 }
453 @ <hr /><h3>TICKET Schema</h3>
454 @ <blockquote><pre>
455 @ %h(zSchema)
456 @ </pre></blockquote>
457 @ <h3>Notes</h3>
458 @ <ul>
@@ -829,14 +829,14 @@
829 while( isspace(*zSafeKey) ) zSafeKey++;
830 for(i=0; zSafeKey[i] && !isspace(zSafeKey[i]); i++){}
831 for(j=i; isspace(zSafeKey[j]); j++){}
832 for(k=j; zSafeKey[k] && zSafeKey[k]!='\n' && zSafeKey[k]!='\r'; k++){}
833 if( !horiz ){
834 cgi_printf("<tr style=\"background-color: %.*s;\"><td>%.*s</td></tr>\n",
835 i, zSafeKey, k-j, &zSafeKey[j]);
836 }else{
837 cgi_printf("<td style=\"background-color: %.*s;\">%.*s</td>\n",
838 i, zSafeKey, k-j, &zSafeKey[j]);
839 }
840 zSafeKey += k;
841 }
842 free(zToFree);
@@ -907,11 +907,11 @@
907 if( !tabs ){
908 struct GenerateHTML sState;
909
910 db_multi_exec("PRAGMA empty_result_callbacks=ON");
911 style_submenu_element("Raw", "Raw",
912 "rptview?tablist=1&amp;%s", PD("QUERY_STRING",""));
913 if( g.okAdmin
914 || (g.okTktFmt && g.zLogin && zOwner && strcmp(g.zLogin,zOwner)==0) ){
915 style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn);
916 }
917 if( g.okTktFmt ){
@@ -921,12 +921,12 @@
921 style_submenu_element("New Ticket", "Create a new ticket",
922 "%s/tktnew", g.zTop);
923 }
924 style_header(zTitle);
925 output_color_key(zClrKey, 1,
926 "border=\"0\" cellpadding=\"3\" cellspacing=\"0\" class=\"report\"");
927 @ <table border="1" cellpadding="2" cellspacing="0" class="report">
928 sState.rn = rn;
929 sState.nCount = 0;
930 sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)&zErr1);
931 sqlite3_exec(g.db, zSql, generate_html, &sState, &zErr2);
932 sqlite3_set_authorizer(g.db, 0, 0);
933
+309 -278
--- src/setup.c
+++ src/setup.c
@@ -99,42 +99,40 @@
9999
return;
100100
}
101101
102102
style_submenu_element("Add", "Add User", "setup_uedit");
103103
style_header("User List");
104
- @ <table border="0" cellpadding="0" cellspacing="25">
105
- @ <tr><td valign="top">
106
- @ <b>Users:</b>
107
- @ <table border="1" cellpadding="10"><tr><td>
108
- @ <table cellspacing=0 cellpadding=0 border=0>
104
+ @ <table class="usetupLayoutTable">
105
+ @ <tr><td class="usetupColumnLayout">
106
+ @ <span class="note">Users:</span>
107
+ @ <table class="usetupUserList">
109108
@ <tr>
110
- @ <th align="right">User&nbsp;ID</th><td width="20">&nbsp;</td>
111
- @ <th>Capabilities</th><td width="15">&nbsp;</td>
112
- @ <th>Contact&nbsp;Info</th>
109
+ @ <th class="usetupListUser" style="text-align: right;padding-right: 20px;">User&nbsp;ID</th>
110
+ @ <th class="usetupListCap" style="text-align: center;padding-right: 15px;">Capabilities</th>
111
+ @ <th class="usetupListCon" style="text-align: left;">Contact&nbsp;Info</th>
113112
@ </tr>
114113
db_prepare(&s, "SELECT uid, login, cap, info FROM user ORDER BY login");
115114
while( db_step(&s)==SQLITE_ROW ){
116115
const char *zCap = db_column_text(&s, 2);
117116
if( strstr(zCap, "s") ) zCap = "s";
118117
@ <tr>
119
- @ <td align="right">
118
+ @ <td class="usetupListUser" style="text-align: right;padding-right: 20px;white-space:nowrap;">
120119
if( g.okAdmin && (zCap[0]!='s' || g.okSetup) ){
121120
@ <a href="setup_uedit?id=%d(db_column_int(&s,0))">
122121
}
123
- @ <nobr>%h(db_column_text(&s,1))</nobr>
122
+ @ %h(db_column_text(&s,1))
124123
if( g.okAdmin ){
125124
@ </a>
126125
}
127
- @ </td><td>&nbsp;&nbsp;&nbsp;</td>
128
- @ <td align="center">%s(zCap)</td>
129
- @ <td>&nbsp;&nbsp;&nbsp;</td>
130
- @ <td align="left">%s(db_column_text(&s,3))</td>
126
+ @ </td>
127
+ @ <td class="usetupListCap" style="text-align: center;padding-right: 15px;">%s(zCap)</td>
128
+ @ <td class="usetupListCon" style="text-align: left;">%s(db_column_text(&s,3))</td>
131129
@ </tr>
132130
}
133
- @ </table></td></tr></table>
134
- @ <td valign="top">
135
- @ <b>Notes:</b>
131
+ @ </table>
132
+ @ </td><td class="usetupColumnLayout">
133
+ @ <span class="note">Notes:</span>
136134
@ <ol>
137135
@ <li><p>The permission flags are as follows:</p>
138136
@ <table>
139137
@ <tr><td valign="top"><b>a</b></td>
140138
@ <td><i>Admin:</i> Create and delete users</td></tr>
@@ -181,31 +179,35 @@
181179
@ user <tt>developer</tt></td></tr>
182180
@ <tr><td valign="top"><b>w</b></td>
183181
@ <td><i>Write-Tkt:</i> Edit tickets</td></tr>
184182
@ <tr><td valign="top"><b>z</b></td>
185183
@ <td><i>Zip download:</i> Download a baseline via the
186
- @ <tt>/zip</tt> URL even without check<b>o</b>ut
187
- @ and <b>h</b>istory permissions</td></tr>
184
+ @ <tt>/zip</tt> URL even without
185
+ @ check<span class="capability">o</span>ut
186
+ @ and <span class="capability">h</span>istory permissions</td></tr>
188187
@ </table>
189188
@ </li>
190189
@
191190
@ <li><p>
192
- @ Every user, logged in or not, inherits the privileges of <b>nobody</b>.
191
+ @ Every user, logged in or not, inherits the privileges of
192
+ @ <span class="usertype">nobody</span>.
193193
@ </p></li>
194194
@
195195
@ <li><p>
196
- @ Any human can login as <b>anonymous</b> since the password is
197
- @ clearly displayed on the login page for them to type. The purpose
198
- @ of requiring anonymous to log in is to prevent access by spiders.
196
+ @ Any human can login as <span class="usertype">anonymous</span> since the
197
+ @ password is clearly displayed on the login page for them to type. The
198
+ @ purpose of requiring anonymous to log in is to prevent access by spiders.
199199
@ Every logged-in user inherits the combined privileges of
200
- @ <b>anonymous</b> and
201
- @ <b>nobody</b>.
200
+ @ <span class="usertype">anonymous</span> and
201
+ @ <span class="usertype">nobody</span>.
202202
@ </p></li>
203203
@
204204
@ <li><p>
205
- @ Users with privilege <b>v</b> inherit the combined privileges of
206
- @ <b>developer</b>, <b>anonymous</b>, and <b>nobody</b>.
205
+ @ Users with privilege <span class="capability">v</span> inherit the combined
206
+ @ privileges of <span class="usertype">developer</span>,
207
+ @ <span class="usertype">anonymous</span>, and
208
+ @ <span class="usertype">nobody</span>.
207209
@ </p></li>
208210
@
209211
@ </ol>
210212
@ </td></tr></table>
211213
style_footer();
@@ -323,12 +325,12 @@
323325
}
324326
if( uid>0 &&
325327
db_exists("SELECT 1 FROM user WHERE login=%Q AND uid!=%d", zLogin, uid)
326328
){
327329
style_header("User Creation Error");
328
- @ <font color="red">Login "%h(zLogin)" is already used by a different
329
- @ user.</font>
330
+ @ <span class="loginError">Login "%h(zLogin)" is already used by
331
+ @ a different user.</span>
330332
@
331333
@ <p><a href="setup_uedit?id=%d(uid)">[Bummer]</a></p>
332334
style_footer();
333335
return;
334336
}
@@ -353,65 +355,69 @@
353355
if( uid ){
354356
zLogin = db_text("", "SELECT login FROM user WHERE uid=%d", uid);
355357
zInfo = db_text("", "SELECT info FROM user WHERE uid=%d", uid);
356358
zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", uid);
357359
zPw = db_text("", "SELECT pw FROM user WHERE uid=%d", uid);
358
- if( strchr(zCap, 'a') ) oaa = " checked";
359
- if( strchr(zCap, 'b') ) oab = " checked";
360
- if( strchr(zCap, 'c') ) oac = " checked";
361
- if( strchr(zCap, 'd') ) oad = " checked";
362
- if( strchr(zCap, 'e') ) oae = " checked";
363
- if( strchr(zCap, 'f') ) oaf = " checked";
364
- if( strchr(zCap, 'g') ) oag = " checked";
365
- if( strchr(zCap, 'h') ) oah = " checked";
366
- if( strchr(zCap, 'i') ) oai = " checked";
367
- if( strchr(zCap, 'j') ) oaj = " checked";
368
- if( strchr(zCap, 'k') ) oak = " checked";
369
- if( strchr(zCap, 'm') ) oam = " checked";
370
- if( strchr(zCap, 'n') ) oan = " checked";
371
- if( strchr(zCap, 'o') ) oao = " checked";
372
- if( strchr(zCap, 'p') ) oap = " checked";
373
- if( strchr(zCap, 'r') ) oar = " checked";
374
- if( strchr(zCap, 's') ) oas = " checked";
375
- if( strchr(zCap, 't') ) oat = " checked";
376
- if( strchr(zCap, 'u') ) oau = " checked";
377
- if( strchr(zCap, 'v') ) oav = " checked";
378
- if( strchr(zCap, 'w') ) oaw = " checked";
379
- if( strchr(zCap, 'z') ) oaz = " checked";
360
+ if( strchr(zCap, 'a') ) oaa = " checked=\"checked\"";
361
+ if( strchr(zCap, 'b') ) oab = " checked=\"checked\"";
362
+ if( strchr(zCap, 'c') ) oac = " checked=\"checked\"";
363
+ if( strchr(zCap, 'd') ) oad = " checked=\"checked\"";
364
+ if( strchr(zCap, 'e') ) oae = " checked=\"checked\"";
365
+ if( strchr(zCap, 'f') ) oaf = " checked=\"checked\"";
366
+ if( strchr(zCap, 'g') ) oag = " checked=\"checked\"";
367
+ if( strchr(zCap, 'h') ) oah = " checked=\"checked\"";
368
+ if( strchr(zCap, 'i') ) oai = " checked=\"checked\"";
369
+ if( strchr(zCap, 'j') ) oaj = " checked=\"checked\"";
370
+ if( strchr(zCap, 'k') ) oak = " checked=\"checked\"";
371
+ if( strchr(zCap, 'm') ) oam = " checked=\"checked\"";
372
+ if( strchr(zCap, 'n') ) oan = " checked=\"checked\"";
373
+ if( strchr(zCap, 'o') ) oao = " checked=\"checked\"";
374
+ if( strchr(zCap, 'p') ) oap = " checked=\"checked\"";
375
+ if( strchr(zCap, 'r') ) oar = " checked=\"checked\"";
376
+ if( strchr(zCap, 's') ) oas = " checked=\"checked\"";
377
+ if( strchr(zCap, 't') ) oat = " checked=\"checked\"";
378
+ if( strchr(zCap, 'u') ) oau = " checked=\"checked\"";
379
+ if( strchr(zCap, 'v') ) oav = " checked=\"checked\"";
380
+ if( strchr(zCap, 'w') ) oaw = " checked=\"checked\"";
381
+ if( strchr(zCap, 'z') ) oaz = " checked=\"checked\"";
380382
}
381383
382384
/* figure out inherited permissions */
383385
memset(inherit, 0, sizeof(inherit));
384386
if( strcmp(zLogin, "developer") ){
385387
char *z1, *z2;
386388
z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='developer'");
387389
while( z1 && *z1 ){
388
- inherit[0x7f & *(z1++)] = "<font color=\"red\">&bull;</font>";
390
+ inherit[0x7f & *(z1++)] =
391
+ "<span class=\"ueditInheritDeveloper\">&bull;</span>";
389392
}
390393
free(z2);
391394
}
392395
if( strcmp(zLogin, "reader") ){
393396
char *z1, *z2;
394397
z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='reader'");
395398
while( z1 && *z1 ){
396
- inherit[0x7f & *(z1++)] = "<font color=\"black\">&bull;</font>";
399
+ inherit[0x7f & *(z1++)] =
400
+ "<span class=\"ueditInheritReader\">&bull;</span>";
397401
}
398402
free(z2);
399403
}
400404
if( strcmp(zLogin, "anonymous") ){
401405
char *z1, *z2;
402406
z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='anonymous'");
403407
while( z1 && *z1 ){
404
- inherit[0x7f & *(z1++)] = "<font color=\"blue\">&bull;</font>";
408
+ inherit[0x7f & *(z1++)] =
409
+ "<span class=\"ueditInheritAnonymous\">&bull;</span>";
405410
}
406411
free(z2);
407412
}
408413
if( strcmp(zLogin, "nobody") ){
409414
char *z1, *z2;
410415
z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='nobody'");
411416
while( z1 && *z1 ){
412
- inherit[0x7f & *(z1++)] = "<font color=\"green\">&bull;</font>";
417
+ inherit[0x7f & *(z1++)] =
418
+ "<span class=\"ueditInheritNobody\">&bull;</span>";
413419
}
414420
free(z2);
415421
}
416422
417423
/* Begin generating the page
@@ -420,77 +426,79 @@
420426
if( uid ){
421427
style_header(mprintf("Edit User %h", zLogin));
422428
}else{
423429
style_header("Add A New User");
424430
}
425
- @ <table align="left" hspace="20" vspace="10"><tr><td>
426
- @ <form action="%s(g.zPath)" method="POST">
431
+ @ <div class="ueditCapBox">
432
+ @ <form action="%s(g.zPath)" method="post"><div>
427433
login_insert_csrf_secret();
428434
@ <table>
429435
@ <tr>
430
- @ <td align="right"><nobr>User ID:</nobr></td>
431
- if( uid ){
432
- @ <td>%d(uid) <input type="hidden" name="id" value="%d(uid)"></td>
433
- }else{
434
- @ <td>(new user)<input type="hidden" name="id" value=0></td>
435
- }
436
- @ </tr>
437
- @ <tr>
438
- @ <td align="right"><nobr>Login:</nobr></td>
439
- @ <td><input type="text" name="login" value="%h(zLogin)"></td>
440
- @ </tr>
441
- @ <tr>
442
- @ <td align="right"><nobr>Contact&nbsp;Info:</nobr></td>
443
- @ <td><input type="text" name="info" size=40 value="%h(zInfo)"></td>
444
- @ </tr>
445
- @ <tr>
446
- @ <td align="right" valign="top">Capabilities:</td>
436
+ @ <td class="usetupEditLabel">User ID:</td>
437
+ if( uid ){
438
+ @ <td>%d(uid) <input type="hidden" name="id" value="%d(uid)" /></td>
439
+ }else{
440
+ @ <td>(new user)<input type="hidden" name="id" value="0" /></td>
441
+ }
442
+ @ </tr>
443
+ @ <tr>
444
+ @ <td class="usetupEditLabel">Login:</td>
445
+ @ <td><input type="text" name="login" value="%h(zLogin)" /></td>
446
+ @ </tr>
447
+ @ <tr>
448
+ @ <td class="usetupEditLabel">Contact&nbsp;Info:</td>
449
+ @ <td><input type="text" name="info" size="40" value="%h(zInfo)" /></td>
450
+ @ </tr>
451
+ @ <tr>
452
+ @ <td class="usetupEditLabel">Capabilities:</td>
447453
@ <td>
448454
#define B(x) inherit[x]
449455
if( g.okSetup ){
450
- @ <input type="checkbox" name="as"%s(oas)/>%s(B('s'))Setup<br>
451
- }
452
- @ <input type="checkbox" name="aa"%s(oaa)/>%s(B('a'))Admin<br>
453
- @ <input type="checkbox" name="ad"%s(oad)/>%s(B('d'))Delete<br>
454
- @ <input type="checkbox" name="ae"%s(oae)/>%s(B('e'))Email<br>
455
- @ <input type="checkbox" name="ap"%s(oap)/>%s(B('p'))Password<br>
456
- @ <input type="checkbox" name="ai"%s(oai)/>%s(B('i'))Check-In<br>
457
- @ <input type="checkbox" name="ao"%s(oao)/>%s(B('o'))Check-Out<br>
458
- @ <input type="checkbox" name="ah"%s(oah)/>%s(B('h'))History<br>
459
- @ <input type="checkbox" name="au"%s(oau)/>%s(B('u'))Reader<br>
460
- @ <input type="checkbox" name="av"%s(oav)/>%s(B('v'))Developer<br>
461
- @ <input type="checkbox" name="ag"%s(oag)/>%s(B('g'))Clone<br>
462
- @ <input type="checkbox" name="aj"%s(oaj)/>%s(B('j'))Read Wiki<br>
463
- @ <input type="checkbox" name="af"%s(oaf)/>%s(B('f'))New Wiki<br>
464
- @ <input type="checkbox" name="am"%s(oam)/>%s(B('m'))Append Wiki<br>
465
- @ <input type="checkbox" name="ak"%s(oak)/>%s(B('k'))Write Wiki<br>
466
- @ <input type="checkbox" name="ab"%s(oab)/>%s(B('b'))Attachments<br>
467
- @ <input type="checkbox" name="ar"%s(oar)/>%s(B('r'))Read Ticket<br>
468
- @ <input type="checkbox" name="an"%s(oan)/>%s(B('n'))New Ticket<br>
469
- @ <input type="checkbox" name="ac"%s(oac)/>%s(B('c'))Append Ticket<br>
470
- @ <input type="checkbox" name="aw"%s(oaw)/>%s(B('w'))Write Ticket<br>
471
- @ <input type="checkbox" name="at"%s(oat)/>%s(B('t'))Ticket Report<br>
472
- @ <input type="checkbox" name="az"%s(oaz)/>%s(B('z'))Download Zip
456
+ @ <input type="checkbox" name="as"%s(oas) />%s(B('s'))Setup<br />
457
+ }
458
+ @ <input type="checkbox" name="aa"%s(oaa) />%s(B('a'))Admin<br />
459
+ @ <input type="checkbox" name="ad"%s(oad) />%s(B('d'))Delete<br />
460
+ @ <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br />
461
+ @ <input type="checkbox" name="ap"%s(oap) />%s(B('p'))Password<br />
462
+ @ <input type="checkbox" name="ai"%s(oai) />%s(B('i'))Check-In<br />
463
+ @ <input type="checkbox" name="ao"%s(oao) />%s(B('o'))Check-Out<br />
464
+ @ <input type="checkbox" name="ah"%s(oah) />%s(B('h'))History<br />
465
+ @ <input type="checkbox" name="au"%s(oau) />%s(B('u'))Reader<br />
466
+ @ <input type="checkbox" name="av"%s(oav) />%s(B('v'))Developer<br />
467
+ @ <input type="checkbox" name="ag"%s(oag) />%s(B('g'))Clone<br />
468
+ @ <input type="checkbox" name="aj"%s(oaj) />%s(B('j'))Read Wiki<br />
469
+ @ <input type="checkbox" name="af"%s(oaf) />%s(B('f'))New Wiki<br />
470
+ @ <input type="checkbox" name="am"%s(oam) />%s(B('m'))Append Wiki<br />
471
+ @ <input type="checkbox" name="ak"%s(oak) />%s(B('k'))Write Wiki<br />
472
+ @ <input type="checkbox" name="ab"%s(oab) />%s(B('b'))Attachments<br />
473
+ @ <input type="checkbox" name="ar"%s(oar) />%s(B('r'))Read Ticket<br />
474
+ @ <input type="checkbox" name="an"%s(oan) />%s(B('n'))New Ticket<br />
475
+ @ <input type="checkbox" name="ac"%s(oac) />%s(B('c'))Append Ticket<br />
476
+ @ <input type="checkbox" name="aw"%s(oaw) />%s(B('w'))Write Ticket<br />
477
+ @ <input type="checkbox" name="at"%s(oat) />%s(B('t'))Ticket Report<br />
478
+ @ <input type="checkbox" name="az"%s(oaz) />%s(B('z'))Download Zip
473479
@ </td>
474480
@ </tr>
475481
@ <tr>
476482
@ <td align="right">Password:</td>
477483
if( zPw[0] ){
478484
/* Obscure the password for all users */
479
- @ <td><input type="password" name="pw" value="**********"></td>
485
+ @ <td><input type="password" name="pw" value="**********" /></td>
480486
}else{
481487
/* Show an empty password as an empty input field */
482
- @ <td><input type="password" name="pw" value=""></td>
488
+ @ <td><input type="password" name="pw" value="" /></td>
483489
}
484490
@ </tr>
485491
if( !higherUser ){
486492
@ <tr>
487
- @ <td>&nbsp</td>
488
- @ <td><input type="submit" name="submit" value="Apply Changes">
493
+ @ <td>&nbsp;</td>
494
+ @ <td><input type="submit" name="submit" value="Apply Changes" /></td>
489495
@ </tr>
490496
}
491
- @ </table></td></tr></table>
497
+ @ </table>
498
+ @ </div></form>
499
+ @ </div>
492500
@ <h2>Privileges And Capabilities:</h2>
493501
@ <ul>
494502
if( higherUser ){
495503
@ <li><p><font color="blue"><b>
496504
@ User %h(zLogin) has Setup privileges and you only have Admin privileges
@@ -497,95 +505,114 @@
497505
@ so you are not permitted to make changes to %h(zLogin).
498506
@ </b></font></p></li>
499507
@
500508
}
501509
@ <li><p>
502
- @ The <b>Setup</b> user can make arbitrary configuration changes.
503
- @ An <b>Admin</b> user can add other users and change user privileges
510
+ @ The <span class="capability">Setup</span> user can make arbitrary
511
+ @ configuration changes. An <span class="usertype">Admin</span> user
512
+ @ can add other users and change user privileges
504513
@ and reset user passwords. Both automatically get all other privileges
505514
@ listed below. Use these two settings with discretion.
506515
@ </p></li>
507516
@
508517
@ <li><p>
509
- @ The "<font color="green"><big>&bull;</big></font>" mark indicates
510
- @ the privileges of "nobody" that are available to all users
511
- @ regardless of whether or not they are logged in.
512
- @ </p></li>
513
- @
514
- @ <li><p>
515
- @ The "<font color="blue"><big>&bull;</big></font>" mark indicates
516
- @ the privileges of "anonymous" that are inherited by all logged-in users.
517
- @ </p></li>
518
- @
519
- @ <li><p>
520
- @ The "<font color="red"><big>&bull;</big></font>" mark indicates
521
- @ the privileges of "developer" that are inherited by all users with
522
- @ the <b>Developer</b> privilege.
523
- @ </p></li>
524
- @
525
- @ <li><p>
526
- @ The "<font color="black"><big>&bull;</big></font>" mark indicates
527
- @ the privileges of "reader" that are inherited by all users with
528
- @ the <b>Reader</b> privilege.
529
- @ </p></li>
530
- @
531
- @ <li><p>
532
- @ The <b>Delete</b> privilege give the user the ability to erase
533
- @ wiki, tickets, and attachments that have been added by anonymous
534
- @ users. This capability is intended for deletion of spam. The
535
- @ delete capability is only in effect for 24 hours after the item
536
- @ is first posted. The Setup user can delete anything at any time.
537
- @ </p></li>
538
- @
539
- @ <li><p>
540
- @ The <b>History</b> privilege allows a user to see most hyperlinks.
541
- @ This is recommended ON for most logged-in users but OFF for
542
- @ user "nobody" to avoid problems with spiders trying to walk every
543
- @ historical version of every baseline and file.
544
- @ </p></li>
545
- @
546
- @ <li><p>
547
- @ The <b>Zip</b> privilege allows a user to see the "download as ZIP"
548
- @ hyperlink and permits access to the <tt>/zip</tt> page. This allows
549
- @ users to download ZIP archives without granting other rights like
550
- @ <b>Read</b> or <b>History</b>. This privilege is recommended for
551
- @ user <b>nobody</b> so that automatic package downloaders can obtain
552
- @ the sources without going through the login procedure.
553
- @ </p></li>
554
- @
555
- @ <li><p>
556
- @ The <b>Check-in</b> privilege allows remote users to "push".
557
- @ The <b>Check-out</b> privilege allows remote users to "pull".
558
- @ The <b>Clone</b> privilege allows remote users to "clone".
559
- @ </li><p>
560
- @
561
- @ <li><p>
562
- @ The <b>Read Wiki</b>, <b>New Wiki</b>, <b>Append Wiki</b>, and
563
- @ <b>Write Wiki</b> privileges control access to wiki pages. The
564
- @ <b>Read Ticket</b>, <b>New Ticket</b>, <b>Append Ticket</b>, and
565
- @ <b>Write Ticket</b> privileges control access to trouble tickets.
566
- @ The <b>Ticket Report</b> privilege allows the user to create or edit
567
- @ ticket report formats.
568
- @ </p></li>
569
- @
570
- @ <li><p>
571
- @ Users with the <b>Password</b> privilege are allowed to change their
572
- @ own password. Recommended ON for most users but OFF for special
573
- @ users "developer", "anonymous", and "nobody".
574
- @ </p></li>
575
- @
576
- @ <li><p>
577
- @ The <b>EMail</b> privilege allows the display of sensitive information
578
- @ such as the email address of users and contact information on tickets.
579
- @ Recommended OFF for "anonymous" and for "nobody" but ON for
580
- @ "developer".
581
- @ </p></li>
582
- @
583
- @ <li><p>
584
- @ The <b>Attachment</b> privilege is needed in order to add attachments
585
- @ to tickets or wiki. Write privilege on the ticket or wiki is also
586
- @ required.</p></li>
518
+ @ The "<span class="ueditInheritNobody"><big>&bull;</big></span>" mark
519
+ @ indicates the privileges of <span class="usertype">nobody</span> that
520
+ @ are available to all users regardless of whether or not they are logged in.
521
+ @ </p></li>
522
+ @
523
+ @ <li><p>
524
+ @ The "<span class="ueditInheritAnonymous"><big>&bull;</big></span>" mark
525
+ @ indicates the privileges of <span class="usertype">anonymous</span> that
526
+ @ are inherited by all logged-in users.
527
+ @ </p></li>
528
+ @
529
+ @ <li><p>
530
+ @ The "<span class="ueditInheritDeveloper"><big>&bull;</big></span>" mark
531
+ @ indicates the privileges of <span class="usertype">developer</span> that
532
+ @ are inherited by all users with the
533
+ @ <span class="capability">Developer</span> privilege.
534
+ @ </p></li>
535
+ @
536
+ @ <li><p>
537
+ @ The "<span class="ueditInheritReader"><big>&bull;</big></span>" mark
538
+ @ indicates the privileges of <span class="usertype">reader</span> that
539
+ @ are inherited by all users with the <span class="capability">Reader</span>
540
+ @ privilege.
541
+ @ </p></li>
542
+ @
543
+ @ <li><p>
544
+ @ The <span class="capability">Delete</span> privilege give the user the
545
+ @ ability to erase wiki, tickets, and attachments that have been added
546
+ @ by anonymous users. This capability is intended for deletion of spam.
547
+ @ The delete capability is only in effect for 24 hours after the item
548
+ @ is first posted. The <span class="usertype">Setup</span> user can
549
+ @ delete anything at any time.
550
+ @ </p></li>
551
+ @
552
+ @ <li><p>
553
+ @ The <span class="capability">History</span> privilege allows a user
554
+ @ to see most hyperlinks. This is recommended ON for most logged-in users
555
+ @ but OFF for user "nobody" to avoid problems with spiders trying to walk
556
+ @ every historical version of every baseline and file.
557
+ @ </p></li>
558
+ @
559
+ @ <li><p>
560
+ @ The <span class="capability">Zip</span> privilege allows a user to
561
+ @ see the "download as ZIP"
562
+ @ hyperlink and permits access to the <tt>/zip</tt> page. This allows
563
+ @ users to download ZIP archives without granting other rights like
564
+ @ <span class="capability">Read</span> or
565
+ @ <span class="capability">History</span>. This privilege is recommended for
566
+ @ user <span class="usertype">nobody</span> so that automatic package
567
+ @ downloaders can obtain the sources without going through the login
568
+ @ procedure.
569
+ @ </p></li>
570
+ @
571
+ @ <li><p>
572
+ @ The <span class="capability">Check-in</span> privilege allows remote
573
+ @ users to "push". The <span class="capability">Check-out</span> privilege
574
+ @ allows remote users to "pull". The <span class="capability">Clone</span>
575
+ @ privilege allows remote users to "clone".
576
+ @ </p></li>
577
+ @
578
+ @ <li><p>
579
+ @ The <span class="capability">Read Wiki</span>,
580
+ @ <span class="capability">New Wiki</span>,
581
+ @ <span class="capability">Append Wiki</span>, and
582
+ @ <b>Write Wiki</b> privileges control access to wiki pages. The
583
+ @ <span class="capability">Read Ticket</span>,
584
+ @ <span class="capability">New Ticket</span>,
585
+ @ <span class="capability">Append Ticket</span>, and
586
+ @ <span class="capability">Write Ticket</span> privileges control access
587
+ @ to trouble tickets.
588
+ @ The <span class="capability">Ticket Report</span> privilege allows
589
+ @ the user to create or edit ticket report formats.
590
+ @ </p></li>
591
+ @
592
+ @ <li><p>
593
+ @ Users with the <span class="capability">Password</span> privilege
594
+ @ are allowed to change their own password. Recommended ON for most
595
+ @ users but OFF for special users <span class="usertype">developer</span>,
596
+ @ <span class="usertype">anonymous</span>,
597
+ @ and <span class="usertype">nobody</span>.
598
+ @ </p></li>
599
+ @
600
+ @ <li><p>
601
+ @ The <span class="capability">EMail</span> privilege allows the display of
602
+ @ sensitive information such as the email address of users and contact
603
+ @ information on tickets. Recommended OFF for
604
+ @ <span class="usertype">anonymousy</span> and for
605
+ @ <span class="usertype">nobody</span> but ON for
606
+ @ <span class="usertype">developer</span>.
607
+ @ </p></li>
608
+ @
609
+ @ <li><p>
610
+ @ The <span class="capability">Attachment</span> privilege is needed in
611
+ @ order to add attachments to tickets or wiki. Write privilege on the
612
+ @ ticket or wiki is also required.
613
+ @ </p></li>
587614
@
588615
@ <li><p>
589616
@ Login is prohibited if the password is an empty string.
590617
@ </p></li>
591618
@ </ul>
@@ -592,42 +619,46 @@
592619
@
593620
@ <h2>Special Logins</h2>
594621
@
595622
@ <ul>
596623
@ <li><p>
597
- @ No login is required for user "<b>nobody</b>". The capabilities
598
- @ of the <b>nobody</b> user are inherited by all users, regardless of
599
- @ whether or not they are logged in. To disable universal access
600
- @ to the repository, make sure no user named "<b>nobody</b>" exists or
601
- @ that the <b>nobody</b> user has no capabilities enabled.
602
- @ The password for <b>nobody</b> is ignore. To avoid problems with
603
- @ spiders overloading the server, it is recommended
604
- @ that the 'h' (History) capability be turned off for the <b>nobody</b>
605
- @ user.
606
- @ </p></li>
607
- @
608
- @ <li><p>
609
- @ Login is required for user "<b>anonymous</b>" but the password
610
- @ is displayed on the login screen beside the password entry box
611
- @ so anybody who can read should be able to login as anonymous.
612
- @ On the other hand, spiders and web-crawlers will typically not
613
- @ be able to login. Set the capabilities of the anonymous user
614
- @ to things that you want any human to be able to do, but not any
615
- @ spider. Every other logged-in user inherits the privileges of
616
- @ <b>anonymous</b>.
617
- @ </p></li>
618
- @
619
- @ <li><p>
620
- @ The "<b>developer</b>" user is intended as a template for trusted users
621
- @ with check-in privileges. When adding new trusted users, simply
622
- @ select the <b>Developer</b> privilege to cause the new user to inherit
623
- @ all privileges of the "developer" user. Similarly, the "<b>reader</b>"
624
- @ user is a template for users who are allowed more access than anonymous,
625
- @ but less than a developer.
626
- @ </p></li>
627
- @ </ul>
628
- @ </form>
624
+ @ No login is required for user <span class="usertype">nobody</span>. The
625
+ @ capabilities of the <span class="usertype">nobody</span> user are
626
+ @ inherited by all users, regardless of whether or not they are logged in.
627
+ @ To disable universal access to the repository, make sure no user named
628
+ @ <span class="usertype">nobody</span> exists or that the
629
+ @ <span class="usertype">nobody</span> user has no capabilities
630
+ @ enabled. The password for <span class="usertype">nobody</span> is ignore.
631
+ @ To avoid problems with spiders overloading the server, it is recommended
632
+ @ that the <span class="capability">h</span> (History) capability be turned
633
+ @ off for the <span class="usertype">nobody</span> user.
634
+ @ </p></li>
635
+ @
636
+ @ <li><p>
637
+ @ Login is required for user <span class="usertype">anonymous</span> but the
638
+ @ password is displayed on the login screen beside the password entry box
639
+ @ so anybody who can read should be able to login as anonymous.
640
+ @ On the other hand, spiders and web-crawlers will typically not
641
+ @ be able to login. Set the capabilities of the
642
+ @ <span class="usertype">anonymous</span>
643
+ @ user to things that you want any human to be able to do, but not any
644
+ @ spider. Every other logged-in user inherits the privileges of
645
+ @ <span class="usertype">anonymous</span>.
646
+ @ </p></li>
647
+ @
648
+ @ <li><p>
649
+ @ The <span class="usertype">developer</span> user is intended as a template
650
+ @ for trusted users with check-in privileges. When adding new trusted users,
651
+ @ simply select the <span class="capability">developer</span> privilege to
652
+ @ cause the new user to inherit all privileges of the
653
+ @ <span class="usertype">developer</span>
654
+ @ user. Similarly, the <span class="usertype">reader</span> user is a
655
+ @ template for users who are allowed more access than
656
+ @ <span class="usertype">anonymous</span>,
657
+ @ but less than a <span class="usertype">developer</span>.
658
+ @ </p></li>
659
+ @ </ul>
629660
style_footer();
630661
}
631662
632663
633664
/*
@@ -651,13 +682,14 @@
651682
db_set(zVar, iQ ? "1" : "0", 0);
652683
iVal = iQ;
653684
}
654685
}
655686
if( iVal ){
656
- @ <input type="checkbox" name="%s(zQParm)" checked><b>%s(zLabel)</b></input>
687
+ @ <input type="checkbox" name="%s(zQParm)" checked="checked" />
688
+ @ <b>%s(zLabel)</b>
657689
}else{
658
- @ <input type="checkbox" name="%s(zQParm)"><b>%s(zLabel)</b></input>
690
+ @ <input type="checkbox" name="%s(zQParm)" /><b>%s(zLabel)</b>
659691
}
660692
}
661693
662694
/*
663695
** Generate an entry box for an attribute.
@@ -674,11 +706,11 @@
674706
if( zQ && strcmp(zQ,zVal)!=0 ){
675707
login_verify_csrf_secret();
676708
db_set(zVar, zQ, 0);
677709
zVal = zQ;
678710
}
679
- @ <input type="text" name="%s(zQParm)" value="%h(zVal)" size="%d(width)">
711
+ @ <input type="text" name="%s(zQParm)" value="%h(zVal)" size="%d(width)" />
680712
@ <b>%s(zLabel)</b>
681713
}
682714
683715
/*
684716
** Generate a text box for an attribute.
@@ -698,11 +730,12 @@
698730
db_set(zVar, zQ, 0);
699731
z = zQ;
700732
}
701733
if( rows>0 && cols>0 ){
702734
@ <textarea name="%s(zQP)" rows="%d(rows)" cols="%d(cols)">%h(z)</textarea>
703
- @ <b>%s(zLabel)</b>
735
+ if (zLabel && *zLabel)
736
+ @ <span class="textareaLabel">%s(zLabel)</span>
704737
}
705738
}
706739
707740
708741
/*
@@ -714,57 +747,57 @@
714747
login_needed();
715748
}
716749
717750
style_header("Access Control Settings");
718751
db_begin_transaction();
719
- @ <form action="%s(g.zBaseURL)/setup_access" method="POST">
752
+ @ <form action="%s(g.zBaseURL)/setup_access" method="post"><div>
720753
login_insert_csrf_secret();
721
- @ <hr>
754
+ @ <hr />
722755
onoff_attribute("Require password for local access",
723756
"localauth", "localauth", 0);
724757
@ <p>When enabled, the password sign-in is required for
725758
@ web access coming from 127.0.0.1. When disabled, web access
726759
@ from 127.0.0.1 is allows without any login - the user id is selected
727760
@ from the ~/.fossil database. Password login is always required
728761
@ for incoming web connections on internet addresses other than
729
- @ 127.0.0.1.</p></li>
762
+ @ 127.0.0.1.</p>
730763
731
- @ <hr>
764
+ @ <hr />
732765
onoff_attribute("Allow REMOTE_USER authentication",
733766
"remote_user_ok", "remote_user_ok", 0);
734767
@ <p>When enabled, if the REMOTE_USER environment variable is set to the
735768
@ login name of a valid user and no other login credentials are available,
736769
@ then the REMOTE_USER is accepted as an authenticated user.
737
- @ </p></li>
770
+ @ </p>
738771
739
- @ <hr>
772
+ @ <hr />
740773
entry_attribute("Login expiration time", 6, "cookie-expire", "cex", "8766");
741774
@ <p>The number of hours for which a login is valid. This must be a
742775
@ positive number. The default is 8760 hours which is approximately equal
743776
@ to a year.</p>
744777
745
- @ <hr>
778
+ @ <hr />
746779
entry_attribute("Download packet limit", 10, "max-download", "mxdwn",
747780
"5000000");
748781
@ <p>Fossil tries to limit out-bound sync, clone, and pull packets
749782
@ to this many bytes, uncompressed. If the client requires more data
750783
@ than this, then the client will issue multiple HTTP requests.
751784
@ Values below 1 million are not recommended. 5 million is a
752785
@ reasonable number.</p>
753786
754
- @ <hr>
787
+ @ <hr />
755788
onoff_attribute("Show javascript button to fill in CAPTCHA",
756789
"auto-captcha", "autocaptcha", 0);
757790
@ <p>When enabled, a button appears on the login screen for user
758791
@ "anonymous" that will automatically fill in the CAPTCHA password.
759792
@ This is less secure that forcing the user to do it manually, but is
760793
@ probably secure enough and it is certainly more convenient for
761794
@ anonymous users.</p>
762795
763
- @ <hr>
764
- @ <p><input type="submit" name="submit" value="Apply Changes"></p>
765
- @ </form>
796
+ @ <hr />
797
+ @ <p><input type="submit" name="submit" value="Apply Changes" /></p>
798
+ @ </div></form>
766799
db_end_transaction(0);
767800
style_footer();
768801
}
769802
770803
/*
@@ -776,42 +809,42 @@
776809
login_needed();
777810
}
778811
779812
style_header("Timeline Display Preferences");
780813
db_begin_transaction();
781
- @ <form action="%s(g.zBaseURL)/setup_timeline" method="POST">
814
+ @ <form action="%s(g.zBaseURL)/setup_timeline" method="post"><div>
782815
login_insert_csrf_secret();
783816
784
- @ <hr>
817
+ @ <hr />
785818
onoff_attribute("Allow block-markup in timeline",
786819
"timeline-block-markup", "tbm", 0);
787820
@ <p>In timeline displays, check-in comments can be displayed with or
788821
@ without block markup (paragraphs, tables, etc.)</p>
789822
790
- @ <hr>
823
+ @ <hr />
791824
onoff_attribute("Use Universal Coordinated Time (UTC)",
792825
"timeline-utc", "utc", 1);
793826
@ <p>Show times as UTC (also sometimes called Greenwich Mean Time (GMT) or
794827
@ Zulu) instead of in local time.</p>
795828
796
- @ <hr>
829
+ @ <hr />
797830
onoff_attribute("Show version differences by default",
798831
"show-version-diffs", "vdiff", 0);
799832
@ <p>On the version-information pages linked from the timeline can either
800833
@ show complete diffs of all file changes, or can just list the names of
801834
@ the files that have changed. Users can get to either page by
802835
@ clicking. This setting selects the default.</p>
803836
804
- @ <hr>
837
+ @ <hr />
805838
entry_attribute("Max timeline comment length", 6,
806839
"timeline-max-comment", "tmc", "0");
807840
@ <p>The maximum length of a comment to be displayed in a timeline.
808841
@ "0" there is no length limit.</p>
809842
810
- @ <hr>
811
- @ <p><input type="submit" name="submit" value="Apply Changes"></p>
812
- @ </form>
843
+ @ <hr />
844
+ @ <p><input type="submit" name="submit" value="Apply Changes" /></p>
845
+ @ </div></form>
813846
db_end_transaction(0);
814847
style_footer();
815848
}
816849
817850
/*
@@ -823,11 +856,11 @@
823856
login_needed();
824857
}
825858
826859
style_header("WWW Configuration");
827860
db_begin_transaction();
828
- @ <form action="%s(g.zBaseURL)/setup_config" method="POST">
861
+ @ <form action="%s(g.zBaseURL)/setup_config" method="post"><div>
829862
login_insert_csrf_secret();
830863
@ <hr />
831864
entry_attribute("Project Name", 60, "project-name", "pn", "");
832865
@ <p>Give your project a name so visitors know what this site is about.
833866
@ The project name will also be used as the RSS feed title.</p>
@@ -840,36 +873,37 @@
840873
entry_attribute("Index Page", 60, "index-page", "idxpg", "/home");
841874
@ <p>Enter the pathname of the page to display when the "Home" menu
842875
@ option is selected and when no pathname is
843876
@ specified in the URL. For example, if you visit the url:</p>
844877
@
845
- @ <blockquote>%h(g.zBaseURL)</blockquote>
878
+ @ <blockquote><p>%h(g.zBaseURL)</p></blockquote>
846879
@
847880
@ <p>And you have specified an index page of "/home" the above will
848881
@ automatically redirect to:</p>
849882
@
850
- @ <blockquote>%h(g.zBaseURL)/home</blockquote>
883
+ @ <blockquote><p>%h(g.zBaseURL)/home</p></blockquote>
851884
@
852885
@ <p>The default "/home" page displays a Wiki page with the same name
853886
@ as the Project Name specified above. Some sites prefer to redirect
854887
@ to a documentation page (ex: "/doc/tip/index.wiki") or to "/timeline".</p>
855888
@ <hr />
856889
onoff_attribute("Use HTML as wiki markup language",
857890
"wiki-use-html", "wiki-use-html", 0);
858
- @ <p>Use HTML as the wiki markup language. Wiki links will still be parsed but
859
- @ all other wiki formatting will be ignored. This option is helpful if you have
860
- @ chosen to use a rich HTML editor for wiki markup such as TinyMCE.</p>
891
+ @ <p>Use HTML as the wiki markup language. Wiki links will still be parsed
892
+ @ but all other wiki formatting will be ignored. This option is helpful
893
+ @ if you have chosen to use a rich HTML editor for wiki markup such as
894
+ @ TinyMCE.</p>
861895
@ <p><strong>CAUTION:</strong> when
862896
@ enabling, <i>all</i> HTML tags and attributes are accepted in the wiki.
863897
@ No sanitization is done. This means that it is very possible for malicious
864898
@ users to inject dangerous HTML, CSS and JavaScript code into your wiki.</p>
865899
@ <p>This should <strong>only</strong> be enabled when wiki editing is limited
866900
@ to trusted users. It should <strong>not</strong> be used on a publically
867901
@ editable wiki.</p>
868902
@ <hr />
869
- @ <p><input type="submit" name="submit" value="Apply Changes"></p>
870
- @ </form>
903
+ @ <p><input type="submit" name="submit" value="Apply Changes" /></p>
904
+ @ </div></form>
871905
db_end_transaction(0);
872906
style_footer();
873907
}
874908
875909
/*
@@ -892,30 +926,27 @@
892926
if( P("submit")!=0 ){
893927
db_end_transaction(0);
894928
cgi_redirect("setup_editcss");
895929
}
896930
style_header("Edit CSS");
897
- @ <form action="%s(g.zBaseURL)/setup_editcss" method="POST">
931
+ @ <form action="%s(g.zBaseURL)/setup_editcss" method="post"><div>
898932
login_insert_csrf_secret();
899933
@ Edit the CSS below:<br />
900934
textarea_attribute("", 40, 80, "css", "css", zDefaultCSS);
901935
@ <br />
902
- @ <input type="submit" name="submit" value="Apply Changes">
903
- @ <input type="submit" name="clear" value="Revert To Default">
904
- @ </form>
905
- @ <p><b>Note:</b> Press your browser Reload button after modifying the
906
- @ CSS in order to pull in the modified CSS file.</p>
907
- @ <hr>
936
+ @ <input type="submit" name="submit" value="Apply Changes" />
937
+ @ <input type="submit" name="clear" value="Revert To Default" />
938
+ @ </div></form>
939
+ @ <p><span class="note">Note:</span> Press your browser Reload button after
940
+ @ modifying the CSS in order to pull in the modified CSS file.</p>
941
+ @ <hr />
908942
@ The default CSS is shown below for reference. Other examples
909943
@ of CSS files can be seen on the <a href="setup_skin">skins page</a>.
910944
@ See also the <a href="setup_header">header</a> and
911945
@ <a href="setup_footer">footer</a> editing screens.
912946
@ <blockquote><pre>
913
- @ %h(zDefaultCSS)
914
- @ %h(zTableLabelValueCSS)
915
- @ %h(zDivSidebox)
916
- @ %h(zDivSideboxTitle)
947
+ cgi_append_default_css();
917948
@ </pre></blockquote>
918949
style_footer();
919950
db_end_transaction(0);
920951
}
921952
@@ -933,21 +964,21 @@
933964
cgi_replace_parameter("header", zDefaultHeader);
934965
}else{
935966
textarea_attribute(0, 0, 0, "header", "header", zDefaultHeader);
936967
}
937968
style_header("Edit Page Header");
938
- @ <form action="%s(g.zBaseURL)/setup_header" method="POST">
969
+ @ <form action="%s(g.zBaseURL)/setup_header" method="post"><div>
939970
login_insert_csrf_secret();
940971
@ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to
941972
@ generate the beginning of every page through start of the main
942973
@ menu.</p>
943974
textarea_attribute("", 40, 80, "header", "header", zDefaultHeader);
944975
@ <br />
945
- @ <input type="submit" name="submit" value="Apply Changes">
946
- @ <input type="submit" name="clear" value="Revert To Default">
947
- @ </form>
948
- @ <hr>
976
+ @ <input type="submit" name="submit" value="Apply Changes" />
977
+ @ <input type="submit" name="clear" value="Revert To Default" />
978
+ @ </div></form>
979
+ @ <hr />
949980
@ The default header is shown below for reference. Other examples
950981
@ of headers can be seen on the <a href="setup_skin">skins page</a>.
951982
@ See also the <a href="setup_editcss">CSS</a> and
952983
@ <a href="setup_footer">footer</a> editing screeens.
953984
@ <blockquote><pre>
@@ -971,20 +1002,20 @@
9711002
cgi_replace_parameter("footer", zDefaultFooter);
9721003
}else{
9731004
textarea_attribute(0, 0, 0, "footer", "footer", zDefaultFooter);
9741005
}
9751006
style_header("Edit Page Footer");
976
- @ <form action="%s(g.zBaseURL)/setup_footer" method="POST">
1007
+ @ <form action="%s(g.zBaseURL)/setup_footer" method="post"><div>
9771008
login_insert_csrf_secret();
9781009
@ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to
9791010
@ generate the end of every page.</p>
9801011
textarea_attribute("", 20, 80, "footer", "footer", zDefaultFooter);
9811012
@ <br />
982
- @ <input type="submit" name="submit" value="Apply Changes">
983
- @ <input type="submit" name="clear" value="Revert To Default">
984
- @ </form>
985
- @ <hr>
1013
+ @ <input type="submit" name="submit" value="Apply Changes" />
1014
+ @ <input type="submit" name="clear" value="Revert To Default" />
1015
+ @ </div></form>
1016
+ @ <hr />
9861017
@ The default footer is shown below for reference. Other examples
9871018
@ of footers can be seen on the <a href="setup_skin">skins page</a>.
9881019
@ See also the <a href="setup_editcss">CSS</a> and
9891020
@ <a href="setup_header">header</a> editing screens.
9901021
@ <blockquote><pre>
@@ -1034,31 +1065,31 @@
10341065
cgi_redirect("setup_logo");
10351066
}
10361067
style_header("Edit Project Logo");
10371068
@ <p>The current project logo has a MIME-Type of <b>%h(zMime)</b> and looks
10381069
@ like this:</p>
1039
- @ <blockquote><img src="%s(g.zTop)/logo" alt="logo"></blockquote>
1070
+ @ <blockquote><p><img src="%s(g.zTop)/logo" alt="logo" /></p></blockquote>
10401071
@
10411072
@ <p>The logo is accessible to all users at this URL:
10421073
@ <a href="%s(g.zBaseURL)/logo">%s(g.zBaseURL)/logo</a>.
10431074
@ The logo may or may not appear on each
10441075
@ page depending on the <a href="setup_editcss">CSS</a> and
10451076
@ <a href="setup_header">header setup</a>.</p>
10461077
@
1047
- @ <form action="%s(g.zBaseURL)/setup_logo" method="POST"
1048
- @ enctype="multipart/form-data">
1078
+ @ <form action="%s(g.zBaseURL)/setup_logo" method="post"
1079
+ @ enctype="multipart/form-data"><div>
10491080
@ <p>To set a new logo image, select a file to use as the logo using
10501081
@ the entry box below and then press the "Change Logo" button.</p>
10511082
login_insert_csrf_secret();
10521083
@ Logo Image file:
1053
- @ <input type="file" name="im" size="60" accepts="image/*"><br>
1054
- @ <input type="submit" name="set" value="Change Logo">
1055
- @ <input type="submit" name="clr" value="Revert To Default">
1056
- @ </form>
1057
- @
1058
- @ <p><b>Note:</b> Your browser has probably cached the logo image, so
1059
- @ you will probably need to press the Reload button on your browser after
1060
- @ changing the logo to provoke your browser to reload the new logo image.
1061
- @ </p>
1084
+ @ <input type="file" name="im" size="60" accept="image/*" /><br />
1085
+ @ <input type="submit" name="set" value="Change Logo" />
1086
+ @ <input type="submit" name="clr" value="Revert To Default" />
1087
+ @ </div></form>
1088
+ @
1089
+ @ <p><span class="note">Note:</span> Your browser has probably cached the
1090
+ @ logo image, so you will probably need to press the Reload button on your
1091
+ @ browser after changing the logo to provoke your browser to reload the new
1092
+ @ logo image. </p>
10621093
style_footer();
10631094
db_end_transaction(0);
10641095
}
10651096
--- src/setup.c
+++ src/setup.c
@@ -99,42 +99,40 @@
99 return;
100 }
101
102 style_submenu_element("Add", "Add User", "setup_uedit");
103 style_header("User List");
104 @ <table border="0" cellpadding="0" cellspacing="25">
105 @ <tr><td valign="top">
106 @ <b>Users:</b>
107 @ <table border="1" cellpadding="10"><tr><td>
108 @ <table cellspacing=0 cellpadding=0 border=0>
109 @ <tr>
110 @ <th align="right">User&nbsp;ID</th><td width="20">&nbsp;</td>
111 @ <th>Capabilities</th><td width="15">&nbsp;</td>
112 @ <th>Contact&nbsp;Info</th>
113 @ </tr>
114 db_prepare(&s, "SELECT uid, login, cap, info FROM user ORDER BY login");
115 while( db_step(&s)==SQLITE_ROW ){
116 const char *zCap = db_column_text(&s, 2);
117 if( strstr(zCap, "s") ) zCap = "s";
118 @ <tr>
119 @ <td align="right">
120 if( g.okAdmin && (zCap[0]!='s' || g.okSetup) ){
121 @ <a href="setup_uedit?id=%d(db_column_int(&s,0))">
122 }
123 @ <nobr>%h(db_column_text(&s,1))</nobr>
124 if( g.okAdmin ){
125 @ </a>
126 }
127 @ </td><td>&nbsp;&nbsp;&nbsp;</td>
128 @ <td align="center">%s(zCap)</td>
129 @ <td>&nbsp;&nbsp;&nbsp;</td>
130 @ <td align="left">%s(db_column_text(&s,3))</td>
131 @ </tr>
132 }
133 @ </table></td></tr></table>
134 @ <td valign="top">
135 @ <b>Notes:</b>
136 @ <ol>
137 @ <li><p>The permission flags are as follows:</p>
138 @ <table>
139 @ <tr><td valign="top"><b>a</b></td>
140 @ <td><i>Admin:</i> Create and delete users</td></tr>
@@ -181,31 +179,35 @@
181 @ user <tt>developer</tt></td></tr>
182 @ <tr><td valign="top"><b>w</b></td>
183 @ <td><i>Write-Tkt:</i> Edit tickets</td></tr>
184 @ <tr><td valign="top"><b>z</b></td>
185 @ <td><i>Zip download:</i> Download a baseline via the
186 @ <tt>/zip</tt> URL even without check<b>o</b>ut
187 @ and <b>h</b>istory permissions</td></tr>
 
188 @ </table>
189 @ </li>
190 @
191 @ <li><p>
192 @ Every user, logged in or not, inherits the privileges of <b>nobody</b>.
 
193 @ </p></li>
194 @
195 @ <li><p>
196 @ Any human can login as <b>anonymous</b> since the password is
197 @ clearly displayed on the login page for them to type. The purpose
198 @ of requiring anonymous to log in is to prevent access by spiders.
199 @ Every logged-in user inherits the combined privileges of
200 @ <b>anonymous</b> and
201 @ <b>nobody</b>.
202 @ </p></li>
203 @
204 @ <li><p>
205 @ Users with privilege <b>v</b> inherit the combined privileges of
206 @ <b>developer</b>, <b>anonymous</b>, and <b>nobody</b>.
 
 
207 @ </p></li>
208 @
209 @ </ol>
210 @ </td></tr></table>
211 style_footer();
@@ -323,12 +325,12 @@
323 }
324 if( uid>0 &&
325 db_exists("SELECT 1 FROM user WHERE login=%Q AND uid!=%d", zLogin, uid)
326 ){
327 style_header("User Creation Error");
328 @ <font color="red">Login "%h(zLogin)" is already used by a different
329 @ user.</font>
330 @
331 @ <p><a href="setup_uedit?id=%d(uid)">[Bummer]</a></p>
332 style_footer();
333 return;
334 }
@@ -353,65 +355,69 @@
353 if( uid ){
354 zLogin = db_text("", "SELECT login FROM user WHERE uid=%d", uid);
355 zInfo = db_text("", "SELECT info FROM user WHERE uid=%d", uid);
356 zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", uid);
357 zPw = db_text("", "SELECT pw FROM user WHERE uid=%d", uid);
358 if( strchr(zCap, 'a') ) oaa = " checked";
359 if( strchr(zCap, 'b') ) oab = " checked";
360 if( strchr(zCap, 'c') ) oac = " checked";
361 if( strchr(zCap, 'd') ) oad = " checked";
362 if( strchr(zCap, 'e') ) oae = " checked";
363 if( strchr(zCap, 'f') ) oaf = " checked";
364 if( strchr(zCap, 'g') ) oag = " checked";
365 if( strchr(zCap, 'h') ) oah = " checked";
366 if( strchr(zCap, 'i') ) oai = " checked";
367 if( strchr(zCap, 'j') ) oaj = " checked";
368 if( strchr(zCap, 'k') ) oak = " checked";
369 if( strchr(zCap, 'm') ) oam = " checked";
370 if( strchr(zCap, 'n') ) oan = " checked";
371 if( strchr(zCap, 'o') ) oao = " checked";
372 if( strchr(zCap, 'p') ) oap = " checked";
373 if( strchr(zCap, 'r') ) oar = " checked";
374 if( strchr(zCap, 's') ) oas = " checked";
375 if( strchr(zCap, 't') ) oat = " checked";
376 if( strchr(zCap, 'u') ) oau = " checked";
377 if( strchr(zCap, 'v') ) oav = " checked";
378 if( strchr(zCap, 'w') ) oaw = " checked";
379 if( strchr(zCap, 'z') ) oaz = " checked";
380 }
381
382 /* figure out inherited permissions */
383 memset(inherit, 0, sizeof(inherit));
384 if( strcmp(zLogin, "developer") ){
385 char *z1, *z2;
386 z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='developer'");
387 while( z1 && *z1 ){
388 inherit[0x7f & *(z1++)] = "<font color=\"red\">&bull;</font>";
 
389 }
390 free(z2);
391 }
392 if( strcmp(zLogin, "reader") ){
393 char *z1, *z2;
394 z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='reader'");
395 while( z1 && *z1 ){
396 inherit[0x7f & *(z1++)] = "<font color=\"black\">&bull;</font>";
 
397 }
398 free(z2);
399 }
400 if( strcmp(zLogin, "anonymous") ){
401 char *z1, *z2;
402 z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='anonymous'");
403 while( z1 && *z1 ){
404 inherit[0x7f & *(z1++)] = "<font color=\"blue\">&bull;</font>";
 
405 }
406 free(z2);
407 }
408 if( strcmp(zLogin, "nobody") ){
409 char *z1, *z2;
410 z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='nobody'");
411 while( z1 && *z1 ){
412 inherit[0x7f & *(z1++)] = "<font color=\"green\">&bull;</font>";
 
413 }
414 free(z2);
415 }
416
417 /* Begin generating the page
@@ -420,77 +426,79 @@
420 if( uid ){
421 style_header(mprintf("Edit User %h", zLogin));
422 }else{
423 style_header("Add A New User");
424 }
425 @ <table align="left" hspace="20" vspace="10"><tr><td>
426 @ <form action="%s(g.zPath)" method="POST">
427 login_insert_csrf_secret();
428 @ <table>
429 @ <tr>
430 @ <td align="right"><nobr>User ID:</nobr></td>
431 if( uid ){
432 @ <td>%d(uid) <input type="hidden" name="id" value="%d(uid)"></td>
433 }else{
434 @ <td>(new user)<input type="hidden" name="id" value=0></td>
435 }
436 @ </tr>
437 @ <tr>
438 @ <td align="right"><nobr>Login:</nobr></td>
439 @ <td><input type="text" name="login" value="%h(zLogin)"></td>
440 @ </tr>
441 @ <tr>
442 @ <td align="right"><nobr>Contact&nbsp;Info:</nobr></td>
443 @ <td><input type="text" name="info" size=40 value="%h(zInfo)"></td>
444 @ </tr>
445 @ <tr>
446 @ <td align="right" valign="top">Capabilities:</td>
447 @ <td>
448 #define B(x) inherit[x]
449 if( g.okSetup ){
450 @ <input type="checkbox" name="as"%s(oas)/>%s(B('s'))Setup<br>
451 }
452 @ <input type="checkbox" name="aa"%s(oaa)/>%s(B('a'))Admin<br>
453 @ <input type="checkbox" name="ad"%s(oad)/>%s(B('d'))Delete<br>
454 @ <input type="checkbox" name="ae"%s(oae)/>%s(B('e'))Email<br>
455 @ <input type="checkbox" name="ap"%s(oap)/>%s(B('p'))Password<br>
456 @ <input type="checkbox" name="ai"%s(oai)/>%s(B('i'))Check-In<br>
457 @ <input type="checkbox" name="ao"%s(oao)/>%s(B('o'))Check-Out<br>
458 @ <input type="checkbox" name="ah"%s(oah)/>%s(B('h'))History<br>
459 @ <input type="checkbox" name="au"%s(oau)/>%s(B('u'))Reader<br>
460 @ <input type="checkbox" name="av"%s(oav)/>%s(B('v'))Developer<br>
461 @ <input type="checkbox" name="ag"%s(oag)/>%s(B('g'))Clone<br>
462 @ <input type="checkbox" name="aj"%s(oaj)/>%s(B('j'))Read Wiki<br>
463 @ <input type="checkbox" name="af"%s(oaf)/>%s(B('f'))New Wiki<br>
464 @ <input type="checkbox" name="am"%s(oam)/>%s(B('m'))Append Wiki<br>
465 @ <input type="checkbox" name="ak"%s(oak)/>%s(B('k'))Write Wiki<br>
466 @ <input type="checkbox" name="ab"%s(oab)/>%s(B('b'))Attachments<br>
467 @ <input type="checkbox" name="ar"%s(oar)/>%s(B('r'))Read Ticket<br>
468 @ <input type="checkbox" name="an"%s(oan)/>%s(B('n'))New Ticket<br>
469 @ <input type="checkbox" name="ac"%s(oac)/>%s(B('c'))Append Ticket<br>
470 @ <input type="checkbox" name="aw"%s(oaw)/>%s(B('w'))Write Ticket<br>
471 @ <input type="checkbox" name="at"%s(oat)/>%s(B('t'))Ticket Report<br>
472 @ <input type="checkbox" name="az"%s(oaz)/>%s(B('z'))Download Zip
473 @ </td>
474 @ </tr>
475 @ <tr>
476 @ <td align="right">Password:</td>
477 if( zPw[0] ){
478 /* Obscure the password for all users */
479 @ <td><input type="password" name="pw" value="**********"></td>
480 }else{
481 /* Show an empty password as an empty input field */
482 @ <td><input type="password" name="pw" value=""></td>
483 }
484 @ </tr>
485 if( !higherUser ){
486 @ <tr>
487 @ <td>&nbsp</td>
488 @ <td><input type="submit" name="submit" value="Apply Changes">
489 @ </tr>
490 }
491 @ </table></td></tr></table>
 
 
492 @ <h2>Privileges And Capabilities:</h2>
493 @ <ul>
494 if( higherUser ){
495 @ <li><p><font color="blue"><b>
496 @ User %h(zLogin) has Setup privileges and you only have Admin privileges
@@ -497,95 +505,114 @@
497 @ so you are not permitted to make changes to %h(zLogin).
498 @ </b></font></p></li>
499 @
500 }
501 @ <li><p>
502 @ The <b>Setup</b> user can make arbitrary configuration changes.
503 @ An <b>Admin</b> user can add other users and change user privileges
 
504 @ and reset user passwords. Both automatically get all other privileges
505 @ listed below. Use these two settings with discretion.
506 @ </p></li>
507 @
508 @ <li><p>
509 @ The "<font color="green"><big>&bull;</big></font>" mark indicates
510 @ the privileges of "nobody" that are available to all users
511 @ regardless of whether or not they are logged in.
512 @ </p></li>
513 @
514 @ <li><p>
515 @ The "<font color="blue"><big>&bull;</big></font>" mark indicates
516 @ the privileges of "anonymous" that are inherited by all logged-in users.
517 @ </p></li>
518 @
519 @ <li><p>
520 @ The "<font color="red"><big>&bull;</big></font>" mark indicates
521 @ the privileges of "developer" that are inherited by all users with
522 @ the <b>Developer</b> privilege.
523 @ </p></li>
524 @
525 @ <li><p>
526 @ The "<font color="black"><big>&bull;</big></font>" mark indicates
527 @ the privileges of "reader" that are inherited by all users with
528 @ the <b>Reader</b> privilege.
529 @ </p></li>
530 @
531 @ <li><p>
532 @ The <b>Delete</b> privilege give the user the ability to erase
533 @ wiki, tickets, and attachments that have been added by anonymous
534 @ users. This capability is intended for deletion of spam. The
535 @ delete capability is only in effect for 24 hours after the item
536 @ is first posted. The Setup user can delete anything at any time.
537 @ </p></li>
538 @
539 @ <li><p>
540 @ The <b>History</b> privilege allows a user to see most hyperlinks.
541 @ This is recommended ON for most logged-in users but OFF for
542 @ user "nobody" to avoid problems with spiders trying to walk every
543 @ historical version of every baseline and file.
544 @ </p></li>
545 @
546 @ <li><p>
547 @ The <b>Zip</b> privilege allows a user to see the "download as ZIP"
548 @ hyperlink and permits access to the <tt>/zip</tt> page. This allows
549 @ users to download ZIP archives without granting other rights like
550 @ <b>Read</b> or <b>History</b>. This privilege is recommended for
551 @ user <b>nobody</b> so that automatic package downloaders can obtain
552 @ the sources without going through the login procedure.
553 @ </p></li>
554 @
555 @ <li><p>
556 @ The <b>Check-in</b> privilege allows remote users to "push".
557 @ The <b>Check-out</b> privilege allows remote users to "pull".
558 @ The <b>Clone</b> privilege allows remote users to "clone".
559 @ </li><p>
560 @
561 @ <li><p>
562 @ The <b>Read Wiki</b>, <b>New Wiki</b>, <b>Append Wiki</b>, and
563 @ <b>Write Wiki</b> privileges control access to wiki pages. The
564 @ <b>Read Ticket</b>, <b>New Ticket</b>, <b>Append Ticket</b>, and
565 @ <b>Write Ticket</b> privileges control access to trouble tickets.
566 @ The <b>Ticket Report</b> privilege allows the user to create or edit
567 @ ticket report formats.
568 @ </p></li>
569 @
570 @ <li><p>
571 @ Users with the <b>Password</b> privilege are allowed to change their
572 @ own password. Recommended ON for most users but OFF for special
573 @ users "developer", "anonymous", and "nobody".
574 @ </p></li>
575 @
576 @ <li><p>
577 @ The <b>EMail</b> privilege allows the display of sensitive information
578 @ such as the email address of users and contact information on tickets.
579 @ Recommended OFF for "anonymous" and for "nobody" but ON for
580 @ "developer".
581 @ </p></li>
582 @
583 @ <li><p>
584 @ The <b>Attachment</b> privilege is needed in order to add attachments
585 @ to tickets or wiki. Write privilege on the ticket or wiki is also
586 @ required.</p></li>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
587 @
588 @ <li><p>
589 @ Login is prohibited if the password is an empty string.
590 @ </p></li>
591 @ </ul>
@@ -592,42 +619,46 @@
592 @
593 @ <h2>Special Logins</h2>
594 @
595 @ <ul>
596 @ <li><p>
597 @ No login is required for user "<b>nobody</b>". The capabilities
598 @ of the <b>nobody</b> user are inherited by all users, regardless of
599 @ whether or not they are logged in. To disable universal access
600 @ to the repository, make sure no user named "<b>nobody</b>" exists or
601 @ that the <b>nobody</b> user has no capabilities enabled.
602 @ The password for <b>nobody</b> is ignore. To avoid problems with
603 @ spiders overloading the server, it is recommended
604 @ that the 'h' (History) capability be turned off for the <b>nobody</b>
605 @ user.
606 @ </p></li>
607 @
608 @ <li><p>
609 @ Login is required for user "<b>anonymous</b>" but the password
610 @ is displayed on the login screen beside the password entry box
611 @ so anybody who can read should be able to login as anonymous.
612 @ On the other hand, spiders and web-crawlers will typically not
613 @ be able to login. Set the capabilities of the anonymous user
614 @ to things that you want any human to be able to do, but not any
615 @ spider. Every other logged-in user inherits the privileges of
616 @ <b>anonymous</b>.
617 @ </p></li>
618 @
619 @ <li><p>
620 @ The "<b>developer</b>" user is intended as a template for trusted users
621 @ with check-in privileges. When adding new trusted users, simply
622 @ select the <b>Developer</b> privilege to cause the new user to inherit
623 @ all privileges of the "developer" user. Similarly, the "<b>reader</b>"
624 @ user is a template for users who are allowed more access than anonymous,
625 @ but less than a developer.
626 @ </p></li>
627 @ </ul>
628 @ </form>
 
 
 
 
629 style_footer();
630 }
631
632
633 /*
@@ -651,13 +682,14 @@
651 db_set(zVar, iQ ? "1" : "0", 0);
652 iVal = iQ;
653 }
654 }
655 if( iVal ){
656 @ <input type="checkbox" name="%s(zQParm)" checked><b>%s(zLabel)</b></input>
 
657 }else{
658 @ <input type="checkbox" name="%s(zQParm)"><b>%s(zLabel)</b></input>
659 }
660 }
661
662 /*
663 ** Generate an entry box for an attribute.
@@ -674,11 +706,11 @@
674 if( zQ && strcmp(zQ,zVal)!=0 ){
675 login_verify_csrf_secret();
676 db_set(zVar, zQ, 0);
677 zVal = zQ;
678 }
679 @ <input type="text" name="%s(zQParm)" value="%h(zVal)" size="%d(width)">
680 @ <b>%s(zLabel)</b>
681 }
682
683 /*
684 ** Generate a text box for an attribute.
@@ -698,11 +730,12 @@
698 db_set(zVar, zQ, 0);
699 z = zQ;
700 }
701 if( rows>0 && cols>0 ){
702 @ <textarea name="%s(zQP)" rows="%d(rows)" cols="%d(cols)">%h(z)</textarea>
703 @ <b>%s(zLabel)</b>
 
704 }
705 }
706
707
708 /*
@@ -714,57 +747,57 @@
714 login_needed();
715 }
716
717 style_header("Access Control Settings");
718 db_begin_transaction();
719 @ <form action="%s(g.zBaseURL)/setup_access" method="POST">
720 login_insert_csrf_secret();
721 @ <hr>
722 onoff_attribute("Require password for local access",
723 "localauth", "localauth", 0);
724 @ <p>When enabled, the password sign-in is required for
725 @ web access coming from 127.0.0.1. When disabled, web access
726 @ from 127.0.0.1 is allows without any login - the user id is selected
727 @ from the ~/.fossil database. Password login is always required
728 @ for incoming web connections on internet addresses other than
729 @ 127.0.0.1.</p></li>
730
731 @ <hr>
732 onoff_attribute("Allow REMOTE_USER authentication",
733 "remote_user_ok", "remote_user_ok", 0);
734 @ <p>When enabled, if the REMOTE_USER environment variable is set to the
735 @ login name of a valid user and no other login credentials are available,
736 @ then the REMOTE_USER is accepted as an authenticated user.
737 @ </p></li>
738
739 @ <hr>
740 entry_attribute("Login expiration time", 6, "cookie-expire", "cex", "8766");
741 @ <p>The number of hours for which a login is valid. This must be a
742 @ positive number. The default is 8760 hours which is approximately equal
743 @ to a year.</p>
744
745 @ <hr>
746 entry_attribute("Download packet limit", 10, "max-download", "mxdwn",
747 "5000000");
748 @ <p>Fossil tries to limit out-bound sync, clone, and pull packets
749 @ to this many bytes, uncompressed. If the client requires more data
750 @ than this, then the client will issue multiple HTTP requests.
751 @ Values below 1 million are not recommended. 5 million is a
752 @ reasonable number.</p>
753
754 @ <hr>
755 onoff_attribute("Show javascript button to fill in CAPTCHA",
756 "auto-captcha", "autocaptcha", 0);
757 @ <p>When enabled, a button appears on the login screen for user
758 @ "anonymous" that will automatically fill in the CAPTCHA password.
759 @ This is less secure that forcing the user to do it manually, but is
760 @ probably secure enough and it is certainly more convenient for
761 @ anonymous users.</p>
762
763 @ <hr>
764 @ <p><input type="submit" name="submit" value="Apply Changes"></p>
765 @ </form>
766 db_end_transaction(0);
767 style_footer();
768 }
769
770 /*
@@ -776,42 +809,42 @@
776 login_needed();
777 }
778
779 style_header("Timeline Display Preferences");
780 db_begin_transaction();
781 @ <form action="%s(g.zBaseURL)/setup_timeline" method="POST">
782 login_insert_csrf_secret();
783
784 @ <hr>
785 onoff_attribute("Allow block-markup in timeline",
786 "timeline-block-markup", "tbm", 0);
787 @ <p>In timeline displays, check-in comments can be displayed with or
788 @ without block markup (paragraphs, tables, etc.)</p>
789
790 @ <hr>
791 onoff_attribute("Use Universal Coordinated Time (UTC)",
792 "timeline-utc", "utc", 1);
793 @ <p>Show times as UTC (also sometimes called Greenwich Mean Time (GMT) or
794 @ Zulu) instead of in local time.</p>
795
796 @ <hr>
797 onoff_attribute("Show version differences by default",
798 "show-version-diffs", "vdiff", 0);
799 @ <p>On the version-information pages linked from the timeline can either
800 @ show complete diffs of all file changes, or can just list the names of
801 @ the files that have changed. Users can get to either page by
802 @ clicking. This setting selects the default.</p>
803
804 @ <hr>
805 entry_attribute("Max timeline comment length", 6,
806 "timeline-max-comment", "tmc", "0");
807 @ <p>The maximum length of a comment to be displayed in a timeline.
808 @ "0" there is no length limit.</p>
809
810 @ <hr>
811 @ <p><input type="submit" name="submit" value="Apply Changes"></p>
812 @ </form>
813 db_end_transaction(0);
814 style_footer();
815 }
816
817 /*
@@ -823,11 +856,11 @@
823 login_needed();
824 }
825
826 style_header("WWW Configuration");
827 db_begin_transaction();
828 @ <form action="%s(g.zBaseURL)/setup_config" method="POST">
829 login_insert_csrf_secret();
830 @ <hr />
831 entry_attribute("Project Name", 60, "project-name", "pn", "");
832 @ <p>Give your project a name so visitors know what this site is about.
833 @ The project name will also be used as the RSS feed title.</p>
@@ -840,36 +873,37 @@
840 entry_attribute("Index Page", 60, "index-page", "idxpg", "/home");
841 @ <p>Enter the pathname of the page to display when the "Home" menu
842 @ option is selected and when no pathname is
843 @ specified in the URL. For example, if you visit the url:</p>
844 @
845 @ <blockquote>%h(g.zBaseURL)</blockquote>
846 @
847 @ <p>And you have specified an index page of "/home" the above will
848 @ automatically redirect to:</p>
849 @
850 @ <blockquote>%h(g.zBaseURL)/home</blockquote>
851 @
852 @ <p>The default "/home" page displays a Wiki page with the same name
853 @ as the Project Name specified above. Some sites prefer to redirect
854 @ to a documentation page (ex: "/doc/tip/index.wiki") or to "/timeline".</p>
855 @ <hr />
856 onoff_attribute("Use HTML as wiki markup language",
857 "wiki-use-html", "wiki-use-html", 0);
858 @ <p>Use HTML as the wiki markup language. Wiki links will still be parsed but
859 @ all other wiki formatting will be ignored. This option is helpful if you have
860 @ chosen to use a rich HTML editor for wiki markup such as TinyMCE.</p>
 
861 @ <p><strong>CAUTION:</strong> when
862 @ enabling, <i>all</i> HTML tags and attributes are accepted in the wiki.
863 @ No sanitization is done. This means that it is very possible for malicious
864 @ users to inject dangerous HTML, CSS and JavaScript code into your wiki.</p>
865 @ <p>This should <strong>only</strong> be enabled when wiki editing is limited
866 @ to trusted users. It should <strong>not</strong> be used on a publically
867 @ editable wiki.</p>
868 @ <hr />
869 @ <p><input type="submit" name="submit" value="Apply Changes"></p>
870 @ </form>
871 db_end_transaction(0);
872 style_footer();
873 }
874
875 /*
@@ -892,30 +926,27 @@
892 if( P("submit")!=0 ){
893 db_end_transaction(0);
894 cgi_redirect("setup_editcss");
895 }
896 style_header("Edit CSS");
897 @ <form action="%s(g.zBaseURL)/setup_editcss" method="POST">
898 login_insert_csrf_secret();
899 @ Edit the CSS below:<br />
900 textarea_attribute("", 40, 80, "css", "css", zDefaultCSS);
901 @ <br />
902 @ <input type="submit" name="submit" value="Apply Changes">
903 @ <input type="submit" name="clear" value="Revert To Default">
904 @ </form>
905 @ <p><b>Note:</b> Press your browser Reload button after modifying the
906 @ CSS in order to pull in the modified CSS file.</p>
907 @ <hr>
908 @ The default CSS is shown below for reference. Other examples
909 @ of CSS files can be seen on the <a href="setup_skin">skins page</a>.
910 @ See also the <a href="setup_header">header</a> and
911 @ <a href="setup_footer">footer</a> editing screens.
912 @ <blockquote><pre>
913 @ %h(zDefaultCSS)
914 @ %h(zTableLabelValueCSS)
915 @ %h(zDivSidebox)
916 @ %h(zDivSideboxTitle)
917 @ </pre></blockquote>
918 style_footer();
919 db_end_transaction(0);
920 }
921
@@ -933,21 +964,21 @@
933 cgi_replace_parameter("header", zDefaultHeader);
934 }else{
935 textarea_attribute(0, 0, 0, "header", "header", zDefaultHeader);
936 }
937 style_header("Edit Page Header");
938 @ <form action="%s(g.zBaseURL)/setup_header" method="POST">
939 login_insert_csrf_secret();
940 @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to
941 @ generate the beginning of every page through start of the main
942 @ menu.</p>
943 textarea_attribute("", 40, 80, "header", "header", zDefaultHeader);
944 @ <br />
945 @ <input type="submit" name="submit" value="Apply Changes">
946 @ <input type="submit" name="clear" value="Revert To Default">
947 @ </form>
948 @ <hr>
949 @ The default header is shown below for reference. Other examples
950 @ of headers can be seen on the <a href="setup_skin">skins page</a>.
951 @ See also the <a href="setup_editcss">CSS</a> and
952 @ <a href="setup_footer">footer</a> editing screeens.
953 @ <blockquote><pre>
@@ -971,20 +1002,20 @@
971 cgi_replace_parameter("footer", zDefaultFooter);
972 }else{
973 textarea_attribute(0, 0, 0, "footer", "footer", zDefaultFooter);
974 }
975 style_header("Edit Page Footer");
976 @ <form action="%s(g.zBaseURL)/setup_footer" method="POST">
977 login_insert_csrf_secret();
978 @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to
979 @ generate the end of every page.</p>
980 textarea_attribute("", 20, 80, "footer", "footer", zDefaultFooter);
981 @ <br />
982 @ <input type="submit" name="submit" value="Apply Changes">
983 @ <input type="submit" name="clear" value="Revert To Default">
984 @ </form>
985 @ <hr>
986 @ The default footer is shown below for reference. Other examples
987 @ of footers can be seen on the <a href="setup_skin">skins page</a>.
988 @ See also the <a href="setup_editcss">CSS</a> and
989 @ <a href="setup_header">header</a> editing screens.
990 @ <blockquote><pre>
@@ -1034,31 +1065,31 @@
1034 cgi_redirect("setup_logo");
1035 }
1036 style_header("Edit Project Logo");
1037 @ <p>The current project logo has a MIME-Type of <b>%h(zMime)</b> and looks
1038 @ like this:</p>
1039 @ <blockquote><img src="%s(g.zTop)/logo" alt="logo"></blockquote>
1040 @
1041 @ <p>The logo is accessible to all users at this URL:
1042 @ <a href="%s(g.zBaseURL)/logo">%s(g.zBaseURL)/logo</a>.
1043 @ The logo may or may not appear on each
1044 @ page depending on the <a href="setup_editcss">CSS</a> and
1045 @ <a href="setup_header">header setup</a>.</p>
1046 @
1047 @ <form action="%s(g.zBaseURL)/setup_logo" method="POST"
1048 @ enctype="multipart/form-data">
1049 @ <p>To set a new logo image, select a file to use as the logo using
1050 @ the entry box below and then press the "Change Logo" button.</p>
1051 login_insert_csrf_secret();
1052 @ Logo Image file:
1053 @ <input type="file" name="im" size="60" accepts="image/*"><br>
1054 @ <input type="submit" name="set" value="Change Logo">
1055 @ <input type="submit" name="clr" value="Revert To Default">
1056 @ </form>
1057 @
1058 @ <p><b>Note:</b> Your browser has probably cached the logo image, so
1059 @ you will probably need to press the Reload button on your browser after
1060 @ changing the logo to provoke your browser to reload the new logo image.
1061 @ </p>
1062 style_footer();
1063 db_end_transaction(0);
1064 }
1065
--- src/setup.c
+++ src/setup.c
@@ -99,42 +99,40 @@
99 return;
100 }
101
102 style_submenu_element("Add", "Add User", "setup_uedit");
103 style_header("User List");
104 @ <table class="usetupLayoutTable">
105 @ <tr><td class="usetupColumnLayout">
106 @ <span class="note">Users:</span>
107 @ <table class="usetupUserList">
 
108 @ <tr>
109 @ <th class="usetupListUser" style="text-align: right;padding-right: 20px;">User&nbsp;ID</th>
110 @ <th class="usetupListCap" style="text-align: center;padding-right: 15px;">Capabilities</th>
111 @ <th class="usetupListCon" style="text-align: left;">Contact&nbsp;Info</th>
112 @ </tr>
113 db_prepare(&s, "SELECT uid, login, cap, info FROM user ORDER BY login");
114 while( db_step(&s)==SQLITE_ROW ){
115 const char *zCap = db_column_text(&s, 2);
116 if( strstr(zCap, "s") ) zCap = "s";
117 @ <tr>
118 @ <td class="usetupListUser" style="text-align: right;padding-right: 20px;white-space:nowrap;">
119 if( g.okAdmin && (zCap[0]!='s' || g.okSetup) ){
120 @ <a href="setup_uedit?id=%d(db_column_int(&s,0))">
121 }
122 @ %h(db_column_text(&s,1))
123 if( g.okAdmin ){
124 @ </a>
125 }
126 @ </td>
127 @ <td class="usetupListCap" style="text-align: center;padding-right: 15px;">%s(zCap)</td>
128 @ <td class="usetupListCon" style="text-align: left;">%s(db_column_text(&s,3))</td>
 
129 @ </tr>
130 }
131 @ </table>
132 @ </td><td class="usetupColumnLayout">
133 @ <span class="note">Notes:</span>
134 @ <ol>
135 @ <li><p>The permission flags are as follows:</p>
136 @ <table>
137 @ <tr><td valign="top"><b>a</b></td>
138 @ <td><i>Admin:</i> Create and delete users</td></tr>
@@ -181,31 +179,35 @@
179 @ user <tt>developer</tt></td></tr>
180 @ <tr><td valign="top"><b>w</b></td>
181 @ <td><i>Write-Tkt:</i> Edit tickets</td></tr>
182 @ <tr><td valign="top"><b>z</b></td>
183 @ <td><i>Zip download:</i> Download a baseline via the
184 @ <tt>/zip</tt> URL even without
185 @ check<span class="capability">o</span>ut
186 @ and <span class="capability">h</span>istory permissions</td></tr>
187 @ </table>
188 @ </li>
189 @
190 @ <li><p>
191 @ Every user, logged in or not, inherits the privileges of
192 @ <span class="usertype">nobody</span>.
193 @ </p></li>
194 @
195 @ <li><p>
196 @ Any human can login as <span class="usertype">anonymous</span> since the
197 @ password is clearly displayed on the login page for them to type. The
198 @ purpose of requiring anonymous to log in is to prevent access by spiders.
199 @ Every logged-in user inherits the combined privileges of
200 @ <span class="usertype">anonymous</span> and
201 @ <span class="usertype">nobody</span>.
202 @ </p></li>
203 @
204 @ <li><p>
205 @ Users with privilege <span class="capability">v</span> inherit the combined
206 @ privileges of <span class="usertype">developer</span>,
207 @ <span class="usertype">anonymous</span>, and
208 @ <span class="usertype">nobody</span>.
209 @ </p></li>
210 @
211 @ </ol>
212 @ </td></tr></table>
213 style_footer();
@@ -323,12 +325,12 @@
325 }
326 if( uid>0 &&
327 db_exists("SELECT 1 FROM user WHERE login=%Q AND uid!=%d", zLogin, uid)
328 ){
329 style_header("User Creation Error");
330 @ <span class="loginError">Login "%h(zLogin)" is already used by
331 @ a different user.</span>
332 @
333 @ <p><a href="setup_uedit?id=%d(uid)">[Bummer]</a></p>
334 style_footer();
335 return;
336 }
@@ -353,65 +355,69 @@
355 if( uid ){
356 zLogin = db_text("", "SELECT login FROM user WHERE uid=%d", uid);
357 zInfo = db_text("", "SELECT info FROM user WHERE uid=%d", uid);
358 zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", uid);
359 zPw = db_text("", "SELECT pw FROM user WHERE uid=%d", uid);
360 if( strchr(zCap, 'a') ) oaa = " checked=\"checked\"";
361 if( strchr(zCap, 'b') ) oab = " checked=\"checked\"";
362 if( strchr(zCap, 'c') ) oac = " checked=\"checked\"";
363 if( strchr(zCap, 'd') ) oad = " checked=\"checked\"";
364 if( strchr(zCap, 'e') ) oae = " checked=\"checked\"";
365 if( strchr(zCap, 'f') ) oaf = " checked=\"checked\"";
366 if( strchr(zCap, 'g') ) oag = " checked=\"checked\"";
367 if( strchr(zCap, 'h') ) oah = " checked=\"checked\"";
368 if( strchr(zCap, 'i') ) oai = " checked=\"checked\"";
369 if( strchr(zCap, 'j') ) oaj = " checked=\"checked\"";
370 if( strchr(zCap, 'k') ) oak = " checked=\"checked\"";
371 if( strchr(zCap, 'm') ) oam = " checked=\"checked\"";
372 if( strchr(zCap, 'n') ) oan = " checked=\"checked\"";
373 if( strchr(zCap, 'o') ) oao = " checked=\"checked\"";
374 if( strchr(zCap, 'p') ) oap = " checked=\"checked\"";
375 if( strchr(zCap, 'r') ) oar = " checked=\"checked\"";
376 if( strchr(zCap, 's') ) oas = " checked=\"checked\"";
377 if( strchr(zCap, 't') ) oat = " checked=\"checked\"";
378 if( strchr(zCap, 'u') ) oau = " checked=\"checked\"";
379 if( strchr(zCap, 'v') ) oav = " checked=\"checked\"";
380 if( strchr(zCap, 'w') ) oaw = " checked=\"checked\"";
381 if( strchr(zCap, 'z') ) oaz = " checked=\"checked\"";
382 }
383
384 /* figure out inherited permissions */
385 memset(inherit, 0, sizeof(inherit));
386 if( strcmp(zLogin, "developer") ){
387 char *z1, *z2;
388 z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='developer'");
389 while( z1 && *z1 ){
390 inherit[0x7f & *(z1++)] =
391 "<span class=\"ueditInheritDeveloper\">&bull;</span>";
392 }
393 free(z2);
394 }
395 if( strcmp(zLogin, "reader") ){
396 char *z1, *z2;
397 z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='reader'");
398 while( z1 && *z1 ){
399 inherit[0x7f & *(z1++)] =
400 "<span class=\"ueditInheritReader\">&bull;</span>";
401 }
402 free(z2);
403 }
404 if( strcmp(zLogin, "anonymous") ){
405 char *z1, *z2;
406 z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='anonymous'");
407 while( z1 && *z1 ){
408 inherit[0x7f & *(z1++)] =
409 "<span class=\"ueditInheritAnonymous\">&bull;</span>";
410 }
411 free(z2);
412 }
413 if( strcmp(zLogin, "nobody") ){
414 char *z1, *z2;
415 z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='nobody'");
416 while( z1 && *z1 ){
417 inherit[0x7f & *(z1++)] =
418 "<span class=\"ueditInheritNobody\">&bull;</span>";
419 }
420 free(z2);
421 }
422
423 /* Begin generating the page
@@ -420,77 +426,79 @@
426 if( uid ){
427 style_header(mprintf("Edit User %h", zLogin));
428 }else{
429 style_header("Add A New User");
430 }
431 @ <div class="ueditCapBox">
432 @ <form action="%s(g.zPath)" method="post"><div>
433 login_insert_csrf_secret();
434 @ <table>
435 @ <tr>
436 @ <td class="usetupEditLabel">User ID:</td>
437 if( uid ){
438 @ <td>%d(uid) <input type="hidden" name="id" value="%d(uid)" /></td>
439 }else{
440 @ <td>(new user)<input type="hidden" name="id" value="0" /></td>
441 }
442 @ </tr>
443 @ <tr>
444 @ <td class="usetupEditLabel">Login:</td>
445 @ <td><input type="text" name="login" value="%h(zLogin)" /></td>
446 @ </tr>
447 @ <tr>
448 @ <td class="usetupEditLabel">Contact&nbsp;Info:</td>
449 @ <td><input type="text" name="info" size="40" value="%h(zInfo)" /></td>
450 @ </tr>
451 @ <tr>
452 @ <td class="usetupEditLabel">Capabilities:</td>
453 @ <td>
454 #define B(x) inherit[x]
455 if( g.okSetup ){
456 @ <input type="checkbox" name="as"%s(oas) />%s(B('s'))Setup<br />
457 }
458 @ <input type="checkbox" name="aa"%s(oaa) />%s(B('a'))Admin<br />
459 @ <input type="checkbox" name="ad"%s(oad) />%s(B('d'))Delete<br />
460 @ <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br />
461 @ <input type="checkbox" name="ap"%s(oap) />%s(B('p'))Password<br />
462 @ <input type="checkbox" name="ai"%s(oai) />%s(B('i'))Check-In<br />
463 @ <input type="checkbox" name="ao"%s(oao) />%s(B('o'))Check-Out<br />
464 @ <input type="checkbox" name="ah"%s(oah) />%s(B('h'))History<br />
465 @ <input type="checkbox" name="au"%s(oau) />%s(B('u'))Reader<br />
466 @ <input type="checkbox" name="av"%s(oav) />%s(B('v'))Developer<br />
467 @ <input type="checkbox" name="ag"%s(oag) />%s(B('g'))Clone<br />
468 @ <input type="checkbox" name="aj"%s(oaj) />%s(B('j'))Read Wiki<br />
469 @ <input type="checkbox" name="af"%s(oaf) />%s(B('f'))New Wiki<br />
470 @ <input type="checkbox" name="am"%s(oam) />%s(B('m'))Append Wiki<br />
471 @ <input type="checkbox" name="ak"%s(oak) />%s(B('k'))Write Wiki<br />
472 @ <input type="checkbox" name="ab"%s(oab) />%s(B('b'))Attachments<br />
473 @ <input type="checkbox" name="ar"%s(oar) />%s(B('r'))Read Ticket<br />
474 @ <input type="checkbox" name="an"%s(oan) />%s(B('n'))New Ticket<br />
475 @ <input type="checkbox" name="ac"%s(oac) />%s(B('c'))Append Ticket<br />
476 @ <input type="checkbox" name="aw"%s(oaw) />%s(B('w'))Write Ticket<br />
477 @ <input type="checkbox" name="at"%s(oat) />%s(B('t'))Ticket Report<br />
478 @ <input type="checkbox" name="az"%s(oaz) />%s(B('z'))Download Zip
479 @ </td>
480 @ </tr>
481 @ <tr>
482 @ <td align="right">Password:</td>
483 if( zPw[0] ){
484 /* Obscure the password for all users */
485 @ <td><input type="password" name="pw" value="**********" /></td>
486 }else{
487 /* Show an empty password as an empty input field */
488 @ <td><input type="password" name="pw" value="" /></td>
489 }
490 @ </tr>
491 if( !higherUser ){
492 @ <tr>
493 @ <td>&nbsp;</td>
494 @ <td><input type="submit" name="submit" value="Apply Changes" /></td>
495 @ </tr>
496 }
497 @ </table>
498 @ </div></form>
499 @ </div>
500 @ <h2>Privileges And Capabilities:</h2>
501 @ <ul>
502 if( higherUser ){
503 @ <li><p><font color="blue"><b>
504 @ User %h(zLogin) has Setup privileges and you only have Admin privileges
@@ -497,95 +505,114 @@
505 @ so you are not permitted to make changes to %h(zLogin).
506 @ </b></font></p></li>
507 @
508 }
509 @ <li><p>
510 @ The <span class="capability">Setup</span> user can make arbitrary
511 @ configuration changes. An <span class="usertype">Admin</span> user
512 @ can add other users and change user privileges
513 @ and reset user passwords. Both automatically get all other privileges
514 @ listed below. Use these two settings with discretion.
515 @ </p></li>
516 @
517 @ <li><p>
518 @ The "<span class="ueditInheritNobody"><big>&bull;</big></span>" mark
519 @ indicates the privileges of <span class="usertype">nobody</span> that
520 @ are available to all users regardless of whether or not they are logged in.
521 @ </p></li>
522 @
523 @ <li><p>
524 @ The "<span class="ueditInheritAnonymous"><big>&bull;</big></span>" mark
525 @ indicates the privileges of <span class="usertype">anonymous</span> that
526 @ are inherited by all logged-in users.
527 @ </p></li>
528 @
529 @ <li><p>
530 @ The "<span class="ueditInheritDeveloper"><big>&bull;</big></span>" mark
531 @ indicates the privileges of <span class="usertype">developer</span> that
532 @ are inherited by all users with the
533 @ <span class="capability">Developer</span> privilege.
534 @ </p></li>
535 @
536 @ <li><p>
537 @ The "<span class="ueditInheritReader"><big>&bull;</big></span>" mark
538 @ indicates the privileges of <span class="usertype">reader</span> that
539 @ are inherited by all users with the <span class="capability">Reader</span>
540 @ privilege.
541 @ </p></li>
542 @
543 @ <li><p>
544 @ The <span class="capability">Delete</span> privilege give the user the
545 @ ability to erase wiki, tickets, and attachments that have been added
546 @ by anonymous users. This capability is intended for deletion of spam.
547 @ The delete capability is only in effect for 24 hours after the item
548 @ is first posted. The <span class="usertype">Setup</span> user can
549 @ delete anything at any time.
550 @ </p></li>
551 @
552 @ <li><p>
553 @ The <span class="capability">History</span> privilege allows a user
554 @ to see most hyperlinks. This is recommended ON for most logged-in users
555 @ but OFF for user "nobody" to avoid problems with spiders trying to walk
556 @ every historical version of every baseline and file.
557 @ </p></li>
558 @
559 @ <li><p>
560 @ The <span class="capability">Zip</span> privilege allows a user to
561 @ see the "download as ZIP"
562 @ hyperlink and permits access to the <tt>/zip</tt> page. This allows
563 @ users to download ZIP archives without granting other rights like
564 @ <span class="capability">Read</span> or
565 @ <span class="capability">History</span>. This privilege is recommended for
566 @ user <span class="usertype">nobody</span> so that automatic package
567 @ downloaders can obtain the sources without going through the login
568 @ procedure.
569 @ </p></li>
570 @
571 @ <li><p>
572 @ The <span class="capability">Check-in</span> privilege allows remote
573 @ users to "push". The <span class="capability">Check-out</span> privilege
574 @ allows remote users to "pull". The <span class="capability">Clone</span>
575 @ privilege allows remote users to "clone".
576 @ </p></li>
577 @
578 @ <li><p>
579 @ The <span class="capability">Read Wiki</span>,
580 @ <span class="capability">New Wiki</span>,
581 @ <span class="capability">Append Wiki</span>, and
582 @ <b>Write Wiki</b> privileges control access to wiki pages. The
583 @ <span class="capability">Read Ticket</span>,
584 @ <span class="capability">New Ticket</span>,
585 @ <span class="capability">Append Ticket</span>, and
586 @ <span class="capability">Write Ticket</span> privileges control access
587 @ to trouble tickets.
588 @ The <span class="capability">Ticket Report</span> privilege allows
589 @ the user to create or edit ticket report formats.
590 @ </p></li>
591 @
592 @ <li><p>
593 @ Users with the <span class="capability">Password</span> privilege
594 @ are allowed to change their own password. Recommended ON for most
595 @ users but OFF for special users <span class="usertype">developer</span>,
596 @ <span class="usertype">anonymous</span>,
597 @ and <span class="usertype">nobody</span>.
598 @ </p></li>
599 @
600 @ <li><p>
601 @ The <span class="capability">EMail</span> privilege allows the display of
602 @ sensitive information such as the email address of users and contact
603 @ information on tickets. Recommended OFF for
604 @ <span class="usertype">anonymousy</span> and for
605 @ <span class="usertype">nobody</span> but ON for
606 @ <span class="usertype">developer</span>.
607 @ </p></li>
608 @
609 @ <li><p>
610 @ The <span class="capability">Attachment</span> privilege is needed in
611 @ order to add attachments to tickets or wiki. Write privilege on the
612 @ ticket or wiki is also required.
613 @ </p></li>
614 @
615 @ <li><p>
616 @ Login is prohibited if the password is an empty string.
617 @ </p></li>
618 @ </ul>
@@ -592,42 +619,46 @@
619 @
620 @ <h2>Special Logins</h2>
621 @
622 @ <ul>
623 @ <li><p>
624 @ No login is required for user <span class="usertype">nobody</span>. The
625 @ capabilities of the <span class="usertype">nobody</span> user are
626 @ inherited by all users, regardless of whether or not they are logged in.
627 @ To disable universal access to the repository, make sure no user named
628 @ <span class="usertype">nobody</span> exists or that the
629 @ <span class="usertype">nobody</span> user has no capabilities
630 @ enabled. The password for <span class="usertype">nobody</span> is ignore.
631 @ To avoid problems with spiders overloading the server, it is recommended
632 @ that the <span class="capability">h</span> (History) capability be turned
633 @ off for the <span class="usertype">nobody</span> user.
634 @ </p></li>
635 @
636 @ <li><p>
637 @ Login is required for user <span class="usertype">anonymous</span> but the
638 @ password is displayed on the login screen beside the password entry box
639 @ so anybody who can read should be able to login as anonymous.
640 @ On the other hand, spiders and web-crawlers will typically not
641 @ be able to login. Set the capabilities of the
642 @ <span class="usertype">anonymous</span>
643 @ user to things that you want any human to be able to do, but not any
644 @ spider. Every other logged-in user inherits the privileges of
645 @ <span class="usertype">anonymous</span>.
646 @ </p></li>
647 @
648 @ <li><p>
649 @ The <span class="usertype">developer</span> user is intended as a template
650 @ for trusted users with check-in privileges. When adding new trusted users,
651 @ simply select the <span class="capability">developer</span> privilege to
652 @ cause the new user to inherit all privileges of the
653 @ <span class="usertype">developer</span>
654 @ user. Similarly, the <span class="usertype">reader</span> user is a
655 @ template for users who are allowed more access than
656 @ <span class="usertype">anonymous</span>,
657 @ but less than a <span class="usertype">developer</span>.
658 @ </p></li>
659 @ </ul>
660 style_footer();
661 }
662
663
664 /*
@@ -651,13 +682,14 @@
682 db_set(zVar, iQ ? "1" : "0", 0);
683 iVal = iQ;
684 }
685 }
686 if( iVal ){
687 @ <input type="checkbox" name="%s(zQParm)" checked="checked" />
688 @ <b>%s(zLabel)</b>
689 }else{
690 @ <input type="checkbox" name="%s(zQParm)" /><b>%s(zLabel)</b>
691 }
692 }
693
694 /*
695 ** Generate an entry box for an attribute.
@@ -674,11 +706,11 @@
706 if( zQ && strcmp(zQ,zVal)!=0 ){
707 login_verify_csrf_secret();
708 db_set(zVar, zQ, 0);
709 zVal = zQ;
710 }
711 @ <input type="text" name="%s(zQParm)" value="%h(zVal)" size="%d(width)" />
712 @ <b>%s(zLabel)</b>
713 }
714
715 /*
716 ** Generate a text box for an attribute.
@@ -698,11 +730,12 @@
730 db_set(zVar, zQ, 0);
731 z = zQ;
732 }
733 if( rows>0 && cols>0 ){
734 @ <textarea name="%s(zQP)" rows="%d(rows)" cols="%d(cols)">%h(z)</textarea>
735 if (zLabel && *zLabel)
736 @ <span class="textareaLabel">%s(zLabel)</span>
737 }
738 }
739
740
741 /*
@@ -714,57 +747,57 @@
747 login_needed();
748 }
749
750 style_header("Access Control Settings");
751 db_begin_transaction();
752 @ <form action="%s(g.zBaseURL)/setup_access" method="post"><div>
753 login_insert_csrf_secret();
754 @ <hr />
755 onoff_attribute("Require password for local access",
756 "localauth", "localauth", 0);
757 @ <p>When enabled, the password sign-in is required for
758 @ web access coming from 127.0.0.1. When disabled, web access
759 @ from 127.0.0.1 is allows without any login - the user id is selected
760 @ from the ~/.fossil database. Password login is always required
761 @ for incoming web connections on internet addresses other than
762 @ 127.0.0.1.</p>
763
764 @ <hr />
765 onoff_attribute("Allow REMOTE_USER authentication",
766 "remote_user_ok", "remote_user_ok", 0);
767 @ <p>When enabled, if the REMOTE_USER environment variable is set to the
768 @ login name of a valid user and no other login credentials are available,
769 @ then the REMOTE_USER is accepted as an authenticated user.
770 @ </p>
771
772 @ <hr />
773 entry_attribute("Login expiration time", 6, "cookie-expire", "cex", "8766");
774 @ <p>The number of hours for which a login is valid. This must be a
775 @ positive number. The default is 8760 hours which is approximately equal
776 @ to a year.</p>
777
778 @ <hr />
779 entry_attribute("Download packet limit", 10, "max-download", "mxdwn",
780 "5000000");
781 @ <p>Fossil tries to limit out-bound sync, clone, and pull packets
782 @ to this many bytes, uncompressed. If the client requires more data
783 @ than this, then the client will issue multiple HTTP requests.
784 @ Values below 1 million are not recommended. 5 million is a
785 @ reasonable number.</p>
786
787 @ <hr />
788 onoff_attribute("Show javascript button to fill in CAPTCHA",
789 "auto-captcha", "autocaptcha", 0);
790 @ <p>When enabled, a button appears on the login screen for user
791 @ "anonymous" that will automatically fill in the CAPTCHA password.
792 @ This is less secure that forcing the user to do it manually, but is
793 @ probably secure enough and it is certainly more convenient for
794 @ anonymous users.</p>
795
796 @ <hr />
797 @ <p><input type="submit" name="submit" value="Apply Changes" /></p>
798 @ </div></form>
799 db_end_transaction(0);
800 style_footer();
801 }
802
803 /*
@@ -776,42 +809,42 @@
809 login_needed();
810 }
811
812 style_header("Timeline Display Preferences");
813 db_begin_transaction();
814 @ <form action="%s(g.zBaseURL)/setup_timeline" method="post"><div>
815 login_insert_csrf_secret();
816
817 @ <hr />
818 onoff_attribute("Allow block-markup in timeline",
819 "timeline-block-markup", "tbm", 0);
820 @ <p>In timeline displays, check-in comments can be displayed with or
821 @ without block markup (paragraphs, tables, etc.)</p>
822
823 @ <hr />
824 onoff_attribute("Use Universal Coordinated Time (UTC)",
825 "timeline-utc", "utc", 1);
826 @ <p>Show times as UTC (also sometimes called Greenwich Mean Time (GMT) or
827 @ Zulu) instead of in local time.</p>
828
829 @ <hr />
830 onoff_attribute("Show version differences by default",
831 "show-version-diffs", "vdiff", 0);
832 @ <p>On the version-information pages linked from the timeline can either
833 @ show complete diffs of all file changes, or can just list the names of
834 @ the files that have changed. Users can get to either page by
835 @ clicking. This setting selects the default.</p>
836
837 @ <hr />
838 entry_attribute("Max timeline comment length", 6,
839 "timeline-max-comment", "tmc", "0");
840 @ <p>The maximum length of a comment to be displayed in a timeline.
841 @ "0" there is no length limit.</p>
842
843 @ <hr />
844 @ <p><input type="submit" name="submit" value="Apply Changes" /></p>
845 @ </div></form>
846 db_end_transaction(0);
847 style_footer();
848 }
849
850 /*
@@ -823,11 +856,11 @@
856 login_needed();
857 }
858
859 style_header("WWW Configuration");
860 db_begin_transaction();
861 @ <form action="%s(g.zBaseURL)/setup_config" method="post"><div>
862 login_insert_csrf_secret();
863 @ <hr />
864 entry_attribute("Project Name", 60, "project-name", "pn", "");
865 @ <p>Give your project a name so visitors know what this site is about.
866 @ The project name will also be used as the RSS feed title.</p>
@@ -840,36 +873,37 @@
873 entry_attribute("Index Page", 60, "index-page", "idxpg", "/home");
874 @ <p>Enter the pathname of the page to display when the "Home" menu
875 @ option is selected and when no pathname is
876 @ specified in the URL. For example, if you visit the url:</p>
877 @
878 @ <blockquote><p>%h(g.zBaseURL)</p></blockquote>
879 @
880 @ <p>And you have specified an index page of "/home" the above will
881 @ automatically redirect to:</p>
882 @
883 @ <blockquote><p>%h(g.zBaseURL)/home</p></blockquote>
884 @
885 @ <p>The default "/home" page displays a Wiki page with the same name
886 @ as the Project Name specified above. Some sites prefer to redirect
887 @ to a documentation page (ex: "/doc/tip/index.wiki") or to "/timeline".</p>
888 @ <hr />
889 onoff_attribute("Use HTML as wiki markup language",
890 "wiki-use-html", "wiki-use-html", 0);
891 @ <p>Use HTML as the wiki markup language. Wiki links will still be parsed
892 @ but all other wiki formatting will be ignored. This option is helpful
893 @ if you have chosen to use a rich HTML editor for wiki markup such as
894 @ TinyMCE.</p>
895 @ <p><strong>CAUTION:</strong> when
896 @ enabling, <i>all</i> HTML tags and attributes are accepted in the wiki.
897 @ No sanitization is done. This means that it is very possible for malicious
898 @ users to inject dangerous HTML, CSS and JavaScript code into your wiki.</p>
899 @ <p>This should <strong>only</strong> be enabled when wiki editing is limited
900 @ to trusted users. It should <strong>not</strong> be used on a publically
901 @ editable wiki.</p>
902 @ <hr />
903 @ <p><input type="submit" name="submit" value="Apply Changes" /></p>
904 @ </div></form>
905 db_end_transaction(0);
906 style_footer();
907 }
908
909 /*
@@ -892,30 +926,27 @@
926 if( P("submit")!=0 ){
927 db_end_transaction(0);
928 cgi_redirect("setup_editcss");
929 }
930 style_header("Edit CSS");
931 @ <form action="%s(g.zBaseURL)/setup_editcss" method="post"><div>
932 login_insert_csrf_secret();
933 @ Edit the CSS below:<br />
934 textarea_attribute("", 40, 80, "css", "css", zDefaultCSS);
935 @ <br />
936 @ <input type="submit" name="submit" value="Apply Changes" />
937 @ <input type="submit" name="clear" value="Revert To Default" />
938 @ </div></form>
939 @ <p><span class="note">Note:</span> Press your browser Reload button after
940 @ modifying the CSS in order to pull in the modified CSS file.</p>
941 @ <hr />
942 @ The default CSS is shown below for reference. Other examples
943 @ of CSS files can be seen on the <a href="setup_skin">skins page</a>.
944 @ See also the <a href="setup_header">header</a> and
945 @ <a href="setup_footer">footer</a> editing screens.
946 @ <blockquote><pre>
947 cgi_append_default_css();
 
 
 
948 @ </pre></blockquote>
949 style_footer();
950 db_end_transaction(0);
951 }
952
@@ -933,21 +964,21 @@
964 cgi_replace_parameter("header", zDefaultHeader);
965 }else{
966 textarea_attribute(0, 0, 0, "header", "header", zDefaultHeader);
967 }
968 style_header("Edit Page Header");
969 @ <form action="%s(g.zBaseURL)/setup_header" method="post"><div>
970 login_insert_csrf_secret();
971 @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to
972 @ generate the beginning of every page through start of the main
973 @ menu.</p>
974 textarea_attribute("", 40, 80, "header", "header", zDefaultHeader);
975 @ <br />
976 @ <input type="submit" name="submit" value="Apply Changes" />
977 @ <input type="submit" name="clear" value="Revert To Default" />
978 @ </div></form>
979 @ <hr />
980 @ The default header is shown below for reference. Other examples
981 @ of headers can be seen on the <a href="setup_skin">skins page</a>.
982 @ See also the <a href="setup_editcss">CSS</a> and
983 @ <a href="setup_footer">footer</a> editing screeens.
984 @ <blockquote><pre>
@@ -971,20 +1002,20 @@
1002 cgi_replace_parameter("footer", zDefaultFooter);
1003 }else{
1004 textarea_attribute(0, 0, 0, "footer", "footer", zDefaultFooter);
1005 }
1006 style_header("Edit Page Footer");
1007 @ <form action="%s(g.zBaseURL)/setup_footer" method="post"><div>
1008 login_insert_csrf_secret();
1009 @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to
1010 @ generate the end of every page.</p>
1011 textarea_attribute("", 20, 80, "footer", "footer", zDefaultFooter);
1012 @ <br />
1013 @ <input type="submit" name="submit" value="Apply Changes" />
1014 @ <input type="submit" name="clear" value="Revert To Default" />
1015 @ </div></form>
1016 @ <hr />
1017 @ The default footer is shown below for reference. Other examples
1018 @ of footers can be seen on the <a href="setup_skin">skins page</a>.
1019 @ See also the <a href="setup_editcss">CSS</a> and
1020 @ <a href="setup_header">header</a> editing screens.
1021 @ <blockquote><pre>
@@ -1034,31 +1065,31 @@
1065 cgi_redirect("setup_logo");
1066 }
1067 style_header("Edit Project Logo");
1068 @ <p>The current project logo has a MIME-Type of <b>%h(zMime)</b> and looks
1069 @ like this:</p>
1070 @ <blockquote><p><img src="%s(g.zTop)/logo" alt="logo" /></p></blockquote>
1071 @
1072 @ <p>The logo is accessible to all users at this URL:
1073 @ <a href="%s(g.zBaseURL)/logo">%s(g.zBaseURL)/logo</a>.
1074 @ The logo may or may not appear on each
1075 @ page depending on the <a href="setup_editcss">CSS</a> and
1076 @ <a href="setup_header">header setup</a>.</p>
1077 @
1078 @ <form action="%s(g.zBaseURL)/setup_logo" method="post"
1079 @ enctype="multipart/form-data"><div>
1080 @ <p>To set a new logo image, select a file to use as the logo using
1081 @ the entry box below and then press the "Change Logo" button.</p>
1082 login_insert_csrf_secret();
1083 @ Logo Image file:
1084 @ <input type="file" name="im" size="60" accept="image/*" /><br />
1085 @ <input type="submit" name="set" value="Change Logo" />
1086 @ <input type="submit" name="clr" value="Revert To Default" />
1087 @ </div></form>
1088 @
1089 @ <p><span class="note">Note:</span> Your browser has probably cached the
1090 @ logo image, so you will probably need to press the Reload button on your
1091 @ browser after changing the logo to provoke your browser to reload the new
1092 @ logo image. </p>
1093 style_footer();
1094 db_end_transaction(0);
1095 }
1096
+29 -26
--- src/shun.c
+++ src/shun.c
@@ -112,63 +112,63 @@
112112
@ or artifacts that by design or accident interfere with the processing
113113
@ of the repository. Do not shun artifacts merely to remove them from
114114
@ sight - set the "hidden" tag on such artifacts instead.</p>
115115
@
116116
@ <blockquote>
117
- @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)">
117
+ @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><div>
118118
login_insert_csrf_secret();
119
- @ <input type="text" name="uuid" value="%h(PD("shun",""))" size="50">
120
- @ <input type="submit" name="add" value="Shun">
121
- @ </form>
119
+ @ <input type="text" name="uuid" value="%h(PD("shun",""))" size="50" />
120
+ @ <input type="submit" name="add" value="Shun" />
121
+ @ </div></form>
122122
@ </blockquote>
123123
@
124124
@ <p>Enter the UUID of a previous shunned artifact to cause it to be
125125
@ accepted again in the repository. The artifact content is not
126126
@ restored because the content is unknown. The only change is that
127127
@ the formerly shunned artifact will be accepted on subsequent sync
128128
@ operations.</p>
129129
@
130130
@ <blockquote>
131
- @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)">
131
+ @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><div>
132132
login_insert_csrf_secret();
133
- @ <input type="text" name="uuid" size="50">
134
- @ <input type="submit" name="sub" value="Accept">
135
- @ </form>
133
+ @ <input type="text" name="uuid" size="50" />
134
+ @ <input type="submit" name="sub" value="Accept" />
135
+ @ </div></form>
136136
@ </blockquote>
137137
@
138138
@ <p>Press the Rebuild button below to rebuild the respository. The
139139
@ content of newly shunned artifacts is not purged until the repository
140140
@ is rebuilt. On larger repositories, the rebuild may take minute or
141141
@ two, so be patient after pressing the button.</p>
142142
@
143143
@ <blockquote>
144
- @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)">
144
+ @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><div>
145145
login_insert_csrf_secret();
146
- @ <input type="submit" name="rebuild" value="Rebuild">
147
- @ </form>
146
+ @ <input type="submit" name="rebuild" value="Rebuild" />
147
+ @ </div></form>
148148
@ </blockquote>
149149
@
150
- @ <hr><p>Shunned Artifacts:</p>
151
- @ <blockquote>
150
+ @ <hr /><p>Shunned Artifacts:</p>
151
+ @ <blockquote><p>
152152
db_prepare(&q,
153153
"SELECT uuid, EXISTS(SELECT 1 FROM blob WHERE blob.uuid=shun.uuid)"
154154
" FROM shun ORDER BY uuid");
155155
while( db_step(&q)==SQLITE_ROW ){
156156
const char *zUuid = db_column_text(&q, 0);
157157
int stillExists = db_column_int(&q, 1);
158158
cnt++;
159159
if( stillExists ){
160
- @ <b><a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a></b><br>
160
+ @ <b><a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a></b><br />
161161
}else{
162
- @ <b>%s(zUuid)</b><br>
162
+ @ <b>%s(zUuid)</b><br />
163163
}
164164
}
165165
if( cnt==0 ){
166166
@ <i>no artifacts are shunned on this server</i>
167167
}
168168
db_finalize(&q);
169
- @ </blockquote>
169
+ @ </p></blockquote>
170170
style_footer();
171171
}
172172
173173
/*
174174
** Remove from the BLOB table all artifacts that are in the SHUN table.
@@ -229,14 +229,15 @@
229229
@
230230
@ <p>Click on the "rcvid" to show a list of specific artifacts received
231231
@ by a transaction. After identifying illicit artifacts, remove them
232232
@ using the "Shun" feature.</p>
233233
@
234
- @ <table cellpadding=0 cellspacing=0 border=0>
235
- @ <tr><th>rcvid</th><th width=15>
236
- @ <th>Date</th><th width=15><th>User</th>
237
- @ <th width=15><th>IP&nbsp;Address</th></tr>
234
+ @ <table cellpadding="0" cellspacing="0" border="0">
235
+ @ <tr><th style="padding-right: 15px;text-align: right;">rcvid</th>
236
+ @ <th style="padding-right: 15px;text-align: left;">Date</th>
237
+ @ <th style="padding-right: 15px;text-align: left;">User</th>
238
+ @ <th style="text-align: left;">IP&nbsp;Address</th></tr>
238239
cnt = 0;
239240
while( db_step(&q)==SQLITE_ROW ){
240241
int rcvid = db_column_int(&q, 0);
241242
const char *zUser = db_column_text(&q, 1);
242243
const char *zDate = db_column_text(&q, 2);
@@ -245,14 +246,14 @@
245246
style_submenu_element("Older", "Older",
246247
"rcvfromlist?ofst=%d", ofst+30);
247248
}else{
248249
cnt++;
249250
@ <tr>
250
- @ <td><a href="rcvfrom?rcvid=%d(rcvid)">%d(rcvid)</a></td><td>
251
- @ <td>%s(zDate)</td><td>
252
- @ <td>%h(zUser)</td><td>
253
- @ <td>&nbsp;%s(zIpAddr)&nbsp</td>
251
+ @ <td style="padding-right: 15px;text-align: right;"><a href="rcvfrom?rcvid=%d(rcvid)">%d(rcvid)</a></td>
252
+ @ <td style="padding-right: 15px;text-align: left;">%s(zDate)</td>
253
+ @ <td style="padding-right: 15px;text-align: left;">%h(zUser)</td>
254
+ @ <td style="text-align: left;">%s(zIpAddr)</td>
254255
@ </tr>
255256
}
256257
}
257258
db_finalize(&q);
258259
@ </table>
@@ -277,11 +278,11 @@
277278
"SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr"
278279
" FROM rcvfrom LEFT JOIN user USING(uid)"
279280
" WHERE rcvid=%d",
280281
rcvid
281282
);
282
- @ <table cellspacing=15 cellpadding=0 border=0>
283
+ @ <table cellspacing="15" cellpadding="0" border="0">
283284
@ <tr><td valign="top" align="right"><b>rcvid:</b></td>
284285
@ <td valign="top">%d(rcvid)</td></tr>
285286
if( db_step(&q)==SQLITE_ROW ){
286287
const char *zUser = db_column_text(&q, 0);
287288
const char *zDate = db_column_text(&q, 1);
@@ -302,10 +303,12 @@
302303
while( db_step(&q)==SQLITE_ROW ){
303304
int rid = db_column_int(&q, 0);
304305
const char *zUuid = db_column_text(&q, 1);
305306
int size = db_column_int(&q, 2);
306307
@ <a href="%s(g.zBaseURL)/info/%s(zUuid)">%s(zUuid)</a>
307
- @ (rid: %d(rid), size: %d(size))<br>
308
+ @ (rid: %d(rid), size: %d(size))<br />
308309
}
309310
@ </td></tr>
310311
@ </table>
312
+ db_finalize(&q);
313
+ style_footer();
311314
}
312315
--- src/shun.c
+++ src/shun.c
@@ -112,63 +112,63 @@
112 @ or artifacts that by design or accident interfere with the processing
113 @ of the repository. Do not shun artifacts merely to remove them from
114 @ sight - set the "hidden" tag on such artifacts instead.</p>
115 @
116 @ <blockquote>
117 @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)">
118 login_insert_csrf_secret();
119 @ <input type="text" name="uuid" value="%h(PD("shun",""))" size="50">
120 @ <input type="submit" name="add" value="Shun">
121 @ </form>
122 @ </blockquote>
123 @
124 @ <p>Enter the UUID of a previous shunned artifact to cause it to be
125 @ accepted again in the repository. The artifact content is not
126 @ restored because the content is unknown. The only change is that
127 @ the formerly shunned artifact will be accepted on subsequent sync
128 @ operations.</p>
129 @
130 @ <blockquote>
131 @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)">
132 login_insert_csrf_secret();
133 @ <input type="text" name="uuid" size="50">
134 @ <input type="submit" name="sub" value="Accept">
135 @ </form>
136 @ </blockquote>
137 @
138 @ <p>Press the Rebuild button below to rebuild the respository. The
139 @ content of newly shunned artifacts is not purged until the repository
140 @ is rebuilt. On larger repositories, the rebuild may take minute or
141 @ two, so be patient after pressing the button.</p>
142 @
143 @ <blockquote>
144 @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)">
145 login_insert_csrf_secret();
146 @ <input type="submit" name="rebuild" value="Rebuild">
147 @ </form>
148 @ </blockquote>
149 @
150 @ <hr><p>Shunned Artifacts:</p>
151 @ <blockquote>
152 db_prepare(&q,
153 "SELECT uuid, EXISTS(SELECT 1 FROM blob WHERE blob.uuid=shun.uuid)"
154 " FROM shun ORDER BY uuid");
155 while( db_step(&q)==SQLITE_ROW ){
156 const char *zUuid = db_column_text(&q, 0);
157 int stillExists = db_column_int(&q, 1);
158 cnt++;
159 if( stillExists ){
160 @ <b><a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a></b><br>
161 }else{
162 @ <b>%s(zUuid)</b><br>
163 }
164 }
165 if( cnt==0 ){
166 @ <i>no artifacts are shunned on this server</i>
167 }
168 db_finalize(&q);
169 @ </blockquote>
170 style_footer();
171 }
172
173 /*
174 ** Remove from the BLOB table all artifacts that are in the SHUN table.
@@ -229,14 +229,15 @@
229 @
230 @ <p>Click on the "rcvid" to show a list of specific artifacts received
231 @ by a transaction. After identifying illicit artifacts, remove them
232 @ using the "Shun" feature.</p>
233 @
234 @ <table cellpadding=0 cellspacing=0 border=0>
235 @ <tr><th>rcvid</th><th width=15>
236 @ <th>Date</th><th width=15><th>User</th>
237 @ <th width=15><th>IP&nbsp;Address</th></tr>
 
238 cnt = 0;
239 while( db_step(&q)==SQLITE_ROW ){
240 int rcvid = db_column_int(&q, 0);
241 const char *zUser = db_column_text(&q, 1);
242 const char *zDate = db_column_text(&q, 2);
@@ -245,14 +246,14 @@
245 style_submenu_element("Older", "Older",
246 "rcvfromlist?ofst=%d", ofst+30);
247 }else{
248 cnt++;
249 @ <tr>
250 @ <td><a href="rcvfrom?rcvid=%d(rcvid)">%d(rcvid)</a></td><td>
251 @ <td>%s(zDate)</td><td>
252 @ <td>%h(zUser)</td><td>
253 @ <td>&nbsp;%s(zIpAddr)&nbsp</td>
254 @ </tr>
255 }
256 }
257 db_finalize(&q);
258 @ </table>
@@ -277,11 +278,11 @@
277 "SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr"
278 " FROM rcvfrom LEFT JOIN user USING(uid)"
279 " WHERE rcvid=%d",
280 rcvid
281 );
282 @ <table cellspacing=15 cellpadding=0 border=0>
283 @ <tr><td valign="top" align="right"><b>rcvid:</b></td>
284 @ <td valign="top">%d(rcvid)</td></tr>
285 if( db_step(&q)==SQLITE_ROW ){
286 const char *zUser = db_column_text(&q, 0);
287 const char *zDate = db_column_text(&q, 1);
@@ -302,10 +303,12 @@
302 while( db_step(&q)==SQLITE_ROW ){
303 int rid = db_column_int(&q, 0);
304 const char *zUuid = db_column_text(&q, 1);
305 int size = db_column_int(&q, 2);
306 @ <a href="%s(g.zBaseURL)/info/%s(zUuid)">%s(zUuid)</a>
307 @ (rid: %d(rid), size: %d(size))<br>
308 }
309 @ </td></tr>
310 @ </table>
 
 
311 }
312
--- src/shun.c
+++ src/shun.c
@@ -112,63 +112,63 @@
112 @ or artifacts that by design or accident interfere with the processing
113 @ of the repository. Do not shun artifacts merely to remove them from
114 @ sight - set the "hidden" tag on such artifacts instead.</p>
115 @
116 @ <blockquote>
117 @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><div>
118 login_insert_csrf_secret();
119 @ <input type="text" name="uuid" value="%h(PD("shun",""))" size="50" />
120 @ <input type="submit" name="add" value="Shun" />
121 @ </div></form>
122 @ </blockquote>
123 @
124 @ <p>Enter the UUID of a previous shunned artifact to cause it to be
125 @ accepted again in the repository. The artifact content is not
126 @ restored because the content is unknown. The only change is that
127 @ the formerly shunned artifact will be accepted on subsequent sync
128 @ operations.</p>
129 @
130 @ <blockquote>
131 @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><div>
132 login_insert_csrf_secret();
133 @ <input type="text" name="uuid" size="50" />
134 @ <input type="submit" name="sub" value="Accept" />
135 @ </div></form>
136 @ </blockquote>
137 @
138 @ <p>Press the Rebuild button below to rebuild the respository. The
139 @ content of newly shunned artifacts is not purged until the repository
140 @ is rebuilt. On larger repositories, the rebuild may take minute or
141 @ two, so be patient after pressing the button.</p>
142 @
143 @ <blockquote>
144 @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><div>
145 login_insert_csrf_secret();
146 @ <input type="submit" name="rebuild" value="Rebuild" />
147 @ </div></form>
148 @ </blockquote>
149 @
150 @ <hr /><p>Shunned Artifacts:</p>
151 @ <blockquote><p>
152 db_prepare(&q,
153 "SELECT uuid, EXISTS(SELECT 1 FROM blob WHERE blob.uuid=shun.uuid)"
154 " FROM shun ORDER BY uuid");
155 while( db_step(&q)==SQLITE_ROW ){
156 const char *zUuid = db_column_text(&q, 0);
157 int stillExists = db_column_int(&q, 1);
158 cnt++;
159 if( stillExists ){
160 @ <b><a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a></b><br />
161 }else{
162 @ <b>%s(zUuid)</b><br />
163 }
164 }
165 if( cnt==0 ){
166 @ <i>no artifacts are shunned on this server</i>
167 }
168 db_finalize(&q);
169 @ </p></blockquote>
170 style_footer();
171 }
172
173 /*
174 ** Remove from the BLOB table all artifacts that are in the SHUN table.
@@ -229,14 +229,15 @@
229 @
230 @ <p>Click on the "rcvid" to show a list of specific artifacts received
231 @ by a transaction. After identifying illicit artifacts, remove them
232 @ using the "Shun" feature.</p>
233 @
234 @ <table cellpadding="0" cellspacing="0" border="0">
235 @ <tr><th style="padding-right: 15px;text-align: right;">rcvid</th>
236 @ <th style="padding-right: 15px;text-align: left;">Date</th>
237 @ <th style="padding-right: 15px;text-align: left;">User</th>
238 @ <th style="text-align: left;">IP&nbsp;Address</th></tr>
239 cnt = 0;
240 while( db_step(&q)==SQLITE_ROW ){
241 int rcvid = db_column_int(&q, 0);
242 const char *zUser = db_column_text(&q, 1);
243 const char *zDate = db_column_text(&q, 2);
@@ -245,14 +246,14 @@
246 style_submenu_element("Older", "Older",
247 "rcvfromlist?ofst=%d", ofst+30);
248 }else{
249 cnt++;
250 @ <tr>
251 @ <td style="padding-right: 15px;text-align: right;"><a href="rcvfrom?rcvid=%d(rcvid)">%d(rcvid)</a></td>
252 @ <td style="padding-right: 15px;text-align: left;">%s(zDate)</td>
253 @ <td style="padding-right: 15px;text-align: left;">%h(zUser)</td>
254 @ <td style="text-align: left;">%s(zIpAddr)</td>
255 @ </tr>
256 }
257 }
258 db_finalize(&q);
259 @ </table>
@@ -277,11 +278,11 @@
278 "SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr"
279 " FROM rcvfrom LEFT JOIN user USING(uid)"
280 " WHERE rcvid=%d",
281 rcvid
282 );
283 @ <table cellspacing="15" cellpadding="0" border="0">
284 @ <tr><td valign="top" align="right"><b>rcvid:</b></td>
285 @ <td valign="top">%d(rcvid)</td></tr>
286 if( db_step(&q)==SQLITE_ROW ){
287 const char *zUser = db_column_text(&q, 0);
288 const char *zDate = db_column_text(&q, 1);
@@ -302,10 +303,12 @@
303 while( db_step(&q)==SQLITE_ROW ){
304 int rid = db_column_int(&q, 0);
305 const char *zUuid = db_column_text(&q, 1);
306 int size = db_column_int(&q, 2);
307 @ <a href="%s(g.zBaseURL)/info/%s(zUuid)">%s(zUuid)</a>
308 @ (rid: %d(rid), size: %d(size))<br />
309 }
310 @ </td></tr>
311 @ </table>
312 db_finalize(&q);
313 style_footer();
314 }
315
+11 -11
--- src/skins.c
+++ src/skins.c
@@ -165,11 +165,11 @@
165165
@ <body>
166166
@ <div class="header">
167167
@ <div class="logo">
168168
@ <img src="$baseurl/logo" alt="logo">
169169
@ </div>
170
-@ <div class="title"><small>$<project_name></small><br>$<title></div>
170
+@ <div class="title"><small>$<project_name></small><br />$<title></div>
171171
@ <div class="status"><nobr><th1>
172172
@ if {[info exists login]} {
173173
@ puts "Logged in as $login"
174174
@ } else {
175175
@ puts "Not logged in"
@@ -600,11 +600,11 @@
600600
@ </head>
601601
@ <body>
602602
@ <div class="header">
603603
@ <div class="logo">
604604
@ <!-- <img src="$baseurl/logo" alt="logo"> -->
605
-@ <br><nobr>$<project_name></nobr>
605
+@ <br /><nobr>$<project_name></nobr>
606606
@ </div>
607607
@ <div class="title">$<title></div>
608608
@ <div class="status"><nobr><th1>
609609
@ if {[info exists login]} {
610610
@ puts "Logged in as $login"
@@ -731,18 +731,18 @@
731731
db_begin_transaction();
732732
733733
/* Process requests to delete a user-defined skin */
734734
if( P("del1") && (zName = skinVarName(P("sn"), 1))!=0 ){
735735
style_header("Confirm Custom Skin Delete");
736
- @ <form action="%s(g.zBaseURL)/setup_skin" method="POST">
736
+ @ <form action="%s(g.zBaseURL)/setup_skin" method="post"><div>
737737
@ <p>Deletion of a custom skin is a permanent action that cannot
738738
@ be undone. Please confirm that this is what you want to do:</p>
739
- @ <input type="hidden" name="sn" value="%h(P("sn"))">
740
- @ <input type="submit" name="del2" value="Confirm - Delete The Skin">
741
- @ <input type="submit" name="cancel" value="Cancel - Do Not Delete">
739
+ @ <input type="hidden" name="sn" value="%h(P("sn"))" />
740
+ @ <input type="submit" name="del2" value="Confirm - Delete The Skin" />
741
+ @ <input type="submit" name="cancel" value="Cancel - Do Not Delete" />
742742
login_insert_csrf_secret();
743
- @ </form>
743
+ @ </div></form>
744744
style_footer();
745745
return;
746746
}
747747
if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){
748748
db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
@@ -812,15 +812,15 @@
812812
for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
813813
z = aBuiltinSkin[i].zName;
814814
if( strcmp(aBuiltinSkin[i].zValue, zCurrent)==0 ){
815815
@ <li><p>%h(z).&nbsp;&nbsp; <b>Currently In Use</b></p>
816816
}else{
817
- @ <li><form action="%s(g.zBaseURL)/setup_skin" method="POST">
817
+ @ <li><form action="%s(g.zBaseURL)/setup_skin" method="post"><div>
818818
@ %h(z).&nbsp;&nbsp;
819
- @ <input type="hidden" name="sn" value="%h(z)">
820
- @ <input type="submit" name="load" value="Use This Skin">
821
- @ </form></li>
819
+ @ <input type="hidden" name="sn" value="%h(z)" />
820
+ @ <input type="submit" name="load" value="Use This Skin" />
821
+ @ </div></form></li>
822822
}
823823
}
824824
db_prepare(&q,
825825
"SELECT substr(name, 6), value FROM config"
826826
" WHERE name GLOB 'skin:*'"
827827
--- src/skins.c
+++ src/skins.c
@@ -165,11 +165,11 @@
165 @ <body>
166 @ <div class="header">
167 @ <div class="logo">
168 @ <img src="$baseurl/logo" alt="logo">
169 @ </div>
170 @ <div class="title"><small>$<project_name></small><br>$<title></div>
171 @ <div class="status"><nobr><th1>
172 @ if {[info exists login]} {
173 @ puts "Logged in as $login"
174 @ } else {
175 @ puts "Not logged in"
@@ -600,11 +600,11 @@
600 @ </head>
601 @ <body>
602 @ <div class="header">
603 @ <div class="logo">
604 @ <!-- <img src="$baseurl/logo" alt="logo"> -->
605 @ <br><nobr>$<project_name></nobr>
606 @ </div>
607 @ <div class="title">$<title></div>
608 @ <div class="status"><nobr><th1>
609 @ if {[info exists login]} {
610 @ puts "Logged in as $login"
@@ -731,18 +731,18 @@
731 db_begin_transaction();
732
733 /* Process requests to delete a user-defined skin */
734 if( P("del1") && (zName = skinVarName(P("sn"), 1))!=0 ){
735 style_header("Confirm Custom Skin Delete");
736 @ <form action="%s(g.zBaseURL)/setup_skin" method="POST">
737 @ <p>Deletion of a custom skin is a permanent action that cannot
738 @ be undone. Please confirm that this is what you want to do:</p>
739 @ <input type="hidden" name="sn" value="%h(P("sn"))">
740 @ <input type="submit" name="del2" value="Confirm - Delete The Skin">
741 @ <input type="submit" name="cancel" value="Cancel - Do Not Delete">
742 login_insert_csrf_secret();
743 @ </form>
744 style_footer();
745 return;
746 }
747 if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){
748 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
@@ -812,15 +812,15 @@
812 for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
813 z = aBuiltinSkin[i].zName;
814 if( strcmp(aBuiltinSkin[i].zValue, zCurrent)==0 ){
815 @ <li><p>%h(z).&nbsp;&nbsp; <b>Currently In Use</b></p>
816 }else{
817 @ <li><form action="%s(g.zBaseURL)/setup_skin" method="POST">
818 @ %h(z).&nbsp;&nbsp;
819 @ <input type="hidden" name="sn" value="%h(z)">
820 @ <input type="submit" name="load" value="Use This Skin">
821 @ </form></li>
822 }
823 }
824 db_prepare(&q,
825 "SELECT substr(name, 6), value FROM config"
826 " WHERE name GLOB 'skin:*'"
827
--- src/skins.c
+++ src/skins.c
@@ -165,11 +165,11 @@
165 @ <body>
166 @ <div class="header">
167 @ <div class="logo">
168 @ <img src="$baseurl/logo" alt="logo">
169 @ </div>
170 @ <div class="title"><small>$<project_name></small><br />$<title></div>
171 @ <div class="status"><nobr><th1>
172 @ if {[info exists login]} {
173 @ puts "Logged in as $login"
174 @ } else {
175 @ puts "Not logged in"
@@ -600,11 +600,11 @@
600 @ </head>
601 @ <body>
602 @ <div class="header">
603 @ <div class="logo">
604 @ <!-- <img src="$baseurl/logo" alt="logo"> -->
605 @ <br /><nobr>$<project_name></nobr>
606 @ </div>
607 @ <div class="title">$<title></div>
608 @ <div class="status"><nobr><th1>
609 @ if {[info exists login]} {
610 @ puts "Logged in as $login"
@@ -731,18 +731,18 @@
731 db_begin_transaction();
732
733 /* Process requests to delete a user-defined skin */
734 if( P("del1") && (zName = skinVarName(P("sn"), 1))!=0 ){
735 style_header("Confirm Custom Skin Delete");
736 @ <form action="%s(g.zBaseURL)/setup_skin" method="post"><div>
737 @ <p>Deletion of a custom skin is a permanent action that cannot
738 @ be undone. Please confirm that this is what you want to do:</p>
739 @ <input type="hidden" name="sn" value="%h(P("sn"))" />
740 @ <input type="submit" name="del2" value="Confirm - Delete The Skin" />
741 @ <input type="submit" name="cancel" value="Cancel - Do Not Delete" />
742 login_insert_csrf_secret();
743 @ </div></form>
744 style_footer();
745 return;
746 }
747 if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){
748 db_multi_exec("DELETE FROM config WHERE name=%Q", zName);
@@ -812,15 +812,15 @@
812 for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){
813 z = aBuiltinSkin[i].zName;
814 if( strcmp(aBuiltinSkin[i].zValue, zCurrent)==0 ){
815 @ <li><p>%h(z).&nbsp;&nbsp; <b>Currently In Use</b></p>
816 }else{
817 @ <li><form action="%s(g.zBaseURL)/setup_skin" method="post"><div>
818 @ %h(z).&nbsp;&nbsp;
819 @ <input type="hidden" name="sn" value="%h(z)" />
820 @ <input type="submit" name="load" value="Use This Skin" />
821 @ </div></form></li>
822 }
823 }
824 db_prepare(&q,
825 "SELECT substr(name, 6), value FROM config"
826 " WHERE name GLOB 'skin:*'"
827
+18 -6
--- src/stat.c
+++ src/stat.c
@@ -28,15 +28,17 @@
2828
** Show statistics and global information about the repository.
2929
*/
3030
void stat_page(void){
3131
i64 t;
3232
int n, m, fsize;
33
+ int szMax, szAvg;
3334
char zBuf[100];
35
+
3436
login_check_credentials();
3537
if( !g.okRead ){ login_needed(); return; }
3638
style_header("Repository Statistics");
37
- @ <p><table class="label-value">
39
+ @ <table class="label-value">
3840
@ <tr><th>Repository&nbsp;Size:</th><td>
3941
fsize = file_size(g.zRepositoryName);
4042
@ %d(fsize) bytes
4143
@ </td></tr>
4244
@ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
@@ -44,14 +46,21 @@
4446
m = db_int(0, "SELECT count(*) FROM delta");
4547
@ %d(n) (stored as %d(n-m) full text and %d(m) delta blobs)
4648
@ </td></tr>
4749
if( n>0 ){
4850
int a, b;
51
+ Stmt q;
4952
@ <tr><th>Uncompressed&nbsp;Artifact&nbsp;Size:</th><td>
50
- t = db_int64(0, "SELECT total(size) FROM blob WHERE size>0");
53
+ db_prepare(&q, "SELECT total(size), avg(size), max(size)"
54
+ " FROM blob WHERE size>0");
55
+ db_step(&q);
56
+ t = db_column_int64(&q, 0);
57
+ szAvg = db_column_int(&q, 1);
58
+ szMax = db_column_int(&q, 2);
59
+ db_finalize(&q);
5160
sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", t);
52
- @ %d((int)(((double)t)/(double)n)) bytes average, %s(zBuf) bytes total
61
+ @ %d(szAvg) bytes average, %d(szMax) bytes max, %s(zBuf) bytes total
5362
@ </td></tr>
5463
@ <tr><th>Compression&nbsp;Ratio:</th><td>
5564
if( t/fsize < 5 ){
5665
b = 10;
5766
fsize /= 10;
@@ -82,10 +91,12 @@
8291
@ </td></tr>
8392
@ <tr><th>Duration&nbsp;Of&nbsp;Project:</th><td>
8493
n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
8594
" + 0.99");
8695
@ %d(n) days
96
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%.2f", n/365.24);
97
+ @ or approximately %s(zBuf) years
8798
@ </td></tr>
8899
@ <tr><th>Project&nbsp;ID:</th><td>
89100
@ %h(db_get("project-code",""))
90101
@ </td></tr>
91102
@ <tr><th>Server&nbsp;ID:</th><td>
@@ -94,19 +105,20 @@
94105
95106
@ <tr><th>Fossil&nbsp;Version:</th><td>
96107
@ %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
97108
@ </td></tr>
98109
@ <tr><th>SQLite&nbsp;Version:</th><td>
99
- @ %h(db_text(0, "SELECT substr(sqlite_source_id(),1,30)"))
100
- @ (%h(SQLITE_VERSION))
110
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%.19s [%.10s] (%s)",
111
+ SQLITE_SOURCE_ID, &SQLITE_SOURCE_ID[20], SQLITE_VERSION);
112
+ @ %s(zBuf)
101113
@ </td></tr>
102114
@ <tr><th>Database&nbsp;Stats:</th><td>
103115
@ %d(db_int(0, "PRAGMA %s.page_count", g.zRepoDb)) pages,
104116
@ %d(db_int(0, "PRAGMA %s.page_size", g.zRepoDb)) bytes/page,
105117
@ %d(db_int(0, "PRAGMA %s.freelist_count", g.zRepoDb)) free pages,
106118
@ %s(db_text(0, "PRAGMA %s.encoding", g.zRepoDb)),
107119
@ %s(db_text(0, "PRAGMA %s.journal_mode", g.zRepoDb)) mode
108120
@ </td></tr>
109121
110
- @ </table></p>
122
+ @ </table>
111123
style_footer();
112124
}
113125
--- src/stat.c
+++ src/stat.c
@@ -28,15 +28,17 @@
28 ** Show statistics and global information about the repository.
29 */
30 void stat_page(void){
31 i64 t;
32 int n, m, fsize;
 
33 char zBuf[100];
 
34 login_check_credentials();
35 if( !g.okRead ){ login_needed(); return; }
36 style_header("Repository Statistics");
37 @ <p><table class="label-value">
38 @ <tr><th>Repository&nbsp;Size:</th><td>
39 fsize = file_size(g.zRepositoryName);
40 @ %d(fsize) bytes
41 @ </td></tr>
42 @ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
@@ -44,14 +46,21 @@
44 m = db_int(0, "SELECT count(*) FROM delta");
45 @ %d(n) (stored as %d(n-m) full text and %d(m) delta blobs)
46 @ </td></tr>
47 if( n>0 ){
48 int a, b;
 
49 @ <tr><th>Uncompressed&nbsp;Artifact&nbsp;Size:</th><td>
50 t = db_int64(0, "SELECT total(size) FROM blob WHERE size>0");
 
 
 
 
 
 
51 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", t);
52 @ %d((int)(((double)t)/(double)n)) bytes average, %s(zBuf) bytes total
53 @ </td></tr>
54 @ <tr><th>Compression&nbsp;Ratio:</th><td>
55 if( t/fsize < 5 ){
56 b = 10;
57 fsize /= 10;
@@ -82,10 +91,12 @@
82 @ </td></tr>
83 @ <tr><th>Duration&nbsp;Of&nbsp;Project:</th><td>
84 n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
85 " + 0.99");
86 @ %d(n) days
 
 
87 @ </td></tr>
88 @ <tr><th>Project&nbsp;ID:</th><td>
89 @ %h(db_get("project-code",""))
90 @ </td></tr>
91 @ <tr><th>Server&nbsp;ID:</th><td>
@@ -94,19 +105,20 @@
94
95 @ <tr><th>Fossil&nbsp;Version:</th><td>
96 @ %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
97 @ </td></tr>
98 @ <tr><th>SQLite&nbsp;Version:</th><td>
99 @ %h(db_text(0, "SELECT substr(sqlite_source_id(),1,30)"))
100 @ (%h(SQLITE_VERSION))
 
101 @ </td></tr>
102 @ <tr><th>Database&nbsp;Stats:</th><td>
103 @ %d(db_int(0, "PRAGMA %s.page_count", g.zRepoDb)) pages,
104 @ %d(db_int(0, "PRAGMA %s.page_size", g.zRepoDb)) bytes/page,
105 @ %d(db_int(0, "PRAGMA %s.freelist_count", g.zRepoDb)) free pages,
106 @ %s(db_text(0, "PRAGMA %s.encoding", g.zRepoDb)),
107 @ %s(db_text(0, "PRAGMA %s.journal_mode", g.zRepoDb)) mode
108 @ </td></tr>
109
110 @ </table></p>
111 style_footer();
112 }
113
--- src/stat.c
+++ src/stat.c
@@ -28,15 +28,17 @@
28 ** Show statistics and global information about the repository.
29 */
30 void stat_page(void){
31 i64 t;
32 int n, m, fsize;
33 int szMax, szAvg;
34 char zBuf[100];
35
36 login_check_credentials();
37 if( !g.okRead ){ login_needed(); return; }
38 style_header("Repository Statistics");
39 @ <table class="label-value">
40 @ <tr><th>Repository&nbsp;Size:</th><td>
41 fsize = file_size(g.zRepositoryName);
42 @ %d(fsize) bytes
43 @ </td></tr>
44 @ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
@@ -44,14 +46,21 @@
46 m = db_int(0, "SELECT count(*) FROM delta");
47 @ %d(n) (stored as %d(n-m) full text and %d(m) delta blobs)
48 @ </td></tr>
49 if( n>0 ){
50 int a, b;
51 Stmt q;
52 @ <tr><th>Uncompressed&nbsp;Artifact&nbsp;Size:</th><td>
53 db_prepare(&q, "SELECT total(size), avg(size), max(size)"
54 " FROM blob WHERE size>0");
55 db_step(&q);
56 t = db_column_int64(&q, 0);
57 szAvg = db_column_int(&q, 1);
58 szMax = db_column_int(&q, 2);
59 db_finalize(&q);
60 sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", t);
61 @ %d(szAvg) bytes average, %d(szMax) bytes max, %s(zBuf) bytes total
62 @ </td></tr>
63 @ <tr><th>Compression&nbsp;Ratio:</th><td>
64 if( t/fsize < 5 ){
65 b = 10;
66 fsize /= 10;
@@ -82,10 +91,12 @@
91 @ </td></tr>
92 @ <tr><th>Duration&nbsp;Of&nbsp;Project:</th><td>
93 n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)"
94 " + 0.99");
95 @ %d(n) days
96 sqlite3_snprintf(sizeof(zBuf), zBuf, "%.2f", n/365.24);
97 @ or approximately %s(zBuf) years
98 @ </td></tr>
99 @ <tr><th>Project&nbsp;ID:</th><td>
100 @ %h(db_get("project-code",""))
101 @ </td></tr>
102 @ <tr><th>Server&nbsp;ID:</th><td>
@@ -94,19 +105,20 @@
105
106 @ <tr><th>Fossil&nbsp;Version:</th><td>
107 @ %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
108 @ </td></tr>
109 @ <tr><th>SQLite&nbsp;Version:</th><td>
110 sqlite3_snprintf(sizeof(zBuf), zBuf, "%.19s [%.10s] (%s)",
111 SQLITE_SOURCE_ID, &SQLITE_SOURCE_ID[20], SQLITE_VERSION);
112 @ %s(zBuf)
113 @ </td></tr>
114 @ <tr><th>Database&nbsp;Stats:</th><td>
115 @ %d(db_int(0, "PRAGMA %s.page_count", g.zRepoDb)) pages,
116 @ %d(db_int(0, "PRAGMA %s.page_size", g.zRepoDb)) bytes/page,
117 @ %d(db_int(0, "PRAGMA %s.freelist_count", g.zRepoDb)) free pages,
118 @ %s(db_text(0, "PRAGMA %s.encoding", g.zRepoDb)),
119 @ %s(db_text(0, "PRAGMA %s.journal_mode", g.zRepoDb)) mode
120 @ </td></tr>
121
122 @ </table>
123 style_footer();
124 }
125
+316 -50
--- src/style.c
+++ src/style.c
@@ -139,20 +139,23 @@
139139
}
140140
@ <div class="content">
141141
cgi_destination(CGI_BODY);
142142
143143
/* Put the footer at the bottom of the page.
144
+ ** the additional clear/both is needed to extend the content
145
+ ** part to the end of an optional sidebox.
144146
*/
145
- @ </div><br clear="both"/>
147
+ @ <div style="clear: both;"></div>
148
+ @ </div>
146149
zFooter = db_get("footer", (char*)zDefaultFooter);
147150
if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1);
148151
Th_Render(zFooter);
149152
if( g.thTrace ) Th_Trace("END_FOOTER<br />\n", -1);
150153
151154
/* Render trace log if TH1 tracing is enabled. */
152155
if( g.thTrace ){
153
- cgi_append_content("<font color=\"red\"><hr>\n", -1);
156
+ cgi_append_content("<font color=\"red\"><hr />\n", -1);
154157
cgi_append_content(blob_str(&g.thLog), blob_size(&g.thLog));
155158
cgi_append_content("</font>\n", -1);
156159
}
157160
}
158161
@@ -179,27 +182,27 @@
179182
const char zDefaultHeader[] =
180183
@ <html>
181184
@ <head>
182185
@ <title>$<project_name>: $<title></title>
183186
@ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
184
-@ href="$baseurl/timeline.rss">
187
+@ href="$baseurl/timeline.rss" />
185188
@ <link rel="stylesheet" href="$baseurl/style.css?default" type="text/css"
186
-@ media="screen">
189
+@ media="screen" />
187190
@ </head>
188191
@ <body>
189192
@ <div class="header">
190193
@ <div class="logo">
191194
@ <img src="$baseurl/logo" alt="logo">
192195
@ </div>
193
-@ <div class="title"><small>$<project_name></small><br>$<title></div>
194
-@ <div class="status"><nobr><th1>
196
+@ <div class="title"><small>$<project_name></small><br />$<title></div>
197
+@ <div class="status"><th1>
195198
@ if {[info exists login]} {
196199
@ puts "Logged in as $login"
197200
@ } else {
198201
@ puts "Not logged in"
199202
@ }
200
-@ </th1></nobr></div>
203
+@ </th1></div>
201204
@ </div>
202205
@ <div class="mainmenu"><th1>
203206
@ html "<a href='$baseurl$index_page'>Home</a> "
204207
@ if {[anycap jor]} {
205208
@ html "<a href='$baseurl/timeline'>Timeline</a> "
@@ -274,11 +277,11 @@
274277
@ font-weight: bold;
275278
@ text-align: center;
276279
@ padding: 0 0 0 1em;
277280
@ color: #558195;
278281
@ vertical-align: bottom;
279
-@ width: 100%;
282
+@ width: 100% ;
280283
@ }
281284
@
282285
@ /* The login status message in the top right-hand corner */
283286
@ div.status {
284287
@ display: table-cell;
@@ -286,16 +289,17 @@
286289
@ vertical-align: bottom;
287290
@ color: #558195;
288291
@ font-size: 0.8em;
289292
@ font-weight: bold;
290293
@ min-width: 200px;
294
+@ white-space: nowrap;
291295
@ }
292296
@
293297
@ /* The header across the top of the page */
294298
@ div.header {
295299
@ display: table;
296
-@ width: 100%;
300
+@ width: 100% ;
297301
@ }
298302
@
299303
@ /* The main menu bar that appears at the top of the page beneath
300304
@ ** the header */
301305
@ div.mainmenu {
@@ -339,10 +343,11 @@
339343
@ padding: 1px 1px 1px 1px;
340344
@ font-size: 1.2em;
341345
@ font-weight: bold;
342346
@ background-color: #558195;
343347
@ color: white;
348
+@ white-space: nowrap;
344349
@ }
345350
@
346351
@ /* The "Date" that occurs on the left hand side of timelines */
347352
@ div.divider {
348353
@ background: #a1c4d4;
@@ -368,83 +373,344 @@
368373
@ div.footer a { color: white; }
369374
@ div.footer a:link { color: white; }
370375
@ div.footer a:visited { color: white; }
371376
@ div.footer a:hover { background-color: white; color: #558195; }
372377
@
373
-@ /* <verbatim> blocks */
378
+@ /* verbatim blocks */
374379
@ pre.verbatim {
375380
@ background-color: #f5f5f5;
376381
@ padding: 0.5em;
377382
@}
378383
@
379
-;
380
-const char zTableLabelValueCSS[] =
381384
@ /* The label/value pairs on (for example) the ci page */
382385
@ table.label-value th {
383386
@ vertical-align: top;
384387
@ text-align: right;
385388
@ padding: 0.2ex 2ex;
386389
@ }
387
-;
388
-const char zDivSidebox[] =
389
-@ /* The nomenclature sidebox for branches,.. */
390
-@ div.sidebox {
391
-@ float: right;
392
-@ border-width: medium;
393
-@ border-style: double;
394
-@ margin: 10;
395
-@ }
396
-;
397
-const char zDivSideboxTitle[] =
398
-@ /* The nomenclature title in sideboxes for branches,.. */
399
-@ div.sideboxTitle {
400
-@ display: inline;
401
-@ font-weight: bold;
402
-@ }
403
-;
404
-
405
-
406
-/* The following table holds the names of CSS elements and the CSS
407
-** text that implements those elements.
408
-*/
409
-static const struct {
410
- const char *zElement; /* Name of the CSS element */
411
- const char *zText; /* Text of the element */
412
-} cssElements[] = {
413
- { "table.label-value", zTableLabelValueCSS },
414
- { "div.sidebox", zDivSidebox },
415
- { "div.sideboxTitle", zDivSideboxTitle },
416
-};
390
+@
391
+;
392
+
393
+
394
+/* The following table contains bits of default CSS that must
395
+** be included if they are not found in the application-defined
396
+** CSS.
397
+*/
398
+const struct strctCssDefaults {
399
+ char const * const elementClass; /* Name of element needed */
400
+ char const * const comment; /* Comment text */
401
+ char const * const value; /* CSS text */
402
+} cssDefaultList[] = {
403
+ { "",
404
+ "",
405
+ zDefaultCSS
406
+ },
407
+ { "div.sidebox",
408
+ "The nomenclature sidebox for branches,..",
409
+ @ float: right;
410
+ @ background-color: white;
411
+ @ border-width: medium;
412
+ @ border-style: double;
413
+ @ margin: 10;
414
+ },
415
+ { "div.sideboxTitle",
416
+ "The nomenclature title in sideboxes for branches,..",
417
+ @ display: inline;
418
+ @ font-weight: bold;
419
+ },
420
+ { "div.sideboxDescribed",
421
+ "The defined element in sideboxes for branches,..",
422
+ @ display: inline;
423
+ @ font-weight: bold;
424
+ },
425
+ { "span.disabled",
426
+ "The defined element in sideboxes for branches,..",
427
+ @ color: red;
428
+ },
429
+ { "span.timelineDisabled",
430
+ "The suppressed duplicates lines in timeline, ..",
431
+ @ font-style: italic;
432
+ @ font-size: small;
433
+ },
434
+ { "table.timelineTable",
435
+ "the format for the timeline data table",
436
+ @ cellspacing: 0;
437
+ @ border: 0;
438
+ @ cellpadding: 0
439
+ },
440
+ { "td.timelineTableCell",
441
+ "the format for the timeline data cells",
442
+ @ valign: top;
443
+ @ align: left;
444
+ },
445
+ { "span.timelineLeaf",
446
+ "the format for the timeline leaf marks",
447
+ @ font-weight: bold;
448
+ },
449
+ { "a.timelineHistLink",
450
+ "the format for the timeline version links",
451
+ @
452
+ },
453
+ { "span.timelineHistDsp",
454
+ "the format for the timeline version display(no history permission!)",
455
+ @ font-weight: bold;
456
+ },
457
+ { "td.timelineTime",
458
+ "the format for the timeline time display",
459
+ @ vertical-align: top;
460
+ @ text-align: right;
461
+ },
462
+ { "td.timelineGraph",
463
+ "the format for the grap placeholder cells in timelines",
464
+ @ width: 20;
465
+ @ text-align: left;
466
+ @ vertical-align: top;
467
+ },
468
+ { "a.tagLink",
469
+ "the format for the tag links",
470
+ @
471
+ },
472
+ { "span.tagDsp",
473
+ "the format for the tag display(no history permission!)",
474
+ @ font-weight: bold;
475
+ },
476
+ { "span.wikiError",
477
+ "the format for wiki errors",
478
+ @ font-weight: bold;
479
+ @ color: red;
480
+ },
481
+ { "span.infoTagCancelled",
482
+ "the format for fixed/canceled tags,..",
483
+ @ font-weight: bold;
484
+ @ text-decoration: line-through;
485
+ },
486
+ { "span.infoTag",
487
+ "the format for tags,..",
488
+ @ font-weight: bold;
489
+ },
490
+ { "span.wikiTagCancelled",
491
+ "the format for fixed/cancelled tags,.. on wiki pages",
492
+ @ text-decoration: line-through;
493
+ },
494
+ { "table.browser",
495
+ "format for the file display table",
496
+ @ /* the format for wiki errors */
497
+ @ width: 100% ;
498
+ @ border: 0;
499
+ },
500
+ { "td.browser",
501
+ "format for cells in the file browser",
502
+ @ width: 24% ;
503
+ @ vertical-align: top;
504
+ },
505
+ { "ul.browser",
506
+ "format for the list in the file browser",
507
+ @ margin-left: 0.5em;
508
+ @ padding-left: 0.5em;
509
+ },
510
+ { "table.login_out",
511
+ "table format for login/out label/input table",
512
+ @ text-align: left;
513
+ @ margin-right: 10px;
514
+ @ margin-left: 10px;
515
+ @ margin-top: 10px;
516
+ },
517
+ { "div.captcha",
518
+ "captcha display options",
519
+ @ text-align: center;
520
+ },
521
+ { "table.captcha",
522
+ "format for the layout table, used for the captcha display",
523
+ @ margin: auto;
524
+ @ padding: 10px;
525
+ @ outline-width: 1;
526
+ @ outline-style: double;
527
+ },
528
+ { "td.login_out_label",
529
+ "format for the label cells in the login/out table",
530
+ @ text-align: center;
531
+ },
532
+ { "span.loginError",
533
+ "format for login error messages",
534
+ @ color: red;
535
+ },
536
+ { "span.note",
537
+ "format for leading text for notes",
538
+ @ font-weight: bold;
539
+ },
540
+ { "span.textareaLabel",
541
+ "format for textare labels",
542
+ @ font-weight: bold;
543
+ },
544
+ { "table.usetupLayoutTable",
545
+ "format for the user setup layout table",
546
+ @ outline-style: none;
547
+ @ padding: 0;
548
+ @ margin: 25px;
549
+ },
550
+ { "td.usetupColumnLayout",
551
+ "format of the columns on the user setup list page",
552
+ @ vertical-align: top
553
+ },
554
+ { "table.usetupUserList",
555
+ "format for the user list table on the user setup page",
556
+ @ outline-style: double;
557
+ @ outline-width: 1;
558
+ @ padding: 10px;
559
+ },
560
+ { "th.usetupListUser",
561
+ "format for table header user in user list on user setup page",
562
+ @ text-align: right;
563
+ @ padding-right: 20px;
564
+ },
565
+ { "th.usetupListCap",
566
+ "format for table header capabilities in user list on user setup page",
567
+ @ text-align: center;
568
+ @ padding-right: 15px;
569
+ },
570
+ { "th.usetupListCon",
571
+ "format for table header contact info in user list on user setup page",
572
+ @ text-align: left;
573
+ },
574
+ { "td.usetupListUser",
575
+ "format for table cell user in user list on user setup page",
576
+ @ text-align: right;
577
+ @ padding-right: 20px;
578
+ @ white-space:nowrap;
579
+ },
580
+ { "td.usetupListCap",
581
+ "format for table cell capabilities in user list on user setup page",
582
+ @ text-align: center;
583
+ @ padding-right: 15px;
584
+ },
585
+ { "td.usetupListCon",
586
+ "format for table cell contact info in user list on user setup page",
587
+ @ text-align: left
588
+ },
589
+ { "div.ueditCapBox",
590
+ "layout definition for the capabilities box on the user edit detail page",
591
+ @ float: left;
592
+ @ margin-right: 20px;
593
+ @ margin-bottom: 20px;
594
+ },
595
+ { "td.usetupEditLabel",
596
+ "format of the label cells in the detailed user edit page",
597
+ @ text-align: right;
598
+ @ vertical-align: top;
599
+ @ white-space: nowrap;
600
+ },
601
+ { "span.ueditInheritNobody",
602
+ "color for capabilities, inherited by nobody",
603
+ @ color: green;
604
+ },
605
+ { "span.ueditInheritDeveloper",
606
+ "color for capabilities, inherited by developer",
607
+ @ color: red;
608
+ },
609
+ { "span.ueditInheritReader",
610
+ "color for capabilities, inherited by reader",
611
+ @ color: black;
612
+ },
613
+ { "span.ueditInheritAnonymous",
614
+ "color for capabilities, inherited by anonymous",
615
+ @ color: blue;
616
+ },
617
+ { "span.capability",
618
+ "format for capabilites, mentioned on the user edit page",
619
+ @ font-weight: bold;
620
+ },
621
+ { "span.usertype",
622
+ "format for different user types, mentioned on the user edit page",
623
+ @ font-weight: bold;
624
+ },
625
+ { "span.usertype:before",
626
+ "leading text for user types, mentioned on the user edit page",
627
+ @ content:"'";
628
+ },
629
+ { "span.usertype:after",
630
+ "trailing text for user types, mentioned on the user edit page",
631
+ @ content:"'";
632
+ },
633
+ { "span.wikiruleHead",
634
+ "format for leading text in wikirules definitions",
635
+ @ font-weight: bold;
636
+ },
637
+ { "td.tktDspLabel",
638
+ "format for labels on ticket display page",
639
+ @ text-align: right;
640
+ },
641
+ { "td.tktDspValue",
642
+ "format for values on ticket display page",
643
+ @ text-align: left;
644
+ @ vertical-align: top;
645
+ @ background-color: #d0d0d0;
646
+ },
647
+ { "span.tktError",
648
+ "format for ticket error messages",
649
+ @ color: red;
650
+ @ font-weight: bold;
651
+ },
652
+ { 0,
653
+ 0,
654
+ 0
655
+ }
656
+};
657
+
658
+/*
659
+** Append all of the default CSS to the CGI output.
660
+*/
661
+void cgi_append_default_css(void) {
662
+ int i;
663
+
664
+ for (i=0;cssDefaultList[i].elementClass;i++){
665
+ if (cssDefaultList[i].elementClass[0]){
666
+ cgi_printf("/* %s */\n%s {\n%s\n}\n\n",
667
+ cssDefaultList[i].comment,
668
+ cssDefaultList[i].elementClass,
669
+ cssDefaultList[i].value
670
+ );
671
+ }else{
672
+ cgi_printf("%s",
673
+ cssDefaultList[i].value
674
+ );
675
+ }
676
+ }
677
+}
417678
418679
/*
419680
** WEBPAGE: style.css
420681
*/
421682
void page_style_css(void){
422
- const char *zCSS;
683
+ const char *zCSS = 0;
423684
int i;
424685
425686
cgi_set_content_type("text/css");
426687
zCSS = db_get("css",(char*)zDefaultCSS);
427688
/* append user defined css */
428689
cgi_append_content(zCSS, -1);
429690
/* add special missing definitions */
430
- for(i=0; i<count(cssElements); i++){
431
- if( strstr(cssElements[i].zElement, zCSS)==0 ){
432
- cgi_append_content(cssElements[i].zText, -1);
691
+ for (i=1;cssDefaultList[i].elementClass;i++)
692
+ if (!strstr(zCSS,cssDefaultList[i].elementClass)) {
693
+ cgi_append_content("/* ", -1);
694
+ cgi_append_content(cssDefaultList[i].comment, -1);
695
+ cgi_append_content(" */\n", -1);
696
+ cgi_append_content(cssDefaultList[i].elementClass, -1);
697
+ cgi_append_content(" {\n", -1);
698
+ cgi_append_content(cssDefaultList[i].value, -1);
699
+ cgi_append_content("}\n\n", -1);
433700
}
434
- }
435701
g.isConst = 1;
436702
}
437703
438704
/*
439705
** WEBPAGE: test_env
440706
*/
441707
void page_test_env(void){
442708
style_header("Environment Test");
443709
#if !defined(_WIN32)
444
- @ uid=%d(getuid()), gid=%d(getgid())<br>
710
+ @ uid=%d(getuid()), gid=%d(getgid())<br />
445711
#endif
446
- @ g.zBaseURL = %h(g.zBaseURL)<br>
447
- @ g.zTop = %h(g.zTop)<br>
712
+ @ g.zBaseURL = %h(g.zBaseURL)<br />
713
+ @ g.zTop = %h(g.zTop)<br />
448714
cgi_print_all();
449715
style_footer();
450716
}
451717
--- src/style.c
+++ src/style.c
@@ -139,20 +139,23 @@
139 }
140 @ <div class="content">
141 cgi_destination(CGI_BODY);
142
143 /* Put the footer at the bottom of the page.
 
 
144 */
145 @ </div><br clear="both"/>
 
146 zFooter = db_get("footer", (char*)zDefaultFooter);
147 if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1);
148 Th_Render(zFooter);
149 if( g.thTrace ) Th_Trace("END_FOOTER<br />\n", -1);
150
151 /* Render trace log if TH1 tracing is enabled. */
152 if( g.thTrace ){
153 cgi_append_content("<font color=\"red\"><hr>\n", -1);
154 cgi_append_content(blob_str(&g.thLog), blob_size(&g.thLog));
155 cgi_append_content("</font>\n", -1);
156 }
157 }
158
@@ -179,27 +182,27 @@
179 const char zDefaultHeader[] =
180 @ <html>
181 @ <head>
182 @ <title>$<project_name>: $<title></title>
183 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
184 @ href="$baseurl/timeline.rss">
185 @ <link rel="stylesheet" href="$baseurl/style.css?default" type="text/css"
186 @ media="screen">
187 @ </head>
188 @ <body>
189 @ <div class="header">
190 @ <div class="logo">
191 @ <img src="$baseurl/logo" alt="logo">
192 @ </div>
193 @ <div class="title"><small>$<project_name></small><br>$<title></div>
194 @ <div class="status"><nobr><th1>
195 @ if {[info exists login]} {
196 @ puts "Logged in as $login"
197 @ } else {
198 @ puts "Not logged in"
199 @ }
200 @ </th1></nobr></div>
201 @ </div>
202 @ <div class="mainmenu"><th1>
203 @ html "<a href='$baseurl$index_page'>Home</a> "
204 @ if {[anycap jor]} {
205 @ html "<a href='$baseurl/timeline'>Timeline</a> "
@@ -274,11 +277,11 @@
274 @ font-weight: bold;
275 @ text-align: center;
276 @ padding: 0 0 0 1em;
277 @ color: #558195;
278 @ vertical-align: bottom;
279 @ width: 100%;
280 @ }
281 @
282 @ /* The login status message in the top right-hand corner */
283 @ div.status {
284 @ display: table-cell;
@@ -286,16 +289,17 @@
286 @ vertical-align: bottom;
287 @ color: #558195;
288 @ font-size: 0.8em;
289 @ font-weight: bold;
290 @ min-width: 200px;
 
291 @ }
292 @
293 @ /* The header across the top of the page */
294 @ div.header {
295 @ display: table;
296 @ width: 100%;
297 @ }
298 @
299 @ /* The main menu bar that appears at the top of the page beneath
300 @ ** the header */
301 @ div.mainmenu {
@@ -339,10 +343,11 @@
339 @ padding: 1px 1px 1px 1px;
340 @ font-size: 1.2em;
341 @ font-weight: bold;
342 @ background-color: #558195;
343 @ color: white;
 
344 @ }
345 @
346 @ /* The "Date" that occurs on the left hand side of timelines */
347 @ div.divider {
348 @ background: #a1c4d4;
@@ -368,83 +373,344 @@
368 @ div.footer a { color: white; }
369 @ div.footer a:link { color: white; }
370 @ div.footer a:visited { color: white; }
371 @ div.footer a:hover { background-color: white; color: #558195; }
372 @
373 @ /* <verbatim> blocks */
374 @ pre.verbatim {
375 @ background-color: #f5f5f5;
376 @ padding: 0.5em;
377 @}
378 @
379 ;
380 const char zTableLabelValueCSS[] =
381 @ /* The label/value pairs on (for example) the ci page */
382 @ table.label-value th {
383 @ vertical-align: top;
384 @ text-align: right;
385 @ padding: 0.2ex 2ex;
386 @ }
387 ;
388 const char zDivSidebox[] =
389 @ /* The nomenclature sidebox for branches,.. */
390 @ div.sidebox {
391 @ float: right;
392 @ border-width: medium;
393 @ border-style: double;
394 @ margin: 10;
395 @ }
396 ;
397 const char zDivSideboxTitle[] =
398 @ /* The nomenclature title in sideboxes for branches,.. */
399 @ div.sideboxTitle {
400 @ display: inline;
401 @ font-weight: bold;
402 @ }
403 ;
404
405
406 /* The following table holds the names of CSS elements and the CSS
407 ** text that implements those elements.
408 */
409 static const struct {
410 const char *zElement; /* Name of the CSS element */
411 const char *zText; /* Text of the element */
412 } cssElements[] = {
413 { "table.label-value", zTableLabelValueCSS },
414 { "div.sidebox", zDivSidebox },
415 { "div.sideboxTitle", zDivSideboxTitle },
416 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
417
418 /*
419 ** WEBPAGE: style.css
420 */
421 void page_style_css(void){
422 const char *zCSS;
423 int i;
424
425 cgi_set_content_type("text/css");
426 zCSS = db_get("css",(char*)zDefaultCSS);
427 /* append user defined css */
428 cgi_append_content(zCSS, -1);
429 /* add special missing definitions */
430 for(i=0; i<count(cssElements); i++){
431 if( strstr(cssElements[i].zElement, zCSS)==0 ){
432 cgi_append_content(cssElements[i].zText, -1);
 
 
 
 
 
 
433 }
434 }
435 g.isConst = 1;
436 }
437
438 /*
439 ** WEBPAGE: test_env
440 */
441 void page_test_env(void){
442 style_header("Environment Test");
443 #if !defined(_WIN32)
444 @ uid=%d(getuid()), gid=%d(getgid())<br>
445 #endif
446 @ g.zBaseURL = %h(g.zBaseURL)<br>
447 @ g.zTop = %h(g.zTop)<br>
448 cgi_print_all();
449 style_footer();
450 }
451
--- src/style.c
+++ src/style.c
@@ -139,20 +139,23 @@
139 }
140 @ <div class="content">
141 cgi_destination(CGI_BODY);
142
143 /* Put the footer at the bottom of the page.
144 ** the additional clear/both is needed to extend the content
145 ** part to the end of an optional sidebox.
146 */
147 @ <div style="clear: both;"></div>
148 @ </div>
149 zFooter = db_get("footer", (char*)zDefaultFooter);
150 if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1);
151 Th_Render(zFooter);
152 if( g.thTrace ) Th_Trace("END_FOOTER<br />\n", -1);
153
154 /* Render trace log if TH1 tracing is enabled. */
155 if( g.thTrace ){
156 cgi_append_content("<font color=\"red\"><hr />\n", -1);
157 cgi_append_content(blob_str(&g.thLog), blob_size(&g.thLog));
158 cgi_append_content("</font>\n", -1);
159 }
160 }
161
@@ -179,27 +182,27 @@
182 const char zDefaultHeader[] =
183 @ <html>
184 @ <head>
185 @ <title>$<project_name>: $<title></title>
186 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed"
187 @ href="$baseurl/timeline.rss" />
188 @ <link rel="stylesheet" href="$baseurl/style.css?default" type="text/css"
189 @ media="screen" />
190 @ </head>
191 @ <body>
192 @ <div class="header">
193 @ <div class="logo">
194 @ <img src="$baseurl/logo" alt="logo">
195 @ </div>
196 @ <div class="title"><small>$<project_name></small><br />$<title></div>
197 @ <div class="status"><th1>
198 @ if {[info exists login]} {
199 @ puts "Logged in as $login"
200 @ } else {
201 @ puts "Not logged in"
202 @ }
203 @ </th1></div>
204 @ </div>
205 @ <div class="mainmenu"><th1>
206 @ html "<a href='$baseurl$index_page'>Home</a> "
207 @ if {[anycap jor]} {
208 @ html "<a href='$baseurl/timeline'>Timeline</a> "
@@ -274,11 +277,11 @@
277 @ font-weight: bold;
278 @ text-align: center;
279 @ padding: 0 0 0 1em;
280 @ color: #558195;
281 @ vertical-align: bottom;
282 @ width: 100% ;
283 @ }
284 @
285 @ /* The login status message in the top right-hand corner */
286 @ div.status {
287 @ display: table-cell;
@@ -286,16 +289,17 @@
289 @ vertical-align: bottom;
290 @ color: #558195;
291 @ font-size: 0.8em;
292 @ font-weight: bold;
293 @ min-width: 200px;
294 @ white-space: nowrap;
295 @ }
296 @
297 @ /* The header across the top of the page */
298 @ div.header {
299 @ display: table;
300 @ width: 100% ;
301 @ }
302 @
303 @ /* The main menu bar that appears at the top of the page beneath
304 @ ** the header */
305 @ div.mainmenu {
@@ -339,10 +343,11 @@
343 @ padding: 1px 1px 1px 1px;
344 @ font-size: 1.2em;
345 @ font-weight: bold;
346 @ background-color: #558195;
347 @ color: white;
348 @ white-space: nowrap;
349 @ }
350 @
351 @ /* The "Date" that occurs on the left hand side of timelines */
352 @ div.divider {
353 @ background: #a1c4d4;
@@ -368,83 +373,344 @@
373 @ div.footer a { color: white; }
374 @ div.footer a:link { color: white; }
375 @ div.footer a:visited { color: white; }
376 @ div.footer a:hover { background-color: white; color: #558195; }
377 @
378 @ /* verbatim blocks */
379 @ pre.verbatim {
380 @ background-color: #f5f5f5;
381 @ padding: 0.5em;
382 @}
383 @
 
 
384 @ /* The label/value pairs on (for example) the ci page */
385 @ table.label-value th {
386 @ vertical-align: top;
387 @ text-align: right;
388 @ padding: 0.2ex 2ex;
389 @ }
390 @
391 ;
392
393
394 /* The following table contains bits of default CSS that must
395 ** be included if they are not found in the application-defined
396 ** CSS.
397 */
398 const struct strctCssDefaults {
399 char const * const elementClass; /* Name of element needed */
400 char const * const comment; /* Comment text */
401 char const * const value; /* CSS text */
402 } cssDefaultList[] = {
403 { "",
404 "",
405 zDefaultCSS
406 },
407 { "div.sidebox",
408 "The nomenclature sidebox for branches,..",
409 @ float: right;
410 @ background-color: white;
411 @ border-width: medium;
412 @ border-style: double;
413 @ margin: 10;
414 },
415 { "div.sideboxTitle",
416 "The nomenclature title in sideboxes for branches,..",
417 @ display: inline;
418 @ font-weight: bold;
419 },
420 { "div.sideboxDescribed",
421 "The defined element in sideboxes for branches,..",
422 @ display: inline;
423 @ font-weight: bold;
424 },
425 { "span.disabled",
426 "The defined element in sideboxes for branches,..",
427 @ color: red;
428 },
429 { "span.timelineDisabled",
430 "The suppressed duplicates lines in timeline, ..",
431 @ font-style: italic;
432 @ font-size: small;
433 },
434 { "table.timelineTable",
435 "the format for the timeline data table",
436 @ cellspacing: 0;
437 @ border: 0;
438 @ cellpadding: 0
439 },
440 { "td.timelineTableCell",
441 "the format for the timeline data cells",
442 @ valign: top;
443 @ align: left;
444 },
445 { "span.timelineLeaf",
446 "the format for the timeline leaf marks",
447 @ font-weight: bold;
448 },
449 { "a.timelineHistLink",
450 "the format for the timeline version links",
451 @
452 },
453 { "span.timelineHistDsp",
454 "the format for the timeline version display(no history permission!)",
455 @ font-weight: bold;
456 },
457 { "td.timelineTime",
458 "the format for the timeline time display",
459 @ vertical-align: top;
460 @ text-align: right;
461 },
462 { "td.timelineGraph",
463 "the format for the grap placeholder cells in timelines",
464 @ width: 20;
465 @ text-align: left;
466 @ vertical-align: top;
467 },
468 { "a.tagLink",
469 "the format for the tag links",
470 @
471 },
472 { "span.tagDsp",
473 "the format for the tag display(no history permission!)",
474 @ font-weight: bold;
475 },
476 { "span.wikiError",
477 "the format for wiki errors",
478 @ font-weight: bold;
479 @ color: red;
480 },
481 { "span.infoTagCancelled",
482 "the format for fixed/canceled tags,..",
483 @ font-weight: bold;
484 @ text-decoration: line-through;
485 },
486 { "span.infoTag",
487 "the format for tags,..",
488 @ font-weight: bold;
489 },
490 { "span.wikiTagCancelled",
491 "the format for fixed/cancelled tags,.. on wiki pages",
492 @ text-decoration: line-through;
493 },
494 { "table.browser",
495 "format for the file display table",
496 @ /* the format for wiki errors */
497 @ width: 100% ;
498 @ border: 0;
499 },
500 { "td.browser",
501 "format for cells in the file browser",
502 @ width: 24% ;
503 @ vertical-align: top;
504 },
505 { "ul.browser",
506 "format for the list in the file browser",
507 @ margin-left: 0.5em;
508 @ padding-left: 0.5em;
509 },
510 { "table.login_out",
511 "table format for login/out label/input table",
512 @ text-align: left;
513 @ margin-right: 10px;
514 @ margin-left: 10px;
515 @ margin-top: 10px;
516 },
517 { "div.captcha",
518 "captcha display options",
519 @ text-align: center;
520 },
521 { "table.captcha",
522 "format for the layout table, used for the captcha display",
523 @ margin: auto;
524 @ padding: 10px;
525 @ outline-width: 1;
526 @ outline-style: double;
527 },
528 { "td.login_out_label",
529 "format for the label cells in the login/out table",
530 @ text-align: center;
531 },
532 { "span.loginError",
533 "format for login error messages",
534 @ color: red;
535 },
536 { "span.note",
537 "format for leading text for notes",
538 @ font-weight: bold;
539 },
540 { "span.textareaLabel",
541 "format for textare labels",
542 @ font-weight: bold;
543 },
544 { "table.usetupLayoutTable",
545 "format for the user setup layout table",
546 @ outline-style: none;
547 @ padding: 0;
548 @ margin: 25px;
549 },
550 { "td.usetupColumnLayout",
551 "format of the columns on the user setup list page",
552 @ vertical-align: top
553 },
554 { "table.usetupUserList",
555 "format for the user list table on the user setup page",
556 @ outline-style: double;
557 @ outline-width: 1;
558 @ padding: 10px;
559 },
560 { "th.usetupListUser",
561 "format for table header user in user list on user setup page",
562 @ text-align: right;
563 @ padding-right: 20px;
564 },
565 { "th.usetupListCap",
566 "format for table header capabilities in user list on user setup page",
567 @ text-align: center;
568 @ padding-right: 15px;
569 },
570 { "th.usetupListCon",
571 "format for table header contact info in user list on user setup page",
572 @ text-align: left;
573 },
574 { "td.usetupListUser",
575 "format for table cell user in user list on user setup page",
576 @ text-align: right;
577 @ padding-right: 20px;
578 @ white-space:nowrap;
579 },
580 { "td.usetupListCap",
581 "format for table cell capabilities in user list on user setup page",
582 @ text-align: center;
583 @ padding-right: 15px;
584 },
585 { "td.usetupListCon",
586 "format for table cell contact info in user list on user setup page",
587 @ text-align: left
588 },
589 { "div.ueditCapBox",
590 "layout definition for the capabilities box on the user edit detail page",
591 @ float: left;
592 @ margin-right: 20px;
593 @ margin-bottom: 20px;
594 },
595 { "td.usetupEditLabel",
596 "format of the label cells in the detailed user edit page",
597 @ text-align: right;
598 @ vertical-align: top;
599 @ white-space: nowrap;
600 },
601 { "span.ueditInheritNobody",
602 "color for capabilities, inherited by nobody",
603 @ color: green;
604 },
605 { "span.ueditInheritDeveloper",
606 "color for capabilities, inherited by developer",
607 @ color: red;
608 },
609 { "span.ueditInheritReader",
610 "color for capabilities, inherited by reader",
611 @ color: black;
612 },
613 { "span.ueditInheritAnonymous",
614 "color for capabilities, inherited by anonymous",
615 @ color: blue;
616 },
617 { "span.capability",
618 "format for capabilites, mentioned on the user edit page",
619 @ font-weight: bold;
620 },
621 { "span.usertype",
622 "format for different user types, mentioned on the user edit page",
623 @ font-weight: bold;
624 },
625 { "span.usertype:before",
626 "leading text for user types, mentioned on the user edit page",
627 @ content:"'";
628 },
629 { "span.usertype:after",
630 "trailing text for user types, mentioned on the user edit page",
631 @ content:"'";
632 },
633 { "span.wikiruleHead",
634 "format for leading text in wikirules definitions",
635 @ font-weight: bold;
636 },
637 { "td.tktDspLabel",
638 "format for labels on ticket display page",
639 @ text-align: right;
640 },
641 { "td.tktDspValue",
642 "format for values on ticket display page",
643 @ text-align: left;
644 @ vertical-align: top;
645 @ background-color: #d0d0d0;
646 },
647 { "span.tktError",
648 "format for ticket error messages",
649 @ color: red;
650 @ font-weight: bold;
651 },
652 { 0,
653 0,
654 0
655 }
656 };
657
658 /*
659 ** Append all of the default CSS to the CGI output.
660 */
661 void cgi_append_default_css(void) {
662 int i;
663
664 for (i=0;cssDefaultList[i].elementClass;i++){
665 if (cssDefaultList[i].elementClass[0]){
666 cgi_printf("/* %s */\n%s {\n%s\n}\n\n",
667 cssDefaultList[i].comment,
668 cssDefaultList[i].elementClass,
669 cssDefaultList[i].value
670 );
671 }else{
672 cgi_printf("%s",
673 cssDefaultList[i].value
674 );
675 }
676 }
677 }
678
679 /*
680 ** WEBPAGE: style.css
681 */
682 void page_style_css(void){
683 const char *zCSS = 0;
684 int i;
685
686 cgi_set_content_type("text/css");
687 zCSS = db_get("css",(char*)zDefaultCSS);
688 /* append user defined css */
689 cgi_append_content(zCSS, -1);
690 /* add special missing definitions */
691 for (i=1;cssDefaultList[i].elementClass;i++)
692 if (!strstr(zCSS,cssDefaultList[i].elementClass)) {
693 cgi_append_content("/* ", -1);
694 cgi_append_content(cssDefaultList[i].comment, -1);
695 cgi_append_content(" */\n", -1);
696 cgi_append_content(cssDefaultList[i].elementClass, -1);
697 cgi_append_content(" {\n", -1);
698 cgi_append_content(cssDefaultList[i].value, -1);
699 cgi_append_content("}\n\n", -1);
700 }
 
701 g.isConst = 1;
702 }
703
704 /*
705 ** WEBPAGE: test_env
706 */
707 void page_test_env(void){
708 style_header("Environment Test");
709 #if !defined(_WIN32)
710 @ uid=%d(getuid()), gid=%d(getgid())<br />
711 #endif
712 @ g.zBaseURL = %h(g.zBaseURL)<br />
713 @ g.zTop = %h(g.zTop)<br />
714 cgi_print_all();
715 style_footer();
716 }
717
+8 -6
--- src/tag.c
+++ src/tag.c
@@ -514,13 +514,14 @@
514514
);
515515
@ <ul>
516516
while( db_step(&q)==SQLITE_ROW ){
517517
const char *zName = db_column_text(&q, 0);
518518
if( g.okHistory ){
519
- @ <li><a href=%s(g.zBaseURL)/timeline?t=%T(zName)>%h(zName)</a></li>
519
+ @ <li><a class="tagLink" href="%s(g.zBaseURL)/timeline?t=%T(zName)">
520
+ @ %h(zName)</a></li>
520521
}else{
521
- @ <li><strong>%h(zName)</strong></li>
522
+ @ <li><span class="tagDsp">%h(zName)</span></li>
522523
}
523524
}
524525
@ </ul>
525526
db_finalize(&q);
526527
style_footer();
@@ -542,13 +543,14 @@
542543
rid
543544
);
544545
while( db_step(&q)==SQLITE_ROW ){
545546
const char *zTagName = db_column_text(&q, 0);
546547
if( g.okHistory ){
547
- @ <a href="%s(g.zBaseURL)/timeline?t=%T(zTagName)">[%h(zTagName)]</a>
548
+ @ <a class="tagLink" href="%s(g.zBaseURL)/timeline?t=%T(zTagName)">
549
+ @ [%h(zTagName)]</a>
548550
}else{
549
- @ <b>[%h(zTagName)]</b>
551
+ @ <span class="tagDsp">[%h(zTagName)]</span>
550552
}
551553
}
552554
db_finalize(&q);
553555
}
554556
@@ -573,14 +575,14 @@
573575
" ORDER BY event.mtime DESC",
574576
timeline_query_for_www()
575577
);
576578
www_print_timeline(&q, 0, tagtimeline_extra);
577579
db_finalize(&q);
578
- @ <br clear="both">
579
- @ <script>
580
+ @ <br />
581
+ @ <script type="text/JavaScript">
580582
@ function xin(id){
581583
@ }
582584
@ function xout(id){
583585
@ }
584586
@ </script>
585587
style_footer();
586588
}
587589
--- src/tag.c
+++ src/tag.c
@@ -514,13 +514,14 @@
514 );
515 @ <ul>
516 while( db_step(&q)==SQLITE_ROW ){
517 const char *zName = db_column_text(&q, 0);
518 if( g.okHistory ){
519 @ <li><a href=%s(g.zBaseURL)/timeline?t=%T(zName)>%h(zName)</a></li>
 
520 }else{
521 @ <li><strong>%h(zName)</strong></li>
522 }
523 }
524 @ </ul>
525 db_finalize(&q);
526 style_footer();
@@ -542,13 +543,14 @@
542 rid
543 );
544 while( db_step(&q)==SQLITE_ROW ){
545 const char *zTagName = db_column_text(&q, 0);
546 if( g.okHistory ){
547 @ <a href="%s(g.zBaseURL)/timeline?t=%T(zTagName)">[%h(zTagName)]</a>
 
548 }else{
549 @ <b>[%h(zTagName)]</b>
550 }
551 }
552 db_finalize(&q);
553 }
554
@@ -573,14 +575,14 @@
573 " ORDER BY event.mtime DESC",
574 timeline_query_for_www()
575 );
576 www_print_timeline(&q, 0, tagtimeline_extra);
577 db_finalize(&q);
578 @ <br clear="both">
579 @ <script>
580 @ function xin(id){
581 @ }
582 @ function xout(id){
583 @ }
584 @ </script>
585 style_footer();
586 }
587
--- src/tag.c
+++ src/tag.c
@@ -514,13 +514,14 @@
514 );
515 @ <ul>
516 while( db_step(&q)==SQLITE_ROW ){
517 const char *zName = db_column_text(&q, 0);
518 if( g.okHistory ){
519 @ <li><a class="tagLink" href="%s(g.zBaseURL)/timeline?t=%T(zName)">
520 @ %h(zName)</a></li>
521 }else{
522 @ <li><span class="tagDsp">%h(zName)</span></li>
523 }
524 }
525 @ </ul>
526 db_finalize(&q);
527 style_footer();
@@ -542,13 +543,14 @@
543 rid
544 );
545 while( db_step(&q)==SQLITE_ROW ){
546 const char *zTagName = db_column_text(&q, 0);
547 if( g.okHistory ){
548 @ <a class="tagLink" href="%s(g.zBaseURL)/timeline?t=%T(zTagName)">
549 @ [%h(zTagName)]</a>
550 }else{
551 @ <span class="tagDsp">[%h(zTagName)]</span>
552 }
553 }
554 db_finalize(&q);
555 }
556
@@ -573,14 +575,14 @@
575 " ORDER BY event.mtime DESC",
576 timeline_query_for_www()
577 );
578 www_print_timeline(&q, 0, tagtimeline_extra);
579 db_finalize(&q);
580 @ <br />
581 @ <script type="text/JavaScript">
582 @ function xin(id){
583 @ }
584 @ function xout(id){
585 @ }
586 @ </script>
587 style_footer();
588 }
589
+2 -1
--- src/th_main.c
+++ src/th_main.c
@@ -278,11 +278,12 @@
278278
blob_reset(&name);
279279
for(i=0; i<nElem; i++){
280280
zH = htmlize((char*)azElem[i], aszElem[i]);
281281
if( zValue && aszElem[i]==nValue
282282
&& memcmp(zValue, azElem[i], nValue)==0 ){
283
- z = mprintf("<option value=\"%s\" selected>%s</option>", zH, zH);
283
+ z = mprintf("<option value=\"%s\" selected=\"selected\">%s</option>",
284
+ zH, zH);
284285
}else{
285286
z = mprintf("<option value=\"%s\">%s</option>", zH, zH);
286287
}
287288
free(zH);
288289
sendText(z, -1, 0);
289290
--- src/th_main.c
+++ src/th_main.c
@@ -278,11 +278,12 @@
278 blob_reset(&name);
279 for(i=0; i<nElem; i++){
280 zH = htmlize((char*)azElem[i], aszElem[i]);
281 if( zValue && aszElem[i]==nValue
282 && memcmp(zValue, azElem[i], nValue)==0 ){
283 z = mprintf("<option value=\"%s\" selected>%s</option>", zH, zH);
 
284 }else{
285 z = mprintf("<option value=\"%s\">%s</option>", zH, zH);
286 }
287 free(zH);
288 sendText(z, -1, 0);
289
--- src/th_main.c
+++ src/th_main.c
@@ -278,11 +278,12 @@
278 blob_reset(&name);
279 for(i=0; i<nElem; i++){
280 zH = htmlize((char*)azElem[i], aszElem[i]);
281 if( zValue && aszElem[i]==nValue
282 && memcmp(zValue, azElem[i], nValue)==0 ){
283 z = mprintf("<option value=\"%s\" selected=\"selected\">%s</option>",
284 zH, zH);
285 }else{
286 z = mprintf("<option value=\"%s\">%s</option>", zH, zH);
287 }
288 free(zH);
289 sendText(z, -1, 0);
290
+33 -24
--- src/timeline.c
+++ src/timeline.c
@@ -48,13 +48,14 @@
4848
*/
4949
void hyperlink_to_uuid(const char *zUuid){
5050
char zShortUuid[UUID_SIZE+1];
5151
shorten_uuid(zShortUuid, zUuid);
5252
if( g.okHistory ){
53
- @ <a href="%s(g.zBaseURL)/info/%s(zShortUuid)">[%s(zShortUuid)]</a>
53
+ @ <a class="timelineHistLink" href="%s(g.zBaseURL)/info/%s(zShortUuid)">
54
+ @ [%s(zShortUuid)]</a>
5455
}else{
55
- @ <b>[%s(zShortUuid)]</b>
56
+ @ <span class="timelineHistDsp">[%s(zShortUuid)]</span>
5657
}
5758
}
5859
5960
/*
6061
** Generate a hyperlink that invokes javascript to highlight
@@ -83,11 +84,11 @@
8384
void hyperlink_to_diff(const char *zV1, const char *zV2){
8485
if( g.okHistory ){
8586
if( zV2==0 ){
8687
@ <a href="%s(g.zBaseURL)/diff?v2=%s(zV1)">[diff]</a>
8788
}else{
88
- @ <a href="%s(g.zBaseURL)/diff?v1=%s(zV1)&v2=%s(zV2)">[diff]</a>
89
+ @ <a href="%s(g.zBaseURL)/diff?v1=%s(zV1)&amp;v2=%s(zV2)">[diff]</a>
8990
}
9091
}
9192
}
9293
9394
/*
@@ -109,11 +110,11 @@
109110
*/
110111
void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){
111112
if( zSuf==0 ) zSuf = "";
112113
if( g.okHistory ){
113114
if( zD && zD[0] ){
114
- @ <a href="%s(g.zTop)/timeline?c=%T(zD)&u=%T(zU)">%h(zU)</a>%s(zSuf)
115
+ @ <a href="%s(g.zTop)/timeline?c=%T(zD)&amp;u=%T(zU)">%h(zU)</a>%s(zSuf)
115116
}else{
116117
@ <a href="%s(g.zTop)/timeline?u=%T(zU)">%h(zU)</a>%s(zSuf)
117118
}
118119
}else{
119120
@ %s(zU)
@@ -189,14 +190,17 @@
189190
}else{
190191
wikiFlags = WIKI_INLINE | WIKI_NOBLOCK;
191192
}
192193
if( tmFlags & TIMELINE_GRAPH ){
193194
pGraph = graph_init();
195
+ /* style is not moved to css, because this is
196
+ ** a technical div for the timeline graph
197
+ */
194198
@ <div id="canvas" style="position:relative;width:1px;height:1px;"></div>
195199
}
196200
197
- @ <table cellspacing=0 border=0 cellpadding=0>
201
+ @ <table class="timelineTable">
198202
blob_zero(&comment);
199203
while( db_step(pQuery)==SQLITE_ROW ){
200204
int rid = db_column_int(pQuery, 0);
201205
const char *zUuid = db_column_text(pQuery, 1);
202206
int isLeaf = db_column_int(pQuery, 5);
@@ -218,30 +222,30 @@
218222
}
219223
}
220224
}
221225
prevTagid = tagid;
222226
if( suppressCnt ){
223
- @ <tr><td><td><td>
224
- @ <small><i>... %d(suppressCnt) similar
225
- @ event%s(suppressCnt>1?"s":"") omitted.</i></small></tr>
227
+ @ <tr><td /><td /><td>
228
+ @ <span class="timelineDisabled">... %d(suppressCnt) similar
229
+ @ event%s(suppressCnt>1?"s":"") omitted.</span></td></tr>
226230
suppressCnt = 0;
227231
}
228232
if( strcmp(zType,"div")==0 ){
229
- @ <tr><td colspan=3><hr></td></tr>
233
+ @ <tr><td colspan="3"><hr /></td></tr>
230234
continue;
231235
}
232236
if( memcmp(zDate, zPrevDate, 10) ){
233237
sprintf(zPrevDate, "%.10s", zDate);
234238
@ <tr><td>
235
- @ <div class="divider"><nobr>%s(zPrevDate)</nobr></div>
239
+ @ <div class="divider">%s(zPrevDate)</div>
236240
@ </td></tr>
237241
}
238242
memcpy(zTime, &zDate[11], 5);
239243
zTime[5] = 0;
240244
@ <tr>
241
- @ <td valign="top" align="right">%s(zTime)</td>
242
- @ <td width="20" align="left" valign="top">
245
+ @ <td class="timelineTime">%s(zTime)</td>
246
+ @ <td class="timelineGraph">
243247
if( pGraph && zType[0]=='c' ){
244248
int nParent = 0;
245249
int aParent[32];
246250
const char *zBr;
247251
int gidx;
@@ -267,24 +271,25 @@
267271
}
268272
gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr);
269273
db_reset(&qbranch);
270274
@ <div id="m%d(gidx)"></div>
271275
}
276
+ @</td>
272277
if( zBgClr && zBgClr[0] ){
273
- @ <td valign="top" align="left" bgcolor="%h(zBgClr)">
278
+ @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
274279
}else{
275
- @ <td valign="top" align="left">
280
+ @ <td class="timelineTableCell">
276281
}
277282
if( zType[0]=='c' ){
278283
hyperlink_to_uuid(zUuid);
279284
if( isLeaf ){
280285
if( db_exists("SELECT 1 FROM tagxref"
281286
" WHERE rid=%d AND tagid=%d AND tagtype>0",
282287
rid, TAG_CLOSED) ){
283
- @ <b>Closed-Leaf:</b>
288
+ @ <span class="timelineLeaf">Closed-Leaf:</span>
284289
}else{
285
- @ <b>Leaf:</b>
290
+ @ <span class="timelineLeaf">Leaf:</span>
286291
}
287292
}
288293
}else if( (tmFlags & TIMELINE_ARTID)!=0 ){
289294
hyperlink_to_uuid(zUuid);
290295
}
@@ -309,23 +314,27 @@
309314
xExtra(rid);
310315
}
311316
@ </td></tr>
312317
}
313318
if( suppressCnt ){
314
- @ <tr><td><td><td>
315
- @ <small><i>... %d(suppressCnt) similar
316
- @ event%s(suppressCnt>1?"s":"") omitted.</i></small></tr>
319
+ @ <tr><td /><td /><td>
320
+ @ <span class="timelineDisabled">... %d(suppressCnt) similar
321
+ @ event%s(suppressCnt>1?"s":"") omitted.</span></td></tr>
317322
suppressCnt = 0;
318323
}
319324
if( pGraph ){
320325
graph_finish(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0);
321326
if( pGraph->nErr ){
322327
graph_free(pGraph);
323328
pGraph = 0;
324329
}else{
325
- @ <tr><td><td>
330
+ /* style is not moved to css, because this is
331
+ ** a technical div for the timeline graph
332
+ */
333
+ @ <tr><td /><td>
326334
@ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div>
335
+ @ </td></tr>
327336
}
328337
}
329338
@ </table>
330339
timeline_output_graph_javascript(pGraph);
331340
}
@@ -337,11 +346,11 @@
337346
void timeline_output_graph_javascript(GraphContext *pGraph){
338347
if( pGraph && pGraph->nErr==0 ){
339348
GraphRow *pRow;
340349
int i;
341350
char cSep;
342
- @ <script type="text/JavaScript">
351
+ @ <script type="text/JavaScript">
343352
cgi_printf("var rowinfo = [\n");
344353
for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){
345354
cgi_printf("{id:\"m%d\",bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,au:",
346355
pRow->idx,
347356
pRow->zBgClr,
@@ -883,15 +892,15 @@
883892
}else if( zBrName ){
884893
blob_appendf(&desc, " related to \"%h\"", zBrName);
885894
tmFlags |= TIMELINE_DISJOINT;
886895
}
887896
if( zAfter ){
888
- blob_appendf(&desc, " occurring on or after %h.<br>", zAfter);
897
+ blob_appendf(&desc, " occurring on or after %h.<br />", zAfter);
889898
}else if( zBefore ){
890
- blob_appendf(&desc, " occurring on or before %h.<br>", zBefore);
899
+ blob_appendf(&desc, " occurring on or before %h.<br />", zBefore);
891900
}else if( zCirca ){
892
- blob_appendf(&desc, " occurring around %h.<br>", zCirca);
901
+ blob_appendf(&desc, " occurring around %h.<br />", zCirca);
893902
}
894903
if( zSearch ){
895904
blob_appendf(&desc, " matching \"%h\"", zSearch);
896905
}
897906
if( g.okHistory ){
898907
--- src/timeline.c
+++ src/timeline.c
@@ -48,13 +48,14 @@
48 */
49 void hyperlink_to_uuid(const char *zUuid){
50 char zShortUuid[UUID_SIZE+1];
51 shorten_uuid(zShortUuid, zUuid);
52 if( g.okHistory ){
53 @ <a href="%s(g.zBaseURL)/info/%s(zShortUuid)">[%s(zShortUuid)]</a>
 
54 }else{
55 @ <b>[%s(zShortUuid)]</b>
56 }
57 }
58
59 /*
60 ** Generate a hyperlink that invokes javascript to highlight
@@ -83,11 +84,11 @@
83 void hyperlink_to_diff(const char *zV1, const char *zV2){
84 if( g.okHistory ){
85 if( zV2==0 ){
86 @ <a href="%s(g.zBaseURL)/diff?v2=%s(zV1)">[diff]</a>
87 }else{
88 @ <a href="%s(g.zBaseURL)/diff?v1=%s(zV1)&v2=%s(zV2)">[diff]</a>
89 }
90 }
91 }
92
93 /*
@@ -109,11 +110,11 @@
109 */
110 void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){
111 if( zSuf==0 ) zSuf = "";
112 if( g.okHistory ){
113 if( zD && zD[0] ){
114 @ <a href="%s(g.zTop)/timeline?c=%T(zD)&u=%T(zU)">%h(zU)</a>%s(zSuf)
115 }else{
116 @ <a href="%s(g.zTop)/timeline?u=%T(zU)">%h(zU)</a>%s(zSuf)
117 }
118 }else{
119 @ %s(zU)
@@ -189,14 +190,17 @@
189 }else{
190 wikiFlags = WIKI_INLINE | WIKI_NOBLOCK;
191 }
192 if( tmFlags & TIMELINE_GRAPH ){
193 pGraph = graph_init();
 
 
 
194 @ <div id="canvas" style="position:relative;width:1px;height:1px;"></div>
195 }
196
197 @ <table cellspacing=0 border=0 cellpadding=0>
198 blob_zero(&comment);
199 while( db_step(pQuery)==SQLITE_ROW ){
200 int rid = db_column_int(pQuery, 0);
201 const char *zUuid = db_column_text(pQuery, 1);
202 int isLeaf = db_column_int(pQuery, 5);
@@ -218,30 +222,30 @@
218 }
219 }
220 }
221 prevTagid = tagid;
222 if( suppressCnt ){
223 @ <tr><td><td><td>
224 @ <small><i>... %d(suppressCnt) similar
225 @ event%s(suppressCnt>1?"s":"") omitted.</i></small></tr>
226 suppressCnt = 0;
227 }
228 if( strcmp(zType,"div")==0 ){
229 @ <tr><td colspan=3><hr></td></tr>
230 continue;
231 }
232 if( memcmp(zDate, zPrevDate, 10) ){
233 sprintf(zPrevDate, "%.10s", zDate);
234 @ <tr><td>
235 @ <div class="divider"><nobr>%s(zPrevDate)</nobr></div>
236 @ </td></tr>
237 }
238 memcpy(zTime, &zDate[11], 5);
239 zTime[5] = 0;
240 @ <tr>
241 @ <td valign="top" align="right">%s(zTime)</td>
242 @ <td width="20" align="left" valign="top">
243 if( pGraph && zType[0]=='c' ){
244 int nParent = 0;
245 int aParent[32];
246 const char *zBr;
247 int gidx;
@@ -267,24 +271,25 @@
267 }
268 gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr);
269 db_reset(&qbranch);
270 @ <div id="m%d(gidx)"></div>
271 }
 
272 if( zBgClr && zBgClr[0] ){
273 @ <td valign="top" align="left" bgcolor="%h(zBgClr)">
274 }else{
275 @ <td valign="top" align="left">
276 }
277 if( zType[0]=='c' ){
278 hyperlink_to_uuid(zUuid);
279 if( isLeaf ){
280 if( db_exists("SELECT 1 FROM tagxref"
281 " WHERE rid=%d AND tagid=%d AND tagtype>0",
282 rid, TAG_CLOSED) ){
283 @ <b>Closed-Leaf:</b>
284 }else{
285 @ <b>Leaf:</b>
286 }
287 }
288 }else if( (tmFlags & TIMELINE_ARTID)!=0 ){
289 hyperlink_to_uuid(zUuid);
290 }
@@ -309,23 +314,27 @@
309 xExtra(rid);
310 }
311 @ </td></tr>
312 }
313 if( suppressCnt ){
314 @ <tr><td><td><td>
315 @ <small><i>... %d(suppressCnt) similar
316 @ event%s(suppressCnt>1?"s":"") omitted.</i></small></tr>
317 suppressCnt = 0;
318 }
319 if( pGraph ){
320 graph_finish(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0);
321 if( pGraph->nErr ){
322 graph_free(pGraph);
323 pGraph = 0;
324 }else{
325 @ <tr><td><td>
 
 
 
326 @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div>
 
327 }
328 }
329 @ </table>
330 timeline_output_graph_javascript(pGraph);
331 }
@@ -337,11 +346,11 @@
337 void timeline_output_graph_javascript(GraphContext *pGraph){
338 if( pGraph && pGraph->nErr==0 ){
339 GraphRow *pRow;
340 int i;
341 char cSep;
342 @ <script type="text/JavaScript">
343 cgi_printf("var rowinfo = [\n");
344 for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){
345 cgi_printf("{id:\"m%d\",bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,au:",
346 pRow->idx,
347 pRow->zBgClr,
@@ -883,15 +892,15 @@
883 }else if( zBrName ){
884 blob_appendf(&desc, " related to \"%h\"", zBrName);
885 tmFlags |= TIMELINE_DISJOINT;
886 }
887 if( zAfter ){
888 blob_appendf(&desc, " occurring on or after %h.<br>", zAfter);
889 }else if( zBefore ){
890 blob_appendf(&desc, " occurring on or before %h.<br>", zBefore);
891 }else if( zCirca ){
892 blob_appendf(&desc, " occurring around %h.<br>", zCirca);
893 }
894 if( zSearch ){
895 blob_appendf(&desc, " matching \"%h\"", zSearch);
896 }
897 if( g.okHistory ){
898
--- src/timeline.c
+++ src/timeline.c
@@ -48,13 +48,14 @@
48 */
49 void hyperlink_to_uuid(const char *zUuid){
50 char zShortUuid[UUID_SIZE+1];
51 shorten_uuid(zShortUuid, zUuid);
52 if( g.okHistory ){
53 @ <a class="timelineHistLink" href="%s(g.zBaseURL)/info/%s(zShortUuid)">
54 @ [%s(zShortUuid)]</a>
55 }else{
56 @ <span class="timelineHistDsp">[%s(zShortUuid)]</span>
57 }
58 }
59
60 /*
61 ** Generate a hyperlink that invokes javascript to highlight
@@ -83,11 +84,11 @@
84 void hyperlink_to_diff(const char *zV1, const char *zV2){
85 if( g.okHistory ){
86 if( zV2==0 ){
87 @ <a href="%s(g.zBaseURL)/diff?v2=%s(zV1)">[diff]</a>
88 }else{
89 @ <a href="%s(g.zBaseURL)/diff?v1=%s(zV1)&amp;v2=%s(zV2)">[diff]</a>
90 }
91 }
92 }
93
94 /*
@@ -109,11 +110,11 @@
110 */
111 void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){
112 if( zSuf==0 ) zSuf = "";
113 if( g.okHistory ){
114 if( zD && zD[0] ){
115 @ <a href="%s(g.zTop)/timeline?c=%T(zD)&amp;u=%T(zU)">%h(zU)</a>%s(zSuf)
116 }else{
117 @ <a href="%s(g.zTop)/timeline?u=%T(zU)">%h(zU)</a>%s(zSuf)
118 }
119 }else{
120 @ %s(zU)
@@ -189,14 +190,17 @@
190 }else{
191 wikiFlags = WIKI_INLINE | WIKI_NOBLOCK;
192 }
193 if( tmFlags & TIMELINE_GRAPH ){
194 pGraph = graph_init();
195 /* style is not moved to css, because this is
196 ** a technical div for the timeline graph
197 */
198 @ <div id="canvas" style="position:relative;width:1px;height:1px;"></div>
199 }
200
201 @ <table class="timelineTable">
202 blob_zero(&comment);
203 while( db_step(pQuery)==SQLITE_ROW ){
204 int rid = db_column_int(pQuery, 0);
205 const char *zUuid = db_column_text(pQuery, 1);
206 int isLeaf = db_column_int(pQuery, 5);
@@ -218,30 +222,30 @@
222 }
223 }
224 }
225 prevTagid = tagid;
226 if( suppressCnt ){
227 @ <tr><td /><td /><td>
228 @ <span class="timelineDisabled">... %d(suppressCnt) similar
229 @ event%s(suppressCnt>1?"s":"") omitted.</span></td></tr>
230 suppressCnt = 0;
231 }
232 if( strcmp(zType,"div")==0 ){
233 @ <tr><td colspan="3"><hr /></td></tr>
234 continue;
235 }
236 if( memcmp(zDate, zPrevDate, 10) ){
237 sprintf(zPrevDate, "%.10s", zDate);
238 @ <tr><td>
239 @ <div class="divider">%s(zPrevDate)</div>
240 @ </td></tr>
241 }
242 memcpy(zTime, &zDate[11], 5);
243 zTime[5] = 0;
244 @ <tr>
245 @ <td class="timelineTime">%s(zTime)</td>
246 @ <td class="timelineGraph">
247 if( pGraph && zType[0]=='c' ){
248 int nParent = 0;
249 int aParent[32];
250 const char *zBr;
251 int gidx;
@@ -267,24 +271,25 @@
271 }
272 gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr);
273 db_reset(&qbranch);
274 @ <div id="m%d(gidx)"></div>
275 }
276 @</td>
277 if( zBgClr && zBgClr[0] ){
278 @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
279 }else{
280 @ <td class="timelineTableCell">
281 }
282 if( zType[0]=='c' ){
283 hyperlink_to_uuid(zUuid);
284 if( isLeaf ){
285 if( db_exists("SELECT 1 FROM tagxref"
286 " WHERE rid=%d AND tagid=%d AND tagtype>0",
287 rid, TAG_CLOSED) ){
288 @ <span class="timelineLeaf">Closed-Leaf:</span>
289 }else{
290 @ <span class="timelineLeaf">Leaf:</span>
291 }
292 }
293 }else if( (tmFlags & TIMELINE_ARTID)!=0 ){
294 hyperlink_to_uuid(zUuid);
295 }
@@ -309,23 +314,27 @@
314 xExtra(rid);
315 }
316 @ </td></tr>
317 }
318 if( suppressCnt ){
319 @ <tr><td /><td /><td>
320 @ <span class="timelineDisabled">... %d(suppressCnt) similar
321 @ event%s(suppressCnt>1?"s":"") omitted.</span></td></tr>
322 suppressCnt = 0;
323 }
324 if( pGraph ){
325 graph_finish(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0);
326 if( pGraph->nErr ){
327 graph_free(pGraph);
328 pGraph = 0;
329 }else{
330 /* style is not moved to css, because this is
331 ** a technical div for the timeline graph
332 */
333 @ <tr><td /><td>
334 @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div>
335 @ </td></tr>
336 }
337 }
338 @ </table>
339 timeline_output_graph_javascript(pGraph);
340 }
@@ -337,11 +346,11 @@
346 void timeline_output_graph_javascript(GraphContext *pGraph){
347 if( pGraph && pGraph->nErr==0 ){
348 GraphRow *pRow;
349 int i;
350 char cSep;
351 @ <script type="text/JavaScript">
352 cgi_printf("var rowinfo = [\n");
353 for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){
354 cgi_printf("{id:\"m%d\",bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,au:",
355 pRow->idx,
356 pRow->zBgClr,
@@ -883,15 +892,15 @@
892 }else if( zBrName ){
893 blob_appendf(&desc, " related to \"%h\"", zBrName);
894 tmFlags |= TIMELINE_DISJOINT;
895 }
896 if( zAfter ){
897 blob_appendf(&desc, " occurring on or after %h.<br />", zAfter);
898 }else if( zBefore ){
899 blob_appendf(&desc, " occurring on or before %h.<br />", zBefore);
900 }else if( zCirca ){
901 blob_appendf(&desc, " occurring around %h.<br />", zCirca);
902 }
903 if( zSearch ){
904 blob_appendf(&desc, " matching \"%h\"", zSearch);
905 }
906 if( g.okHistory ){
907
+16 -13
--- src/tkt.c
+++ src/tkt.c
@@ -313,11 +313,11 @@
313313
style_submenu_element("New Ticket", "Create a new ticket",
314314
"%s/tktnew", g.zTop);
315315
}
316316
if( g.okApndTkt && g.okAttach ){
317317
style_submenu_element("Attach", "Add An Attachment",
318
- "%s/attachadd?tkt=%T&from=%s/tktview/%t",
318
+ "%s/attachadd?tkt=%T&amp;from=%s/tktview/%t",
319319
g.zTop, zUuid, g.zTop, zUuid);
320320
}
321321
style_header("View Ticket");
322322
if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1);
323323
ticket_init();
@@ -342,24 +342,24 @@
342342
while( db_step(&q)==SQLITE_ROW ){
343343
const char *zDate = db_column_text(&q, 0);
344344
const char *zFile = db_column_text(&q, 1);
345345
const char *zUser = db_column_text(&q, 2);
346346
if( cnt==0 ){
347
- @ <hr><h2>Attachments:</h2>
347
+ @ <hr /><h2>Attachments:</h2>
348348
@ <ul>
349349
}
350350
cnt++;
351351
if( g.okRead && g.okHistory ){
352
- @ <li><a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&file=%t(zFile)">
352
+ @ <li><a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&amp;file=%t(zFile)">
353353
@ %h(zFile)</a>
354354
}else{
355355
@ %h(zFile)
356356
}
357357
@ added by %h(zUser) on
358358
hyperlink_to_date(zDate, ".");
359359
if( g.okWrTkt && g.okAttach ){
360
- @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&file=%t(zFile)&from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>]
360
+ @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&amp;file=%t(zFile)&amp;from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>]
361361
}
362362
}
363363
if( cnt ){
364364
@ </ul>
365365
}
@@ -511,12 +511,13 @@
511511
if( g.thTrace ) Th_Trace("BEGIN_TKTNEW<br />\n", -1);
512512
ticket_init();
513513
getAllTicketFields();
514514
initializeVariablesFromDb();
515515
initializeVariablesFromCGI();
516
- @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)">
516
+ @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><p>
517517
login_insert_csrf_secret();
518
+ @ </p>
518519
zScript = ticket_newpage_code();
519520
Th_Store("login", g.zLogin);
520521
Th_Store("date", db_text(0, "SELECT datetime('now')"));
521522
Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd,
522523
(void*)&zNewUuid, 0);
@@ -554,34 +555,36 @@
554555
cgi_redirectf("tktview?name=%T", zName);
555556
}
556557
style_header("Edit Ticket");
557558
if( zName==0 || (nName = strlen(zName))<4 || nName>UUID_SIZE
558559
|| !validate16(zName,nName) ){
559
- @ <font color="red"><b>Not a valid ticket id: \"%h(zName)\"</b></font>
560
+ @ <span class="tktError">Not a valid ticket id: \"%h(zName)\"</span>
560561
style_footer();
561562
return;
562563
}
563564
nRec = db_int(0, "SELECT count(*) FROM ticket WHERE tkt_uuid GLOB '%q*'",
564565
zName);
565566
if( nRec==0 ){
566
- @ <font color="red"><b>No such ticket: \"%h(zName)\"</b></font>
567
+ @ <span class="tktError">No such ticket: \"%h(zName)\"</span>
567568
style_footer();
568569
return;
569570
}
570571
if( nRec>1 ){
571
- @ <font color="red"><b>%d(nRec) tickets begin with: \"%h(zName)\"</b></font>
572
+ @ <span class="tktError"><b>%d(nRec) tickets begin with:
573
+ @ \"%h(zName)\"</span>
572574
style_footer();
573575
return;
574576
}
575577
if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1);
576578
ticket_init();
577579
getAllTicketFields();
578580
initializeVariablesFromCGI();
579581
initializeVariablesFromDb();
580
- @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)">
581
- @ <input type="hidden" name="name" value="%s(zName)">
582
+ @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><p>
583
+ @ <input type="hidden" name="name" value="%s(zName)" />
582584
login_insert_csrf_secret();
585
+ @ </p>
583586
zScript = ticket_editpage_code();
584587
Th_Store("login", g.zLogin);
585588
Th_Store("date", db_text(0, "SELECT datetime('now')"));
586589
Th_CreateCommand(g.interp, "append_field", appendRemarkCmd, 0, 0);
587590
Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zName,0);
@@ -624,11 +627,11 @@
624627
return 0;
625628
}
626629
627630
/*
628631
** WEBPAGE: tkttimeline
629
-** URL: /tkttimeline?name=TICKETUUID&y=TYPE
632
+** URL: /tkttimeline?name=TICKETUUID&amp;y=TYPE
630633
**
631634
** Show the change history for a single ticket in timeline format.
632635
*/
633636
void tkttimeline_page(void){
634637
Stmt q;
@@ -644,11 +647,11 @@
644647
if( !g.okHistory || !g.okRdTkt ){ login_needed(); return; }
645648
zUuid = PD("name","");
646649
zType = PD("y","a");
647650
if( zType[0]!='c' ){
648651
style_submenu_element("Check-ins", "Check-ins",
649
- "%s/tkttimeline?name=%T&y=ci", g.zTop, zUuid);
652
+ "%s/tkttimeline?name=%T&amp;y=ci", g.zTop, zUuid);
650653
}else{
651654
style_submenu_element("Timeline", "Timeline",
652655
"%s/tkttimeline?name=%T", g.zTop, zUuid);
653656
}
654657
style_submenu_element("History", "History",
@@ -776,12 +779,12 @@
776779
@ <p>Ticket change
777780
@ [<a href="%s(g.zTop)/artifact/%T(zChngUuid)">%s(zShort)</a>]
778781
@ (rid %d(rid)) by
779782
hyperlink_to_user(m.zUser,zDate," on");
780783
hyperlink_to_date(zDate, ":");
781
- ticket_output_change_artifact(&m);
782784
@ </p>
785
+ ticket_output_change_artifact(&m);
783786
}
784787
manifest_clear(&m);
785788
}
786789
}
787790
db_finalize(&q);
788791
--- src/tkt.c
+++ src/tkt.c
@@ -313,11 +313,11 @@
313 style_submenu_element("New Ticket", "Create a new ticket",
314 "%s/tktnew", g.zTop);
315 }
316 if( g.okApndTkt && g.okAttach ){
317 style_submenu_element("Attach", "Add An Attachment",
318 "%s/attachadd?tkt=%T&from=%s/tktview/%t",
319 g.zTop, zUuid, g.zTop, zUuid);
320 }
321 style_header("View Ticket");
322 if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1);
323 ticket_init();
@@ -342,24 +342,24 @@
342 while( db_step(&q)==SQLITE_ROW ){
343 const char *zDate = db_column_text(&q, 0);
344 const char *zFile = db_column_text(&q, 1);
345 const char *zUser = db_column_text(&q, 2);
346 if( cnt==0 ){
347 @ <hr><h2>Attachments:</h2>
348 @ <ul>
349 }
350 cnt++;
351 if( g.okRead && g.okHistory ){
352 @ <li><a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&file=%t(zFile)">
353 @ %h(zFile)</a>
354 }else{
355 @ %h(zFile)
356 }
357 @ added by %h(zUser) on
358 hyperlink_to_date(zDate, ".");
359 if( g.okWrTkt && g.okAttach ){
360 @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&file=%t(zFile)&from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>]
361 }
362 }
363 if( cnt ){
364 @ </ul>
365 }
@@ -511,12 +511,13 @@
511 if( g.thTrace ) Th_Trace("BEGIN_TKTNEW<br />\n", -1);
512 ticket_init();
513 getAllTicketFields();
514 initializeVariablesFromDb();
515 initializeVariablesFromCGI();
516 @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)">
517 login_insert_csrf_secret();
 
518 zScript = ticket_newpage_code();
519 Th_Store("login", g.zLogin);
520 Th_Store("date", db_text(0, "SELECT datetime('now')"));
521 Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd,
522 (void*)&zNewUuid, 0);
@@ -554,34 +555,36 @@
554 cgi_redirectf("tktview?name=%T", zName);
555 }
556 style_header("Edit Ticket");
557 if( zName==0 || (nName = strlen(zName))<4 || nName>UUID_SIZE
558 || !validate16(zName,nName) ){
559 @ <font color="red"><b>Not a valid ticket id: \"%h(zName)\"</b></font>
560 style_footer();
561 return;
562 }
563 nRec = db_int(0, "SELECT count(*) FROM ticket WHERE tkt_uuid GLOB '%q*'",
564 zName);
565 if( nRec==0 ){
566 @ <font color="red"><b>No such ticket: \"%h(zName)\"</b></font>
567 style_footer();
568 return;
569 }
570 if( nRec>1 ){
571 @ <font color="red"><b>%d(nRec) tickets begin with: \"%h(zName)\"</b></font>
 
572 style_footer();
573 return;
574 }
575 if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1);
576 ticket_init();
577 getAllTicketFields();
578 initializeVariablesFromCGI();
579 initializeVariablesFromDb();
580 @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)">
581 @ <input type="hidden" name="name" value="%s(zName)">
582 login_insert_csrf_secret();
 
583 zScript = ticket_editpage_code();
584 Th_Store("login", g.zLogin);
585 Th_Store("date", db_text(0, "SELECT datetime('now')"));
586 Th_CreateCommand(g.interp, "append_field", appendRemarkCmd, 0, 0);
587 Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zName,0);
@@ -624,11 +627,11 @@
624 return 0;
625 }
626
627 /*
628 ** WEBPAGE: tkttimeline
629 ** URL: /tkttimeline?name=TICKETUUID&y=TYPE
630 **
631 ** Show the change history for a single ticket in timeline format.
632 */
633 void tkttimeline_page(void){
634 Stmt q;
@@ -644,11 +647,11 @@
644 if( !g.okHistory || !g.okRdTkt ){ login_needed(); return; }
645 zUuid = PD("name","");
646 zType = PD("y","a");
647 if( zType[0]!='c' ){
648 style_submenu_element("Check-ins", "Check-ins",
649 "%s/tkttimeline?name=%T&y=ci", g.zTop, zUuid);
650 }else{
651 style_submenu_element("Timeline", "Timeline",
652 "%s/tkttimeline?name=%T", g.zTop, zUuid);
653 }
654 style_submenu_element("History", "History",
@@ -776,12 +779,12 @@
776 @ <p>Ticket change
777 @ [<a href="%s(g.zTop)/artifact/%T(zChngUuid)">%s(zShort)</a>]
778 @ (rid %d(rid)) by
779 hyperlink_to_user(m.zUser,zDate," on");
780 hyperlink_to_date(zDate, ":");
781 ticket_output_change_artifact(&m);
782 @ </p>
 
783 }
784 manifest_clear(&m);
785 }
786 }
787 db_finalize(&q);
788
--- src/tkt.c
+++ src/tkt.c
@@ -313,11 +313,11 @@
313 style_submenu_element("New Ticket", "Create a new ticket",
314 "%s/tktnew", g.zTop);
315 }
316 if( g.okApndTkt && g.okAttach ){
317 style_submenu_element("Attach", "Add An Attachment",
318 "%s/attachadd?tkt=%T&amp;from=%s/tktview/%t",
319 g.zTop, zUuid, g.zTop, zUuid);
320 }
321 style_header("View Ticket");
322 if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1);
323 ticket_init();
@@ -342,24 +342,24 @@
342 while( db_step(&q)==SQLITE_ROW ){
343 const char *zDate = db_column_text(&q, 0);
344 const char *zFile = db_column_text(&q, 1);
345 const char *zUser = db_column_text(&q, 2);
346 if( cnt==0 ){
347 @ <hr /><h2>Attachments:</h2>
348 @ <ul>
349 }
350 cnt++;
351 if( g.okRead && g.okHistory ){
352 @ <li><a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&amp;file=%t(zFile)">
353 @ %h(zFile)</a>
354 }else{
355 @ %h(zFile)
356 }
357 @ added by %h(zUser) on
358 hyperlink_to_date(zDate, ".");
359 if( g.okWrTkt && g.okAttach ){
360 @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&amp;file=%t(zFile)&amp;from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>]
361 }
362 }
363 if( cnt ){
364 @ </ul>
365 }
@@ -511,12 +511,13 @@
511 if( g.thTrace ) Th_Trace("BEGIN_TKTNEW<br />\n", -1);
512 ticket_init();
513 getAllTicketFields();
514 initializeVariablesFromDb();
515 initializeVariablesFromCGI();
516 @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><p>
517 login_insert_csrf_secret();
518 @ </p>
519 zScript = ticket_newpage_code();
520 Th_Store("login", g.zLogin);
521 Th_Store("date", db_text(0, "SELECT datetime('now')"));
522 Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd,
523 (void*)&zNewUuid, 0);
@@ -554,34 +555,36 @@
555 cgi_redirectf("tktview?name=%T", zName);
556 }
557 style_header("Edit Ticket");
558 if( zName==0 || (nName = strlen(zName))<4 || nName>UUID_SIZE
559 || !validate16(zName,nName) ){
560 @ <span class="tktError">Not a valid ticket id: \"%h(zName)\"</span>
561 style_footer();
562 return;
563 }
564 nRec = db_int(0, "SELECT count(*) FROM ticket WHERE tkt_uuid GLOB '%q*'",
565 zName);
566 if( nRec==0 ){
567 @ <span class="tktError">No such ticket: \"%h(zName)\"</span>
568 style_footer();
569 return;
570 }
571 if( nRec>1 ){
572 @ <span class="tktError"><b>%d(nRec) tickets begin with:
573 @ \"%h(zName)\"</span>
574 style_footer();
575 return;
576 }
577 if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1);
578 ticket_init();
579 getAllTicketFields();
580 initializeVariablesFromCGI();
581 initializeVariablesFromDb();
582 @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><p>
583 @ <input type="hidden" name="name" value="%s(zName)" />
584 login_insert_csrf_secret();
585 @ </p>
586 zScript = ticket_editpage_code();
587 Th_Store("login", g.zLogin);
588 Th_Store("date", db_text(0, "SELECT datetime('now')"));
589 Th_CreateCommand(g.interp, "append_field", appendRemarkCmd, 0, 0);
590 Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zName,0);
@@ -624,11 +627,11 @@
627 return 0;
628 }
629
630 /*
631 ** WEBPAGE: tkttimeline
632 ** URL: /tkttimeline?name=TICKETUUID&amp;y=TYPE
633 **
634 ** Show the change history for a single ticket in timeline format.
635 */
636 void tkttimeline_page(void){
637 Stmt q;
@@ -644,11 +647,11 @@
647 if( !g.okHistory || !g.okRdTkt ){ login_needed(); return; }
648 zUuid = PD("name","");
649 zType = PD("y","a");
650 if( zType[0]!='c' ){
651 style_submenu_element("Check-ins", "Check-ins",
652 "%s/tkttimeline?name=%T&amp;y=ci", g.zTop, zUuid);
653 }else{
654 style_submenu_element("Timeline", "Timeline",
655 "%s/tkttimeline?name=%T", g.zTop, zUuid);
656 }
657 style_submenu_element("History", "History",
@@ -776,12 +779,12 @@
779 @ <p>Ticket change
780 @ [<a href="%s(g.zTop)/artifact/%T(zChngUuid)">%s(zShort)</a>]
781 @ (rid %d(rid)) by
782 hyperlink_to_user(m.zUser,zDate," on");
783 hyperlink_to_date(zDate, ":");
 
784 @ </p>
785 ticket_output_change_artifact(&m);
786 }
787 manifest_clear(&m);
788 }
789 }
790 db_finalize(&q);
791
+94 -98
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -130,21 +130,21 @@
130130
db_set(zDbField, z, 0);
131131
if( xRebuild ) xRebuild();
132132
cgi_redirect("tktsetup");
133133
}
134134
}
135
- @ <form action="%s(g.zBaseURL)/%s(g.zPath)" method="POST">
135
+ @ <form action="%s(g.zBaseURL)/%s(g.zPath)" method="post"><div>
136136
login_insert_csrf_secret();
137137
@ <p>%s(zDesc)</p>
138138
@ <textarea name="x" rows="%d(height)" cols="80">%h(z)</textarea>
139
- @ <blockquote>
140
- @ <input type="submit" name="submit" value="Apply Changes">
141
- @ <input type="submit" name="clear" value="Revert To Default">
142
- @ <input type="submit" name="setup" value="Cancel">
143
- @ </blockquote>
144
- @ </form>
145
- @ <hr>
139
+ @ <blockquote><p>
140
+ @ <input type="submit" name="submit" value="Apply Changes" />
141
+ @ <input type="submit" name="clear" value="Revert To Default" />
142
+ @ <input type="submit" name="setup" value="Cancel" />
143
+ @ </p></blockquote>
144
+ @ </div></form>
145
+ @ <hr />
146146
@ <h2>Default %s(zTitle)</h2>
147147
@ <blockquote><pre>
148148
@ %h(zDfltValue)
149149
@ </pre></blockquote>
150150
style_footer();
@@ -153,13 +153,13 @@
153153
/*
154154
** WEBPAGE: tktsetup_tab
155155
*/
156156
void tktsetup_tab_page(void){
157157
static const char zDesc[] =
158
- @ <p>Enter a valid CREATE TABLE statement for the "ticket" table. The
158
+ @ Enter a valid CREATE TABLE statement for the "ticket" table. The
159159
@ table must contain columns named "tkt_id", "tkt_uuid", and "tkt_mtime"
160
- @ with an unique index on "tkt_uuid" and "tkt_mtime".</p>
160
+ @ with an unique index on "tkt_uuid" and "tkt_mtime".
161161
;
162162
tktsetup_generic(
163163
"Ticket Table Schema",
164164
"ticket-table",
165165
zDefaultTicketTable,
@@ -229,12 +229,12 @@
229229
/*
230230
** WEBPAGE: tktsetup_com
231231
*/
232232
void tktsetup_com_page(void){
233233
static const char zDesc[] =
234
- @ <p>Enter TH1 script that initializes variables prior to generating
235
- @ any of the ticket view, edit, or creation pages.</p>
234
+ @ Enter TH1 script that initializes variables prior to generating
235
+ @ any of the ticket view, edit, or creation pages.
236236
;
237237
tktsetup_generic(
238238
"Ticket Common Script",
239239
"ticket-common",
240240
zDefaultTicketCommon,
@@ -250,80 +250,80 @@
250250
@ if {[info exists submit]} {
251251
@ set status Open
252252
@ submit_ticket
253253
@ }
254254
@ </th1>
255
-@ <h1 align="center">Enter A New Ticket</h1>
255
+@ <h1 style="text-align: center;">Enter A New Ticket</h1>
256256
@ <table cellpadding="5">
257257
@ <tr>
258258
@ <td colspan="2">
259
-@ Enter a one-line summary of the ticket:<br>
260
-@ <input type="text" name="title" size="60" value="$<title>">
259
+@ Enter a one-line summary of the ticket:<br />
260
+@ <input type="text" name="title" size="60" value="$<title>" />
261261
@ </td>
262262
@ </tr>
263263
@
264264
@ <tr>
265
-@ <td align="right">Type:
265
+@ <td style="text-align: center;">Type:
266266
@ <th1>combobox type $type_choices 1</th1>
267267
@ </td>
268268
@ <td>What type of ticket is this?</td>
269269
@ </tr>
270270
@
271271
@ <tr>
272
-@ <td align="right">Version:
273
-@ <input type="text" name="foundin" size="20" value="$<foundin>">
272
+@ <td style="text-align: center;">Version:
273
+@ <input type="text" name="foundin" size="20" value="$<foundin>" />
274274
@ </td>
275275
@ <td>In what version or build number do you observe the problem?</td>
276276
@ </tr>
277277
@
278278
@ <tr>
279
-@ <td align="right">Severity:
279
+@ <td style="text-align: center;">Severity:
280280
@ <th1>combobox severity $severity_choices 1</th1>
281281
@ </td>
282282
@ <td>How debilitating is the problem? How badly does the problem
283283
@ affect the operation of the product?</td>
284284
@ </tr>
285285
@
286286
@ <tr>
287
-@ <td align="right">EMail:
288
-@ <input type="text" name="private_contact" value="$<private_contact>" size="30">
287
+@ <td style="text-align: center;">EMail:
288
+@ <input type="text" name="private_contact" value="$<private_contact>" size="30" />
289289
@ </td>
290
-@ <td><u>Not publicly visible</u>. Used by developers to contact you with
291
-@ questions.</td>
290
+@ <td><span style="text-decoration: underline;">Not publicly visible</span>.
291
+@ Used by developers to contact you with questions.</td>
292292
@ </tr>
293293
@
294294
@ <tr>
295295
@ <td colspan="2">
296296
@ Enter a detailed description of the problem.
297297
@ For code defects, be sure to provide details on exactly how
298298
@ the problem can be reproduced. Provide as much detail as
299299
@ possible.
300
-@ <br>
300
+@ <br />
301301
@ <th1>set nline [linecount $comment 50 10]</th1>
302302
@ <textarea name="comment" cols="80" rows="$nline"
303
-@ wrap="virtual" class="wikiedit">$<comment></textarea><br>
304
-@ <input type="submit" name="preview" value="Preview">
303
+@ wrap="virtual" class="wikiedit">$<comment></textarea><br />
304
+@ <input type="submit" name="preview" value="Preview" /></td>
305305
@ </tr>
306306
@
307307
@ <th1>enable_output [info exists preview]</th1>
308308
@ <tr><td colspan="2">
309
-@ Description Preview:<br><hr>
309
+@ Description Preview:<br /><hr />
310310
@ <th1>wiki $comment</th1>
311
-@ <hr>
311
+@ <hr />
312312
@ </td></tr>
313313
@ <th1>enable_output 1</th1>
314314
@
315315
@ <tr>
316
-@ <td align="right">
317
-@ <input type="submit" name="submit" value="Submit">
316
+@ <td style="text-align: center;">
317
+@ <input type="submit" name="submit" value="Submit" />
318318
@ </td>
319319
@ <td>After filling in the information above, press this button to create
320320
@ the new ticket</td>
321321
@ </tr>
322322
@ <tr>
323
-@ <td align="right">
324
-@ <input type="submit" name="cancel" value="Cancel">
323
+@ <td style="text-align: center;">
324
+@ <input type="submit" name="cancel" value="Cancel" />
325325
@ </td>
326326
@ <td>Abandon and forget this ticket</td>
327327
@ </tr>
328328
@ </table>
329329
;
@@ -338,12 +338,12 @@
338338
/*
339339
** WEBPAGE: tktsetup_newpage
340340
*/
341341
void tktsetup_newpage_page(void){
342342
static const char zDesc[] =
343
- @ <p>Enter HTML with embedded TH1 script that will render the "new ticket"
344
- @ page</p>
343
+ @ Enter HTML with embedded TH1 script that will render the "new ticket"
344
+ @ page
345345
;
346346
tktsetup_generic(
347347
"HTML For New Tickets",
348348
"ticket-newpage",
349349
zDefaultNew,
@@ -354,51 +354,50 @@
354354
);
355355
}
356356
357357
static const char zDefaultView[] =
358358
@ <table cellpadding="5">
359
-@ <tr><td align="right">Ticket&nbsp;UUID:</td><td bgcolor="#d0d0d0" colspan="3">
360
-@ $<tkt_uuid>
361
-@ </td></tr>
362
-@ <tr><td align="right">Title:</td>
363
-@ <td bgcolor="#d0d0d0" colspan="3" valign="top">
359
+@ <tr><td class="tktDspLabel">Ticket&nbsp;UUID:</td>
360
+@ <td class="tktDspValue" colspan="3">$<tkt_uuid></td></tr>
361
+@ <tr><td class="tktDspLabel">Title:</td>
362
+@ <td class="tktDspValue" colspan="3">
364363
@ <th1>wiki $title</th1>
365364
@ </td></tr>
366
-@ <tr><td align="right">Status:</td><td bgcolor="#d0d0d0">
365
+@ <tr><td class="tktDspLabel">Status:</td><td class="tktDspValue">
367366
@ $<status>
368367
@ </td>
369
-@ <td align="right">Type:</td><td bgcolor="#d0d0d0">
368
+@ <td class="tktDspLabel">Type:</td><td class="tktDspValue">
370369
@ $<type>
371370
@ </td></tr>
372
-@ <tr><td align="right">Severity:</td><td bgcolor="#d0d0d0">
371
+@ <tr><td class="tktDspLabel">Severity:</td><td class="tktDspValue">
373372
@ $<severity>
374373
@ </td>
375
-@ <td align="right">Priority:</td><td bgcolor="#d0d0d0">
374
+@ <td class="tktDspLabel">Priority:</td><td class="tktDspValue">
376375
@ $<priority>
377376
@ </td></tr>
378
-@ <tr><td align="right">Subsystem:</td><td bgcolor="#d0d0d0">
377
+@ <tr><td class="tktDspLabel">Subsystem:</td><td class="tktDspValue">
379378
@ $<subsystem>
380379
@ </td>
381
-@ <td align="right">Resolution:</td><td bgcolor="#d0d0d0">
380
+@ <td class="tktDspLabel">Resolution:</td><td class="tktDspValue">
382381
@ $<resolution>
383382
@ </td></tr>
384
-@ <tr><td align="right">Last&nbsp;Modified:</td><td bgcolor="#d0d0d0">
383
+@ <tr><td class="tktDspLabel">Last&nbsp;Modified:</td><td class="tktDspValue">
385384
@ $<tkt_datetime>
386385
@ </td>
387386
@ <th1>enable_output [hascap e]</th1>
388
-@ <td align="right">Contact:</td><td bgcolor="#d0d0d0">
387
+@ <td class="tktDspLabel">Contact:</td><td class="tktDspValue">
389388
@ $<private_contact>
390389
@ </td>
391390
@ <th1>enable_output 1</th1>
392391
@ </tr>
393
-@ <tr><td align="right">Version&nbsp;Found&nbsp;In:</td>
394
-@ <td colspan="3" valign="top" bgcolor="#d0d0d0">
392
+@ <tr><td class="tktDspLabel">Version&nbsp;Found&nbsp;In:</td>
393
+@ <td colspan="3" valign="top" class="tktDspValue">
395394
@ $<foundin>
396395
@ </td></tr>
397396
@ <tr><td>Description &amp; Comments:</td></tr>
398
-@ <tr><td colspan="4" bgcolor="#d0d0d0">
399
-@ <span bgcolor="#d0d0d0"><th1>wiki $comment</th1></span>
397
+@ <tr><td colspan="4" class="tktDspValue">
398
+@ <th1>wiki $comment</th1>
400399
@ </td></tr>
401400
@ </table>
402401
;
403402
404403
@@ -412,12 +411,11 @@
412411
/*
413412
** WEBPAGE: tktsetup_viewpage
414413
*/
415414
void tktsetup_viewpage_page(void){
416415
static const char zDesc[] =
417
- @ <p>Enter HTML with embedded TH1 script that will render the "view ticket"
418
- @ page</p>
416
+ @ Enter HTML with embedded TH1 script that will render the "view ticket" page
419417
;
420418
tktsetup_generic(
421419
"HTML For Viewing Tickets",
422420
"ticket-viewpage",
423421
zDefaultView,
@@ -432,51 +430,51 @@
432430
@ <th1>
433431
@ if {![info exists username]} {set username $login}
434432
@ if {[info exists submit]} {
435433
@ if {[info exists cmappnd]} {
436434
@ if {[string length $cmappnd]>0} {
437
-@ set ctxt "\n\n<hr><i>[htmlize $login]"
435
+@ set ctxt "\n\n<hr /><i>[htmlize $login]"
438436
@ if {$username ne $login} {
439437
@ set ctxt "$ctxt claiming to be [htmlize $username]"
440438
@ }
441
-@ set ctxt "$ctxt added on [date]:</i><br>\n$cmappnd"
439
+@ set ctxt "$ctxt added on [date]:</i><br />\n$cmappnd"
442440
@ append_field comment $ctxt
443441
@ }
444442
@ }
445443
@ submit_ticket
446444
@ }
447445
@ </th1>
448446
@ <table cellpadding="5">
449
-@ <tr><td align="right">Title:</td><td>
450
-@ <input type="text" name="title" value="$<title>" size="60">
447
+@ <tr><td class="tktDspLabel">Title:</td><td>
448
+@ <input type="text" name="title" value="$<title>" size="60" />
451449
@ </td></tr>
452
-@ <tr><td align="right">Status:</td><td>
450
+@ <tr><td class="tktDspLabel">Status:</td><td>
453451
@ <th1>combobox status $status_choices 1</th1>
454452
@ </td></tr>
455
-@ <tr><td align="right">Type:</td><td>
453
+@ <tr><td class="tktDspLabel">Type:</td><td>
456454
@ <th1>combobox type $type_choices 1</th1>
457455
@ </td></tr>
458
-@ <tr><td align="right">Severity:</td><td>
456
+@ <tr><td class="tktDspLabel">Severity:</td><td>
459457
@ <th1>combobox severity $severity_choices 1</th1>
460458
@ </td></tr>
461
-@ <tr><td align="right">Priority:</td><td>
459
+@ <tr><td class="tktDspLabel">Priority:</td><td>
462460
@ <th1>combobox priority $priority_choices 1</th1>
463461
@ </td></tr>
464
-@ <tr><td align="right">Resolution:</td><td>
462
+@ <tr><td class="tktDspLabel">Resolution:</td><td>
465463
@ <th1>combobox resolution $resolution_choices 1</th1>
466464
@ </td></tr>
467
-@ <tr><td align="right">Subsystem:</td><td>
465
+@ <tr><td class="tktDspLabel">Subsystem:</td><td>
468466
@ <th1>combobox subsystem $subsystem_choices 1</th1>
469467
@ </td></tr>
470468
@ <th1>enable_output [hascap e]</th1>
471
-@ <tr><td align="right">Contact:</td><td>
469
+@ <tr><td class="tktDspLabel">Contact:</td><td>
472470
@ <input type="text" name="private_contact" size="40"
473
-@ value="$<private_contact>">
471
+@ value="$<private_contact>" />
474472
@ </td></tr>
475473
@ <th1>enable_output 1</th1>
476
-@ <tr><td align="right">Version&nbsp;Found&nbsp;In:</td><td>
477
-@ <input type="text" name="foundin" size="50" value="$<foundin>">
474
+@ <tr><td class="tktDspLabel">Version&nbsp;Found&nbsp;In:</td><td>
475
+@ <input type="text" name="foundin" size="50" value="$<foundin>" />
478476
@ </td></tr>
479477
@ <tr><td colspan="2">
480478
@ <th1>
481479
@ if {![info exists eall]} {set eall 0}
482480
@ if {[info exists aonlybtn]} {set eall 0}
@@ -484,45 +482,45 @@
484482
@ if {![hascap w]} {set eall 0}
485483
@ if {![info exists cmappnd]} {set cmappnd {}}
486484
@ set nline [linecount $comment 15 10]
487485
@ enable_output $eall
488486
@ </th1>
489
-@ Description And Comments:<br>
487
+@ Description And Comments:<br />
490488
@ <textarea name="comment" cols="80" rows="$nline"
491
-@ wrap="virtual" class="wikiedit">$<comment></textarea><br>
492
-@ <input type="hidden" name="eall" value="1">
493
-@ <input type="submit" name="aonlybtn" value="Append Remark">
494
-@ <input type="submit" name="preview1btn" value="Preview">
489
+@ wrap="virtual" class="wikiedit">$<comment></textarea><br />
490
+@ <input type="hidden" name="eall" value="1" />
491
+@ <input type="submit" name="aonlybtn" value="Append Remark" />
492
+@ <input type="submit" name="preview1btn" value="Preview" />
495493
@ <th1>enable_output [expr {!$eall}]</th1>
496494
@ Append Remark from
497
-@ <input type="text" name="username" value="$<username>" size="30">:<br>
495
+@ <input type="text" name="username" value="$<username>" size="30" />:<br />
498496
@ <textarea name="cmappnd" cols="80" rows="15"
499
-@ wrap="virtual" class="wikiedit">$<cmappnd></textarea><br>
497
+@ wrap="virtual" class="wikiedit">$<cmappnd></textarea><br />
500498
@ <th1>enable_output [expr {[hascap w] && !$eall}]</th1>
501
-@ <input type="submit" name="eallbtn" value="Edit All">
499
+@ <input type="submit" name="eallbtn" value="Edit All" />
502500
@ <th1>enable_output [expr {!$eall}]</th1>
503
-@ <input type="submit" name="preview2btn" value="Preview">
501
+@ <input type="submit" name="preview2btn" value="Preview" />
504502
@ <th1>enable_output 1</th1>
505503
@ </td></tr>
506504
@
507505
@ <th1>enable_output [info exists preview1btn]</th1>
508506
@ <tr><td colspan="2">
509
-@ Description Preview:<br><hr>
507
+@ Description Preview:<br /><hr />
510508
@ <th1>wiki $comment</th1>
511
-@ <hr>
509
+@ <hr />
512510
@ </td></tr>
513511
@ <th1>enable_output [info exists preview2btn]</th1>
514512
@ <tr><td colspan="2">
515
-@ Description Preview:<br><hr>
513
+@ Description Preview:<br /><hr />
516514
@ <th1>wiki $cmappnd</th1>
517
-@ <hr>
515
+@ <hr />
518516
@ </td></tr>
519517
@ <th1>enable_output 1</th1>
520518
@
521519
@ <tr><td align="right"></td><td>
522
-@ <input type="submit" name="submit" value="Submit Changes">
523
-@ <input type="submit" name="cancel" value="Cancel">
520
+@ <input type="submit" name="submit" value="Submit Changes" />
521
+@ <input type="submit" name="cancel" value="Cancel" />
524522
@ </td></tr>
525523
@ </table>
526524
;
527525
528526
/*
@@ -535,12 +533,11 @@
535533
/*
536534
** WEBPAGE: tktsetup_editpage
537535
*/
538536
void tktsetup_editpage_page(void){
539537
static const char zDesc[] =
540
- @ <p>Enter HTML with embedded TH1 script that will render the "edit ticket"
541
- @ page</p>
538
+ @ Enter HTML with embedded TH1 script that will render the "edit ticket" page
542539
;
543540
tktsetup_generic(
544541
"HTML For Editing Tickets",
545542
"ticket-editpage",
546543
zDefaultEdit,
@@ -585,12 +582,11 @@
585582
/*
586583
** WEBPAGE: tktsetup_reportlist
587584
*/
588585
void tktsetup_reportlist(void){
589586
static const char zDesc[] =
590
- @ <p>Enter HTML with embedded TH1 script that will render the "report list"
591
- @ page</p>
587
+ @ Enter HTML with embedded TH1 script that will render the "report list" page
592588
;
593589
tktsetup_generic(
594590
"HTML For Report List",
595591
"ticket-reportlist",
596592
zDefaultReportList,
@@ -633,13 +629,13 @@
633629
/*
634630
** WEBPAGE: tktsetup_rpttplt
635631
*/
636632
void tktsetup_rpttplt_page(void){
637633
static const char zDesc[] =
638
- @ <p>Enter the default ticket report format template. This is the
634
+ @ Enter the default ticket report format template. This is the
639635
@ the template report format that initially appears when creating a
640
- @ new ticket summary report.</p>
636
+ @ new ticket summary report.
641637
;
642638
tktsetup_generic(
643639
"Default Report Template",
644640
"ticket-report-template",
645641
zDefaultReport,
@@ -674,13 +670,13 @@
674670
/*
675671
** WEBPAGE: tktsetup_keytplt
676672
*/
677673
void tktsetup_keytplt_page(void){
678674
static const char zDesc[] =
679
- @ <p>Enter the default ticket report color-key template. This is the
675
+ @ Enter the default ticket report color-key template. This is the
680676
@ the color-key that initially appears when creating a
681
- @ new ticket summary report.</p>
677
+ @ new ticket summary report.
682678
;
683679
tktsetup_generic(
684680
"Default Report Color-Key Template",
685681
"ticket-key-template",
686682
zDefaultKey,
@@ -703,34 +699,34 @@
703699
if( P("setup") ){
704700
cgi_redirect("tktsetup");
705701
}
706702
style_header("Ticket Display On Timelines");
707703
db_begin_transaction();
708
- @ <form action="%s(g.zBaseURL)/tktsetup_timeline" method="POST">
704
+ @ <form action="%s(g.zBaseURL)/tktsetup_timeline" method="post"><div>
709705
login_insert_csrf_secret();
710706
711
- @ <hr>
707
+ @ <hr />
712708
entry_attribute("Ticket Title", 40, "ticket-title-expr", "t", "title");
713709
@ <p>An SQL expression in a query against the TICKET table that will
714710
@ return the title of the ticket for display purposes.</p>
715711
716
- @ <hr>
712
+ @ <hr />
717713
entry_attribute("Ticket Status", 40, "ticket-status-column", "s", "status");
718714
@ <p>The name of the column in the TICKET table that contains the ticket
719715
@ status in human-readable form. Case sensitive.</p>
720716
721
- @ <hr>
717
+ @ <hr />
722718
entry_attribute("Ticket Closed", 40, "ticket-closed-expr", "c",
723719
"status='Closed'");
724720
@ <p>An SQL expression that evaluates to true in a TICKET table query if
725721
@ the ticket is closed.</p>
726722
727
- @ <hr>
723
+ @ <hr />
728724
@ <p>
729
- @ <input type="submit" name="submit" value="Apply Changes">
730
- @ <input type="submit" name="setup" value="Cancel">
725
+ @ <input type="submit" name="submit" value="Apply Changes" />
726
+ @ <input type="submit" name="setup" value="Cancel" />
731727
@ </p>
732
- @ </form>
728
+ @ </div></form>
733729
db_end_transaction(0);
734730
style_footer();
735731
736732
}
737733
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -130,21 +130,21 @@
130 db_set(zDbField, z, 0);
131 if( xRebuild ) xRebuild();
132 cgi_redirect("tktsetup");
133 }
134 }
135 @ <form action="%s(g.zBaseURL)/%s(g.zPath)" method="POST">
136 login_insert_csrf_secret();
137 @ <p>%s(zDesc)</p>
138 @ <textarea name="x" rows="%d(height)" cols="80">%h(z)</textarea>
139 @ <blockquote>
140 @ <input type="submit" name="submit" value="Apply Changes">
141 @ <input type="submit" name="clear" value="Revert To Default">
142 @ <input type="submit" name="setup" value="Cancel">
143 @ </blockquote>
144 @ </form>
145 @ <hr>
146 @ <h2>Default %s(zTitle)</h2>
147 @ <blockquote><pre>
148 @ %h(zDfltValue)
149 @ </pre></blockquote>
150 style_footer();
@@ -153,13 +153,13 @@
153 /*
154 ** WEBPAGE: tktsetup_tab
155 */
156 void tktsetup_tab_page(void){
157 static const char zDesc[] =
158 @ <p>Enter a valid CREATE TABLE statement for the "ticket" table. The
159 @ table must contain columns named "tkt_id", "tkt_uuid", and "tkt_mtime"
160 @ with an unique index on "tkt_uuid" and "tkt_mtime".</p>
161 ;
162 tktsetup_generic(
163 "Ticket Table Schema",
164 "ticket-table",
165 zDefaultTicketTable,
@@ -229,12 +229,12 @@
229 /*
230 ** WEBPAGE: tktsetup_com
231 */
232 void tktsetup_com_page(void){
233 static const char zDesc[] =
234 @ <p>Enter TH1 script that initializes variables prior to generating
235 @ any of the ticket view, edit, or creation pages.</p>
236 ;
237 tktsetup_generic(
238 "Ticket Common Script",
239 "ticket-common",
240 zDefaultTicketCommon,
@@ -250,80 +250,80 @@
250 @ if {[info exists submit]} {
251 @ set status Open
252 @ submit_ticket
253 @ }
254 @ </th1>
255 @ <h1 align="center">Enter A New Ticket</h1>
256 @ <table cellpadding="5">
257 @ <tr>
258 @ <td colspan="2">
259 @ Enter a one-line summary of the ticket:<br>
260 @ <input type="text" name="title" size="60" value="$<title>">
261 @ </td>
262 @ </tr>
263 @
264 @ <tr>
265 @ <td align="right">Type:
266 @ <th1>combobox type $type_choices 1</th1>
267 @ </td>
268 @ <td>What type of ticket is this?</td>
269 @ </tr>
270 @
271 @ <tr>
272 @ <td align="right">Version:
273 @ <input type="text" name="foundin" size="20" value="$<foundin>">
274 @ </td>
275 @ <td>In what version or build number do you observe the problem?</td>
276 @ </tr>
277 @
278 @ <tr>
279 @ <td align="right">Severity:
280 @ <th1>combobox severity $severity_choices 1</th1>
281 @ </td>
282 @ <td>How debilitating is the problem? How badly does the problem
283 @ affect the operation of the product?</td>
284 @ </tr>
285 @
286 @ <tr>
287 @ <td align="right">EMail:
288 @ <input type="text" name="private_contact" value="$<private_contact>" size="30">
289 @ </td>
290 @ <td><u>Not publicly visible</u>. Used by developers to contact you with
291 @ questions.</td>
292 @ </tr>
293 @
294 @ <tr>
295 @ <td colspan="2">
296 @ Enter a detailed description of the problem.
297 @ For code defects, be sure to provide details on exactly how
298 @ the problem can be reproduced. Provide as much detail as
299 @ possible.
300 @ <br>
301 @ <th1>set nline [linecount $comment 50 10]</th1>
302 @ <textarea name="comment" cols="80" rows="$nline"
303 @ wrap="virtual" class="wikiedit">$<comment></textarea><br>
304 @ <input type="submit" name="preview" value="Preview">
305 @ </tr>
306 @
307 @ <th1>enable_output [info exists preview]</th1>
308 @ <tr><td colspan="2">
309 @ Description Preview:<br><hr>
310 @ <th1>wiki $comment</th1>
311 @ <hr>
312 @ </td></tr>
313 @ <th1>enable_output 1</th1>
314 @
315 @ <tr>
316 @ <td align="right">
317 @ <input type="submit" name="submit" value="Submit">
318 @ </td>
319 @ <td>After filling in the information above, press this button to create
320 @ the new ticket</td>
321 @ </tr>
322 @ <tr>
323 @ <td align="right">
324 @ <input type="submit" name="cancel" value="Cancel">
325 @ </td>
326 @ <td>Abandon and forget this ticket</td>
327 @ </tr>
328 @ </table>
329 ;
@@ -338,12 +338,12 @@
338 /*
339 ** WEBPAGE: tktsetup_newpage
340 */
341 void tktsetup_newpage_page(void){
342 static const char zDesc[] =
343 @ <p>Enter HTML with embedded TH1 script that will render the "new ticket"
344 @ page</p>
345 ;
346 tktsetup_generic(
347 "HTML For New Tickets",
348 "ticket-newpage",
349 zDefaultNew,
@@ -354,51 +354,50 @@
354 );
355 }
356
357 static const char zDefaultView[] =
358 @ <table cellpadding="5">
359 @ <tr><td align="right">Ticket&nbsp;UUID:</td><td bgcolor="#d0d0d0" colspan="3">
360 @ $<tkt_uuid>
361 @ </td></tr>
362 @ <tr><td align="right">Title:</td>
363 @ <td bgcolor="#d0d0d0" colspan="3" valign="top">
364 @ <th1>wiki $title</th1>
365 @ </td></tr>
366 @ <tr><td align="right">Status:</td><td bgcolor="#d0d0d0">
367 @ $<status>
368 @ </td>
369 @ <td align="right">Type:</td><td bgcolor="#d0d0d0">
370 @ $<type>
371 @ </td></tr>
372 @ <tr><td align="right">Severity:</td><td bgcolor="#d0d0d0">
373 @ $<severity>
374 @ </td>
375 @ <td align="right">Priority:</td><td bgcolor="#d0d0d0">
376 @ $<priority>
377 @ </td></tr>
378 @ <tr><td align="right">Subsystem:</td><td bgcolor="#d0d0d0">
379 @ $<subsystem>
380 @ </td>
381 @ <td align="right">Resolution:</td><td bgcolor="#d0d0d0">
382 @ $<resolution>
383 @ </td></tr>
384 @ <tr><td align="right">Last&nbsp;Modified:</td><td bgcolor="#d0d0d0">
385 @ $<tkt_datetime>
386 @ </td>
387 @ <th1>enable_output [hascap e]</th1>
388 @ <td align="right">Contact:</td><td bgcolor="#d0d0d0">
389 @ $<private_contact>
390 @ </td>
391 @ <th1>enable_output 1</th1>
392 @ </tr>
393 @ <tr><td align="right">Version&nbsp;Found&nbsp;In:</td>
394 @ <td colspan="3" valign="top" bgcolor="#d0d0d0">
395 @ $<foundin>
396 @ </td></tr>
397 @ <tr><td>Description &amp; Comments:</td></tr>
398 @ <tr><td colspan="4" bgcolor="#d0d0d0">
399 @ <span bgcolor="#d0d0d0"><th1>wiki $comment</th1></span>
400 @ </td></tr>
401 @ </table>
402 ;
403
404
@@ -412,12 +411,11 @@
412 /*
413 ** WEBPAGE: tktsetup_viewpage
414 */
415 void tktsetup_viewpage_page(void){
416 static const char zDesc[] =
417 @ <p>Enter HTML with embedded TH1 script that will render the "view ticket"
418 @ page</p>
419 ;
420 tktsetup_generic(
421 "HTML For Viewing Tickets",
422 "ticket-viewpage",
423 zDefaultView,
@@ -432,51 +430,51 @@
432 @ <th1>
433 @ if {![info exists username]} {set username $login}
434 @ if {[info exists submit]} {
435 @ if {[info exists cmappnd]} {
436 @ if {[string length $cmappnd]>0} {
437 @ set ctxt "\n\n<hr><i>[htmlize $login]"
438 @ if {$username ne $login} {
439 @ set ctxt "$ctxt claiming to be [htmlize $username]"
440 @ }
441 @ set ctxt "$ctxt added on [date]:</i><br>\n$cmappnd"
442 @ append_field comment $ctxt
443 @ }
444 @ }
445 @ submit_ticket
446 @ }
447 @ </th1>
448 @ <table cellpadding="5">
449 @ <tr><td align="right">Title:</td><td>
450 @ <input type="text" name="title" value="$<title>" size="60">
451 @ </td></tr>
452 @ <tr><td align="right">Status:</td><td>
453 @ <th1>combobox status $status_choices 1</th1>
454 @ </td></tr>
455 @ <tr><td align="right">Type:</td><td>
456 @ <th1>combobox type $type_choices 1</th1>
457 @ </td></tr>
458 @ <tr><td align="right">Severity:</td><td>
459 @ <th1>combobox severity $severity_choices 1</th1>
460 @ </td></tr>
461 @ <tr><td align="right">Priority:</td><td>
462 @ <th1>combobox priority $priority_choices 1</th1>
463 @ </td></tr>
464 @ <tr><td align="right">Resolution:</td><td>
465 @ <th1>combobox resolution $resolution_choices 1</th1>
466 @ </td></tr>
467 @ <tr><td align="right">Subsystem:</td><td>
468 @ <th1>combobox subsystem $subsystem_choices 1</th1>
469 @ </td></tr>
470 @ <th1>enable_output [hascap e]</th1>
471 @ <tr><td align="right">Contact:</td><td>
472 @ <input type="text" name="private_contact" size="40"
473 @ value="$<private_contact>">
474 @ </td></tr>
475 @ <th1>enable_output 1</th1>
476 @ <tr><td align="right">Version&nbsp;Found&nbsp;In:</td><td>
477 @ <input type="text" name="foundin" size="50" value="$<foundin>">
478 @ </td></tr>
479 @ <tr><td colspan="2">
480 @ <th1>
481 @ if {![info exists eall]} {set eall 0}
482 @ if {[info exists aonlybtn]} {set eall 0}
@@ -484,45 +482,45 @@
484 @ if {![hascap w]} {set eall 0}
485 @ if {![info exists cmappnd]} {set cmappnd {}}
486 @ set nline [linecount $comment 15 10]
487 @ enable_output $eall
488 @ </th1>
489 @ Description And Comments:<br>
490 @ <textarea name="comment" cols="80" rows="$nline"
491 @ wrap="virtual" class="wikiedit">$<comment></textarea><br>
492 @ <input type="hidden" name="eall" value="1">
493 @ <input type="submit" name="aonlybtn" value="Append Remark">
494 @ <input type="submit" name="preview1btn" value="Preview">
495 @ <th1>enable_output [expr {!$eall}]</th1>
496 @ Append Remark from
497 @ <input type="text" name="username" value="$<username>" size="30">:<br>
498 @ <textarea name="cmappnd" cols="80" rows="15"
499 @ wrap="virtual" class="wikiedit">$<cmappnd></textarea><br>
500 @ <th1>enable_output [expr {[hascap w] && !$eall}]</th1>
501 @ <input type="submit" name="eallbtn" value="Edit All">
502 @ <th1>enable_output [expr {!$eall}]</th1>
503 @ <input type="submit" name="preview2btn" value="Preview">
504 @ <th1>enable_output 1</th1>
505 @ </td></tr>
506 @
507 @ <th1>enable_output [info exists preview1btn]</th1>
508 @ <tr><td colspan="2">
509 @ Description Preview:<br><hr>
510 @ <th1>wiki $comment</th1>
511 @ <hr>
512 @ </td></tr>
513 @ <th1>enable_output [info exists preview2btn]</th1>
514 @ <tr><td colspan="2">
515 @ Description Preview:<br><hr>
516 @ <th1>wiki $cmappnd</th1>
517 @ <hr>
518 @ </td></tr>
519 @ <th1>enable_output 1</th1>
520 @
521 @ <tr><td align="right"></td><td>
522 @ <input type="submit" name="submit" value="Submit Changes">
523 @ <input type="submit" name="cancel" value="Cancel">
524 @ </td></tr>
525 @ </table>
526 ;
527
528 /*
@@ -535,12 +533,11 @@
535 /*
536 ** WEBPAGE: tktsetup_editpage
537 */
538 void tktsetup_editpage_page(void){
539 static const char zDesc[] =
540 @ <p>Enter HTML with embedded TH1 script that will render the "edit ticket"
541 @ page</p>
542 ;
543 tktsetup_generic(
544 "HTML For Editing Tickets",
545 "ticket-editpage",
546 zDefaultEdit,
@@ -585,12 +582,11 @@
585 /*
586 ** WEBPAGE: tktsetup_reportlist
587 */
588 void tktsetup_reportlist(void){
589 static const char zDesc[] =
590 @ <p>Enter HTML with embedded TH1 script that will render the "report list"
591 @ page</p>
592 ;
593 tktsetup_generic(
594 "HTML For Report List",
595 "ticket-reportlist",
596 zDefaultReportList,
@@ -633,13 +629,13 @@
633 /*
634 ** WEBPAGE: tktsetup_rpttplt
635 */
636 void tktsetup_rpttplt_page(void){
637 static const char zDesc[] =
638 @ <p>Enter the default ticket report format template. This is the
639 @ the template report format that initially appears when creating a
640 @ new ticket summary report.</p>
641 ;
642 tktsetup_generic(
643 "Default Report Template",
644 "ticket-report-template",
645 zDefaultReport,
@@ -674,13 +670,13 @@
674 /*
675 ** WEBPAGE: tktsetup_keytplt
676 */
677 void tktsetup_keytplt_page(void){
678 static const char zDesc[] =
679 @ <p>Enter the default ticket report color-key template. This is the
680 @ the color-key that initially appears when creating a
681 @ new ticket summary report.</p>
682 ;
683 tktsetup_generic(
684 "Default Report Color-Key Template",
685 "ticket-key-template",
686 zDefaultKey,
@@ -703,34 +699,34 @@
703 if( P("setup") ){
704 cgi_redirect("tktsetup");
705 }
706 style_header("Ticket Display On Timelines");
707 db_begin_transaction();
708 @ <form action="%s(g.zBaseURL)/tktsetup_timeline" method="POST">
709 login_insert_csrf_secret();
710
711 @ <hr>
712 entry_attribute("Ticket Title", 40, "ticket-title-expr", "t", "title");
713 @ <p>An SQL expression in a query against the TICKET table that will
714 @ return the title of the ticket for display purposes.</p>
715
716 @ <hr>
717 entry_attribute("Ticket Status", 40, "ticket-status-column", "s", "status");
718 @ <p>The name of the column in the TICKET table that contains the ticket
719 @ status in human-readable form. Case sensitive.</p>
720
721 @ <hr>
722 entry_attribute("Ticket Closed", 40, "ticket-closed-expr", "c",
723 "status='Closed'");
724 @ <p>An SQL expression that evaluates to true in a TICKET table query if
725 @ the ticket is closed.</p>
726
727 @ <hr>
728 @ <p>
729 @ <input type="submit" name="submit" value="Apply Changes">
730 @ <input type="submit" name="setup" value="Cancel">
731 @ </p>
732 @ </form>
733 db_end_transaction(0);
734 style_footer();
735
736 }
737
--- src/tktsetup.c
+++ src/tktsetup.c
@@ -130,21 +130,21 @@
130 db_set(zDbField, z, 0);
131 if( xRebuild ) xRebuild();
132 cgi_redirect("tktsetup");
133 }
134 }
135 @ <form action="%s(g.zBaseURL)/%s(g.zPath)" method="post"><div>
136 login_insert_csrf_secret();
137 @ <p>%s(zDesc)</p>
138 @ <textarea name="x" rows="%d(height)" cols="80">%h(z)</textarea>
139 @ <blockquote><p>
140 @ <input type="submit" name="submit" value="Apply Changes" />
141 @ <input type="submit" name="clear" value="Revert To Default" />
142 @ <input type="submit" name="setup" value="Cancel" />
143 @ </p></blockquote>
144 @ </div></form>
145 @ <hr />
146 @ <h2>Default %s(zTitle)</h2>
147 @ <blockquote><pre>
148 @ %h(zDfltValue)
149 @ </pre></blockquote>
150 style_footer();
@@ -153,13 +153,13 @@
153 /*
154 ** WEBPAGE: tktsetup_tab
155 */
156 void tktsetup_tab_page(void){
157 static const char zDesc[] =
158 @ Enter a valid CREATE TABLE statement for the "ticket" table. The
159 @ table must contain columns named "tkt_id", "tkt_uuid", and "tkt_mtime"
160 @ with an unique index on "tkt_uuid" and "tkt_mtime".
161 ;
162 tktsetup_generic(
163 "Ticket Table Schema",
164 "ticket-table",
165 zDefaultTicketTable,
@@ -229,12 +229,12 @@
229 /*
230 ** WEBPAGE: tktsetup_com
231 */
232 void tktsetup_com_page(void){
233 static const char zDesc[] =
234 @ Enter TH1 script that initializes variables prior to generating
235 @ any of the ticket view, edit, or creation pages.
236 ;
237 tktsetup_generic(
238 "Ticket Common Script",
239 "ticket-common",
240 zDefaultTicketCommon,
@@ -250,80 +250,80 @@
250 @ if {[info exists submit]} {
251 @ set status Open
252 @ submit_ticket
253 @ }
254 @ </th1>
255 @ <h1 style="text-align: center;">Enter A New Ticket</h1>
256 @ <table cellpadding="5">
257 @ <tr>
258 @ <td colspan="2">
259 @ Enter a one-line summary of the ticket:<br />
260 @ <input type="text" name="title" size="60" value="$<title>" />
261 @ </td>
262 @ </tr>
263 @
264 @ <tr>
265 @ <td style="text-align: center;">Type:
266 @ <th1>combobox type $type_choices 1</th1>
267 @ </td>
268 @ <td>What type of ticket is this?</td>
269 @ </tr>
270 @
271 @ <tr>
272 @ <td style="text-align: center;">Version:
273 @ <input type="text" name="foundin" size="20" value="$<foundin>" />
274 @ </td>
275 @ <td>In what version or build number do you observe the problem?</td>
276 @ </tr>
277 @
278 @ <tr>
279 @ <td style="text-align: center;">Severity:
280 @ <th1>combobox severity $severity_choices 1</th1>
281 @ </td>
282 @ <td>How debilitating is the problem? How badly does the problem
283 @ affect the operation of the product?</td>
284 @ </tr>
285 @
286 @ <tr>
287 @ <td style="text-align: center;">EMail:
288 @ <input type="text" name="private_contact" value="$<private_contact>" size="30" />
289 @ </td>
290 @ <td><span style="text-decoration: underline;">Not publicly visible</span>.
291 @ Used by developers to contact you with questions.</td>
292 @ </tr>
293 @
294 @ <tr>
295 @ <td colspan="2">
296 @ Enter a detailed description of the problem.
297 @ For code defects, be sure to provide details on exactly how
298 @ the problem can be reproduced. Provide as much detail as
299 @ possible.
300 @ <br />
301 @ <th1>set nline [linecount $comment 50 10]</th1>
302 @ <textarea name="comment" cols="80" rows="$nline"
303 @ wrap="virtual" class="wikiedit">$<comment></textarea><br />
304 @ <input type="submit" name="preview" value="Preview" /></td>
305 @ </tr>
306 @
307 @ <th1>enable_output [info exists preview]</th1>
308 @ <tr><td colspan="2">
309 @ Description Preview:<br /><hr />
310 @ <th1>wiki $comment</th1>
311 @ <hr />
312 @ </td></tr>
313 @ <th1>enable_output 1</th1>
314 @
315 @ <tr>
316 @ <td style="text-align: center;">
317 @ <input type="submit" name="submit" value="Submit" />
318 @ </td>
319 @ <td>After filling in the information above, press this button to create
320 @ the new ticket</td>
321 @ </tr>
322 @ <tr>
323 @ <td style="text-align: center;">
324 @ <input type="submit" name="cancel" value="Cancel" />
325 @ </td>
326 @ <td>Abandon and forget this ticket</td>
327 @ </tr>
328 @ </table>
329 ;
@@ -338,12 +338,12 @@
338 /*
339 ** WEBPAGE: tktsetup_newpage
340 */
341 void tktsetup_newpage_page(void){
342 static const char zDesc[] =
343 @ Enter HTML with embedded TH1 script that will render the "new ticket"
344 @ page
345 ;
346 tktsetup_generic(
347 "HTML For New Tickets",
348 "ticket-newpage",
349 zDefaultNew,
@@ -354,51 +354,50 @@
354 );
355 }
356
357 static const char zDefaultView[] =
358 @ <table cellpadding="5">
359 @ <tr><td class="tktDspLabel">Ticket&nbsp;UUID:</td>
360 @ <td class="tktDspValue" colspan="3">$<tkt_uuid></td></tr>
361 @ <tr><td class="tktDspLabel">Title:</td>
362 @ <td class="tktDspValue" colspan="3">
 
363 @ <th1>wiki $title</th1>
364 @ </td></tr>
365 @ <tr><td class="tktDspLabel">Status:</td><td class="tktDspValue">
366 @ $<status>
367 @ </td>
368 @ <td class="tktDspLabel">Type:</td><td class="tktDspValue">
369 @ $<type>
370 @ </td></tr>
371 @ <tr><td class="tktDspLabel">Severity:</td><td class="tktDspValue">
372 @ $<severity>
373 @ </td>
374 @ <td class="tktDspLabel">Priority:</td><td class="tktDspValue">
375 @ $<priority>
376 @ </td></tr>
377 @ <tr><td class="tktDspLabel">Subsystem:</td><td class="tktDspValue">
378 @ $<subsystem>
379 @ </td>
380 @ <td class="tktDspLabel">Resolution:</td><td class="tktDspValue">
381 @ $<resolution>
382 @ </td></tr>
383 @ <tr><td class="tktDspLabel">Last&nbsp;Modified:</td><td class="tktDspValue">
384 @ $<tkt_datetime>
385 @ </td>
386 @ <th1>enable_output [hascap e]</th1>
387 @ <td class="tktDspLabel">Contact:</td><td class="tktDspValue">
388 @ $<private_contact>
389 @ </td>
390 @ <th1>enable_output 1</th1>
391 @ </tr>
392 @ <tr><td class="tktDspLabel">Version&nbsp;Found&nbsp;In:</td>
393 @ <td colspan="3" valign="top" class="tktDspValue">
394 @ $<foundin>
395 @ </td></tr>
396 @ <tr><td>Description &amp; Comments:</td></tr>
397 @ <tr><td colspan="4" class="tktDspValue">
398 @ <th1>wiki $comment</th1>
399 @ </td></tr>
400 @ </table>
401 ;
402
403
@@ -412,12 +411,11 @@
411 /*
412 ** WEBPAGE: tktsetup_viewpage
413 */
414 void tktsetup_viewpage_page(void){
415 static const char zDesc[] =
416 @ Enter HTML with embedded TH1 script that will render the "view ticket" page
 
417 ;
418 tktsetup_generic(
419 "HTML For Viewing Tickets",
420 "ticket-viewpage",
421 zDefaultView,
@@ -432,51 +430,51 @@
430 @ <th1>
431 @ if {![info exists username]} {set username $login}
432 @ if {[info exists submit]} {
433 @ if {[info exists cmappnd]} {
434 @ if {[string length $cmappnd]>0} {
435 @ set ctxt "\n\n<hr /><i>[htmlize $login]"
436 @ if {$username ne $login} {
437 @ set ctxt "$ctxt claiming to be [htmlize $username]"
438 @ }
439 @ set ctxt "$ctxt added on [date]:</i><br />\n$cmappnd"
440 @ append_field comment $ctxt
441 @ }
442 @ }
443 @ submit_ticket
444 @ }
445 @ </th1>
446 @ <table cellpadding="5">
447 @ <tr><td class="tktDspLabel">Title:</td><td>
448 @ <input type="text" name="title" value="$<title>" size="60" />
449 @ </td></tr>
450 @ <tr><td class="tktDspLabel">Status:</td><td>
451 @ <th1>combobox status $status_choices 1</th1>
452 @ </td></tr>
453 @ <tr><td class="tktDspLabel">Type:</td><td>
454 @ <th1>combobox type $type_choices 1</th1>
455 @ </td></tr>
456 @ <tr><td class="tktDspLabel">Severity:</td><td>
457 @ <th1>combobox severity $severity_choices 1</th1>
458 @ </td></tr>
459 @ <tr><td class="tktDspLabel">Priority:</td><td>
460 @ <th1>combobox priority $priority_choices 1</th1>
461 @ </td></tr>
462 @ <tr><td class="tktDspLabel">Resolution:</td><td>
463 @ <th1>combobox resolution $resolution_choices 1</th1>
464 @ </td></tr>
465 @ <tr><td class="tktDspLabel">Subsystem:</td><td>
466 @ <th1>combobox subsystem $subsystem_choices 1</th1>
467 @ </td></tr>
468 @ <th1>enable_output [hascap e]</th1>
469 @ <tr><td class="tktDspLabel">Contact:</td><td>
470 @ <input type="text" name="private_contact" size="40"
471 @ value="$<private_contact>" />
472 @ </td></tr>
473 @ <th1>enable_output 1</th1>
474 @ <tr><td class="tktDspLabel">Version&nbsp;Found&nbsp;In:</td><td>
475 @ <input type="text" name="foundin" size="50" value="$<foundin>" />
476 @ </td></tr>
477 @ <tr><td colspan="2">
478 @ <th1>
479 @ if {![info exists eall]} {set eall 0}
480 @ if {[info exists aonlybtn]} {set eall 0}
@@ -484,45 +482,45 @@
482 @ if {![hascap w]} {set eall 0}
483 @ if {![info exists cmappnd]} {set cmappnd {}}
484 @ set nline [linecount $comment 15 10]
485 @ enable_output $eall
486 @ </th1>
487 @ Description And Comments:<br />
488 @ <textarea name="comment" cols="80" rows="$nline"
489 @ wrap="virtual" class="wikiedit">$<comment></textarea><br />
490 @ <input type="hidden" name="eall" value="1" />
491 @ <input type="submit" name="aonlybtn" value="Append Remark" />
492 @ <input type="submit" name="preview1btn" value="Preview" />
493 @ <th1>enable_output [expr {!$eall}]</th1>
494 @ Append Remark from
495 @ <input type="text" name="username" value="$<username>" size="30" />:<br />
496 @ <textarea name="cmappnd" cols="80" rows="15"
497 @ wrap="virtual" class="wikiedit">$<cmappnd></textarea><br />
498 @ <th1>enable_output [expr {[hascap w] && !$eall}]</th1>
499 @ <input type="submit" name="eallbtn" value="Edit All" />
500 @ <th1>enable_output [expr {!$eall}]</th1>
501 @ <input type="submit" name="preview2btn" value="Preview" />
502 @ <th1>enable_output 1</th1>
503 @ </td></tr>
504 @
505 @ <th1>enable_output [info exists preview1btn]</th1>
506 @ <tr><td colspan="2">
507 @ Description Preview:<br /><hr />
508 @ <th1>wiki $comment</th1>
509 @ <hr />
510 @ </td></tr>
511 @ <th1>enable_output [info exists preview2btn]</th1>
512 @ <tr><td colspan="2">
513 @ Description Preview:<br /><hr />
514 @ <th1>wiki $cmappnd</th1>
515 @ <hr />
516 @ </td></tr>
517 @ <th1>enable_output 1</th1>
518 @
519 @ <tr><td align="right"></td><td>
520 @ <input type="submit" name="submit" value="Submit Changes" />
521 @ <input type="submit" name="cancel" value="Cancel" />
522 @ </td></tr>
523 @ </table>
524 ;
525
526 /*
@@ -535,12 +533,11 @@
533 /*
534 ** WEBPAGE: tktsetup_editpage
535 */
536 void tktsetup_editpage_page(void){
537 static const char zDesc[] =
538 @ Enter HTML with embedded TH1 script that will render the "edit ticket" page
 
539 ;
540 tktsetup_generic(
541 "HTML For Editing Tickets",
542 "ticket-editpage",
543 zDefaultEdit,
@@ -585,12 +582,11 @@
582 /*
583 ** WEBPAGE: tktsetup_reportlist
584 */
585 void tktsetup_reportlist(void){
586 static const char zDesc[] =
587 @ Enter HTML with embedded TH1 script that will render the "report list" page
 
588 ;
589 tktsetup_generic(
590 "HTML For Report List",
591 "ticket-reportlist",
592 zDefaultReportList,
@@ -633,13 +629,13 @@
629 /*
630 ** WEBPAGE: tktsetup_rpttplt
631 */
632 void tktsetup_rpttplt_page(void){
633 static const char zDesc[] =
634 @ Enter the default ticket report format template. This is the
635 @ the template report format that initially appears when creating a
636 @ new ticket summary report.
637 ;
638 tktsetup_generic(
639 "Default Report Template",
640 "ticket-report-template",
641 zDefaultReport,
@@ -674,13 +670,13 @@
670 /*
671 ** WEBPAGE: tktsetup_keytplt
672 */
673 void tktsetup_keytplt_page(void){
674 static const char zDesc[] =
675 @ Enter the default ticket report color-key template. This is the
676 @ the color-key that initially appears when creating a
677 @ new ticket summary report.
678 ;
679 tktsetup_generic(
680 "Default Report Color-Key Template",
681 "ticket-key-template",
682 zDefaultKey,
@@ -703,34 +699,34 @@
699 if( P("setup") ){
700 cgi_redirect("tktsetup");
701 }
702 style_header("Ticket Display On Timelines");
703 db_begin_transaction();
704 @ <form action="%s(g.zBaseURL)/tktsetup_timeline" method="post"><div>
705 login_insert_csrf_secret();
706
707 @ <hr />
708 entry_attribute("Ticket Title", 40, "ticket-title-expr", "t", "title");
709 @ <p>An SQL expression in a query against the TICKET table that will
710 @ return the title of the ticket for display purposes.</p>
711
712 @ <hr />
713 entry_attribute("Ticket Status", 40, "ticket-status-column", "s", "status");
714 @ <p>The name of the column in the TICKET table that contains the ticket
715 @ status in human-readable form. Case sensitive.</p>
716
717 @ <hr />
718 entry_attribute("Ticket Closed", 40, "ticket-closed-expr", "c",
719 "status='Closed'");
720 @ <p>An SQL expression that evaluates to true in a TICKET table query if
721 @ the ticket is closed.</p>
722
723 @ <hr />
724 @ <p>
725 @ <input type="submit" name="submit" value="Apply Changes" />
726 @ <input type="submit" name="setup" value="Cancel" />
727 @ </p>
728 @ </div></form>
729 db_end_transaction(0);
730 style_footer();
731
732 }
733
+11 -8
--- src/translate.c
+++ src/translate.c
@@ -66,15 +66,16 @@
6666
6767
/*
6868
** Translate the input stream into the output stream
6969
*/
7070
static void trans(FILE *in, FILE *out){
71
- int i, j, k; /* Loop counters */
72
- char c1, c2; /* Characters used to start a comment */
73
- int lastWasEq = 0; /* True if last non-whitespace character was "=" */
74
- char zLine[2000]; /* A single line of input */
75
- char zOut[4000]; /* The input line translated into appropriate output */
71
+ int i, j, k; /* Loop counters */
72
+ char c1, c2; /* Characters used to start a comment */
73
+ int lastWasEq = 0; /* True if last non-whitespace character was "=" */
74
+ int lastWasComma = 0; /* True if last non-whitespace character was "," */
75
+ char zLine[2000]; /* A single line of input */
76
+ char zOut[4000]; /* The input line translated into appropriate output */
7677
7778
c1 = c2 = '-';
7879
while( fgets(zLine, sizeof(zLine), in) ){
7980
for(i=0; zLine[i] && isspace(zLine[i]); i++){}
8081
if( zLine[i]!='@' ){
@@ -85,14 +86,16 @@
8586
c1 = zLine[14];
8687
c2 = zLine[15];
8788
}
8889
i += strlen(&zLine[i]);
8990
while( i>0 && isspace(zLine[i-1]) ){ i--; }
90
- lastWasEq = i>0 && zLine[i-1]=='=';
91
- }else if( lastWasEq ){
91
+ lastWasEq = i>0 && zLine[i-1]=='=';
92
+ lastWasComma = i>0 && zLine[i-1]==',';
93
+ }else if( lastWasEq || lastWasComma){
9294
/* If the last non-whitespace character before the first @ was
93
- ** an "=" then generate a string literal. But skip comments
95
+ ** an "="(var init/set) or a ","(const definition in list) then
96
+ ** generate a string literal. But skip comments
9497
** consisting of all text between c1 and c2 (default "--")
9598
** and end of line.
9699
*/
97100
int indent, omitline;
98101
i++;
99102
--- src/translate.c
+++ src/translate.c
@@ -66,15 +66,16 @@
66
67 /*
68 ** Translate the input stream into the output stream
69 */
70 static void trans(FILE *in, FILE *out){
71 int i, j, k; /* Loop counters */
72 char c1, c2; /* Characters used to start a comment */
73 int lastWasEq = 0; /* True if last non-whitespace character was "=" */
74 char zLine[2000]; /* A single line of input */
75 char zOut[4000]; /* The input line translated into appropriate output */
 
76
77 c1 = c2 = '-';
78 while( fgets(zLine, sizeof(zLine), in) ){
79 for(i=0; zLine[i] && isspace(zLine[i]); i++){}
80 if( zLine[i]!='@' ){
@@ -85,14 +86,16 @@
85 c1 = zLine[14];
86 c2 = zLine[15];
87 }
88 i += strlen(&zLine[i]);
89 while( i>0 && isspace(zLine[i-1]) ){ i--; }
90 lastWasEq = i>0 && zLine[i-1]=='=';
91 }else if( lastWasEq ){
 
92 /* If the last non-whitespace character before the first @ was
93 ** an "=" then generate a string literal. But skip comments
 
94 ** consisting of all text between c1 and c2 (default "--")
95 ** and end of line.
96 */
97 int indent, omitline;
98 i++;
99
--- src/translate.c
+++ src/translate.c
@@ -66,15 +66,16 @@
66
67 /*
68 ** Translate the input stream into the output stream
69 */
70 static void trans(FILE *in, FILE *out){
71 int i, j, k; /* Loop counters */
72 char c1, c2; /* Characters used to start a comment */
73 int lastWasEq = 0; /* True if last non-whitespace character was "=" */
74 int lastWasComma = 0; /* True if last non-whitespace character was "," */
75 char zLine[2000]; /* A single line of input */
76 char zOut[4000]; /* The input line translated into appropriate output */
77
78 c1 = c2 = '-';
79 while( fgets(zLine, sizeof(zLine), in) ){
80 for(i=0; zLine[i] && isspace(zLine[i]); i++){}
81 if( zLine[i]!='@' ){
@@ -85,14 +86,16 @@
86 c1 = zLine[14];
87 c2 = zLine[15];
88 }
89 i += strlen(&zLine[i]);
90 while( i>0 && isspace(zLine[i-1]) ){ i--; }
91 lastWasEq = i>0 && zLine[i-1]=='=';
92 lastWasComma = i>0 && zLine[i-1]==',';
93 }else if( lastWasEq || lastWasComma){
94 /* If the last non-whitespace character before the first @ was
95 ** an "="(var init/set) or a ","(const definition in list) then
96 ** generate a string literal. But skip comments
97 ** consisting of all text between c1 and c2 (default "--")
98 ** and end of line.
99 */
100 int indent, omitline;
101 i++;
102
--- src/update.c
+++ src/update.c
@@ -111,10 +111,11 @@
111111
tid = db_int(0, "SELECT rid FROM leaves, event"
112112
" WHERE event.objid=leaves.rid"
113113
" ORDER BY event.mtime DESC");
114114
}
115115
116
+ if( tid==vid ) return; /* Nothing to update */
116117
db_begin_transaction();
117118
vfile_check_signature(vid, 1);
118119
if( !nochangeFlag ) undo_begin();
119120
load_vfile_from_rid(tid);
120121
121122
--- src/update.c
+++ src/update.c
@@ -111,10 +111,11 @@
111 tid = db_int(0, "SELECT rid FROM leaves, event"
112 " WHERE event.objid=leaves.rid"
113 " ORDER BY event.mtime DESC");
114 }
115
 
116 db_begin_transaction();
117 vfile_check_signature(vid, 1);
118 if( !nochangeFlag ) undo_begin();
119 load_vfile_from_rid(tid);
120
121
--- src/update.c
+++ src/update.c
@@ -111,10 +111,11 @@
111 tid = db_int(0, "SELECT rid FROM leaves, event"
112 " WHERE event.objid=leaves.rid"
113 " ORDER BY event.mtime DESC");
114 }
115
116 if( tid==vid ) return; /* Nothing to update */
117 db_begin_transaction();
118 vfile_check_signature(vid, 1);
119 if( !nochangeFlag ) undo_begin();
120 load_vfile_from_rid(tid);
121
122
+1 -1
--- src/url.c
+++ src/url.c
@@ -351,11 +351,11 @@
351351
zName2 = 0;
352352
z = zValue2;
353353
if( z==0 ) continue;
354354
}
355355
blob_appendf(&p->url, "%s%s=%T", zSep, p->azName[i], z);
356
- zSep = "&";
356
+ zSep = "&amp;";
357357
}
358358
if( zName1 && zValue1 ){
359359
blob_appendf(&p->url, "%s%s=%T", zSep, zName1, zValue1);
360360
}
361361
if( zName2 && zValue2 ){
362362
--- src/url.c
+++ src/url.c
@@ -351,11 +351,11 @@
351 zName2 = 0;
352 z = zValue2;
353 if( z==0 ) continue;
354 }
355 blob_appendf(&p->url, "%s%s=%T", zSep, p->azName[i], z);
356 zSep = "&";
357 }
358 if( zName1 && zValue1 ){
359 blob_appendf(&p->url, "%s%s=%T", zSep, zName1, zValue1);
360 }
361 if( zName2 && zValue2 ){
362
--- src/url.c
+++ src/url.c
@@ -351,11 +351,11 @@
351 zName2 = 0;
352 z = zValue2;
353 if( z==0 ) continue;
354 }
355 blob_appendf(&p->url, "%s%s=%T", zSep, p->azName[i], z);
356 zSep = "&amp;";
357 }
358 if( zName1 && zValue1 ){
359 blob_appendf(&p->url, "%s%s=%T", zSep, zName1, zValue1);
360 }
361 if( zName2 && zValue2 ){
362
+46 -46
--- src/wiki.c
+++ src/wiki.c
@@ -48,15 +48,15 @@
4848
/*
4949
** Output rules for well-formed wiki pages
5050
*/
5151
static void well_formed_wiki_name_rules(void){
5252
@ <ul>
53
- @ <li> Must not begin or end with a space.
53
+ @ <li> Must not begin or end with a space.</li>
5454
@ <li> Must not contain any control characters, including tab or
55
- @ newline.
56
- @ <li> Must not have two or more spaces in a row internally.
57
- @ <li> Must be between 3 and 100 characters in length.
55
+ @ newline.</li>
56
+ @ <li> Must not have two or more spaces in a row internally.</li>
57
+ @ <li> Must be between 3 and 100 characters in length.</li>
5858
@ </ul>
5959
}
6060
6161
/*
6262
** Check a wiki name. If it is not well-formed, then issue an error
@@ -63,12 +63,12 @@
6363
** and return true. If it is well-formed, return false.
6464
*/
6565
static int check_name(const char *z){
6666
if( !wiki_name_is_wellformed((const unsigned char *)z) ){
6767
style_header("Wiki Page Name Error");
68
- @ The wiki name "<b>%h(z)</b>" is not well-formed. Rules for
69
- @ wiki page names:
68
+ @ The wiki name "<span class="wikiError">%h(z)</span>" is not well-formed.
69
+ @ Rules for wiki page names:
7070
well_formed_wiki_name_rules();
7171
style_footer();
7272
return 1;
7373
}
7474
return 0;
@@ -155,14 +155,14 @@
155155
if( g.okNewWiki ){
156156
@ <li> Create a <a href="%s(g.zBaseURL)/wikinew">new wiki page</a>.</li>
157157
}
158158
@ <li> <a href="%s(g.zBaseURL)/wcontent">List of All Wiki Pages</a>
159159
@ available on this server.</li>
160
- @ <li> <form method="GET" action="%s(g.zBaseURL)/wfind">
161
- @ Search wiki titles: <input type="text" name="title"/>
162
- @ &nbsp; <input type="submit" />
163
- @ </li>
160
+ @ <li> <form method="get" action="%s(g.zBaseURL)/wfind"><div>
161
+ @ Search wiki titles: <input type="text" name="title"/>
162
+ @ &nbsp; <input type="submit" /></div></form>
163
+ @ </li>
164164
@ </ul>
165165
style_footer();
166166
return;
167167
}
168168
if( check_name(zPageName) ) return;
@@ -194,11 +194,11 @@
194194
style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T",
195195
g.zTop, zPageName);
196196
}
197197
if( rid && g.okApndWiki && g.okAttach ){
198198
style_submenu_element("Attach", "Add An Attachment",
199
- "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T",
199
+ "%s/attachadd?page=%T&amp;from=%s/wiki%%3fname=%T",
200200
g.zTop, zPageName, g.zTop, zPageName);
201201
}
202202
if( rid && g.okApndWiki ){
203203
style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T",
204204
g.zTop, zPageName);
@@ -227,19 +227,20 @@
227227
@ <hr><h2>Attachments:</h2>
228228
@ <ul>
229229
}
230230
cnt++;
231231
if( g.okHistory && g.okRead ){
232
- @ <li><a href="%s(g.zTop)/attachview?page=%s(zPageName)&file=%t(zFile)">
232
+ @ <li>
233
+ @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&amp;file=%t(zFile)">
233234
@ %h(zFile)</a>
234235
}else{
235236
@ <li>%h(zFile)
236237
}
237238
@ added by %h(zUser) on
238239
hyperlink_to_date(zDate, ".");
239240
if( g.okWrWiki && g.okAttach ){
240
- @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&file=%t(zFile)&from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>]
241
+ @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&amp;file=%t(zFile)&amp;from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>]
241242
}
242243
}
243244
if( cnt ){
244245
@ </ul>
245246
}
@@ -351,30 +352,30 @@
351352
zHtmlPageName = mprintf("Edit: %s", zPageName);
352353
style_header(zHtmlPageName);
353354
if( P("preview")!=0 ){
354355
blob_zero(&wiki);
355356
blob_append(&wiki, zBody, -1);
356
- @ Preview:<hr>
357
+ @ Preview:<hr />
357358
wiki_convert(&wiki, 0, 0);
358
- @ <hr>
359
+ @ <hr />
359360
blob_reset(&wiki);
360361
}
361362
for(n=2, z=zBody; z[0]; z++){
362363
if( z[0]=='\n' ) n++;
363364
}
364365
if( n<20 ) n = 20;
365366
if( n>40 ) n = 40;
366
- @ <form method="POST" action="%s(g.zBaseURL)/wikiedit">
367
+ @ <form method="post" action="%s(g.zBaseURL)/wikiedit"><div>
367368
login_insert_csrf_secret();
368
- @ <input type="hidden" name="name" value="%h(zPageName)">
369
+ @ <input type="hidden" name="name" value="%h(zPageName)" />
369370
@ <textarea name="w" class="wikiedit" cols="80"
370371
@ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
371
- @ <br>
372
- @ <input type="submit" name="preview" value="Preview Your Changes">
373
- @ <input type="submit" name="submit" value="Apply These Changes">
374
- @ <input type="submit" name="cancel" value="Cancel">
375
- @ </form>
372
+ @ <br />
373
+ @ <input type="submit" name="preview" value="Preview Your Changes" />
374
+ @ <input type="submit" name="submit" value="Apply These Changes" />
375
+ @ <input type="submit" name="cancel" value="Cancel" />
376
+ @ </div></form>
376377
if( !isSandbox ){
377378
manifest_clear(&m);
378379
}
379380
style_footer();
380381
}
@@ -396,21 +397,20 @@
396397
zName = PD("name","");
397398
if( zName[0] && wiki_name_is_wellformed((const unsigned char *)zName) ){
398399
cgi_redirectf("wikiedit?name=%T", zName);
399400
}
400401
style_header("Create A New Wiki Page");
401
- @ <p>Rules for wiki page names:
402
+ @ <p>Rules for wiki page names:</p>
402403
well_formed_wiki_name_rules();
403
- @ </p>
404
- @ <form method="POST" action="%s(g.zBaseURL)/wikinew">
404
+ @ <form method="post" action="%s(g.zBaseURL)/wikinew">
405405
@ <p>Name of new wiki page:
406
- @ <input type="text" width="35" name="name" value="%h(zName)">
407
- @ <input type="submit" value="Create">
406
+ @ <input style="width: 35;" type="text" name="name" value="%h(zName)" />
407
+ @ <input type="submit" value="Create" />
408408
@ </p></form>
409409
if( zName[0] ){
410
- @ <p><b><font color="red">
411
- @ "%h(zName)" is not a valid wiki page name!</font></b></p>
410
+ @ <p><span class="wikiError">
411
+ @ "%h(zName)" is not a valid wiki page name!</span></p>
412412
}
413413
style_footer();
414414
}
415415
416416
@@ -537,15 +537,15 @@
537537
zUser = PD("u", g.zLogin);
538538
@ <form method="POST" action="%s(g.zBaseURL)/wikiappend">
539539
login_insert_csrf_secret();
540540
@ <input type="hidden" name="name" value="%h(zPageName)">
541541
@ Your Name:
542
- @ <input type="text" name="u" size="20" value="%h(zUser)"><br>
543
- @ Comment to append:<br>
542
+ @ <input type="text" name="u" size="20" value="%h(zUser)"><br />
543
+ @ Comment to append:<br />
544544
@ <textarea name="r" class="wikiedit" cols="80"
545545
@ rows="10" wrap="virtual">%h(PD("r",""))</textarea>
546
- @ <br>
546
+ @ <br />
547547
@ <input type="submit" name="preview" value="Preview Your Comment">
548548
@ <input type="submit" name="submit" value="Append Your Changes">
549549
@ <input type="submit" name="cancel" value="Cancel">
550550
@ </form>
551551
style_footer();
@@ -560,11 +560,11 @@
560560
** Function called to output extra text at the end of each line in
561561
** a wiki history listing.
562562
*/
563563
static void wiki_history_extra(int rid){
564564
if( db_exists("SELECT 1 FROM tagxref WHERE rid=%d", rid) ){
565
- @ <a href="%s(g.zTop)/wdiff?name=%t(zWikiPageName)&a=%d(rid)">[diff]</a>
565
+ @ <a href="%s(g.zTop)/wdiff?name=%t(zWikiPageName)&amp;a=%d(rid)">[diff]</a>
566566
}
567567
}
568568
569569
/*
570570
** WEBPAGE: whistory
@@ -740,39 +740,39 @@
740740
@ </ol>
741741
@ <p>We call the first five rules above "wiki" formatting rules. The
742742
@ last two rules are the HTML formatting rule.</p>
743743
@ <h2>Formatting Rule Details</h2>
744744
@ <ol>
745
- @ <li> <p><b>Paragraphs</b>. Any sequence of one or more blank lines forms
745
+ @ <li> <p><span class="wikiruleHead">Paragraphs</span>. Any sequence of one or more blank lines forms
746746
@ a paragraph break. Centered or right-justified paragraphs are not
747747
@ supported by wiki markup, but you can do these things if you need them
748
- @ using HTML.</p>
749
- @ <li> <p><b>Bullet Lists</b>.
748
+ @ using HTML.</p></li>
749
+ @ <li> <p><span class="wikiruleHead">Bullet Lists</span>.
750750
@ A bullet list item is a line that begins with a single "*" character
751751
@ surrounded on
752752
@ both sides by two or more spaces or by a tab. Only a single level
753
- @ of bullet list is supported by wiki. For nested lists, use HTML.</p>
754
- @ <li> <p><b>Enumeration Lists</b>.
753
+ @ of bullet list is supported by wiki. For nested lists, use HTML.</p></li>
754
+ @ <li> <p><span class="wikiruleHead">Enumeration Lists</span>.
755755
@ An enumeration list item is a line that begins with a single "#" character
756756
@ surrounded on both sides by two or more spaces or by a tab. Only a single
757757
@ level of enumeration list is supported by wiki. For nested lists or for
758
- @ enumerations that count using letters or roman numerials, use HTML.</p>
759
- @ <li> <p><b>Indented Paragraphs</b>.
758
+ @ enumerations that count using letters or roman numerials, use HTML.</p></li>
759
+ @ <li> <p><span class="wikiruleHead">Indented Paragraphs</span>.
760760
@ Any paragraph that begins with two or more spaces or a tab and
761761
@ which is not a bullet or enumeration list item is rendered
762762
@ indented. Only a single level of indentation is supported by wiki; use
763
- @ HTML for deeper indentation.</p>
764
- @ <li> <p><b>Hyperlinks</b>.
763
+ @ HTML for deeper indentation.</p></li>
764
+ @ <li> <p><span class="wikiruleHead">Hyperlinks</span>.
765765
@ Text within square brackets ("[...]") becomes a hyperlink. The
766766
@ target can be a wiki page name, the artifact ID of a check-in or ticket,
767767
@ the name of an image, or a URL. By default, the target is displayed
768768
@ as the text of the hyperlink. But you can specify alternative text
769769
@ after the target name separated by a "|" character.</p>
770770
@ <p>You can also link to internal anchor names using [#anchor-name], providing
771771
@ you have added the necessary "&lt;a name="anchor-name"&gt;&lt;/a&gt;"
772
- @ tag to your wiki page.</p>
773
- @ <li> <p><b>HTML</b>.
772
+ @ tag to your wiki page.</p></li>
773
+ @ <li> <p><span class="wikiruleHead">HTML</span>.
774774
@ The following standard HTML elements may be used:
775775
@ &lt;a&gt;
776776
@ &lt;address&gt;
777777
@ &lt;b&gt;
778778
@ &lt;big&gt;
@@ -822,16 +822,16 @@
822822
@ &lt;verbatim&gt; and &lt;nowiki&gt;.
823823
@ No other elements are allowed. All attributes are checked and
824824
@ only a few benign attributes are allowed on each element.
825825
@ In particular, any attributes that specify javascript or CSS
826826
@ are elided.</p></li>
827
- @ <li><p><b>Special Markup.</b>
827
+ @ <li><p><span class="wikiruleHead">Special Markup.</span>
828828
@ The &lt;nowiki&gt; tag disables all wiki formatting rules
829829
@ through the matching &lt;/nowiki&gt; element.
830830
@ The &lt;verbatim&gt; tag works like &lt;pre&gt; with the addition
831831
@ that it also disables all wiki and HTML markup
832
- @ through the matching &lt;/verbatim&gt;.
832
+ @ through the matching &lt;/verbatim&gt;.</p></li>
833833
@ </ol>
834834
style_footer();
835835
}
836836
837837
/*
838838
--- src/wiki.c
+++ src/wiki.c
@@ -48,15 +48,15 @@
48 /*
49 ** Output rules for well-formed wiki pages
50 */
51 static void well_formed_wiki_name_rules(void){
52 @ <ul>
53 @ <li> Must not begin or end with a space.
54 @ <li> Must not contain any control characters, including tab or
55 @ newline.
56 @ <li> Must not have two or more spaces in a row internally.
57 @ <li> Must be between 3 and 100 characters in length.
58 @ </ul>
59 }
60
61 /*
62 ** Check a wiki name. If it is not well-formed, then issue an error
@@ -63,12 +63,12 @@
63 ** and return true. If it is well-formed, return false.
64 */
65 static int check_name(const char *z){
66 if( !wiki_name_is_wellformed((const unsigned char *)z) ){
67 style_header("Wiki Page Name Error");
68 @ The wiki name "<b>%h(z)</b>" is not well-formed. Rules for
69 @ wiki page names:
70 well_formed_wiki_name_rules();
71 style_footer();
72 return 1;
73 }
74 return 0;
@@ -155,14 +155,14 @@
155 if( g.okNewWiki ){
156 @ <li> Create a <a href="%s(g.zBaseURL)/wikinew">new wiki page</a>.</li>
157 }
158 @ <li> <a href="%s(g.zBaseURL)/wcontent">List of All Wiki Pages</a>
159 @ available on this server.</li>
160 @ <li> <form method="GET" action="%s(g.zBaseURL)/wfind">
161 @ Search wiki titles: <input type="text" name="title"/>
162 @ &nbsp; <input type="submit" />
163 @ </li>
164 @ </ul>
165 style_footer();
166 return;
167 }
168 if( check_name(zPageName) ) return;
@@ -194,11 +194,11 @@
194 style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T",
195 g.zTop, zPageName);
196 }
197 if( rid && g.okApndWiki && g.okAttach ){
198 style_submenu_element("Attach", "Add An Attachment",
199 "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T",
200 g.zTop, zPageName, g.zTop, zPageName);
201 }
202 if( rid && g.okApndWiki ){
203 style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T",
204 g.zTop, zPageName);
@@ -227,19 +227,20 @@
227 @ <hr><h2>Attachments:</h2>
228 @ <ul>
229 }
230 cnt++;
231 if( g.okHistory && g.okRead ){
232 @ <li><a href="%s(g.zTop)/attachview?page=%s(zPageName)&file=%t(zFile)">
 
233 @ %h(zFile)</a>
234 }else{
235 @ <li>%h(zFile)
236 }
237 @ added by %h(zUser) on
238 hyperlink_to_date(zDate, ".");
239 if( g.okWrWiki && g.okAttach ){
240 @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&file=%t(zFile)&from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>]
241 }
242 }
243 if( cnt ){
244 @ </ul>
245 }
@@ -351,30 +352,30 @@
351 zHtmlPageName = mprintf("Edit: %s", zPageName);
352 style_header(zHtmlPageName);
353 if( P("preview")!=0 ){
354 blob_zero(&wiki);
355 blob_append(&wiki, zBody, -1);
356 @ Preview:<hr>
357 wiki_convert(&wiki, 0, 0);
358 @ <hr>
359 blob_reset(&wiki);
360 }
361 for(n=2, z=zBody; z[0]; z++){
362 if( z[0]=='\n' ) n++;
363 }
364 if( n<20 ) n = 20;
365 if( n>40 ) n = 40;
366 @ <form method="POST" action="%s(g.zBaseURL)/wikiedit">
367 login_insert_csrf_secret();
368 @ <input type="hidden" name="name" value="%h(zPageName)">
369 @ <textarea name="w" class="wikiedit" cols="80"
370 @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
371 @ <br>
372 @ <input type="submit" name="preview" value="Preview Your Changes">
373 @ <input type="submit" name="submit" value="Apply These Changes">
374 @ <input type="submit" name="cancel" value="Cancel">
375 @ </form>
376 if( !isSandbox ){
377 manifest_clear(&m);
378 }
379 style_footer();
380 }
@@ -396,21 +397,20 @@
396 zName = PD("name","");
397 if( zName[0] && wiki_name_is_wellformed((const unsigned char *)zName) ){
398 cgi_redirectf("wikiedit?name=%T", zName);
399 }
400 style_header("Create A New Wiki Page");
401 @ <p>Rules for wiki page names:
402 well_formed_wiki_name_rules();
403 @ </p>
404 @ <form method="POST" action="%s(g.zBaseURL)/wikinew">
405 @ <p>Name of new wiki page:
406 @ <input type="text" width="35" name="name" value="%h(zName)">
407 @ <input type="submit" value="Create">
408 @ </p></form>
409 if( zName[0] ){
410 @ <p><b><font color="red">
411 @ "%h(zName)" is not a valid wiki page name!</font></b></p>
412 }
413 style_footer();
414 }
415
416
@@ -537,15 +537,15 @@
537 zUser = PD("u", g.zLogin);
538 @ <form method="POST" action="%s(g.zBaseURL)/wikiappend">
539 login_insert_csrf_secret();
540 @ <input type="hidden" name="name" value="%h(zPageName)">
541 @ Your Name:
542 @ <input type="text" name="u" size="20" value="%h(zUser)"><br>
543 @ Comment to append:<br>
544 @ <textarea name="r" class="wikiedit" cols="80"
545 @ rows="10" wrap="virtual">%h(PD("r",""))</textarea>
546 @ <br>
547 @ <input type="submit" name="preview" value="Preview Your Comment">
548 @ <input type="submit" name="submit" value="Append Your Changes">
549 @ <input type="submit" name="cancel" value="Cancel">
550 @ </form>
551 style_footer();
@@ -560,11 +560,11 @@
560 ** Function called to output extra text at the end of each line in
561 ** a wiki history listing.
562 */
563 static void wiki_history_extra(int rid){
564 if( db_exists("SELECT 1 FROM tagxref WHERE rid=%d", rid) ){
565 @ <a href="%s(g.zTop)/wdiff?name=%t(zWikiPageName)&a=%d(rid)">[diff]</a>
566 }
567 }
568
569 /*
570 ** WEBPAGE: whistory
@@ -740,39 +740,39 @@
740 @ </ol>
741 @ <p>We call the first five rules above "wiki" formatting rules. The
742 @ last two rules are the HTML formatting rule.</p>
743 @ <h2>Formatting Rule Details</h2>
744 @ <ol>
745 @ <li> <p><b>Paragraphs</b>. Any sequence of one or more blank lines forms
746 @ a paragraph break. Centered or right-justified paragraphs are not
747 @ supported by wiki markup, but you can do these things if you need them
748 @ using HTML.</p>
749 @ <li> <p><b>Bullet Lists</b>.
750 @ A bullet list item is a line that begins with a single "*" character
751 @ surrounded on
752 @ both sides by two or more spaces or by a tab. Only a single level
753 @ of bullet list is supported by wiki. For nested lists, use HTML.</p>
754 @ <li> <p><b>Enumeration Lists</b>.
755 @ An enumeration list item is a line that begins with a single "#" character
756 @ surrounded on both sides by two or more spaces or by a tab. Only a single
757 @ level of enumeration list is supported by wiki. For nested lists or for
758 @ enumerations that count using letters or roman numerials, use HTML.</p>
759 @ <li> <p><b>Indented Paragraphs</b>.
760 @ Any paragraph that begins with two or more spaces or a tab and
761 @ which is not a bullet or enumeration list item is rendered
762 @ indented. Only a single level of indentation is supported by wiki; use
763 @ HTML for deeper indentation.</p>
764 @ <li> <p><b>Hyperlinks</b>.
765 @ Text within square brackets ("[...]") becomes a hyperlink. The
766 @ target can be a wiki page name, the artifact ID of a check-in or ticket,
767 @ the name of an image, or a URL. By default, the target is displayed
768 @ as the text of the hyperlink. But you can specify alternative text
769 @ after the target name separated by a "|" character.</p>
770 @ <p>You can also link to internal anchor names using [#anchor-name], providing
771 @ you have added the necessary "&lt;a name="anchor-name"&gt;&lt;/a&gt;"
772 @ tag to your wiki page.</p>
773 @ <li> <p><b>HTML</b>.
774 @ The following standard HTML elements may be used:
775 @ &lt;a&gt;
776 @ &lt;address&gt;
777 @ &lt;b&gt;
778 @ &lt;big&gt;
@@ -822,16 +822,16 @@
822 @ &lt;verbatim&gt; and &lt;nowiki&gt;.
823 @ No other elements are allowed. All attributes are checked and
824 @ only a few benign attributes are allowed on each element.
825 @ In particular, any attributes that specify javascript or CSS
826 @ are elided.</p></li>
827 @ <li><p><b>Special Markup.</b>
828 @ The &lt;nowiki&gt; tag disables all wiki formatting rules
829 @ through the matching &lt;/nowiki&gt; element.
830 @ The &lt;verbatim&gt; tag works like &lt;pre&gt; with the addition
831 @ that it also disables all wiki and HTML markup
832 @ through the matching &lt;/verbatim&gt;.
833 @ </ol>
834 style_footer();
835 }
836
837 /*
838
--- src/wiki.c
+++ src/wiki.c
@@ -48,15 +48,15 @@
48 /*
49 ** Output rules for well-formed wiki pages
50 */
51 static void well_formed_wiki_name_rules(void){
52 @ <ul>
53 @ <li> Must not begin or end with a space.</li>
54 @ <li> Must not contain any control characters, including tab or
55 @ newline.</li>
56 @ <li> Must not have two or more spaces in a row internally.</li>
57 @ <li> Must be between 3 and 100 characters in length.</li>
58 @ </ul>
59 }
60
61 /*
62 ** Check a wiki name. If it is not well-formed, then issue an error
@@ -63,12 +63,12 @@
63 ** and return true. If it is well-formed, return false.
64 */
65 static int check_name(const char *z){
66 if( !wiki_name_is_wellformed((const unsigned char *)z) ){
67 style_header("Wiki Page Name Error");
68 @ The wiki name "<span class="wikiError">%h(z)</span>" is not well-formed.
69 @ Rules for wiki page names:
70 well_formed_wiki_name_rules();
71 style_footer();
72 return 1;
73 }
74 return 0;
@@ -155,14 +155,14 @@
155 if( g.okNewWiki ){
156 @ <li> Create a <a href="%s(g.zBaseURL)/wikinew">new wiki page</a>.</li>
157 }
158 @ <li> <a href="%s(g.zBaseURL)/wcontent">List of All Wiki Pages</a>
159 @ available on this server.</li>
160 @ <li> <form method="get" action="%s(g.zBaseURL)/wfind"><div>
161 @ Search wiki titles: <input type="text" name="title"/>
162 @ &nbsp; <input type="submit" /></div></form>
163 @ </li>
164 @ </ul>
165 style_footer();
166 return;
167 }
168 if( check_name(zPageName) ) return;
@@ -194,11 +194,11 @@
194 style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T",
195 g.zTop, zPageName);
196 }
197 if( rid && g.okApndWiki && g.okAttach ){
198 style_submenu_element("Attach", "Add An Attachment",
199 "%s/attachadd?page=%T&amp;from=%s/wiki%%3fname=%T",
200 g.zTop, zPageName, g.zTop, zPageName);
201 }
202 if( rid && g.okApndWiki ){
203 style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T",
204 g.zTop, zPageName);
@@ -227,19 +227,20 @@
227 @ <hr><h2>Attachments:</h2>
228 @ <ul>
229 }
230 cnt++;
231 if( g.okHistory && g.okRead ){
232 @ <li>
233 @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&amp;file=%t(zFile)">
234 @ %h(zFile)</a>
235 }else{
236 @ <li>%h(zFile)
237 }
238 @ added by %h(zUser) on
239 hyperlink_to_date(zDate, ".");
240 if( g.okWrWiki && g.okAttach ){
241 @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&amp;file=%t(zFile)&amp;from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>]
242 }
243 }
244 if( cnt ){
245 @ </ul>
246 }
@@ -351,30 +352,30 @@
352 zHtmlPageName = mprintf("Edit: %s", zPageName);
353 style_header(zHtmlPageName);
354 if( P("preview")!=0 ){
355 blob_zero(&wiki);
356 blob_append(&wiki, zBody, -1);
357 @ Preview:<hr />
358 wiki_convert(&wiki, 0, 0);
359 @ <hr />
360 blob_reset(&wiki);
361 }
362 for(n=2, z=zBody; z[0]; z++){
363 if( z[0]=='\n' ) n++;
364 }
365 if( n<20 ) n = 20;
366 if( n>40 ) n = 40;
367 @ <form method="post" action="%s(g.zBaseURL)/wikiedit"><div>
368 login_insert_csrf_secret();
369 @ <input type="hidden" name="name" value="%h(zPageName)" />
370 @ <textarea name="w" class="wikiedit" cols="80"
371 @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
372 @ <br />
373 @ <input type="submit" name="preview" value="Preview Your Changes" />
374 @ <input type="submit" name="submit" value="Apply These Changes" />
375 @ <input type="submit" name="cancel" value="Cancel" />
376 @ </div></form>
377 if( !isSandbox ){
378 manifest_clear(&m);
379 }
380 style_footer();
381 }
@@ -396,21 +397,20 @@
397 zName = PD("name","");
398 if( zName[0] && wiki_name_is_wellformed((const unsigned char *)zName) ){
399 cgi_redirectf("wikiedit?name=%T", zName);
400 }
401 style_header("Create A New Wiki Page");
402 @ <p>Rules for wiki page names:</p>
403 well_formed_wiki_name_rules();
404 @ <form method="post" action="%s(g.zBaseURL)/wikinew">
 
405 @ <p>Name of new wiki page:
406 @ <input style="width: 35;" type="text" name="name" value="%h(zName)" />
407 @ <input type="submit" value="Create" />
408 @ </p></form>
409 if( zName[0] ){
410 @ <p><span class="wikiError">
411 @ "%h(zName)" is not a valid wiki page name!</span></p>
412 }
413 style_footer();
414 }
415
416
@@ -537,15 +537,15 @@
537 zUser = PD("u", g.zLogin);
538 @ <form method="POST" action="%s(g.zBaseURL)/wikiappend">
539 login_insert_csrf_secret();
540 @ <input type="hidden" name="name" value="%h(zPageName)">
541 @ Your Name:
542 @ <input type="text" name="u" size="20" value="%h(zUser)"><br />
543 @ Comment to append:<br />
544 @ <textarea name="r" class="wikiedit" cols="80"
545 @ rows="10" wrap="virtual">%h(PD("r",""))</textarea>
546 @ <br />
547 @ <input type="submit" name="preview" value="Preview Your Comment">
548 @ <input type="submit" name="submit" value="Append Your Changes">
549 @ <input type="submit" name="cancel" value="Cancel">
550 @ </form>
551 style_footer();
@@ -560,11 +560,11 @@
560 ** Function called to output extra text at the end of each line in
561 ** a wiki history listing.
562 */
563 static void wiki_history_extra(int rid){
564 if( db_exists("SELECT 1 FROM tagxref WHERE rid=%d", rid) ){
565 @ <a href="%s(g.zTop)/wdiff?name=%t(zWikiPageName)&amp;a=%d(rid)">[diff]</a>
566 }
567 }
568
569 /*
570 ** WEBPAGE: whistory
@@ -740,39 +740,39 @@
740 @ </ol>
741 @ <p>We call the first five rules above "wiki" formatting rules. The
742 @ last two rules are the HTML formatting rule.</p>
743 @ <h2>Formatting Rule Details</h2>
744 @ <ol>
745 @ <li> <p><span class="wikiruleHead">Paragraphs</span>. Any sequence of one or more blank lines forms
746 @ a paragraph break. Centered or right-justified paragraphs are not
747 @ supported by wiki markup, but you can do these things if you need them
748 @ using HTML.</p></li>
749 @ <li> <p><span class="wikiruleHead">Bullet Lists</span>.
750 @ A bullet list item is a line that begins with a single "*" character
751 @ surrounded on
752 @ both sides by two or more spaces or by a tab. Only a single level
753 @ of bullet list is supported by wiki. For nested lists, use HTML.</p></li>
754 @ <li> <p><span class="wikiruleHead">Enumeration Lists</span>.
755 @ An enumeration list item is a line that begins with a single "#" character
756 @ surrounded on both sides by two or more spaces or by a tab. Only a single
757 @ level of enumeration list is supported by wiki. For nested lists or for
758 @ enumerations that count using letters or roman numerials, use HTML.</p></li>
759 @ <li> <p><span class="wikiruleHead">Indented Paragraphs</span>.
760 @ Any paragraph that begins with two or more spaces or a tab and
761 @ which is not a bullet or enumeration list item is rendered
762 @ indented. Only a single level of indentation is supported by wiki; use
763 @ HTML for deeper indentation.</p></li>
764 @ <li> <p><span class="wikiruleHead">Hyperlinks</span>.
765 @ Text within square brackets ("[...]") becomes a hyperlink. The
766 @ target can be a wiki page name, the artifact ID of a check-in or ticket,
767 @ the name of an image, or a URL. By default, the target is displayed
768 @ as the text of the hyperlink. But you can specify alternative text
769 @ after the target name separated by a "|" character.</p>
770 @ <p>You can also link to internal anchor names using [#anchor-name], providing
771 @ you have added the necessary "&lt;a name="anchor-name"&gt;&lt;/a&gt;"
772 @ tag to your wiki page.</p></li>
773 @ <li> <p><span class="wikiruleHead">HTML</span>.
774 @ The following standard HTML elements may be used:
775 @ &lt;a&gt;
776 @ &lt;address&gt;
777 @ &lt;b&gt;
778 @ &lt;big&gt;
@@ -822,16 +822,16 @@
822 @ &lt;verbatim&gt; and &lt;nowiki&gt;.
823 @ No other elements are allowed. All attributes are checked and
824 @ only a few benign attributes are allowed on each element.
825 @ In particular, any attributes that specify javascript or CSS
826 @ are elided.</p></li>
827 @ <li><p><span class="wikiruleHead">Special Markup.</span>
828 @ The &lt;nowiki&gt; tag disables all wiki formatting rules
829 @ through the matching &lt;/nowiki&gt; element.
830 @ The &lt;verbatim&gt; tag works like &lt;pre&gt; with the addition
831 @ that it also disables all wiki and HTML markup
832 @ through the matching &lt;/verbatim&gt;.</p></li>
833 @ </ol>
834 style_footer();
835 }
836
837 /*
838
+47 -21
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -321,21 +321,21 @@
321321
}
322322
323323
/*
324324
** Token types
325325
*/
326
-#define TOKEN_MARKUP 1 /* <...> */
327
-#define TOKEN_CHARACTER 2 /* "&" or "<" not part of markup */
328
-#define TOKEN_LINK 3 /* [...] */
329
-#define TOKEN_PARAGRAPH 4 /* blank lines */
330
-#define TOKEN_NEWLINE 5 /* A single "\n" */
331
-#define TOKEN_BUL_LI 6 /* " * " */
332
-#define TOKEN_NUM_LI 7 /* " # " */
333
-#define TOKEN_ENUM 8 /* " \(?\d+[.)]? " */
334
-#define TOKEN_INDENT 9 /* " " */
335
-#define TOKEN_RAW 10 /* Output exactly (used when wiki-use-html==1) */
336
-#define TOKEN_TEXT 11 /* None of the above */
326
+#define TOKEN_MARKUP 1 /* <...> */
327
+#define TOKEN_CHARACTER 2 /* "&" or "<" not part of markup */
328
+#define TOKEN_LINK 3 /* [...] */
329
+#define TOKEN_PARAGRAPH 4 /* blank lines */
330
+#define TOKEN_NEWLINE 5 /* A single "\n" */
331
+#define TOKEN_BUL_LI 6 /* " * " */
332
+#define TOKEN_NUM_LI 7 /* " # " */
333
+#define TOKEN_ENUM 8 /* " \(?\d+[.)]? " */
334
+#define TOKEN_INDENT 9 /* " " */
335
+#define TOKEN_RAW 10 /* Output exactly (used when wiki-use-html==1) */
336
+#define TOKEN_TEXT 11 /* None of the above */
337337
338338
/*
339339
** State flags
340340
*/
341341
#define AT_NEWLINE 0x001 /* At start of a line */
@@ -745,10 +745,13 @@
745745
static void renderMarkup(Blob *pOut, ParsedMarkup *p){
746746
int i;
747747
if( p->endTag ){
748748
blob_appendf(pOut, "</%s>", aMarkup[p->iCode].zName);
749749
}else{
750
+ /* Close active paragraph for several elements, which are not allowed
751
+ ** in paragraphs in XHTML.
752
+ */
750753
blob_appendf(pOut, "<%s", aMarkup[p->iCode].zName);
751754
for(i=0; i<p->nAttr; i++){
752755
blob_appendf(pOut, " %s", aAttribute[p->aAttr[i].iACode].zName);
753756
if( p->aAttr[i].zValue ){
754757
const char *zVal = p->aAttr[i].zValue;
@@ -756,10 +759,13 @@
756759
blob_appendf(pOut, "=\"%s%s\"", g.zBaseURL, zVal);
757760
}else{
758761
blob_appendf(pOut, "=\"%s\"", zVal);
759762
}
760763
}
764
+ }
765
+ if (p->iType & MUTYPE_SINGLE){
766
+ blob_append(pOut, " /", 2);
761767
}
762768
blob_append(pOut, ">", 1);
763769
}
764770
}
765771
@@ -885,12 +891,13 @@
885891
886892
/*
887893
** Begin a new paragraph if that something that is needed.
888894
*/
889895
static void startAutoParagraph(Renderer *p){
890
- if( p->wantAutoParagraph==0 || p->wikiList==MARKUP_OL || p->wikiList==MARKUP_UL ) return;
891
- blob_appendf(p->pOut, "<p>", -1);
896
+ if( p->wantAutoParagraph==0 ) return;
897
+ if( p->wikiList==MARKUP_OL || p->wikiList==MARKUP_UL ) return;
898
+ blob_appendf(p->pOut, "<p type=\"auto\">", -1);
892899
pushStack(p, MARKUP_P);
893900
p->wantAutoParagraph = 0;
894901
p->inAutoParagraph = 1;
895902
}
896903
@@ -1019,17 +1026,18 @@
10191026
/* Special display processing for tickets. Display the hyperlink
10201027
** as crossed out if the ticket is closed.
10211028
*/
10221029
if( isClosed ){
10231030
if( g.okHistory ){
1024
- blob_appendf(p->pOut,"<a href=\"%s/info/%s\"><s>",
1025
- g.zBaseURL, zTarget
1031
+ blob_appendf(p->pOut,
1032
+ "<a href=\"%s/info/%s\"><span class=\"wikiTagCancelled\">",
1033
+ g.zBaseURL, zTarget
10261034
);
1027
- zTerm = "</s></a>";
1035
+ zTerm = "</span></a>";
10281036
}else{
1029
- blob_appendf(p->pOut,"<s>");
1030
- zTerm = "</s>";
1037
+ blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">");
1038
+ zTerm = "</span>";
10311039
}
10321040
}else{
10331041
if( g.okHistory ){
10341042
blob_appendf(p->pOut,"<a href=\"%s/info/%s\">",
10351043
g.zBaseURL, zTarget
@@ -1133,10 +1141,11 @@
11331141
}else{
11341142
if( p->wikiList!=MARKUP_UL ){
11351143
if( p->wikiList ){
11361144
popStackToTag(p, p->wikiList);
11371145
}
1146
+ endAutoParagraph(p);
11381147
pushStack(p, MARKUP_UL);
11391148
blob_append(p->pOut, "<ul>", 4);
11401149
p->wikiList = MARKUP_UL;
11411150
}
11421151
popStackToTag(p, MARKUP_LI);
@@ -1152,10 +1161,11 @@
11521161
}else{
11531162
if( p->wikiList!=MARKUP_OL ){
11541163
if( p->wikiList ){
11551164
popStackToTag(p, p->wikiList);
11561165
}
1166
+ endAutoParagraph(p);
11571167
pushStack(p, MARKUP_OL);
11581168
blob_append(p->pOut, "<ol>", 4);
11591169
p->wikiList = MARKUP_OL;
11601170
}
11611171
popStackToTag(p, MARKUP_LI);
@@ -1171,10 +1181,11 @@
11711181
}else{
11721182
if( p->wikiList!=MARKUP_OL ){
11731183
if( p->wikiList ){
11741184
popStackToTag(p, p->wikiList);
11751185
}
1186
+ endAutoParagraph(p);
11761187
pushStack(p, MARKUP_OL);
11771188
blob_append(p->pOut, "<ol>", 4);
11781189
p->wikiList = MARKUP_OL;
11791190
}
11801191
popStackToTag(p, MARKUP_LI);
@@ -1233,11 +1244,13 @@
12331244
p->state = savedState;
12341245
blob_append(p->pOut, zClose, -1);
12351246
break;
12361247
}
12371248
case TOKEN_TEXT: {
1238
- startAutoParagraph(p);
1249
+ int i;
1250
+ for(i=0; i<n && isspace(z[i]); i++){}
1251
+ if( i<n ) startAutoParagraph(p);
12391252
blob_append(p->pOut, z, n);
12401253
break;
12411254
}
12421255
case TOKEN_RAW: {
12431256
blob_append(p->pOut, z, n);
@@ -1347,16 +1360,19 @@
13471360
blob_appendf(p->pOut, "<pre name='code' class='%s'>",
13481361
markup.aAttr[vAttrIdx].zValue);
13491362
vAttrDidAppend=1;
13501363
}
13511364
}
1352
- if( !vAttrDidAppend )
1365
+ if( !vAttrDidAppend ) {
1366
+ endAutoParagraph(p);
13531367
blob_append(p->pOut, "<pre class='verbatim'>",-1);
1368
+ }
13541369
p->wantAutoParagraph = 0;
13551370
}else
13561371
if( markup.iType==MUTYPE_LI ){
13571372
if( backupToType(p, MUTYPE_LIST)==0 ){
1373
+ endAutoParagraph(p);
13581374
pushStack(p, MARKUP_UL);
13591375
blob_append(p->pOut, "<ul>", 4);
13601376
}
13611377
pushStack(p, MARKUP_LI);
13621378
renderMarkup(p->pOut, &markup);
@@ -1384,12 +1400,22 @@
13841400
pushStack(p, markup.iCode);
13851401
}else
13861402
{
13871403
if( markup.iType==MUTYPE_FONT ){
13881404
startAutoParagraph(p);
1389
- }else if( markup.iType==MUTYPE_BLOCK ){
1405
+ }else if( markup.iType==MUTYPE_BLOCK || markup.iType==MUTYPE_LIST ){
13901406
p->wantAutoParagraph = 0;
1407
+ }
1408
+ if( markup.iCode==MARKUP_HR
1409
+ || markup.iCode==MARKUP_H1
1410
+ || markup.iCode==MARKUP_H2
1411
+ || markup.iCode==MARKUP_H3
1412
+ || markup.iCode==MARKUP_H4
1413
+ || markup.iCode==MARKUP_H5
1414
+ || markup.iCode==MARKUP_P
1415
+ ){
1416
+ endAutoParagraph(p);
13911417
}
13921418
if( (markup.iType & MUTYPE_STACK )!=0 ){
13931419
pushStack(p, markup.iCode);
13941420
}
13951421
renderMarkup(p->pOut, &markup);
13961422
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -321,21 +321,21 @@
321 }
322
323 /*
324 ** Token types
325 */
326 #define TOKEN_MARKUP 1 /* <...> */
327 #define TOKEN_CHARACTER 2 /* "&" or "<" not part of markup */
328 #define TOKEN_LINK 3 /* [...] */
329 #define TOKEN_PARAGRAPH 4 /* blank lines */
330 #define TOKEN_NEWLINE 5 /* A single "\n" */
331 #define TOKEN_BUL_LI 6 /* " * " */
332 #define TOKEN_NUM_LI 7 /* " # " */
333 #define TOKEN_ENUM 8 /* " \(?\d+[.)]? " */
334 #define TOKEN_INDENT 9 /* " " */
335 #define TOKEN_RAW 10 /* Output exactly (used when wiki-use-html==1) */
336 #define TOKEN_TEXT 11 /* None of the above */
337
338 /*
339 ** State flags
340 */
341 #define AT_NEWLINE 0x001 /* At start of a line */
@@ -745,10 +745,13 @@
745 static void renderMarkup(Blob *pOut, ParsedMarkup *p){
746 int i;
747 if( p->endTag ){
748 blob_appendf(pOut, "</%s>", aMarkup[p->iCode].zName);
749 }else{
 
 
 
750 blob_appendf(pOut, "<%s", aMarkup[p->iCode].zName);
751 for(i=0; i<p->nAttr; i++){
752 blob_appendf(pOut, " %s", aAttribute[p->aAttr[i].iACode].zName);
753 if( p->aAttr[i].zValue ){
754 const char *zVal = p->aAttr[i].zValue;
@@ -756,10 +759,13 @@
756 blob_appendf(pOut, "=\"%s%s\"", g.zBaseURL, zVal);
757 }else{
758 blob_appendf(pOut, "=\"%s\"", zVal);
759 }
760 }
 
 
 
761 }
762 blob_append(pOut, ">", 1);
763 }
764 }
765
@@ -885,12 +891,13 @@
885
886 /*
887 ** Begin a new paragraph if that something that is needed.
888 */
889 static void startAutoParagraph(Renderer *p){
890 if( p->wantAutoParagraph==0 || p->wikiList==MARKUP_OL || p->wikiList==MARKUP_UL ) return;
891 blob_appendf(p->pOut, "<p>", -1);
 
892 pushStack(p, MARKUP_P);
893 p->wantAutoParagraph = 0;
894 p->inAutoParagraph = 1;
895 }
896
@@ -1019,17 +1026,18 @@
1019 /* Special display processing for tickets. Display the hyperlink
1020 ** as crossed out if the ticket is closed.
1021 */
1022 if( isClosed ){
1023 if( g.okHistory ){
1024 blob_appendf(p->pOut,"<a href=\"%s/info/%s\"><s>",
1025 g.zBaseURL, zTarget
 
1026 );
1027 zTerm = "</s></a>";
1028 }else{
1029 blob_appendf(p->pOut,"<s>");
1030 zTerm = "</s>";
1031 }
1032 }else{
1033 if( g.okHistory ){
1034 blob_appendf(p->pOut,"<a href=\"%s/info/%s\">",
1035 g.zBaseURL, zTarget
@@ -1133,10 +1141,11 @@
1133 }else{
1134 if( p->wikiList!=MARKUP_UL ){
1135 if( p->wikiList ){
1136 popStackToTag(p, p->wikiList);
1137 }
 
1138 pushStack(p, MARKUP_UL);
1139 blob_append(p->pOut, "<ul>", 4);
1140 p->wikiList = MARKUP_UL;
1141 }
1142 popStackToTag(p, MARKUP_LI);
@@ -1152,10 +1161,11 @@
1152 }else{
1153 if( p->wikiList!=MARKUP_OL ){
1154 if( p->wikiList ){
1155 popStackToTag(p, p->wikiList);
1156 }
 
1157 pushStack(p, MARKUP_OL);
1158 blob_append(p->pOut, "<ol>", 4);
1159 p->wikiList = MARKUP_OL;
1160 }
1161 popStackToTag(p, MARKUP_LI);
@@ -1171,10 +1181,11 @@
1171 }else{
1172 if( p->wikiList!=MARKUP_OL ){
1173 if( p->wikiList ){
1174 popStackToTag(p, p->wikiList);
1175 }
 
1176 pushStack(p, MARKUP_OL);
1177 blob_append(p->pOut, "<ol>", 4);
1178 p->wikiList = MARKUP_OL;
1179 }
1180 popStackToTag(p, MARKUP_LI);
@@ -1233,11 +1244,13 @@
1233 p->state = savedState;
1234 blob_append(p->pOut, zClose, -1);
1235 break;
1236 }
1237 case TOKEN_TEXT: {
1238 startAutoParagraph(p);
 
 
1239 blob_append(p->pOut, z, n);
1240 break;
1241 }
1242 case TOKEN_RAW: {
1243 blob_append(p->pOut, z, n);
@@ -1347,16 +1360,19 @@
1347 blob_appendf(p->pOut, "<pre name='code' class='%s'>",
1348 markup.aAttr[vAttrIdx].zValue);
1349 vAttrDidAppend=1;
1350 }
1351 }
1352 if( !vAttrDidAppend )
 
1353 blob_append(p->pOut, "<pre class='verbatim'>",-1);
 
1354 p->wantAutoParagraph = 0;
1355 }else
1356 if( markup.iType==MUTYPE_LI ){
1357 if( backupToType(p, MUTYPE_LIST)==0 ){
 
1358 pushStack(p, MARKUP_UL);
1359 blob_append(p->pOut, "<ul>", 4);
1360 }
1361 pushStack(p, MARKUP_LI);
1362 renderMarkup(p->pOut, &markup);
@@ -1384,12 +1400,22 @@
1384 pushStack(p, markup.iCode);
1385 }else
1386 {
1387 if( markup.iType==MUTYPE_FONT ){
1388 startAutoParagraph(p);
1389 }else if( markup.iType==MUTYPE_BLOCK ){
1390 p->wantAutoParagraph = 0;
 
 
 
 
 
 
 
 
 
 
1391 }
1392 if( (markup.iType & MUTYPE_STACK )!=0 ){
1393 pushStack(p, markup.iCode);
1394 }
1395 renderMarkup(p->pOut, &markup);
1396
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -321,21 +321,21 @@
321 }
322
323 /*
324 ** Token types
325 */
326 #define TOKEN_MARKUP 1 /* <...> */
327 #define TOKEN_CHARACTER 2 /* "&" or "<" not part of markup */
328 #define TOKEN_LINK 3 /* [...] */
329 #define TOKEN_PARAGRAPH 4 /* blank lines */
330 #define TOKEN_NEWLINE 5 /* A single "\n" */
331 #define TOKEN_BUL_LI 6 /* " * " */
332 #define TOKEN_NUM_LI 7 /* " # " */
333 #define TOKEN_ENUM 8 /* " \(?\d+[.)]? " */
334 #define TOKEN_INDENT 9 /* " " */
335 #define TOKEN_RAW 10 /* Output exactly (used when wiki-use-html==1) */
336 #define TOKEN_TEXT 11 /* None of the above */
337
338 /*
339 ** State flags
340 */
341 #define AT_NEWLINE 0x001 /* At start of a line */
@@ -745,10 +745,13 @@
745 static void renderMarkup(Blob *pOut, ParsedMarkup *p){
746 int i;
747 if( p->endTag ){
748 blob_appendf(pOut, "</%s>", aMarkup[p->iCode].zName);
749 }else{
750 /* Close active paragraph for several elements, which are not allowed
751 ** in paragraphs in XHTML.
752 */
753 blob_appendf(pOut, "<%s", aMarkup[p->iCode].zName);
754 for(i=0; i<p->nAttr; i++){
755 blob_appendf(pOut, " %s", aAttribute[p->aAttr[i].iACode].zName);
756 if( p->aAttr[i].zValue ){
757 const char *zVal = p->aAttr[i].zValue;
@@ -756,10 +759,13 @@
759 blob_appendf(pOut, "=\"%s%s\"", g.zBaseURL, zVal);
760 }else{
761 blob_appendf(pOut, "=\"%s\"", zVal);
762 }
763 }
764 }
765 if (p->iType & MUTYPE_SINGLE){
766 blob_append(pOut, " /", 2);
767 }
768 blob_append(pOut, ">", 1);
769 }
770 }
771
@@ -885,12 +891,13 @@
891
892 /*
893 ** Begin a new paragraph if that something that is needed.
894 */
895 static void startAutoParagraph(Renderer *p){
896 if( p->wantAutoParagraph==0 ) return;
897 if( p->wikiList==MARKUP_OL || p->wikiList==MARKUP_UL ) return;
898 blob_appendf(p->pOut, "<p type=\"auto\">", -1);
899 pushStack(p, MARKUP_P);
900 p->wantAutoParagraph = 0;
901 p->inAutoParagraph = 1;
902 }
903
@@ -1019,17 +1026,18 @@
1026 /* Special display processing for tickets. Display the hyperlink
1027 ** as crossed out if the ticket is closed.
1028 */
1029 if( isClosed ){
1030 if( g.okHistory ){
1031 blob_appendf(p->pOut,
1032 "<a href=\"%s/info/%s\"><span class=\"wikiTagCancelled\">",
1033 g.zBaseURL, zTarget
1034 );
1035 zTerm = "</span></a>";
1036 }else{
1037 blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">");
1038 zTerm = "</span>";
1039 }
1040 }else{
1041 if( g.okHistory ){
1042 blob_appendf(p->pOut,"<a href=\"%s/info/%s\">",
1043 g.zBaseURL, zTarget
@@ -1133,10 +1141,11 @@
1141 }else{
1142 if( p->wikiList!=MARKUP_UL ){
1143 if( p->wikiList ){
1144 popStackToTag(p, p->wikiList);
1145 }
1146 endAutoParagraph(p);
1147 pushStack(p, MARKUP_UL);
1148 blob_append(p->pOut, "<ul>", 4);
1149 p->wikiList = MARKUP_UL;
1150 }
1151 popStackToTag(p, MARKUP_LI);
@@ -1152,10 +1161,11 @@
1161 }else{
1162 if( p->wikiList!=MARKUP_OL ){
1163 if( p->wikiList ){
1164 popStackToTag(p, p->wikiList);
1165 }
1166 endAutoParagraph(p);
1167 pushStack(p, MARKUP_OL);
1168 blob_append(p->pOut, "<ol>", 4);
1169 p->wikiList = MARKUP_OL;
1170 }
1171 popStackToTag(p, MARKUP_LI);
@@ -1171,10 +1181,11 @@
1181 }else{
1182 if( p->wikiList!=MARKUP_OL ){
1183 if( p->wikiList ){
1184 popStackToTag(p, p->wikiList);
1185 }
1186 endAutoParagraph(p);
1187 pushStack(p, MARKUP_OL);
1188 blob_append(p->pOut, "<ol>", 4);
1189 p->wikiList = MARKUP_OL;
1190 }
1191 popStackToTag(p, MARKUP_LI);
@@ -1233,11 +1244,13 @@
1244 p->state = savedState;
1245 blob_append(p->pOut, zClose, -1);
1246 break;
1247 }
1248 case TOKEN_TEXT: {
1249 int i;
1250 for(i=0; i<n && isspace(z[i]); i++){}
1251 if( i<n ) startAutoParagraph(p);
1252 blob_append(p->pOut, z, n);
1253 break;
1254 }
1255 case TOKEN_RAW: {
1256 blob_append(p->pOut, z, n);
@@ -1347,16 +1360,19 @@
1360 blob_appendf(p->pOut, "<pre name='code' class='%s'>",
1361 markup.aAttr[vAttrIdx].zValue);
1362 vAttrDidAppend=1;
1363 }
1364 }
1365 if( !vAttrDidAppend ) {
1366 endAutoParagraph(p);
1367 blob_append(p->pOut, "<pre class='verbatim'>",-1);
1368 }
1369 p->wantAutoParagraph = 0;
1370 }else
1371 if( markup.iType==MUTYPE_LI ){
1372 if( backupToType(p, MUTYPE_LIST)==0 ){
1373 endAutoParagraph(p);
1374 pushStack(p, MARKUP_UL);
1375 blob_append(p->pOut, "<ul>", 4);
1376 }
1377 pushStack(p, MARKUP_LI);
1378 renderMarkup(p->pOut, &markup);
@@ -1384,12 +1400,22 @@
1400 pushStack(p, markup.iCode);
1401 }else
1402 {
1403 if( markup.iType==MUTYPE_FONT ){
1404 startAutoParagraph(p);
1405 }else if( markup.iType==MUTYPE_BLOCK || markup.iType==MUTYPE_LIST ){
1406 p->wantAutoParagraph = 0;
1407 }
1408 if( markup.iCode==MARKUP_HR
1409 || markup.iCode==MARKUP_H1
1410 || markup.iCode==MARKUP_H2
1411 || markup.iCode==MARKUP_H3
1412 || markup.iCode==MARKUP_H4
1413 || markup.iCode==MARKUP_H5
1414 || markup.iCode==MARKUP_P
1415 ){
1416 endAutoParagraph(p);
1417 }
1418 if( (markup.iType & MUTYPE_STACK )!=0 ){
1419 pushStack(p, markup.iCode);
1420 }
1421 renderMarkup(p->pOut, &markup);
1422

Keyboard Shortcuts

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