Index: src/attach.c ================================================================== --- src/attach.c +++ src/attach.c @@ -75,20 +75,20 @@ zFilename = &zFilename[i+1]; i = -1; } } if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){ - zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename); + zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename); }else{ - zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename); + zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename); } @ @ <p><a href="/attachview?%s(zUrlTail)">%h(zFilename)</a> - @ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br> + @ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br /> if( zComment ) while( isspace(zComment[0]) ) zComment++; if( zComment && zComment[0] ){ - @ %w(zComment)<br> + @ %w(zComment)<br /> } if( zPage==0 && zTkt==0 ){ if( zSrc==0 || zSrc[0]==0 ){ zSrc = "Deleted from"; }else { @@ -273,13 +273,13 @@ style_header("Add Attachment"); @ <h2>Add Attachment To %s(zTargetType)</h2> @ <form action="%s(g.zBaseURL)/attachadd" method="POST" @ enctype="multipart/form-data"> @ File to Attach: - @ <input type="file" name="f" size="60"><br> - @ Description:<br> - @ <textarea name="comment" cols=80 rows=5 wrap="virtual"></textarea><br> + @ <input type="file" name="f" size="60"><br /> + @ Description:<br /> + @ <textarea name="comment" cols=80 rows=5 wrap="virtual"></textarea><br /> if( zTkt ){ @ <input type="hidden" name="tkt" value="%h(zTkt)"> }else{ @ <input type="hidden" name="page" value="%h(zPage)"> } @@ -351,11 +351,11 @@ cgi_redirect(zFrom); } style_header("Delete Attachment"); @ <form action="%s(g.zBaseURL)/attachdelete" method="POST"> @ <p>Confirm that you want to delete the attachment named - @ "%h(zFile)" on %s(zTkt?"ticket":"wiki page") %h(zTarget):<br> + @ "%h(zFile)" on %s(zTkt?"ticket":"wiki page") %h(zTarget):<br /> if( zTkt ){ @ <input type="hidden" name="tkt" value="%h(zTkt)"> }else{ @ <input type="hidden" name="page" value="%h(zPage)"> } Index: src/branch.c ================================================================== --- src/branch.c +++ src/branch.c @@ -231,16 +231,19 @@ } login_anonymous_available(); compute_leaves(0, 1); style_sidebox_begin("Nomenclature:", "33%"); @ <ol> - @ <li> An <a href="brlist">open branch</a> is a branch that has one or + @ <li> An <div class="sideboxDescribed"><a href="brlist"> + @ open branch</a></div> is a branch that has one or @ more <a href="leaves">open leaves.</a> @ The presence of open leaves presumably means @ that the branch is still being extended with new check-ins.</li> - @ <li> A <a href="brlist?closed">closed branch</a> is a branch with only - @ <a href="leaves?closed">closed leaves</a>. + @ <li> A <div class="sideboxDescribed"><a href="brlist?closed"> + @ closed branch</a></div> is a branch with only + @ <div class="sideboxDescribed"><a href="leaves?closed"> + @ closed leaves</a></div>. @ Closed branches are fixed and do not change (unless they are first @ reopened)</li> @ </ol> style_sidebox_end(); @@ -284,13 +287,11 @@ } if( cnt ){ @ </ul> } db_finalize(&q); - @ </ul> - @ <br clear="both"> - @ <script> + @ <script type="text/JavaScript"> @ function xin(id){ @ } @ function xout(id){ @ } @ </script> @@ -341,14 +342,13 @@ " ORDER BY event.mtime DESC", timeline_query_for_www(), TAG_BRANCH ); www_print_timeline(&q, 0, brtimeline_extra); db_finalize(&q); - @ <br clear="both"> - @ <script> + @ <script type="text/JavaScript"> @ function xin(id){ @ } @ function xout(id){ @ } @ </script> style_footer(); } Index: src/browse.c ================================================================== --- src/browse.c +++ src/browse.c @@ -144,11 +144,11 @@ char zShort[20]; memcpy(zShort, zUuid, 10); zShort[10] = 0; @ <h2>Files of check-in [<a href="vinfo?name=%T(zUuid)">%s(zShort)</a>] @ %s(blob_str(&dirname))</h2> - zSubdirLink = mprintf("%s/dir?ci=%S&name=%T", g.zTop, zUuid, zPrefix); + zSubdirLink = mprintf("%s/dir?ci=%S&name=%T", g.zTop, zUuid, zPrefix); if( zD ){ style_submenu_element("Top", "Top", "%s/dir?ci=%S", g.zTop, zUuid); style_submenu_element("All", "All", "%s/dir?name=%t", g.zTop, zD); }else{ style_submenu_element("All", "All", "%s/dir", g.zBaseURL); @@ -157,13 +157,13 @@ @ <h2>The union of all files from all check-ins @ %s(blob_str(&dirname))</h2> zSubdirLink = mprintf("%s/dir?name=%T", g.zBaseURL, zPrefix); if( zD ){ style_submenu_element("Top", "Top", "%s/dir", g.zBaseURL); - style_submenu_element("Tip", "Tip", "%s/dir?name=%t&ci=tip", + style_submenu_element("Tip", "Tip", "%s/dir?name=%t&ci=tip", g.zBaseURL, zD); - style_submenu_element("Trunk", "Trunk", "%s/dir?name=%t&ci=trunk", + style_submenu_element("Trunk", "Trunk", "%s/dir?name=%t&ci=trunk", g.zBaseURL,zD); }else{ style_submenu_element("Tip", "Tip", "%s/dir?ci=tip", g.zBaseURL); style_submenu_element("Trunk", "Trunk", "%s/dir?ci=trunk", g.zBaseURL); } @@ -216,29 +216,30 @@ mxLen = db_int(12, "SELECT max(length(x)) FROM localfiles /*scan*/"); cnt = db_int(0, "SELECT count(*) FROM localfiles /*scan*/"); nCol = 4; nRow = (cnt+nCol-1)/nCol; db_prepare(&q, "SELECT x, u FROM localfiles ORDER BY x /*scan*/"); - @ <table border="0" width="100%%"><tr><td valign="top" width="25%%"> + @ <table class="browser"><tr><td class="browser"><ul class="browser"> i = 0; while( db_step(&q)==SQLITE_ROW ){ const char *zFN; if( i==nRow ){ - @ </td><td valign="top" width="25%%"> + @ </ul></td><td class="browser"><ul class="browser"> i = 0; } i++; zFN = db_column_text(&q, 0); if( zFN[0]=='/' ){ zFN++; @ <li><a href="%s(zSubdirLink)%T(zFN)">%h(zFN)/</a></li> }else if( zCI ){ const char *zUuid = db_column_text(&q, 1); - @ <li><a href="%s(g.zBaseURL)/artifact?name=%s(zUuid)">%h(zFN)</a> + @ <li><a href="%s(g.zBaseURL)/artifact?name=%s(zUuid)">%h(zFN)</a></li> }else{ - @ <li><a href="%s(g.zBaseURL)/finfo?name=%T(zPrefix)%T(zFN)">%h(zFN)</a> + @ <li><a href="%s(g.zBaseURL)/finfo?name=%T(zPrefix)%T(zFN)">%h(zFN) + @ </a></li> } } db_finalize(&q); - @ </td></tr></table> + @ </ul></td></tr></table> style_footer(); } Index: src/db.c ================================================================== --- src/db.c +++ src/db.c @@ -664,11 +664,11 @@ } #endif if( file_isdir(zHome)!=1 ){ fossil_fatal("invalid home directory: %s", zHome); } -#ifndef __MINGW32__ +#ifndef _WIN32 if( access(zHome, W_OK) ){ fossil_fatal("home directory %s must be writeable", zHome); } #endif g.zHome = mprintf("%/", zHome); Index: src/descendants.c ================================================================== --- src/descendants.c +++ src/descendants.c @@ -318,14 +318,17 @@ style_header("Leaves"); login_anonymous_available(); compute_leaves(0, showAll ? 0 : showClosed ? 2 : 1); style_sidebox_begin("Nomenclature:", "33%"); @ <ol> - @ <li> A <b>leaf</b> is a check-in with no descendants.</li> - @ <li> An <b>open leaf</b> is a leaf that does not have a "closed" tag + @ <li> A <div class="sideboxDescribed">leaf</div> + @ is a check-in with no descendants.</li> + @ <li> An <div class="sideboxDescribed">open leaf</div> + @ is a leaf that does not have a "closed" tag @ and is thus assumed to still be in use.</li> - @ <li> A <b>closed leaf</b> has a "closed" tag and is thus assumed to + @ <li> A <div class="sideboxDescribed">closed leaf</div> + @ has a "closed" tag and is thus assumed to @ be historical and no longer in active use.</li> @ </ol> style_sidebox_end(); if( showAll ){ @@ -341,14 +344,14 @@ " ORDER BY event.mtime DESC", timeline_query_for_www() ); www_print_timeline(&q, TIMELINE_LEAFONLY, leaves_extra); db_finalize(&q); - @ <br clear="both"> - @ <script> + @ <br /> + @ <script type="text/JavaScript"> @ function xin(id){ @ } @ function xout(id){ @ } @ </script> style_footer(); } Index: src/finfo.c ================================================================== --- src/finfo.c +++ src/finfo.c @@ -136,11 +136,11 @@ hyperlinked_path(zFilename, &title); @ <h2>%b(&title)</h2> blob_reset(&title); pGraph = graph_init(); @ <div id="canvas" style="position:relative;width:1px;height:1px;"></div> - @ <table cellspacing=0 border=0 cellpadding=0> + @ <table class="timelineTable"> while( db_step(&q)==SQLITE_ROW ){ const char *zDate = db_column_text(&q, 0); const char *zCom = db_column_text(&q, 1); const char *zUser = db_column_text(&q, 2); int fpid = db_column_int(&q, 3); @@ -157,22 +157,22 @@ if( zBr==0 ) zBr = "trunk"; gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr); if( memcmp(zDate, zPrevDate, 10) ){ sprintf(zPrevDate, "%.10s", zDate); @ <tr><td> - @ <div class="divider"><nobr>%s(zPrevDate)</nobr></div> + @ <div class="divider">%s(zPrevDate)</div> @ </td></tr> } memcpy(zTime, &zDate[11], 5); zTime[5] = 0; - @ <tr><td valign="top" align="right"> + @ <tr><td class="timelineTime"> @ <a href="%s(g.zTop)/timeline?c=%t(zDate)">%s(zTime)</a></td> - @ <td width="20" align="left" valign="top"><div id="m%d(gidx)"></div></td> + @ <td class="timelineGraph"><div id="m%d(gidx)"></div></td> if( zBgClr && zBgClr[0] ){ - @ <td valign="top" align="left" bgcolor="%h(zBgClr)"> + @ <td class="timelineTableCell" style="background-color: %h(zBgClr);"> }else{ - @ <td valign="top" align="left"> + @ <td class="timelineTableCell"> } sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid); sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin); if( zUuid ){ if( g.okHistory ){ @@ -187,27 +187,29 @@ hyperlink_to_uuid(zShortCkin); @ %h(zCom) (user: hyperlink_to_user(zUser, zDate, ""); @ branch: %h(zBr)) if( g.okHistory && zUuid ){ + const char *z = zFilename; if( fpid ){ @ <a href="%s(g.zTop)/fdiff?v1=%s(zPUuid)&v2=%s(zUuid)">[diff]</a> } - @ <a href="%s(g.zTop)/annotate?checkin=%S(zCkin)&filename=%h(zFilename)"> + @ <a href="%s(g.zTop)/annotate?checkin=%S(zCkin)&filename=%h(z)"> @ [annotate]</a> } - @ </td> + @ </td></tr> } db_finalize(&q); if( pGraph ){ graph_finish(pGraph, 1); if( pGraph->nErr ){ graph_free(pGraph); pGraph = 0; }else{ - @ <tr><td><td><div style="width:%d(pGraph->mxRail*20+30)px;"></div> + @ <tr><td></td><td><div style="width:%d(pGraph->mxRail*20+30)px;"></div> + @ </td></tr> } } @ </table> timeline_output_graph_javascript(pGraph); style_footer(); } Index: src/info.c ================================================================== --- src/info.c +++ src/info.c @@ -194,15 +194,15 @@ @ <div class="section">Tags And Properties</div> @ <ul> } @ <li> if( tagtype==0 ){ - @ <b><s>%h(zTagname)</s></b> cancelled + @ <span class="infoTagCancelled">%h(zTagname)</span> cancelled }else if( zValue ){ - @ <b>%h(zTagname)=%h(zValue)</b> + @ <span class="infoTag">%h(zTagname)=%h(zValue)</span> }else { - @ <b>%h(zTagname)</b> + @ <span class="infoTag">%h(zTagname)</span> } if( tagtype==2 ){ if( zOrigUuid && zOrigUuid[0] ){ @ inherited from hyperlink_to_uuid(zOrigUuid); @@ -222,10 +222,11 @@ } hyperlink_to_uuid(zSrcUuid); @ on hyperlink_to_date(zDate,0); } + @ </li> } db_finalize(&q); if( cnt ){ @ </ul> } @@ -276,18 +277,19 @@ @ <p>Modified <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> @ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a> @ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a> if( !showDiff ){ @ - @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)">[diff]</a> + @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)">[diff]</a> }else{ int rid1 = uuid_to_rid(zOld, 0); int rid2 = uuid_to_rid(zNew, 0); @ <blockquote><pre> append_diff(rid1, rid2); @ </pre></blockquote> } + @ </p> }else if( zOld ){ @ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> @ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a></p> }else{ @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> @@ -354,11 +356,11 @@ TAG_COMMENT, rid); zUser = db_column_text(&q, 2); zComment = db_column_text(&q, 3); zDate = db_column_text(&q,1); @ <div class="section">Overview</div> - @ <p><table class="label-value"> + @ <table class="label-value"> @ <tr><th>SHA1 Hash:</th><td>%s(zUuid) if( g.okSetup ){ @ (Record ID: %d(rid)) } @ </td></tr> @@ -397,13 +399,13 @@ db_finalize(&q); } if( g.okHistory ){ const char *zProjName = db_get("project-name", "unnamed"); @ <tr><th>Timelines:</th><td> - @ <a href="%s(g.zBaseURL)/timeline?p=%S(zUuid)">ancestors</a> - @ | <a href="%s(g.zBaseURL)/timeline?d=%S(zUuid)">descendants</a> - @ | <a href="%s(g.zBaseURL)/timeline?d=%S(zUuid)&p=%S(zUuid)">both</a> + @ <a href="%s(g.zBaseURL)/timeline?p=%S(zUuid)">ancestors</a> + @ | <a href="%s(g.zBaseURL)/timeline?d=%S(zUuid)">descendants</a> + @ | <a href="%s(g.zBaseURL)/timeline?d=%S(zUuid)&p=%S(zUuid)">both</a> db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag " " WHERE rid=%d AND tagtype>0 " " AND tag.tagid=tagxref.tagid " " AND +tag.tagname GLOB 'sym-*'", rid); while( db_step(&q)==SQLITE_ROW ){ @@ -424,11 +426,11 @@ @ | <a href="%s(g.zTop)/ci_edit?r=%S(zUuid)">edit</a> } @ </td> @ </tr> } - @ </table></p> + @ </table> }else{ style_header("Check-in Information"); login_anonymous_available(); } db_finalize(&q); @@ -616,11 +618,11 @@ } /* ** WEBPAGE: vdiff -** URL: /vdiff?from=UUID&to=UUID&detail=BOOLEAN +** URL: /vdiff?from=UUID&to=UUID&detail=BOOLEAN ** ** Show all differences between two checkins. */ void vdiff_page(void){ int ridFrom, ridTo; @@ -638,11 +640,11 @@ style_header("Check-in Differences"); @ <h2>Difference From:</h2><blockquote> checkin_description(ridFrom); @ </blockquote><h2>To:</h2><blockquote> checkin_description(ridTo); - @ </blockquote><hr><p> + @ </blockquote><hr /><p> iFrom = iTo = 0; while( iFrom<mFrom.nFile && iTo<mTo.nFile ){ int cmp; if( iFrom>=mFrom.nFile ){ @@ -880,18 +882,18 @@ v1 = name_to_rid_www("v1"); v2 = name_to_rid_www("v2"); if( v1==0 || v2==0 ) fossil_redirect_home(); style_header("Diff"); @ <h2>Differences From:</h2> - @ <blockquote> + @ <blockquote><p> object_description(v1, 1, 0); - @ </blockquote> + @ </p></blockquote> @ <h2>To:</h2> - @ <blockquote> + @ <blockquote><p> object_description(v2, 1, 0); - @ </blockquote> - @ <hr> + @ </p></blockquote> + @ <hr /> @ <blockquote><pre> content_get(v1, &c1); content_get(v2, &c2); blob_zero(&diff); text_diff(&c1, &c2, &diff, 4, 1); @@ -994,27 +996,27 @@ if( !g.okRead ){ login_needed(); return; } if( rid==0 ) fossil_redirect_home(); if( g.okAdmin ){ const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ - style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", + style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", g.zTop, zUuid); }else{ style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); } } style_header("Hex Artifact Content"); zUuid = db_text("?","SELECT uuid FROM blob WHERE rid=%d", rid); @ <h2>Artifact %s(zUuid):</h2> - @ <blockquote> + @ <blockquote><p> blob_zero(&downloadName); object_description(rid, 0, &downloadName); style_submenu_element("Download", "Download", "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid); - @ </blockquote> - @ <hr> + @ </p></blockquote> + @ <hr /> content_get(rid, &content); @ <blockquote><pre> hexdump(&content); @ </pre></blockquote> style_footer(); @@ -1076,21 +1078,21 @@ if( !g.okRead ){ login_needed(); return; } if( rid==0 ) fossil_redirect_home(); if( g.okAdmin ){ const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ - style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", + style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", g.zTop, zUuid); }else{ style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); } } style_header("Artifact Content"); zUuid = db_text("?", "SELECT uuid FROM blob WHERE rid=%d", rid); @ <h2>Artifact %s(zUuid)</h2> - @ <blockquote> + @ <blockquote><p> blob_zero(&downloadName); object_description(rid, 0, &downloadName); style_submenu_element("Download", "Download", "%s/raw/%T?name=%s", g.zTop, blob_str(&downloadName), zUuid); zMime = mimetype_from_name(blob_str(&downloadName)); @@ -1100,25 +1102,25 @@ style_submenu_element("Html", "Html", "%s/artifact?name=%s", g.zTop, zUuid); }else{ renderAsHtml = 1; style_submenu_element("Text", "Text", - "%s/artifact?name=%s&txt=1", g.zTop, zUuid); + "%s/artifact?name=%s&txt=1", g.zTop, zUuid); } }else if( strcmp(zMime, "application/x-fossil-wiki")==0 ){ if( P("txt") ){ style_submenu_element("Wiki", "Wiki", "%s/artifact?name=%s", g.zTop, zUuid); }else{ renderAsWiki = 1; style_submenu_element("Text", "Text", - "%s/artifact?name=%s&txt=1", g.zTop, zUuid); + "%s/artifact?name=%s&txt=1", g.zTop, zUuid); } } } - @ </blockquote> - @ <hr> + @ </p></blockquote> + @ <hr /> content_get(rid, &content); if( renderAsWiki ){ wiki_convert(&content, 0, 0); }else if( renderAsHtml ){ @ <div> @@ -1131,11 +1133,11 @@ @ <pre> @ %h(blob_str(&content)) @ </pre> style_submenu_element("Hex","Hex", "%s/hexdump?name=%s", g.zTop, zUuid); }else if( strncmp(zMime, "image/", 6)==0 ){ - @ <img src="%s(g.zBaseURL)/raw?name=%s(zUuid)&m=%s(zMime)"></img> + @ <img src="%s(g.zBaseURL)/raw?name=%s(zUuid)&m=%s(zMime)"></img> style_submenu_element("Hex","Hex", "%s/hexdump?name=%s", g.zTop, zUuid); }else{ @ <pre> hexdump(&content); @ </pre> @@ -1164,11 +1166,11 @@ rid = name_to_rid_www("name"); if( rid==0 ){ fossil_redirect_home(); } zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); if( g.okAdmin ){ if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ - style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", + style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", g.zTop, zUuid); }else{ style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", g.zTop, zUuid); } @@ -1442,11 +1444,11 @@ int nTag = 0; @ <b>Preview:</b> @ <blockquote> @ <table border=0> if( zNewColor && zNewColor[0] ){ - @ <tr><td bgcolor="%h(zNewColor)"> + @ <tr><td style="background-color: %h(zNewColor);"> }else{ @ <tr><td> } wiki_convert(&comment, 0, WIKI_INLINE); blob_zero(&suffix); @@ -1467,11 +1469,11 @@ db_finalize(&q); blob_appendf(&suffix, ")"); @ %s(blob_str(&suffix)) @ </td></tr></table> @ </blockquote> - @ <hr> + @ <hr /> blob_reset(&suffix); } @ <p>Make changes to attributes of check-in @ [<a href="ci?name=%s(zUuid)">%s(zUuid)</a>]:</p> @ <form action="%s(g.zBaseURL)/ci_edit" method="POST"> @@ -1505,11 +1507,11 @@ } @ Propagate color to descendants</input></td></tr> @ <tr> for(i=0; i<nColor; i++){ if( aColor[i].zColor[0] ){ - @ <td bgcolor="%h(aColor[i].zColor)"> + @ <td style="background-color: %h(aColor[i].zColor);"> }else{ @ <td> } if( strcmp(zNewColor, aColor[i].zColor)==0 ){ @ <input type="radio" name="clr" value="%h(aColor[i].zColor)" checked> @@ -1541,13 +1543,13 @@ int tagid = db_column_int(&q, 0); const char *zTagName = db_column_text(&q, 1); char zLabel[30]; sprintf(zLabel, "c%d", tagid); if( P(zLabel) ){ - @ <br><input type="checkbox" name="c%d(tagid)" checked> + @ <br /><input type="checkbox" name="c%d(tagid)" checked> }else{ - @ <br><input type="checkbox" name="c%d(tagid)"> + @ <br /><input type="checkbox" name="c%d(tagid)"> } if( strncmp(zTagName, "sym-", 4)==0 ){ @ Cancel tag <b>%h(&zTagName[4])</b> }else{ @ Cancel special tag <b>%h(zTagName)</b> Index: src/login.c ================================================================== --- src/login.c +++ src/login.c @@ -153,21 +153,21 @@ if( db_int(1, "SELECT 0 FROM user" " WHERE uid=%d AND (pw=%Q OR pw=%Q)", g.userUid, zPasswd, zSha1Pw) ){ sleep(1); zErrMsg = - @ <p><font color="red"> + @ <p><span class="loginError"> @ You entered an incorrect old password while attempting to change @ your password. Your password is unchanged. - @ </font></p> + @ </span></p> ; }else if( strcmp(zNew1,zNew2)!=0 ){ zErrMsg = - @ <p><font color="red"> + @ <p><span class="loginError"> @ The two copies of your new passwords do not match. @ Your password is unchanged. - @ </font></p> + @ </span></p> ; }else{ char *zNewPw = sha1_shared_secret(zNew1, g.zLogin); db_multi_exec( "UPDATE user SET pw=%Q WHERE uid=%d", zNewPw, g.userUid @@ -206,13 +206,13 @@ zUsername, zPasswd, zSha1Pw ); if( uid<=0 ){ sleep(1); zErrMsg = - @ <p><font color="red"> + @ <p><span class="loginError"> @ You entered an unknown user or an incorrect password. - @ </font></p> + @ </span></p> ; }else{ char *zCookie; const char *zCookieName = login_cookie_name(); const char *zExpire = db_get("cookie-expire","8766"); @@ -229,38 +229,38 @@ redirect_to_g(); } } style_header("Login/Logout"); @ %s(zErrMsg) - @ <form action="login" method="POST"> + @ <form action="login" method="post"> if( P("g") ){ - @ <input type="hidden" name="g" value="%h(P("g"))"> + @ <input type="hidden" name="g" value="%h(P("g"))" /> } - @ <table align="left" hspace="10"> + @ <table class="login_out"> @ <tr> - @ <td align="right">User ID:</td> + @ <td class="login_out_label">User ID:</td> if( anonFlag ){ - @ <td><input type="text" id="u" name="u" value="anonymous" size=30></td> + @ <td><input type="text" id="u" name="u" value="anonymous" size="30" /></td> }else{ - @ <td><input type="text" id="u" name="u" value="" size=30></td> + @ <td><input type="text" id="u" name="u" value="" size="30" /></td> } @ </tr> @ <tr> - @ <td align="right">Password:</td> - @ <td><input type="password" id="p" name="p" value="" size=30></td> + @ <td class="login_out_label">Password:</td> + @ <td><input type="password" id="p" name="p" value="" size="30" /></td> @ </tr> if( g.zLogin==0 ){ zAnonPw = db_text(0, "SELECT pw FROM user" " WHERE login='anonymous'" " AND cap!=''"); } @ <tr> @ <td></td> - @ <td><input type="submit" name="in" value="Login"></td> + @ <td><input type="submit" name="in" value="Login" /></td> @ </tr> @ </table> - @ <script>document.getElementById('u').focus()</script> + @ <script type="text/JavaScript">document.getElementById('u').focus()</script> if( g.zLogin==0 ){ @ <p>Enter }else{ @ <p>You are currently logged in as <b>%h(g.zLogin)</b></p> @ <p>To change your login to a different user, enter @@ -273,46 +273,46 @@ unsigned int uSeed = captcha_seed(); char const *zDecoded = captcha_decode(uSeed); int bAutoCaptcha = db_get_boolean("auto-captcha", 1); char *zCaptcha = captcha_render(zDecoded); - @ <input type="hidden" name="cs" value="%u(uSeed)"/> - @ <p>Visitors may enter <b>anonymous</b> as the user-ID with + @ <p><input type="hidden" name="cs" value="%u(uSeed)" /> + @ Visitors may enter <b>anonymous</b> as the user-ID with @ the 8-character hexadecimal password shown below:</p> - @ <center><table border="1" cellpadding="10"><tr><td><pre> + @ <div class="captcha"><table class="captcha"><tr><td><pre> @ %s(zCaptcha) @ </pre></td></tr></table> if( bAutoCaptcha ) { @ <input type="button" value="Fill out captcha" @ onclick="document.getElementById('u').value='anonymous'; - @ document.getElementById('p').value='%s(zDecoded)';"/> + @ document.getElementById('p').value='%s(zDecoded)';" /> } - @ </center> + @ </div> free(zCaptcha); } if( g.zLogin ){ - @ <br clear="both"><hr> + @ <hr /> @ <p>To log off the system (and delete your login cookie) - @ press the following button:<br> - @ <input type="submit" name="out" value="Logout"></p> + @ press the following button:<br /> + @ <input type="submit" name="out" value="Logout" /></p> } @ </form> if( g.okPassword ){ - @ <br clear="both"><hr> + @ <hr /> @ <p>To change your password, enter your old password and your @ new password twice below then press the "Change Password" @ button.</p> - @ <form action="login" method="POST"> + @ <form action="login" method="post"> @ <table> - @ <tr><td align="right">Old Password:</td> - @ <td><input type="password" name="p" size=30></td></tr> - @ <tr><td align="right">New Password:</td> - @ <td><input type="password" name="n1" size=30></td></tr> - @ <tr><td align="right">Repeat New Password:</td> - @ <td><input type="password" name="n2" size=30></td></tr> + @ <tr><td class="login_out_label">Old Password:</td> + @ <td><input type="password" name="p" size="30" /></td></tr> + @ <tr><td class="login_out_label">New Password:</td> + @ <td><input type="password" name="n1" size="30" /></td></tr> + @ <tr><td class="login_out_label">Repeat New Password:</td> + @ <td><input type="password" name="n2" size="30" /></td></tr> @ <tr><td></td> - @ <td><input type="submit" value="Change Password"></td></tr> + @ <td><input type="submit" value="Change Password" /></td></tr> @ </table> @ </form> } style_footer(); } @@ -596,22 +596,22 @@ if( !g.okHistory && db_exists("SELECT 1 FROM user" " WHERE login='anonymous'" " AND cap LIKE '%%h%%'") ){ const char *zUrl = PD("REQUEST_URI", "index"); - @ <p>Many <font color="red">hyperlinks are disabled.</font><br /> - @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a> + @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br /> + @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a> @ to enable hyperlinks.</p> } } /* ** While rendering a form, call this routine to add the Anti-CSRF token ** as a hidden element of the form. */ void login_insert_csrf_secret(void){ - @ <input type="hidden" name="csrf" value="%s(g.zCsrfToken)"> + @ <input type="hidden" name="csrf" value="%s(g.zCsrfToken)" /> } /* ** Before using the results of a form, first call this routine to verify ** that ths Anti-CSRF token is present and is valid. If the Anti-CSRF token Index: src/report.c ================================================================== --- src/report.c +++ src/report.c @@ -277,13 +277,13 @@ zSQL = db_column_text(&q, 1); zOwner = db_column_text(&q, 2); zClrKey = db_column_text(&q, 3); @ <table cellpadding=0 cellspacing=0 border=0> @ <tr><td valign="top" align="right">Title:</td><td width=15></td> - @ <td colspan=3>%h(zTitle)</td></tr> + @ <td colspan="3">%h(zTitle)</td></tr> @ <tr><td valign="top" align="right">Owner:</td><td></td> - @ <td colspan=3>%h(zOwner)</td></tr> + @ <td colspan="3">%h(zOwner)</td></tr> @ <tr><td valign="top" align="right">SQL:</td><td></td> @ <td valign="top"><pre> @ %h(zSQL) @ </pre></td> @ <td width=15></td><td valign="top"> @@ -393,21 +393,21 @@ } } if( zOwner==0 ) zOwner = g.zLogin; style_submenu_element("Cancel", "Cancel", "reportlist"); if( rn>0 ){ - style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn); + style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn); } style_header(rn>0 ? "Edit Report Format":"Create New Report Format"); if( zErr ){ @ <blockquote><font color="#ff0000"><b>%h(zErr)</b></font></blockquote> } @ <form action="rptedit" method="POST"> @ <input type="hidden" name="rn" value="%d(rn)"> - @ <p>Report Title:<br> + @ <p>Report Title:<br /> @ <input type="text" name="t" value="%h(zTitle)" size="60"></p> - @ <p>Enter a complete SQL query statement against the "TICKET" table:<br> + @ <p>Enter a complete SQL query statement against the "TICKET" table:<br /> @ <textarea name="s" rows="20" cols="80">%h(zSQL)</textarea> @ </p> login_insert_csrf_secret(); if( g.okAdmin ){ @ <p>Report owner: @@ -417,11 +417,11 @@ @ <input type="hidden" name="w" value="%h(zOwner)"> } @ <p>Enter an optional color key in the following box. (If blank, no @ color key is displayed.) Each line contains the text for a single @ entry in the key. The first token of each line is the background - @ color for that line.<br> + @ color for that line.<br /> @ <textarea name="k" rows="8" cols="50">%h(zClrKey)</textarea> @ </p> if( !g.okAdmin && strcmp(zOwner,g.zLogin)!=0 ){ @ <p>This report format is owned by %h(zOwner). You are not allowed @ to change it.</p> @@ -448,11 +448,11 @@ zSchema = db_text(0,"SELECT sql FROM sqlite_master WHERE name='ticket'"); if( zSchema==0 ){ zSchema = db_text(0,"SELECT sql FROM repository.sqlite_master" " WHERE name='ticket'"); } - @ <hr><h3>TICKET Schema</h3> + @ <hr /><h3>TICKET Schema</h3> @ <blockquote><pre> @ %h(zSchema) @ </pre></blockquote> @ <h3>Notes</h3> @ <ul> @@ -829,14 +829,14 @@ while( isspace(*zSafeKey) ) zSafeKey++; for(i=0; zSafeKey[i] && !isspace(zSafeKey[i]); i++){} for(j=i; isspace(zSafeKey[j]); j++){} for(k=j; zSafeKey[k] && zSafeKey[k]!='\n' && zSafeKey[k]!='\r'; k++){} if( !horiz ){ - cgi_printf("<tr bgcolor=\"%.*s\"><td>%.*s</td></tr>\n", + cgi_printf("<tr style=\"background-color: %.*s;\"><td>%.*s</td></tr>\n", i, zSafeKey, k-j, &zSafeKey[j]); }else{ - cgi_printf("<td bgcolor=\"%.*s\">%.*s</td>\n", + cgi_printf("<td style=\"background-color: %.*s;\">%.*s</td>\n", i, zSafeKey, k-j, &zSafeKey[j]); } zSafeKey += k; } free(zToFree); @@ -907,11 +907,11 @@ if( !tabs ){ struct GenerateHTML sState; db_multi_exec("PRAGMA empty_result_callbacks=ON"); style_submenu_element("Raw", "Raw", - "rptview?tablist=1&%s", PD("QUERY_STRING","")); + "rptview?tablist=1&%s", PD("QUERY_STRING","")); if( g.okAdmin || (g.okTktFmt && g.zLogin && zOwner && strcmp(g.zLogin,zOwner)==0) ){ style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn); } if( g.okTktFmt ){ @@ -921,12 +921,12 @@ style_submenu_element("New Ticket", "Create a new ticket", "%s/tktnew", g.zTop); } style_header(zTitle); output_color_key(zClrKey, 1, - "border=0 cellpadding=3 cellspacing=0 class=\"report\""); - @ <table border=1 cellpadding=2 cellspacing=0 class="report"> + "border=\"0\" cellpadding=\"3\" cellspacing=\"0\" class=\"report\""); + @ <table border="1" cellpadding="2" cellspacing="0" class="report"> sState.rn = rn; sState.nCount = 0; sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)&zErr1); sqlite3_exec(g.db, zSql, generate_html, &sState, &zErr2); sqlite3_set_authorizer(g.db, 0, 0); Index: src/setup.c ================================================================== --- src/setup.c +++ src/setup.c @@ -99,42 +99,40 @@ return; } style_submenu_element("Add", "Add User", "setup_uedit"); style_header("User List"); - @ <table border="0" cellpadding="0" cellspacing="25"> - @ <tr><td valign="top"> - @ <b>Users:</b> - @ <table border="1" cellpadding="10"><tr><td> - @ <table cellspacing=0 cellpadding=0 border=0> + @ <table class="usetupLayoutTable"> + @ <tr><td class="usetupColumnLayout"> + @ <span class="note">Users:</span> + @ <table class="usetupUserList"> @ <tr> - @ <th align="right">User ID</th><td width="20"> </td> - @ <th>Capabilities</th><td width="15"> </td> - @ <th>Contact Info</th> + @ <th class="usetupListUser" style="text-align: right;padding-right: 20px;">User ID</th> + @ <th class="usetupListCap" style="text-align: center;padding-right: 15px;">Capabilities</th> + @ <th class="usetupListCon" style="text-align: left;">Contact Info</th> @ </tr> db_prepare(&s, "SELECT uid, login, cap, info FROM user ORDER BY login"); while( db_step(&s)==SQLITE_ROW ){ const char *zCap = db_column_text(&s, 2); if( strstr(zCap, "s") ) zCap = "s"; @ <tr> - @ <td align="right"> + @ <td class="usetupListUser" style="text-align: right;padding-right: 20px;white-space:nowrap;"> if( g.okAdmin && (zCap[0]!='s' || g.okSetup) ){ @ <a href="setup_uedit?id=%d(db_column_int(&s,0))"> } - @ <nobr>%h(db_column_text(&s,1))</nobr> + @ %h(db_column_text(&s,1)) if( g.okAdmin ){ @ </a> } - @ </td><td> </td> - @ <td align="center">%s(zCap)</td> - @ <td> </td> - @ <td align="left">%s(db_column_text(&s,3))</td> + @ </td> + @ <td class="usetupListCap" style="text-align: center;padding-right: 15px;">%s(zCap)</td> + @ <td class="usetupListCon" style="text-align: left;">%s(db_column_text(&s,3))</td> @ </tr> } - @ </table></td></tr></table> - @ <td valign="top"> - @ <b>Notes:</b> + @ </table> + @ </td><td class="usetupColumnLayout"> + @ <span class="note">Notes:</span> @ <ol> @ <li><p>The permission flags are as follows:</p> @ <table> @ <tr><td valign="top"><b>a</b></td> @ <td><i>Admin:</i> Create and delete users</td></tr> @@ -181,31 +179,35 @@ @ user <tt>developer</tt></td></tr> @ <tr><td valign="top"><b>w</b></td> @ <td><i>Write-Tkt:</i> Edit tickets</td></tr> @ <tr><td valign="top"><b>z</b></td> @ <td><i>Zip download:</i> Download a baseline via the - @ <tt>/zip</tt> URL even without check<b>o</b>ut - @ and <b>h</b>istory permissions</td></tr> + @ <tt>/zip</tt> URL even without + @ check<span class="capability">o</span>ut + @ and <span class="capability">h</span>istory permissions</td></tr> @ </table> @ </li> @ @ <li><p> - @ Every user, logged in or not, inherits the privileges of <b>nobody</b>. + @ Every user, logged in or not, inherits the privileges of + @ <span class="usertype">nobody</span>. @ </p></li> @ @ <li><p> - @ Any human can login as <b>anonymous</b> since the password is - @ clearly displayed on the login page for them to type. The purpose - @ of requiring anonymous to log in is to prevent access by spiders. + @ Any human can login as <span class="usertype">anonymous</span> since the + @ password is clearly displayed on the login page for them to type. The + @ purpose of requiring anonymous to log in is to prevent access by spiders. @ Every logged-in user inherits the combined privileges of - @ <b>anonymous</b> and - @ <b>nobody</b>. + @ <span class="usertype">anonymous</span> and + @ <span class="usertype">nobody</span>. @ </p></li> @ @ <li><p> - @ Users with privilege <b>v</b> inherit the combined privileges of - @ <b>developer</b>, <b>anonymous</b>, and <b>nobody</b>. + @ Users with privilege <span class="capability">v</span> inherit the combined + @ privileges of <span class="usertype">developer</span>, + @ <span class="usertype">anonymous</span>, and + @ <span class="usertype">nobody</span>. @ </p></li> @ @ </ol> @ </td></tr></table> style_footer(); @@ -323,12 +325,12 @@ } if( uid>0 && db_exists("SELECT 1 FROM user WHERE login=%Q AND uid!=%d", zLogin, uid) ){ style_header("User Creation Error"); - @ <font color="red">Login "%h(zLogin)" is already used by a different - @ user.</font> + @ <span class="loginError">Login "%h(zLogin)" is already used by + @ a different user.</span> @ @ <p><a href="setup_uedit?id=%d(uid)">[Bummer]</a></p> style_footer(); return; } @@ -353,65 +355,69 @@ if( uid ){ zLogin = db_text("", "SELECT login FROM user WHERE uid=%d", uid); zInfo = db_text("", "SELECT info FROM user WHERE uid=%d", uid); zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", uid); zPw = db_text("", "SELECT pw FROM user WHERE uid=%d", uid); - if( strchr(zCap, 'a') ) oaa = " checked"; - if( strchr(zCap, 'b') ) oab = " checked"; - if( strchr(zCap, 'c') ) oac = " checked"; - if( strchr(zCap, 'd') ) oad = " checked"; - if( strchr(zCap, 'e') ) oae = " checked"; - if( strchr(zCap, 'f') ) oaf = " checked"; - if( strchr(zCap, 'g') ) oag = " checked"; - if( strchr(zCap, 'h') ) oah = " checked"; - if( strchr(zCap, 'i') ) oai = " checked"; - if( strchr(zCap, 'j') ) oaj = " checked"; - if( strchr(zCap, 'k') ) oak = " checked"; - if( strchr(zCap, 'm') ) oam = " checked"; - if( strchr(zCap, 'n') ) oan = " checked"; - if( strchr(zCap, 'o') ) oao = " checked"; - if( strchr(zCap, 'p') ) oap = " checked"; - if( strchr(zCap, 'r') ) oar = " checked"; - if( strchr(zCap, 's') ) oas = " checked"; - if( strchr(zCap, 't') ) oat = " checked"; - if( strchr(zCap, 'u') ) oau = " checked"; - if( strchr(zCap, 'v') ) oav = " checked"; - if( strchr(zCap, 'w') ) oaw = " checked"; - if( strchr(zCap, 'z') ) oaz = " checked"; + if( strchr(zCap, 'a') ) oaa = " checked=\"checked\""; + if( strchr(zCap, 'b') ) oab = " checked=\"checked\""; + if( strchr(zCap, 'c') ) oac = " checked=\"checked\""; + if( strchr(zCap, 'd') ) oad = " checked=\"checked\""; + if( strchr(zCap, 'e') ) oae = " checked=\"checked\""; + if( strchr(zCap, 'f') ) oaf = " checked=\"checked\""; + if( strchr(zCap, 'g') ) oag = " checked=\"checked\""; + if( strchr(zCap, 'h') ) oah = " checked=\"checked\""; + if( strchr(zCap, 'i') ) oai = " checked=\"checked\""; + if( strchr(zCap, 'j') ) oaj = " checked=\"checked\""; + if( strchr(zCap, 'k') ) oak = " checked=\"checked\""; + if( strchr(zCap, 'm') ) oam = " checked=\"checked\""; + if( strchr(zCap, 'n') ) oan = " checked=\"checked\""; + if( strchr(zCap, 'o') ) oao = " checked=\"checked\""; + if( strchr(zCap, 'p') ) oap = " checked=\"checked\""; + if( strchr(zCap, 'r') ) oar = " checked=\"checked\""; + if( strchr(zCap, 's') ) oas = " checked=\"checked\""; + if( strchr(zCap, 't') ) oat = " checked=\"checked\""; + if( strchr(zCap, 'u') ) oau = " checked=\"checked\""; + if( strchr(zCap, 'v') ) oav = " checked=\"checked\""; + if( strchr(zCap, 'w') ) oaw = " checked=\"checked\""; + if( strchr(zCap, 'z') ) oaz = " checked=\"checked\""; } /* figure out inherited permissions */ memset(inherit, 0, sizeof(inherit)); if( strcmp(zLogin, "developer") ){ char *z1, *z2; z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='developer'"); while( z1 && *z1 ){ - inherit[0x7f & *(z1++)] = "<font color=\"red\">•</font>"; + inherit[0x7f & *(z1++)] = + "<span class=\"ueditInheritDeveloper\">•</span>"; } free(z2); } if( strcmp(zLogin, "reader") ){ char *z1, *z2; z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='reader'"); while( z1 && *z1 ){ - inherit[0x7f & *(z1++)] = "<font color=\"black\">•</font>"; + inherit[0x7f & *(z1++)] = + "<span class=\"ueditInheritReader\">•</span>"; } free(z2); } if( strcmp(zLogin, "anonymous") ){ char *z1, *z2; z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='anonymous'"); while( z1 && *z1 ){ - inherit[0x7f & *(z1++)] = "<font color=\"blue\">•</font>"; + inherit[0x7f & *(z1++)] = + "<span class=\"ueditInheritAnonymous\">•</span>"; } free(z2); } if( strcmp(zLogin, "nobody") ){ char *z1, *z2; z1 = z2 = db_text(0,"SELECT cap FROM user WHERE login='nobody'"); while( z1 && *z1 ){ - inherit[0x7f & *(z1++)] = "<font color=\"green\">•</font>"; + inherit[0x7f & *(z1++)] = + "<span class=\"ueditInheritNobody\">•</span>"; } free(z2); } /* Begin generating the page @@ -420,77 +426,79 @@ if( uid ){ style_header(mprintf("Edit User %h", zLogin)); }else{ style_header("Add A New User"); } - @ <table align="left" hspace="20" vspace="10"><tr><td> - @ <form action="%s(g.zPath)" method="POST"> + @ <div class="ueditCapBox"> + @ <form action="%s(g.zPath)" method="post"><div> login_insert_csrf_secret(); @ <table> @ <tr> - @ <td align="right"><nobr>User ID:</nobr></td> + @ <td class="usetupEditLabel">User ID:</td> if( uid ){ - @ <td>%d(uid) <input type="hidden" name="id" value="%d(uid)"></td> + @ <td>%d(uid) <input type="hidden" name="id" value="%d(uid)" /></td> }else{ - @ <td>(new user)<input type="hidden" name="id" value=0></td> + @ <td>(new user)<input type="hidden" name="id" value="0" /></td> } @ </tr> + @ <tr> + @ <td class="usetupEditLabel">Login:</td> + @ <td><input type="text" name="login" value="%h(zLogin)" /></td> + @ </tr> @ <tr> - @ <td align="right"><nobr>Login:</nobr></td> - @ <td><input type="text" name="login" value="%h(zLogin)"></td> + @ <td class="usetupEditLabel">Contact Info:</td> + @ <td><input type="text" name="info" size="40" value="%h(zInfo)" /></td> @ </tr> @ <tr> - @ <td align="right"><nobr>Contact Info:</nobr></td> - @ <td><input type="text" name="info" size=40 value="%h(zInfo)"></td> - @ </tr> - @ <tr> - @ <td align="right" valign="top">Capabilities:</td> + @ <td class="usetupEditLabel">Capabilities:</td> @ <td> #define B(x) inherit[x] if( g.okSetup ){ - @ <input type="checkbox" name="as"%s(oas)/>%s(B('s'))Setup<br> - } - @ <input type="checkbox" name="aa"%s(oaa)/>%s(B('a'))Admin<br> - @ <input type="checkbox" name="ad"%s(oad)/>%s(B('d'))Delete<br> - @ <input type="checkbox" name="ae"%s(oae)/>%s(B('e'))Email<br> - @ <input type="checkbox" name="ap"%s(oap)/>%s(B('p'))Password<br> - @ <input type="checkbox" name="ai"%s(oai)/>%s(B('i'))Check-In<br> - @ <input type="checkbox" name="ao"%s(oao)/>%s(B('o'))Check-Out<br> - @ <input type="checkbox" name="ah"%s(oah)/>%s(B('h'))History<br> - @ <input type="checkbox" name="au"%s(oau)/>%s(B('u'))Reader<br> - @ <input type="checkbox" name="av"%s(oav)/>%s(B('v'))Developer<br> - @ <input type="checkbox" name="ag"%s(oag)/>%s(B('g'))Clone<br> - @ <input type="checkbox" name="aj"%s(oaj)/>%s(B('j'))Read Wiki<br> - @ <input type="checkbox" name="af"%s(oaf)/>%s(B('f'))New Wiki<br> - @ <input type="checkbox" name="am"%s(oam)/>%s(B('m'))Append Wiki<br> - @ <input type="checkbox" name="ak"%s(oak)/>%s(B('k'))Write Wiki<br> - @ <input type="checkbox" name="ab"%s(oab)/>%s(B('b'))Attachments<br> - @ <input type="checkbox" name="ar"%s(oar)/>%s(B('r'))Read Ticket<br> - @ <input type="checkbox" name="an"%s(oan)/>%s(B('n'))New Ticket<br> - @ <input type="checkbox" name="ac"%s(oac)/>%s(B('c'))Append Ticket<br> - @ <input type="checkbox" name="aw"%s(oaw)/>%s(B('w'))Write Ticket<br> - @ <input type="checkbox" name="at"%s(oat)/>%s(B('t'))Ticket Report<br> - @ <input type="checkbox" name="az"%s(oaz)/>%s(B('z'))Download Zip + @ <input type="checkbox" name="as"%s(oas) />%s(B('s'))Setup<br /> + } + @ <input type="checkbox" name="aa"%s(oaa) />%s(B('a'))Admin<br /> + @ <input type="checkbox" name="ad"%s(oad) />%s(B('d'))Delete<br /> + @ <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br /> + @ <input type="checkbox" name="ap"%s(oap) />%s(B('p'))Password<br /> + @ <input type="checkbox" name="ai"%s(oai) />%s(B('i'))Check-In<br /> + @ <input type="checkbox" name="ao"%s(oao) />%s(B('o'))Check-Out<br /> + @ <input type="checkbox" name="ah"%s(oah) />%s(B('h'))History<br /> + @ <input type="checkbox" name="au"%s(oau) />%s(B('u'))Reader<br /> + @ <input type="checkbox" name="av"%s(oav) />%s(B('v'))Developer<br /> + @ <input type="checkbox" name="ag"%s(oag) />%s(B('g'))Clone<br /> + @ <input type="checkbox" name="aj"%s(oaj) />%s(B('j'))Read Wiki<br /> + @ <input type="checkbox" name="af"%s(oaf) />%s(B('f'))New Wiki<br /> + @ <input type="checkbox" name="am"%s(oam) />%s(B('m'))Append Wiki<br /> + @ <input type="checkbox" name="ak"%s(oak) />%s(B('k'))Write Wiki<br /> + @ <input type="checkbox" name="ab"%s(oab) />%s(B('b'))Attachments<br /> + @ <input type="checkbox" name="ar"%s(oar) />%s(B('r'))Read Ticket<br /> + @ <input type="checkbox" name="an"%s(oan) />%s(B('n'))New Ticket<br /> + @ <input type="checkbox" name="ac"%s(oac) />%s(B('c'))Append Ticket<br /> + @ <input type="checkbox" name="aw"%s(oaw) />%s(B('w'))Write Ticket<br /> + @ <input type="checkbox" name="at"%s(oat) />%s(B('t'))Ticket Report<br /> + @ <input type="checkbox" name="az"%s(oaz) />%s(B('z'))Download Zip @ </td> @ </tr> @ <tr> @ <td align="right">Password:</td> if( zPw[0] ){ /* Obscure the password for all users */ - @ <td><input type="password" name="pw" value="**********"></td> + @ <td><input type="password" name="pw" value="**********" /></td> }else{ /* Show an empty password as an empty input field */ - @ <td><input type="password" name="pw" value=""></td> + @ <td><input type="password" name="pw" value="" /></td> } @ </tr> if( !higherUser ){ @ <tr> - @ <td> </td> - @ <td><input type="submit" name="submit" value="Apply Changes"> + @ <td> </td> + @ <td><input type="submit" name="submit" value="Apply Changes" /></td> @ </tr> } - @ </table></td></tr></table> + @ </table> + @ </div></form> + @ </div> @ <h2>Privileges And Capabilities:</h2> @ <ul> if( higherUser ){ @ <li><p><font color="blue"><b> @ User %h(zLogin) has Setup privileges and you only have Admin privileges @@ -497,137 +505,160 @@ @ so you are not permitted to make changes to %h(zLogin). @ </b></font></p></li> @ } @ <li><p> - @ The <b>Setup</b> user can make arbitrary configuration changes. - @ An <b>Admin</b> user can add other users and change user privileges + @ The <span class="capability">Setup</span> user can make arbitrary + @ configuration changes. An <span class="usertype">Admin</span> user + @ can add other users and change user privileges @ and reset user passwords. Both automatically get all other privileges @ listed below. Use these two settings with discretion. @ </p></li> @ @ <li><p> - @ The "<font color="green"><big>•</big></font>" mark indicates - @ the privileges of "nobody" that are available to all users - @ regardless of whether or not they are logged in. + @ The "<span class="ueditInheritNobody"><big>•</big></span>" mark + @ indicates the privileges of <span class="usertype">nobody</span> that + @ are available to all users regardless of whether or not they are logged in. + @ </p></li> + @ + @ <li><p> + @ The "<span class="ueditInheritAnonymous"><big>•</big></span>" mark + @ indicates the privileges of <span class="usertype">anonymous</span> that + @ are inherited by all logged-in users. + @ </p></li> + @ + @ <li><p> + @ The "<span class="ueditInheritDeveloper"><big>•</big></span>" mark + @ indicates the privileges of <span class="usertype">developer</span> that + @ are inherited by all users with the + @ <span class="capability">Developer</span> privilege. + @ </p></li> + @ + @ <li><p> + @ The "<span class="ueditInheritReader"><big>•</big></span>" mark + @ indicates the privileges of <span class="usertype">reader</span> that + @ are inherited by all users with the <span class="capability">Reader</span> + @ privilege. + @ </p></li> + @ + @ <li><p> + @ The <span class="capability">Delete</span> privilege give the user the + @ ability to erase wiki, tickets, and attachments that have been added + @ by anonymous users. This capability is intended for deletion of spam. + @ The delete capability is only in effect for 24 hours after the item + @ is first posted. The <span class="usertype">Setup</span> user can + @ delete anything at any time. + @ </p></li> + @ + @ <li><p> + @ The <span class="capability">History</span> privilege allows a user + @ to see most hyperlinks. This is recommended ON for most logged-in users + @ but OFF for user "nobody" to avoid problems with spiders trying to walk + @ every historical version of every baseline and file. + @ </p></li> + @ + @ <li><p> + @ The <span class="capability">Zip</span> privilege allows a user to + @ see the "download as ZIP" + @ hyperlink and permits access to the <tt>/zip</tt> page. This allows + @ users to download ZIP archives without granting other rights like + @ <span class="capability">Read</span> or + @ <span class="capability">History</span>. This privilege is recommended for + @ user <span class="usertype">nobody</span> so that automatic package + @ downloaders can obtain the sources without going through the login + @ procedure. @ </p></li> @ @ <li><p> - @ The "<font color="blue"><big>•</big></font>" mark indicates - @ the privileges of "anonymous" that are inherited by all logged-in users. + @ The <span class="capability">Check-in</span> privilege allows remote + @ users to "push". The <span class="capability">Check-out</span> privilege + @ allows remote users to "pull". The <span class="capability">Clone</span> + @ privilege allows remote users to "clone". @ </p></li> @ @ <li><p> - @ The "<font color="red"><big>•</big></font>" mark indicates - @ the privileges of "developer" that are inherited by all users with - @ the <b>Developer</b> privilege. + @ The <span class="capability">Read Wiki</span>, + @ <span class="capability">New Wiki</span>, + @ <span class="capability">Append Wiki</span>, and + @ <b>Write Wiki</b> privileges control access to wiki pages. The + @ <span class="capability">Read Ticket</span>, + @ <span class="capability">New Ticket</span>, + @ <span class="capability">Append Ticket</span>, and + @ <span class="capability">Write Ticket</span> privileges control access + @ to trouble tickets. + @ The <span class="capability">Ticket Report</span> privilege allows + @ the user to create or edit ticket report formats. @ </p></li> @ @ <li><p> - @ The "<font color="black"><big>•</big></font>" mark indicates - @ the privileges of "reader" that are inherited by all users with - @ the <b>Reader</b> privilege. - @ </p></li> - @ - @ <li><p> - @ The <b>Delete</b> privilege give the user the ability to erase - @ wiki, tickets, and attachments that have been added by anonymous - @ users. This capability is intended for deletion of spam. The - @ delete capability is only in effect for 24 hours after the item - @ is first posted. The Setup user can delete anything at any time. + @ Users with the <span class="capability">Password</span> privilege + @ are allowed to change their own password. Recommended ON for most + @ users but OFF for special users <span class="usertype">developer</span>, + @ <span class="usertype">anonymous</span>, + @ and <span class="usertype">nobody</span>. @ </p></li> @ @ <li><p> - @ The <b>History</b> privilege allows a user to see most hyperlinks. - @ This is recommended ON for most logged-in users but OFF for - @ user "nobody" to avoid problems with spiders trying to walk every - @ historical version of every baseline and file. - @ </p></li> - @ - @ <li><p> - @ The <b>Zip</b> privilege allows a user to see the "download as ZIP" - @ hyperlink and permits access to the <tt>/zip</tt> page. This allows - @ users to download ZIP archives without granting other rights like - @ <b>Read</b> or <b>History</b>. This privilege is recommended for - @ user <b>nobody</b> so that automatic package downloaders can obtain - @ the sources without going through the login procedure. + @ The <span class="capability">EMail</span> privilege allows the display of + @ sensitive information such as the email address of users and contact + @ information on tickets. Recommended OFF for + @ <span class="usertype">anonymousy</span> and for + @ <span class="usertype">nobody</span> but ON for + @ <span class="usertype">developer</span>. @ </p></li> @ @ <li><p> - @ The <b>Check-in</b> privilege allows remote users to "push". - @ The <b>Check-out</b> privilege allows remote users to "pull". - @ The <b>Clone</b> privilege allows remote users to "clone". - @ </li><p> - @ - @ <li><p> - @ The <b>Read Wiki</b>, <b>New Wiki</b>, <b>Append Wiki</b>, and - @ <b>Write Wiki</b> privileges control access to wiki pages. The - @ <b>Read Ticket</b>, <b>New Ticket</b>, <b>Append Ticket</b>, and - @ <b>Write Ticket</b> privileges control access to trouble tickets. - @ The <b>Ticket Report</b> privilege allows the user to create or edit - @ ticket report formats. + @ The <span class="capability">Attachment</span> privilege is needed in + @ order to add attachments to tickets or wiki. Write privilege on the + @ ticket or wiki is also required. @ </p></li> @ - @ <li><p> - @ Users with the <b>Password</b> privilege are allowed to change their - @ own password. Recommended ON for most users but OFF for special - @ users "developer", "anonymous", and "nobody". - @ </p></li> - @ - @ <li><p> - @ The <b>EMail</b> privilege allows the display of sensitive information - @ such as the email address of users and contact information on tickets. - @ Recommended OFF for "anonymous" and for "nobody" but ON for - @ "developer". - @ </p></li> - @ - @ <li><p> - @ The <b>Attachment</b> privilege is needed in order to add attachments - @ to tickets or wiki. Write privilege on the ticket or wiki is also - @ required.</p></li> - @ @ <li><p> @ Login is prohibited if the password is an empty string. @ </p></li> @ </ul> @ @ <h2>Special Logins</h2> @ @ <ul> @ <li><p> - @ No login is required for user "<b>nobody</b>". The capabilities - @ of the <b>nobody</b> user are inherited by all users, regardless of - @ whether or not they are logged in. To disable universal access - @ to the repository, make sure no user named "<b>nobody</b>" exists or - @ that the <b>nobody</b> user has no capabilities enabled. - @ The password for <b>nobody</b> is ignore. To avoid problems with - @ spiders overloading the server, it is recommended - @ that the 'h' (History) capability be turned off for the <b>nobody</b> - @ user. + @ No login is required for user <span class="usertype">nobody</span>. The + @ capabilities of the <span class="usertype">nobody</span> user are + @ inherited by all users, regardless of whether or not they are logged in. + @ To disable universal access to the repository, make sure no user named + @ <span class="usertype">nobody</span> exists or that the + @ <span class="usertype">nobody</span> user has no capabilities + @ enabled. The password for <span class="usertype">nobody</span> is ignore. + @ To avoid problems with spiders overloading the server, it is recommended + @ that the <span class="capability">h</span> (History) capability be turned + @ off for the <span class="usertype">nobody</span> user. @ </p></li> @ @ <li><p> - @ Login is required for user "<b>anonymous</b>" but the password - @ is displayed on the login screen beside the password entry box + @ Login is required for user <span class="usertype">anonymous</span> but the + @ password is displayed on the login screen beside the password entry box @ so anybody who can read should be able to login as anonymous. @ On the other hand, spiders and web-crawlers will typically not - @ be able to login. Set the capabilities of the anonymous user - @ to things that you want any human to be able to do, but not any + @ be able to login. Set the capabilities of the + @ <span class="usertype">anonymous</span> + @ user to things that you want any human to be able to do, but not any @ spider. Every other logged-in user inherits the privileges of - @ <b>anonymous</b>. + @ <span class="usertype">anonymous</span>. @ </p></li> @ @ <li><p> - @ The "<b>developer</b>" user is intended as a template for trusted users - @ with check-in privileges. When adding new trusted users, simply - @ select the <b>Developer</b> privilege to cause the new user to inherit - @ all privileges of the "developer" user. Similarly, the "<b>reader</b>" - @ user is a template for users who are allowed more access than anonymous, - @ but less than a developer. + @ The <span class="usertype">developer</span> user is intended as a template + @ for trusted users with check-in privileges. When adding new trusted users, + @ simply select the <span class="capability">developer</span> privilege to + @ cause the new user to inherit all privileges of the + @ <span class="usertype">developer</span> + @ user. Similarly, the <span class="usertype">reader</span> user is a + @ template for users who are allowed more access than + @ <span class="usertype">anonymous</span>, + @ but less than a <span class="usertype">developer</span>. @ </p></li> @ </ul> - @ </form> style_footer(); } /* @@ -651,13 +682,14 @@ db_set(zVar, iQ ? "1" : "0", 0); iVal = iQ; } } if( iVal ){ - @ <input type="checkbox" name="%s(zQParm)" checked><b>%s(zLabel)</b></input> + @ <input type="checkbox" name="%s(zQParm)" checked="checked" /> + @ <b>%s(zLabel)</b> }else{ - @ <input type="checkbox" name="%s(zQParm)"><b>%s(zLabel)</b></input> + @ <input type="checkbox" name="%s(zQParm)" /><b>%s(zLabel)</b> } } /* ** Generate an entry box for an attribute. @@ -674,11 +706,11 @@ if( zQ && strcmp(zQ,zVal)!=0 ){ login_verify_csrf_secret(); db_set(zVar, zQ, 0); zVal = zQ; } - @ <input type="text" name="%s(zQParm)" value="%h(zVal)" size="%d(width)"> + @ <input type="text" name="%s(zQParm)" value="%h(zVal)" size="%d(width)" /> @ <b>%s(zLabel)</b> } /* ** Generate a text box for an attribute. @@ -698,11 +730,12 @@ db_set(zVar, zQ, 0); z = zQ; } if( rows>0 && cols>0 ){ @ <textarea name="%s(zQP)" rows="%d(rows)" cols="%d(cols)">%h(z)</textarea> - @ <b>%s(zLabel)</b> + if (zLabel && *zLabel) + @ <span class="textareaLabel">%s(zLabel)</span> } } /* @@ -714,57 +747,57 @@ login_needed(); } style_header("Access Control Settings"); db_begin_transaction(); - @ <form action="%s(g.zBaseURL)/setup_access" method="POST"> + @ <form action="%s(g.zBaseURL)/setup_access" method="post"><div> login_insert_csrf_secret(); - @ <hr> + @ <hr /> onoff_attribute("Require password for local access", "localauth", "localauth", 0); @ <p>When enabled, the password sign-in is required for @ web access coming from 127.0.0.1. When disabled, web access @ from 127.0.0.1 is allows without any login - the user id is selected @ from the ~/.fossil database. Password login is always required @ for incoming web connections on internet addresses other than - @ 127.0.0.1.</p></li> + @ 127.0.0.1.</p> - @ <hr> + @ <hr /> onoff_attribute("Allow REMOTE_USER authentication", "remote_user_ok", "remote_user_ok", 0); @ <p>When enabled, if the REMOTE_USER environment variable is set to the @ login name of a valid user and no other login credentials are available, @ then the REMOTE_USER is accepted as an authenticated user. - @ </p></li> + @ </p> - @ <hr> + @ <hr /> entry_attribute("Login expiration time", 6, "cookie-expire", "cex", "8766"); @ <p>The number of hours for which a login is valid. This must be a @ positive number. The default is 8760 hours which is approximately equal @ to a year.</p> - @ <hr> + @ <hr /> entry_attribute("Download packet limit", 10, "max-download", "mxdwn", "5000000"); @ <p>Fossil tries to limit out-bound sync, clone, and pull packets @ to this many bytes, uncompressed. If the client requires more data @ than this, then the client will issue multiple HTTP requests. @ Values below 1 million are not recommended. 5 million is a @ reasonable number.</p> - @ <hr> + @ <hr /> onoff_attribute("Show javascript button to fill in CAPTCHA", "auto-captcha", "autocaptcha", 0); @ <p>When enabled, a button appears on the login screen for user @ "anonymous" that will automatically fill in the CAPTCHA password. @ This is less secure that forcing the user to do it manually, but is @ probably secure enough and it is certainly more convenient for @ anonymous users.</p> - @ <hr> - @ <p><input type="submit" name="submit" value="Apply Changes"></p> - @ </form> + @ <hr /> + @ <p><input type="submit" name="submit" value="Apply Changes" /></p> + @ </div></form> db_end_transaction(0); style_footer(); } /* @@ -776,42 +809,42 @@ login_needed(); } style_header("Timeline Display Preferences"); db_begin_transaction(); - @ <form action="%s(g.zBaseURL)/setup_timeline" method="POST"> + @ <form action="%s(g.zBaseURL)/setup_timeline" method="post"><div> login_insert_csrf_secret(); - @ <hr> + @ <hr /> onoff_attribute("Allow block-markup in timeline", "timeline-block-markup", "tbm", 0); @ <p>In timeline displays, check-in comments can be displayed with or @ without block markup (paragraphs, tables, etc.)</p> - @ <hr> + @ <hr /> onoff_attribute("Use Universal Coordinated Time (UTC)", "timeline-utc", "utc", 1); @ <p>Show times as UTC (also sometimes called Greenwich Mean Time (GMT) or @ Zulu) instead of in local time.</p> - @ <hr> + @ <hr /> onoff_attribute("Show version differences by default", "show-version-diffs", "vdiff", 0); @ <p>On the version-information pages linked from the timeline can either @ show complete diffs of all file changes, or can just list the names of @ the files that have changed. Users can get to either page by @ clicking. This setting selects the default.</p> - @ <hr> + @ <hr /> entry_attribute("Max timeline comment length", 6, "timeline-max-comment", "tmc", "0"); @ <p>The maximum length of a comment to be displayed in a timeline. @ "0" there is no length limit.</p> - @ <hr> - @ <p><input type="submit" name="submit" value="Apply Changes"></p> - @ </form> + @ <hr /> + @ <p><input type="submit" name="submit" value="Apply Changes" /></p> + @ </div></form> db_end_transaction(0); style_footer(); } /* @@ -823,11 +856,11 @@ login_needed(); } style_header("WWW Configuration"); db_begin_transaction(); - @ <form action="%s(g.zBaseURL)/setup_config" method="POST"> + @ <form action="%s(g.zBaseURL)/setup_config" method="post"><div> login_insert_csrf_secret(); @ <hr /> entry_attribute("Project Name", 60, "project-name", "pn", ""); @ <p>Give your project a name so visitors know what this site is about. @ The project name will also be used as the RSS feed title.</p> @@ -840,36 +873,37 @@ entry_attribute("Index Page", 60, "index-page", "idxpg", "/home"); @ <p>Enter the pathname of the page to display when the "Home" menu @ option is selected and when no pathname is @ specified in the URL. For example, if you visit the url:</p> @ - @ <blockquote>%h(g.zBaseURL)</blockquote> + @ <blockquote><p>%h(g.zBaseURL)</p></blockquote> @ @ <p>And you have specified an index page of "/home" the above will @ automatically redirect to:</p> @ - @ <blockquote>%h(g.zBaseURL)/home</blockquote> + @ <blockquote><p>%h(g.zBaseURL)/home</p></blockquote> @ @ <p>The default "/home" page displays a Wiki page with the same name @ as the Project Name specified above. Some sites prefer to redirect @ to a documentation page (ex: "/doc/tip/index.wiki") or to "/timeline".</p> @ <hr /> onoff_attribute("Use HTML as wiki markup language", "wiki-use-html", "wiki-use-html", 0); - @ <p>Use HTML as the wiki markup language. Wiki links will still be parsed but - @ all other wiki formatting will be ignored. This option is helpful if you have - @ chosen to use a rich HTML editor for wiki markup such as TinyMCE.</p> + @ <p>Use HTML as the wiki markup language. Wiki links will still be parsed + @ but all other wiki formatting will be ignored. This option is helpful + @ if you have chosen to use a rich HTML editor for wiki markup such as + @ TinyMCE.</p> @ <p><strong>CAUTION:</strong> when @ enabling, <i>all</i> HTML tags and attributes are accepted in the wiki. @ No sanitization is done. This means that it is very possible for malicious @ users to inject dangerous HTML, CSS and JavaScript code into your wiki.</p> @ <p>This should <strong>only</strong> be enabled when wiki editing is limited @ to trusted users. It should <strong>not</strong> be used on a publically @ editable wiki.</p> @ <hr /> - @ <p><input type="submit" name="submit" value="Apply Changes"></p> - @ </form> + @ <p><input type="submit" name="submit" value="Apply Changes" /></p> + @ </div></form> db_end_transaction(0); style_footer(); } /* @@ -892,30 +926,27 @@ if( P("submit")!=0 ){ db_end_transaction(0); cgi_redirect("setup_editcss"); } style_header("Edit CSS"); - @ <form action="%s(g.zBaseURL)/setup_editcss" method="POST"> + @ <form action="%s(g.zBaseURL)/setup_editcss" method="post"><div> login_insert_csrf_secret(); @ Edit the CSS below:<br /> textarea_attribute("", 40, 80, "css", "css", zDefaultCSS); @ <br /> - @ <input type="submit" name="submit" value="Apply Changes"> - @ <input type="submit" name="clear" value="Revert To Default"> - @ </form> - @ <p><b>Note:</b> Press your browser Reload button after modifying the - @ CSS in order to pull in the modified CSS file.</p> - @ <hr> + @ <input type="submit" name="submit" value="Apply Changes" /> + @ <input type="submit" name="clear" value="Revert To Default" /> + @ </div></form> + @ <p><span class="note">Note:</span> Press your browser Reload button after + @ modifying the CSS in order to pull in the modified CSS file.</p> + @ <hr /> @ The default CSS is shown below for reference. Other examples @ of CSS files can be seen on the <a href="setup_skin">skins page</a>. @ See also the <a href="setup_header">header</a> and @ <a href="setup_footer">footer</a> editing screens. @ <blockquote><pre> - @ %h(zDefaultCSS) - @ %h(zTableLabelValueCSS) - @ %h(zDivSidebox) - @ %h(zDivSideboxTitle) + cgi_append_default_css(); @ </pre></blockquote> style_footer(); db_end_transaction(0); } @@ -933,21 +964,21 @@ cgi_replace_parameter("header", zDefaultHeader); }else{ textarea_attribute(0, 0, 0, "header", "header", zDefaultHeader); } style_header("Edit Page Header"); - @ <form action="%s(g.zBaseURL)/setup_header" method="POST"> + @ <form action="%s(g.zBaseURL)/setup_header" method="post"><div> login_insert_csrf_secret(); @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to @ generate the beginning of every page through start of the main @ menu.</p> textarea_attribute("", 40, 80, "header", "header", zDefaultHeader); @ <br /> - @ <input type="submit" name="submit" value="Apply Changes"> - @ <input type="submit" name="clear" value="Revert To Default"> - @ </form> - @ <hr> + @ <input type="submit" name="submit" value="Apply Changes" /> + @ <input type="submit" name="clear" value="Revert To Default" /> + @ </div></form> + @ <hr /> @ The default header is shown below for reference. Other examples @ of headers can be seen on the <a href="setup_skin">skins page</a>. @ See also the <a href="setup_editcss">CSS</a> and @ <a href="setup_footer">footer</a> editing screeens. @ <blockquote><pre> @@ -971,20 +1002,20 @@ cgi_replace_parameter("footer", zDefaultFooter); }else{ textarea_attribute(0, 0, 0, "footer", "footer", zDefaultFooter); } style_header("Edit Page Footer"); - @ <form action="%s(g.zBaseURL)/setup_footer" method="POST"> + @ <form action="%s(g.zBaseURL)/setup_footer" method="post"><div> login_insert_csrf_secret(); @ <p>Edit HTML text with embedded TH1 (a TCL dialect) that will be used to @ generate the end of every page.</p> textarea_attribute("", 20, 80, "footer", "footer", zDefaultFooter); @ <br /> - @ <input type="submit" name="submit" value="Apply Changes"> - @ <input type="submit" name="clear" value="Revert To Default"> - @ </form> - @ <hr> + @ <input type="submit" name="submit" value="Apply Changes" /> + @ <input type="submit" name="clear" value="Revert To Default" /> + @ </div></form> + @ <hr /> @ The default footer is shown below for reference. Other examples @ of footers can be seen on the <a href="setup_skin">skins page</a>. @ See also the <a href="setup_editcss">CSS</a> and @ <a href="setup_header">header</a> editing screens. @ <blockquote><pre> @@ -1034,31 +1065,31 @@ cgi_redirect("setup_logo"); } style_header("Edit Project Logo"); @ <p>The current project logo has a MIME-Type of <b>%h(zMime)</b> and looks @ like this:</p> - @ <blockquote><img src="%s(g.zTop)/logo" alt="logo"></blockquote> + @ <blockquote><p><img src="%s(g.zTop)/logo" alt="logo" /></p></blockquote> @ @ <p>The logo is accessible to all users at this URL: @ <a href="%s(g.zBaseURL)/logo">%s(g.zBaseURL)/logo</a>. @ The logo may or may not appear on each @ page depending on the <a href="setup_editcss">CSS</a> and @ <a href="setup_header">header setup</a>.</p> @ - @ <form action="%s(g.zBaseURL)/setup_logo" method="POST" - @ enctype="multipart/form-data"> + @ <form action="%s(g.zBaseURL)/setup_logo" method="post" + @ enctype="multipart/form-data"><div> @ <p>To set a new logo image, select a file to use as the logo using @ the entry box below and then press the "Change Logo" button.</p> login_insert_csrf_secret(); @ Logo Image file: - @ <input type="file" name="im" size="60" accepts="image/*"><br> - @ <input type="submit" name="set" value="Change Logo"> - @ <input type="submit" name="clr" value="Revert To Default"> - @ </form> + @ <input type="file" name="im" size="60" accept="image/*" /><br /> + @ <input type="submit" name="set" value="Change Logo" /> + @ <input type="submit" name="clr" value="Revert To Default" /> + @ </div></form> @ - @ <p><b>Note:</b> Your browser has probably cached the logo image, so - @ you will probably need to press the Reload button on your browser after - @ changing the logo to provoke your browser to reload the new logo image. - @ </p> + @ <p><span class="note">Note:</span> Your browser has probably cached the + @ logo image, so you will probably need to press the Reload button on your + @ browser after changing the logo to provoke your browser to reload the new + @ logo image. </p> style_footer(); db_end_transaction(0); } Index: src/shun.c ================================================================== --- src/shun.c +++ src/shun.c @@ -112,63 +112,63 @@ @ or artifacts that by design or accident interfere with the processing @ of the repository. Do not shun artifacts merely to remove them from @ sight - set the "hidden" tag on such artifacts instead.</p> @ @ <blockquote> - @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> + @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><div> login_insert_csrf_secret(); - @ <input type="text" name="uuid" value="%h(PD("shun",""))" size="50"> - @ <input type="submit" name="add" value="Shun"> - @ </form> + @ <input type="text" name="uuid" value="%h(PD("shun",""))" size="50" /> + @ <input type="submit" name="add" value="Shun" /> + @ </div></form> @ </blockquote> @ @ <p>Enter the UUID of a previous shunned artifact to cause it to be @ accepted again in the repository. The artifact content is not @ restored because the content is unknown. The only change is that @ the formerly shunned artifact will be accepted on subsequent sync @ operations.</p> @ @ <blockquote> - @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> + @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><div> login_insert_csrf_secret(); - @ <input type="text" name="uuid" size="50"> - @ <input type="submit" name="sub" value="Accept"> - @ </form> + @ <input type="text" name="uuid" size="50" /> + @ <input type="submit" name="sub" value="Accept" /> + @ </div></form> @ </blockquote> @ @ <p>Press the Rebuild button below to rebuild the respository. The @ content of newly shunned artifacts is not purged until the repository @ is rebuilt. On larger repositories, the rebuild may take minute or @ two, so be patient after pressing the button.</p> @ @ <blockquote> - @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> + @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><div> login_insert_csrf_secret(); - @ <input type="submit" name="rebuild" value="Rebuild"> - @ </form> + @ <input type="submit" name="rebuild" value="Rebuild" /> + @ </div></form> @ </blockquote> @ - @ <hr><p>Shunned Artifacts:</p> - @ <blockquote> + @ <hr /><p>Shunned Artifacts:</p> + @ <blockquote><p> db_prepare(&q, "SELECT uuid, EXISTS(SELECT 1 FROM blob WHERE blob.uuid=shun.uuid)" " FROM shun ORDER BY uuid"); while( db_step(&q)==SQLITE_ROW ){ const char *zUuid = db_column_text(&q, 0); int stillExists = db_column_int(&q, 1); cnt++; if( stillExists ){ - @ <b><a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a></b><br> + @ <b><a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a></b><br /> }else{ - @ <b>%s(zUuid)</b><br> + @ <b>%s(zUuid)</b><br /> } } if( cnt==0 ){ @ <i>no artifacts are shunned on this server</i> } db_finalize(&q); - @ </blockquote> + @ </p></blockquote> style_footer(); } /* ** Remove from the BLOB table all artifacts that are in the SHUN table. @@ -229,14 +229,15 @@ @ @ <p>Click on the "rcvid" to show a list of specific artifacts received @ by a transaction. After identifying illicit artifacts, remove them @ using the "Shun" feature.</p> @ - @ <table cellpadding=0 cellspacing=0 border=0> - @ <tr><th>rcvid</th><th width=15> - @ <th>Date</th><th width=15><th>User</th> - @ <th width=15><th>IP Address</th></tr> + @ <table cellpadding="0" cellspacing="0" border="0"> + @ <tr><th style="padding-right: 15px;text-align: right;">rcvid</th> + @ <th style="padding-right: 15px;text-align: left;">Date</th> + @ <th style="padding-right: 15px;text-align: left;">User</th> + @ <th style="text-align: left;">IP Address</th></tr> cnt = 0; while( db_step(&q)==SQLITE_ROW ){ int rcvid = db_column_int(&q, 0); const char *zUser = db_column_text(&q, 1); const char *zDate = db_column_text(&q, 2); @@ -245,14 +246,14 @@ style_submenu_element("Older", "Older", "rcvfromlist?ofst=%d", ofst+30); }else{ cnt++; @ <tr> - @ <td><a href="rcvfrom?rcvid=%d(rcvid)">%d(rcvid)</a></td><td> - @ <td>%s(zDate)</td><td> - @ <td>%h(zUser)</td><td> - @ <td> %s(zIpAddr) </td> + @ <td style="padding-right: 15px;text-align: right;"><a href="rcvfrom?rcvid=%d(rcvid)">%d(rcvid)</a></td> + @ <td style="padding-right: 15px;text-align: left;">%s(zDate)</td> + @ <td style="padding-right: 15px;text-align: left;">%h(zUser)</td> + @ <td style="text-align: left;">%s(zIpAddr)</td> @ </tr> } } db_finalize(&q); @ </table> @@ -277,11 +278,11 @@ "SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr" " FROM rcvfrom LEFT JOIN user USING(uid)" " WHERE rcvid=%d", rcvid ); - @ <table cellspacing=15 cellpadding=0 border=0> + @ <table cellspacing="15" cellpadding="0" border="0"> @ <tr><td valign="top" align="right"><b>rcvid:</b></td> @ <td valign="top">%d(rcvid)</td></tr> if( db_step(&q)==SQLITE_ROW ){ const char *zUser = db_column_text(&q, 0); const char *zDate = db_column_text(&q, 1); @@ -302,10 +303,12 @@ while( db_step(&q)==SQLITE_ROW ){ int rid = db_column_int(&q, 0); const char *zUuid = db_column_text(&q, 1); int size = db_column_int(&q, 2); @ <a href="%s(g.zBaseURL)/info/%s(zUuid)">%s(zUuid)</a> - @ (rid: %d(rid), size: %d(size))<br> + @ (rid: %d(rid), size: %d(size))<br /> } @ </td></tr> @ </table> + db_finalize(&q); + style_footer(); } Index: src/skins.c ================================================================== --- src/skins.c +++ src/skins.c @@ -165,11 +165,11 @@ @ <body> @ <div class="header"> @ <div class="logo"> @ <img src="$baseurl/logo" alt="logo"> @ </div> -@ <div class="title"><small>$<project_name></small><br>$<title></div> +@ <div class="title"><small>$<project_name></small><br />$<title></div> @ <div class="status"><nobr><th1> @ if {[info exists login]} { @ puts "Logged in as $login" @ } else { @ puts "Not logged in" @@ -600,11 +600,11 @@ @ </head> @ <body> @ <div class="header"> @ <div class="logo"> @ <!-- <img src="$baseurl/logo" alt="logo"> --> -@ <br><nobr>$<project_name></nobr> +@ <br /><nobr>$<project_name></nobr> @ </div> @ <div class="title">$<title></div> @ <div class="status"><nobr><th1> @ if {[info exists login]} { @ puts "Logged in as $login" @@ -731,18 +731,18 @@ db_begin_transaction(); /* Process requests to delete a user-defined skin */ if( P("del1") && (zName = skinVarName(P("sn"), 1))!=0 ){ style_header("Confirm Custom Skin Delete"); - @ <form action="%s(g.zBaseURL)/setup_skin" method="POST"> + @ <form action="%s(g.zBaseURL)/setup_skin" method="post"><div> @ <p>Deletion of a custom skin is a permanent action that cannot @ be undone. Please confirm that this is what you want to do:</p> - @ <input type="hidden" name="sn" value="%h(P("sn"))"> - @ <input type="submit" name="del2" value="Confirm - Delete The Skin"> - @ <input type="submit" name="cancel" value="Cancel - Do Not Delete"> + @ <input type="hidden" name="sn" value="%h(P("sn"))" /> + @ <input type="submit" name="del2" value="Confirm - Delete The Skin" /> + @ <input type="submit" name="cancel" value="Cancel - Do Not Delete" /> login_insert_csrf_secret(); - @ </form> + @ </div></form> style_footer(); return; } if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){ db_multi_exec("DELETE FROM config WHERE name=%Q", zName); @@ -812,15 +812,15 @@ for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ z = aBuiltinSkin[i].zName; if( strcmp(aBuiltinSkin[i].zValue, zCurrent)==0 ){ @ <li><p>%h(z). <b>Currently In Use</b></p> }else{ - @ <li><form action="%s(g.zBaseURL)/setup_skin" method="POST"> + @ <li><form action="%s(g.zBaseURL)/setup_skin" method="post"><div> @ %h(z). - @ <input type="hidden" name="sn" value="%h(z)"> - @ <input type="submit" name="load" value="Use This Skin"> - @ </form></li> + @ <input type="hidden" name="sn" value="%h(z)" /> + @ <input type="submit" name="load" value="Use This Skin" /> + @ </div></form></li> } } db_prepare(&q, "SELECT substr(name, 6), value FROM config" " WHERE name GLOB 'skin:*'" Index: src/stat.c ================================================================== --- src/stat.c +++ src/stat.c @@ -28,15 +28,17 @@ ** Show statistics and global information about the repository. */ void stat_page(void){ i64 t; int n, m, fsize; + int szMax, szAvg; char zBuf[100]; + login_check_credentials(); if( !g.okRead ){ login_needed(); return; } style_header("Repository Statistics"); - @ <p><table class="label-value"> + @ <table class="label-value"> @ <tr><th>Repository Size:</th><td> fsize = file_size(g.zRepositoryName); @ %d(fsize) bytes @ </td></tr> @ <tr><th>Number Of Artifacts:</th><td> @@ -44,14 +46,21 @@ m = db_int(0, "SELECT count(*) FROM delta"); @ %d(n) (stored as %d(n-m) full text and %d(m) delta blobs) @ </td></tr> if( n>0 ){ int a, b; + Stmt q; @ <tr><th>Uncompressed Artifact Size:</th><td> - t = db_int64(0, "SELECT total(size) FROM blob WHERE size>0"); + db_prepare(&q, "SELECT total(size), avg(size), max(size)" + " FROM blob WHERE size>0"); + db_step(&q); + t = db_column_int64(&q, 0); + szAvg = db_column_int(&q, 1); + szMax = db_column_int(&q, 2); + db_finalize(&q); sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", t); - @ %d((int)(((double)t)/(double)n)) bytes average, %s(zBuf) bytes total + @ %d(szAvg) bytes average, %d(szMax) bytes max, %s(zBuf) bytes total @ </td></tr> @ <tr><th>Compression Ratio:</th><td> if( t/fsize < 5 ){ b = 10; fsize /= 10; @@ -82,10 +91,12 @@ @ </td></tr> @ <tr><th>Duration Of Project:</th><td> n = db_int(0, "SELECT julianday('now') - (SELECT min(mtime) FROM event)" " + 0.99"); @ %d(n) days + sqlite3_snprintf(sizeof(zBuf), zBuf, "%.2f", n/365.24); + @ or approximately %s(zBuf) years @ </td></tr> @ <tr><th>Project ID:</th><td> @ %h(db_get("project-code","")) @ </td></tr> @ <tr><th>Server ID:</th><td> @@ -94,19 +105,20 @@ @ <tr><th>Fossil Version:</th><td> @ %h(MANIFEST_DATE) %h(MANIFEST_VERSION) @ </td></tr> @ <tr><th>SQLite Version:</th><td> - @ %h(db_text(0, "SELECT substr(sqlite_source_id(),1,30)")) - @ (%h(SQLITE_VERSION)) + sqlite3_snprintf(sizeof(zBuf), zBuf, "%.19s [%.10s] (%s)", + SQLITE_SOURCE_ID, &SQLITE_SOURCE_ID[20], SQLITE_VERSION); + @ %s(zBuf) @ </td></tr> @ <tr><th>Database Stats:</th><td> @ %d(db_int(0, "PRAGMA %s.page_count", g.zRepoDb)) pages, @ %d(db_int(0, "PRAGMA %s.page_size", g.zRepoDb)) bytes/page, @ %d(db_int(0, "PRAGMA %s.freelist_count", g.zRepoDb)) free pages, @ %s(db_text(0, "PRAGMA %s.encoding", g.zRepoDb)), @ %s(db_text(0, "PRAGMA %s.journal_mode", g.zRepoDb)) mode @ </td></tr> - @ </table></p> + @ </table> style_footer(); } Index: src/style.c ================================================================== --- src/style.c +++ src/style.c @@ -139,20 +139,23 @@ } @ <div class="content"> cgi_destination(CGI_BODY); /* Put the footer at the bottom of the page. + ** the additional clear/both is needed to extend the content + ** part to the end of an optional sidebox. */ - @ </div><br clear="both"/> + @ <div style="clear: both;"></div> + @ </div> zFooter = db_get("footer", (char*)zDefaultFooter); if( g.thTrace ) Th_Trace("BEGIN_FOOTER<br />\n", -1); Th_Render(zFooter); if( g.thTrace ) Th_Trace("END_FOOTER<br />\n", -1); /* Render trace log if TH1 tracing is enabled. */ if( g.thTrace ){ - cgi_append_content("<font color=\"red\"><hr>\n", -1); + cgi_append_content("<font color=\"red\"><hr />\n", -1); cgi_append_content(blob_str(&g.thLog), blob_size(&g.thLog)); cgi_append_content("</font>\n", -1); } } @@ -179,27 +182,27 @@ const char zDefaultHeader[] = @ <html> @ <head> @ <title>$<project_name>: $<title></title> @ <link rel="alternate" type="application/rss+xml" title="RSS Feed" -@ href="$baseurl/timeline.rss"> +@ href="$baseurl/timeline.rss" /> @ <link rel="stylesheet" href="$baseurl/style.css?default" type="text/css" -@ media="screen"> +@ media="screen" /> @ </head> @ <body> @ <div class="header"> @ <div class="logo"> @ <img src="$baseurl/logo" alt="logo"> @ </div> -@ <div class="title"><small>$<project_name></small><br>$<title></div> -@ <div class="status"><nobr><th1> +@ <div class="title"><small>$<project_name></small><br />$<title></div> +@ <div class="status"><th1> @ if {[info exists login]} { @ puts "Logged in as $login" @ } else { @ puts "Not logged in" @ } -@ </th1></nobr></div> +@ </th1></div> @ </div> @ <div class="mainmenu"><th1> @ html "<a href='$baseurl$index_page'>Home</a> " @ if {[anycap jor]} { @ html "<a href='$baseurl/timeline'>Timeline</a> " @@ -274,11 +277,11 @@ @ font-weight: bold; @ text-align: center; @ padding: 0 0 0 1em; @ color: #558195; @ vertical-align: bottom; -@ width: 100%; +@ width: 100% ; @ } @ @ /* The login status message in the top right-hand corner */ @ div.status { @ display: table-cell; @@ -286,16 +289,17 @@ @ vertical-align: bottom; @ color: #558195; @ font-size: 0.8em; @ font-weight: bold; @ min-width: 200px; +@ white-space: nowrap; @ } @ @ /* The header across the top of the page */ @ div.header { @ display: table; -@ width: 100%; +@ width: 100% ; @ } @ @ /* The main menu bar that appears at the top of the page beneath @ ** the header */ @ div.mainmenu { @@ -339,10 +343,11 @@ @ padding: 1px 1px 1px 1px; @ font-size: 1.2em; @ font-weight: bold; @ background-color: #558195; @ color: white; +@ white-space: nowrap; @ } @ @ /* The "Date" that occurs on the left hand side of timelines */ @ div.divider { @ background: #a1c4d4; @@ -368,83 +373,344 @@ @ div.footer a { color: white; } @ div.footer a:link { color: white; } @ div.footer a:visited { color: white; } @ div.footer a:hover { background-color: white; color: #558195; } @ -@ /* <verbatim> blocks */ +@ /* verbatim blocks */ @ pre.verbatim { @ background-color: #f5f5f5; @ padding: 0.5em; @} @ -; -const char zTableLabelValueCSS[] = @ /* The label/value pairs on (for example) the ci page */ @ table.label-value th { @ vertical-align: top; @ text-align: right; @ padding: 0.2ex 2ex; @ } -; -const char zDivSidebox[] = -@ /* The nomenclature sidebox for branches,.. */ -@ div.sidebox { -@ float: right; -@ border-width: medium; -@ border-style: double; -@ margin: 10; -@ } -; -const char zDivSideboxTitle[] = -@ /* The nomenclature title in sideboxes for branches,.. */ -@ div.sideboxTitle { -@ display: inline; -@ font-weight: bold; -@ } +@ ; -/* The following table holds the names of CSS elements and the CSS -** text that implements those elements. +/* The following table contains bits of default CSS that must +** be included if they are not found in the application-defined +** CSS. */ -static const struct { - const char *zElement; /* Name of the CSS element */ - const char *zText; /* Text of the element */ -} cssElements[] = { - { "table.label-value", zTableLabelValueCSS }, - { "div.sidebox", zDivSidebox }, - { "div.sideboxTitle", zDivSideboxTitle }, +const struct strctCssDefaults { + char const * const elementClass; /* Name of element needed */ + char const * const comment; /* Comment text */ + char const * const value; /* CSS text */ +} cssDefaultList[] = { + { "", + "", + zDefaultCSS + }, + { "div.sidebox", + "The nomenclature sidebox for branches,..", + @ float: right; + @ background-color: white; + @ border-width: medium; + @ border-style: double; + @ margin: 10; + }, + { "div.sideboxTitle", + "The nomenclature title in sideboxes for branches,..", + @ display: inline; + @ font-weight: bold; + }, + { "div.sideboxDescribed", + "The defined element in sideboxes for branches,..", + @ display: inline; + @ font-weight: bold; + }, + { "span.disabled", + "The defined element in sideboxes for branches,..", + @ color: red; + }, + { "span.timelineDisabled", + "The suppressed duplicates lines in timeline, ..", + @ font-style: italic; + @ font-size: small; + }, + { "table.timelineTable", + "the format for the timeline data table", + @ cellspacing: 0; + @ border: 0; + @ cellpadding: 0 + }, + { "td.timelineTableCell", + "the format for the timeline data cells", + @ valign: top; + @ align: left; + }, + { "span.timelineLeaf", + "the format for the timeline leaf marks", + @ font-weight: bold; + }, + { "a.timelineHistLink", + "the format for the timeline version links", + @ + }, + { "span.timelineHistDsp", + "the format for the timeline version display(no history permission!)", + @ font-weight: bold; + }, + { "td.timelineTime", + "the format for the timeline time display", + @ vertical-align: top; + @ text-align: right; + }, + { "td.timelineGraph", + "the format for the grap placeholder cells in timelines", + @ width: 20; + @ text-align: left; + @ vertical-align: top; + }, + { "a.tagLink", + "the format for the tag links", + @ + }, + { "span.tagDsp", + "the format for the tag display(no history permission!)", + @ font-weight: bold; + }, + { "span.wikiError", + "the format for wiki errors", + @ font-weight: bold; + @ color: red; + }, + { "span.infoTagCancelled", + "the format for fixed/canceled tags,..", + @ font-weight: bold; + @ text-decoration: line-through; + }, + { "span.infoTag", + "the format for tags,..", + @ font-weight: bold; + }, + { "span.wikiTagCancelled", + "the format for fixed/cancelled tags,.. on wiki pages", + @ text-decoration: line-through; + }, + { "table.browser", + "format for the file display table", + @ /* the format for wiki errors */ + @ width: 100% ; + @ border: 0; + }, + { "td.browser", + "format for cells in the file browser", + @ width: 24% ; + @ vertical-align: top; + }, + { "ul.browser", + "format for the list in the file browser", + @ margin-left: 0.5em; + @ padding-left: 0.5em; + }, + { "table.login_out", + "table format for login/out label/input table", + @ text-align: left; + @ margin-right: 10px; + @ margin-left: 10px; + @ margin-top: 10px; + }, + { "div.captcha", + "captcha display options", + @ text-align: center; + }, + { "table.captcha", + "format for the layout table, used for the captcha display", + @ margin: auto; + @ padding: 10px; + @ outline-width: 1; + @ outline-style: double; + }, + { "td.login_out_label", + "format for the label cells in the login/out table", + @ text-align: center; + }, + { "span.loginError", + "format for login error messages", + @ color: red; + }, + { "span.note", + "format for leading text for notes", + @ font-weight: bold; + }, + { "span.textareaLabel", + "format for textare labels", + @ font-weight: bold; + }, + { "table.usetupLayoutTable", + "format for the user setup layout table", + @ outline-style: none; + @ padding: 0; + @ margin: 25px; + }, + { "td.usetupColumnLayout", + "format of the columns on the user setup list page", + @ vertical-align: top + }, + { "table.usetupUserList", + "format for the user list table on the user setup page", + @ outline-style: double; + @ outline-width: 1; + @ padding: 10px; + }, + { "th.usetupListUser", + "format for table header user in user list on user setup page", + @ text-align: right; + @ padding-right: 20px; + }, + { "th.usetupListCap", + "format for table header capabilities in user list on user setup page", + @ text-align: center; + @ padding-right: 15px; + }, + { "th.usetupListCon", + "format for table header contact info in user list on user setup page", + @ text-align: left; + }, + { "td.usetupListUser", + "format for table cell user in user list on user setup page", + @ text-align: right; + @ padding-right: 20px; + @ white-space:nowrap; + }, + { "td.usetupListCap", + "format for table cell capabilities in user list on user setup page", + @ text-align: center; + @ padding-right: 15px; + }, + { "td.usetupListCon", + "format for table cell contact info in user list on user setup page", + @ text-align: left + }, + { "div.ueditCapBox", + "layout definition for the capabilities box on the user edit detail page", + @ float: left; + @ margin-right: 20px; + @ margin-bottom: 20px; + }, + { "td.usetupEditLabel", + "format of the label cells in the detailed user edit page", + @ text-align: right; + @ vertical-align: top; + @ white-space: nowrap; + }, + { "span.ueditInheritNobody", + "color for capabilities, inherited by nobody", + @ color: green; + }, + { "span.ueditInheritDeveloper", + "color for capabilities, inherited by developer", + @ color: red; + }, + { "span.ueditInheritReader", + "color for capabilities, inherited by reader", + @ color: black; + }, + { "span.ueditInheritAnonymous", + "color for capabilities, inherited by anonymous", + @ color: blue; + }, + { "span.capability", + "format for capabilites, mentioned on the user edit page", + @ font-weight: bold; + }, + { "span.usertype", + "format for different user types, mentioned on the user edit page", + @ font-weight: bold; + }, + { "span.usertype:before", + "leading text for user types, mentioned on the user edit page", + @ content:"'"; + }, + { "span.usertype:after", + "trailing text for user types, mentioned on the user edit page", + @ content:"'"; + }, + { "span.wikiruleHead", + "format for leading text in wikirules definitions", + @ font-weight: bold; + }, + { "td.tktDspLabel", + "format for labels on ticket display page", + @ text-align: right; + }, + { "td.tktDspValue", + "format for values on ticket display page", + @ text-align: left; + @ vertical-align: top; + @ background-color: #d0d0d0; + }, + { "span.tktError", + "format for ticket error messages", + @ color: red; + @ font-weight: bold; + }, + { 0, + 0, + 0 + } }; + +/* +** Append all of the default CSS to the CGI output. +*/ +void cgi_append_default_css(void) { + int i; + + for (i=0;cssDefaultList[i].elementClass;i++){ + if (cssDefaultList[i].elementClass[0]){ + cgi_printf("/* %s */\n%s {\n%s\n}\n\n", + cssDefaultList[i].comment, + cssDefaultList[i].elementClass, + cssDefaultList[i].value + ); + }else{ + cgi_printf("%s", + cssDefaultList[i].value + ); + } + } +} /* ** WEBPAGE: style.css */ void page_style_css(void){ - const char *zCSS; + const char *zCSS = 0; int i; cgi_set_content_type("text/css"); zCSS = db_get("css",(char*)zDefaultCSS); /* append user defined css */ cgi_append_content(zCSS, -1); /* add special missing definitions */ - for(i=0; i<count(cssElements); i++){ - if( strstr(cssElements[i].zElement, zCSS)==0 ){ - cgi_append_content(cssElements[i].zText, -1); + for (i=1;cssDefaultList[i].elementClass;i++) + if (!strstr(zCSS,cssDefaultList[i].elementClass)) { + cgi_append_content("/* ", -1); + cgi_append_content(cssDefaultList[i].comment, -1); + cgi_append_content(" */\n", -1); + cgi_append_content(cssDefaultList[i].elementClass, -1); + cgi_append_content(" {\n", -1); + cgi_append_content(cssDefaultList[i].value, -1); + cgi_append_content("}\n\n", -1); } - } g.isConst = 1; } /* ** WEBPAGE: test_env */ void page_test_env(void){ style_header("Environment Test"); #if !defined(_WIN32) - @ uid=%d(getuid()), gid=%d(getgid())<br> + @ uid=%d(getuid()), gid=%d(getgid())<br /> #endif - @ g.zBaseURL = %h(g.zBaseURL)<br> - @ g.zTop = %h(g.zTop)<br> + @ g.zBaseURL = %h(g.zBaseURL)<br /> + @ g.zTop = %h(g.zTop)<br /> cgi_print_all(); style_footer(); } Index: src/tag.c ================================================================== --- src/tag.c +++ src/tag.c @@ -514,13 +514,14 @@ ); @ <ul> while( db_step(&q)==SQLITE_ROW ){ const char *zName = db_column_text(&q, 0); if( g.okHistory ){ - @ <li><a href=%s(g.zBaseURL)/timeline?t=%T(zName)>%h(zName)</a></li> + @ <li><a class="tagLink" href="%s(g.zBaseURL)/timeline?t=%T(zName)"> + @ %h(zName)</a></li> }else{ - @ <li><strong>%h(zName)</strong></li> + @ <li><span class="tagDsp">%h(zName)</span></li> } } @ </ul> db_finalize(&q); style_footer(); @@ -542,13 +543,14 @@ rid ); while( db_step(&q)==SQLITE_ROW ){ const char *zTagName = db_column_text(&q, 0); if( g.okHistory ){ - @ <a href="%s(g.zBaseURL)/timeline?t=%T(zTagName)">[%h(zTagName)]</a> + @ <a class="tagLink" href="%s(g.zBaseURL)/timeline?t=%T(zTagName)"> + @ [%h(zTagName)]</a> }else{ - @ <b>[%h(zTagName)]</b> + @ <span class="tagDsp">[%h(zTagName)]</span> } } db_finalize(&q); } @@ -573,14 +575,14 @@ " ORDER BY event.mtime DESC", timeline_query_for_www() ); www_print_timeline(&q, 0, tagtimeline_extra); db_finalize(&q); - @ <br clear="both"> - @ <script> + @ <br /> + @ <script type="text/JavaScript"> @ function xin(id){ @ } @ function xout(id){ @ } @ </script> style_footer(); } Index: src/th_main.c ================================================================== --- src/th_main.c +++ src/th_main.c @@ -278,11 +278,12 @@ blob_reset(&name); for(i=0; i<nElem; i++){ zH = htmlize((char*)azElem[i], aszElem[i]); if( zValue && aszElem[i]==nValue && memcmp(zValue, azElem[i], nValue)==0 ){ - z = mprintf("<option value=\"%s\" selected>%s</option>", zH, zH); + z = mprintf("<option value=\"%s\" selected=\"selected\">%s</option>", + zH, zH); }else{ z = mprintf("<option value=\"%s\">%s</option>", zH, zH); } free(zH); sendText(z, -1, 0); Index: src/timeline.c ================================================================== --- src/timeline.c +++ src/timeline.c @@ -48,13 +48,14 @@ */ void hyperlink_to_uuid(const char *zUuid){ char zShortUuid[UUID_SIZE+1]; shorten_uuid(zShortUuid, zUuid); if( g.okHistory ){ - @ <a href="%s(g.zBaseURL)/info/%s(zShortUuid)">[%s(zShortUuid)]</a> + @ <a class="timelineHistLink" href="%s(g.zBaseURL)/info/%s(zShortUuid)"> + @ [%s(zShortUuid)]</a> }else{ - @ <b>[%s(zShortUuid)]</b> + @ <span class="timelineHistDsp">[%s(zShortUuid)]</span> } } /* ** Generate a hyperlink that invokes javascript to highlight @@ -83,11 +84,11 @@ void hyperlink_to_diff(const char *zV1, const char *zV2){ if( g.okHistory ){ if( zV2==0 ){ @ <a href="%s(g.zBaseURL)/diff?v2=%s(zV1)">[diff]</a> }else{ - @ <a href="%s(g.zBaseURL)/diff?v1=%s(zV1)&v2=%s(zV2)">[diff]</a> + @ <a href="%s(g.zBaseURL)/diff?v1=%s(zV1)&v2=%s(zV2)">[diff]</a> } } } /* @@ -109,11 +110,11 @@ */ void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){ if( zSuf==0 ) zSuf = ""; if( g.okHistory ){ if( zD && zD[0] ){ - @ <a href="%s(g.zTop)/timeline?c=%T(zD)&u=%T(zU)">%h(zU)</a>%s(zSuf) + @ <a href="%s(g.zTop)/timeline?c=%T(zD)&u=%T(zU)">%h(zU)</a>%s(zSuf) }else{ @ <a href="%s(g.zTop)/timeline?u=%T(zU)">%h(zU)</a>%s(zSuf) } }else{ @ %s(zU) @@ -189,14 +190,17 @@ }else{ wikiFlags = WIKI_INLINE | WIKI_NOBLOCK; } if( tmFlags & TIMELINE_GRAPH ){ pGraph = graph_init(); + /* style is not moved to css, because this is + ** a technical div for the timeline graph + */ @ <div id="canvas" style="position:relative;width:1px;height:1px;"></div> } - @ <table cellspacing=0 border=0 cellpadding=0> + @ <table class="timelineTable"> blob_zero(&comment); while( db_step(pQuery)==SQLITE_ROW ){ int rid = db_column_int(pQuery, 0); const char *zUuid = db_column_text(pQuery, 1); int isLeaf = db_column_int(pQuery, 5); @@ -218,30 +222,30 @@ } } } prevTagid = tagid; if( suppressCnt ){ - @ <tr><td><td><td> - @ <small><i>... %d(suppressCnt) similar - @ event%s(suppressCnt>1?"s":"") omitted.</i></small></tr> + @ <tr><td /><td /><td> + @ <span class="timelineDisabled">... %d(suppressCnt) similar + @ event%s(suppressCnt>1?"s":"") omitted.</span></td></tr> suppressCnt = 0; } if( strcmp(zType,"div")==0 ){ - @ <tr><td colspan=3><hr></td></tr> + @ <tr><td colspan="3"><hr /></td></tr> continue; } if( memcmp(zDate, zPrevDate, 10) ){ sprintf(zPrevDate, "%.10s", zDate); @ <tr><td> - @ <div class="divider"><nobr>%s(zPrevDate)</nobr></div> + @ <div class="divider">%s(zPrevDate)</div> @ </td></tr> } memcpy(zTime, &zDate[11], 5); zTime[5] = 0; @ <tr> - @ <td valign="top" align="right">%s(zTime)</td> - @ <td width="20" align="left" valign="top"> + @ <td class="timelineTime">%s(zTime)</td> + @ <td class="timelineGraph"> if( pGraph && zType[0]=='c' ){ int nParent = 0; int aParent[32]; const char *zBr; int gidx; @@ -267,24 +271,25 @@ } gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr); db_reset(&qbranch); @ <div id="m%d(gidx)"></div> } + @</td> if( zBgClr && zBgClr[0] ){ - @ <td valign="top" align="left" bgcolor="%h(zBgClr)"> + @ <td class="timelineTableCell" style="background-color: %h(zBgClr);"> }else{ - @ <td valign="top" align="left"> + @ <td class="timelineTableCell"> } if( zType[0]=='c' ){ hyperlink_to_uuid(zUuid); if( isLeaf ){ if( db_exists("SELECT 1 FROM tagxref" " WHERE rid=%d AND tagid=%d AND tagtype>0", rid, TAG_CLOSED) ){ - @ <b>Closed-Leaf:</b> + @ <span class="timelineLeaf">Closed-Leaf:</span> }else{ - @ <b>Leaf:</b> + @ <span class="timelineLeaf">Leaf:</span> } } }else if( (tmFlags & TIMELINE_ARTID)!=0 ){ hyperlink_to_uuid(zUuid); } @@ -309,23 +314,27 @@ xExtra(rid); } @ </td></tr> } if( suppressCnt ){ - @ <tr><td><td><td> - @ <small><i>... %d(suppressCnt) similar - @ event%s(suppressCnt>1?"s":"") omitted.</i></small></tr> + @ <tr><td /><td /><td> + @ <span class="timelineDisabled">... %d(suppressCnt) similar + @ event%s(suppressCnt>1?"s":"") omitted.</span></td></tr> suppressCnt = 0; } if( pGraph ){ graph_finish(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0); if( pGraph->nErr ){ graph_free(pGraph); pGraph = 0; }else{ - @ <tr><td><td> + /* style is not moved to css, because this is + ** a technical div for the timeline graph + */ + @ <tr><td /><td> @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div> + @ </td></tr> } } @ </table> timeline_output_graph_javascript(pGraph); } @@ -337,11 +346,11 @@ void timeline_output_graph_javascript(GraphContext *pGraph){ if( pGraph && pGraph->nErr==0 ){ GraphRow *pRow; int i; char cSep; - @ <script type="text/JavaScript"> + @ <script type="text/JavaScript"> cgi_printf("var rowinfo = [\n"); for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){ cgi_printf("{id:\"m%d\",bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,u:%d,au:", pRow->idx, pRow->zBgClr, @@ -883,15 +892,15 @@ }else if( zBrName ){ blob_appendf(&desc, " related to \"%h\"", zBrName); tmFlags |= TIMELINE_DISJOINT; } if( zAfter ){ - blob_appendf(&desc, " occurring on or after %h.<br>", zAfter); + blob_appendf(&desc, " occurring on or after %h.<br />", zAfter); }else if( zBefore ){ - blob_appendf(&desc, " occurring on or before %h.<br>", zBefore); + blob_appendf(&desc, " occurring on or before %h.<br />", zBefore); }else if( zCirca ){ - blob_appendf(&desc, " occurring around %h.<br>", zCirca); + blob_appendf(&desc, " occurring around %h.<br />", zCirca); } if( zSearch ){ blob_appendf(&desc, " matching \"%h\"", zSearch); } if( g.okHistory ){ Index: src/tkt.c ================================================================== --- src/tkt.c +++ src/tkt.c @@ -313,11 +313,11 @@ style_submenu_element("New Ticket", "Create a new ticket", "%s/tktnew", g.zTop); } if( g.okApndTkt && g.okAttach ){ style_submenu_element("Attach", "Add An Attachment", - "%s/attachadd?tkt=%T&from=%s/tktview/%t", + "%s/attachadd?tkt=%T&from=%s/tktview/%t", g.zTop, zUuid, g.zTop, zUuid); } style_header("View Ticket"); if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1); ticket_init(); @@ -342,24 +342,24 @@ while( db_step(&q)==SQLITE_ROW ){ const char *zDate = db_column_text(&q, 0); const char *zFile = db_column_text(&q, 1); const char *zUser = db_column_text(&q, 2); if( cnt==0 ){ - @ <hr><h2>Attachments:</h2> + @ <hr /><h2>Attachments:</h2> @ <ul> } cnt++; if( g.okRead && g.okHistory ){ - @ <li><a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&file=%t(zFile)"> + @ <li><a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&file=%t(zFile)"> @ %h(zFile)</a> }else{ @ %h(zFile) } @ added by %h(zUser) on hyperlink_to_date(zDate, "."); if( g.okWrTkt && g.okAttach ){ - @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&file=%t(zFile)&from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>] + @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&file=%t(zFile)&from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>] } } if( cnt ){ @ </ul> } @@ -511,12 +511,13 @@ if( g.thTrace ) Th_Trace("BEGIN_TKTNEW<br />\n", -1); ticket_init(); getAllTicketFields(); initializeVariablesFromDb(); initializeVariablesFromCGI(); - @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> + @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><p> login_insert_csrf_secret(); + @ </p> zScript = ticket_newpage_code(); Th_Store("login", g.zLogin); Th_Store("date", db_text(0, "SELECT datetime('now')")); Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zNewUuid, 0); @@ -554,34 +555,36 @@ cgi_redirectf("tktview?name=%T", zName); } style_header("Edit Ticket"); if( zName==0 || (nName = strlen(zName))<4 || nName>UUID_SIZE || !validate16(zName,nName) ){ - @ <font color="red"><b>Not a valid ticket id: \"%h(zName)\"</b></font> + @ <span class="tktError">Not a valid ticket id: \"%h(zName)\"</span> style_footer(); return; } nRec = db_int(0, "SELECT count(*) FROM ticket WHERE tkt_uuid GLOB '%q*'", zName); if( nRec==0 ){ - @ <font color="red"><b>No such ticket: \"%h(zName)\"</b></font> + @ <span class="tktError">No such ticket: \"%h(zName)\"</span> style_footer(); return; } if( nRec>1 ){ - @ <font color="red"><b>%d(nRec) tickets begin with: \"%h(zName)\"</b></font> + @ <span class="tktError"><b>%d(nRec) tickets begin with: + @ \"%h(zName)\"</span> style_footer(); return; } if( g.thTrace ) Th_Trace("BEGIN_TKTEDIT<br />\n", -1); ticket_init(); getAllTicketFields(); initializeVariablesFromCGI(); initializeVariablesFromDb(); - @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> - @ <input type="hidden" name="name" value="%s(zName)"> + @ <form method="post" action="%s(g.zBaseURL)/%s(g.zPath)"><p> + @ <input type="hidden" name="name" value="%s(zName)" /> login_insert_csrf_secret(); + @ </p> zScript = ticket_editpage_code(); Th_Store("login", g.zLogin); Th_Store("date", db_text(0, "SELECT datetime('now')")); Th_CreateCommand(g.interp, "append_field", appendRemarkCmd, 0, 0); Th_CreateCommand(g.interp, "submit_ticket", submitTicketCmd, (void*)&zName,0); @@ -624,11 +627,11 @@ return 0; } /* ** WEBPAGE: tkttimeline -** URL: /tkttimeline?name=TICKETUUID&y=TYPE +** URL: /tkttimeline?name=TICKETUUID&y=TYPE ** ** Show the change history for a single ticket in timeline format. */ void tkttimeline_page(void){ Stmt q; @@ -644,11 +647,11 @@ if( !g.okHistory || !g.okRdTkt ){ login_needed(); return; } zUuid = PD("name",""); zType = PD("y","a"); if( zType[0]!='c' ){ style_submenu_element("Check-ins", "Check-ins", - "%s/tkttimeline?name=%T&y=ci", g.zTop, zUuid); + "%s/tkttimeline?name=%T&y=ci", g.zTop, zUuid); }else{ style_submenu_element("Timeline", "Timeline", "%s/tkttimeline?name=%T", g.zTop, zUuid); } style_submenu_element("History", "History", @@ -776,12 +779,12 @@ @ <p>Ticket change @ [<a href="%s(g.zTop)/artifact/%T(zChngUuid)">%s(zShort)</a>] @ (rid %d(rid)) by hyperlink_to_user(m.zUser,zDate," on"); hyperlink_to_date(zDate, ":"); - ticket_output_change_artifact(&m); @ </p> + ticket_output_change_artifact(&m); } manifest_clear(&m); } } db_finalize(&q); Index: src/tktsetup.c ================================================================== --- src/tktsetup.c +++ src/tktsetup.c @@ -130,21 +130,21 @@ db_set(zDbField, z, 0); if( xRebuild ) xRebuild(); cgi_redirect("tktsetup"); } } - @ <form action="%s(g.zBaseURL)/%s(g.zPath)" method="POST"> + @ <form action="%s(g.zBaseURL)/%s(g.zPath)" method="post"><div> login_insert_csrf_secret(); @ <p>%s(zDesc)</p> @ <textarea name="x" rows="%d(height)" cols="80">%h(z)</textarea> - @ <blockquote> - @ <input type="submit" name="submit" value="Apply Changes"> - @ <input type="submit" name="clear" value="Revert To Default"> - @ <input type="submit" name="setup" value="Cancel"> - @ </blockquote> - @ </form> - @ <hr> + @ <blockquote><p> + @ <input type="submit" name="submit" value="Apply Changes" /> + @ <input type="submit" name="clear" value="Revert To Default" /> + @ <input type="submit" name="setup" value="Cancel" /> + @ </p></blockquote> + @ </div></form> + @ <hr /> @ <h2>Default %s(zTitle)</h2> @ <blockquote><pre> @ %h(zDfltValue) @ </pre></blockquote> style_footer(); @@ -153,13 +153,13 @@ /* ** WEBPAGE: tktsetup_tab */ void tktsetup_tab_page(void){ static const char zDesc[] = - @ <p>Enter a valid CREATE TABLE statement for the "ticket" table. The + @ Enter a valid CREATE TABLE statement for the "ticket" table. The @ table must contain columns named "tkt_id", "tkt_uuid", and "tkt_mtime" - @ with an unique index on "tkt_uuid" and "tkt_mtime".</p> + @ with an unique index on "tkt_uuid" and "tkt_mtime". ; tktsetup_generic( "Ticket Table Schema", "ticket-table", zDefaultTicketTable, @@ -229,12 +229,12 @@ /* ** WEBPAGE: tktsetup_com */ void tktsetup_com_page(void){ static const char zDesc[] = - @ <p>Enter TH1 script that initializes variables prior to generating - @ any of the ticket view, edit, or creation pages.</p> + @ Enter TH1 script that initializes variables prior to generating + @ any of the ticket view, edit, or creation pages. ; tktsetup_generic( "Ticket Common Script", "ticket-common", zDefaultTicketCommon, @@ -250,80 +250,80 @@ @ if {[info exists submit]} { @ set status Open @ submit_ticket @ } @ </th1> -@ <h1 align="center">Enter A New Ticket</h1> +@ <h1 style="text-align: center;">Enter A New Ticket</h1> @ <table cellpadding="5"> @ <tr> @ <td colspan="2"> -@ Enter a one-line summary of the ticket:<br> -@ <input type="text" name="title" size="60" value="$<title>"> +@ Enter a one-line summary of the ticket:<br /> +@ <input type="text" name="title" size="60" value="$<title>" /> @ </td> @ </tr> @ @ <tr> -@ <td align="right">Type: +@ <td style="text-align: center;">Type: @ <th1>combobox type $type_choices 1</th1> @ </td> @ <td>What type of ticket is this?</td> @ </tr> @ @ <tr> -@ <td align="right">Version: -@ <input type="text" name="foundin" size="20" value="$<foundin>"> +@ <td style="text-align: center;">Version: +@ <input type="text" name="foundin" size="20" value="$<foundin>" /> @ </td> @ <td>In what version or build number do you observe the problem?</td> @ </tr> @ @ <tr> -@ <td align="right">Severity: +@ <td style="text-align: center;">Severity: @ <th1>combobox severity $severity_choices 1</th1> @ </td> @ <td>How debilitating is the problem? How badly does the problem @ affect the operation of the product?</td> @ </tr> @ @ <tr> -@ <td align="right">EMail: -@ <input type="text" name="private_contact" value="$<private_contact>" size="30"> +@ <td style="text-align: center;">EMail: +@ <input type="text" name="private_contact" value="$<private_contact>" size="30" /> @ </td> -@ <td><u>Not publicly visible</u>. Used by developers to contact you with -@ questions.</td> +@ <td><span style="text-decoration: underline;">Not publicly visible</span>. +@ Used by developers to contact you with questions.</td> @ </tr> @ @ <tr> @ <td colspan="2"> @ Enter a detailed description of the problem. @ For code defects, be sure to provide details on exactly how @ the problem can be reproduced. Provide as much detail as @ possible. -@ <br> +@ <br /> @ <th1>set nline [linecount $comment 50 10]</th1> @ <textarea name="comment" cols="80" rows="$nline" -@ wrap="virtual" class="wikiedit">$<comment></textarea><br> -@ <input type="submit" name="preview" value="Preview"> +@ wrap="virtual" class="wikiedit">$<comment></textarea><br /> +@ <input type="submit" name="preview" value="Preview" /></td> @ </tr> @ @ <th1>enable_output [info exists preview]</th1> @ <tr><td colspan="2"> -@ Description Preview:<br><hr> +@ Description Preview:<br /><hr /> @ <th1>wiki $comment</th1> -@ <hr> +@ <hr /> @ </td></tr> @ <th1>enable_output 1</th1> @ @ <tr> -@ <td align="right"> -@ <input type="submit" name="submit" value="Submit"> +@ <td style="text-align: center;"> +@ <input type="submit" name="submit" value="Submit" /> @ </td> @ <td>After filling in the information above, press this button to create @ the new ticket</td> @ </tr> @ <tr> -@ <td align="right"> -@ <input type="submit" name="cancel" value="Cancel"> +@ <td style="text-align: center;"> +@ <input type="submit" name="cancel" value="Cancel" /> @ </td> @ <td>Abandon and forget this ticket</td> @ </tr> @ </table> ; @@ -338,12 +338,12 @@ /* ** WEBPAGE: tktsetup_newpage */ void tktsetup_newpage_page(void){ static const char zDesc[] = - @ <p>Enter HTML with embedded TH1 script that will render the "new ticket" - @ page</p> + @ Enter HTML with embedded TH1 script that will render the "new ticket" + @ page ; tktsetup_generic( "HTML For New Tickets", "ticket-newpage", zDefaultNew, @@ -354,51 +354,50 @@ ); } static const char zDefaultView[] = @ <table cellpadding="5"> -@ <tr><td align="right">Ticket UUID:</td><td bgcolor="#d0d0d0" colspan="3"> -@ $<tkt_uuid> -@ </td></tr> -@ <tr><td align="right">Title:</td> -@ <td bgcolor="#d0d0d0" colspan="3" valign="top"> +@ <tr><td class="tktDspLabel">Ticket UUID:</td> +@ <td class="tktDspValue" colspan="3">$<tkt_uuid></td></tr> +@ <tr><td class="tktDspLabel">Title:</td> +@ <td class="tktDspValue" colspan="3"> @ <th1>wiki $title</th1> @ </td></tr> -@ <tr><td align="right">Status:</td><td bgcolor="#d0d0d0"> +@ <tr><td class="tktDspLabel">Status:</td><td class="tktDspValue"> @ $<status> @ </td> -@ <td align="right">Type:</td><td bgcolor="#d0d0d0"> +@ <td class="tktDspLabel">Type:</td><td class="tktDspValue"> @ $<type> @ </td></tr> -@ <tr><td align="right">Severity:</td><td bgcolor="#d0d0d0"> +@ <tr><td class="tktDspLabel">Severity:</td><td class="tktDspValue"> @ $<severity> @ </td> -@ <td align="right">Priority:</td><td bgcolor="#d0d0d0"> +@ <td class="tktDspLabel">Priority:</td><td class="tktDspValue"> @ $<priority> @ </td></tr> -@ <tr><td align="right">Subsystem:</td><td bgcolor="#d0d0d0"> +@ <tr><td class="tktDspLabel">Subsystem:</td><td class="tktDspValue"> @ $<subsystem> @ </td> -@ <td align="right">Resolution:</td><td bgcolor="#d0d0d0"> +@ <td class="tktDspLabel">Resolution:</td><td class="tktDspValue"> @ $<resolution> @ </td></tr> -@ <tr><td align="right">Last Modified:</td><td bgcolor="#d0d0d0"> +@ <tr><td class="tktDspLabel">Last Modified:</td><td class="tktDspValue"> @ $<tkt_datetime> @ </td> @ <th1>enable_output [hascap e]</th1> -@ <td align="right">Contact:</td><td bgcolor="#d0d0d0"> +@ <td class="tktDspLabel">Contact:</td><td class="tktDspValue"> @ $<private_contact> @ </td> @ <th1>enable_output 1</th1> @ </tr> -@ <tr><td align="right">Version Found In:</td> -@ <td colspan="3" valign="top" bgcolor="#d0d0d0"> +@ <tr><td class="tktDspLabel">Version Found In:</td> +@ <td colspan="3" valign="top" class="tktDspValue"> @ $<foundin> @ </td></tr> @ <tr><td>Description & Comments:</td></tr> -@ <tr><td colspan="4" bgcolor="#d0d0d0"> -@ <span bgcolor="#d0d0d0"><th1>wiki $comment</th1></span> +@ <tr><td colspan="4" class="tktDspValue"> +@ <th1>wiki $comment</th1> @ </td></tr> @ </table> ; @@ -412,12 +411,11 @@ /* ** WEBPAGE: tktsetup_viewpage */ void tktsetup_viewpage_page(void){ static const char zDesc[] = - @ <p>Enter HTML with embedded TH1 script that will render the "view ticket" - @ page</p> + @ Enter HTML with embedded TH1 script that will render the "view ticket" page ; tktsetup_generic( "HTML For Viewing Tickets", "ticket-viewpage", zDefaultView, @@ -432,51 +430,51 @@ @ <th1> @ if {![info exists username]} {set username $login} @ if {[info exists submit]} { @ if {[info exists cmappnd]} { @ if {[string length $cmappnd]>0} { -@ set ctxt "\n\n<hr><i>[htmlize $login]" +@ set ctxt "\n\n<hr /><i>[htmlize $login]" @ if {$username ne $login} { @ set ctxt "$ctxt claiming to be [htmlize $username]" @ } -@ set ctxt "$ctxt added on [date]:</i><br>\n$cmappnd" +@ set ctxt "$ctxt added on [date]:</i><br />\n$cmappnd" @ append_field comment $ctxt @ } @ } @ submit_ticket @ } @ </th1> @ <table cellpadding="5"> -@ <tr><td align="right">Title:</td><td> -@ <input type="text" name="title" value="$<title>" size="60"> +@ <tr><td class="tktDspLabel">Title:</td><td> +@ <input type="text" name="title" value="$<title>" size="60" /> @ </td></tr> -@ <tr><td align="right">Status:</td><td> +@ <tr><td class="tktDspLabel">Status:</td><td> @ <th1>combobox status $status_choices 1</th1> @ </td></tr> -@ <tr><td align="right">Type:</td><td> +@ <tr><td class="tktDspLabel">Type:</td><td> @ <th1>combobox type $type_choices 1</th1> @ </td></tr> -@ <tr><td align="right">Severity:</td><td> +@ <tr><td class="tktDspLabel">Severity:</td><td> @ <th1>combobox severity $severity_choices 1</th1> @ </td></tr> -@ <tr><td align="right">Priority:</td><td> +@ <tr><td class="tktDspLabel">Priority:</td><td> @ <th1>combobox priority $priority_choices 1</th1> @ </td></tr> -@ <tr><td align="right">Resolution:</td><td> +@ <tr><td class="tktDspLabel">Resolution:</td><td> @ <th1>combobox resolution $resolution_choices 1</th1> @ </td></tr> -@ <tr><td align="right">Subsystem:</td><td> +@ <tr><td class="tktDspLabel">Subsystem:</td><td> @ <th1>combobox subsystem $subsystem_choices 1</th1> @ </td></tr> @ <th1>enable_output [hascap e]</th1> -@ <tr><td align="right">Contact:</td><td> +@ <tr><td class="tktDspLabel">Contact:</td><td> @ <input type="text" name="private_contact" size="40" -@ value="$<private_contact>"> +@ value="$<private_contact>" /> @ </td></tr> @ <th1>enable_output 1</th1> -@ <tr><td align="right">Version Found In:</td><td> -@ <input type="text" name="foundin" size="50" value="$<foundin>"> +@ <tr><td class="tktDspLabel">Version Found In:</td><td> +@ <input type="text" name="foundin" size="50" value="$<foundin>" /> @ </td></tr> @ <tr><td colspan="2"> @ <th1> @ if {![info exists eall]} {set eall 0} @ if {[info exists aonlybtn]} {set eall 0} @@ -484,45 +482,45 @@ @ if {![hascap w]} {set eall 0} @ if {![info exists cmappnd]} {set cmappnd {}} @ set nline [linecount $comment 15 10] @ enable_output $eall @ </th1> -@ Description And Comments:<br> +@ Description And Comments:<br /> @ <textarea name="comment" cols="80" rows="$nline" -@ wrap="virtual" class="wikiedit">$<comment></textarea><br> -@ <input type="hidden" name="eall" value="1"> -@ <input type="submit" name="aonlybtn" value="Append Remark"> -@ <input type="submit" name="preview1btn" value="Preview"> +@ wrap="virtual" class="wikiedit">$<comment></textarea><br /> +@ <input type="hidden" name="eall" value="1" /> +@ <input type="submit" name="aonlybtn" value="Append Remark" /> +@ <input type="submit" name="preview1btn" value="Preview" /> @ <th1>enable_output [expr {!$eall}]</th1> @ Append Remark from -@ <input type="text" name="username" value="$<username>" size="30">:<br> +@ <input type="text" name="username" value="$<username>" size="30" />:<br /> @ <textarea name="cmappnd" cols="80" rows="15" -@ wrap="virtual" class="wikiedit">$<cmappnd></textarea><br> +@ wrap="virtual" class="wikiedit">$<cmappnd></textarea><br /> @ <th1>enable_output [expr {[hascap w] && !$eall}]</th1> -@ <input type="submit" name="eallbtn" value="Edit All"> +@ <input type="submit" name="eallbtn" value="Edit All" /> @ <th1>enable_output [expr {!$eall}]</th1> -@ <input type="submit" name="preview2btn" value="Preview"> +@ <input type="submit" name="preview2btn" value="Preview" /> @ <th1>enable_output 1</th1> @ </td></tr> @ @ <th1>enable_output [info exists preview1btn]</th1> @ <tr><td colspan="2"> -@ Description Preview:<br><hr> +@ Description Preview:<br /><hr /> @ <th1>wiki $comment</th1> -@ <hr> +@ <hr /> @ </td></tr> @ <th1>enable_output [info exists preview2btn]</th1> @ <tr><td colspan="2"> -@ Description Preview:<br><hr> +@ Description Preview:<br /><hr /> @ <th1>wiki $cmappnd</th1> -@ <hr> +@ <hr /> @ </td></tr> @ <th1>enable_output 1</th1> @ @ <tr><td align="right"></td><td> -@ <input type="submit" name="submit" value="Submit Changes"> -@ <input type="submit" name="cancel" value="Cancel"> +@ <input type="submit" name="submit" value="Submit Changes" /> +@ <input type="submit" name="cancel" value="Cancel" /> @ </td></tr> @ </table> ; /* @@ -535,12 +533,11 @@ /* ** WEBPAGE: tktsetup_editpage */ void tktsetup_editpage_page(void){ static const char zDesc[] = - @ <p>Enter HTML with embedded TH1 script that will render the "edit ticket" - @ page</p> + @ Enter HTML with embedded TH1 script that will render the "edit ticket" page ; tktsetup_generic( "HTML For Editing Tickets", "ticket-editpage", zDefaultEdit, @@ -585,12 +582,11 @@ /* ** WEBPAGE: tktsetup_reportlist */ void tktsetup_reportlist(void){ static const char zDesc[] = - @ <p>Enter HTML with embedded TH1 script that will render the "report list" - @ page</p> + @ Enter HTML with embedded TH1 script that will render the "report list" page ; tktsetup_generic( "HTML For Report List", "ticket-reportlist", zDefaultReportList, @@ -633,13 +629,13 @@ /* ** WEBPAGE: tktsetup_rpttplt */ void tktsetup_rpttplt_page(void){ static const char zDesc[] = - @ <p>Enter the default ticket report format template. This is the + @ Enter the default ticket report format template. This is the @ the template report format that initially appears when creating a - @ new ticket summary report.</p> + @ new ticket summary report. ; tktsetup_generic( "Default Report Template", "ticket-report-template", zDefaultReport, @@ -674,13 +670,13 @@ /* ** WEBPAGE: tktsetup_keytplt */ void tktsetup_keytplt_page(void){ static const char zDesc[] = - @ <p>Enter the default ticket report color-key template. This is the + @ Enter the default ticket report color-key template. This is the @ the color-key that initially appears when creating a - @ new ticket summary report.</p> + @ new ticket summary report. ; tktsetup_generic( "Default Report Color-Key Template", "ticket-key-template", zDefaultKey, @@ -703,34 +699,34 @@ if( P("setup") ){ cgi_redirect("tktsetup"); } style_header("Ticket Display On Timelines"); db_begin_transaction(); - @ <form action="%s(g.zBaseURL)/tktsetup_timeline" method="POST"> + @ <form action="%s(g.zBaseURL)/tktsetup_timeline" method="post"><div> login_insert_csrf_secret(); - @ <hr> + @ <hr /> entry_attribute("Ticket Title", 40, "ticket-title-expr", "t", "title"); @ <p>An SQL expression in a query against the TICKET table that will @ return the title of the ticket for display purposes.</p> - @ <hr> + @ <hr /> entry_attribute("Ticket Status", 40, "ticket-status-column", "s", "status"); @ <p>The name of the column in the TICKET table that contains the ticket @ status in human-readable form. Case sensitive.</p> - @ <hr> + @ <hr /> entry_attribute("Ticket Closed", 40, "ticket-closed-expr", "c", "status='Closed'"); @ <p>An SQL expression that evaluates to true in a TICKET table query if @ the ticket is closed.</p> - @ <hr> + @ <hr /> @ <p> - @ <input type="submit" name="submit" value="Apply Changes"> - @ <input type="submit" name="setup" value="Cancel"> + @ <input type="submit" name="submit" value="Apply Changes" /> + @ <input type="submit" name="setup" value="Cancel" /> @ </p> - @ </form> + @ </div></form> db_end_transaction(0); style_footer(); } Index: src/translate.c ================================================================== --- src/translate.c +++ src/translate.c @@ -66,15 +66,16 @@ /* ** Translate the input stream into the output stream */ static void trans(FILE *in, FILE *out){ - int i, j, k; /* Loop counters */ - char c1, c2; /* Characters used to start a comment */ - int lastWasEq = 0; /* True if last non-whitespace character was "=" */ - char zLine[2000]; /* A single line of input */ - char zOut[4000]; /* The input line translated into appropriate output */ + int i, j, k; /* Loop counters */ + char c1, c2; /* Characters used to start a comment */ + int lastWasEq = 0; /* True if last non-whitespace character was "=" */ + int lastWasComma = 0; /* True if last non-whitespace character was "," */ + char zLine[2000]; /* A single line of input */ + char zOut[4000]; /* The input line translated into appropriate output */ c1 = c2 = '-'; while( fgets(zLine, sizeof(zLine), in) ){ for(i=0; zLine[i] && isspace(zLine[i]); i++){} if( zLine[i]!='@' ){ @@ -85,14 +86,16 @@ c1 = zLine[14]; c2 = zLine[15]; } i += strlen(&zLine[i]); while( i>0 && isspace(zLine[i-1]) ){ i--; } - lastWasEq = i>0 && zLine[i-1]=='='; - }else if( lastWasEq ){ + lastWasEq = i>0 && zLine[i-1]=='='; + lastWasComma = i>0 && zLine[i-1]==','; + }else if( lastWasEq || lastWasComma){ /* If the last non-whitespace character before the first @ was - ** an "=" then generate a string literal. But skip comments + ** an "="(var init/set) or a ","(const definition in list) then + ** generate a string literal. But skip comments ** consisting of all text between c1 and c2 (default "--") ** and end of line. */ int indent, omitline; i++; Index: src/update.c ================================================================== --- src/update.c +++ src/update.c @@ -111,10 +111,11 @@ tid = db_int(0, "SELECT rid FROM leaves, event" " WHERE event.objid=leaves.rid" " ORDER BY event.mtime DESC"); } + if( tid==vid ) return; /* Nothing to update */ db_begin_transaction(); vfile_check_signature(vid, 1); if( !nochangeFlag ) undo_begin(); load_vfile_from_rid(tid); Index: src/url.c ================================================================== --- src/url.c +++ src/url.c @@ -351,11 +351,11 @@ zName2 = 0; z = zValue2; if( z==0 ) continue; } blob_appendf(&p->url, "%s%s=%T", zSep, p->azName[i], z); - zSep = "&"; + zSep = "&"; } if( zName1 && zValue1 ){ blob_appendf(&p->url, "%s%s=%T", zSep, zName1, zValue1); } if( zName2 && zValue2 ){ Index: src/wiki.c ================================================================== --- src/wiki.c +++ src/wiki.c @@ -48,15 +48,15 @@ /* ** Output rules for well-formed wiki pages */ static void well_formed_wiki_name_rules(void){ @ <ul> - @ <li> Must not begin or end with a space. + @ <li> Must not begin or end with a space.</li> @ <li> Must not contain any control characters, including tab or - @ newline. - @ <li> Must not have two or more spaces in a row internally. - @ <li> Must be between 3 and 100 characters in length. + @ newline.</li> + @ <li> Must not have two or more spaces in a row internally.</li> + @ <li> Must be between 3 and 100 characters in length.</li> @ </ul> } /* ** Check a wiki name. If it is not well-formed, then issue an error @@ -63,12 +63,12 @@ ** and return true. If it is well-formed, return false. */ static int check_name(const char *z){ if( !wiki_name_is_wellformed((const unsigned char *)z) ){ style_header("Wiki Page Name Error"); - @ The wiki name "<b>%h(z)</b>" is not well-formed. Rules for - @ wiki page names: + @ The wiki name "<span class="wikiError">%h(z)</span>" is not well-formed. + @ Rules for wiki page names: well_formed_wiki_name_rules(); style_footer(); return 1; } return 0; @@ -155,14 +155,14 @@ if( g.okNewWiki ){ @ <li> Create a <a href="%s(g.zBaseURL)/wikinew">new wiki page</a>.</li> } @ <li> <a href="%s(g.zBaseURL)/wcontent">List of All Wiki Pages</a> @ available on this server.</li> - @ <li> <form method="GET" action="%s(g.zBaseURL)/wfind"> - @ Search wiki titles: <input type="text" name="title"/> - @ <input type="submit" /> - @ </li> + @ <li> <form method="get" action="%s(g.zBaseURL)/wfind"><div> + @ Search wiki titles: <input type="text" name="title"/> + @ <input type="submit" /></div></form> + @ </li> @ </ul> style_footer(); return; } if( check_name(zPageName) ) return; @@ -194,11 +194,11 @@ style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T", g.zTop, zPageName); } if( rid && g.okApndWiki && g.okAttach ){ style_submenu_element("Attach", "Add An Attachment", - "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T", + "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T", g.zTop, zPageName, g.zTop, zPageName); } if( rid && g.okApndWiki ){ style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T", g.zTop, zPageName); @@ -227,19 +227,20 @@ @ <hr><h2>Attachments:</h2> @ <ul> } cnt++; if( g.okHistory && g.okRead ){ - @ <li><a href="%s(g.zTop)/attachview?page=%s(zPageName)&file=%t(zFile)"> + @ <li> + @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&file=%t(zFile)"> @ %h(zFile)</a> }else{ @ <li>%h(zFile) } @ added by %h(zUser) on hyperlink_to_date(zDate, "."); if( g.okWrWiki && g.okAttach ){ - @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&file=%t(zFile)&from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>] + @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&file=%t(zFile)&from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>] } } if( cnt ){ @ </ul> } @@ -351,30 +352,30 @@ zHtmlPageName = mprintf("Edit: %s", zPageName); style_header(zHtmlPageName); if( P("preview")!=0 ){ blob_zero(&wiki); blob_append(&wiki, zBody, -1); - @ Preview:<hr> + @ Preview:<hr /> wiki_convert(&wiki, 0, 0); - @ <hr> + @ <hr /> blob_reset(&wiki); } for(n=2, z=zBody; z[0]; z++){ if( z[0]=='\n' ) n++; } if( n<20 ) n = 20; if( n>40 ) n = 40; - @ <form method="POST" action="%s(g.zBaseURL)/wikiedit"> + @ <form method="post" action="%s(g.zBaseURL)/wikiedit"><div> login_insert_csrf_secret(); - @ <input type="hidden" name="name" value="%h(zPageName)"> + @ <input type="hidden" name="name" value="%h(zPageName)" /> @ <textarea name="w" class="wikiedit" cols="80" @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea> - @ <br> - @ <input type="submit" name="preview" value="Preview Your Changes"> - @ <input type="submit" name="submit" value="Apply These Changes"> - @ <input type="submit" name="cancel" value="Cancel"> - @ </form> + @ <br /> + @ <input type="submit" name="preview" value="Preview Your Changes" /> + @ <input type="submit" name="submit" value="Apply These Changes" /> + @ <input type="submit" name="cancel" value="Cancel" /> + @ </div></form> if( !isSandbox ){ manifest_clear(&m); } style_footer(); } @@ -396,21 +397,20 @@ zName = PD("name",""); if( zName[0] && wiki_name_is_wellformed((const unsigned char *)zName) ){ cgi_redirectf("wikiedit?name=%T", zName); } style_header("Create A New Wiki Page"); - @ <p>Rules for wiki page names: + @ <p>Rules for wiki page names:</p> well_formed_wiki_name_rules(); - @ </p> - @ <form method="POST" action="%s(g.zBaseURL)/wikinew"> + @ <form method="post" action="%s(g.zBaseURL)/wikinew"> @ <p>Name of new wiki page: - @ <input type="text" width="35" name="name" value="%h(zName)"> - @ <input type="submit" value="Create"> + @ <input style="width: 35;" type="text" name="name" value="%h(zName)" /> + @ <input type="submit" value="Create" /> @ </p></form> if( zName[0] ){ - @ <p><b><font color="red"> - @ "%h(zName)" is not a valid wiki page name!</font></b></p> + @ <p><span class="wikiError"> + @ "%h(zName)" is not a valid wiki page name!</span></p> } style_footer(); } @@ -537,15 +537,15 @@ zUser = PD("u", g.zLogin); @ <form method="POST" action="%s(g.zBaseURL)/wikiappend"> login_insert_csrf_secret(); @ <input type="hidden" name="name" value="%h(zPageName)"> @ Your Name: - @ <input type="text" name="u" size="20" value="%h(zUser)"><br> - @ Comment to append:<br> + @ <input type="text" name="u" size="20" value="%h(zUser)"><br /> + @ Comment to append:<br /> @ <textarea name="r" class="wikiedit" cols="80" @ rows="10" wrap="virtual">%h(PD("r",""))</textarea> - @ <br> + @ <br /> @ <input type="submit" name="preview" value="Preview Your Comment"> @ <input type="submit" name="submit" value="Append Your Changes"> @ <input type="submit" name="cancel" value="Cancel"> @ </form> style_footer(); @@ -560,11 +560,11 @@ ** Function called to output extra text at the end of each line in ** a wiki history listing. */ static void wiki_history_extra(int rid){ if( db_exists("SELECT 1 FROM tagxref WHERE rid=%d", rid) ){ - @ <a href="%s(g.zTop)/wdiff?name=%t(zWikiPageName)&a=%d(rid)">[diff]</a> + @ <a href="%s(g.zTop)/wdiff?name=%t(zWikiPageName)&a=%d(rid)">[diff]</a> } } /* ** WEBPAGE: whistory @@ -740,39 +740,39 @@ @ </ol> @ <p>We call the first five rules above "wiki" formatting rules. The @ last two rules are the HTML formatting rule.</p> @ <h2>Formatting Rule Details</h2> @ <ol> - @ <li> <p><b>Paragraphs</b>. Any sequence of one or more blank lines forms + @ <li> <p><span class="wikiruleHead">Paragraphs</span>. Any sequence of one or more blank lines forms @ a paragraph break. Centered or right-justified paragraphs are not @ supported by wiki markup, but you can do these things if you need them - @ using HTML.</p> - @ <li> <p><b>Bullet Lists</b>. + @ using HTML.</p></li> + @ <li> <p><span class="wikiruleHead">Bullet Lists</span>. @ A bullet list item is a line that begins with a single "*" character @ surrounded on @ both sides by two or more spaces or by a tab. Only a single level - @ of bullet list is supported by wiki. For nested lists, use HTML.</p> - @ <li> <p><b>Enumeration Lists</b>. + @ of bullet list is supported by wiki. For nested lists, use HTML.</p></li> + @ <li> <p><span class="wikiruleHead">Enumeration Lists</span>. @ An enumeration list item is a line that begins with a single "#" character @ surrounded on both sides by two or more spaces or by a tab. Only a single @ level of enumeration list is supported by wiki. For nested lists or for - @ enumerations that count using letters or roman numerials, use HTML.</p> - @ <li> <p><b>Indented Paragraphs</b>. + @ enumerations that count using letters or roman numerials, use HTML.</p></li> + @ <li> <p><span class="wikiruleHead">Indented Paragraphs</span>. @ Any paragraph that begins with two or more spaces or a tab and @ which is not a bullet or enumeration list item is rendered @ indented. Only a single level of indentation is supported by wiki; use - @ HTML for deeper indentation.</p> - @ <li> <p><b>Hyperlinks</b>. + @ HTML for deeper indentation.</p></li> + @ <li> <p><span class="wikiruleHead">Hyperlinks</span>. @ Text within square brackets ("[...]") becomes a hyperlink. The @ target can be a wiki page name, the artifact ID of a check-in or ticket, @ the name of an image, or a URL. By default, the target is displayed @ as the text of the hyperlink. But you can specify alternative text @ after the target name separated by a "|" character.</p> @ <p>You can also link to internal anchor names using [#anchor-name], providing @ you have added the necessary "<a name="anchor-name"></a>" - @ tag to your wiki page.</p> - @ <li> <p><b>HTML</b>. + @ tag to your wiki page.</p></li> + @ <li> <p><span class="wikiruleHead">HTML</span>. @ The following standard HTML elements may be used: @ <a> @ <address> @ <b> @ <big> @@ -822,16 +822,16 @@ @ <verbatim> and <nowiki>. @ No other elements are allowed. All attributes are checked and @ only a few benign attributes are allowed on each element. @ In particular, any attributes that specify javascript or CSS @ are elided.</p></li> - @ <li><p><b>Special Markup.</b> + @ <li><p><span class="wikiruleHead">Special Markup.</span> @ The <nowiki> tag disables all wiki formatting rules @ through the matching </nowiki> element. @ The <verbatim> tag works like <pre> with the addition @ that it also disables all wiki and HTML markup - @ through the matching </verbatim>. + @ through the matching </verbatim>.</p></li> @ </ol> style_footer(); } /* Index: src/wikiformat.c ================================================================== --- src/wikiformat.c +++ src/wikiformat.c @@ -321,21 +321,21 @@ } /* ** Token types */ -#define TOKEN_MARKUP 1 /* <...> */ -#define TOKEN_CHARACTER 2 /* "&" or "<" not part of markup */ -#define TOKEN_LINK 3 /* [...] */ -#define TOKEN_PARAGRAPH 4 /* blank lines */ -#define TOKEN_NEWLINE 5 /* A single "\n" */ -#define TOKEN_BUL_LI 6 /* " * " */ -#define TOKEN_NUM_LI 7 /* " # " */ -#define TOKEN_ENUM 8 /* " \(?\d+[.)]? " */ -#define TOKEN_INDENT 9 /* " " */ -#define TOKEN_RAW 10 /* Output exactly (used when wiki-use-html==1) */ -#define TOKEN_TEXT 11 /* None of the above */ +#define TOKEN_MARKUP 1 /* <...> */ +#define TOKEN_CHARACTER 2 /* "&" or "<" not part of markup */ +#define TOKEN_LINK 3 /* [...] */ +#define TOKEN_PARAGRAPH 4 /* blank lines */ +#define TOKEN_NEWLINE 5 /* A single "\n" */ +#define TOKEN_BUL_LI 6 /* " * " */ +#define TOKEN_NUM_LI 7 /* " # " */ +#define TOKEN_ENUM 8 /* " \(?\d+[.)]? " */ +#define TOKEN_INDENT 9 /* " " */ +#define TOKEN_RAW 10 /* Output exactly (used when wiki-use-html==1) */ +#define TOKEN_TEXT 11 /* None of the above */ /* ** State flags */ #define AT_NEWLINE 0x001 /* At start of a line */ @@ -745,10 +745,13 @@ static void renderMarkup(Blob *pOut, ParsedMarkup *p){ int i; if( p->endTag ){ blob_appendf(pOut, "</%s>", aMarkup[p->iCode].zName); }else{ + /* Close active paragraph for several elements, which are not allowed + ** in paragraphs in XHTML. + */ blob_appendf(pOut, "<%s", aMarkup[p->iCode].zName); for(i=0; i<p->nAttr; i++){ blob_appendf(pOut, " %s", aAttribute[p->aAttr[i].iACode].zName); if( p->aAttr[i].zValue ){ const char *zVal = p->aAttr[i].zValue; @@ -756,10 +759,13 @@ blob_appendf(pOut, "=\"%s%s\"", g.zBaseURL, zVal); }else{ blob_appendf(pOut, "=\"%s\"", zVal); } } + } + if (p->iType & MUTYPE_SINGLE){ + blob_append(pOut, " /", 2); } blob_append(pOut, ">", 1); } } @@ -885,12 +891,13 @@ /* ** Begin a new paragraph if that something that is needed. */ static void startAutoParagraph(Renderer *p){ - if( p->wantAutoParagraph==0 || p->wikiList==MARKUP_OL || p->wikiList==MARKUP_UL ) return; - blob_appendf(p->pOut, "<p>", -1); + if( p->wantAutoParagraph==0 ) return; + if( p->wikiList==MARKUP_OL || p->wikiList==MARKUP_UL ) return; + blob_appendf(p->pOut, "<p type=\"auto\">", -1); pushStack(p, MARKUP_P); p->wantAutoParagraph = 0; p->inAutoParagraph = 1; } @@ -1019,17 +1026,18 @@ /* Special display processing for tickets. Display the hyperlink ** as crossed out if the ticket is closed. */ if( isClosed ){ if( g.okHistory ){ - blob_appendf(p->pOut,"<a href=\"%s/info/%s\"><s>", - g.zBaseURL, zTarget + blob_appendf(p->pOut, + "<a href=\"%s/info/%s\"><span class=\"wikiTagCancelled\">", + g.zBaseURL, zTarget ); - zTerm = "</s></a>"; + zTerm = "</span></a>"; }else{ - blob_appendf(p->pOut,"<s>"); - zTerm = "</s>"; + blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">"); + zTerm = "</span>"; } }else{ if( g.okHistory ){ blob_appendf(p->pOut,"<a href=\"%s/info/%s\">", g.zBaseURL, zTarget @@ -1133,10 +1141,11 @@ }else{ if( p->wikiList!=MARKUP_UL ){ if( p->wikiList ){ popStackToTag(p, p->wikiList); } + endAutoParagraph(p); pushStack(p, MARKUP_UL); blob_append(p->pOut, "<ul>", 4); p->wikiList = MARKUP_UL; } popStackToTag(p, MARKUP_LI); @@ -1152,10 +1161,11 @@ }else{ if( p->wikiList!=MARKUP_OL ){ if( p->wikiList ){ popStackToTag(p, p->wikiList); } + endAutoParagraph(p); pushStack(p, MARKUP_OL); blob_append(p->pOut, "<ol>", 4); p->wikiList = MARKUP_OL; } popStackToTag(p, MARKUP_LI); @@ -1171,10 +1181,11 @@ }else{ if( p->wikiList!=MARKUP_OL ){ if( p->wikiList ){ popStackToTag(p, p->wikiList); } + endAutoParagraph(p); pushStack(p, MARKUP_OL); blob_append(p->pOut, "<ol>", 4); p->wikiList = MARKUP_OL; } popStackToTag(p, MARKUP_LI); @@ -1233,11 +1244,13 @@ p->state = savedState; blob_append(p->pOut, zClose, -1); break; } case TOKEN_TEXT: { - startAutoParagraph(p); + int i; + for(i=0; i<n && isspace(z[i]); i++){} + if( i<n ) startAutoParagraph(p); blob_append(p->pOut, z, n); break; } case TOKEN_RAW: { blob_append(p->pOut, z, n); @@ -1347,16 +1360,19 @@ blob_appendf(p->pOut, "<pre name='code' class='%s'>", markup.aAttr[vAttrIdx].zValue); vAttrDidAppend=1; } } - if( !vAttrDidAppend ) + if( !vAttrDidAppend ) { + endAutoParagraph(p); blob_append(p->pOut, "<pre class='verbatim'>",-1); + } p->wantAutoParagraph = 0; }else if( markup.iType==MUTYPE_LI ){ if( backupToType(p, MUTYPE_LIST)==0 ){ + endAutoParagraph(p); pushStack(p, MARKUP_UL); blob_append(p->pOut, "<ul>", 4); } pushStack(p, MARKUP_LI); renderMarkup(p->pOut, &markup); @@ -1384,12 +1400,22 @@ pushStack(p, markup.iCode); }else { if( markup.iType==MUTYPE_FONT ){ startAutoParagraph(p); - }else if( markup.iType==MUTYPE_BLOCK ){ + }else if( markup.iType==MUTYPE_BLOCK || markup.iType==MUTYPE_LIST ){ p->wantAutoParagraph = 0; + } + if( markup.iCode==MARKUP_HR + || markup.iCode==MARKUP_H1 + || markup.iCode==MARKUP_H2 + || markup.iCode==MARKUP_H3 + || markup.iCode==MARKUP_H4 + || markup.iCode==MARKUP_H5 + || markup.iCode==MARKUP_P + ){ + endAutoParagraph(p); } if( (markup.iType & MUTYPE_STACK )!=0 ){ pushStack(p, markup.iCode); } renderMarkup(p->pOut, &markup);