Check-in [8ae52fc418]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
SHA1 Hash:8ae52fc4183f3100ce47ca69f1545e3425001f28
Date: 2012-04-28 07:15:25
User: drh
Edited Comment:Changes anchor tags (<a>) so that the href= attribute can be set by javascript rather than by HTML. This is to make it harder for spiders to follow the hyperlinks to every diff and annotation in the project history. It all seems to work, but it needs further testing and review before going live.
Original Comment:Changes anchor tags (<a&gt) so that the href= attribute can be set by javascript rather than by HTML. This is to make it harder for spiders to follow the hyperlinks to every diff and annotation in the project history. It all seems to work, but it needs further testing and review before going live.
Tags And Properties
Changes

Changes to src/branch.c

319 style_submenu_element("Color-Test", "Color-Test", "brlist?colortest"); 319 style_submenu_element("Color-Test", "Color-Test", "brlist?colortest"); 320 }else{ 320 }else{ 321 style_submenu_element("All", "All", "brlist?all"); 321 style_submenu_element("All", "All", "brlist?all"); 322 } 322 } 323 login_anonymous_available(); 323 login_anonymous_available(); 324 style_sidebox_begin("Nomenclature:", "33%"); 324 style_sidebox_begin("Nomenclature:", "33%"); 325 @ <ol> 325 @ <ol> 326 @ <li> An <div class="sideboxDescribed"><a href="brlist"> | 326 @ <li> An <div class="sideboxDescribed">%z(href("brlist")) 327 @ open branch</a></div> is a branch that has one or 327 @ open branch</a></div> is a branch that has one or 328 @ more <a href="leaves">open leaves.</a> | 328 @ more %z(href("leaves"))open leaves.</a> 329 @ The presence of open leaves presumably means 329 @ The presence of open leaves presumably means 330 @ that the branch is still being extended with new check-ins.</li> 330 @ that the branch is still being extended with new check-ins.</li> 331 @ <li> A <div class="sideboxDescribed"><a href="brlist?closed"> | 331 @ <li> A <div class="sideboxDescribed">%z(href("brlist?closed")) 332 @ closed branch</a></div> is a branch with only 332 @ closed branch</a></div> is a branch with only 333 @ <div class="sideboxDescribed"><a href="leaves?closed"> | 333 @ <div class="sideboxDescribed">%z(href("leaves?closed")) 334 @ closed leaves</a></div>. 334 @ closed leaves</a></div>. 335 @ Closed branches are fixed and do not change (unless they are first 335 @ Closed branches are fixed and do not change (unless they are first 336 @ reopened)</li> 336 @ reopened)</li> 337 @ </ol> 337 @ </ol> 338 style_sidebox_end(); 338 style_sidebox_end(); 339 339 340 branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0)); 340 branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0)); ................................................................................................................................................................................ 354 @ <ul> 354 @ <ul> 355 cnt++; 355 cnt++; 356 } 356 } 357 if( colorTest ){ 357 if( colorTest ){ 358 const char *zColor = hash_color(zBr); 358 const char *zColor = hash_color(zBr); 359 @ <li><span style="background-color: %s(zColor)"> 359 @ <li><span style="background-color: %s(zColor)"> 360 @ %h(zBr) &rarr; %s(zColor)</span></li> 360 @ %h(zBr) &rarr; %s(zColor)</span></li> 361 }else if( g.perm.History ){ < 362 @ <li><a href="%s(g.zTop)/timeline?r=%T(zBr)")>%h(zBr)</a></li> < 363 }else{ 361 }else{ 364 @ <li><b>%h(zBr)</b></li> < > 362 @ <li>%z(href("%R/timeline?r=%T",zBr))%h(zBr)</a></li> 365 } 363 } 366 } 364 } 367 if( cnt ){ 365 if( cnt ){ 368 @ </ul> 366 @ </ul> 369 } 367 } 370 db_finalize(&q); 368 db_finalize(&q); 371 @ <script type="text/JavaScript"> 369 @ <script type="text/JavaScript"> ................................................................................................................................................................................ 380 /* 378 /* 381 ** This routine is called while for each check-in that is rendered by 379 ** This routine is called while for each check-in that is rendered by 382 ** the timeline of a "brlist" page. Add some additional hyperlinks 380 ** the timeline of a "brlist" page. Add some additional hyperlinks 383 ** to the end of the line. 381 ** to the end of the line. 384 */ 382 */ 385 static void brtimeline_extra(int rid){ 383 static void brtimeline_extra(int rid){ 386 Stmt q; 384 Stmt q; 387 if( !g.perm.History ) return; | 385 if( !g.perm.Hyperlink ) return; 388 db_prepare(&q, 386 db_prepare(&q, 389 "SELECT substr(tagname,5) FROM tagxref, tag" 387 "SELECT substr(tagname,5) FROM tagxref, tag" 390 " WHERE tagxref.rid=%d" 388 " WHERE tagxref.rid=%d" 391 " AND tagxref.tagid=tag.tagid" 389 " AND tagxref.tagid=tag.tagid" 392 " AND tagxref.tagtype>0" 390 " AND tagxref.tagtype>0" 393 " AND tag.tagname GLOB 'sym-*'", 391 " AND tag.tagname GLOB 'sym-*'", 394 rid 392 rid 395 ); 393 ); 396 while( db_step(&q)==SQLITE_ROW ){ 394 while( db_step(&q)==SQLITE_ROW ){ 397 const char *zTagName = db_column_text(&q, 0); 395 const char *zTagName = db_column_text(&q, 0); 398 @ <a href="%s(g.zTop)/timeline?r=%T(zTagName)">[timeline]</a> | 396 @ %z(href("%R/timeline?r=%T",zTagName))[timeline]</a> 399 } 397 } 400 db_finalize(&q); 398 db_finalize(&q); 401 } 399 } 402 400 403 /* 401 /* 404 ** WEBPAGE: brtimeline 402 ** WEBPAGE: brtimeline 405 ** 403 **

Changes to src/browse.c

77 int i, j; 77 int i, j; 78 char *zSep = ""; 78 char *zSep = ""; 79 79 80 for(i=0; zPath[i]; i=j){ 80 for(i=0; zPath[i]; i=j){ 81 for(j=i; zPath[j] && zPath[j]!='/'; j++){} 81 for(j=i; zPath[j] && zPath[j]!='/'; j++){} 82 if( zPath[j] && g.perm.History ){ 82 if( zPath[j] && g.perm.History ){ 83 if( zCI ){ 83 if( zCI ){ > 84 char *zLink = href("%R/dir?ci=%S&amp;name=%#T", zCI, j, zPath); 84 blob_appendf(pOut, "%s<a href=\"%s/dir?ci=%S&amp;name=%#T\">%#h</a>", | 85 blob_appendf(pOut, "%s%z%#h</a>", 85 zSep, g.zTop, zCI, j, zPath, j-i, &zPath[i]); | 86 zSep, zLink, j-i, &zPath[i]); 86 }else{ 87 }else{ > 88 char *zLink = href("%R/dir?name=%#T", j, zPath); 87 blob_appendf(pOut, "%s<a href=\"%s/dir?name=%#T\">%#h</a>", | 89 blob_appendf(pOut, "%s%z%#h</a>", 88 zSep, g.zTop, j, zPath, j-i, &zPath[i]); | 90 zSep, zLink, j-i, &zPath[i]); 89 } 91 } 90 }else{ 92 }else{ 91 blob_appendf(pOut, "%s%#h", zSep, j-i, &zPath[i]); 93 blob_appendf(pOut, "%s%#h", zSep, j-i, &zPath[i]); 92 } 94 } 93 zSep = "/"; 95 zSep = "/"; 94 while( zPath[j]=='/' ){ j++; } 96 while( zPath[j]=='/' ){ j++; } 95 } 97 } ................................................................................................................................................................................ 153 blob_append(&dirname, "in the top-level directory", -1); 155 blob_append(&dirname, "in the top-level directory", -1); 154 zPrefix = ""; 156 zPrefix = ""; 155 } 157 } 156 if( zCI ){ 158 if( zCI ){ 157 char zShort[20]; 159 char zShort[20]; 158 memcpy(zShort, zUuid, 10); 160 memcpy(zShort, zUuid, 10); 159 zShort[10] = 0; 161 zShort[10] = 0; 160 @ <h2>Files of check-in [<a href="vinfo?name=%T(zUuid)">%s(zShort)</a>] | 162 @ <h2>Files of check-in [%z(href("vinfo?name=%T",zUuid))%s(zShort)</a>] 161 @ %s(blob_str(&dirname))</h2> 163 @ %s(blob_str(&dirname))</h2> 162 zSubdirLink = mprintf("%s/dir?ci=%S&amp;name=%T", g.zTop, zUuid, zPrefix); | 164 zSubdirLink = mprintf("%R/dir?ci=%S&amp;name=%T", zUuid, zPrefix); 163 if( zD ){ 165 if( zD ){ 164 style_submenu_element("Top", "Top", "%s/dir?ci=%S", g.zTop, zUuid); | 166 style_submenu_element("Top", "Top", "%R/dir?ci=%S", zUuid); 165 style_submenu_element("All", "All", "%s/dir?name=%t", g.zTop, zD); | 167 style_submenu_element("All", "All", "%R/dir?name=%t", zD); 166 }else{ 168 }else{ 167 style_submenu_element("All", "All", "%s/dir", g.zTop); | 169 style_submenu_element("All", "All", "%R/dir"); 168 } 170 } 169 }else{ 171 }else{ 170 int hasTrunk; 172 int hasTrunk; 171 @ <h2>The union of all files from all check-ins 173 @ <h2>The union of all files from all check-ins 172 @ %s(blob_str(&dirname))</h2> 174 @ %s(blob_str(&dirname))</h2> 173 hasTrunk = db_exists( 175 hasTrunk = db_exists( 174 "SELECT 1 FROM tagxref WHERE tagid=%d AND value='trunk'", 176 "SELECT 1 FROM tagxref WHERE tagid=%d AND value='trunk'", 175 TAG_BRANCH); 177 TAG_BRANCH); 176 zSubdirLink = mprintf("%s/dir?name=%T", g.zTop, zPrefix); | 178 zSubdirLink = mprintf("%R/dir?name=%T", zPrefix); 177 if( zD ){ 179 if( zD ){ 178 style_submenu_element("Top", "Top", "%s/dir", g.zTop); | 180 style_submenu_element("Top", "Top", "%R/dir"); 179 style_submenu_element("Tip", "Tip", "%s/dir?name=%t&amp;ci=tip", | 181 style_submenu_element("Tip", "Tip", "%R/dir?name=%t&amp;ci=tip", zD); 180 g.zTop, zD); < 181 if( hasTrunk ){ 182 if( hasTrunk ){ 182 style_submenu_element("Trunk", "Trunk", "%s/dir?name=%t&amp;ci=trunk", | 183 style_submenu_element("Trunk", "Trunk", "%R/dir?name=%t&amp;ci=trunk", 183 g.zTop,zD); | 184 zD); 184 } 185 } 185 }else{ 186 }else{ 186 style_submenu_element("Tip", "Tip", "%s/dir?ci=tip", g.zTop); | 187 style_submenu_element("Tip", "Tip", "%R/dir?ci=tip"); 187 if( hasTrunk ){ 188 if( hasTrunk ){ 188 style_submenu_element("Trunk", "Trunk", "%s/dir?ci=trunk", g.zTop); | 189 style_submenu_element("Trunk", "Trunk", "%R/dir?ci=trunk"); 189 } 190 } 190 } 191 } 191 } 192 } 192 193 193 /* Compute the temporary table "localfiles" containing the names 194 /* Compute the temporary table "localfiles" containing the names 194 ** of all files and subdirectories in the zD[] directory. 195 ** of all files and subdirectories in the zD[] directory. 195 ** 196 ** ................................................................................................................................................................................ 276 @ </ul></td><td class="browser"><ul class="browser"> 277 @ </ul></td><td class="browser"><ul class="browser"> 277 i = 0; 278 i = 0; 278 } 279 } 279 i++; 280 i++; 280 zFN = db_column_text(&q, 0); 281 zFN = db_column_text(&q, 0); 281 if( zFN[0]=='/' ){ 282 if( zFN[0]=='/' ){ 282 zFN++; 283 zFN++; 283 @ <li><a href="%s(zSubdirLink)%T(zFN)">%h(zFN)/</a></li> | 284 @ <li>%z(href("%s%T",zSubdirLink,zFN))%h(zFN)</a></li> 284 }else if( zCI ){ 285 }else if( zCI ){ 285 const char *zUuid = db_column_text(&q, 1); 286 const char *zUuid = db_column_text(&q, 1); 286 @ <li><a href="%s(g.zTop)/artifact/%s(zUuid)">%h(zFN)</a></li> | 287 @ <li>%z(href("%R/artifact/%s",zUuid))%h(zFN)</a></li> 287 }else{ 288 }else{ 288 @ <li><a href="%s(g.zTop)/finfo?name=%T(zPrefix)%T(zFN)">%h(zFN) | 289 @ <li>%z(href("%R/finfo?name=%T%T",zPrefix,zFN))%h(zFN) 289 @ </a></li> 290 @ </a></li> 290 } 291 } 291 } 292 } 292 db_finalize(&q); 293 db_finalize(&q); 293 manifest_destroy(pM); 294 manifest_destroy(pM); 294 @ </ul></td></tr></table> 295 @ </ul></td></tr></table> 295 style_footer(); 296 style_footer(); 296 } 297 }

Changes to src/diff.c

1776 while( db_step(&q)==SQLITE_ROW ){ 1776 while( db_step(&q)==SQLITE_ROW ){ 1777 int pid = db_column_int(&q, 0); 1777 int pid = db_column_int(&q, 0); 1778 const char *zUuid = db_column_text(&q, 1); 1778 const char *zUuid = db_column_text(&q, 1); 1779 const char *zDate = db_column_text(&q, 2); 1779 const char *zDate = db_column_text(&q, 2); 1780 const char *zUser = db_column_text(&q, 3); 1780 const char *zUser = db_column_text(&q, 3); 1781 if( webLabel ){ 1781 if( webLabel ){ 1782 zLabel = mprintf( 1782 zLabel = mprintf( 1783 "<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %13.13s", | 1783 "<a href='%R/info/%s' target='infowindow'>%.10s</a> %s %13.13s", 1784 g.zTop, zUuid, zUuid, zDate, zUser | 1784 zUuid, zUuid, zDate, zUser 1785 ); 1785 ); 1786 }else{ 1786 }else{ 1787 zLabel = mprintf("%.10s %s %13.13s", zUuid, zDate, zUser); 1787 zLabel = mprintf("%.10s %s %13.13s", zUuid, zDate, zUser); 1788 } 1788 } 1789 p->nVers++; 1789 p->nVers++; 1790 p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) ); 1790 p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) ); 1791 p->azVers[p->nVers-1] = zLabel; 1791 p->azVers[p->nVers-1] = zLabel; ................................................................................................................................................................................ 1819 if( mid==0 || fnid==0 ){ fossil_redirect_home(); } 1819 if( mid==0 || fnid==0 ){ fossil_redirect_home(); } 1820 iLimit = atoi(PD("limit","-1")); 1820 iLimit = atoi(PD("limit","-1")); 1821 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ 1821 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ 1822 fossil_redirect_home(); 1822 fossil_redirect_home(); 1823 } 1823 } 1824 style_header("File Annotation"); 1824 style_header("File Annotation"); 1825 if( P("filevers") ) annFlags |= ANN_FILE_VERS; 1825 if( P("filevers") ) annFlags |= ANN_FILE_VERS; 1826 annotate_file(&ann, fnid, mid, g.perm.History, iLimit, annFlags); | 1826 annotate_file(&ann, fnid, mid, g.perm.Hyperlink, iLimit, annFlags); 1827 if( P("log") ){ 1827 if( P("log") ){ 1828 int i; 1828 int i; 1829 @ <h2>Versions analyzed:</h2> 1829 @ <h2>Versions analyzed:</h2> 1830 @ <ol> 1830 @ <ol> 1831 for(i=0; i<ann.nVers; i++){ 1831 for(i=0; i<ann.nVers; i++){ 1832 @ <li><tt>%s(ann.azVers[i])</tt></li> 1832 @ <li><tt>%s(ann.azVers[i])</tt></li> 1833 } 1833 }

Changes to src/event.c

29 #include "event.h" 29 #include "event.h" 30 30 31 /* 31 /* 32 ** Output a hyperlink to an event given its tagid. 32 ** Output a hyperlink to an event given its tagid. 33 */ 33 */ 34 void hyperlink_to_event_tagid(int tagid){ 34 void hyperlink_to_event_tagid(int tagid){ 35 char *zEventId; 35 char *zEventId; 36 char zShort[12]; < 37 < 38 zEventId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d", 36 zEventId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d", 39 tagid); 37 tagid); 40 sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zEventId); < 41 if( g.perm.History ){ < 42 @ [<a href="%s(g.zTop)/event?name=%s(zEventId)">%s(zShort)</a>] < 43 }else{ < 44 @ [%s(zShort)] < 45 } < > 38 @ [%z(href("%R/event/%s",zEventId))%S(zEventId)</a>] 46 free(zEventId); 39 free(zEventId); 47 } 40 } 48 41 49 /* 42 /* 50 ** WEBPAGE: event 43 ** WEBPAGE: event 51 ** URL: /event 44 ** URL: /event 52 ** PARAMETERS: 45 ** PARAMETERS: ................................................................................................................................................................................ 128 if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){ 121 if( g.perm.WrWiki && g.perm.Write && nextRid==0 ){ 129 style_submenu_element("Edit", "Edit", "%s/eventedit?name=%s", 122 style_submenu_element("Edit", "Edit", "%s/eventedit?name=%s", 130 g.zTop, zEventId); 123 g.zTop, zEventId); 131 } 124 } 132 zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate); 125 zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate); 133 style_submenu_element("Context", "Context", "%s/timeline?c=%T", 126 style_submenu_element("Context", "Context", "%s/timeline?c=%T", 134 g.zTop, zETime); 127 g.zTop, zETime); 135 if( g.perm.History ){ | 128 if( g.perm.Hyperlink ){ 136 if( showDetail ){ 129 if( showDetail ){ 137 style_submenu_element("Plain", "Plain", "%s/event?name=%s&amp;aid=%s", 130 style_submenu_element("Plain", "Plain", "%s/event?name=%s&amp;aid=%s", 138 g.zTop, zEventId, zUuid); 131 g.zTop, zEventId, zUuid); 139 if( nextRid ){ 132 if( nextRid ){ 140 char *zNext; 133 char *zNext; 141 zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid); 134 zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid); 142 style_submenu_element("Next", "Next", 135 style_submenu_element("Next", "Next", ................................................................................................................................................................................ 155 }else{ 148 }else{ 156 style_submenu_element("Detail", "Detail", 149 style_submenu_element("Detail", "Detail", 157 "%s/event?name=%s&amp;aid=%s&amp;detail=1", 150 "%s/event?name=%s&amp;aid=%s&amp;detail=1", 158 g.zTop, zEventId, zUuid); 151 g.zTop, zEventId, zUuid); 159 } 152 } 160 } 153 } 161 154 162 if( showDetail && g.perm.History ){ | 155 if( showDetail && g.perm.Hyperlink ){ 163 int i; 156 int i; 164 const char *zClr = 0; 157 const char *zClr = 0; 165 Blob comment; 158 Blob comment; 166 159 167 zATime = db_text(0, "SELECT datetime(%.17g)", pEvent->rDate); 160 zATime = db_text(0, "SELECT datetime(%.17g)", pEvent->rDate); 168 @ <p>Event [<a href="%s(g.zTop)/artifact/%s(zUuid)">%S(zUuid)</a>] at | 161 @ <p>Event [%z(href("%R/artifact/%s",zUuid))%S(zUuid)</a>] at 169 @ [<a href="%s(g.zTop)/timeline?c=%T(zETime)">%s(zETime)</a>] | 162 @ [%z(href("%R/timeline?c=%T",zETime))%s(zETime)</a>] 170 @ entered by user <b>%h(pEvent->zUser)</b> on 163 @ entered by user <b>%h(pEvent->zUser)</b> on 171 @ [<a href="%s(g.zTop)/timeline?c=%T(zATime)">%s(zATime)</a>]:</p> | 164 @ [%z(href("%R/timeline?c=%T",zATime))%s(zATime)</a>]:</p> 172 @ <blockquote> 165 @ <blockquote> 173 for(i=0; i<pEvent->nTag; i++){ 166 for(i=0; i<pEvent->nTag; i++){ 174 if( fossil_strcmp(pEvent->aTag[i].zName,"+bgcolor")==0 ){ 167 if( fossil_strcmp(pEvent->aTag[i].zName,"+bgcolor")==0 ){ 175 zClr = pEvent->aTag[i].zValue; 168 zClr = pEvent->aTag[i].zValue; 176 } 169 } 177 } 170 } 178 if( zClr && zClr[0]==0 ) zClr = 0; 171 if( zClr && zClr[0]==0 ) zClr = 0;

Changes to src/finfo.c

303 @ <tr><td> 303 @ <tr><td> 304 @ <div class="divider">%s(zPrevDate)</div> 304 @ <div class="divider">%s(zPrevDate)</div> 305 @ </td></tr> 305 @ </td></tr> 306 } 306 } 307 memcpy(zTime, &zDate[11], 5); 307 memcpy(zTime, &zDate[11], 5); 308 zTime[5] = 0; 308 zTime[5] = 0; 309 @ <tr><td class="timelineTime"> 309 @ <tr><td class="timelineTime"> 310 @ <a href="%s(g.zTop)/timeline?c=%t(zDate)">%s(zTime)</a></td> | 310 @ %z(href("%R/timeline?c=%t",zDate))%s(zTime)</a></td> 311 @ <td class="timelineGraph"><div id="m%d(gidx)"></div></td> 311 @ <td class="timelineGraph"><div id="m%d(gidx)"></div></td> 312 if( zBgClr && zBgClr[0] ){ 312 if( zBgClr && zBgClr[0] ){ 313 @ <td class="timelineTableCell" style="background-color: %h(zBgClr);"> 313 @ <td class="timelineTableCell" style="background-color: %h(zBgClr);"> 314 }else{ 314 }else{ 315 @ <td class="timelineTableCell"> 315 @ <td class="timelineTableCell"> 316 } 316 } 317 sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid); 317 sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid); 318 sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin); 318 sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin); 319 if( zUuid ){ 319 if( zUuid ){ 320 if( g.perm.History ){ < 321 @ <a href="%s(g.zTop)/artifact/%s(zUuid)">[%S(zUuid)]</a> < 322 }else{ < 323 @ [%S(zUuid)] < 324 } < 325 @ part of check-in | 320 @ %z(href("%R/artifact/%s",zUuid))[%S(zUuid)]</a> part of check-in 326 }else{ 321 }else{ 327 @ <b>Deleted</b> by check-in 322 @ <b>Deleted</b> by check-in 328 } 323 } 329 hyperlink_to_uuid(zShortCkin); 324 hyperlink_to_uuid(zShortCkin); 330 @ %h(zCom) (user: 325 @ %h(zCom) (user: 331 hyperlink_to_user(zUser, zDate, ""); 326 hyperlink_to_user(zUser, zDate, ""); 332 @ branch: %h(zBr)) 327 @ branch: %h(zBr)) 333 if( g.perm.History && zUuid ){ 328 if( g.perm.History && zUuid ){ 334 const char *z = zFilename; 329 const char *z = zFilename; 335 if( fpid ){ 330 if( fpid ){ 336 @ <a href="%s(g.zTop)/fdiff?v1=%s(zPUuid)&amp;v2=%s(zUuid)">[diff]</a> | 331 @ %z(href("%R/fdiff?v1=%s&amp;v2=%s",zPUuid,zUuid))[diff]</a> 337 } 332 } 338 @ <a href="%s(g.zTop)/annotate?checkin=%S(zCkin)&amp;filename=%h(z)"> | 333 @ %z(href("%R/annotate?checkin=%S&amp;filename=%h",zCkin,z)) 339 @ [annotate]</a> 334 @ [annotate]</a> 340 } 335 } 341 @ </td></tr> 336 @ </td></tr> 342 } 337 } 343 db_finalize(&q); 338 db_finalize(&q); 344 if( pGraph ){ 339 if( pGraph ){ 345 graph_finish(pGraph, 0); 340 graph_finish(pGraph, 0);

Changes to src/info.c

259 hyperlink_to_uuid(zOrigUuid); 259 hyperlink_to_uuid(zOrigUuid); 260 }else{ 260 }else{ 261 @ propagates to descendants 261 @ propagates to descendants 262 } 262 } 263 #if 0 263 #if 0 264 if( zValue && fossil_strcmp(zTagname,"branch")==0 ){ 264 if( zValue && fossil_strcmp(zTagname,"branch")==0 ){ 265 @ &nbsp;&nbsp; 265 @ &nbsp;&nbsp; 266 @ <a href="%s(g.zTop)/timeline?r=%T(zValue)">branch timeline</a> | 266 @ %z(href("%R/timeline?r=%T",zValue))branch timeline</a> 267 } 267 } 268 #endif 268 #endif 269 } 269 } 270 if( zSrcUuid && zSrcUuid[0] ){ 270 if( zSrcUuid && zSrcUuid[0] ){ 271 if( tagtype==0 ){ 271 if( tagtype==0 ){ 272 @ by 272 @ by 273 }else{ 273 }else{ ................................................................................................................................................................................ 331 const char *zName, /* Name of the file that has changed */ 331 const char *zName, /* Name of the file that has changed */ 332 const char *zOld, /* blob.uuid before change. NULL for added files */ 332 const char *zOld, /* blob.uuid before change. NULL for added files */ 333 const char *zNew, /* blob.uuid after change. NULL for deletes */ 333 const char *zNew, /* blob.uuid after change. NULL for deletes */ 334 const char *zOldName, /* Prior name. NULL if no name change. */ 334 const char *zOldName, /* Prior name. NULL if no name change. */ 335 int diffFlags, /* Flags for text_diff(). Zero to omit diffs */ 335 int diffFlags, /* Flags for text_diff(). Zero to omit diffs */ 336 int mperm /* executable or symlink permission for zNew */ 336 int mperm /* executable or symlink permission for zNew */ 337 ){ 337 ){ 338 if( !g.perm.History ){ | 338 if( !g.perm.Hyperlink ){ 339 if( zNew==0 ){ 339 if( zNew==0 ){ 340 @ <p>Deleted %h(zName)</p> 340 @ <p>Deleted %h(zName)</p> 341 }else if( zOld==0 ){ 341 }else if( zOld==0 ){ 342 @ <p>Added %h(zName)</p> 342 @ <p>Added %h(zName)</p> 343 }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ 343 }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ 344 @ <p>Name change from %h(zOldName) to %h(zName) 344 @ <p>Name change from %h(zOldName) to %h(zName) 345 }else if( fossil_strcmp(zNew, zOld)==0 ){ 345 }else if( fossil_strcmp(zNew, zOld)==0 ){ ................................................................................................................................................................................ 352 @ <pre style="white-space:pre;"> 352 @ <pre style="white-space:pre;"> 353 append_diff(zOld, zNew, diffFlags); 353 append_diff(zOld, zNew, diffFlags); 354 @ </pre> 354 @ </pre> 355 } 355 } 356 }else{ 356 }else{ 357 if( zOld && zNew ){ 357 if( zOld && zNew ){ 358 if( fossil_strcmp(zOld, zNew)!=0 ){ 358 if( fossil_strcmp(zOld, zNew)!=0 ){ 359 @ <p>Modified <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> | 359 @ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a> 360 @ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a> | 360 @ from %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a> 361 @ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a> | 361 @ to %z(href("%R/artifact/%s",zNew))[%S(zNew)].</a> 362 }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ 362 }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ 363 @ <p>Name change from 363 @ <p>Name change from 364 @ from <a href="%s(g.zTop)/finfo?name=%T(zOldName)">%h(zOldName)</a> | 364 @ from %z(href("%R/finfo?name=%T",zOldName))%h(zOldName)</a> 365 @ to <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>. | 365 @ to %z(href("%R/finfo?name=%T",zName))%h(zName)</a>. 366 }else{ 366 }else{ 367 @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for 367 @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for 368 @ <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> | 368 @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> 369 } 369 } 370 }else if( zOld ){ 370 }else if( zOld ){ 371 @ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> | 371 @ <p>Deleted %z(href("%s/finfo?name=%T",g.zTop,zName))%h(zName)</a> 372 @ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a> | 372 @ version %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a> 373 }else{ 373 }else{ 374 @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> | 374 @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> 375 @ version <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)]</a> | 375 @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a> 376 } 376 } 377 if( diffFlags ){ 377 if( diffFlags ){ 378 @ <pre style="white-space:pre;"> 378 @ <pre style="white-space:pre;"> 379 append_diff(zOld, zNew, diffFlags); 379 append_diff(zOld, zNew, diffFlags); 380 @ </pre> 380 @ </pre> 381 }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ 381 }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ 382 @ &nbsp;&nbsp; 382 @ &nbsp;&nbsp; 383 @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&amp;v2=%S(zNew)">[diff]</a> | 383 @ %z(href("%R/fdiff?v1=%S&amp;v2=%S",zOld,zNew))[diff]</a> 384 } 384 } 385 @ </p> 385 @ </p> 386 } 386 } 387 } 387 } 388 388 389 /* 389 /* 390 ** Construct an appropriate diffFlag for text_diff() based on query 390 ** Construct an appropriate diffFlag for text_diff() based on query ................................................................................................................................................................................ 533 const char *zDate = db_column_text(&q, 2); 533 const char *zDate = db_column_text(&q, 2); 534 if( zUser==0 || zUser[0]==0 ) zUser = "unknown"; 534 if( zUser==0 || zUser[0]==0 ) zUser = "unknown"; 535 @ <tr><th>Received&nbsp;From:</th> 535 @ <tr><th>Received&nbsp;From:</th> 536 @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr> 536 @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr> 537 } 537 } 538 db_finalize(&q); 538 db_finalize(&q); 539 } 539 } 540 if( g.perm.History ){ | 540 if( g.perm.Hyperlink ){ 541 const char *zProjName = db_get("project-name", "unnamed"); 541 const char *zProjName = db_get("project-name", "unnamed"); 542 @ <tr><th>Timelines:</th><td> 542 @ <tr><th>Timelines:</th><td> 543 @ <a href="%s(g.zTop)/timeline?f=%S(zUuid)">family</a> | 543 @ %z(href("%R/timeline?f=%S",zUuid))family</a> 544 if( zParent ){ 544 if( zParent ){ 545 @ | <a href="%s(g.zTop)/timeline?p=%S(zUuid)">ancestors</a> | 545 @ | %z(href("%R/timeline?p=%S",zUuid))ancestors</a> 546 } 546 } 547 if( !isLeaf ){ 547 if( !isLeaf ){ 548 @ | <a href="%s(g.zTop)/timeline?d=%S(zUuid)">descendants</a> | 548 @ | %z(href("%R/timeline?d=%S",zUuid))descendants</a> 549 } 549 } 550 if( zParent && !isLeaf ){ 550 if( zParent && !isLeaf ){ 551 @ | <a href="%s(g.zTop)/timeline?dp=%S(zUuid)">both</a> | 551 @ | %z(href("%R/timeline?dp=%S",zUuid))both</a> 552 } 552 } 553 db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag " 553 db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag " 554 " WHERE rid=%d AND tagtype>0 " 554 " WHERE rid=%d AND tagtype>0 " 555 " AND tag.tagid=tagxref.tagid " 555 " AND tag.tagid=tagxref.tagid " 556 " AND +tag.tagname GLOB 'sym-*'", rid); 556 " AND +tag.tagname GLOB 'sym-*'", rid); 557 while( db_step(&q)==SQLITE_ROW ){ 557 while( db_step(&q)==SQLITE_ROW ){ 558 const char *zTagName = db_column_text(&q, 0); 558 const char *zTagName = db_column_text(&q, 0); 559 @ | <a href="%s(g.zTop)/timeline?r=%T(zTagName)">%h(zTagName)</a> | 559 @ | %z(href("%R/timeline?r=%T",zTagName))%h(zTagName)</a> 560 } 560 } 561 db_finalize(&q); 561 db_finalize(&q); 562 @ </td></tr> 562 @ </td></tr> 563 @ <tr><th>Other&nbsp;Links:</th> 563 @ <tr><th>Other&nbsp;Links:</th> 564 @ <td> 564 @ <td> 565 @ <a href="%s(g.zTop)/dir?ci=%S(zUuid)">files</a> | 565 @ %z(href("%R/dir?ci=%S",zUuid))files</a> 566 if( g.perm.Zip ){ 566 if( g.perm.Zip ){ 567 char *zUrl = mprintf("%s/tarball/%s-%S.tar.gz?uuid=%s", | 567 char *zUrl = mprintf("%R/tarball/%s-%S.tar.gz?uuid=%s", 568 g.zTop, zProjName, zUuid, zUuid); | 568 zProjName, zUuid, zUuid); 569 @ | <a href="%s(zUrl)">Tarball</a> | 569 @ | %z(href("%s",zUrl))Tarball</a> 570 @ | <a href="%s(g.zTop)/zip/%s(zProjName)-%S(zUuid).zip?uuid=%s(zUuid)"> | 570 @ | %z(href("%R/zip/%s-%S.zip?uuid=%s",zProjName,zUuid,zUuid)) 571 @ ZIP archive</a> 571 @ ZIP archive</a> 572 fossil_free(zUrl); 572 fossil_free(zUrl); 573 } 573 } 574 @ | <a href="%s(g.zTop)/artifact/%S(zUuid)">manifest</a> | 574 @ | %z(href("%R/artifact/%S",zUuid))manifest</a> 575 if( g.perm.Write ){ 575 if( g.perm.Write ){ 576 @ | <a href="%s(g.zTop)/ci_edit?r=%S(zUuid)">edit</a> | 576 @ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a> 577 } 577 } 578 @ </td> 578 @ </td> 579 @ </tr> 579 @ </tr> 580 } 580 } 581 @ </table> 581 @ </table> 582 }else{ 582 }else{ 583 style_header("Check-in Information"); 583 style_header("Check-in Information"); ................................................................................................................................................................................ 588 if( zParent ){ 588 if( zParent ){ 589 @ <div class="section">Changes</div> 589 @ <div class="section">Changes</div> 590 @ <div class="sectionmenu"> 590 @ <div class="sectionmenu"> 591 showDiff = g.zPath[0]!='c'; 591 showDiff = g.zPath[0]!='c'; 592 if( db_get_boolean("show-version-diffs", 0)==0 ){ 592 if( db_get_boolean("show-version-diffs", 0)==0 ){ 593 showDiff = !showDiff; 593 showDiff = !showDiff; 594 if( showDiff ){ 594 if( showDiff ){ 595 @ <a class="button" href="%s(g.zTop)/vinfo/%T(zName)"> | 595 @ %z(xhref("class='button'","%R/vinfo/%T",zName))) 596 @ hide&nbsp;diffs</a> 596 @ hide&nbsp;diffs</a> 597 if( sideBySide ){ 597 if( sideBySide ){ 598 @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=0"> | 598 @ %z(xhref("class='button'","%R/ci/%T?sbs=0",zName)) 599 @ unified&nbsp;diffs</a> 599 @ unified&nbsp;diffs</a> 600 }else{ 600 }else{ 601 @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=1"> | 601 @ %z(xhref("class='button'","%R/ci/%T?sbs=1",zName)) 602 @ side-by-side&nbsp;diffs</a> 602 @ side-by-side&nbsp;diffs</a> 603 } 603 } 604 }else{ 604 }else{ 605 @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=0"> | 605 @ %z(xhref("class='button'","%R/ci/%T?sbs=0",zName)) 606 @ show&nbsp;unified&nbsp;diffs</a> 606 @ show&nbsp;unified&nbsp;diffs</a> 607 @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=1"> | 607 @ %z(xhref("class='button'","%R/ci/%T?sbs=1",zName)) 608 @ show&nbsp;side-by-side&nbsp;diffs</a> 608 @ show&nbsp;side-by-side&nbsp;diffs</a> 609 } 609 } 610 }else{ 610 }else{ 611 if( showDiff ){ 611 if( showDiff ){ 612 @ <a class="button" href="%s(g.zTop)/ci/%T(zName)">hide&nbsp;diffs</a> | 612 @ %z(xhref("class='button'","%R/ci/%T",zName))hide&nbsp;diffs</a> 613 if( sideBySide ){ 613 if( sideBySide ){ 614 @ <a class="button" href="%s(g.zTop)/info/%T(zName)?sbs=0"> | 614 @ %z(xhref("class='button'","%R/info/%T?sbs=0",zName)) 615 @ unified&nbsp;diffs</a> 615 @ unified&nbsp;diffs</a> 616 }else{ 616 }else{ 617 @ <a class="button" href="%s(g.zTop)/info/%T(zName)?sbs=1"> | 617 @ %z(xhref("class='button'","%R/info/%T?sbs=1",zName)) 618 @ side-by-side&nbsp;diffs</a> 618 @ side-by-side&nbsp;diffs</a> 619 } 619 } 620 }else{ 620 }else{ 621 @ <a class="button" href="%s(g.zTop)/vinfo/%T(zName)?sbs=0"> | 621 @ %z(xhref("class='button'","%R/vinfo/%T?sbs=0",zName)) 622 @ show&nbsp;unified&nbsp;diffs</a> 622 @ show&nbsp;unified&nbsp;diffs</a> 623 @ <a class="button" href="%s(g.zTop)/vinfo/%T(zName)?sbs=1"> | 623 @ %z(xhref("class='button'","%R/vinfo/%T?sbs=1",zName)) 624 @ show&nbsp;side-by-side&nbsp;diffs</a> 624 @ show&nbsp;side-by-side&nbsp;diffs</a> 625 } 625 } 626 } 626 } 627 @ <a class="button" href="%s(g.zTop)/vpatch?from=%S(zParent)&to=%S(zUuid)"> | 627 @ %z(xhref("class='button'","%R/vpatch?from=%S&amp;to=%S",zParent,zUuid)) 628 @ patch</a></div> 628 @ patch</a></div> 629 db_prepare(&q, 629 db_prepare(&q, 630 "SELECT name," 630 "SELECT name," 631 " mperm," 631 " mperm," 632 " (SELECT uuid FROM blob WHERE rid=mlink.pid)," 632 " (SELECT uuid FROM blob WHERE rid=mlink.pid)," 633 " (SELECT uuid FROM blob WHERE rid=mlink.fid)," 633 " (SELECT uuid FROM blob WHERE rid=mlink.fid)," 634 " (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)" 634 " (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)" ................................................................................................................................................................................ 696 @ <tr><th>Date:</th><td> 696 @ <tr><th>Date:</th><td> 697 hyperlink_to_date(zDate, "</td></tr>"); 697 hyperlink_to_date(zDate, "</td></tr>"); 698 if( g.perm.Setup ){ 698 if( g.perm.Setup ){ 699 @ <tr><th>Record ID:</th><td>%d(rid)</td></tr> 699 @ <tr><th>Record ID:</th><td>%d(rid)</td></tr> 700 } 700 } 701 @ <tr><th>Original&nbsp;User:</th><td> 701 @ <tr><th>Original&nbsp;User:</th><td> 702 hyperlink_to_user(zUser, zDate, "</td></tr>"); 702 hyperlink_to_user(zUser, zDate, "</td></tr>"); 703 if( g.perm.History ){ | 703 if( g.perm.Hyperlink ){ 704 @ <tr><th>Commands:</th> 704 @ <tr><th>Commands:</th> 705 @ <td> 705 @ <td> 706 @ <a href="%s(g.zTop)/whistory?name=%t(zName)">history</a> | 706 @ &z(href("%R/whistory?name=%t",zName))history</a> 707 @ | <a href="%s(g.zTop)/artifact/%S(zUuid)">raw-text</a> | 707 @ | %z(href("%R/artifact/%S",zUuid))raw-text</a> 708 @ </td> 708 @ </td> 709 @ </tr> 709 @ </tr> 710 } 710 } 711 @ </table></p> 711 @ </table></p> 712 }else{ 712 }else{ 713 style_header("Wiki Information"); 713 style_header("Wiki Information"); 714 rid = 0; 714 rid = 0; ................................................................................................................................................................................ 934 if( mPerm==PERM_LNK ){ 934 if( mPerm==PERM_LNK ){ 935 @ <li>Symbolic link 935 @ <li>Symbolic link 936 }else if( mPerm==PERM_EXE ){ 936 }else if( mPerm==PERM_EXE ){ 937 @ <li>Executable file 937 @ <li>Executable file 938 }else{ 938 }else{ 939 @ <li>File 939 @ <li>File 940 } 940 } 941 if( g.perm.History ){ | 941 @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> 942 @ <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> < 943 }else{ < 944 @ %h(zName) < 945 } < 946 @ <ul> 942 @ <ul> 947 prevName = fossil_strdup(zName); 943 prevName = fossil_strdup(zName); 948 } 944 } 949 @ <li> 945 @ <li> 950 hyperlink_to_date(zDate,""); 946 hyperlink_to_date(zDate,""); 951 @ - part of checkin 947 @ - part of checkin 952 hyperlink_to_uuid(zVers); 948 hyperlink_to_uuid(zVers); 953 if( zBr && zBr[0] ){ 949 if( zBr && zBr[0] ){ 954 if( g.perm.History ){ | 950 @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a> 955 @ on branch <a href="%s(g.zTop)/timeline?r=%T(zBr)">%h(zBr)</a> < 956 }else{ < 957 @ on branch %h(zBr) < 958 } < 959 } 951 } 960 @ - %w(zCom) (user: 952 @ - %w(zCom) (user: 961 hyperlink_to_user(zUser,zDate,""); 953 hyperlink_to_user(zUser,zDate,""); 962 @ ) 954 @ ) 963 if( g.perm.History ){ | 955 if( g.perm.Hyperlink ){ 964 @ <a href="%s(g.zTop)/annotate?checkin=%S(zVers)&filename=%T(zName)"> | 956 @ %z(href("%R/annotate?checkin=%S&filename=%T",zVers,zName)) 965 @ [annotate]</a> 957 @ [annotate]</a> 966 } 958 } 967 cnt++; 959 cnt++; 968 if( pDownloadName && blob_size(pDownloadName)==0 ){ 960 if( pDownloadName && blob_size(pDownloadName)==0 ){ 969 blob_append(pDownloadName, zName, -1); 961 blob_append(pDownloadName, zName, -1); 970 } 962 } 971 } 963 } ................................................................................................................................................................................ 987 const char *zDate = db_column_text(&q, 1); 979 const char *zDate = db_column_text(&q, 1); 988 const char *zUser = db_column_text(&q, 2); 980 const char *zUser = db_column_text(&q, 2); 989 if( cnt>0 ){ 981 if( cnt>0 ){ 990 @ Also wiki page 982 @ Also wiki page 991 }else{ 983 }else{ 992 @ Wiki page 984 @ Wiki page 993 } 985 } 994 if( g.perm.History ){ | 986 @ [%z(href("%R/wiki?name=%t",zPagename))%h(zPagename)</a>] by 995 @ [<a href="%s(g.zTop)/wiki?name=%t(zPagename)">%h(zPagename)</a>] < 996 }else{ < 997 @ [%h(zPagename)] < 998 } < 999 @ by < 1000 hyperlink_to_user(zUser,zDate," on"); 987 hyperlink_to_user(zUser,zDate," on"); 1001 hyperlink_to_date(zDate,"."); 988 hyperlink_to_date(zDate,"."); 1002 nWiki++; 989 nWiki++; 1003 cnt++; 990 cnt++; 1004 if( pDownloadName && blob_size(pDownloadName)==0 ){ 991 if( pDownloadName && blob_size(pDownloadName)==0 ){ 1005 blob_appendf(pDownloadName, "%s.wiki", zPagename); 992 blob_appendf(pDownloadName, "%s.wiki", zPagename); 1006 } 993 } ................................................................................................................................................................................ 1063 /* const char *zSrc = db_column_text(&q, 4); */ 1050 /* const char *zSrc = db_column_text(&q, 4); */ 1064 if( cnt>0 ){ 1051 if( cnt>0 ){ 1065 @ Also attachment "%h(zFilename)" to 1052 @ Also attachment "%h(zFilename)" to 1066 }else{ 1053 }else{ 1067 @ Attachment "%h(zFilename)" to 1054 @ Attachment "%h(zFilename)" to 1068 } 1055 } 1069 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){ 1056 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){ 1070 if( g.perm.History && g.perm.RdTkt ){ | 1057 if( g.perm.Hyperlink && g.perm.RdTkt ){ 1071 @ ticket [<a href="%s(g.zTop)/tktview?name=%S(zTarget)">%S(zTarget)</a>] | 1058 @ ticket [%z(href("%R/tktview?name=%S",zTarget))%S(zTarget)</a>] 1072 }else{ 1059 }else{ 1073 @ ticket [%S(zTarget)] 1060 @ ticket [%S(zTarget)] 1074 } 1061 } 1075 }else{ 1062 }else{ 1076 if( g.perm.History && g.perm.RdWiki ){ | 1063 if( g.perm.Hyperlink && g.perm.RdWiki ){ 1077 @ wiki page [<a href="%s(g.zTop)/wiki?name=%t(zTarget)">%h(zTarget)</a>] | 1064 @ wiki page [%z(href("%R/wiki?name=%t",zTarget)))%h(zTarget)</a>] 1078 }else{ 1065 }else{ 1079 @ wiki page [%h(zTarget)] 1066 @ wiki page [%h(zTarget)] 1080 } 1067 } 1081 } 1068 } 1082 @ added by 1069 @ added by 1083 hyperlink_to_user(zUser,zDate," on"); 1070 hyperlink_to_user(zUser,zDate," on"); 1084 hyperlink_to_date(zDate,"."); 1071 hyperlink_to_date(zDate,"."); ................................................................................................................................................................................ 1089 } 1076 } 1090 db_finalize(&q); 1077 db_finalize(&q); 1091 if( cnt==0 ){ 1078 if( cnt==0 ){ 1092 @ Control artifact. 1079 @ Control artifact. 1093 if( pDownloadName && blob_size(pDownloadName)==0 ){ 1080 if( pDownloadName && blob_size(pDownloadName)==0 ){ 1094 blob_appendf(pDownloadName, "%.10s.txt", zUuid); 1081 blob_appendf(pDownloadName, "%.10s.txt", zUuid); 1095 } 1082 } 1096 }else if( linkToView && g.perm.History ){ | 1083 }else if( linkToView && g.perm.Hyperlink ){ 1097 @ <a href="%s(g.zTop)/artifact/%S(zUuid)">[view]</a> | 1084 @ %z(href("%R/artifact/%S",zUuid))[view]</a> 1098 } 1085 } 1099 } 1086 } 1100 1087 1101 1088 1102 /* 1089 /* 1103 ** WEBPAGE: fdiff 1090 ** WEBPAGE: fdiff 1104 ** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN 1091 ** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN ................................................................................................................................................................................ 1158 style_submenu_element("Unified Diff", "udiff", 1145 style_submenu_element("Unified Diff", "udiff", 1159 "%s/fdiff?v1=%T&v2=%T&sbs=0", 1146 "%s/fdiff?v1=%T&v2=%T&sbs=0", 1160 g.zTop, P("v1"), P("v2")); 1147 g.zTop, P("v1"), P("v2")); 1161 } 1148 } 1162 1149 1163 if( P("smhdr")!=0 ){ 1150 if( P("smhdr")!=0 ){ 1164 @ <h2>Differences From Artifact 1151 @ <h2>Differences From Artifact 1165 @ <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a> To | 1152 @ %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a> To 1166 @ <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>.</h2> | 1153 @ %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>.</h2> 1167 }else{ 1154 }else{ 1168 @ <h2>Differences From 1155 @ <h2>Differences From 1169 @ Artifact <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a>:</h2> | 1156 @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2> 1170 object_description(v1, 0, 0); 1157 object_description(v1, 0, 0); 1171 @ <h2>To Artifact | 1158 @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2> 1172 @ <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>:</h2> < 1173 object_description(v2, 0, 0); 1159 object_description(v2, 0, 0); 1174 } 1160 } 1175 @ <hr /> 1161 @ <hr /> 1176 @ <div class="%s(zStyle)"> 1162 @ <div class="%s(zStyle)"> 1177 @ %s(blob_str(&diff)) 1163 @ %s(blob_str(&diff)) 1178 @ </div> 1164 @ </div> 1179 blob_reset(&diff); 1165 blob_reset(&diff); ................................................................................................................................................................................ 1520 if( pTktChng==0 ){ 1506 if( pTktChng==0 ){ 1521 fossil_redirect_home(); 1507 fossil_redirect_home(); 1522 } 1508 } 1523 style_header("Ticket Change Details"); 1509 style_header("Ticket Change Details"); 1524 zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate); 1510 zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate); 1525 memcpy(zTktName, pTktChng->zTicketUuid, 10); 1511 memcpy(zTktName, pTktChng->zTicketUuid, 10); 1526 zTktName[10] = 0; 1512 zTktName[10] = 0; 1527 if( g.perm.History ){ | 1513 if( g.perm.Hyperlink ){ 1528 @ <h2>Changes to ticket 1514 @ <h2>Changes to ticket 1529 @ <a href="%s(pTktChng->zTicketUuid)">%s(zTktName)</a></h2> | 1515 @ %z(href("%R/tktview/%s",pTktChng->zTicketUuid)))%s(zTktName)</a></h2> 1530 @ 1516 @ 1531 @ <p>By %h(pTktChng->zUser) on %s(zDate). See also: 1517 @ <p>By %h(pTktChng->zUser) on %s(zDate). See also: 1532 @ <a href="%s(g.zTop)/artifact/%T(zUuid)">artifact content</a>, and | 1518 @ %z(href("%R/artifact/%T",zUuid))artifact content</a>, and 1533 @ <a href="%s(g.zTop)/tkthistory/%s(pTktChng->zTicketUuid)">ticket | 1519 @ %z(href("%R/tkthistory/%s",pTktChng->zTicketUuid))ticket history</a></p> 1534 @ history</a></p> < 1535 }else{ 1520 }else{ 1536 @ <h2>Changes to ticket %s(zTktName)</h2> 1521 @ <h2>Changes to ticket %s(zTktName)</h2> 1537 @ 1522 @ 1538 @ <p>By %h(pTktChng->zUser) on %s(zDate). 1523 @ <p>By %h(pTktChng->zUser) on %s(zDate). 1539 @ </p> 1524 @ </p> 1540 } 1525 } 1541 @ 1526 @ ................................................................................................................................................................................ 1963 @ %s(blob_str(&suffix)) 1948 @ %s(blob_str(&suffix)) 1964 @ </td></tr></table> 1949 @ </td></tr></table> 1965 @ </blockquote> 1950 @ </blockquote> 1966 @ <hr /> 1951 @ <hr /> 1967 blob_reset(&suffix); 1952 blob_reset(&suffix); 1968 } 1953 } 1969 @ <p>Make changes to attributes of check-in 1954 @ <p>Make changes to attributes of check-in 1970 @ [<a href="ci?name=%s(zUuid)">%s(zUuid)</a>]:</p> | 1955 @ [%z(href("%R/ci/%s",zUuid))%s(zUuid)</a>]:</p> 1971 @ <form action="%s(g.zTop)/ci_edit" method="post"><div> 1956 @ <form action="%s(g.zTop)/ci_edit" method="post"><div> 1972 login_insert_csrf_secret(); 1957 login_insert_csrf_secret(); 1973 @ <input type="hidden" name="r" value="%S(zUuid)" /> 1958 @ <input type="hidden" name="r" value="%S(zUuid)" /> 1974 @ <table border="0" cellspacing="10"> 1959 @ <table border="0" cellspacing="10"> 1975 1960 1976 @ <tr><td align="right" valign="top"><b>User:</b></td> 1961 @ <tr><td align="right" valign="top"><b>User:</b></td> 1977 @ <td valign="top"> 1962 @ <td valign="top">

Changes to src/login.c

909 if( fossil_strcmp(g.zLogin,"nobody")==0 ){ 909 if( fossil_strcmp(g.zLogin,"nobody")==0 ){ 910 g.zLogin = 0; 910 g.zLogin = 0; 911 } 911 } 912 912 913 /* Set the capabilities */ 913 /* Set the capabilities */ 914 login_replace_capabilities(zCap, 0); 914 login_replace_capabilities(zCap, 0); 915 login_set_anon_nobody_capabilities(); 915 login_set_anon_nobody_capabilities(); > 916 if( zCap[0] && !g.perm.History && !g.perm.Link 916 if( zCap[0] && !g.perm.History && db_get_boolean("auto-enable-hyperlinks",1) | 917 && db_get_boolean("auto-enable-hyperlinks",1) 917 && isHuman(P("HTTP_USER_AGENT")) ){ 918 && isHuman(P("HTTP_USER_AGENT")) ){ 918 g.perm.History = 1; 919 g.perm.History = 1; 919 } 920 } 920 921 921 /* If the public-pages glob pattern is defined and REQUEST_URI matches 922 /* If the public-pages glob pattern is defined and REQUEST_URI matches 922 ** one of the globs in public-pages, then also add in all default-perms 923 ** one of the globs in public-pages, then also add in all default-perms 923 ** permissions. 924 ** permissions. ................................................................................................................................................................................ 981 g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt = 1 982 g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt = 1 982 /* Fall thru into Read/Write */ 983 /* Fall thru into Read/Write */ 983 case 'i': g.perm.Read = g.perm.Write = 1; break; 984 case 'i': g.perm.Read = g.perm.Write = 1; break; 984 case 'o': g.perm.Read = 1; break; 985 case 'o': g.perm.Read = 1; break; 985 case 'z': g.perm.Zip = 1; break; 986 case 'z': g.perm.Zip = 1; break; 986 987 987 case 'd': g.perm.Delete = 1; break; 988 case 'd': g.perm.Delete = 1; break; 988 case 'h': g.perm.History = 1; break; | 989 case 'h': g.perm.History = g.perm.Hyperlink = 1; break; > 990 case 'l': g.perm.Link = g.perm.Hyperlink = 1; break; 989 case 'g': g.perm.Clone = 1; break; 991 case 'g': g.perm.Clone = 1; break; 990 case 'p': g.perm.Password = 1; break; 992 case 'p': g.perm.Password = 1; break; 991 993 992 case 'j': g.perm.RdWiki = 1; break; 994 case 'j': g.perm.RdWiki = 1; break; 993 case 'k': g.perm.WrWiki = g.perm.RdWiki = g.perm.ApndWiki =1; break; 995 case 'k': g.perm.WrWiki = g.perm.RdWiki = g.perm.ApndWiki =1; break; 994 case 'm': g.perm.ApndWiki = 1; break; 996 case 'm': g.perm.ApndWiki = 1; break; 995 case 'f': g.perm.NewWiki = 1; break; 997 case 'f': g.perm.NewWiki = 1; break; ................................................................................................................................................................................ 1055 case 'e': rc = g.perm.RdAddr; break; 1057 case 'e': rc = g.perm.RdAddr; break; 1056 case 'f': rc = g.perm.NewWiki; break; 1058 case 'f': rc = g.perm.NewWiki; break; 1057 case 'g': rc = g.perm.Clone; break; 1059 case 'g': rc = g.perm.Clone; break; 1058 case 'h': rc = g.perm.History; break; 1060 case 'h': rc = g.perm.History; break; 1059 case 'i': rc = g.perm.Write; break; 1061 case 'i': rc = g.perm.Write; break; 1060 case 'j': rc = g.perm.RdWiki; break; 1062 case 'j': rc = g.perm.RdWiki; break; 1061 case 'k': rc = g.perm.WrWiki; break; 1063 case 'k': rc = g.perm.WrWiki; break; 1062 /* case 'l': */ | 1064 case 'l': rc = g.perm.Link; break; 1063 case 'm': rc = g.perm.ApndWiki; break; 1065 case 'm': rc = g.perm.ApndWiki; break; 1064 case 'n': rc = g.perm.NewTkt; break; 1066 case 'n': rc = g.perm.NewTkt; break; 1065 case 'o': rc = g.perm.Read; break; 1067 case 'o': rc = g.perm.Read; break; 1066 case 'p': rc = g.perm.Password; break; 1068 case 'p': rc = g.perm.Password; break; 1067 /* case 'q': */ 1069 /* case 'q': */ 1068 case 'r': rc = g.perm.RdTkt; break; 1070 case 'r': rc = g.perm.RdTkt; break; 1069 case 's': rc = g.perm.Setup; break; 1071 case 's': rc = g.perm.Setup; break; ................................................................................................................................................................................ 1133 /* 1135 /* 1134 ** Call this routine if the user lacks okHistory permission. If 1136 ** Call this routine if the user lacks okHistory permission. If 1135 ** the anonymous user has okHistory permission, then paint a mesage 1137 ** the anonymous user has okHistory permission, then paint a mesage 1136 ** to inform the user that much more information is available by 1138 ** to inform the user that much more information is available by 1137 ** logging in as anonymous. 1139 ** logging in as anonymous. 1138 */ 1140 */ 1139 void login_anonymous_available(void){ 1141 void login_anonymous_available(void){ 1140 if( !g.perm.History && | 1142 if( !g.perm.History && !g.perm.Link && 1141 db_exists("SELECT 1 FROM user" 1143 db_exists("SELECT 1 FROM user" 1142 " WHERE login='anonymous'" 1144 " WHERE login='anonymous'" 1143 " AND cap LIKE '%%h%%'") ){ 1145 " AND cap LIKE '%%h%%'") ){ 1144 const char *zUrl = PD("REQUEST_URI", "index"); 1146 const char *zUrl = PD("REQUEST_URI", "index"); 1145 @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br /> 1147 @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br /> 1146 @ Use <a href="%s(g.zTop)/login?anon=1&amp;g=%T(zUrl)">anonymous login</a> 1148 @ Use <a href="%s(g.zTop)/login?anon=1&amp;g=%T(zUrl)">anonymous login</a> 1147 @ to enable hyperlinks.</p> 1149 @ to enable hyperlinks.</p>

Changes to src/main.c

49 /* 49 /* 50 ** Maximum number of auxiliary parameters on reports 50 ** Maximum number of auxiliary parameters on reports 51 */ 51 */ 52 #define MX_AUX 5 52 #define MX_AUX 5 53 53 54 /* 54 /* 55 ** Holds flags for fossil user permissions. 55 ** Holds flags for fossil user permissions. > 56 ** > 57 ** History enables various hyperlinks directly, with an href= attribute > 58 ** in the HTML. Link puts an id= attribute in HTML and then adds the > 59 ** href= attribute using javascript. The Link option is designed to make > 60 ** it harder for bots and spiders to follow hyperlinks, and yet give the > 61 ** same experience to users. the Hyperlink permission is a composite which > 62 ** is enabled if either History or Hyperlink is turned on. 56 */ 63 */ 57 struct FossilUserPerms { 64 struct FossilUserPerms { 58 char Setup; /* s: use Setup screens on web interface */ 65 char Setup; /* s: use Setup screens on web interface */ 59 char Admin; /* a: administrative permission */ 66 char Admin; /* a: administrative permission */ 60 char Delete; /* d: delete wiki or tickets */ 67 char Delete; /* d: delete wiki or tickets */ 61 char Password; /* p: change password */ 68 char Password; /* p: change password */ 62 char Query; /* q: create new reports */ 69 char Query; /* q: create new reports */ 63 char Write; /* i: xfer inbound. checkin */ 70 char Write; /* i: xfer inbound. checkin */ 64 char Read; /* o: xfer outbound. checkout */ 71 char Read; /* o: xfer outbound. checkout */ 65 char History; /* h: access historical information. */ 72 char History; /* h: access historical information. */ > 73 char Link; /* l: enable href= using javascript */ 66 char Clone; /* g: clone */ 74 char Clone; /* g: clone */ 67 char RdWiki; /* j: view wiki via web */ 75 char RdWiki; /* j: view wiki via web */ 68 char NewWiki; /* f: create new wiki via web */ 76 char NewWiki; /* f: create new wiki via web */ 69 char ApndWiki; /* m: append to wiki via web */ 77 char ApndWiki; /* m: append to wiki via web */ 70 char WrWiki; /* k: edit wiki via web */ 78 char WrWiki; /* k: edit wiki via web */ 71 char RdTkt; /* r: view tickets via web */ 79 char RdTkt; /* r: view tickets via web */ 72 char NewTkt; /* n: create new tickets */ 80 char NewTkt; /* n: create new tickets */ ................................................................................................................................................................................ 73 char ApndTkt; /* c: append to tickets via the web */ 81 char ApndTkt; /* c: append to tickets via the web */ 74 char WrTkt; /* w: make changes to tickets via web */ 82 char WrTkt; /* w: make changes to tickets via web */ 75 char Attach; /* b: add attachments */ 83 char Attach; /* b: add attachments */ 76 char TktFmt; /* t: create new ticket report formats */ 84 char TktFmt; /* t: create new ticket report formats */ 77 char RdAddr; /* e: read email addresses or other private data */ 85 char RdAddr; /* e: read email addresses or other private data */ 78 char Zip; /* z: download zipped artifact via /zip URL */ 86 char Zip; /* z: download zipped artifact via /zip URL */ 79 char Private; /* x: can send and receive private content */ 87 char Private; /* x: can send and receive private content */ > 88 char Hyperlink; /* "h" or "l" */ 80 }; 89 }; 81 90 82 #ifdef FOSSIL_ENABLE_TCL 91 #ifdef FOSSIL_ENABLE_TCL 83 /* 92 /* 84 ** All Tcl related context information is in this structure. This structure 93 ** All Tcl related context information is in this structure. This structure 85 ** definition has been copied from and should be kept in sync with the one in 94 ** definition has been copied from and should be kept in sync with the one in 86 ** "th_tcl.c". 95 ** "th_tcl.c".

Changes to src/printf.c

45 #define etHTTPIZE 17 /* Make text safe for HTTP. "/" encoded as %2f */ 45 #define etHTTPIZE 17 /* Make text safe for HTTP. "/" encoded as %2f */ 46 #define etURLIZE 18 /* Make text safe for HTTP. "/" not encoded */ 46 #define etURLIZE 18 /* Make text safe for HTTP. "/" not encoded */ 47 #define etFOSSILIZE 19 /* The fossil header encoding format. */ 47 #define etFOSSILIZE 19 /* The fossil header encoding format. */ 48 #define etPATH 20 /* Path type */ 48 #define etPATH 20 /* Path type */ 49 #define etWIKISTR 21 /* Wiki text rendered from a char*: %w */ 49 #define etWIKISTR 21 /* Wiki text rendered from a char*: %w */ 50 #define etWIKIBLOB 22 /* Wiki text rendered from a Blob*: %W */ 50 #define etWIKIBLOB 22 /* Wiki text rendered from a Blob*: %W */ 51 #define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */ 51 #define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */ > 52 #define etROOT 24 /* String value of g.zTop: % */ 52 53 53 54 54 /* 55 /* 55 ** An "etByte" is an 8-bit unsigned value. 56 ** An "etByte" is an 8-bit unsigned value. 56 */ 57 */ 57 typedef unsigned char etByte; 58 typedef unsigned char etByte; 58 59 ................................................................................................................................................................................ 91 { 'q', 0, 4, etSQLESCAPE, 0, 0 }, 92 { 'q', 0, 4, etSQLESCAPE, 0, 0 }, 92 { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, 93 { 'Q', 0, 4, etSQLESCAPE2, 0, 0 }, 93 { 'b', 0, 2, etBLOB, 0, 0 }, 94 { 'b', 0, 2, etBLOB, 0, 0 }, 94 { 'B', 0, 2, etBLOBSQL, 0, 0 }, 95 { 'B', 0, 2, etBLOBSQL, 0, 0 }, 95 { 'w', 0, 2, etWIKISTR, 0, 0 }, 96 { 'w', 0, 2, etWIKISTR, 0, 0 }, 96 { 'W', 0, 2, etWIKIBLOB, 0, 0 }, 97 { 'W', 0, 2, etWIKIBLOB, 0, 0 }, 97 { 'h', 0, 4, etHTMLIZE, 0, 0 }, 98 { 'h', 0, 4, etHTMLIZE, 0, 0 }, > 99 { 'R', 0, 0, etROOT, 0, 0 }, 98 { 't', 0, 4, etHTTPIZE, 0, 0 }, /* "/" -> "%2F" */ 100 { 't', 0, 4, etHTTPIZE, 0, 0 }, /* "/" -> "%2F" */ 99 { 'T', 0, 4, etURLIZE, 0, 0 }, /* "/" unchanged */ 101 { 'T', 0, 4, etURLIZE, 0, 0 }, /* "/" unchanged */ 100 { 'F', 0, 4, etFOSSILIZE, 0, 0 }, 102 { 'F', 0, 4, etFOSSILIZE, 0, 0 }, 101 { 'S', 0, 4, etSTRINGID, 0, 0 }, 103 { 'S', 0, 4, etSTRINGID, 0, 0 }, 102 { 'c', 0, 0, etCHARX, 0, 0 }, 104 { 'c', 0, 0, etCHARX, 0, 0 }, 103 { 'o', 8, 0, etRADIX, 0, 2 }, 105 { 'o', 8, 0, etRADIX, 0, 2 }, 104 { 'u', 10, 0, etRADIX, 0, 0 }, 106 { 'u', 10, 0, etRADIX, 0, 0 }, ................................................................................................................................................................................ 568 bufpt[i]='/'; 570 bufpt[i]='/'; 569 }else{ 571 }else{ 570 bufpt[i]=e[i]; 572 bufpt[i]=e[i]; 571 } 573 } 572 } 574 } 573 bufpt[length]='\0'; 575 bufpt[length]='\0'; 574 break; 576 break; > 577 } > 578 case etROOT: { > 579 bufpt = g.zTop; > 580 length = (int)strlen(bufpt); > 581 break; 575 } 582 } 576 case etSTRINGID: { 583 case etSTRINGID: { 577 precision = 16; 584 precision = 16; 578 /* Fall through */ 585 /* Fall through */ 579 } 586 } 580 case etSTRING: 587 case etSTRING: 581 case etDYNSTRING: { 588 case etDYNSTRING: {

Changes to src/report.c

54 } 54 } 55 rn = db_column_int(&q, 0); 55 rn = db_column_int(&q, 0); 56 cnt++; 56 cnt++; 57 blob_appendf(&ril, "<li>"); 57 blob_appendf(&ril, "<li>"); 58 if( zTitle[0] == '_' ){ 58 if( zTitle[0] == '_' ){ 59 blob_appendf(&ril, "%s", zTitle); 59 blob_appendf(&ril, "%s", zTitle); 60 } else { 60 } else { 61 blob_appendf(&ril, "<a href=\"rptview?rn=%d\" rel=\"nofollow\">%h</a>", rn | 61 blob_appendf(&ril, "%z%h</a>", href("%R/rptview?rn=%d", rn), zTitle); 62 } 62 } 63 blob_appendf(&ril, "&nbsp;&nbsp;&nbsp;"); 63 blob_appendf(&ril, "&nbsp;&nbsp;&nbsp;"); 64 if( g.perm.Write && zOwner && zOwner[0] ){ 64 if( g.perm.Write && zOwner && zOwner[0] ){ 65 blob_appendf(&ril, "(by <i>%h</i></i>) ", zOwner); 65 blob_appendf(&ril, "(by <i>%h</i></i>) ", zOwner); 66 } 66 } 67 if( g.perm.TktFmt ){ 67 if( g.perm.TktFmt ){ > 68 blob_appendf(&ril, "[%zcopy</a>] ", 68 blob_appendf(&ril, "[<a href=\"rptedit?rn=%d&amp;copy=1\" rel=\"nofollow\" | 69 href("%R/rptedit?rn=%d&amp;copy=1", rn)); 69 } 70 } 70 if( g.perm.Admin 71 if( g.perm.Admin 71 || (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0) 72 || (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0) 72 ){ 73 ){ 73 blob_appendf(&ril, "[<a href=\"rptedit?rn=%d\" rel=\"nofollow\">edit</a>] | 74 blob_appendf(&ril, "[%zedit</a>]", > 75 href("%R/rptedit?rn=%d", rn)); 74 } 76 } 75 if( g.perm.TktFmt ){ 77 if( g.perm.TktFmt ){ 76 blob_appendf(&ril, "[<a href=\"rptsql?rn=%d\" rel=\"nofollow\">sql</a>] ", | 78 blob_appendf(&ril, "[%zsql</a>]", > 79 href("%R/rptsql?rn=%d", rn)); 77 } 80 } 78 blob_appendf(&ril, "</li>\n"); 81 blob_appendf(&ril, "</li>\n"); 79 } 82 } 80 83 81 Th_Store("report_items", blob_str(&ril)); 84 Th_Store("report_items", blob_str(&ril)); 82 85 83 Th_Render(zScript); 86 Th_Render(zScript); ................................................................................................................................................................................ 718 for(i=0; i<nArg; i++){ 721 for(i=0; i<nArg; i++){ 719 char *zData; 722 char *zData; 720 if( i==pState->iBg ) continue; 723 if( i==pState->iBg ) continue; 721 zData = azArg[i]; 724 zData = azArg[i]; 722 if( zData==0 ) zData = ""; 725 if( zData==0 ) zData = ""; 723 if( pState->iNewRow>=0 && i>=pState->iNewRow ){ 726 if( pState->iNewRow>=0 && i>=pState->iNewRow ){ 724 if( zTid && g.perm.Write ){ 727 if( zTid && g.perm.Write ){ 725 @ <td valign="top"><a href="tktedit/%h(zTid)">edit</a></td> | 728 @ <td valign="top">%z(href("%R/tktedit/%h",zTid))edit</a></td> 726 zTid = 0; 729 zTid = 0; 727 } 730 } 728 if( zData[0] ){ 731 if( zData[0] ){ 729 Blob content; 732 Blob content; 730 @ </tr><tr style="background-color:%h(zBg)"><td colspan=%d(pState->nCol) 733 @ </tr><tr style="background-color:%h(zBg)"><td colspan=%d(pState->nCol) 731 blob_init(&content, zData, -1); 734 blob_init(&content, zData, -1); 732 wiki_convert(&content, 0, 0); 735 wiki_convert(&content, 0, 0); 733 blob_reset(&content); 736 blob_reset(&content); 734 } 737 } 735 }else if( azName[i][0]=='#' ){ 738 }else if( azName[i][0]=='#' ){ 736 zTid = zData; 739 zTid = zData; 737 if( g.perm.History ){ < 738 @ <td valign="top"><a href="tktview?name=%h(zData)">%h(zData)</a></td> < 739 }else{ < 740 @ <td valign="top">%h(zData)</td> | 740 @ <td valign="top">%z(href("%R/tktview?name=%h",zData))%h(zData)</a></td> 741 } < 742 }else if( zData[0]==0 ){ 741 }else if( zData[0]==0 ){ 743 @ <td valign="top">&nbsp;</td> 742 @ <td valign="top">&nbsp;</td> 744 }else{ 743 }else{ 745 @ <td valign="top"> 744 @ <td valign="top"> 746 @ %h(zData) 745 @ %h(zData) 747 @ </td> 746 @ </td> 748 } 747 } 749 } 748 } 750 if( zTid && g.perm.Write ){ 749 if( zTid && g.perm.Write ){ 751 @ <td valign="top"><a href="tktedit/%h(zTid)">edit</a></td> | 750 @ <td valign="top">%z(href("%R/tktedit/%h",zTid))edit</a></td> 752 } 751 } 753 @ </tr> 752 @ </tr> 754 return 0; 753 return 0; 755 } 754 } 756 755 757 /* 756 /* 758 ** Output the text given in the argument. Convert tabs and newlines into 757 ** Output the text given in the argument. Convert tabs and newlines into

Changes to src/setup.c

168 @ repository history</td></tr> 168 @ repository history</td></tr> 169 @ <tr><td valign="top"><b>i</b></td> 169 @ <tr><td valign="top"><b>i</b></td> 170 @ <td><i>Check-In:</i> Commit new versions in the repository</td></tr> 170 @ <td><i>Check-In:</i> Commit new versions in the repository</td></tr> 171 @ <tr><td valign="top"><b>j</b></td> 171 @ <tr><td valign="top"><b>j</b></td> 172 @ <td><i>Read-Wiki:</i> View wiki pages</td></tr> 172 @ <td><i>Read-Wiki:</i> View wiki pages</td></tr> 173 @ <tr><td valign="top"><b>k</b></td> 173 @ <tr><td valign="top"><b>k</b></td> 174 @ <td><i>Write-Wiki:</i> Edit wiki pages</td></tr> 174 @ <td><i>Write-Wiki:</i> Edit wiki pages</td></tr> > 175 @ <tr><td valign="top"><b>l</b></td> > 176 @ <td><i>Link-Late:</i> Use javascript for hyperlinks to > 177 @ discourage bots</td></tr> 175 @ <tr><td valign="top"><b>m</b></td> 178 @ <tr><td valign="top"><b>m</b></td> 176 @ <td><i>Append-Wiki:</i> Append to wiki pages</td></tr> 179 @ <td><i>Append-Wiki:</i> Append to wiki pages</td></tr> 177 @ <tr><td valign="top"><b>n</b></td> 180 @ <tr><td valign="top"><b>n</b></td> 178 @ <td><i>New-Tkt:</i> Create new tickets</td></tr> 181 @ <td><i>New-Tkt:</i> Create new tickets</td></tr> 179 @ <tr><td valign="top"><b>o</b></td> 182 @ <tr><td valign="top"><b>o</b></td> 180 @ <td><i>Check-Out:</i> Check out versions</td></tr> 183 @ <td><i>Check-Out:</i> Check out versions</td></tr> 181 @ <tr><td valign="top"><b>p</b></td> 184 @ <tr><td valign="top"><b>p</b></td> ................................................................................................................................................................................ 246 249 247 /* 250 /* 248 ** WEBPAGE: /setup_uedit 251 ** WEBPAGE: /setup_uedit 249 */ 252 */ 250 void user_edit(void){ 253 void user_edit(void){ 251 const char *zId, *zLogin, *zInfo, *zCap, *zPw; 254 const char *zId, *zLogin, *zInfo, *zCap, *zPw; 252 char *oaa, *oas, *oar, *oaw, *oan, *oai, *oaj, *oao, *oap; 255 char *oaa, *oas, *oar, *oaw, *oan, *oai, *oaj, *oao, *oap; 253 char *oak, *oad, *oac, *oaf, *oam, *oah, *oag, *oae; | 256 char *oak, *oad, *oac, *oaf, *oam, *oah, *oal, *oag, *oae; 254 char *oat, *oau, *oav, *oab, *oax, *oaz; 257 char *oat, *oau, *oav, *oab, *oax, *oaz; 255 const char *zGroup; 258 const char *zGroup; 256 const char *zOldLogin; 259 const char *zOldLogin; 257 char *inherit[128]; 260 char *inherit[128]; 258 int doWrite; 261 int doWrite; 259 int uid; 262 int uid; 260 int higherUser = 0; /* True if user being edited is SETUP and the */ 263 int higherUser = 0; /* True if user being edited is SETUP and the */ ................................................................................................................................................................................ 302 int ar = P("ar")!=0; 305 int ar = P("ar")!=0; 303 int as = g.perm.Setup && P("as")!=0; 306 int as = g.perm.Setup && P("as")!=0; 304 int aw = P("aw")!=0; 307 int aw = P("aw")!=0; 305 int ac = P("ac")!=0; 308 int ac = P("ac")!=0; 306 int af = P("af")!=0; 309 int af = P("af")!=0; 307 int am = P("am")!=0; 310 int am = P("am")!=0; 308 int ah = P("ah")!=0; 311 int ah = P("ah")!=0; > 312 int al = P("al")!=0; 309 int ag = P("ag")!=0; 313 int ag = P("ag")!=0; 310 int at = P("at")!=0; 314 int at = P("at")!=0; 311 int au = P("au")!=0; 315 int au = P("au")!=0; 312 int av = P("av")!=0; 316 int av = P("av")!=0; 313 int ax = P("ax")!=0; 317 int ax = P("ax")!=0; 314 int az = P("az")!=0; 318 int az = P("az")!=0; 315 if( aa ){ zCap[i++] = 'a'; } 319 if( aa ){ zCap[i++] = 'a'; } ................................................................................................................................................................................ 319 if( ae ){ zCap[i++] = 'e'; } 323 if( ae ){ zCap[i++] = 'e'; } 320 if( af ){ zCap[i++] = 'f'; } 324 if( af ){ zCap[i++] = 'f'; } 321 if( ah ){ zCap[i++] = 'h'; } 325 if( ah ){ zCap[i++] = 'h'; } 322 if( ag ){ zCap[i++] = 'g'; } 326 if( ag ){ zCap[i++] = 'g'; } 323 if( ai ){ zCap[i++] = 'i'; } 327 if( ai ){ zCap[i++] = 'i'; } 324 if( aj ){ zCap[i++] = 'j'; } 328 if( aj ){ zCap[i++] = 'j'; } 325 if( ak ){ zCap[i++] = 'k'; } 329 if( ak ){ zCap[i++] = 'k'; } > 330 if( al ){ zCap[i++] = 'l'; } 326 if( am ){ zCap[i++] = 'm'; } 331 if( am ){ zCap[i++] = 'm'; } 327 if( an ){ zCap[i++] = 'n'; } 332 if( an ){ zCap[i++] = 'n'; } 328 if( ao ){ zCap[i++] = 'o'; } 333 if( ao ){ zCap[i++] = 'o'; } 329 if( ap ){ zCap[i++] = 'p'; } 334 if( ap ){ zCap[i++] = 'p'; } 330 if( ar ){ zCap[i++] = 'r'; } 335 if( ar ){ zCap[i++] = 'r'; } 331 if( as ){ zCap[i++] = 's'; } 336 if( as ){ zCap[i++] = 's'; } 332 if( at ){ zCap[i++] = 't'; } 337 if( at ){ zCap[i++] = 't'; } ................................................................................................................................................................................ 410 415 411 /* Load the existing information about the user, if any 416 /* Load the existing information about the user, if any 412 */ 417 */ 413 zLogin = ""; 418 zLogin = ""; 414 zInfo = ""; 419 zInfo = ""; 415 zCap = ""; 420 zCap = ""; 416 zPw = ""; 421 zPw = ""; 417 oaa = oab = oac = oad = oae = oaf = oag = oah = oai = oaj = oak = oam = | 422 oaa = oab = oac = oad = oae = oaf = oag = oah = oai = oaj = oak = oal = oam = 418 oan = oao = oap = oar = oas = oat = oau = oav = oaw = oax = oaz = ""; 423 oan = oao = oap = oar = oas = oat = oau = oav = oaw = oax = oaz = ""; 419 if( uid ){ 424 if( uid ){ 420 zLogin = db_text("", "SELECT login FROM user WHERE uid=%d", uid); 425 zLogin = db_text("", "SELECT login FROM user WHERE uid=%d", uid); 421 zInfo = db_text("", "SELECT info FROM user WHERE uid=%d", uid); 426 zInfo = db_text("", "SELECT info FROM user WHERE uid=%d", uid); 422 zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", uid); 427 zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", uid); 423 zPw = db_text("", "SELECT pw FROM user WHERE uid=%d", uid); 428 zPw = db_text("", "SELECT pw FROM user WHERE uid=%d", uid); 424 if( strchr(zCap, 'a') ) oaa = " checked=\"checked\""; 429 if( strchr(zCap, 'a') ) oaa = " checked=\"checked\""; ................................................................................................................................................................................ 428 if( strchr(zCap, 'e') ) oae = " checked=\"checked\""; 433 if( strchr(zCap, 'e') ) oae = " checked=\"checked\""; 429 if( strchr(zCap, 'f') ) oaf = " checked=\"checked\""; 434 if( strchr(zCap, 'f') ) oaf = " checked=\"checked\""; 430 if( strchr(zCap, 'g') ) oag = " checked=\"checked\""; 435 if( strchr(zCap, 'g') ) oag = " checked=\"checked\""; 431 if( strchr(zCap, 'h') ) oah = " checked=\"checked\""; 436 if( strchr(zCap, 'h') ) oah = " checked=\"checked\""; 432 if( strchr(zCap, 'i') ) oai = " checked=\"checked\""; 437 if( strchr(zCap, 'i') ) oai = " checked=\"checked\""; 433 if( strchr(zCap, 'j') ) oaj = " checked=\"checked\""; 438 if( strchr(zCap, 'j') ) oaj = " checked=\"checked\""; 434 if( strchr(zCap, 'k') ) oak = " checked=\"checked\""; 439 if( strchr(zCap, 'k') ) oak = " checked=\"checked\""; > 440 if( strchr(zCap, 'l') ) oal = " checked=\"checked\""; 435 if( strchr(zCap, 'm') ) oam = " checked=\"checked\""; 441 if( strchr(zCap, 'm') ) oam = " checked=\"checked\""; 436 if( strchr(zCap, 'n') ) oan = " checked=\"checked\""; 442 if( strchr(zCap, 'n') ) oan = " checked=\"checked\""; 437 if( strchr(zCap, 'o') ) oao = " checked=\"checked\""; 443 if( strchr(zCap, 'o') ) oao = " checked=\"checked\""; 438 if( strchr(zCap, 'p') ) oap = " checked=\"checked\""; 444 if( strchr(zCap, 'p') ) oap = " checked=\"checked\""; 439 if( strchr(zCap, 'r') ) oar = " checked=\"checked\""; 445 if( strchr(zCap, 'r') ) oar = " checked=\"checked\""; 440 if( strchr(zCap, 's') ) oas = " checked=\"checked\""; 446 if( strchr(zCap, 's') ) oas = " checked=\"checked\""; 441 if( strchr(zCap, 't') ) oat = " checked=\"checked\""; 447 if( strchr(zCap, 't') ) oat = " checked=\"checked\""; ................................................................................................................................................................................ 522 } 528 } 523 @ <input type="checkbox" name="aa"%s(oaa) />%s(B('a'))Admin<br /> 529 @ <input type="checkbox" name="aa"%s(oaa) />%s(B('a'))Admin<br /> 524 @ <input type="checkbox" name="ad"%s(oad) />%s(B('d'))Delete<br /> 530 @ <input type="checkbox" name="ad"%s(oad) />%s(B('d'))Delete<br /> 525 @ <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br /> 531 @ <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br /> 526 @ <input type="checkbox" name="ap"%s(oap) />%s(B('p'))Password<br /> 532 @ <input type="checkbox" name="ap"%s(oap) />%s(B('p'))Password<br /> 527 @ <input type="checkbox" name="ai"%s(oai) />%s(B('i'))Check-In<br /> 533 @ <input type="checkbox" name="ai"%s(oai) />%s(B('i'))Check-In<br /> 528 @ <input type="checkbox" name="ao"%s(oao) />%s(B('o'))Check-Out<br /> 534 @ <input type="checkbox" name="ao"%s(oao) />%s(B('o'))Check-Out<br /> 529 @ <input type="checkbox" name="ah"%s(oah) />%s(B('h'))History<br /> | 535 @ <input type="checkbox" name="ah"%s(oah) />%s(B('h'))Hyperlinks<br /> > 536 @ <input type="checkbox" name="al"%s(oal) />%s(B('l'))Links-deferred<br /> 530 @ <input type="checkbox" name="au"%s(oau) />%s(B('u'))Reader<br /> 537 @ <input type="checkbox" name="au"%s(oau) />%s(B('u'))Reader<br /> 531 @ <input type="checkbox" name="av"%s(oav) />%s(B('v'))Developer<br /> 538 @ <input type="checkbox" name="av"%s(oav) />%s(B('v'))Developer<br /> 532 @ <input type="checkbox" name="ag"%s(oag) />%s(B('g'))Clone<br /> 539 @ <input type="checkbox" name="ag"%s(oag) />%s(B('g'))Clone<br /> 533 @ <input type="checkbox" name="aj"%s(oaj) />%s(B('j'))Read Wiki<br /> 540 @ <input type="checkbox" name="aj"%s(oaj) />%s(B('j'))Read Wiki<br /> 534 @ <input type="checkbox" name="af"%s(oaf) />%s(B('f'))New Wiki<br /> 541 @ <input type="checkbox" name="af"%s(oaf) />%s(B('f'))New Wiki<br /> 535 @ <input type="checkbox" name="am"%s(oam) />%s(B('m'))Append Wiki<br /> 542 @ <input type="checkbox" name="am"%s(oam) />%s(B('m'))Append Wiki<br /> 536 @ <input type="checkbox" name="ak"%s(oak) />%s(B('k'))Write Wiki<br /> 543 @ <input type="checkbox" name="ak"%s(oak) />%s(B('k'))Write Wiki<br /> ................................................................................................................................................................................ 623 @ by anonymous users. This capability is intended for deletion of spam. 630 @ by anonymous users. This capability is intended for deletion of spam. 624 @ The delete capability is only in effect for 24 hours after the item 631 @ The delete capability is only in effect for 24 hours after the item 625 @ is first posted. The <span class="usertype">Setup</span> user can 632 @ is first posted. The <span class="usertype">Setup</span> user can 626 @ delete anything at any time. 633 @ delete anything at any time. 627 @ </p></li> 634 @ </p></li> 628 @ 635 @ 629 @ <li><p> 636 @ <li><p> 630 @ The <span class="capability">History</span> privilege allows a user | 637 @ The <span class="capability">Hyperlinks</span> privilege allows a user 631 @ to see most hyperlinks. This is recommended ON for most logged-in users 638 @ to see most hyperlinks. This is recommended ON for most logged-in users 632 @ but OFF for user "nobody" to avoid problems with spiders trying to walk 639 @ but OFF for user "nobody" to avoid problems with spiders trying to walk 633 @ every historical version of every baseline and file. | 640 @ every historical version of every baseline and file. The > 641 @ <span class="capability">Link-deferred</span> privilege enables hyperlinks > 642 @ using javascript, which makes them harder for bots and spiders to find. 634 @ </p></li> 643 @ </p></li> 635 @ 644 @ 636 @ <li><p> 645 @ <li><p> 637 @ The <span class="capability">Zip</span> privilege allows a user to 646 @ The <span class="capability">Zip</span> privilege allows a user to 638 @ see the "download as ZIP" 647 @ see the "download as ZIP" 639 @ hyperlink and permits access to the <tt>/zip</tt> page. This allows 648 @ hyperlink and permits access to the <tt>/zip</tt> page. This allows 640 @ users to download ZIP archives without granting other rights like 649 @ users to download ZIP archives without granting other rights like 641 @ <span class="capability">Read</span> or 650 @ <span class="capability">Read</span> or 642 @ <span class="capability">History</span>. This privilege is recommended for | 651 @ <span class="capability">Hyperlink</span>. The "z" privilege is recommended 643 @ user <span class="usertype">nobody</span> so that automatic package | 652 @ for user <span class="usertype">nobody</span> so that automatic package 644 @ downloaders can obtain the sources without going through the login 653 @ downloaders can obtain the sources without going through the login 645 @ procedure. 654 @ procedure. 646 @ </p></li> 655 @ </p></li> 647 @ 656 @ 648 @ <li><p> 657 @ <li><p> 649 @ The <span class="capability">Check-in</span> privilege allows remote 658 @ The <span class="capability">Check-in</span> privilege allows remote 650 @ users to "push". The <span class="capability">Check-out</span> privilege 659 @ users to "push". The <span class="capability">Check-out</span> privilege ................................................................................................................................................................................ 702 @ capabilities of the <span class="usertype">nobody</span> user are 711 @ capabilities of the <span class="usertype">nobody</span> user are 703 @ inherited by all users, regardless of whether or not they are logged in. 712 @ inherited by all users, regardless of whether or not they are logged in. 704 @ To disable universal access to the repository, make sure no user named 713 @ To disable universal access to the repository, make sure no user named 705 @ <span class="usertype">nobody</span> exists or that the 714 @ <span class="usertype">nobody</span> exists or that the 706 @ <span class="usertype">nobody</span> user has no capabilities 715 @ <span class="usertype">nobody</span> user has no capabilities 707 @ enabled. The password for <span class="usertype">nobody</span> is ignore. 716 @ enabled. The password for <span class="usertype">nobody</span> is ignore. 708 @ To avoid problems with spiders overloading the server, it is recommended 717 @ To avoid problems with spiders overloading the server, it is recommended 709 @ that the <span class="capability">h</span> (History) capability be turned | 718 @ that the <span class="capability">h</span> (Hyperlinks) capability be 710 @ off for the <span class="usertype">nobody</span> user. | 719 @ turned off for the <span class="usertype">nobody</span> user. 711 @ </p></li> 720 @ </p></li> 712 @ 721 @ 713 @ <li><p> 722 @ <li><p> 714 @ Login is required for user <span class="usertype">anonymous</span> but the 723 @ Login is required for user <span class="usertype">anonymous</span> but the 715 @ password is displayed on the login screen beside the password entry box 724 @ password is displayed on the login screen beside the password entry box 716 @ so anybody who can read should be able to login as anonymous. 725 @ so anybody who can read should be able to login as anonymous. 717 @ On the other hand, spiders and web-crawlers will typically not 726 @ On the other hand, spiders and web-crawlers will typically not

Changes to src/style.c

43 static int headerHasBeenGenerated = 0; 43 static int headerHasBeenGenerated = 0; 44 44 45 /* 45 /* 46 ** remember, if a sidebox was used 46 ** remember, if a sidebox was used 47 */ 47 */ 48 static int sideboxUsed = 0; 48 static int sideboxUsed = 0; 49 49 > 50 > 51 /* > 52 ** List of hyperlinks that need to be resolved by javascript in > 53 ** the footer. > 54 */ > 55 char **aHref = 0; > 56 int nHref = 0; > 57 int nHrefAlloc = 0; > 58 > 59 /* > 60 ** Generate and return a anchor tag like this: > 61 ** > 62 ** <a href="URL"> > 63 ** or <a id="ID"> > 64 ** > 65 ** The form of the anchor tag is determined by the g.perm.History > 66 ** variable. The href="URL" form is used if g.perm.History is true. > 67 ** If g.perm.History is false and g.perm.Link is true then the > 68 ** id="ID" form is used and javascript is generated in the footer to cause > 69 ** href values to be inserted after the page has loaded. If both > 70 ** g.perm.History and g.perm.Link are false, then the <a id="ID"> form is > 71 ** generated but the javascript is not generated so the links never > 72 ** activate. > 73 ** > 74 ** Handling the href="URL" using javascript is a defense against bots. > 75 ** > 76 ** The name of this routine is deliberately kept short so that can be > 77 ** easily used within @-lines. Example: > 78 ** > 79 ** @ %z(href("%s/artifact/%s",g.zTop,zUuid))%h(zFN)</a> > 80 ** > 81 ** Note %z format. The string returned by this function is always > 82 ** obtained from fossil_malloc(). > 83 ** > 84 ** There are two versions of this routine href() does a plain hyperlink > 85 ** and xhref() adds extra attribute text. > 86 */ > 87 char *xhref(const char *zExtra, const char *zFormat, ...){ > 88 char *zUrl; > 89 va_list ap; > 90 va_start(ap, zFormat); > 91 zUrl = vmprintf(zFormat, ap); > 92 va_end(ap); > 93 if( g.perm.History ){ > 94 return mprintf("<a %s href=\"%z\">", zExtra, zUrl); > 95 } > 96 if( nHref>=nHrefAlloc ){ > 97 nHrefAlloc = nHrefAlloc*2 + 10; > 98 aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0])); > 99 } > 100 aHref[nHref++] = zUrl; > 101 return mprintf("<a %s id=%d>", zExtra, nHref); > 102 } > 103 char *href(const char *zFormat, ...){ > 104 char *zUrl; > 105 va_list ap; > 106 va_start(ap, zFormat); > 107 zUrl = vmprintf(zFormat, ap); > 108 va_end(ap); > 109 if( g.perm.History ){ > 110 return mprintf("<a href=\"%z\">", zUrl); > 111 } > 112 if( nHref>=nHrefAlloc ){ > 113 nHrefAlloc = nHrefAlloc*2 + 10; > 114 aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0])); > 115 } > 116 aHref[nHref++] = zUrl; > 117 return mprintf("<a id=%d>", nHref); > 118 } > 119 > 120 /* > 121 ** Generate javascript that will set the href= attribute on all anchors. > 122 */ > 123 void style_resolve_href(void){ > 124 int i; > 125 if( !g.perm.Link || nHref==0 ) return; > 126 @ <script> > 127 for(i=0; i<nHref; i++){ > 128 @ document.getElementById(%d(i+1)).href="%s(aHref[i])"; > 129 } > 130 @ </script> > 131 } > 132 50 /* 133 /* 51 ** Add a new element to the submenu 134 ** Add a new element to the submenu 52 */ 135 */ 53 void style_submenu_element( 136 void style_submenu_element( 54 const char *zLabel, 137 const char *zLabel, 55 const char *zTitle, 138 const char *zTitle, 56 const char *zLink, 139 const char *zLink, ................................................................................................................................................................................ 162 245 163 /* Render trace log if TH1 tracing is enabled. */ 246 /* Render trace log if TH1 tracing is enabled. */ 164 if( g.thTrace ){ 247 if( g.thTrace ){ 165 cgi_append_content("<span class=\"thTrace\"><hr />\n", -1); 248 cgi_append_content("<span class=\"thTrace\"><hr />\n", -1); 166 cgi_append_content(blob_str(&g.thLog), blob_size(&g.thLog)); 249 cgi_append_content(blob_str(&g.thLog), blob_size(&g.thLog)); 167 cgi_append_content("</span>\n", -1); 250 cgi_append_content("</span>\n", -1); 168 } 251 } > 252 > 253 /* Set the href= field on hyperlinks */ > 254 style_resolve_href(); 169 } 255 } 170 256 171 /* 257 /* 172 ** Begin a side-box on the right-hand side of a page. The title and 258 ** Begin a side-box on the right-hand side of a page. The title and 173 ** the width of the box are given as arguments. The width is usually 259 ** the width of the box are given as arguments. The width is usually 174 ** a percentage of total screen width. 260 ** a percentage of total screen width. 175 */ 261 */

Changes to src/tag.c

546 " AND tagtype=1)" 546 " AND tagtype=1)" 547 " AND tagname GLOB 'sym-*'" 547 " AND tagname GLOB 'sym-*'" 548 " ORDER BY tagname" 548 " ORDER BY tagname" 549 ); 549 ); 550 @ <ul> 550 @ <ul> 551 while( db_step(&q)==SQLITE_ROW ){ 551 while( db_step(&q)==SQLITE_ROW ){ 552 const char *zName = db_column_text(&q, 0); 552 const char *zName = db_column_text(&q, 0); 553 if( g.perm.History ){ | 553 if( g.perm.Hyperlink ){ 554 @ <li><a class="tagLink" href="%s(g.zTop)/timeline?t=%T(zName)"> | 554 @ <li>%z(xhref("class='taglink'","%R/timeline?t=%T",zName)) 555 @ %h(zName)</a></li> 555 @ %h(zName)</a></li> 556 }else{ 556 }else{ 557 @ <li><span class="tagDsp">%h(zName)</span></li> 557 @ <li><span class="tagDsp">%h(zName)</span></li> 558 } 558 } 559 } 559 } 560 @ </ul> 560 @ </ul> 561 db_finalize(&q); 561 db_finalize(&q);

Changes to src/timeline.c

45 45 46 /* 46 /* 47 ** Generate a hyperlink to a version. 47 ** Generate a hyperlink to a version. 48 */ 48 */ 49 void hyperlink_to_uuid(const char *zUuid){ 49 void hyperlink_to_uuid(const char *zUuid){ 50 char z[UUID_SIZE+1]; 50 char z[UUID_SIZE+1]; 51 shorten_uuid(z, zUuid); 51 shorten_uuid(z, zUuid); 52 if( g.perm.History ){ | 52 if( g.perm.Hyperlink ){ 53 @ <a class="timelineHistLink" href="%s(g.zTop)/info/%s(z)">[%s(z)]</a> | 53 @ %z(xhref("class='timelineHistLink'","%R/info/%s",z))[%s(z)]</a> 54 }else{ 54 }else{ 55 @ <span class="timelineHistDsp">[%s(z)]</span> 55 @ <span class="timelineHistDsp">[%s(z)]</span> 56 } 56 } 57 } 57 } 58 58 59 /* 59 /* 60 ** Generate a hyperlink to a diff between two versions. 60 ** Generate a hyperlink to a diff between two versions. 61 */ 61 */ 62 void hyperlink_to_diff(const char *zV1, const char *zV2){ 62 void hyperlink_to_diff(const char *zV1, const char *zV2){ 63 if( g.perm.History ){ | 63 if( g.perm.Hyperlink ){ 64 if( zV2==0 ){ 64 if( zV2==0 ){ 65 @ <a href="%s(g.zTop)/diff?v2=%s(zV1)">[diff]</a> | 65 @ %z(href("%R/diff?v2=%s",zV1))[diff]</a> 66 }else{ 66 }else{ 67 @ <a href="%s(g.zTop)/diff?v1=%s(zV1)&amp;v2=%s(zV2)">[diff]</a> | 67 @ %z(href("%R/diff?v1=%s&amp;v2=%s",zV1,zV2))[diff]</a> 68 } 68 } 69 } 69 } 70 } 70 } 71 71 72 /* 72 /* 73 ** Generate a hyperlink to a date & time. 73 ** Generate a hyperlink to a date & time. 74 */ 74 */ 75 void hyperlink_to_date(const char *zDate, const char *zSuffix){ 75 void hyperlink_to_date(const char *zDate, const char *zSuffix){ 76 if( zSuffix==0 ) zSuffix = ""; 76 if( zSuffix==0 ) zSuffix = ""; 77 if( g.perm.History ){ | 77 if( g.perm.Hyperlink ){ 78 @ <a href="%s(g.zTop)/timeline?c=%T(zDate)">%s(zDate)</a>%s(zSuffix) | 78 @ %z(href("%R/timeline?c=%T",zDate))%s(zDate)</a>%s(zSuffix) 79 }else{ 79 }else{ 80 @ %s(zDate)%s(zSuffix) 80 @ %s(zDate)%s(zSuffix) 81 } 81 } 82 } 82 } 83 83 84 /* 84 /* 85 ** Generate a hyperlink to a user. This will link to a timeline showing 85 ** Generate a hyperlink to a user. This will link to a timeline showing 86 ** events by that user. If the date+time is specified, then the timeline 86 ** events by that user. If the date+time is specified, then the timeline 87 ** is centered on that date+time. 87 ** is centered on that date+time. 88 */ 88 */ 89 void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){ 89 void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){ 90 if( zSuf==0 ) zSuf = ""; 90 if( zSuf==0 ) zSuf = ""; 91 if( g.perm.History ){ | 91 if( g.perm.Hyperlink ){ 92 if( zD && zD[0] ){ 92 if( zD && zD[0] ){ 93 @ <a href="%s(g.zTop)/timeline?c=%T(zD)&amp;u=%T(zU)">%h(zU)</a>%s(zSuf) | 93 @ %z(href("%R/timeline?c=%T&amp;u=%T",zD,zU))%h(zU)</a>%s(zSuf) 94 }else{ 94 }else{ 95 @ <a href="%s(g.zTop)/timeline?u=%T(zU)">%h(zU)</a>%s(zSuf) | 95 @ %z(href("%R/timeline?u=%T",zU))%h(zU)</a>%s(zSuf) 96 } 96 } 97 }else{ 97 }else{ 98 @ %s(zU) 98 @ %s(zU) 99 } 99 } 100 } 100 } 101 101 102 /* 102 /* ................................................................................................................................................................................ 351 } 351 } 352 blob_reset(&comment); 352 blob_reset(&comment); 353 353 354 /* Generate the "user: USERNAME" at the end of the comment, together 354 /* Generate the "user: USERNAME" at the end of the comment, together 355 ** with a hyperlink to another timeline for that user. 355 ** with a hyperlink to another timeline for that user. 356 */ 356 */ 357 if( zTagList && zTagList[0]==0 ) zTagList = 0; 357 if( zTagList && zTagList[0]==0 ) zTagList = 0; 358 if( g.perm.History && fossil_strcmp(zUser, zThisUser)!=0 ){ | 358 if( g.perm.Hyperlink && fossil_strcmp(zUser, zThisUser)!=0 ){ 359 char *zLink = mprintf("%s/timeline?u=%h&c=%t&nd", | 359 char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd", zUser, zDate); 360 g.zTop, zUser, zDate); < 361 @ (user: <a href="%s(zLink)">%h(zUser)</a>%s(zTagList?",":"\051") | 360 @ (user: %z(href("%z",zLink))%h(zUser)</a>%s(zTagList?",":"\051") 362 fossil_free(zLink); < 363 }else{ 361 }else{ 364 @ (user: %h(zUser)%s(zTagList?",":"\051") 362 @ (user: %h(zUser)%s(zTagList?",":"\051") 365 } 363 } 366 364 367 /* Generate a "detail" link for tags. */ 365 /* Generate a "detail" link for tags. */ 368 if( zType[0]=='g' && g.perm.History ){ | 366 if( zType[0]=='g' && g.perm.Hyperlink ){ 369 @ [<a href="%s(g.zTop)/info/%S(zUuid)">details</a>] | 367 @ [%z(href("%R/info/%S",zUuid))details</a>] 370 } 368 } 371 369 372 /* Generate the "tags: TAGLIST" at the end of the comment, together 370 /* Generate the "tags: TAGLIST" at the end of the comment, together 373 ** with hyperlinks to the tag list. 371 ** with hyperlinks to the tag list. 374 */ 372 */ 375 if( zTagList ){ 373 if( zTagList ){ 376 if( g.perm.History ){ | 374 if( g.perm.Hyperlink ){ 377 int i; 375 int i; 378 const char *z = zTagList; 376 const char *z = zTagList; 379 Blob links; 377 Blob links; 380 blob_zero(&links); 378 blob_zero(&links); 381 while( z && z[0] ){ 379 while( z && z[0] ){ 382 for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){} 380 for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){} 383 if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){ 381 if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){ 384 blob_appendf(&links, 382 blob_appendf(&links, 385 "<a href=\"%s/timeline?r=%#t&nd&c=%s\">%#h</a>%.2s", | 383 "%z%#h</a>%.2s", 386 g.zTop, i, z, zDate, i, z, &z[i] | 384 href("%R/timeline?r=%#t&nd&c=%s",i,z,zDate), i,z, &z[i] 387 ); 385 ); 388 }else{ 386 }else{ 389 blob_appendf(&links, "%#h", i+2, z); 387 blob_appendf(&links, "%#h", i+2, z); 390 } 388 } 391 if( z[i]==0 ) break; 389 if( z[i]==0 ) break; 392 z += i+2; 390 z += i+2; 393 } 391 } ................................................................................................................................................................................ 401 399 402 /* Generate extra hyperlinks at the end of the comment */ 400 /* Generate extra hyperlinks at the end of the comment */ 403 if( xExtra ){ 401 if( xExtra ){ 404 xExtra(rid); 402 xExtra(rid); 405 } 403 } 406 404 407 /* Generate the file-change list if requested */ 405 /* Generate the file-change list if requested */ 408 if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' && g.perm.History ){ | 406 if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' && g.perm.Hyperlink ){ 409 int inUl = 0; 407 int inUl = 0; 410 if( !fchngQueryInit ){ 408 if( !fchngQueryInit ){ 411 db_prepare(&fchngQuery, 409 db_prepare(&fchngQuery, 412 "SELECT (pid==0) AS isnew," 410 "SELECT (pid==0) AS isnew," 413 " (fid==0) AS isdel," 411 " (fid==0) AS isdel," 414 " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name," 412 " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name," 415 " (SELECT uuid FROM blob WHERE rid=fid)," 413 " (SELECT uuid FROM blob WHERE rid=fid)," ................................................................................................................................................................................ 431 const char *zNew = db_column_text(&fchngQuery, 3); 429 const char *zNew = db_column_text(&fchngQuery, 3); 432 if( !inUl ){ 430 if( !inUl ){ 433 @ <ul class="filelist"> 431 @ <ul class="filelist"> 434 inUl = 1; 432 inUl = 1; 435 } 433 } 436 if( isNew ){ 434 if( isNew ){ 437 @ <li> %h(zFilename) (new file) &nbsp; 435 @ <li> %h(zFilename) (new file) &nbsp; 438 @ <a href="%s(g.zTop)/artifact/%S(zNew)" | 436 @ %z(xhref("target='diffwindow'","%R/artifact/%S",zNew)) 439 @ target="diffwindow">[view]</a></li> | 437 @ [view]</a></li> 440 }else if( isDel ){ 438 }else if( isDel ){ 441 @ <li> %h(zFilename) (deleted)</li> 439 @ <li> %h(zFilename) (deleted)</li> 442 }else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){ 440 }else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){ 443 @ <li> %h(zOldName) &rarr; %h(zFilename) 441 @ <li> %h(zOldName) &rarr; %h(zFilename) 444 @ <a href="%s(g.zTop)/artifact/%S(zNew)" | 442 @ %z(xhref("target='diffwindow'","%R/artifact/%S",zNew)) 445 @ target="diffwindow">[view]</a></li> | 443 @ [view]</a></li> 446 }else{ 444 }else{ 447 if( zOldName!=0 ){ 445 if( zOldName!=0 ){ 448 @ <li> %h(zOldName) &rarr; %h(zFilename) 446 @ <li> %h(zOldName) &rarr; %h(zFilename) 449 }else{ 447 }else{ 450 @ <li> %h(zFilename) &nbsp; 448 @ <li> %h(zFilename) &nbsp; 451 } 449 } 452 @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)" | 450 @ %z(xhref("target='diffwindow'","%R/fdiff?v1=%S&v2=%S",zOld,zNew)) 453 @ target="diffwindow">[diff]</a></li> | 451 @ [diff]</a></li> 454 } 452 } 455 } 453 } 456 db_reset(&fchngQuery); 454 db_reset(&fchngQuery); 457 if( inUl ){ 455 if( inUl ){ 458 @ </ul> 456 @ </ul> 459 } 457 } 460 } 458 } ................................................................................................................................................................................ 972 while( p ){ 970 while( p ){ 973 blob_appendf(&sql, ",%d", p->rid); 971 blob_appendf(&sql, ",%d", p->rid); 974 p = p->u.pTo; 972 p = p->u.pTo; 975 } 973 } 976 blob_append(&sql, ")", -1); 974 blob_append(&sql, ")", -1); 977 path_reset(); 975 path_reset(); 978 blob_append(&desc, "All nodes on the path from ", -1); 976 blob_append(&desc, "All nodes on the path from ", -1); 979 if( g.perm.History ){ < 980 blob_appendf(&desc, "<a href='%s/info/%h'>[%h]</a>", g.zTop,zFrom,zFrom); < 981 }else{ < 982 blob_appendf(&desc, "[%h]", zFrom); | 977 blob_appendf(&desc, "%z%h</a>", href("%R/info/%h", zFrom), zFrom); 983 } < 984 blob_append(&desc, " and ", -1); 978 blob_append(&desc, " and ", -1); 985 if( g.perm.History ){ < 986 blob_appendf(&desc, "<a href='%s/info/%h'>[%h]</a>.", g.zTop, zTo, zTo); < 987 }else{ < 988 blob_appendf(&desc, "[%h].", zTo); | 979 blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h",zTo), zTo); 989 } < 990 tmFlags |= TIMELINE_DISJOINT; 980 tmFlags |= TIMELINE_DISJOINT; 991 db_multi_exec("%s", blob_str(&sql)); 981 db_multi_exec("%s", blob_str(&sql)); 992 }else if( (p_rid || d_rid) && g.perm.Read ){ 982 }else if( (p_rid || d_rid) && g.perm.Read ){ 993 /* If p= or d= is present, ignore all other parameters other than n= */ 983 /* If p= or d= is present, ignore all other parameters other than n= */ 994 char *zUuid; 984 char *zUuid; 995 int np, nd; 985 int np, nd; 996 986 ................................................................................................................................................................................ 1019 if( np>0 ){ 1009 if( np>0 ){ 1020 if( nd>0 ) blob_appendf(&desc, " and "); 1010 if( nd>0 ) blob_appendf(&desc, " and "); 1021 blob_appendf(&desc, "%d ancestors", np); 1011 blob_appendf(&desc, "%d ancestors", np); 1022 db_multi_exec("%s", blob_str(&sql)); 1012 db_multi_exec("%s", blob_str(&sql)); 1023 } 1013 } 1024 if( d_rid==0 && useDividers ) timeline_add_dividers(0, p_rid); 1014 if( d_rid==0 && useDividers ) timeline_add_dividers(0, p_rid); 1025 } 1015 } 1026 if( g.perm.History ){ < 1027 blob_appendf(&desc, " of <a href='%s/info/%s'>[%.10s]</a>", < 1028 g.zTop, zUuid, zUuid); < 1029 }else{ < 1030 blob_appendf(&desc, " of check-in [%.10s]", zUuid); | 1016 blob_appendf(&desc, " of %z[%.10s]</a>", 1031 } < > 1017 href("%R/info/%s", zUuid), zUuid); 1032 }else if( f_rid && g.perm.Read ){ 1018 }else if( f_rid && g.perm.Read ){ 1033 /* If f= is present, ignore all other parameters other than n= */ 1019 /* If f= is present, ignore all other parameters other than n= */ 1034 char *zUuid; 1020 char *zUuid; 1035 db_multi_exec( 1021 db_multi_exec( 1036 "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);" 1022 "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);" 1037 "INSERT INTO ok VALUES(%d);" 1023 "INSERT INTO ok VALUES(%d);" 1038 "INSERT OR IGNORE INTO ok SELECT pid FROM plink WHERE cid=%d;" 1024 "INSERT OR IGNORE INTO ok SELECT pid FROM plink WHERE cid=%d;" ................................................................................................................................................................................ 1040 f_rid, f_rid, f_rid 1026 f_rid, f_rid, f_rid 1041 ); 1027 ); 1042 blob_appendf(&sql, " AND event.objid IN ok"); 1028 blob_appendf(&sql, " AND event.objid IN ok"); 1043 db_multi_exec("%s", blob_str(&sql)); 1029 db_multi_exec("%s", blob_str(&sql)); 1044 if( useDividers ) timeline_add_dividers(0, f_rid); 1030 if( useDividers ) timeline_add_dividers(0, f_rid); 1045 blob_appendf(&desc, "Parents and children of check-in "); 1031 blob_appendf(&desc, "Parents and children of check-in "); 1046 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid); 1032 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid); 1047 if( g.perm.History ){ < 1048 blob_appendf(&desc, "<a href='%s/info/%s'>[%.10s]</a>", < 1049 g.zTop, zUuid, zUuid); < 1050 }else{ < 1051 blob_appendf(&desc, "[%.10s]", zUuid); | 1033 blob_appendf(&desc, "%z[%.10s]</a>", href("%R/info/%s", zUuid), zUuid); 1052 } < 1053 }else{ 1034 }else{ 1054 /* Otherwise, a timeline based on a span of time */ 1035 /* Otherwise, a timeline based on a span of time */ 1055 int n; 1036 int n; 1056 const char *zEType = "timeline item"; 1037 const char *zEType = "timeline item"; 1057 char *zDate; 1038 char *zDate; 1058 char *zNEntry = mprintf("%d", nEntry); 1039 char *zNEntry = mprintf("%d", nEntry); 1059 url_add_parameter(&url, "n", zNEntry); 1040 url_add_parameter(&url, "n", zNEntry); ................................................................................................................................................................................ 1217 blob_appendf(&desc, " occurring on or before %h.<br />", zBefore); 1198 blob_appendf(&desc, " occurring on or before %h.<br />", zBefore); 1218 }else if( zCirca ){ 1199 }else if( zCirca ){ 1219 blob_appendf(&desc, " occurring around %h.<br />", zCirca); 1200 blob_appendf(&desc, " occurring around %h.<br />", zCirca); 1220 } 1201 } 1221 if( zSearch ){ 1202 if( zSearch ){ 1222 blob_appendf(&desc, " matching \"%h\"", zSearch); 1203 blob_appendf(&desc, " matching \"%h\"", zSearch); 1223 } 1204 } 1224 if( g.perm.History ){ | 1205 if( g.perm.Hyperlink ){ 1225 if( zAfter || n==nEntry ){ 1206 if( zAfter || n==nEntry ){ 1226 zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/"); 1207 zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/"); 1227 timeline_submenu(&url, "Older", "b", zDate, "a"); 1208 timeline_submenu(&url, "Older", "b", zDate, "a"); 1228 free(zDate); 1209 free(zDate); 1229 } 1210 } 1230 if( zBefore || (zAfter && n==nEntry) ){ 1211 if( zBefore || (zAfter && n==nEntry) ){ 1231 zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/"); 1212 zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/"); ................................................................................................................................................................................ 1621 /* 1602 /* 1622 ** WEBPAGE: test_timewarps 1603 ** WEBPAGE: test_timewarps 1623 */ 1604 */ 1624 void test_timewarp_page(void){ 1605 void test_timewarp_page(void){ 1625 Stmt q; 1606 Stmt q; 1626 1607 1627 login_check_credentials(); 1608 login_check_credentials(); 1628 if( !g.perm.Read || !g.perm.History ){ login_needed(); return; } | 1609 if( !g.perm.Read || !g.perm.Hyperlink ){ login_needed(); return; } 1629 style_header("Instances of timewarp"); 1610 style_header("Instances of timewarp"); 1630 @ <ul> 1611 @ <ul> 1631 db_prepare(&q, 1612 db_prepare(&q, 1632 "SELECT blob.uuid " 1613 "SELECT blob.uuid " 1633 " FROM plink p, plink c, blob" 1614 " FROM plink p, plink c, blob" 1634 " WHERE p.cid=c.pid AND p.mtime>c.mtime" 1615 " WHERE p.cid=c.pid AND p.mtime>c.mtime" 1635 " AND blob.rid=c.cid" 1616 " AND blob.rid=c.cid"

Changes to src/tkt.c

303 303 304 login_check_credentials(); 304 login_check_credentials(); 305 if( !g.perm.RdTkt ){ login_needed(); return; } 305 if( !g.perm.RdTkt ){ login_needed(); return; } 306 if( g.perm.WrTkt || g.perm.ApndTkt ){ 306 if( g.perm.WrTkt || g.perm.ApndTkt ){ 307 style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T", 307 style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T", 308 g.zTop, PD("name","")); 308 g.zTop, PD("name","")); 309 } 309 } 310 if( g.perm.History ){ | 310 if( g.perm.Hyperlink ){ 311 style_submenu_element("History", "History Of This Ticket", 311 style_submenu_element("History", "History Of This Ticket", 312 "%s/tkthistory/%T", g.zTop, zUuid); 312 "%s/tkthistory/%T", g.zTop, zUuid); 313 style_submenu_element("Timeline", "Timeline Of This Ticket", 313 style_submenu_element("Timeline", "Timeline Of This Ticket", 314 "%s/tkttimeline/%T", g.zTop, zUuid); 314 "%s/tkttimeline/%T", g.zTop, zUuid); 315 style_submenu_element("Check-ins", "Check-ins Of This Ticket", 315 style_submenu_element("Check-ins", "Check-ins Of This Ticket", 316 "%s/tkttimeline/%T?y=ci", g.zTop, zUuid); 316 "%s/tkttimeline/%T?y=ci", g.zTop, zUuid); 317 } 317 } ................................................................................................................................................................................ 351 const char *zUser = db_column_text(&q, 2); 351 const char *zUser = db_column_text(&q, 2); 352 if( cnt==0 ){ 352 if( cnt==0 ){ 353 @ <hr /><h2>Attachments:</h2> 353 @ <hr /><h2>Attachments:</h2> 354 @ <ul> 354 @ <ul> 355 } 355 } 356 cnt++; 356 cnt++; 357 @ <li> 357 @ <li> 358 if( g.perm.Read && g.perm.History ){ | 358 if( g.perm.Read && g.perm.Hyperlink ){ 359 @ <a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&amp;file=%t(zFile)"> | 359 @ %z(href("%R/attachview?tkt=%s&amp;file=%t",zFullName,zFile)) 360 @ %h(zFile)</a> 360 @ %h(zFile)</a> 361 }else{ 361 }else{ 362 @ %h(zFile) 362 @ %h(zFile) 363 } 363 } 364 @ added by %h(zUser) on 364 @ added by %h(zUser) on 365 hyperlink_to_date(zDate, "."); 365 hyperlink_to_date(zDate, "."); 366 if( g.perm.WrTkt && g.perm.Attach ){ 366 if( g.perm.WrTkt && g.perm.Attach ){ 367 @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&amp;file=%t(zFile) | 367 @ [%z(href("%R/attachdelete?tkt=%s&amp;file=%t&amp;from=%R/tktview%%3fna 368 } 368 } 369 @ </li> 369 @ </li> 370 } 370 } 371 if( cnt ){ 371 if( cnt ){ 372 @ </ul> 372 @ </ul> 373 } 373 } 374 db_finalize(&q); 374 db_finalize(&q); ................................................................................................................................................................................ 660 const char *zUuid; 660 const char *zUuid; 661 char *zFullUuid; 661 char *zFullUuid; 662 int tagid; 662 int tagid; 663 char zGlobPattern[50]; 663 char zGlobPattern[50]; 664 const char *zType; 664 const char *zType; 665 665 666 login_check_credentials(); 666 login_check_credentials(); 667 if( !g.perm.History || !g.perm.RdTkt ){ login_needed(); return; } | 667 if( !g.perm.Hyperlink || !g.perm.RdTkt ){ login_needed(); return; } 668 zUuid = PD("name",""); 668 zUuid = PD("name",""); 669 zType = PD("y","a"); 669 zType = PD("y","a"); 670 if( zType[0]!='c' ){ 670 if( zType[0]!='c' ){ 671 style_submenu_element("Check-ins", "Check-ins", 671 style_submenu_element("Check-ins", "Check-ins", 672 "%s/tkttimeline?name=%T&amp;y=ci", g.zTop, zUuid); 672 "%s/tkttimeline?name=%T&amp;y=ci", g.zTop, zUuid); 673 }else{ 673 }else{ 674 style_submenu_element("Timeline", "Timeline", 674 style_submenu_element("Timeline", "Timeline", ................................................................................................................................................................................ 734 void tkthistory_page(void){ 734 void tkthistory_page(void){ 735 Stmt q; 735 Stmt q; 736 char *zTitle; 736 char *zTitle; 737 const char *zUuid; 737 const char *zUuid; 738 int tagid; 738 int tagid; 739 739 740 login_check_credentials(); 740 login_check_credentials(); 741 if( !g.perm.History || !g.perm.RdTkt ){ login_needed(); return; } | 741 if( !g.perm.Hyperlink || !g.perm.RdTkt ){ login_needed(); return; } 742 zUuid = PD("name",""); 742 zUuid = PD("name",""); 743 zTitle = mprintf("History Of Ticket %h", zUuid); 743 zTitle = mprintf("History Of Ticket %h", zUuid); 744 style_submenu_element("Status", "Status", 744 style_submenu_element("Status", "Status", 745 "%s/info/%s", g.zTop, zUuid); 745 "%s/info/%s", g.zTop, zUuid); 746 style_submenu_element("Check-ins", "Check-ins", 746 style_submenu_element("Check-ins", "Check-ins", 747 "%s/tkttimeline?name=%s&amp;y=ci", g.zTop, zUuid); 747 "%s/tkttimeline?name=%s&amp;y=ci", g.zTop, zUuid); 748 style_submenu_element("Timeline", "Timeline", 748 style_submenu_element("Timeline", "Timeline", ................................................................................................................................................................................ 784 if( zSrc==0 || zSrc[0]==0 ){ 784 if( zSrc==0 || zSrc[0]==0 ){ 785 @ 785 @ 786 @ <p>Delete attachment "%h(zFile)" 786 @ <p>Delete attachment "%h(zFile)" 787 }else{ 787 }else{ 788 @ 788 @ 789 @ <p>Add attachment "%h(zFile)" 789 @ <p>Add attachment "%h(zFile)" 790 } 790 } 791 @ [<a href="%s(g.zTop)/artifact/%T(zChngUuid)">%s(zShort)</a>] | 791 @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>] 792 @ (rid %d(rid)) by 792 @ (rid %d(rid)) by 793 hyperlink_to_user(zUser,zDate," on"); 793 hyperlink_to_user(zUser,zDate," on"); 794 hyperlink_to_date(zDate, ".</p>"); 794 hyperlink_to_date(zDate, ".</p>"); 795 }else{ 795 }else{ 796 pTicket = manifest_get(rid, CFTYPE_TICKET); 796 pTicket = manifest_get(rid, CFTYPE_TICKET); 797 if( pTicket ){ 797 if( pTicket ){ 798 @ 798 @ 799 @ <p>Ticket change 799 @ <p>Ticket change 800 @ [<a href="%s(g.zTop)/artifact/%T(zChngUuid)">%s(zShort)</a>] | 800 @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>] 801 @ (rid %d(rid)) by 801 @ (rid %d(rid)) by 802 hyperlink_to_user(pTicket->zUser,zDate," on"); 802 hyperlink_to_user(pTicket->zUser,zDate," on"); 803 hyperlink_to_date(zDate, ":"); 803 hyperlink_to_date(zDate, ":"); 804 @ </p> 804 @ </p> 805 ticket_output_change_artifact(pTicket); 805 ticket_output_change_artifact(pTicket); 806 } 806 } 807 manifest_destroy(pTicket); 807 manifest_destroy(pTicket);

Changes to src/wiki.c

102 g.isHome = 1; 102 g.isHome = 1; 103 wiki_page(); 103 wiki_page(); 104 return; 104 return; 105 } 105 } 106 style_header("Home"); 106 style_header("Home"); 107 @ <p>This is a stub home-page for the project. 107 @ <p>This is a stub home-page for the project. 108 @ To fill in this page, first go to 108 @ To fill in this page, first go to 109 @ <a href="%s(g.zTop)/setup_config">setup/config</a> | 109 @ %z(href("%R/setup_config"))setup/config</a> 110 @ and establish a "Project Name". Then create a 110 @ and establish a "Project Name". Then create a 111 @ wiki page with that name. The content of that wiki page 111 @ wiki page with that name. The content of that wiki page 112 @ will be displayed in place of this message.</p> 112 @ will be displayed in place of this message.</p> 113 style_footer(); 113 style_footer(); 114 } 114 } 115 115 116 /* 116 /* ................................................................................................................................................................................ 140 if( !g.perm.RdWiki ){ login_needed(); return; } 140 if( !g.perm.RdWiki ){ login_needed(); return; } 141 zPageName = P("name"); 141 zPageName = P("name"); 142 if( zPageName==0 ){ 142 if( zPageName==0 ){ 143 style_header("Wiki"); 143 style_header("Wiki"); 144 @ <ul> 144 @ <ul> 145 { char *zHomePageName = db_get("project-name",0); 145 { char *zHomePageName = db_get("project-name",0); 146 if( zHomePageName ){ 146 if( zHomePageName ){ 147 @ <li> <a href="%s(g.zTop)/wiki?name=%t(zHomePageName)"> | 147 @ <li> %z(href("%R/wiki?name=%t",zHomePageName)) 148 @ %h(zHomePageName)</a> wiki home page.</li> 148 @ %h(zHomePageName)</a> wiki home page.</li> 149 } 149 } 150 } 150 } 151 @ <li> <a href="%s(g.zTop)/timeline?y=w">Recent changes</a> to wiki | 151 @ <li> %z(href("%R/timeline?y=w"))Recent changes</a> to wiki pages.</li> 152 @ pages. </li> < 153 @ <li> <a href="%s(g.zTop)/wiki_rules">Formatting rules</a> for | 152 @ <li> %z(href("%R/wiki_rules"))Formatting rules</a> for wiki.</li> 154 @ wiki.</li> < 155 @ <li> Use the <a href="%s(g.zTop)/wiki?name=Sandbox">Sandbox</a> < > 153 @ <li> Use the %z(href("%R/wiki?name=Sandbox"))Sandbox</a> 156 @ to experiment.</li> 154 @ to experiment.</li> 157 if( g.perm.NewWiki ){ 155 if( g.perm.NewWiki ){ 158 @ <li> Create a <a href="%s(g.zTop)/wikinew">new wiki page</a>.</li> < > 156 @ <li> Create a %z(href("%R/wikinew"))new wiki page</a>.</li> 159 if( g.perm.Write ){ 157 if( g.perm.Write ){ 160 @ <li> Create a <a href="%s(g.zTop)/eventedit">new event</a>.</li> < > 158 @ <li> Create a %z(href("%R/eventedit"))new event</a>.</li> 161 } 159 } 162 } 160 } 163 @ <li> <a href="%s(g.zTop)/wcontent">List of All Wiki Pages</a> | 161 @ <li> %z(href("%R/wcontent"))List of All Wiki Pages</a> 164 @ available on this server.</li> 162 @ available on this server.</li> 165 @ <li> <form method="get" action="%s(g.zTop)/wfind"><div> 163 @ <li> <form method="get" action="%s(g.zTop)/wfind"><div> 166 @ Search wiki titles: <input type="text" name="title"/> 164 @ Search wiki titles: <input type="text" name="title"/> 167 @ &nbsp; <input type="submit" /></div></form> 165 @ &nbsp; <input type="submit" /></div></form> 168 @ </li> 166 @ </li> 169 @ </ul> 167 @ </ul> 170 style_footer(); 168 style_footer(); ................................................................................................................................................................................ 197 "%s/attachadd?page=%T&amp;from=%s/wiki%%3fname=%T", 195 "%s/attachadd?page=%T&amp;from=%s/wiki%%3fname=%T", 198 g.zTop, zPageName, g.zTop, zPageName); 196 g.zTop, zPageName, g.zTop, zPageName); 199 } 197 } 200 if( rid && g.perm.ApndWiki ){ 198 if( rid && g.perm.ApndWiki ){ 201 style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T", 199 style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T", 202 g.zTop, zPageName); 200 g.zTop, zPageName); 203 } 201 } 204 if( g.perm.History ){ | 202 if( g.perm.Hyperlink ){ 205 style_submenu_element("History", "History", "%s/whistory?name=%T", 203 style_submenu_element("History", "History", "%s/whistory?name=%T", 206 g.zTop, zPageName); 204 g.zTop, zPageName); 207 } 205 } 208 } 206 } 209 style_header(zPageName); 207 style_header(zPageName); 210 blob_init(&wiki, zBody, -1); 208 blob_init(&wiki, zBody, -1); 211 wiki_convert(&wiki, 0, 0); 209 wiki_convert(&wiki, 0, 0); ................................................................................................................................................................................ 223 const char *zUser = db_column_text(&q, 2); 221 const char *zUser = db_column_text(&q, 2); 224 if( cnt==0 ){ 222 if( cnt==0 ){ 225 @ <hr /><h2>Attachments:</h2> 223 @ <hr /><h2>Attachments:</h2> 226 @ <ul> 224 @ <ul> 227 } 225 } 228 cnt++; 226 cnt++; 229 @ <li> 227 @ <li> 230 if( g.perm.History && g.perm.Read ){ | 228 if( g.perm.Hyperlink && g.perm.Read ){ 231 @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&amp;file=%t(zFile)"> | 229 @ %z(href("%R/attachview?page=%T&amp;file=%t",zPageName,zFile)) 232 @ %h(zFile)</a> 230 @ %h(zFile)</a> 233 }else{ 231 }else{ 234 @ %h(zFile) 232 @ %h(zFile) 235 } 233 } 236 @ added by %h(zUser) on 234 @ added by %h(zUser) on 237 hyperlink_to_date(zDate, "."); 235 hyperlink_to_date(zDate, "."); 238 if( g.perm.WrWiki && g.perm.Attach ){ 236 if( g.perm.WrWiki && g.perm.Attach ){ 239 @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&amp;file=%t(zFile)& | 237 @ [%z(href("%R/attachdelete?page=%t&amp;file=%t&amp;from=%R/wiki%%3fname=% 240 } 238 } 241 @ </li> 239 @ </li> 242 } 240 } 243 if( cnt ){ 241 if( cnt ){ 244 @ </ul> 242 @ </ul> 245 } 243 } 246 db_finalize(&q); 244 db_finalize(&q); ................................................................................................................................................................................ 542 540 543 /* 541 /* 544 ** Function called to output extra text at the end of each line in 542 ** Function called to output extra text at the end of each line in 545 ** a wiki history listing. 543 ** a wiki history listing. 546 */ 544 */ 547 static void wiki_history_extra(int rid){ 545 static void wiki_history_extra(int rid){ 548 if( db_exists("SELECT 1 FROM tagxref WHERE rid=%d", rid) ){ 546 if( db_exists("SELECT 1 FROM tagxref WHERE rid=%d", rid) ){ 549 @ <a href="%s(g.zTop)/wdiff?name=%t(zWikiPageName)&amp;a=%d(rid)">[diff]</a> | 547 @ %z(href("%R/wdiff?name=%t&amp;a=%d",zWikiPageName,rid))[diff]</a> 550 } 548 } 551 } 549 } 552 550 553 /* 551 /* 554 ** WEBPAGE: whistory 552 ** WEBPAGE: whistory 555 ** URL: /whistory?name=PAGENAME 553 ** URL: /whistory?name=PAGENAME 556 ** 554 ** ................................................................................................................................................................................ 558 */ 556 */ 559 void whistory_page(void){ 557 void whistory_page(void){ 560 Stmt q; 558 Stmt q; 561 char *zTitle; 559 char *zTitle; 562 char *zSQL; 560 char *zSQL; 563 const char *zPageName; 561 const char *zPageName; 564 login_check_credentials(); 562 login_check_credentials(); 565 if( !g.perm.History ){ login_needed(); return; } | 563 if( !g.perm.Hyperlink ){ login_needed(); return; } 566 zPageName = PD("name",""); 564 zPageName = PD("name",""); 567 zTitle = mprintf("History Of %s", zPageName); 565 zTitle = mprintf("History Of %s", zPageName); 568 style_header(zTitle); 566 style_header(zTitle); 569 free(zTitle); 567 free(zTitle); 570 568 571 zSQL = mprintf("%s AND event.objid IN " 569 zSQL = mprintf("%s AND event.objid IN " 572 " (SELECT rid FROM tagxref WHERE tagid=" 570 " (SELECT rid FROM tagxref WHERE tagid=" ................................................................................................................................................................................ 595 const char *zPageName; 593 const char *zPageName; 596 Manifest *pW1, *pW2 = 0; 594 Manifest *pW1, *pW2 = 0; 597 Blob w1, w2, d; 595 Blob w1, w2, d; 598 int diffFlags; 596 int diffFlags; 599 597 600 login_check_credentials(); 598 login_check_credentials(); 601 rid1 = atoi(PD("a","0")); 599 rid1 = atoi(PD("a","0")); 602 if( !g.perm.History ){ login_needed(); return; } | 600 if( !g.perm.Hyperlink ){ login_needed(); return; } 603 if( rid1==0 ) fossil_redirect_home(); 601 if( rid1==0 ) fossil_redirect_home(); 604 rid2 = atoi(PD("b","0")); 602 rid2 = atoi(PD("b","0")); 605 zPageName = PD("name",""); 603 zPageName = PD("name",""); 606 zTitle = mprintf("Changes To %s", zPageName); 604 zTitle = mprintf("Changes To %s", zPageName); 607 style_header(zTitle); 605 style_header(zTitle); 608 free(zTitle); 606 free(zTitle); 609 607 ................................................................................................................................................................................ 672 } 670 } 673 @ <ul> 671 @ <ul> 674 wiki_prepare_page_list(&q); 672 wiki_prepare_page_list(&q); 675 while( db_step(&q)==SQLITE_ROW ){ 673 while( db_step(&q)==SQLITE_ROW ){ 676 const char *zName = db_column_text(&q, 0); 674 const char *zName = db_column_text(&q, 0); 677 int size = db_column_int(&q, 1); 675 int size = db_column_int(&q, 1); 678 if( size>0 ){ 676 if( size>0 ){ 679 @ <li><a href="%s(g.zTop)/wiki?name=%T(zName)">%h(zName)</a></li> | 677 @ <li>%z(href("%R/wiki?name=%T",zName))%h(zName)</a></li> 680 }else if( showAll ){ 678 }else if( showAll ){ 681 @ <li><a href="%s(g.zTop)/wiki?name=%T(zName)"><s>%h(zName)</s></a></li> | 679 @ <li>%z(href("%R/wiki?name=%T",zName))<s>%h(zName)</s></a></li> 682 } 680 } 683 } 681 } 684 db_finalize(&q); 682 db_finalize(&q); 685 @ </ul> 683 @ </ul> 686 style_footer(); 684 style_footer(); 687 } 685 } 688 686 ................................................................................................................................................................................ 702 @ <ul> 700 @ <ul> 703 db_prepare(&q, 701 db_prepare(&q, 704 "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'" 702 "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'" 705 " ORDER BY lower(tagname) /*sort*/" , 703 " ORDER BY lower(tagname) /*sort*/" , 706 zTitle); 704 zTitle); 707 while( db_step(&q)==SQLITE_ROW ){ 705 while( db_step(&q)==SQLITE_ROW ){ 708 const char *zName = db_column_text(&q, 0); 706 const char *zName = db_column_text(&q, 0); 709 @ <li><a href="%s(g.zTop)/wiki?name=%T(zName)">%h(zName)</a></li> | 707 @ <li>%z(href("%R/wiki?name=%T",zName))%h(zName)</a></li> 710 } 708 } 711 db_finalize(&q); 709 db_finalize(&q); 712 @ </ul> 710 @ </ul> 713 style_footer(); 711 style_footer(); 714 } 712 } 715 713 716 /* 714 /*

Changes to src/wikiformat.c

1047 }else if( zTarget[0]=='/' ){ 1047 }else if( zTarget[0]=='/' ){ 1048 if( 1 /* g.perm.History */ ){ 1048 if( 1 /* g.perm.History */ ){ 1049 blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zTop, zTarget); 1049 blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zTop, zTarget); 1050 }else{ 1050 }else{ 1051 zTerm = ""; 1051 zTerm = ""; 1052 } 1052 } 1053 }else if( zTarget[0]=='.' || zTarget[0]=='#' ){ 1053 }else if( zTarget[0]=='.' || zTarget[0]=='#' ){ 1054 if( 1 /* g.perm.History */ ){ | 1054 if( 1 ){ 1055 blob_appendf(p->pOut, "<a href=\"%h\">", zTarget); 1055 blob_appendf(p->pOut, "<a href=\"%h\">", zTarget); 1056 }else{ 1056 }else{ 1057 zTerm = ""; 1057 zTerm = ""; 1058 } 1058 } 1059 }else if( is_valid_uuid(zTarget) ){ 1059 }else if( is_valid_uuid(zTarget) ){ 1060 int isClosed = 0; 1060 int isClosed = 0; 1061 if( is_ticket(zTarget, &isClosed) ){ 1061 if( is_ticket(zTarget, &isClosed) ){ 1062 /* Special display processing for tickets. Display the hyperlink 1062 /* Special display processing for tickets. Display the hyperlink 1063 ** as crossed out if the ticket is closed. 1063 ** as crossed out if the ticket is closed. 1064 */ 1064 */ 1065 if( isClosed ){ 1065 if( isClosed ){ 1066 if( g.perm.History ){ | 1066 if( g.perm.Hyperlink ){ 1067 blob_appendf(p->pOut, 1067 blob_appendf(p->pOut, 1068 "<a href=\"%s/info/%s\"><span class=\"wikiTagCancelled\">[", | 1068 "%z<span class=\"wikiTagCancelled\">[", 1069 g.zTop, zTarget | 1069 href("%R/info/%s",zTarget) 1070 ); 1070 ); 1071 zTerm = "]</span></a>"; 1071 zTerm = "]</span></a>"; 1072 }else{ 1072 }else{ 1073 blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">["); 1073 blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">["); 1074 zTerm = "]</span>"; 1074 zTerm = "]</span>"; 1075 } 1075 } 1076 }else{ 1076 }else{ 1077 if( g.perm.History ){ | 1077 if( g.perm.Hyperlink ){ 1078 blob_appendf(p->pOut,"<a href=\"%s/info/%s\">[", | 1078 blob_appendf(p->pOut,"%z[", href("%R/info/%s", zTarget)); 1079 g.zTop, zTarget < 1080 ); < 1081 zTerm = "]</a>"; 1079 zTerm = "]</a>"; 1082 }else{ 1080 }else{ 1083 blob_appendf(p->pOut, "["); 1081 blob_appendf(p->pOut, "["); 1084 zTerm = "]"; 1082 zTerm = "]"; 1085 } 1083 } 1086 } 1084 } 1087 }else if( !in_this_repo(zTarget) ){ 1085 }else if( !in_this_repo(zTarget) ){ 1088 blob_appendf(p->pOut, "<span class=\"brokenlink\">[", zTarget); 1086 blob_appendf(p->pOut, "<span class=\"brokenlink\">[", zTarget); 1089 zTerm = "]</span>"; 1087 zTerm = "]</span>"; 1090 }else if( g.perm.History ){ | 1088 }else if( g.perm.Hyperlink ){ 1091 blob_appendf(p->pOut, "<a href=\"%s/info/%s\">[", g.zTop, zTarget); | 1089 blob_appendf(p->pOut, "%z[",href("%R/info/%s", zTarget)); 1092 zTerm = "]</a>"; 1090 zTerm = "]</a>"; 1093 } 1091 } 1094 }else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-' 1092 }else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-' 1095 && db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){ 1093 && db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){ 1096 blob_appendf(p->pOut, "<a href=\"%s/timeline?c=%T\">", g.zTop, zTarget); 1094 blob_appendf(p->pOut, "<a href=\"%s/timeline?c=%T\">", g.zTop, zTarget); 1097 }else if( strncmp(zTarget, "wiki:", 5)==0 1095 }else if( strncmp(zTarget, "wiki:", 5)==0 1098 && wiki_name_is_wellformed((const unsigned char*)zTarget) ){ 1096 && wiki_name_is_wellformed((const unsigned char*)zTarget) ){