Fossil SCM
Move the enhanced spider-defense mechanism into the trunk.
Commit
433cde1ce8d1d503a9f86a3ac3022ecfaee7bf54
Parent
f9711803e22ee88…
22 files changed
+2
-2
+7
-9
+23
-22
+3
-3
+1
-1
+10
-17
+5
-10
+65
-80
+1
-1
+2
-2
+1
-1
+16
-15
+3
-2
+7
+12
-13
+23
-15
+87
+2
-2
+33
-52
+12
-12
+19
-21
+9
-15
~
src/attach.c
~
src/branch.c
~
src/browse.c
~
src/diff.c
~
src/diffcmd.c
~
src/event.c
~
src/finfo.c
~
src/info.c
~
src/json_dir.c
~
src/json_timeline.c
~
src/json_wiki.c
~
src/login.c
~
src/main.c
~
src/printf.c
~
src/report.c
~
src/setup.c
~
src/style.c
~
src/tag.c
~
src/timeline.c
~
src/tkt.c
~
src/wiki.c
~
src/wikiformat.c
+2
-2
| --- src/attach.c | ||
| +++ src/attach.c | ||
| @@ -75,13 +75,13 @@ | ||
| 75 | 75 | zFilename = &zFilename[i+1]; |
| 76 | 76 | i = -1; |
| 77 | 77 | } |
| 78 | 78 | } |
| 79 | 79 | if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){ |
| 80 | - zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename); | |
| 80 | + zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename); | |
| 81 | 81 | }else{ |
| 82 | - zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename); | |
| 82 | + zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename); | |
| 83 | 83 | } |
| 84 | 84 | @ |
| 85 | 85 | @ <p><a href="/attachview?%s(zUrlTail)">%h(zFilename)</a> |
| 86 | 86 | @ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br /> |
| 87 | 87 | if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++; |
| 88 | 88 |
| --- src/attach.c | |
| +++ src/attach.c | |
| @@ -75,13 +75,13 @@ | |
| 75 | zFilename = &zFilename[i+1]; |
| 76 | i = -1; |
| 77 | } |
| 78 | } |
| 79 | if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){ |
| 80 | zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename); |
| 81 | }else{ |
| 82 | zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename); |
| 83 | } |
| 84 | @ |
| 85 | @ <p><a href="/attachview?%s(zUrlTail)">%h(zFilename)</a> |
| 86 | @ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br /> |
| 87 | if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++; |
| 88 |
| --- src/attach.c | |
| +++ src/attach.c | |
| @@ -75,13 +75,13 @@ | |
| 75 | zFilename = &zFilename[i+1]; |
| 76 | i = -1; |
| 77 | } |
| 78 | } |
| 79 | if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){ |
| 80 | zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename); |
| 81 | }else{ |
| 82 | zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename); |
| 83 | } |
| 84 | @ |
| 85 | @ <p><a href="/attachview?%s(zUrlTail)">%h(zFilename)</a> |
| 86 | @ [<a href="/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br /> |
| 87 | if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++; |
| 88 |
+7
-9
| --- src/branch.c | ||
| +++ src/branch.c | ||
| @@ -321,18 +321,18 @@ | ||
| 321 | 321 | style_submenu_element("All", "All", "brlist?all"); |
| 322 | 322 | } |
| 323 | 323 | login_anonymous_available(); |
| 324 | 324 | style_sidebox_begin("Nomenclature:", "33%"); |
| 325 | 325 | @ <ol> |
| 326 | - @ <li> An <div class="sideboxDescribed"><a href="brlist"> | |
| 326 | + @ <li> An <div class="sideboxDescribed">%z(href("brlist")) | |
| 327 | 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 | 329 | @ The presence of open leaves presumably means |
| 330 | 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 | 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 | 334 | @ closed leaves</a></div>. |
| 335 | 335 | @ Closed branches are fixed and do not change (unless they are first |
| 336 | 336 | @ reopened)</li> |
| 337 | 337 | @ </ol> |
| 338 | 338 | style_sidebox_end(); |
| @@ -356,14 +356,12 @@ | ||
| 356 | 356 | } |
| 357 | 357 | if( colorTest ){ |
| 358 | 358 | const char *zColor = hash_color(zBr); |
| 359 | 359 | @ <li><span style="background-color: %s(zColor)"> |
| 360 | 360 | @ %h(zBr) → %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 | 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 | 365 | if( cnt ){ |
| 368 | 366 | @ </ul> |
| 369 | 367 | } |
| @@ -382,11 +380,11 @@ | ||
| 382 | 380 | ** the timeline of a "brlist" page. Add some additional hyperlinks |
| 383 | 381 | ** to the end of the line. |
| 384 | 382 | */ |
| 385 | 383 | static void brtimeline_extra(int rid){ |
| 386 | 384 | Stmt q; |
| 387 | - if( !g.perm.History ) return; | |
| 385 | + if( !g.perm.Hyperlink ) return; | |
| 388 | 386 | db_prepare(&q, |
| 389 | 387 | "SELECT substr(tagname,5) FROM tagxref, tag" |
| 390 | 388 | " WHERE tagxref.rid=%d" |
| 391 | 389 | " AND tagxref.tagid=tag.tagid" |
| 392 | 390 | " AND tagxref.tagtype>0" |
| @@ -393,11 +391,11 @@ | ||
| 393 | 391 | " AND tag.tagname GLOB 'sym-*'", |
| 394 | 392 | rid |
| 395 | 393 | ); |
| 396 | 394 | while( db_step(&q)==SQLITE_ROW ){ |
| 397 | 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 | 398 | db_finalize(&q); |
| 401 | 399 | } |
| 402 | 400 | |
| 403 | 401 | /* |
| 404 | 402 |
| --- src/branch.c | |
| +++ src/branch.c | |
| @@ -321,18 +321,18 @@ | |
| 321 | style_submenu_element("All", "All", "brlist?all"); |
| 322 | } |
| 323 | login_anonymous_available(); |
| 324 | style_sidebox_begin("Nomenclature:", "33%"); |
| 325 | @ <ol> |
| 326 | @ <li> An <div class="sideboxDescribed"><a href="brlist"> |
| 327 | @ open branch</a></div> is a branch that has one or |
| 328 | @ more <a href="leaves">open leaves.</a> |
| 329 | @ The presence of open leaves presumably means |
| 330 | @ that the branch is still being extended with new check-ins.</li> |
| 331 | @ <li> A <div class="sideboxDescribed"><a href="brlist?closed"> |
| 332 | @ closed branch</a></div> is a branch with only |
| 333 | @ <div class="sideboxDescribed"><a href="leaves?closed"> |
| 334 | @ closed leaves</a></div>. |
| 335 | @ Closed branches are fixed and do not change (unless they are first |
| 336 | @ reopened)</li> |
| 337 | @ </ol> |
| 338 | style_sidebox_end(); |
| @@ -356,14 +356,12 @@ | |
| 356 | } |
| 357 | if( colorTest ){ |
| 358 | const char *zColor = hash_color(zBr); |
| 359 | @ <li><span style="background-color: %s(zColor)"> |
| 360 | @ %h(zBr) → %s(zColor)</span></li> |
| 361 | }else if( g.perm.History ){ |
| 362 | @ <li><a href="%s(g.zTop)/timeline?r=%T(zBr)")>%h(zBr)</a></li> |
| 363 | }else{ |
| 364 | @ <li><b>%h(zBr)</b></li> |
| 365 | } |
| 366 | } |
| 367 | if( cnt ){ |
| 368 | @ </ul> |
| 369 | } |
| @@ -382,11 +380,11 @@ | |
| 382 | ** the timeline of a "brlist" page. Add some additional hyperlinks |
| 383 | ** to the end of the line. |
| 384 | */ |
| 385 | static void brtimeline_extra(int rid){ |
| 386 | Stmt q; |
| 387 | if( !g.perm.History ) return; |
| 388 | db_prepare(&q, |
| 389 | "SELECT substr(tagname,5) FROM tagxref, tag" |
| 390 | " WHERE tagxref.rid=%d" |
| 391 | " AND tagxref.tagid=tag.tagid" |
| 392 | " AND tagxref.tagtype>0" |
| @@ -393,11 +391,11 @@ | |
| 393 | " AND tag.tagname GLOB 'sym-*'", |
| 394 | rid |
| 395 | ); |
| 396 | while( db_step(&q)==SQLITE_ROW ){ |
| 397 | const char *zTagName = db_column_text(&q, 0); |
| 398 | @ <a href="%s(g.zTop)/timeline?r=%T(zTagName)">[timeline]</a> |
| 399 | } |
| 400 | db_finalize(&q); |
| 401 | } |
| 402 | |
| 403 | /* |
| 404 |
| --- src/branch.c | |
| +++ src/branch.c | |
| @@ -321,18 +321,18 @@ | |
| 321 | style_submenu_element("All", "All", "brlist?all"); |
| 322 | } |
| 323 | login_anonymous_available(); |
| 324 | style_sidebox_begin("Nomenclature:", "33%"); |
| 325 | @ <ol> |
| 326 | @ <li> An <div class="sideboxDescribed">%z(href("brlist")) |
| 327 | @ open branch</a></div> is a branch that has one or |
| 328 | @ more %z(href("leaves"))open leaves.</a> |
| 329 | @ The presence of open leaves presumably means |
| 330 | @ that the branch is still being extended with new check-ins.</li> |
| 331 | @ <li> A <div class="sideboxDescribed">%z(href("brlist?closed")) |
| 332 | @ closed branch</a></div> is a branch with only |
| 333 | @ <div class="sideboxDescribed">%z(href("leaves?closed")) |
| 334 | @ closed leaves</a></div>. |
| 335 | @ Closed branches are fixed and do not change (unless they are first |
| 336 | @ reopened)</li> |
| 337 | @ </ol> |
| 338 | style_sidebox_end(); |
| @@ -356,14 +356,12 @@ | |
| 356 | } |
| 357 | if( colorTest ){ |
| 358 | const char *zColor = hash_color(zBr); |
| 359 | @ <li><span style="background-color: %s(zColor)"> |
| 360 | @ %h(zBr) → %s(zColor)</span></li> |
| 361 | }else{ |
| 362 | @ <li>%z(href("%R/timeline?r=%T",zBr))%h(zBr)</a></li> |
| 363 | } |
| 364 | } |
| 365 | if( cnt ){ |
| 366 | @ </ul> |
| 367 | } |
| @@ -382,11 +380,11 @@ | |
| 380 | ** the timeline of a "brlist" page. Add some additional hyperlinks |
| 381 | ** to the end of the line. |
| 382 | */ |
| 383 | static void brtimeline_extra(int rid){ |
| 384 | Stmt q; |
| 385 | if( !g.perm.Hyperlink ) return; |
| 386 | db_prepare(&q, |
| 387 | "SELECT substr(tagname,5) FROM tagxref, tag" |
| 388 | " WHERE tagxref.rid=%d" |
| 389 | " AND tagxref.tagid=tag.tagid" |
| 390 | " AND tagxref.tagtype>0" |
| @@ -393,11 +391,11 @@ | |
| 391 | " AND tag.tagname GLOB 'sym-*'", |
| 392 | rid |
| 393 | ); |
| 394 | while( db_step(&q)==SQLITE_ROW ){ |
| 395 | const char *zTagName = db_column_text(&q, 0); |
| 396 | @ %z(href("%R/timeline?r=%T",zTagName))[timeline]</a> |
| 397 | } |
| 398 | db_finalize(&q); |
| 399 | } |
| 400 | |
| 401 | /* |
| 402 |
+23
-22
| --- src/browse.c | ||
| +++ src/browse.c | ||
| @@ -77,17 +77,19 @@ | ||
| 77 | 77 | int i, j; |
| 78 | 78 | char *zSep = ""; |
| 79 | 79 | |
| 80 | 80 | for(i=0; zPath[i]; i=j){ |
| 81 | 81 | for(j=i; zPath[j] && zPath[j]!='/'; j++){} |
| 82 | - if( zPath[j] && g.perm.History ){ | |
| 82 | + if( zPath[j] && g.perm.Hyperlink ){ | |
| 83 | 83 | if( zCI ){ |
| 84 | - blob_appendf(pOut, "%s<a href=\"%s/dir?ci=%S&name=%#T\">%#h</a>", | |
| 85 | - zSep, g.zTop, zCI, j, zPath, j-i, &zPath[i]); | |
| 84 | + char *zLink = href("%R/dir?ci=%S&name=%#T", zCI, j, zPath); | |
| 85 | + blob_appendf(pOut, "%s%z%#h</a>", | |
| 86 | + zSep, zLink, j-i, &zPath[i]); | |
| 86 | 87 | }else{ |
| 87 | - blob_appendf(pOut, "%s<a href=\"%s/dir?name=%#T\">%#h</a>", | |
| 88 | - zSep, g.zTop, j, zPath, j-i, &zPath[i]); | |
| 88 | + char *zLink = href("%R/dir?name=%#T", j, zPath); | |
| 89 | + blob_appendf(pOut, "%s%z%#h</a>", | |
| 90 | + zSep, zLink, j-i, &zPath[i]); | |
| 89 | 91 | } |
| 90 | 92 | }else{ |
| 91 | 93 | blob_appendf(pOut, "%s%#h", zSep, j-i, &zPath[i]); |
| 92 | 94 | } |
| 93 | 95 | zSep = "/"; |
| @@ -118,11 +120,11 @@ | ||
| 118 | 120 | Blob dirname; |
| 119 | 121 | Manifest *pM = 0; |
| 120 | 122 | const char *zSubdirLink; |
| 121 | 123 | |
| 122 | 124 | login_check_credentials(); |
| 123 | - if( !g.perm.History ){ login_needed(); return; } | |
| 125 | + if( !g.perm.Hyperlink ){ login_needed(); return; } | |
| 124 | 126 | while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; } |
| 125 | 127 | style_header("File List"); |
| 126 | 128 | sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0, |
| 127 | 129 | pathelementFunc, 0, 0); |
| 128 | 130 | |
| @@ -155,39 +157,38 @@ | ||
| 155 | 157 | } |
| 156 | 158 | if( zCI ){ |
| 157 | 159 | char zShort[20]; |
| 158 | 160 | memcpy(zShort, zUuid, 10); |
| 159 | 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 | 163 | @ %s(blob_str(&dirname))</h2> |
| 162 | - zSubdirLink = mprintf("%s/dir?ci=%S&name=%T", g.zTop, zUuid, zPrefix); | |
| 164 | + zSubdirLink = mprintf("%R/dir?ci=%S&name=%T", zUuid, zPrefix); | |
| 163 | 165 | if( zD ){ |
| 164 | - style_submenu_element("Top", "Top", "%s/dir?ci=%S", g.zTop, zUuid); | |
| 165 | - style_submenu_element("All", "All", "%s/dir?name=%t", g.zTop, zD); | |
| 166 | + style_submenu_element("Top", "Top", "%R/dir?ci=%S", zUuid); | |
| 167 | + style_submenu_element("All", "All", "%R/dir?name=%t", zD); | |
| 166 | 168 | }else{ |
| 167 | - style_submenu_element("All", "All", "%s/dir", g.zTop); | |
| 169 | + style_submenu_element("All", "All", "%R/dir"); | |
| 168 | 170 | } |
| 169 | 171 | }else{ |
| 170 | 172 | int hasTrunk; |
| 171 | 173 | @ <h2>The union of all files from all check-ins |
| 172 | 174 | @ %s(blob_str(&dirname))</h2> |
| 173 | 175 | hasTrunk = db_exists( |
| 174 | 176 | "SELECT 1 FROM tagxref WHERE tagid=%d AND value='trunk'", |
| 175 | 177 | TAG_BRANCH); |
| 176 | - zSubdirLink = mprintf("%s/dir?name=%T", g.zTop, zPrefix); | |
| 178 | + zSubdirLink = mprintf("%R/dir?name=%T", zPrefix); | |
| 177 | 179 | if( zD ){ |
| 178 | - style_submenu_element("Top", "Top", "%s/dir", g.zTop); | |
| 179 | - style_submenu_element("Tip", "Tip", "%s/dir?name=%t&ci=tip", | |
| 180 | - g.zTop, zD); | |
| 180 | + style_submenu_element("Top", "Top", "%R/dir"); | |
| 181 | + style_submenu_element("Tip", "Tip", "%R/dir?name=%t&ci=tip", zD); | |
| 181 | 182 | if( hasTrunk ){ |
| 182 | - style_submenu_element("Trunk", "Trunk", "%s/dir?name=%t&ci=trunk", | |
| 183 | - g.zTop,zD); | |
| 183 | + style_submenu_element("Trunk", "Trunk", "%R/dir?name=%t&ci=trunk", | |
| 184 | + zD); | |
| 184 | 185 | } |
| 185 | 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 | 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 | 194 | /* Compute the temporary table "localfiles" containing the names |
| @@ -278,19 +279,19 @@ | ||
| 278 | 279 | } |
| 279 | 280 | i++; |
| 280 | 281 | zFN = db_column_text(&q, 0); |
| 281 | 282 | if( zFN[0]=='/' ){ |
| 282 | 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 | 285 | }else if( zCI ){ |
| 285 | 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 | 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 | 290 | @ </a></li> |
| 290 | 291 | } |
| 291 | 292 | } |
| 292 | 293 | db_finalize(&q); |
| 293 | 294 | manifest_destroy(pM); |
| 294 | 295 | @ </ul></td></tr></table> |
| 295 | 296 | style_footer(); |
| 296 | 297 | } |
| 297 | 298 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -77,17 +77,19 @@ | |
| 77 | int i, j; |
| 78 | char *zSep = ""; |
| 79 | |
| 80 | for(i=0; zPath[i]; i=j){ |
| 81 | for(j=i; zPath[j] && zPath[j]!='/'; j++){} |
| 82 | if( zPath[j] && g.perm.History ){ |
| 83 | if( zCI ){ |
| 84 | blob_appendf(pOut, "%s<a href=\"%s/dir?ci=%S&name=%#T\">%#h</a>", |
| 85 | zSep, g.zTop, zCI, j, zPath, j-i, &zPath[i]); |
| 86 | }else{ |
| 87 | blob_appendf(pOut, "%s<a href=\"%s/dir?name=%#T\">%#h</a>", |
| 88 | zSep, g.zTop, j, zPath, j-i, &zPath[i]); |
| 89 | } |
| 90 | }else{ |
| 91 | blob_appendf(pOut, "%s%#h", zSep, j-i, &zPath[i]); |
| 92 | } |
| 93 | zSep = "/"; |
| @@ -118,11 +120,11 @@ | |
| 118 | Blob dirname; |
| 119 | Manifest *pM = 0; |
| 120 | const char *zSubdirLink; |
| 121 | |
| 122 | login_check_credentials(); |
| 123 | if( !g.perm.History ){ login_needed(); return; } |
| 124 | while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; } |
| 125 | style_header("File List"); |
| 126 | sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0, |
| 127 | pathelementFunc, 0, 0); |
| 128 | |
| @@ -155,39 +157,38 @@ | |
| 155 | } |
| 156 | if( zCI ){ |
| 157 | char zShort[20]; |
| 158 | memcpy(zShort, zUuid, 10); |
| 159 | zShort[10] = 0; |
| 160 | @ <h2>Files of check-in [<a href="vinfo?name=%T(zUuid)">%s(zShort)</a>] |
| 161 | @ %s(blob_str(&dirname))</h2> |
| 162 | zSubdirLink = mprintf("%s/dir?ci=%S&name=%T", g.zTop, zUuid, zPrefix); |
| 163 | if( zD ){ |
| 164 | style_submenu_element("Top", "Top", "%s/dir?ci=%S", g.zTop, zUuid); |
| 165 | style_submenu_element("All", "All", "%s/dir?name=%t", g.zTop, zD); |
| 166 | }else{ |
| 167 | style_submenu_element("All", "All", "%s/dir", g.zTop); |
| 168 | } |
| 169 | }else{ |
| 170 | int hasTrunk; |
| 171 | @ <h2>The union of all files from all check-ins |
| 172 | @ %s(blob_str(&dirname))</h2> |
| 173 | hasTrunk = db_exists( |
| 174 | "SELECT 1 FROM tagxref WHERE tagid=%d AND value='trunk'", |
| 175 | TAG_BRANCH); |
| 176 | zSubdirLink = mprintf("%s/dir?name=%T", g.zTop, zPrefix); |
| 177 | if( zD ){ |
| 178 | style_submenu_element("Top", "Top", "%s/dir", g.zTop); |
| 179 | style_submenu_element("Tip", "Tip", "%s/dir?name=%t&ci=tip", |
| 180 | g.zTop, zD); |
| 181 | if( hasTrunk ){ |
| 182 | style_submenu_element("Trunk", "Trunk", "%s/dir?name=%t&ci=trunk", |
| 183 | g.zTop,zD); |
| 184 | } |
| 185 | }else{ |
| 186 | style_submenu_element("Tip", "Tip", "%s/dir?ci=tip", g.zTop); |
| 187 | if( hasTrunk ){ |
| 188 | style_submenu_element("Trunk", "Trunk", "%s/dir?ci=trunk", g.zTop); |
| 189 | } |
| 190 | } |
| 191 | } |
| 192 | |
| 193 | /* Compute the temporary table "localfiles" containing the names |
| @@ -278,19 +279,19 @@ | |
| 278 | } |
| 279 | i++; |
| 280 | zFN = db_column_text(&q, 0); |
| 281 | if( zFN[0]=='/' ){ |
| 282 | zFN++; |
| 283 | @ <li><a href="%s(zSubdirLink)%T(zFN)">%h(zFN)/</a></li> |
| 284 | }else if( zCI ){ |
| 285 | const char *zUuid = db_column_text(&q, 1); |
| 286 | @ <li><a href="%s(g.zTop)/artifact/%s(zUuid)">%h(zFN)</a></li> |
| 287 | }else{ |
| 288 | @ <li><a href="%s(g.zTop)/finfo?name=%T(zPrefix)%T(zFN)">%h(zFN) |
| 289 | @ </a></li> |
| 290 | } |
| 291 | } |
| 292 | db_finalize(&q); |
| 293 | manifest_destroy(pM); |
| 294 | @ </ul></td></tr></table> |
| 295 | style_footer(); |
| 296 | } |
| 297 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -77,17 +77,19 @@ | |
| 77 | int i, j; |
| 78 | char *zSep = ""; |
| 79 | |
| 80 | for(i=0; zPath[i]; i=j){ |
| 81 | for(j=i; zPath[j] && zPath[j]!='/'; j++){} |
| 82 | if( zPath[j] && g.perm.Hyperlink ){ |
| 83 | if( zCI ){ |
| 84 | char *zLink = href("%R/dir?ci=%S&name=%#T", zCI, j, zPath); |
| 85 | blob_appendf(pOut, "%s%z%#h</a>", |
| 86 | zSep, zLink, j-i, &zPath[i]); |
| 87 | }else{ |
| 88 | char *zLink = href("%R/dir?name=%#T", j, zPath); |
| 89 | blob_appendf(pOut, "%s%z%#h</a>", |
| 90 | zSep, zLink, j-i, &zPath[i]); |
| 91 | } |
| 92 | }else{ |
| 93 | blob_appendf(pOut, "%s%#h", zSep, j-i, &zPath[i]); |
| 94 | } |
| 95 | zSep = "/"; |
| @@ -118,11 +120,11 @@ | |
| 120 | Blob dirname; |
| 121 | Manifest *pM = 0; |
| 122 | const char *zSubdirLink; |
| 123 | |
| 124 | login_check_credentials(); |
| 125 | if( !g.perm.Hyperlink ){ login_needed(); return; } |
| 126 | while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; } |
| 127 | style_header("File List"); |
| 128 | sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0, |
| 129 | pathelementFunc, 0, 0); |
| 130 | |
| @@ -155,39 +157,38 @@ | |
| 157 | } |
| 158 | if( zCI ){ |
| 159 | char zShort[20]; |
| 160 | memcpy(zShort, zUuid, 10); |
| 161 | zShort[10] = 0; |
| 162 | @ <h2>Files of check-in [%z(href("vinfo?name=%T",zUuid))%s(zShort)</a>] |
| 163 | @ %s(blob_str(&dirname))</h2> |
| 164 | zSubdirLink = mprintf("%R/dir?ci=%S&name=%T", zUuid, zPrefix); |
| 165 | if( zD ){ |
| 166 | style_submenu_element("Top", "Top", "%R/dir?ci=%S", zUuid); |
| 167 | style_submenu_element("All", "All", "%R/dir?name=%t", zD); |
| 168 | }else{ |
| 169 | style_submenu_element("All", "All", "%R/dir"); |
| 170 | } |
| 171 | }else{ |
| 172 | int hasTrunk; |
| 173 | @ <h2>The union of all files from all check-ins |
| 174 | @ %s(blob_str(&dirname))</h2> |
| 175 | hasTrunk = db_exists( |
| 176 | "SELECT 1 FROM tagxref WHERE tagid=%d AND value='trunk'", |
| 177 | TAG_BRANCH); |
| 178 | zSubdirLink = mprintf("%R/dir?name=%T", zPrefix); |
| 179 | if( zD ){ |
| 180 | style_submenu_element("Top", "Top", "%R/dir"); |
| 181 | style_submenu_element("Tip", "Tip", "%R/dir?name=%t&ci=tip", zD); |
| 182 | if( hasTrunk ){ |
| 183 | style_submenu_element("Trunk", "Trunk", "%R/dir?name=%t&ci=trunk", |
| 184 | zD); |
| 185 | } |
| 186 | }else{ |
| 187 | style_submenu_element("Tip", "Tip", "%R/dir?ci=tip"); |
| 188 | if( hasTrunk ){ |
| 189 | style_submenu_element("Trunk", "Trunk", "%R/dir?ci=trunk"); |
| 190 | } |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | /* Compute the temporary table "localfiles" containing the names |
| @@ -278,19 +279,19 @@ | |
| 279 | } |
| 280 | i++; |
| 281 | zFN = db_column_text(&q, 0); |
| 282 | if( zFN[0]=='/' ){ |
| 283 | zFN++; |
| 284 | @ <li>%z(href("%s%T",zSubdirLink,zFN))%h(zFN)</a></li> |
| 285 | }else if( zCI ){ |
| 286 | const char *zUuid = db_column_text(&q, 1); |
| 287 | @ <li>%z(href("%R/artifact/%s",zUuid))%h(zFN)</a></li> |
| 288 | }else{ |
| 289 | @ <li>%z(href("%R/finfo?name=%T%T",zPrefix,zFN))%h(zFN) |
| 290 | @ </a></li> |
| 291 | } |
| 292 | } |
| 293 | db_finalize(&q); |
| 294 | manifest_destroy(pM); |
| 295 | @ </ul></td></tr></table> |
| 296 | style_footer(); |
| 297 | } |
| 298 |
+3
-3
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -1778,12 +1778,12 @@ | ||
| 1778 | 1778 | const char *zUuid = db_column_text(&q, 1); |
| 1779 | 1779 | const char *zDate = db_column_text(&q, 2); |
| 1780 | 1780 | const char *zUser = db_column_text(&q, 3); |
| 1781 | 1781 | if( webLabel ){ |
| 1782 | 1782 | zLabel = mprintf( |
| 1783 | - "<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %13.13s", | |
| 1784 | - g.zTop, zUuid, zUuid, zDate, zUser | |
| 1783 | + "<a href='%R/info/%s' target='infowindow'>%.10s</a> %s %13.13s", | |
| 1784 | + zUuid, zUuid, zDate, zUser | |
| 1785 | 1785 | ); |
| 1786 | 1786 | }else{ |
| 1787 | 1787 | zLabel = mprintf("%.10s %s %13.13s", zUuid, zDate, zUser); |
| 1788 | 1788 | } |
| 1789 | 1789 | p->nVers++; |
| @@ -1821,11 +1821,11 @@ | ||
| 1821 | 1821 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ |
| 1822 | 1822 | fossil_redirect_home(); |
| 1823 | 1823 | } |
| 1824 | 1824 | style_header("File Annotation"); |
| 1825 | 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 | 1827 | if( P("log") ){ |
| 1828 | 1828 | int i; |
| 1829 | 1829 | @ <h2>Versions analyzed:</h2> |
| 1830 | 1830 | @ <ol> |
| 1831 | 1831 | for(i=0; i<ann.nVers; i++){ |
| 1832 | 1832 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -1778,12 +1778,12 @@ | |
| 1778 | const char *zUuid = db_column_text(&q, 1); |
| 1779 | const char *zDate = db_column_text(&q, 2); |
| 1780 | const char *zUser = db_column_text(&q, 3); |
| 1781 | if( webLabel ){ |
| 1782 | zLabel = mprintf( |
| 1783 | "<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %13.13s", |
| 1784 | g.zTop, zUuid, zUuid, zDate, zUser |
| 1785 | ); |
| 1786 | }else{ |
| 1787 | zLabel = mprintf("%.10s %s %13.13s", zUuid, zDate, zUser); |
| 1788 | } |
| 1789 | p->nVers++; |
| @@ -1821,11 +1821,11 @@ | |
| 1821 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ |
| 1822 | fossil_redirect_home(); |
| 1823 | } |
| 1824 | style_header("File Annotation"); |
| 1825 | if( P("filevers") ) annFlags |= ANN_FILE_VERS; |
| 1826 | annotate_file(&ann, fnid, mid, g.perm.History, iLimit, annFlags); |
| 1827 | if( P("log") ){ |
| 1828 | int i; |
| 1829 | @ <h2>Versions analyzed:</h2> |
| 1830 | @ <ol> |
| 1831 | for(i=0; i<ann.nVers; i++){ |
| 1832 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -1778,12 +1778,12 @@ | |
| 1778 | const char *zUuid = db_column_text(&q, 1); |
| 1779 | const char *zDate = db_column_text(&q, 2); |
| 1780 | const char *zUser = db_column_text(&q, 3); |
| 1781 | if( webLabel ){ |
| 1782 | zLabel = mprintf( |
| 1783 | "<a href='%R/info/%s' target='infowindow'>%.10s</a> %s %13.13s", |
| 1784 | zUuid, zUuid, zDate, zUser |
| 1785 | ); |
| 1786 | }else{ |
| 1787 | zLabel = mprintf("%.10s %s %13.13s", zUuid, zDate, zUser); |
| 1788 | } |
| 1789 | p->nVers++; |
| @@ -1821,11 +1821,11 @@ | |
| 1821 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ |
| 1822 | fossil_redirect_home(); |
| 1823 | } |
| 1824 | style_header("File Annotation"); |
| 1825 | if( P("filevers") ) annFlags |= ANN_FILE_VERS; |
| 1826 | annotate_file(&ann, fnid, mid, g.perm.Hyperlink, iLimit, annFlags); |
| 1827 | if( P("log") ){ |
| 1828 | int i; |
| 1829 | @ <h2>Versions analyzed:</h2> |
| 1830 | @ <ol> |
| 1831 | for(i=0; i<ann.nVers; i++){ |
| 1832 |
+1
-1
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -541,11 +541,11 @@ | ||
| 541 | 541 | } |
| 542 | 542 | } |
| 543 | 543 | |
| 544 | 544 | /* |
| 545 | 545 | ** WEBPAGE: vpatch |
| 546 | -** URL vpatch?from=UUID&to=UUID | |
| 546 | +** URL vpatch?from=UUID&to=UUID | |
| 547 | 547 | */ |
| 548 | 548 | void vpatch_page(void){ |
| 549 | 549 | const char *zFrom = P("from"); |
| 550 | 550 | const char *zTo = P("to"); |
| 551 | 551 | login_check_credentials(); |
| 552 | 552 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -541,11 +541,11 @@ | |
| 541 | } |
| 542 | } |
| 543 | |
| 544 | /* |
| 545 | ** WEBPAGE: vpatch |
| 546 | ** URL vpatch?from=UUID&to=UUID |
| 547 | */ |
| 548 | void vpatch_page(void){ |
| 549 | const char *zFrom = P("from"); |
| 550 | const char *zTo = P("to"); |
| 551 | login_check_credentials(); |
| 552 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -541,11 +541,11 @@ | |
| 541 | } |
| 542 | } |
| 543 | |
| 544 | /* |
| 545 | ** WEBPAGE: vpatch |
| 546 | ** URL vpatch?from=UUID&to=UUID |
| 547 | */ |
| 548 | void vpatch_page(void){ |
| 549 | const char *zFrom = P("from"); |
| 550 | const char *zTo = P("to"); |
| 551 | login_check_credentials(); |
| 552 |
+10
-17
| --- src/event.c | ||
| +++ src/event.c | ||
| @@ -31,20 +31,13 @@ | ||
| 31 | 31 | /* |
| 32 | 32 | ** Output a hyperlink to an event given its tagid. |
| 33 | 33 | */ |
| 34 | 34 | void hyperlink_to_event_tagid(int tagid){ |
| 35 | 35 | char *zEventId; |
| 36 | - char zShort[12]; | |
| 37 | - | |
| 38 | 36 | zEventId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d", |
| 39 | 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 | 39 | free(zEventId); |
| 47 | 40 | } |
| 48 | 41 | |
| 49 | 42 | /* |
| 50 | 43 | ** WEBPAGE: event |
| @@ -130,47 +123,47 @@ | ||
| 130 | 123 | g.zTop, zEventId); |
| 131 | 124 | } |
| 132 | 125 | zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate); |
| 133 | 126 | style_submenu_element("Context", "Context", "%s/timeline?c=%T", |
| 134 | 127 | g.zTop, zETime); |
| 135 | - if( g.perm.History ){ | |
| 128 | + if( g.perm.Hyperlink ){ | |
| 136 | 129 | if( showDetail ){ |
| 137 | - style_submenu_element("Plain", "Plain", "%s/event?name=%s&aid=%s", | |
| 130 | + style_submenu_element("Plain", "Plain", "%s/event?name=%s&aid=%s", | |
| 138 | 131 | g.zTop, zEventId, zUuid); |
| 139 | 132 | if( nextRid ){ |
| 140 | 133 | char *zNext; |
| 141 | 134 | zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid); |
| 142 | 135 | style_submenu_element("Next", "Next", |
| 143 | - "%s/event?name=%s&aid=%s&detail=1", | |
| 136 | + "%s/event?name=%s&aid=%s&detail=1", | |
| 144 | 137 | g.zTop, zEventId, zNext); |
| 145 | 138 | free(zNext); |
| 146 | 139 | } |
| 147 | 140 | if( prevRid ){ |
| 148 | 141 | char *zPrev; |
| 149 | 142 | zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid); |
| 150 | 143 | style_submenu_element("Prev", "Prev", |
| 151 | - "%s/event?name=%s&aid=%s&detail=1", | |
| 144 | + "%s/event?name=%s&aid=%s&detail=1", | |
| 152 | 145 | g.zTop, zEventId, zPrev); |
| 153 | 146 | free(zPrev); |
| 154 | 147 | } |
| 155 | 148 | }else{ |
| 156 | 149 | style_submenu_element("Detail", "Detail", |
| 157 | - "%s/event?name=%s&aid=%s&detail=1", | |
| 150 | + "%s/event?name=%s&aid=%s&detail=1", | |
| 158 | 151 | g.zTop, zEventId, zUuid); |
| 159 | 152 | } |
| 160 | 153 | } |
| 161 | 154 | |
| 162 | - if( showDetail && g.perm.History ){ | |
| 155 | + if( showDetail && g.perm.Hyperlink ){ | |
| 163 | 156 | int i; |
| 164 | 157 | const char *zClr = 0; |
| 165 | 158 | Blob comment; |
| 166 | 159 | |
| 167 | 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 | |
| 169 | - @ [<a href="%s(g.zTop)/timeline?c=%T(zETime)">%s(zETime)</a>] | |
| 161 | + @ <p>Event [%z(href("%R/artifact/%s",zUuid))%S(zUuid)</a>] at | |
| 162 | + @ [%z(href("%R/timeline?c=%T",zETime))%s(zETime)</a>] | |
| 170 | 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 | 165 | @ <blockquote> |
| 173 | 166 | for(i=0; i<pEvent->nTag; i++){ |
| 174 | 167 | if( fossil_strcmp(pEvent->aTag[i].zName,"+bgcolor")==0 ){ |
| 175 | 168 | zClr = pEvent->aTag[i].zValue; |
| 176 | 169 | } |
| 177 | 170 |
| --- src/event.c | |
| +++ src/event.c | |
| @@ -31,20 +31,13 @@ | |
| 31 | /* |
| 32 | ** Output a hyperlink to an event given its tagid. |
| 33 | */ |
| 34 | void hyperlink_to_event_tagid(int tagid){ |
| 35 | char *zEventId; |
| 36 | char zShort[12]; |
| 37 | |
| 38 | zEventId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d", |
| 39 | tagid); |
| 40 | sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zEventId); |
| 41 | if( g.perm.History ){ |
| 42 | @ [<a href="%s(g.zTop)/event?name=%s(zEventId)">%s(zShort)</a>] |
| 43 | }else{ |
| 44 | @ [%s(zShort)] |
| 45 | } |
| 46 | free(zEventId); |
| 47 | } |
| 48 | |
| 49 | /* |
| 50 | ** WEBPAGE: event |
| @@ -130,47 +123,47 @@ | |
| 130 | g.zTop, zEventId); |
| 131 | } |
| 132 | zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate); |
| 133 | style_submenu_element("Context", "Context", "%s/timeline?c=%T", |
| 134 | g.zTop, zETime); |
| 135 | if( g.perm.History ){ |
| 136 | if( showDetail ){ |
| 137 | style_submenu_element("Plain", "Plain", "%s/event?name=%s&aid=%s", |
| 138 | g.zTop, zEventId, zUuid); |
| 139 | if( nextRid ){ |
| 140 | char *zNext; |
| 141 | zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid); |
| 142 | style_submenu_element("Next", "Next", |
| 143 | "%s/event?name=%s&aid=%s&detail=1", |
| 144 | g.zTop, zEventId, zNext); |
| 145 | free(zNext); |
| 146 | } |
| 147 | if( prevRid ){ |
| 148 | char *zPrev; |
| 149 | zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid); |
| 150 | style_submenu_element("Prev", "Prev", |
| 151 | "%s/event?name=%s&aid=%s&detail=1", |
| 152 | g.zTop, zEventId, zPrev); |
| 153 | free(zPrev); |
| 154 | } |
| 155 | }else{ |
| 156 | style_submenu_element("Detail", "Detail", |
| 157 | "%s/event?name=%s&aid=%s&detail=1", |
| 158 | g.zTop, zEventId, zUuid); |
| 159 | } |
| 160 | } |
| 161 | |
| 162 | if( showDetail && g.perm.History ){ |
| 163 | int i; |
| 164 | const char *zClr = 0; |
| 165 | Blob comment; |
| 166 | |
| 167 | zATime = db_text(0, "SELECT datetime(%.17g)", pEvent->rDate); |
| 168 | @ <p>Event [<a href="%s(g.zTop)/artifact/%s(zUuid)">%S(zUuid)</a>] at |
| 169 | @ [<a href="%s(g.zTop)/timeline?c=%T(zETime)">%s(zETime)</a>] |
| 170 | @ entered by user <b>%h(pEvent->zUser)</b> on |
| 171 | @ [<a href="%s(g.zTop)/timeline?c=%T(zATime)">%s(zATime)</a>]:</p> |
| 172 | @ <blockquote> |
| 173 | for(i=0; i<pEvent->nTag; i++){ |
| 174 | if( fossil_strcmp(pEvent->aTag[i].zName,"+bgcolor")==0 ){ |
| 175 | zClr = pEvent->aTag[i].zValue; |
| 176 | } |
| 177 |
| --- src/event.c | |
| +++ src/event.c | |
| @@ -31,20 +31,13 @@ | |
| 31 | /* |
| 32 | ** Output a hyperlink to an event given its tagid. |
| 33 | */ |
| 34 | void hyperlink_to_event_tagid(int tagid){ |
| 35 | char *zEventId; |
| 36 | zEventId = db_text(0, "SELECT substr(tagname, 7) FROM tag WHERE tagid=%d", |
| 37 | tagid); |
| 38 | @ [%z(href("%R/event/%s",zEventId))%S(zEventId)</a>] |
| 39 | free(zEventId); |
| 40 | } |
| 41 | |
| 42 | /* |
| 43 | ** WEBPAGE: event |
| @@ -130,47 +123,47 @@ | |
| 123 | g.zTop, zEventId); |
| 124 | } |
| 125 | zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate); |
| 126 | style_submenu_element("Context", "Context", "%s/timeline?c=%T", |
| 127 | g.zTop, zETime); |
| 128 | if( g.perm.Hyperlink ){ |
| 129 | if( showDetail ){ |
| 130 | style_submenu_element("Plain", "Plain", "%s/event?name=%s&aid=%s", |
| 131 | g.zTop, zEventId, zUuid); |
| 132 | if( nextRid ){ |
| 133 | char *zNext; |
| 134 | zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid); |
| 135 | style_submenu_element("Next", "Next", |
| 136 | "%s/event?name=%s&aid=%s&detail=1", |
| 137 | g.zTop, zEventId, zNext); |
| 138 | free(zNext); |
| 139 | } |
| 140 | if( prevRid ){ |
| 141 | char *zPrev; |
| 142 | zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid); |
| 143 | style_submenu_element("Prev", "Prev", |
| 144 | "%s/event?name=%s&aid=%s&detail=1", |
| 145 | g.zTop, zEventId, zPrev); |
| 146 | free(zPrev); |
| 147 | } |
| 148 | }else{ |
| 149 | style_submenu_element("Detail", "Detail", |
| 150 | "%s/event?name=%s&aid=%s&detail=1", |
| 151 | g.zTop, zEventId, zUuid); |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | if( showDetail && g.perm.Hyperlink ){ |
| 156 | int i; |
| 157 | const char *zClr = 0; |
| 158 | Blob comment; |
| 159 | |
| 160 | zATime = db_text(0, "SELECT datetime(%.17g)", pEvent->rDate); |
| 161 | @ <p>Event [%z(href("%R/artifact/%s",zUuid))%S(zUuid)</a>] at |
| 162 | @ [%z(href("%R/timeline?c=%T",zETime))%s(zETime)</a>] |
| 163 | @ entered by user <b>%h(pEvent->zUser)</b> on |
| 164 | @ [%z(href("%R/timeline?c=%T",zATime))%s(zATime)</a>]:</p> |
| 165 | @ <blockquote> |
| 166 | for(i=0; i<pEvent->nTag; i++){ |
| 167 | if( fossil_strcmp(pEvent->aTag[i].zName,"+bgcolor")==0 ){ |
| 168 | zClr = pEvent->aTag[i].zValue; |
| 169 | } |
| 170 |
+5
-10
| --- src/finfo.c | ||
| +++ src/finfo.c | ||
| @@ -305,39 +305,34 @@ | ||
| 305 | 305 | @ </td></tr> |
| 306 | 306 | } |
| 307 | 307 | memcpy(zTime, &zDate[11], 5); |
| 308 | 308 | zTime[5] = 0; |
| 309 | 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 | 311 | @ <td class="timelineGraph"><div id="m%d(gidx)"></div></td> |
| 312 | 312 | if( zBgClr && zBgClr[0] ){ |
| 313 | 313 | @ <td class="timelineTableCell" style="background-color: %h(zBgClr);"> |
| 314 | 314 | }else{ |
| 315 | 315 | @ <td class="timelineTableCell"> |
| 316 | 316 | } |
| 317 | 317 | sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid); |
| 318 | 318 | sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin); |
| 319 | 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 | 321 | }else{ |
| 327 | 322 | @ <b>Deleted</b> by check-in |
| 328 | 323 | } |
| 329 | 324 | hyperlink_to_uuid(zShortCkin); |
| 330 | 325 | @ %h(zCom) (user: |
| 331 | 326 | hyperlink_to_user(zUser, zDate, ""); |
| 332 | 327 | @ branch: %h(zBr)) |
| 333 | - if( g.perm.History && zUuid ){ | |
| 328 | + if( g.perm.Hyperlink && zUuid ){ | |
| 334 | 329 | const char *z = zFilename; |
| 335 | 330 | if( fpid ){ |
| 336 | - @ <a href="%s(g.zTop)/fdiff?v1=%s(zPUuid)&v2=%s(zUuid)">[diff]</a> | |
| 331 | + @ %z(href("%R/fdiff?v1=%s&v2=%s",zPUuid,zUuid))[diff]</a> | |
| 337 | 332 | } |
| 338 | - @ <a href="%s(g.zTop)/annotate?checkin=%S(zCkin)&filename=%h(z)"> | |
| 333 | + @ %z(href("%R/annotate?checkin=%S&filename=%h",zCkin,z)) | |
| 339 | 334 | @ [annotate]</a> |
| 340 | 335 | } |
| 341 | 336 | @ </td></tr> |
| 342 | 337 | } |
| 343 | 338 | db_finalize(&q); |
| 344 | 339 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -305,39 +305,34 @@ | |
| 305 | @ </td></tr> |
| 306 | } |
| 307 | memcpy(zTime, &zDate[11], 5); |
| 308 | zTime[5] = 0; |
| 309 | @ <tr><td class="timelineTime"> |
| 310 | @ <a href="%s(g.zTop)/timeline?c=%t(zDate)">%s(zTime)</a></td> |
| 311 | @ <td class="timelineGraph"><div id="m%d(gidx)"></div></td> |
| 312 | if( zBgClr && zBgClr[0] ){ |
| 313 | @ <td class="timelineTableCell" style="background-color: %h(zBgClr);"> |
| 314 | }else{ |
| 315 | @ <td class="timelineTableCell"> |
| 316 | } |
| 317 | sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid); |
| 318 | sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin); |
| 319 | if( zUuid ){ |
| 320 | if( g.perm.History ){ |
| 321 | @ <a href="%s(g.zTop)/artifact/%s(zUuid)">[%S(zUuid)]</a> |
| 322 | }else{ |
| 323 | @ [%S(zUuid)] |
| 324 | } |
| 325 | @ part of check-in |
| 326 | }else{ |
| 327 | @ <b>Deleted</b> by check-in |
| 328 | } |
| 329 | hyperlink_to_uuid(zShortCkin); |
| 330 | @ %h(zCom) (user: |
| 331 | hyperlink_to_user(zUser, zDate, ""); |
| 332 | @ branch: %h(zBr)) |
| 333 | if( g.perm.History && zUuid ){ |
| 334 | const char *z = zFilename; |
| 335 | if( fpid ){ |
| 336 | @ <a href="%s(g.zTop)/fdiff?v1=%s(zPUuid)&v2=%s(zUuid)">[diff]</a> |
| 337 | } |
| 338 | @ <a href="%s(g.zTop)/annotate?checkin=%S(zCkin)&filename=%h(z)"> |
| 339 | @ [annotate]</a> |
| 340 | } |
| 341 | @ </td></tr> |
| 342 | } |
| 343 | db_finalize(&q); |
| 344 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -305,39 +305,34 @@ | |
| 305 | @ </td></tr> |
| 306 | } |
| 307 | memcpy(zTime, &zDate[11], 5); |
| 308 | zTime[5] = 0; |
| 309 | @ <tr><td class="timelineTime"> |
| 310 | @ %z(href("%R/timeline?c=%t",zDate))%s(zTime)</a></td> |
| 311 | @ <td class="timelineGraph"><div id="m%d(gidx)"></div></td> |
| 312 | if( zBgClr && zBgClr[0] ){ |
| 313 | @ <td class="timelineTableCell" style="background-color: %h(zBgClr);"> |
| 314 | }else{ |
| 315 | @ <td class="timelineTableCell"> |
| 316 | } |
| 317 | sqlite3_snprintf(sizeof(zShort), zShort, "%.10s", zUuid); |
| 318 | sqlite3_snprintf(sizeof(zShortCkin), zShortCkin, "%.10s", zCkin); |
| 319 | if( zUuid ){ |
| 320 | @ %z(href("%R/artifact/%s",zUuid))[%S(zUuid)]</a> part of check-in |
| 321 | }else{ |
| 322 | @ <b>Deleted</b> by check-in |
| 323 | } |
| 324 | hyperlink_to_uuid(zShortCkin); |
| 325 | @ %h(zCom) (user: |
| 326 | hyperlink_to_user(zUser, zDate, ""); |
| 327 | @ branch: %h(zBr)) |
| 328 | if( g.perm.Hyperlink && zUuid ){ |
| 329 | const char *z = zFilename; |
| 330 | if( fpid ){ |
| 331 | @ %z(href("%R/fdiff?v1=%s&v2=%s",zPUuid,zUuid))[diff]</a> |
| 332 | } |
| 333 | @ %z(href("%R/annotate?checkin=%S&filename=%h",zCkin,z)) |
| 334 | @ [annotate]</a> |
| 335 | } |
| 336 | @ </td></tr> |
| 337 | } |
| 338 | db_finalize(&q); |
| 339 |
+65
-80
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -261,11 +261,11 @@ | ||
| 261 | 261 | @ propagates to descendants |
| 262 | 262 | } |
| 263 | 263 | #if 0 |
| 264 | 264 | if( zValue && fossil_strcmp(zTagname,"branch")==0 ){ |
| 265 | 265 | @ |
| 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 | 268 | #endif |
| 269 | 269 | } |
| 270 | 270 | if( zSrcUuid && zSrcUuid[0] ){ |
| 271 | 271 | if( tagtype==0 ){ |
| @@ -333,11 +333,11 @@ | ||
| 333 | 333 | const char *zNew, /* blob.uuid after change. NULL for deletes */ |
| 334 | 334 | const char *zOldName, /* Prior name. NULL if no name change. */ |
| 335 | 335 | int diffFlags, /* Flags for text_diff(). Zero to omit diffs */ |
| 336 | 336 | int mperm /* executable or symlink permission for zNew */ |
| 337 | 337 | ){ |
| 338 | - if( !g.perm.History ){ | |
| 338 | + if( !g.perm.Hyperlink ){ | |
| 339 | 339 | if( zNew==0 ){ |
| 340 | 340 | @ <p>Deleted %h(zName)</p> |
| 341 | 341 | }else if( zOld==0 ){ |
| 342 | 342 | @ <p>Added %h(zName)</p> |
| 343 | 343 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| @@ -354,35 +354,35 @@ | ||
| 354 | 354 | @ </pre> |
| 355 | 355 | } |
| 356 | 356 | }else{ |
| 357 | 357 | if( zOld && zNew ){ |
| 358 | 358 | if( fossil_strcmp(zOld, zNew)!=0 ){ |
| 359 | - @ <p>Modified <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> | |
| 360 | - @ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a> | |
| 361 | - @ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a> | |
| 359 | + @ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a> | |
| 360 | + @ from %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a> | |
| 361 | + @ to %z(href("%R/artifact/%s",zNew))[%S(zNew)].</a> | |
| 362 | 362 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| 363 | 363 | @ <p>Name change from |
| 364 | - @ from <a href="%s(g.zTop)/finfo?name=%T(zOldName)">%h(zOldName)</a> | |
| 365 | - @ to <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>. | |
| 364 | + @ from %z(href("%R/finfo?name=%T",zOldName))%h(zOldName)</a> | |
| 365 | + @ to %z(href("%R/finfo?name=%T",zName))%h(zName)</a>. | |
| 366 | 366 | }else{ |
| 367 | 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 | 370 | }else if( zOld ){ |
| 371 | - @ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> | |
| 372 | - @ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a> | |
| 371 | + @ <p>Deleted %z(href("%s/finfo?name=%T",g.zTop,zName))%h(zName)</a> | |
| 372 | + @ version %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a> | |
| 373 | 373 | }else{ |
| 374 | - @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> | |
| 375 | - @ version <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)]</a> | |
| 374 | + @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> | |
| 375 | + @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a> | |
| 376 | 376 | } |
| 377 | 377 | if( diffFlags ){ |
| 378 | 378 | @ <pre style="white-space:pre;"> |
| 379 | 379 | append_diff(zOld, zNew, diffFlags); |
| 380 | 380 | @ </pre> |
| 381 | 381 | }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ |
| 382 | 382 | @ |
| 383 | - @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)">[diff]</a> | |
| 383 | + @ %z(href("%R/fdiff?v1=%S&v2=%S",zOld,zNew))[diff]</a> | |
| 384 | 384 | } |
| 385 | 385 | @ </p> |
| 386 | 386 | } |
| 387 | 387 | } |
| 388 | 388 | |
| @@ -535,47 +535,47 @@ | ||
| 535 | 535 | @ <tr><th>Received From:</th> |
| 536 | 536 | @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr> |
| 537 | 537 | } |
| 538 | 538 | db_finalize(&q); |
| 539 | 539 | } |
| 540 | - if( g.perm.History ){ | |
| 540 | + if( g.perm.Hyperlink ){ | |
| 541 | 541 | const char *zProjName = db_get("project-name", "unnamed"); |
| 542 | 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 | 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 | 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 | 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 | 553 | db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag " |
| 554 | 554 | " WHERE rid=%d AND tagtype>0 " |
| 555 | 555 | " AND tag.tagid=tagxref.tagid " |
| 556 | 556 | " AND +tag.tagname GLOB 'sym-*'", rid); |
| 557 | 557 | while( db_step(&q)==SQLITE_ROW ){ |
| 558 | 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 | 561 | db_finalize(&q); |
| 562 | 562 | @ </td></tr> |
| 563 | 563 | @ <tr><th>Other Links:</th> |
| 564 | 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 | 566 | if( g.perm.Zip ){ |
| 567 | - char *zUrl = mprintf("%s/tarball/%s-%S.tar.gz?uuid=%s", | |
| 568 | - g.zTop, zProjName, zUuid, zUuid); | |
| 569 | - @ | <a href="%s(zUrl)">Tarball</a> | |
| 570 | - @ | <a href="%s(g.zTop)/zip/%s(zProjName)-%S(zUuid).zip?uuid=%s(zUuid)"> | |
| 567 | + char *zUrl = mprintf("%R/tarball/%s-%S.tar.gz?uuid=%s", | |
| 568 | + zProjName, zUuid, zUuid); | |
| 569 | + @ | %z(href("%s",zUrl))Tarball</a> | |
| 570 | + @ | %z(href("%R/zip/%s-%S.zip?uuid=%s",zProjName,zUuid,zUuid)) | |
| 571 | 571 | @ ZIP archive</a> |
| 572 | 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 | 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 | 578 | @ </td> |
| 579 | 579 | @ </tr> |
| 580 | 580 | } |
| 581 | 581 | @ </table> |
| @@ -590,43 +590,43 @@ | ||
| 590 | 590 | @ <div class="sectionmenu"> |
| 591 | 591 | showDiff = g.zPath[0]!='c'; |
| 592 | 592 | if( db_get_boolean("show-version-diffs", 0)==0 ){ |
| 593 | 593 | showDiff = !showDiff; |
| 594 | 594 | if( showDiff ){ |
| 595 | - @ <a class="button" href="%s(g.zTop)/vinfo/%T(zName)"> | |
| 595 | + @ %z(xhref("class='button'","%R/vinfo/%T",zName))) | |
| 596 | 596 | @ hide diffs</a> |
| 597 | 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 | 599 | @ unified diffs</a> |
| 600 | 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 | 602 | @ side-by-side diffs</a> |
| 603 | 603 | } |
| 604 | 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 | 606 | @ show unified 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 | 608 | @ show side-by-side diffs</a> |
| 609 | 609 | } |
| 610 | 610 | }else{ |
| 611 | 611 | if( showDiff ){ |
| 612 | - @ <a class="button" href="%s(g.zTop)/ci/%T(zName)">hide diffs</a> | |
| 612 | + @ %z(xhref("class='button'","%R/ci/%T",zName))hide diffs</a> | |
| 613 | 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 | 615 | @ unified diffs</a> |
| 616 | 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 | 618 | @ side-by-side diffs</a> |
| 619 | 619 | } |
| 620 | 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 | 622 | @ show unified 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 | 624 | @ show side-by-side 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&to=%S",zParent,zUuid)) | |
| 628 | 628 | @ patch</a></div> |
| 629 | 629 | db_prepare(&q, |
| 630 | 630 | "SELECT name," |
| 631 | 631 | " mperm," |
| 632 | 632 | " (SELECT uuid FROM blob WHERE rid=mlink.pid)," |
| @@ -698,15 +698,15 @@ | ||
| 698 | 698 | if( g.perm.Setup ){ |
| 699 | 699 | @ <tr><th>Record ID:</th><td>%d(rid)</td></tr> |
| 700 | 700 | } |
| 701 | 701 | @ <tr><th>Original User:</th><td> |
| 702 | 702 | hyperlink_to_user(zUser, zDate, "</td></tr>"); |
| 703 | - if( g.perm.History ){ | |
| 703 | + if( g.perm.Hyperlink ){ | |
| 704 | 704 | @ <tr><th>Commands:</th> |
| 705 | 705 | @ <td> |
| 706 | - @ <a href="%s(g.zTop)/whistory?name=%t(zName)">history</a> | |
| 707 | - @ | <a href="%s(g.zTop)/artifact/%S(zUuid)">raw-text</a> | |
| 706 | + @ &z(href("%R/whistory?name=%t",zName))history</a> | |
| 707 | + @ | %z(href("%R/artifact/%S",zUuid))raw-text</a> | |
| 708 | 708 | @ </td> |
| 709 | 709 | @ </tr> |
| 710 | 710 | } |
| 711 | 711 | @ </table></p> |
| 712 | 712 | }else{ |
| @@ -792,11 +792,11 @@ | ||
| 792 | 792 | } |
| 793 | 793 | |
| 794 | 794 | |
| 795 | 795 | /* |
| 796 | 796 | ** WEBPAGE: vdiff |
| 797 | -** URL: /vdiff?from=UUID&to=UUID&detail=BOOLEAN;sbs=BOOLEAN | |
| 797 | +** URL: /vdiff?from=UUID&to=UUID&detail=BOOLEAN;sbs=BOOLEAN | |
| 798 | 798 | ** |
| 799 | 799 | ** Show all differences between two checkins. |
| 800 | 800 | */ |
| 801 | 801 | void vdiff_page(void){ |
| 802 | 802 | int ridFrom, ridTo; |
| @@ -936,34 +936,26 @@ | ||
| 936 | 936 | }else if( mPerm==PERM_EXE ){ |
| 937 | 937 | @ <li>Executable file |
| 938 | 938 | }else{ |
| 939 | 939 | @ <li>File |
| 940 | 940 | } |
| 941 | - if( g.perm.History ){ | |
| 942 | - @ <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> | |
| 943 | - }else{ | |
| 944 | - @ %h(zName) | |
| 945 | - } | |
| 941 | + @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> | |
| 946 | 942 | @ <ul> |
| 947 | 943 | prevName = fossil_strdup(zName); |
| 948 | 944 | } |
| 949 | 945 | @ <li> |
| 950 | 946 | hyperlink_to_date(zDate,""); |
| 951 | 947 | @ - part of checkin |
| 952 | 948 | hyperlink_to_uuid(zVers); |
| 953 | 949 | if( zBr && zBr[0] ){ |
| 954 | - if( g.perm.History ){ | |
| 955 | - @ on branch <a href="%s(g.zTop)/timeline?r=%T(zBr)">%h(zBr)</a> | |
| 956 | - }else{ | |
| 957 | - @ on branch %h(zBr) | |
| 958 | - } | |
| 950 | + @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a> | |
| 959 | 951 | } |
| 960 | 952 | @ - %w(zCom) (user: |
| 961 | 953 | hyperlink_to_user(zUser,zDate,""); |
| 962 | 954 | @ ) |
| 963 | - if( g.perm.History ){ | |
| 964 | - @ <a href="%s(g.zTop)/annotate?checkin=%S(zVers)&filename=%T(zName)"> | |
| 955 | + if( g.perm.Hyperlink ){ | |
| 956 | + @ %z(href("%R/annotate?checkin=%S&filename=%T",zVers,zName)) | |
| 965 | 957 | @ [annotate]</a> |
| 966 | 958 | } |
| 967 | 959 | cnt++; |
| 968 | 960 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 969 | 961 | blob_append(pDownloadName, zName, -1); |
| @@ -989,16 +981,11 @@ | ||
| 989 | 981 | if( cnt>0 ){ |
| 990 | 982 | @ Also wiki page |
| 991 | 983 | }else{ |
| 992 | 984 | @ Wiki page |
| 993 | 985 | } |
| 994 | - if( g.perm.History ){ | |
| 995 | - @ [<a href="%s(g.zTop)/wiki?name=%t(zPagename)">%h(zPagename)</a>] | |
| 996 | - }else{ | |
| 997 | - @ [%h(zPagename)] | |
| 998 | - } | |
| 999 | - @ by | |
| 986 | + @ [%z(href("%R/wiki?name=%t",zPagename))%h(zPagename)</a>] by | |
| 1000 | 987 | hyperlink_to_user(zUser,zDate," on"); |
| 1001 | 988 | hyperlink_to_date(zDate,"."); |
| 1002 | 989 | nWiki++; |
| 1003 | 990 | cnt++; |
| 1004 | 991 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| @@ -1065,18 +1052,18 @@ | ||
| 1065 | 1052 | @ Also attachment "%h(zFilename)" to |
| 1066 | 1053 | }else{ |
| 1067 | 1054 | @ Attachment "%h(zFilename)" to |
| 1068 | 1055 | } |
| 1069 | 1056 | if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){ |
| 1070 | - if( g.perm.History && g.perm.RdTkt ){ | |
| 1071 | - @ ticket [<a href="%s(g.zTop)/tktview?name=%S(zTarget)">%S(zTarget)</a>] | |
| 1057 | + if( g.perm.Hyperlink && g.perm.RdTkt ){ | |
| 1058 | + @ ticket [%z(href("%R/tktview?name=%S",zTarget))%S(zTarget)</a>] | |
| 1072 | 1059 | }else{ |
| 1073 | 1060 | @ ticket [%S(zTarget)] |
| 1074 | 1061 | } |
| 1075 | 1062 | }else{ |
| 1076 | - if( g.perm.History && g.perm.RdWiki ){ | |
| 1077 | - @ wiki page [<a href="%s(g.zTop)/wiki?name=%t(zTarget)">%h(zTarget)</a>] | |
| 1063 | + if( g.perm.Hyperlink && g.perm.RdWiki ){ | |
| 1064 | + @ wiki page [%z(href("%R/wiki?name=%t",zTarget)))%h(zTarget)</a>] | |
| 1078 | 1065 | }else{ |
| 1079 | 1066 | @ wiki page [%h(zTarget)] |
| 1080 | 1067 | } |
| 1081 | 1068 | } |
| 1082 | 1069 | @ added by |
| @@ -1091,12 +1078,12 @@ | ||
| 1091 | 1078 | if( cnt==0 ){ |
| 1092 | 1079 | @ Control artifact. |
| 1093 | 1080 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 1094 | 1081 | blob_appendf(pDownloadName, "%.10s.txt", zUuid); |
| 1095 | 1082 | } |
| 1096 | - }else if( linkToView && g.perm.History ){ | |
| 1097 | - @ <a href="%s(g.zTop)/artifact/%S(zUuid)">[view]</a> | |
| 1083 | + }else if( linkToView && g.perm.Hyperlink ){ | |
| 1084 | + @ %z(href("%R/artifact/%S",zUuid))[view]</a> | |
| 1098 | 1085 | } |
| 1099 | 1086 | } |
| 1100 | 1087 | |
| 1101 | 1088 | |
| 1102 | 1089 | /* |
| @@ -1160,18 +1147,17 @@ | ||
| 1160 | 1147 | g.zTop, P("v1"), P("v2")); |
| 1161 | 1148 | } |
| 1162 | 1149 | |
| 1163 | 1150 | if( P("smhdr")!=0 ){ |
| 1164 | 1151 | @ <h2>Differences From Artifact |
| 1165 | - @ <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a> To | |
| 1166 | - @ <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>.</h2> | |
| 1152 | + @ %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a> To | |
| 1153 | + @ %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>.</h2> | |
| 1167 | 1154 | }else{ |
| 1168 | 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 | 1157 | object_description(v1, 0, 0); |
| 1171 | - @ <h2>To Artifact | |
| 1172 | - @ <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>:</h2> | |
| 1158 | + @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2> | |
| 1173 | 1159 | object_description(v2, 0, 0); |
| 1174 | 1160 | } |
| 1175 | 1161 | @ <hr /> |
| 1176 | 1162 | @ <div class="%s(zStyle)"> |
| 1177 | 1163 | @ %s(blob_str(&diff)) |
| @@ -1272,11 +1258,11 @@ | ||
| 1272 | 1258 | if( !g.perm.Read ){ login_needed(); return; } |
| 1273 | 1259 | if( rid==0 ) fossil_redirect_home(); |
| 1274 | 1260 | if( g.perm.Admin ){ |
| 1275 | 1261 | const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1276 | 1262 | if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ |
| 1277 | - style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", | |
| 1263 | + style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", | |
| 1278 | 1264 | g.zTop, zUuid); |
| 1279 | 1265 | }else{ |
| 1280 | 1266 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1281 | 1267 | g.zTop, zUuid); |
| 1282 | 1268 | } |
| @@ -1419,11 +1405,11 @@ | ||
| 1419 | 1405 | if( !g.perm.Read ){ login_needed(); return; } |
| 1420 | 1406 | if( rid==0 ) fossil_redirect_home(); |
| 1421 | 1407 | if( g.perm.Admin ){ |
| 1422 | 1408 | const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1423 | 1409 | if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ |
| 1424 | - style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", | |
| 1410 | + style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", | |
| 1425 | 1411 | g.zTop, zUuid); |
| 1426 | 1412 | }else{ |
| 1427 | 1413 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1428 | 1414 | g.zTop, zUuid); |
| 1429 | 1415 | } |
| @@ -1478,11 +1464,11 @@ | ||
| 1478 | 1464 | @ <pre> |
| 1479 | 1465 | @ %h(z) |
| 1480 | 1466 | @ </pre> |
| 1481 | 1467 | } |
| 1482 | 1468 | }else if( strncmp(zMime, "image/", 6)==0 ){ |
| 1483 | - @ <img src="%s(g.zTop)/raw?name=%s(zUuid)&m=%s(zMime)"></img> | |
| 1469 | + @ <img src="%s(g.zTop)/raw?name=%s(zUuid)&m=%s(zMime)"></img> | |
| 1484 | 1470 | }else{ |
| 1485 | 1471 | @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i> |
| 1486 | 1472 | } |
| 1487 | 1473 | @ </blockquote> |
| 1488 | 1474 | } |
| @@ -1507,11 +1493,11 @@ | ||
| 1507 | 1493 | rid = name_to_rid_www("name"); |
| 1508 | 1494 | if( rid==0 ){ fossil_redirect_home(); } |
| 1509 | 1495 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1510 | 1496 | if( g.perm.Admin ){ |
| 1511 | 1497 | if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ |
| 1512 | - style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", | |
| 1498 | + style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", | |
| 1513 | 1499 | g.zTop, zUuid); |
| 1514 | 1500 | }else{ |
| 1515 | 1501 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1516 | 1502 | g.zTop, zUuid); |
| 1517 | 1503 | } |
| @@ -1522,18 +1508,17 @@ | ||
| 1522 | 1508 | } |
| 1523 | 1509 | style_header("Ticket Change Details"); |
| 1524 | 1510 | zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate); |
| 1525 | 1511 | memcpy(zTktName, pTktChng->zTicketUuid, 10); |
| 1526 | 1512 | zTktName[10] = 0; |
| 1527 | - if( g.perm.History ){ | |
| 1513 | + if( g.perm.Hyperlink ){ | |
| 1528 | 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 | 1517 | @ <p>By %h(pTktChng->zUser) on %s(zDate). See also: |
| 1532 | - @ <a href="%s(g.zTop)/artifact/%T(zUuid)">artifact content</a>, and | |
| 1533 | - @ <a href="%s(g.zTop)/tkthistory/%s(pTktChng->zTicketUuid)">ticket | |
| 1534 | - @ history</a></p> | |
| 1518 | + @ %z(href("%R/artifact/%T",zUuid))artifact content</a>, and | |
| 1519 | + @ %z(href("%R/tkthistory/%s",pTktChng->zTicketUuid))ticket history</a></p> | |
| 1535 | 1520 | }else{ |
| 1536 | 1521 | @ <h2>Changes to ticket %s(zTktName)</h2> |
| 1537 | 1522 | @ |
| 1538 | 1523 | @ <p>By %h(pTktChng->zUser) on %s(zDate). |
| 1539 | 1524 | @ </p> |
| @@ -1965,11 +1950,11 @@ | ||
| 1965 | 1950 | @ </blockquote> |
| 1966 | 1951 | @ <hr /> |
| 1967 | 1952 | blob_reset(&suffix); |
| 1968 | 1953 | } |
| 1969 | 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 | 1956 | @ <form action="%s(g.zTop)/ci_edit" method="post"><div> |
| 1972 | 1957 | login_insert_csrf_secret(); |
| 1973 | 1958 | @ <input type="hidden" name="r" value="%S(zUuid)" /> |
| 1974 | 1959 | @ <table border="0" cellspacing="10"> |
| 1975 | 1960 | |
| 1976 | 1961 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -261,11 +261,11 @@ | |
| 261 | @ propagates to descendants |
| 262 | } |
| 263 | #if 0 |
| 264 | if( zValue && fossil_strcmp(zTagname,"branch")==0 ){ |
| 265 | @ |
| 266 | @ <a href="%s(g.zTop)/timeline?r=%T(zValue)">branch timeline</a> |
| 267 | } |
| 268 | #endif |
| 269 | } |
| 270 | if( zSrcUuid && zSrcUuid[0] ){ |
| 271 | if( tagtype==0 ){ |
| @@ -333,11 +333,11 @@ | |
| 333 | const char *zNew, /* blob.uuid after change. NULL for deletes */ |
| 334 | const char *zOldName, /* Prior name. NULL if no name change. */ |
| 335 | int diffFlags, /* Flags for text_diff(). Zero to omit diffs */ |
| 336 | int mperm /* executable or symlink permission for zNew */ |
| 337 | ){ |
| 338 | if( !g.perm.History ){ |
| 339 | if( zNew==0 ){ |
| 340 | @ <p>Deleted %h(zName)</p> |
| 341 | }else if( zOld==0 ){ |
| 342 | @ <p>Added %h(zName)</p> |
| 343 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| @@ -354,35 +354,35 @@ | |
| 354 | @ </pre> |
| 355 | } |
| 356 | }else{ |
| 357 | if( zOld && zNew ){ |
| 358 | if( fossil_strcmp(zOld, zNew)!=0 ){ |
| 359 | @ <p>Modified <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> |
| 360 | @ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a> |
| 361 | @ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a> |
| 362 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| 363 | @ <p>Name change from |
| 364 | @ from <a href="%s(g.zTop)/finfo?name=%T(zOldName)">%h(zOldName)</a> |
| 365 | @ to <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a>. |
| 366 | }else{ |
| 367 | @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for |
| 368 | @ <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> |
| 369 | } |
| 370 | }else if( zOld ){ |
| 371 | @ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> |
| 372 | @ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a> |
| 373 | }else{ |
| 374 | @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> |
| 375 | @ version <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)]</a> |
| 376 | } |
| 377 | if( diffFlags ){ |
| 378 | @ <pre style="white-space:pre;"> |
| 379 | append_diff(zOld, zNew, diffFlags); |
| 380 | @ </pre> |
| 381 | }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ |
| 382 | @ |
| 383 | @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)">[diff]</a> |
| 384 | } |
| 385 | @ </p> |
| 386 | } |
| 387 | } |
| 388 | |
| @@ -535,47 +535,47 @@ | |
| 535 | @ <tr><th>Received From:</th> |
| 536 | @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr> |
| 537 | } |
| 538 | db_finalize(&q); |
| 539 | } |
| 540 | if( g.perm.History ){ |
| 541 | const char *zProjName = db_get("project-name", "unnamed"); |
| 542 | @ <tr><th>Timelines:</th><td> |
| 543 | @ <a href="%s(g.zTop)/timeline?f=%S(zUuid)">family</a> |
| 544 | if( zParent ){ |
| 545 | @ | <a href="%s(g.zTop)/timeline?p=%S(zUuid)">ancestors</a> |
| 546 | } |
| 547 | if( !isLeaf ){ |
| 548 | @ | <a href="%s(g.zTop)/timeline?d=%S(zUuid)">descendants</a> |
| 549 | } |
| 550 | if( zParent && !isLeaf ){ |
| 551 | @ | <a href="%s(g.zTop)/timeline?dp=%S(zUuid)">both</a> |
| 552 | } |
| 553 | db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag " |
| 554 | " WHERE rid=%d AND tagtype>0 " |
| 555 | " AND tag.tagid=tagxref.tagid " |
| 556 | " AND +tag.tagname GLOB 'sym-*'", rid); |
| 557 | while( db_step(&q)==SQLITE_ROW ){ |
| 558 | const char *zTagName = db_column_text(&q, 0); |
| 559 | @ | <a href="%s(g.zTop)/timeline?r=%T(zTagName)">%h(zTagName)</a> |
| 560 | } |
| 561 | db_finalize(&q); |
| 562 | @ </td></tr> |
| 563 | @ <tr><th>Other Links:</th> |
| 564 | @ <td> |
| 565 | @ <a href="%s(g.zTop)/dir?ci=%S(zUuid)">files</a> |
| 566 | if( g.perm.Zip ){ |
| 567 | char *zUrl = mprintf("%s/tarball/%s-%S.tar.gz?uuid=%s", |
| 568 | g.zTop, zProjName, zUuid, zUuid); |
| 569 | @ | <a href="%s(zUrl)">Tarball</a> |
| 570 | @ | <a href="%s(g.zTop)/zip/%s(zProjName)-%S(zUuid).zip?uuid=%s(zUuid)"> |
| 571 | @ ZIP archive</a> |
| 572 | fossil_free(zUrl); |
| 573 | } |
| 574 | @ | <a href="%s(g.zTop)/artifact/%S(zUuid)">manifest</a> |
| 575 | if( g.perm.Write ){ |
| 576 | @ | <a href="%s(g.zTop)/ci_edit?r=%S(zUuid)">edit</a> |
| 577 | } |
| 578 | @ </td> |
| 579 | @ </tr> |
| 580 | } |
| 581 | @ </table> |
| @@ -590,43 +590,43 @@ | |
| 590 | @ <div class="sectionmenu"> |
| 591 | showDiff = g.zPath[0]!='c'; |
| 592 | if( db_get_boolean("show-version-diffs", 0)==0 ){ |
| 593 | showDiff = !showDiff; |
| 594 | if( showDiff ){ |
| 595 | @ <a class="button" href="%s(g.zTop)/vinfo/%T(zName)"> |
| 596 | @ hide diffs</a> |
| 597 | if( sideBySide ){ |
| 598 | @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=0"> |
| 599 | @ unified diffs</a> |
| 600 | }else{ |
| 601 | @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=1"> |
| 602 | @ side-by-side diffs</a> |
| 603 | } |
| 604 | }else{ |
| 605 | @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=0"> |
| 606 | @ show unified diffs</a> |
| 607 | @ <a class="button" href="%s(g.zTop)/ci/%T(zName)?sbs=1"> |
| 608 | @ show side-by-side diffs</a> |
| 609 | } |
| 610 | }else{ |
| 611 | if( showDiff ){ |
| 612 | @ <a class="button" href="%s(g.zTop)/ci/%T(zName)">hide diffs</a> |
| 613 | if( sideBySide ){ |
| 614 | @ <a class="button" href="%s(g.zTop)/info/%T(zName)?sbs=0"> |
| 615 | @ unified diffs</a> |
| 616 | }else{ |
| 617 | @ <a class="button" href="%s(g.zTop)/info/%T(zName)?sbs=1"> |
| 618 | @ side-by-side diffs</a> |
| 619 | } |
| 620 | }else{ |
| 621 | @ <a class="button" href="%s(g.zTop)/vinfo/%T(zName)?sbs=0"> |
| 622 | @ show unified diffs</a> |
| 623 | @ <a class="button" href="%s(g.zTop)/vinfo/%T(zName)?sbs=1"> |
| 624 | @ show side-by-side diffs</a> |
| 625 | } |
| 626 | } |
| 627 | @ <a class="button" href="%s(g.zTop)/vpatch?from=%S(zParent)&to=%S(zUuid)"> |
| 628 | @ patch</a></div> |
| 629 | db_prepare(&q, |
| 630 | "SELECT name," |
| 631 | " mperm," |
| 632 | " (SELECT uuid FROM blob WHERE rid=mlink.pid)," |
| @@ -698,15 +698,15 @@ | |
| 698 | if( g.perm.Setup ){ |
| 699 | @ <tr><th>Record ID:</th><td>%d(rid)</td></tr> |
| 700 | } |
| 701 | @ <tr><th>Original User:</th><td> |
| 702 | hyperlink_to_user(zUser, zDate, "</td></tr>"); |
| 703 | if( g.perm.History ){ |
| 704 | @ <tr><th>Commands:</th> |
| 705 | @ <td> |
| 706 | @ <a href="%s(g.zTop)/whistory?name=%t(zName)">history</a> |
| 707 | @ | <a href="%s(g.zTop)/artifact/%S(zUuid)">raw-text</a> |
| 708 | @ </td> |
| 709 | @ </tr> |
| 710 | } |
| 711 | @ </table></p> |
| 712 | }else{ |
| @@ -792,11 +792,11 @@ | |
| 792 | } |
| 793 | |
| 794 | |
| 795 | /* |
| 796 | ** WEBPAGE: vdiff |
| 797 | ** URL: /vdiff?from=UUID&to=UUID&detail=BOOLEAN;sbs=BOOLEAN |
| 798 | ** |
| 799 | ** Show all differences between two checkins. |
| 800 | */ |
| 801 | void vdiff_page(void){ |
| 802 | int ridFrom, ridTo; |
| @@ -936,34 +936,26 @@ | |
| 936 | }else if( mPerm==PERM_EXE ){ |
| 937 | @ <li>Executable file |
| 938 | }else{ |
| 939 | @ <li>File |
| 940 | } |
| 941 | if( g.perm.History ){ |
| 942 | @ <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> |
| 943 | }else{ |
| 944 | @ %h(zName) |
| 945 | } |
| 946 | @ <ul> |
| 947 | prevName = fossil_strdup(zName); |
| 948 | } |
| 949 | @ <li> |
| 950 | hyperlink_to_date(zDate,""); |
| 951 | @ - part of checkin |
| 952 | hyperlink_to_uuid(zVers); |
| 953 | if( zBr && zBr[0] ){ |
| 954 | if( g.perm.History ){ |
| 955 | @ on branch <a href="%s(g.zTop)/timeline?r=%T(zBr)">%h(zBr)</a> |
| 956 | }else{ |
| 957 | @ on branch %h(zBr) |
| 958 | } |
| 959 | } |
| 960 | @ - %w(zCom) (user: |
| 961 | hyperlink_to_user(zUser,zDate,""); |
| 962 | @ ) |
| 963 | if( g.perm.History ){ |
| 964 | @ <a href="%s(g.zTop)/annotate?checkin=%S(zVers)&filename=%T(zName)"> |
| 965 | @ [annotate]</a> |
| 966 | } |
| 967 | cnt++; |
| 968 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 969 | blob_append(pDownloadName, zName, -1); |
| @@ -989,16 +981,11 @@ | |
| 989 | if( cnt>0 ){ |
| 990 | @ Also wiki page |
| 991 | }else{ |
| 992 | @ Wiki page |
| 993 | } |
| 994 | if( g.perm.History ){ |
| 995 | @ [<a href="%s(g.zTop)/wiki?name=%t(zPagename)">%h(zPagename)</a>] |
| 996 | }else{ |
| 997 | @ [%h(zPagename)] |
| 998 | } |
| 999 | @ by |
| 1000 | hyperlink_to_user(zUser,zDate," on"); |
| 1001 | hyperlink_to_date(zDate,"."); |
| 1002 | nWiki++; |
| 1003 | cnt++; |
| 1004 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| @@ -1065,18 +1052,18 @@ | |
| 1065 | @ Also attachment "%h(zFilename)" to |
| 1066 | }else{ |
| 1067 | @ Attachment "%h(zFilename)" to |
| 1068 | } |
| 1069 | if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){ |
| 1070 | if( g.perm.History && g.perm.RdTkt ){ |
| 1071 | @ ticket [<a href="%s(g.zTop)/tktview?name=%S(zTarget)">%S(zTarget)</a>] |
| 1072 | }else{ |
| 1073 | @ ticket [%S(zTarget)] |
| 1074 | } |
| 1075 | }else{ |
| 1076 | if( g.perm.History && g.perm.RdWiki ){ |
| 1077 | @ wiki page [<a href="%s(g.zTop)/wiki?name=%t(zTarget)">%h(zTarget)</a>] |
| 1078 | }else{ |
| 1079 | @ wiki page [%h(zTarget)] |
| 1080 | } |
| 1081 | } |
| 1082 | @ added by |
| @@ -1091,12 +1078,12 @@ | |
| 1091 | if( cnt==0 ){ |
| 1092 | @ Control artifact. |
| 1093 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 1094 | blob_appendf(pDownloadName, "%.10s.txt", zUuid); |
| 1095 | } |
| 1096 | }else if( linkToView && g.perm.History ){ |
| 1097 | @ <a href="%s(g.zTop)/artifact/%S(zUuid)">[view]</a> |
| 1098 | } |
| 1099 | } |
| 1100 | |
| 1101 | |
| 1102 | /* |
| @@ -1160,18 +1147,17 @@ | |
| 1160 | g.zTop, P("v1"), P("v2")); |
| 1161 | } |
| 1162 | |
| 1163 | if( P("smhdr")!=0 ){ |
| 1164 | @ <h2>Differences From Artifact |
| 1165 | @ <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a> To |
| 1166 | @ <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>.</h2> |
| 1167 | }else{ |
| 1168 | @ <h2>Differences From |
| 1169 | @ Artifact <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a>:</h2> |
| 1170 | object_description(v1, 0, 0); |
| 1171 | @ <h2>To Artifact |
| 1172 | @ <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>:</h2> |
| 1173 | object_description(v2, 0, 0); |
| 1174 | } |
| 1175 | @ <hr /> |
| 1176 | @ <div class="%s(zStyle)"> |
| 1177 | @ %s(blob_str(&diff)) |
| @@ -1272,11 +1258,11 @@ | |
| 1272 | if( !g.perm.Read ){ login_needed(); return; } |
| 1273 | if( rid==0 ) fossil_redirect_home(); |
| 1274 | if( g.perm.Admin ){ |
| 1275 | const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1276 | if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ |
| 1277 | style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", |
| 1278 | g.zTop, zUuid); |
| 1279 | }else{ |
| 1280 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1281 | g.zTop, zUuid); |
| 1282 | } |
| @@ -1419,11 +1405,11 @@ | |
| 1419 | if( !g.perm.Read ){ login_needed(); return; } |
| 1420 | if( rid==0 ) fossil_redirect_home(); |
| 1421 | if( g.perm.Admin ){ |
| 1422 | const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1423 | if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ |
| 1424 | style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", |
| 1425 | g.zTop, zUuid); |
| 1426 | }else{ |
| 1427 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1428 | g.zTop, zUuid); |
| 1429 | } |
| @@ -1478,11 +1464,11 @@ | |
| 1478 | @ <pre> |
| 1479 | @ %h(z) |
| 1480 | @ </pre> |
| 1481 | } |
| 1482 | }else if( strncmp(zMime, "image/", 6)==0 ){ |
| 1483 | @ <img src="%s(g.zTop)/raw?name=%s(zUuid)&m=%s(zMime)"></img> |
| 1484 | }else{ |
| 1485 | @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i> |
| 1486 | } |
| 1487 | @ </blockquote> |
| 1488 | } |
| @@ -1507,11 +1493,11 @@ | |
| 1507 | rid = name_to_rid_www("name"); |
| 1508 | if( rid==0 ){ fossil_redirect_home(); } |
| 1509 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1510 | if( g.perm.Admin ){ |
| 1511 | if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ |
| 1512 | style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", |
| 1513 | g.zTop, zUuid); |
| 1514 | }else{ |
| 1515 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1516 | g.zTop, zUuid); |
| 1517 | } |
| @@ -1522,18 +1508,17 @@ | |
| 1522 | } |
| 1523 | style_header("Ticket Change Details"); |
| 1524 | zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate); |
| 1525 | memcpy(zTktName, pTktChng->zTicketUuid, 10); |
| 1526 | zTktName[10] = 0; |
| 1527 | if( g.perm.History ){ |
| 1528 | @ <h2>Changes to ticket |
| 1529 | @ <a href="%s(pTktChng->zTicketUuid)">%s(zTktName)</a></h2> |
| 1530 | @ |
| 1531 | @ <p>By %h(pTktChng->zUser) on %s(zDate). See also: |
| 1532 | @ <a href="%s(g.zTop)/artifact/%T(zUuid)">artifact content</a>, and |
| 1533 | @ <a href="%s(g.zTop)/tkthistory/%s(pTktChng->zTicketUuid)">ticket |
| 1534 | @ history</a></p> |
| 1535 | }else{ |
| 1536 | @ <h2>Changes to ticket %s(zTktName)</h2> |
| 1537 | @ |
| 1538 | @ <p>By %h(pTktChng->zUser) on %s(zDate). |
| 1539 | @ </p> |
| @@ -1965,11 +1950,11 @@ | |
| 1965 | @ </blockquote> |
| 1966 | @ <hr /> |
| 1967 | blob_reset(&suffix); |
| 1968 | } |
| 1969 | @ <p>Make changes to attributes of check-in |
| 1970 | @ [<a href="ci?name=%s(zUuid)">%s(zUuid)</a>]:</p> |
| 1971 | @ <form action="%s(g.zTop)/ci_edit" method="post"><div> |
| 1972 | login_insert_csrf_secret(); |
| 1973 | @ <input type="hidden" name="r" value="%S(zUuid)" /> |
| 1974 | @ <table border="0" cellspacing="10"> |
| 1975 | |
| 1976 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -261,11 +261,11 @@ | |
| 261 | @ propagates to descendants |
| 262 | } |
| 263 | #if 0 |
| 264 | if( zValue && fossil_strcmp(zTagname,"branch")==0 ){ |
| 265 | @ |
| 266 | @ %z(href("%R/timeline?r=%T",zValue))branch timeline</a> |
| 267 | } |
| 268 | #endif |
| 269 | } |
| 270 | if( zSrcUuid && zSrcUuid[0] ){ |
| 271 | if( tagtype==0 ){ |
| @@ -333,11 +333,11 @@ | |
| 333 | const char *zNew, /* blob.uuid after change. NULL for deletes */ |
| 334 | const char *zOldName, /* Prior name. NULL if no name change. */ |
| 335 | int diffFlags, /* Flags for text_diff(). Zero to omit diffs */ |
| 336 | int mperm /* executable or symlink permission for zNew */ |
| 337 | ){ |
| 338 | if( !g.perm.Hyperlink ){ |
| 339 | if( zNew==0 ){ |
| 340 | @ <p>Deleted %h(zName)</p> |
| 341 | }else if( zOld==0 ){ |
| 342 | @ <p>Added %h(zName)</p> |
| 343 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| @@ -354,35 +354,35 @@ | |
| 354 | @ </pre> |
| 355 | } |
| 356 | }else{ |
| 357 | if( zOld && zNew ){ |
| 358 | if( fossil_strcmp(zOld, zNew)!=0 ){ |
| 359 | @ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 360 | @ from %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a> |
| 361 | @ to %z(href("%R/artifact/%s",zNew))[%S(zNew)].</a> |
| 362 | }else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){ |
| 363 | @ <p>Name change from |
| 364 | @ from %z(href("%R/finfo?name=%T",zOldName))%h(zOldName)</a> |
| 365 | @ to %z(href("%R/finfo?name=%T",zName))%h(zName)</a>. |
| 366 | }else{ |
| 367 | @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") for |
| 368 | @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 369 | } |
| 370 | }else if( zOld ){ |
| 371 | @ <p>Deleted %z(href("%s/finfo?name=%T",g.zTop,zName))%h(zName)</a> |
| 372 | @ version %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a> |
| 373 | }else{ |
| 374 | @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 375 | @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a> |
| 376 | } |
| 377 | if( diffFlags ){ |
| 378 | @ <pre style="white-space:pre;"> |
| 379 | append_diff(zOld, zNew, diffFlags); |
| 380 | @ </pre> |
| 381 | }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ |
| 382 | @ |
| 383 | @ %z(href("%R/fdiff?v1=%S&v2=%S",zOld,zNew))[diff]</a> |
| 384 | } |
| 385 | @ </p> |
| 386 | } |
| 387 | } |
| 388 | |
| @@ -535,47 +535,47 @@ | |
| 535 | @ <tr><th>Received From:</th> |
| 536 | @ <td>%h(zUser) @ %h(zIpAddr) on %s(zDate)</td></tr> |
| 537 | } |
| 538 | db_finalize(&q); |
| 539 | } |
| 540 | if( g.perm.Hyperlink ){ |
| 541 | const char *zProjName = db_get("project-name", "unnamed"); |
| 542 | @ <tr><th>Timelines:</th><td> |
| 543 | @ %z(href("%R/timeline?f=%S",zUuid))family</a> |
| 544 | if( zParent ){ |
| 545 | @ | %z(href("%R/timeline?p=%S",zUuid))ancestors</a> |
| 546 | } |
| 547 | if( !isLeaf ){ |
| 548 | @ | %z(href("%R/timeline?d=%S",zUuid))descendants</a> |
| 549 | } |
| 550 | if( zParent && !isLeaf ){ |
| 551 | @ | %z(href("%R/timeline?dp=%S",zUuid))both</a> |
| 552 | } |
| 553 | db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag " |
| 554 | " WHERE rid=%d AND tagtype>0 " |
| 555 | " AND tag.tagid=tagxref.tagid " |
| 556 | " AND +tag.tagname GLOB 'sym-*'", rid); |
| 557 | while( db_step(&q)==SQLITE_ROW ){ |
| 558 | const char *zTagName = db_column_text(&q, 0); |
| 559 | @ | %z(href("%R/timeline?r=%T",zTagName))%h(zTagName)</a> |
| 560 | } |
| 561 | db_finalize(&q); |
| 562 | @ </td></tr> |
| 563 | @ <tr><th>Other Links:</th> |
| 564 | @ <td> |
| 565 | @ %z(href("%R/dir?ci=%S",zUuid))files</a> |
| 566 | if( g.perm.Zip ){ |
| 567 | char *zUrl = mprintf("%R/tarball/%s-%S.tar.gz?uuid=%s", |
| 568 | zProjName, zUuid, zUuid); |
| 569 | @ | %z(href("%s",zUrl))Tarball</a> |
| 570 | @ | %z(href("%R/zip/%s-%S.zip?uuid=%s",zProjName,zUuid,zUuid)) |
| 571 | @ ZIP archive</a> |
| 572 | fossil_free(zUrl); |
| 573 | } |
| 574 | @ | %z(href("%R/artifact/%S",zUuid))manifest</a> |
| 575 | if( g.perm.Write ){ |
| 576 | @ | %z(href("%R/ci_edit?r=%S",zUuid))edit</a> |
| 577 | } |
| 578 | @ </td> |
| 579 | @ </tr> |
| 580 | } |
| 581 | @ </table> |
| @@ -590,43 +590,43 @@ | |
| 590 | @ <div class="sectionmenu"> |
| 591 | showDiff = g.zPath[0]!='c'; |
| 592 | if( db_get_boolean("show-version-diffs", 0)==0 ){ |
| 593 | showDiff = !showDiff; |
| 594 | if( showDiff ){ |
| 595 | @ %z(xhref("class='button'","%R/vinfo/%T",zName))) |
| 596 | @ hide diffs</a> |
| 597 | if( sideBySide ){ |
| 598 | @ %z(xhref("class='button'","%R/ci/%T?sbs=0",zName)) |
| 599 | @ unified diffs</a> |
| 600 | }else{ |
| 601 | @ %z(xhref("class='button'","%R/ci/%T?sbs=1",zName)) |
| 602 | @ side-by-side diffs</a> |
| 603 | } |
| 604 | }else{ |
| 605 | @ %z(xhref("class='button'","%R/ci/%T?sbs=0",zName)) |
| 606 | @ show unified diffs</a> |
| 607 | @ %z(xhref("class='button'","%R/ci/%T?sbs=1",zName)) |
| 608 | @ show side-by-side diffs</a> |
| 609 | } |
| 610 | }else{ |
| 611 | if( showDiff ){ |
| 612 | @ %z(xhref("class='button'","%R/ci/%T",zName))hide diffs</a> |
| 613 | if( sideBySide ){ |
| 614 | @ %z(xhref("class='button'","%R/info/%T?sbs=0",zName)) |
| 615 | @ unified diffs</a> |
| 616 | }else{ |
| 617 | @ %z(xhref("class='button'","%R/info/%T?sbs=1",zName)) |
| 618 | @ side-by-side diffs</a> |
| 619 | } |
| 620 | }else{ |
| 621 | @ %z(xhref("class='button'","%R/vinfo/%T?sbs=0",zName)) |
| 622 | @ show unified diffs</a> |
| 623 | @ %z(xhref("class='button'","%R/vinfo/%T?sbs=1",zName)) |
| 624 | @ show side-by-side diffs</a> |
| 625 | } |
| 626 | } |
| 627 | @ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid)) |
| 628 | @ patch</a></div> |
| 629 | db_prepare(&q, |
| 630 | "SELECT name," |
| 631 | " mperm," |
| 632 | " (SELECT uuid FROM blob WHERE rid=mlink.pid)," |
| @@ -698,15 +698,15 @@ | |
| 698 | if( g.perm.Setup ){ |
| 699 | @ <tr><th>Record ID:</th><td>%d(rid)</td></tr> |
| 700 | } |
| 701 | @ <tr><th>Original User:</th><td> |
| 702 | hyperlink_to_user(zUser, zDate, "</td></tr>"); |
| 703 | if( g.perm.Hyperlink ){ |
| 704 | @ <tr><th>Commands:</th> |
| 705 | @ <td> |
| 706 | @ &z(href("%R/whistory?name=%t",zName))history</a> |
| 707 | @ | %z(href("%R/artifact/%S",zUuid))raw-text</a> |
| 708 | @ </td> |
| 709 | @ </tr> |
| 710 | } |
| 711 | @ </table></p> |
| 712 | }else{ |
| @@ -792,11 +792,11 @@ | |
| 792 | } |
| 793 | |
| 794 | |
| 795 | /* |
| 796 | ** WEBPAGE: vdiff |
| 797 | ** URL: /vdiff?from=UUID&to=UUID&detail=BOOLEAN;sbs=BOOLEAN |
| 798 | ** |
| 799 | ** Show all differences between two checkins. |
| 800 | */ |
| 801 | void vdiff_page(void){ |
| 802 | int ridFrom, ridTo; |
| @@ -936,34 +936,26 @@ | |
| 936 | }else if( mPerm==PERM_EXE ){ |
| 937 | @ <li>Executable file |
| 938 | }else{ |
| 939 | @ <li>File |
| 940 | } |
| 941 | @ %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 942 | @ <ul> |
| 943 | prevName = fossil_strdup(zName); |
| 944 | } |
| 945 | @ <li> |
| 946 | hyperlink_to_date(zDate,""); |
| 947 | @ - part of checkin |
| 948 | hyperlink_to_uuid(zVers); |
| 949 | if( zBr && zBr[0] ){ |
| 950 | @ on branch %z(href("%R/timeline?r=%T",zBr))%h(zBr)</a> |
| 951 | } |
| 952 | @ - %w(zCom) (user: |
| 953 | hyperlink_to_user(zUser,zDate,""); |
| 954 | @ ) |
| 955 | if( g.perm.Hyperlink ){ |
| 956 | @ %z(href("%R/annotate?checkin=%S&filename=%T",zVers,zName)) |
| 957 | @ [annotate]</a> |
| 958 | } |
| 959 | cnt++; |
| 960 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 961 | blob_append(pDownloadName, zName, -1); |
| @@ -989,16 +981,11 @@ | |
| 981 | if( cnt>0 ){ |
| 982 | @ Also wiki page |
| 983 | }else{ |
| 984 | @ Wiki page |
| 985 | } |
| 986 | @ [%z(href("%R/wiki?name=%t",zPagename))%h(zPagename)</a>] by |
| 987 | hyperlink_to_user(zUser,zDate," on"); |
| 988 | hyperlink_to_date(zDate,"."); |
| 989 | nWiki++; |
| 990 | cnt++; |
| 991 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| @@ -1065,18 +1052,18 @@ | |
| 1052 | @ Also attachment "%h(zFilename)" to |
| 1053 | }else{ |
| 1054 | @ Attachment "%h(zFilename)" to |
| 1055 | } |
| 1056 | if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){ |
| 1057 | if( g.perm.Hyperlink && g.perm.RdTkt ){ |
| 1058 | @ ticket [%z(href("%R/tktview?name=%S",zTarget))%S(zTarget)</a>] |
| 1059 | }else{ |
| 1060 | @ ticket [%S(zTarget)] |
| 1061 | } |
| 1062 | }else{ |
| 1063 | if( g.perm.Hyperlink && g.perm.RdWiki ){ |
| 1064 | @ wiki page [%z(href("%R/wiki?name=%t",zTarget)))%h(zTarget)</a>] |
| 1065 | }else{ |
| 1066 | @ wiki page [%h(zTarget)] |
| 1067 | } |
| 1068 | } |
| 1069 | @ added by |
| @@ -1091,12 +1078,12 @@ | |
| 1078 | if( cnt==0 ){ |
| 1079 | @ Control artifact. |
| 1080 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 1081 | blob_appendf(pDownloadName, "%.10s.txt", zUuid); |
| 1082 | } |
| 1083 | }else if( linkToView && g.perm.Hyperlink ){ |
| 1084 | @ %z(href("%R/artifact/%S",zUuid))[view]</a> |
| 1085 | } |
| 1086 | } |
| 1087 | |
| 1088 | |
| 1089 | /* |
| @@ -1160,18 +1147,17 @@ | |
| 1147 | g.zTop, P("v1"), P("v2")); |
| 1148 | } |
| 1149 | |
| 1150 | if( P("smhdr")!=0 ){ |
| 1151 | @ <h2>Differences From Artifact |
| 1152 | @ %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a> To |
| 1153 | @ %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>.</h2> |
| 1154 | }else{ |
| 1155 | @ <h2>Differences From |
| 1156 | @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2> |
| 1157 | object_description(v1, 0, 0); |
| 1158 | @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2> |
| 1159 | object_description(v2, 0, 0); |
| 1160 | } |
| 1161 | @ <hr /> |
| 1162 | @ <div class="%s(zStyle)"> |
| 1163 | @ %s(blob_str(&diff)) |
| @@ -1272,11 +1258,11 @@ | |
| 1258 | if( !g.perm.Read ){ login_needed(); return; } |
| 1259 | if( rid==0 ) fossil_redirect_home(); |
| 1260 | if( g.perm.Admin ){ |
| 1261 | const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1262 | if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ |
| 1263 | style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", |
| 1264 | g.zTop, zUuid); |
| 1265 | }else{ |
| 1266 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1267 | g.zTop, zUuid); |
| 1268 | } |
| @@ -1419,11 +1405,11 @@ | |
| 1405 | if( !g.perm.Read ){ login_needed(); return; } |
| 1406 | if( rid==0 ) fossil_redirect_home(); |
| 1407 | if( g.perm.Admin ){ |
| 1408 | const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1409 | if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ |
| 1410 | style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", |
| 1411 | g.zTop, zUuid); |
| 1412 | }else{ |
| 1413 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1414 | g.zTop, zUuid); |
| 1415 | } |
| @@ -1478,11 +1464,11 @@ | |
| 1464 | @ <pre> |
| 1465 | @ %h(z) |
| 1466 | @ </pre> |
| 1467 | } |
| 1468 | }else if( strncmp(zMime, "image/", 6)==0 ){ |
| 1469 | @ <img src="%s(g.zTop)/raw?name=%s(zUuid)&m=%s(zMime)"></img> |
| 1470 | }else{ |
| 1471 | @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i> |
| 1472 | } |
| 1473 | @ </blockquote> |
| 1474 | } |
| @@ -1507,11 +1493,11 @@ | |
| 1493 | rid = name_to_rid_www("name"); |
| 1494 | if( rid==0 ){ fossil_redirect_home(); } |
| 1495 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1496 | if( g.perm.Admin ){ |
| 1497 | if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ |
| 1498 | style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", |
| 1499 | g.zTop, zUuid); |
| 1500 | }else{ |
| 1501 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1502 | g.zTop, zUuid); |
| 1503 | } |
| @@ -1522,18 +1508,17 @@ | |
| 1508 | } |
| 1509 | style_header("Ticket Change Details"); |
| 1510 | zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate); |
| 1511 | memcpy(zTktName, pTktChng->zTicketUuid, 10); |
| 1512 | zTktName[10] = 0; |
| 1513 | if( g.perm.Hyperlink ){ |
| 1514 | @ <h2>Changes to ticket |
| 1515 | @ %z(href("%R/tktview/%s",pTktChng->zTicketUuid)))%s(zTktName)</a></h2> |
| 1516 | @ |
| 1517 | @ <p>By %h(pTktChng->zUser) on %s(zDate). See also: |
| 1518 | @ %z(href("%R/artifact/%T",zUuid))artifact content</a>, and |
| 1519 | @ %z(href("%R/tkthistory/%s",pTktChng->zTicketUuid))ticket history</a></p> |
| 1520 | }else{ |
| 1521 | @ <h2>Changes to ticket %s(zTktName)</h2> |
| 1522 | @ |
| 1523 | @ <p>By %h(pTktChng->zUser) on %s(zDate). |
| 1524 | @ </p> |
| @@ -1965,11 +1950,11 @@ | |
| 1950 | @ </blockquote> |
| 1951 | @ <hr /> |
| 1952 | blob_reset(&suffix); |
| 1953 | } |
| 1954 | @ <p>Make changes to attributes of check-in |
| 1955 | @ [%z(href("%R/ci/%s",zUuid))%s(zUuid)</a>]:</p> |
| 1956 | @ <form action="%s(g.zTop)/ci_edit" method="post"><div> |
| 1957 | login_insert_csrf_secret(); |
| 1958 | @ <input type="hidden" name="r" value="%S(zUuid)" /> |
| 1959 | @ <table border="0" cellspacing="10"> |
| 1960 | |
| 1961 |
+1
-1
| --- src/json_dir.c | ||
| +++ src/json_dir.c | ||
| @@ -66,11 +66,11 @@ | ||
| 66 | 66 | char * zUuid = NULL; |
| 67 | 67 | char const * zCI = NULL; |
| 68 | 68 | Manifest * pM = NULL; |
| 69 | 69 | Stmt q = empty_Stmt; |
| 70 | 70 | int rid = 0; |
| 71 | - if( !g.perm.History ){ | |
| 71 | + if( !g.perm.Hyperlink ){ | |
| 72 | 72 | json_set_err(FSL_JSON_E_DENIED, "Requires 'h' permissions."); |
| 73 | 73 | return NULL; |
| 74 | 74 | } |
| 75 | 75 | zCI = json_find_option_cstr("checkin",NULL,"ci" ); |
| 76 | 76 | |
| 77 | 77 |
| --- src/json_dir.c | |
| +++ src/json_dir.c | |
| @@ -66,11 +66,11 @@ | |
| 66 | char * zUuid = NULL; |
| 67 | char const * zCI = NULL; |
| 68 | Manifest * pM = NULL; |
| 69 | Stmt q = empty_Stmt; |
| 70 | int rid = 0; |
| 71 | if( !g.perm.History ){ |
| 72 | json_set_err(FSL_JSON_E_DENIED, "Requires 'h' permissions."); |
| 73 | return NULL; |
| 74 | } |
| 75 | zCI = json_find_option_cstr("checkin",NULL,"ci" ); |
| 76 | |
| 77 |
| --- src/json_dir.c | |
| +++ src/json_dir.c | |
| @@ -66,11 +66,11 @@ | |
| 66 | char * zUuid = NULL; |
| 67 | char const * zCI = NULL; |
| 68 | Manifest * pM = NULL; |
| 69 | Stmt q = empty_Stmt; |
| 70 | int rid = 0; |
| 71 | if( !g.perm.Hyperlink ){ |
| 72 | json_set_err(FSL_JSON_E_DENIED, "Requires 'h' permissions."); |
| 73 | return NULL; |
| 74 | } |
| 75 | zCI = json_find_option_cstr("checkin",NULL,"ci" ); |
| 76 | |
| 77 |
+2
-2
| --- src/json_timeline.c | ||
| +++ src/json_timeline.c | ||
| @@ -53,11 +53,11 @@ | ||
| 53 | 53 | #if 0 |
| 54 | 54 | /* The original timeline code does not require 'h' access, |
| 55 | 55 | but it arguably should. For JSON mode i think one could argue |
| 56 | 56 | that History permissions are required. |
| 57 | 57 | */ |
| 58 | - if(! g.perm.History && !g.perm.Read ){ | |
| 58 | + if(! g.perm.Hyperlink && !g.perm.Read ){ | |
| 59 | 59 | json_set_err(FSL_JSON_E_DENIED, "Timeline requires 'h' or 'o' access."); |
| 60 | 60 | return NULL; |
| 61 | 61 | } |
| 62 | 62 | #endif |
| 63 | 63 | return json_page_dispatch_helper(&JsonPageDefs_Timeline[0]); |
| @@ -426,11 +426,11 @@ | ||
| 426 | 426 | int check = 0; |
| 427 | 427 | char showFiles = -1/*magic number*/; |
| 428 | 428 | Stmt q = empty_Stmt; |
| 429 | 429 | char warnRowToJsonFailed = 0; |
| 430 | 430 | Blob sql = empty_blob; |
| 431 | - if( !g.perm.History ){ | |
| 431 | + if( !g.perm.Hyperlink ){ | |
| 432 | 432 | /* Reminder to self: HTML impl requires 'o' (Read) |
| 433 | 433 | rights. |
| 434 | 434 | */ |
| 435 | 435 | json_set_err( FSL_JSON_E_DENIED, "Checkin timeline requires 'h' access." ); |
| 436 | 436 | return NULL; |
| 437 | 437 |
| --- src/json_timeline.c | |
| +++ src/json_timeline.c | |
| @@ -53,11 +53,11 @@ | |
| 53 | #if 0 |
| 54 | /* The original timeline code does not require 'h' access, |
| 55 | but it arguably should. For JSON mode i think one could argue |
| 56 | that History permissions are required. |
| 57 | */ |
| 58 | if(! g.perm.History && !g.perm.Read ){ |
| 59 | json_set_err(FSL_JSON_E_DENIED, "Timeline requires 'h' or 'o' access."); |
| 60 | return NULL; |
| 61 | } |
| 62 | #endif |
| 63 | return json_page_dispatch_helper(&JsonPageDefs_Timeline[0]); |
| @@ -426,11 +426,11 @@ | |
| 426 | int check = 0; |
| 427 | char showFiles = -1/*magic number*/; |
| 428 | Stmt q = empty_Stmt; |
| 429 | char warnRowToJsonFailed = 0; |
| 430 | Blob sql = empty_blob; |
| 431 | if( !g.perm.History ){ |
| 432 | /* Reminder to self: HTML impl requires 'o' (Read) |
| 433 | rights. |
| 434 | */ |
| 435 | json_set_err( FSL_JSON_E_DENIED, "Checkin timeline requires 'h' access." ); |
| 436 | return NULL; |
| 437 |
| --- src/json_timeline.c | |
| +++ src/json_timeline.c | |
| @@ -53,11 +53,11 @@ | |
| 53 | #if 0 |
| 54 | /* The original timeline code does not require 'h' access, |
| 55 | but it arguably should. For JSON mode i think one could argue |
| 56 | that History permissions are required. |
| 57 | */ |
| 58 | if(! g.perm.Hyperlink && !g.perm.Read ){ |
| 59 | json_set_err(FSL_JSON_E_DENIED, "Timeline requires 'h' or 'o' access."); |
| 60 | return NULL; |
| 61 | } |
| 62 | #endif |
| 63 | return json_page_dispatch_helper(&JsonPageDefs_Timeline[0]); |
| @@ -426,11 +426,11 @@ | |
| 426 | int check = 0; |
| 427 | char showFiles = -1/*magic number*/; |
| 428 | Stmt q = empty_Stmt; |
| 429 | char warnRowToJsonFailed = 0; |
| 430 | Blob sql = empty_blob; |
| 431 | if( !g.perm.Hyperlink ){ |
| 432 | /* Reminder to self: HTML impl requires 'o' (Read) |
| 433 | rights. |
| 434 | */ |
| 435 | json_set_err( FSL_JSON_E_DENIED, "Checkin timeline requires 'h' access." ); |
| 436 | return NULL; |
| 437 |
+1
-1
| --- src/json_wiki.c | ||
| +++ src/json_wiki.c | ||
| @@ -492,11 +492,11 @@ | ||
| 492 | 492 | Manifest * pW1 = NULL, *pW2 = NULL; |
| 493 | 493 | Blob w1 = empty_blob, w2 = empty_blob, d = empty_blob; |
| 494 | 494 | char const * zErrTag = NULL; |
| 495 | 495 | int diffFlags; |
| 496 | 496 | char * zUuid = NULL; |
| 497 | - if( !g.perm.History ){ | |
| 497 | + if( !g.perm.Hyperlink ){ | |
| 498 | 498 | json_set_err(FSL_JSON_E_DENIED, |
| 499 | 499 | "Requires 'h' permissions."); |
| 500 | 500 | return NULL; |
| 501 | 501 | } |
| 502 | 502 | |
| 503 | 503 |
| --- src/json_wiki.c | |
| +++ src/json_wiki.c | |
| @@ -492,11 +492,11 @@ | |
| 492 | Manifest * pW1 = NULL, *pW2 = NULL; |
| 493 | Blob w1 = empty_blob, w2 = empty_blob, d = empty_blob; |
| 494 | char const * zErrTag = NULL; |
| 495 | int diffFlags; |
| 496 | char * zUuid = NULL; |
| 497 | if( !g.perm.History ){ |
| 498 | json_set_err(FSL_JSON_E_DENIED, |
| 499 | "Requires 'h' permissions."); |
| 500 | return NULL; |
| 501 | } |
| 502 | |
| 503 |
| --- src/json_wiki.c | |
| +++ src/json_wiki.c | |
| @@ -492,11 +492,11 @@ | |
| 492 | Manifest * pW1 = NULL, *pW2 = NULL; |
| 493 | Blob w1 = empty_blob, w2 = empty_blob, d = empty_blob; |
| 494 | char const * zErrTag = NULL; |
| 495 | int diffFlags; |
| 496 | char * zUuid = NULL; |
| 497 | if( !g.perm.Hyperlink ){ |
| 498 | json_set_err(FSL_JSON_E_DENIED, |
| 499 | "Requires 'h' permissions."); |
| 500 | return NULL; |
| 501 | } |
| 502 | |
| 503 |
+16
-15
| --- src/login.c | ||
| +++ src/login.c | ||
| @@ -562,11 +562,11 @@ | ||
| 562 | 562 | redirect_to_g(); |
| 563 | 563 | } |
| 564 | 564 | } |
| 565 | 565 | style_header("Login/Logout"); |
| 566 | 566 | @ %s(zErrMsg) |
| 567 | - if( zGoto ){ | |
| 567 | + if( zGoto && P("anon")==0 ){ | |
| 568 | 568 | @ <p>A login is required for <a href="%h(zGoto)">%h(zGoto)</a>.</p> |
| 569 | 569 | } |
| 570 | 570 | @ <form action="login" method="post"> |
| 571 | 571 | if( zGoto ){ |
| 572 | 572 | @ <input type="hidden" name="g" value="%h(zGoto)" /> |
| @@ -911,13 +911,15 @@ | ||
| 911 | 911 | } |
| 912 | 912 | |
| 913 | 913 | /* Set the capabilities */ |
| 914 | 914 | login_replace_capabilities(zCap, 0); |
| 915 | 915 | login_set_anon_nobody_capabilities(); |
| 916 | - if( zCap[0] && !g.perm.History && db_get_boolean("auto-enable-hyperlinks",1) | |
| 916 | + if( zCap[0] && !g.perm.Hyperlink | |
| 917 | + && db_get_boolean("auto-enable-hyperlinks",1) | |
| 917 | 918 | && isHuman(P("HTTP_USER_AGENT")) ){ |
| 918 | - g.perm.History = 1; | |
| 919 | + g.perm.Hyperlink = 1; | |
| 920 | + g.javascriptHyperlink = 1; | |
| 919 | 921 | } |
| 920 | 922 | |
| 921 | 923 | /* If the public-pages glob pattern is defined and REQUEST_URI matches |
| 922 | 924 | ** one of the globs in public-pages, then also add in all default-perms |
| 923 | 925 | ** permissions. |
| @@ -973,21 +975,21 @@ | ||
| 973 | 975 | } |
| 974 | 976 | for(i=0; zCap[i]; i++){ |
| 975 | 977 | switch( zCap[i] ){ |
| 976 | 978 | case 's': g.perm.Setup = 1; /* Fall thru into Admin */ |
| 977 | 979 | case 'a': g.perm.Admin = g.perm.RdTkt = g.perm.WrTkt = g.perm.Zip = |
| 978 | - g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki = | |
| 979 | - g.perm.ApndWiki = g.perm.History = g.perm.Clone = | |
| 980 | - g.perm.NewTkt = g.perm.Password = g.perm.RdAddr = | |
| 981 | - g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt = 1; | |
| 982 | - /* Fall thru into Read/Write */ | |
| 980 | + g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki = | |
| 981 | + g.perm.ApndWiki = g.perm.Hyperlink = g.perm.Clone = | |
| 982 | + g.perm.NewTkt = g.perm.Password = g.perm.RdAddr = | |
| 983 | + g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt = 1; | |
| 984 | + /* Fall thru into Read/Write */ | |
| 983 | 985 | case 'i': g.perm.Read = g.perm.Write = 1; break; |
| 984 | 986 | case 'o': g.perm.Read = 1; break; |
| 985 | 987 | case 'z': g.perm.Zip = 1; break; |
| 986 | 988 | |
| 987 | 989 | case 'd': g.perm.Delete = 1; break; |
| 988 | - case 'h': g.perm.History = 1; break; | |
| 990 | + case 'h': g.perm.Hyperlink = 1; break; | |
| 989 | 991 | case 'g': g.perm.Clone = 1; break; |
| 990 | 992 | case 'p': g.perm.Password = 1; break; |
| 991 | 993 | |
| 992 | 994 | case 'j': g.perm.RdWiki = 1; break; |
| 993 | 995 | case 'k': g.perm.WrWiki = g.perm.RdWiki = g.perm.ApndWiki =1; break; |
| @@ -1053,15 +1055,14 @@ | ||
| 1053 | 1055 | case 'c': rc = g.perm.ApndTkt; break; |
| 1054 | 1056 | case 'd': rc = g.perm.Delete; break; |
| 1055 | 1057 | case 'e': rc = g.perm.RdAddr; break; |
| 1056 | 1058 | case 'f': rc = g.perm.NewWiki; break; |
| 1057 | 1059 | case 'g': rc = g.perm.Clone; break; |
| 1058 | - case 'h': rc = g.perm.History; break; | |
| 1060 | + case 'h': rc = g.perm.Hyperlink; break; | |
| 1059 | 1061 | case 'i': rc = g.perm.Write; break; |
| 1060 | 1062 | case 'j': rc = g.perm.RdWiki; break; |
| 1061 | 1063 | case 'k': rc = g.perm.WrWiki; break; |
| 1062 | - /* case 'l': */ | |
| 1063 | 1064 | case 'm': rc = g.perm.ApndWiki; break; |
| 1064 | 1065 | case 'n': rc = g.perm.NewTkt; break; |
| 1065 | 1066 | case 'o': rc = g.perm.Read; break; |
| 1066 | 1067 | case 'p': rc = g.perm.Password; break; |
| 1067 | 1068 | /* case 'q': */ |
| @@ -1129,23 +1130,23 @@ | ||
| 1129 | 1130 | assert(0); |
| 1130 | 1131 | } |
| 1131 | 1132 | } |
| 1132 | 1133 | |
| 1133 | 1134 | /* |
| 1134 | -** Call this routine if the user lacks okHistory permission. If | |
| 1135 | -** the anonymous user has okHistory permission, then paint a mesage | |
| 1135 | +** Call this routine if the user lacks g.perm.Hyperlink permission. If | |
| 1136 | +** the anonymous user has Hyperlink permission, then paint a mesage | |
| 1136 | 1137 | ** to inform the user that much more information is available by |
| 1137 | 1138 | ** logging in as anonymous. |
| 1138 | 1139 | */ |
| 1139 | 1140 | void login_anonymous_available(void){ |
| 1140 | - if( !g.perm.History && | |
| 1141 | + if( !g.perm.Hyperlink && | |
| 1141 | 1142 | db_exists("SELECT 1 FROM user" |
| 1142 | 1143 | " WHERE login='anonymous'" |
| 1143 | 1144 | " AND cap LIKE '%%h%%'") ){ |
| 1144 | 1145 | const char *zUrl = PD("REQUEST_URI", "index"); |
| 1145 | 1146 | @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br /> |
| 1146 | - @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a> | |
| 1147 | + @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a> | |
| 1147 | 1148 | @ to enable hyperlinks.</p> |
| 1148 | 1149 | } |
| 1149 | 1150 | } |
| 1150 | 1151 | |
| 1151 | 1152 | /* |
| 1152 | 1153 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -562,11 +562,11 @@ | |
| 562 | redirect_to_g(); |
| 563 | } |
| 564 | } |
| 565 | style_header("Login/Logout"); |
| 566 | @ %s(zErrMsg) |
| 567 | if( zGoto ){ |
| 568 | @ <p>A login is required for <a href="%h(zGoto)">%h(zGoto)</a>.</p> |
| 569 | } |
| 570 | @ <form action="login" method="post"> |
| 571 | if( zGoto ){ |
| 572 | @ <input type="hidden" name="g" value="%h(zGoto)" /> |
| @@ -911,13 +911,15 @@ | |
| 911 | } |
| 912 | |
| 913 | /* Set the capabilities */ |
| 914 | login_replace_capabilities(zCap, 0); |
| 915 | login_set_anon_nobody_capabilities(); |
| 916 | if( zCap[0] && !g.perm.History && db_get_boolean("auto-enable-hyperlinks",1) |
| 917 | && isHuman(P("HTTP_USER_AGENT")) ){ |
| 918 | g.perm.History = 1; |
| 919 | } |
| 920 | |
| 921 | /* If the public-pages glob pattern is defined and REQUEST_URI matches |
| 922 | ** one of the globs in public-pages, then also add in all default-perms |
| 923 | ** permissions. |
| @@ -973,21 +975,21 @@ | |
| 973 | } |
| 974 | for(i=0; zCap[i]; i++){ |
| 975 | switch( zCap[i] ){ |
| 976 | case 's': g.perm.Setup = 1; /* Fall thru into Admin */ |
| 977 | case 'a': g.perm.Admin = g.perm.RdTkt = g.perm.WrTkt = g.perm.Zip = |
| 978 | g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki = |
| 979 | g.perm.ApndWiki = g.perm.History = g.perm.Clone = |
| 980 | g.perm.NewTkt = g.perm.Password = g.perm.RdAddr = |
| 981 | g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt = 1; |
| 982 | /* Fall thru into Read/Write */ |
| 983 | case 'i': g.perm.Read = g.perm.Write = 1; break; |
| 984 | case 'o': g.perm.Read = 1; break; |
| 985 | case 'z': g.perm.Zip = 1; break; |
| 986 | |
| 987 | case 'd': g.perm.Delete = 1; break; |
| 988 | case 'h': g.perm.History = 1; break; |
| 989 | case 'g': g.perm.Clone = 1; break; |
| 990 | case 'p': g.perm.Password = 1; break; |
| 991 | |
| 992 | case 'j': g.perm.RdWiki = 1; break; |
| 993 | case 'k': g.perm.WrWiki = g.perm.RdWiki = g.perm.ApndWiki =1; break; |
| @@ -1053,15 +1055,14 @@ | |
| 1053 | case 'c': rc = g.perm.ApndTkt; break; |
| 1054 | case 'd': rc = g.perm.Delete; break; |
| 1055 | case 'e': rc = g.perm.RdAddr; break; |
| 1056 | case 'f': rc = g.perm.NewWiki; break; |
| 1057 | case 'g': rc = g.perm.Clone; break; |
| 1058 | case 'h': rc = g.perm.History; break; |
| 1059 | case 'i': rc = g.perm.Write; break; |
| 1060 | case 'j': rc = g.perm.RdWiki; break; |
| 1061 | case 'k': rc = g.perm.WrWiki; break; |
| 1062 | /* case 'l': */ |
| 1063 | case 'm': rc = g.perm.ApndWiki; break; |
| 1064 | case 'n': rc = g.perm.NewTkt; break; |
| 1065 | case 'o': rc = g.perm.Read; break; |
| 1066 | case 'p': rc = g.perm.Password; break; |
| 1067 | /* case 'q': */ |
| @@ -1129,23 +1130,23 @@ | |
| 1129 | assert(0); |
| 1130 | } |
| 1131 | } |
| 1132 | |
| 1133 | /* |
| 1134 | ** Call this routine if the user lacks okHistory permission. If |
| 1135 | ** the anonymous user has okHistory permission, then paint a mesage |
| 1136 | ** to inform the user that much more information is available by |
| 1137 | ** logging in as anonymous. |
| 1138 | */ |
| 1139 | void login_anonymous_available(void){ |
| 1140 | if( !g.perm.History && |
| 1141 | db_exists("SELECT 1 FROM user" |
| 1142 | " WHERE login='anonymous'" |
| 1143 | " AND cap LIKE '%%h%%'") ){ |
| 1144 | const char *zUrl = PD("REQUEST_URI", "index"); |
| 1145 | @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br /> |
| 1146 | @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a> |
| 1147 | @ to enable hyperlinks.</p> |
| 1148 | } |
| 1149 | } |
| 1150 | |
| 1151 | /* |
| 1152 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -562,11 +562,11 @@ | |
| 562 | redirect_to_g(); |
| 563 | } |
| 564 | } |
| 565 | style_header("Login/Logout"); |
| 566 | @ %s(zErrMsg) |
| 567 | if( zGoto && P("anon")==0 ){ |
| 568 | @ <p>A login is required for <a href="%h(zGoto)">%h(zGoto)</a>.</p> |
| 569 | } |
| 570 | @ <form action="login" method="post"> |
| 571 | if( zGoto ){ |
| 572 | @ <input type="hidden" name="g" value="%h(zGoto)" /> |
| @@ -911,13 +911,15 @@ | |
| 911 | } |
| 912 | |
| 913 | /* Set the capabilities */ |
| 914 | login_replace_capabilities(zCap, 0); |
| 915 | login_set_anon_nobody_capabilities(); |
| 916 | if( zCap[0] && !g.perm.Hyperlink |
| 917 | && db_get_boolean("auto-enable-hyperlinks",1) |
| 918 | && isHuman(P("HTTP_USER_AGENT")) ){ |
| 919 | g.perm.Hyperlink = 1; |
| 920 | g.javascriptHyperlink = 1; |
| 921 | } |
| 922 | |
| 923 | /* If the public-pages glob pattern is defined and REQUEST_URI matches |
| 924 | ** one of the globs in public-pages, then also add in all default-perms |
| 925 | ** permissions. |
| @@ -973,21 +975,21 @@ | |
| 975 | } |
| 976 | for(i=0; zCap[i]; i++){ |
| 977 | switch( zCap[i] ){ |
| 978 | case 's': g.perm.Setup = 1; /* Fall thru into Admin */ |
| 979 | case 'a': g.perm.Admin = g.perm.RdTkt = g.perm.WrTkt = g.perm.Zip = |
| 980 | g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki = |
| 981 | g.perm.ApndWiki = g.perm.Hyperlink = g.perm.Clone = |
| 982 | g.perm.NewTkt = g.perm.Password = g.perm.RdAddr = |
| 983 | g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt = 1; |
| 984 | /* Fall thru into Read/Write */ |
| 985 | case 'i': g.perm.Read = g.perm.Write = 1; break; |
| 986 | case 'o': g.perm.Read = 1; break; |
| 987 | case 'z': g.perm.Zip = 1; break; |
| 988 | |
| 989 | case 'd': g.perm.Delete = 1; break; |
| 990 | case 'h': g.perm.Hyperlink = 1; break; |
| 991 | case 'g': g.perm.Clone = 1; break; |
| 992 | case 'p': g.perm.Password = 1; break; |
| 993 | |
| 994 | case 'j': g.perm.RdWiki = 1; break; |
| 995 | case 'k': g.perm.WrWiki = g.perm.RdWiki = g.perm.ApndWiki =1; break; |
| @@ -1053,15 +1055,14 @@ | |
| 1055 | case 'c': rc = g.perm.ApndTkt; break; |
| 1056 | case 'd': rc = g.perm.Delete; break; |
| 1057 | case 'e': rc = g.perm.RdAddr; break; |
| 1058 | case 'f': rc = g.perm.NewWiki; break; |
| 1059 | case 'g': rc = g.perm.Clone; break; |
| 1060 | case 'h': rc = g.perm.Hyperlink; break; |
| 1061 | case 'i': rc = g.perm.Write; break; |
| 1062 | case 'j': rc = g.perm.RdWiki; break; |
| 1063 | case 'k': rc = g.perm.WrWiki; break; |
| 1064 | case 'm': rc = g.perm.ApndWiki; break; |
| 1065 | case 'n': rc = g.perm.NewTkt; break; |
| 1066 | case 'o': rc = g.perm.Read; break; |
| 1067 | case 'p': rc = g.perm.Password; break; |
| 1068 | /* case 'q': */ |
| @@ -1129,23 +1130,23 @@ | |
| 1130 | assert(0); |
| 1131 | } |
| 1132 | } |
| 1133 | |
| 1134 | /* |
| 1135 | ** Call this routine if the user lacks g.perm.Hyperlink permission. If |
| 1136 | ** the anonymous user has Hyperlink permission, then paint a mesage |
| 1137 | ** to inform the user that much more information is available by |
| 1138 | ** logging in as anonymous. |
| 1139 | */ |
| 1140 | void login_anonymous_available(void){ |
| 1141 | if( !g.perm.Hyperlink && |
| 1142 | db_exists("SELECT 1 FROM user" |
| 1143 | " WHERE login='anonymous'" |
| 1144 | " AND cap LIKE '%%h%%'") ){ |
| 1145 | const char *zUrl = PD("REQUEST_URI", "index"); |
| 1146 | @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br /> |
| 1147 | @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a> |
| 1148 | @ to enable hyperlinks.</p> |
| 1149 | } |
| 1150 | } |
| 1151 | |
| 1152 | /* |
| 1153 |
+3
-2
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -60,11 +60,11 @@ | ||
| 60 | 60 | char Delete; /* d: delete wiki or tickets */ |
| 61 | 61 | char Password; /* p: change password */ |
| 62 | 62 | char Query; /* q: create new reports */ |
| 63 | 63 | char Write; /* i: xfer inbound. checkin */ |
| 64 | 64 | char Read; /* o: xfer outbound. checkout */ |
| 65 | - char History; /* h: access historical information. */ | |
| 65 | + char Hyperlink; /* h: enable the display of hyperlinks */ | |
| 66 | 66 | char Clone; /* g: clone */ |
| 67 | 67 | char RdWiki; /* j: view wiki via web */ |
| 68 | 68 | char NewWiki; /* f: create new wiki via web */ |
| 69 | 69 | char ApndWiki; /* m: append to wiki via web */ |
| 70 | 70 | char WrWiki; /* k: edit wiki via web */ |
| @@ -135,11 +135,12 @@ | ||
| 135 | 135 | int xlinkClusterOnly; /* Set when cloning. Only process clusters */ |
| 136 | 136 | int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */ |
| 137 | 137 | int *aCommitFile; /* Array of files to be committed */ |
| 138 | 138 | int markPrivate; /* All new artifacts are private if true */ |
| 139 | 139 | int clockSkewSeen; /* True if clocks on client and server out of sync */ |
| 140 | - int isHTTP; /* True if running in server/CGI modes, else assume CLI. */ | |
| 140 | + char isHTTP; /* True if erver/CGI modes, else assume CLI. */ | |
| 141 | + char javascriptHyperlink; /* If true, set href= using script, not HTML */ | |
| 141 | 142 | |
| 142 | 143 | int urlIsFile; /* True if a "file:" url */ |
| 143 | 144 | int urlIsHttps; /* True if a "https:" url */ |
| 144 | 145 | int urlIsSsh; /* True if an "ssh:" url */ |
| 145 | 146 | char *urlName; /* Hostname for http: or filename for file: */ |
| 146 | 147 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -60,11 +60,11 @@ | |
| 60 | char Delete; /* d: delete wiki or tickets */ |
| 61 | char Password; /* p: change password */ |
| 62 | char Query; /* q: create new reports */ |
| 63 | char Write; /* i: xfer inbound. checkin */ |
| 64 | char Read; /* o: xfer outbound. checkout */ |
| 65 | char History; /* h: access historical information. */ |
| 66 | char Clone; /* g: clone */ |
| 67 | char RdWiki; /* j: view wiki via web */ |
| 68 | char NewWiki; /* f: create new wiki via web */ |
| 69 | char ApndWiki; /* m: append to wiki via web */ |
| 70 | char WrWiki; /* k: edit wiki via web */ |
| @@ -135,11 +135,12 @@ | |
| 135 | int xlinkClusterOnly; /* Set when cloning. Only process clusters */ |
| 136 | int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */ |
| 137 | int *aCommitFile; /* Array of files to be committed */ |
| 138 | int markPrivate; /* All new artifacts are private if true */ |
| 139 | int clockSkewSeen; /* True if clocks on client and server out of sync */ |
| 140 | int isHTTP; /* True if running in server/CGI modes, else assume CLI. */ |
| 141 | |
| 142 | int urlIsFile; /* True if a "file:" url */ |
| 143 | int urlIsHttps; /* True if a "https:" url */ |
| 144 | int urlIsSsh; /* True if an "ssh:" url */ |
| 145 | char *urlName; /* Hostname for http: or filename for file: */ |
| 146 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -60,11 +60,11 @@ | |
| 60 | char Delete; /* d: delete wiki or tickets */ |
| 61 | char Password; /* p: change password */ |
| 62 | char Query; /* q: create new reports */ |
| 63 | char Write; /* i: xfer inbound. checkin */ |
| 64 | char Read; /* o: xfer outbound. checkout */ |
| 65 | char Hyperlink; /* h: enable the display of hyperlinks */ |
| 66 | char Clone; /* g: clone */ |
| 67 | char RdWiki; /* j: view wiki via web */ |
| 68 | char NewWiki; /* f: create new wiki via web */ |
| 69 | char ApndWiki; /* m: append to wiki via web */ |
| 70 | char WrWiki; /* k: edit wiki via web */ |
| @@ -135,11 +135,12 @@ | |
| 135 | int xlinkClusterOnly; /* Set when cloning. Only process clusters */ |
| 136 | int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */ |
| 137 | int *aCommitFile; /* Array of files to be committed */ |
| 138 | int markPrivate; /* All new artifacts are private if true */ |
| 139 | int clockSkewSeen; /* True if clocks on client and server out of sync */ |
| 140 | char isHTTP; /* True if erver/CGI modes, else assume CLI. */ |
| 141 | char javascriptHyperlink; /* If true, set href= using script, not HTML */ |
| 142 | |
| 143 | int urlIsFile; /* True if a "file:" url */ |
| 144 | int urlIsHttps; /* True if a "https:" url */ |
| 145 | int urlIsSsh; /* True if an "ssh:" url */ |
| 146 | char *urlName; /* Hostname for http: or filename for file: */ |
| 147 |
+7
| --- src/printf.c | ||
| +++ src/printf.c | ||
| @@ -47,10 +47,11 @@ | ||
| 47 | 47 | #define etFOSSILIZE 19 /* The fossil header encoding format. */ |
| 48 | 48 | #define etPATH 20 /* Path type */ |
| 49 | 49 | #define etWIKISTR 21 /* Wiki text rendered from a char*: %w */ |
| 50 | 50 | #define etWIKIBLOB 22 /* Wiki text rendered from a Blob*: %W */ |
| 51 | 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 | 56 | ** An "etByte" is an 8-bit unsigned value. |
| 56 | 57 | */ |
| @@ -93,10 +94,11 @@ | ||
| 93 | 94 | { 'b', 0, 2, etBLOB, 0, 0 }, |
| 94 | 95 | { 'B', 0, 2, etBLOBSQL, 0, 0 }, |
| 95 | 96 | { 'w', 0, 2, etWIKISTR, 0, 0 }, |
| 96 | 97 | { 'W', 0, 2, etWIKIBLOB, 0, 0 }, |
| 97 | 98 | { 'h', 0, 4, etHTMLIZE, 0, 0 }, |
| 99 | + { 'R', 0, 0, etROOT, 0, 0 }, | |
| 98 | 100 | { 't', 0, 4, etHTTPIZE, 0, 0 }, /* "/" -> "%2F" */ |
| 99 | 101 | { 'T', 0, 4, etURLIZE, 0, 0 }, /* "/" unchanged */ |
| 100 | 102 | { 'F', 0, 4, etFOSSILIZE, 0, 0 }, |
| 101 | 103 | { 'S', 0, 4, etSTRINGID, 0, 0 }, |
| 102 | 104 | { 'c', 0, 0, etCHARX, 0, 0 }, |
| @@ -570,10 +572,15 @@ | ||
| 570 | 572 | bufpt[i]=e[i]; |
| 571 | 573 | } |
| 572 | 574 | } |
| 573 | 575 | bufpt[length]='\0'; |
| 574 | 576 | break; |
| 577 | + } | |
| 578 | + case etROOT: { | |
| 579 | + bufpt = g.zTop; | |
| 580 | + length = (int)strlen(bufpt); | |
| 581 | + break; | |
| 575 | 582 | } |
| 576 | 583 | case etSTRINGID: { |
| 577 | 584 | precision = 16; |
| 578 | 585 | /* Fall through */ |
| 579 | 586 | } |
| 580 | 587 |
| --- src/printf.c | |
| +++ src/printf.c | |
| @@ -47,10 +47,11 @@ | |
| 47 | #define etFOSSILIZE 19 /* The fossil header encoding format. */ |
| 48 | #define etPATH 20 /* Path type */ |
| 49 | #define etWIKISTR 21 /* Wiki text rendered from a char*: %w */ |
| 50 | #define etWIKIBLOB 22 /* Wiki text rendered from a Blob*: %W */ |
| 51 | #define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */ |
| 52 | |
| 53 | |
| 54 | /* |
| 55 | ** An "etByte" is an 8-bit unsigned value. |
| 56 | */ |
| @@ -93,10 +94,11 @@ | |
| 93 | { 'b', 0, 2, etBLOB, 0, 0 }, |
| 94 | { 'B', 0, 2, etBLOBSQL, 0, 0 }, |
| 95 | { 'w', 0, 2, etWIKISTR, 0, 0 }, |
| 96 | { 'W', 0, 2, etWIKIBLOB, 0, 0 }, |
| 97 | { 'h', 0, 4, etHTMLIZE, 0, 0 }, |
| 98 | { 't', 0, 4, etHTTPIZE, 0, 0 }, /* "/" -> "%2F" */ |
| 99 | { 'T', 0, 4, etURLIZE, 0, 0 }, /* "/" unchanged */ |
| 100 | { 'F', 0, 4, etFOSSILIZE, 0, 0 }, |
| 101 | { 'S', 0, 4, etSTRINGID, 0, 0 }, |
| 102 | { 'c', 0, 0, etCHARX, 0, 0 }, |
| @@ -570,10 +572,15 @@ | |
| 570 | bufpt[i]=e[i]; |
| 571 | } |
| 572 | } |
| 573 | bufpt[length]='\0'; |
| 574 | break; |
| 575 | } |
| 576 | case etSTRINGID: { |
| 577 | precision = 16; |
| 578 | /* Fall through */ |
| 579 | } |
| 580 |
| --- src/printf.c | |
| +++ src/printf.c | |
| @@ -47,10 +47,11 @@ | |
| 47 | #define etFOSSILIZE 19 /* The fossil header encoding format. */ |
| 48 | #define etPATH 20 /* Path type */ |
| 49 | #define etWIKISTR 21 /* Wiki text rendered from a char*: %w */ |
| 50 | #define etWIKIBLOB 22 /* Wiki text rendered from a Blob*: %W */ |
| 51 | #define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */ |
| 52 | #define etROOT 24 /* String value of g.zTop: % */ |
| 53 | |
| 54 | |
| 55 | /* |
| 56 | ** An "etByte" is an 8-bit unsigned value. |
| 57 | */ |
| @@ -93,10 +94,11 @@ | |
| 94 | { 'b', 0, 2, etBLOB, 0, 0 }, |
| 95 | { 'B', 0, 2, etBLOBSQL, 0, 0 }, |
| 96 | { 'w', 0, 2, etWIKISTR, 0, 0 }, |
| 97 | { 'W', 0, 2, etWIKIBLOB, 0, 0 }, |
| 98 | { 'h', 0, 4, etHTMLIZE, 0, 0 }, |
| 99 | { 'R', 0, 0, etROOT, 0, 0 }, |
| 100 | { 't', 0, 4, etHTTPIZE, 0, 0 }, /* "/" -> "%2F" */ |
| 101 | { 'T', 0, 4, etURLIZE, 0, 0 }, /* "/" unchanged */ |
| 102 | { 'F', 0, 4, etFOSSILIZE, 0, 0 }, |
| 103 | { 'S', 0, 4, etSTRINGID, 0, 0 }, |
| 104 | { 'c', 0, 0, etCHARX, 0, 0 }, |
| @@ -570,10 +572,15 @@ | |
| 572 | bufpt[i]=e[i]; |
| 573 | } |
| 574 | } |
| 575 | bufpt[length]='\0'; |
| 576 | break; |
| 577 | } |
| 578 | case etROOT: { |
| 579 | bufpt = g.zTop; |
| 580 | length = (int)strlen(bufpt); |
| 581 | break; |
| 582 | } |
| 583 | case etSTRINGID: { |
| 584 | precision = 16; |
| 585 | /* Fall through */ |
| 586 | } |
| 587 |
+12
-13
| --- src/report.c | ||
| +++ src/report.c | ||
| @@ -56,26 +56,29 @@ | ||
| 56 | 56 | cnt++; |
| 57 | 57 | blob_appendf(&ril, "<li>"); |
| 58 | 58 | if( zTitle[0] == '_' ){ |
| 59 | 59 | blob_appendf(&ril, "%s", zTitle); |
| 60 | 60 | } else { |
| 61 | - blob_appendf(&ril, "<a href=\"rptview?rn=%d\" rel=\"nofollow\">%h</a>", rn, zTitle); | |
| 61 | + blob_appendf(&ril, "%z%h</a>", href("%R/rptview?rn=%d", rn), zTitle); | |
| 62 | 62 | } |
| 63 | 63 | blob_appendf(&ril, " "); |
| 64 | 64 | if( g.perm.Write && zOwner && zOwner[0] ){ |
| 65 | 65 | blob_appendf(&ril, "(by <i>%h</i></i>) ", zOwner); |
| 66 | 66 | } |
| 67 | 67 | if( g.perm.TktFmt ){ |
| 68 | - blob_appendf(&ril, "[<a href=\"rptedit?rn=%d&copy=1\" rel=\"nofollow\">copy</a>] ", rn); | |
| 68 | + blob_appendf(&ril, "[%zcopy</a>] ", | |
| 69 | + href("%R/rptedit?rn=%d©=1", rn)); | |
| 69 | 70 | } |
| 70 | 71 | if( g.perm.Admin |
| 71 | 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>] ", rn); | |
| 74 | + blob_appendf(&ril, "[%zedit</a>]", | |
| 75 | + href("%R/rptedit?rn=%d", rn)); | |
| 74 | 76 | } |
| 75 | 77 | if( g.perm.TktFmt ){ |
| 76 | - blob_appendf(&ril, "[<a href=\"rptsql?rn=%d\" rel=\"nofollow\">sql</a>] ", rn); | |
| 78 | + blob_appendf(&ril, "[%zsql</a>]", | |
| 79 | + href("%R/rptsql?rn=%d", rn)); | |
| 77 | 80 | } |
| 78 | 81 | blob_appendf(&ril, "</li>\n"); |
| 79 | 82 | } |
| 80 | 83 | |
| 81 | 84 | Th_Store("report_items", blob_str(&ril)); |
| @@ -416,11 +419,11 @@ | ||
| 416 | 419 | } |
| 417 | 420 | } |
| 418 | 421 | if( zOwner==0 ) zOwner = g.zLogin; |
| 419 | 422 | style_submenu_element("Cancel", "Cancel", "reportlist"); |
| 420 | 423 | if( rn>0 ){ |
| 421 | - style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn); | |
| 424 | + style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn); | |
| 422 | 425 | } |
| 423 | 426 | style_header(rn>0 ? "Edit Report Format":"Create New Report Format"); |
| 424 | 427 | if( zErr ){ |
| 425 | 428 | @ <blockquote class="reportError">%h(zErr)</blockquote> |
| 426 | 429 | } |
| @@ -720,11 +723,11 @@ | ||
| 720 | 723 | if( i==pState->iBg ) continue; |
| 721 | 724 | zData = azArg[i]; |
| 722 | 725 | if( zData==0 ) zData = ""; |
| 723 | 726 | if( pState->iNewRow>=0 && i>=pState->iNewRow ){ |
| 724 | 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 | 729 | zTid = 0; |
| 727 | 730 | } |
| 728 | 731 | if( zData[0] ){ |
| 729 | 732 | Blob content; |
| 730 | 733 | @ </tr><tr style="background-color:%h(zBg)"><td colspan=%d(pState->nCol)> |
| @@ -732,25 +735,21 @@ | ||
| 732 | 735 | wiki_convert(&content, 0, 0); |
| 733 | 736 | blob_reset(&content); |
| 734 | 737 | } |
| 735 | 738 | }else if( azName[i][0]=='#' ){ |
| 736 | 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> | |
| 741 | - } | |
| 740 | + @ <td valign="top">%z(href("%R/tktview?name=%h",zData))%h(zData)</a></td> | |
| 742 | 741 | }else if( zData[0]==0 ){ |
| 743 | 742 | @ <td valign="top"> </td> |
| 744 | 743 | }else{ |
| 745 | 744 | @ <td valign="top"> |
| 746 | 745 | @ %h(zData) |
| 747 | 746 | @ </td> |
| 748 | 747 | } |
| 749 | 748 | } |
| 750 | 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 | 752 | @ </tr> |
| 754 | 753 | return 0; |
| 755 | 754 | } |
| 756 | 755 | |
| @@ -949,11 +948,11 @@ | ||
| 949 | 948 | if( !tabs ){ |
| 950 | 949 | struct GenerateHTML sState; |
| 951 | 950 | |
| 952 | 951 | db_multi_exec("PRAGMA empty_result_callbacks=ON"); |
| 953 | 952 | style_submenu_element("Raw", "Raw", |
| 954 | - "rptview?tablist=1&%h", PD("QUERY_STRING","")); | |
| 953 | + "rptview?tablist=1&%h", PD("QUERY_STRING","")); | |
| 955 | 954 | if( g.perm.Admin |
| 956 | 955 | || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){ |
| 957 | 956 | style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn); |
| 958 | 957 | } |
| 959 | 958 | if( g.perm.TktFmt ){ |
| 960 | 959 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -56,26 +56,29 @@ | |
| 56 | cnt++; |
| 57 | blob_appendf(&ril, "<li>"); |
| 58 | if( zTitle[0] == '_' ){ |
| 59 | blob_appendf(&ril, "%s", zTitle); |
| 60 | } else { |
| 61 | blob_appendf(&ril, "<a href=\"rptview?rn=%d\" rel=\"nofollow\">%h</a>", rn, zTitle); |
| 62 | } |
| 63 | blob_appendf(&ril, " "); |
| 64 | if( g.perm.Write && zOwner && zOwner[0] ){ |
| 65 | blob_appendf(&ril, "(by <i>%h</i></i>) ", zOwner); |
| 66 | } |
| 67 | if( g.perm.TktFmt ){ |
| 68 | blob_appendf(&ril, "[<a href=\"rptedit?rn=%d&copy=1\" rel=\"nofollow\">copy</a>] ", rn); |
| 69 | } |
| 70 | if( g.perm.Admin |
| 71 | || (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0) |
| 72 | ){ |
| 73 | blob_appendf(&ril, "[<a href=\"rptedit?rn=%d\" rel=\"nofollow\">edit</a>] ", rn); |
| 74 | } |
| 75 | if( g.perm.TktFmt ){ |
| 76 | blob_appendf(&ril, "[<a href=\"rptsql?rn=%d\" rel=\"nofollow\">sql</a>] ", rn); |
| 77 | } |
| 78 | blob_appendf(&ril, "</li>\n"); |
| 79 | } |
| 80 | |
| 81 | Th_Store("report_items", blob_str(&ril)); |
| @@ -416,11 +419,11 @@ | |
| 416 | } |
| 417 | } |
| 418 | if( zOwner==0 ) zOwner = g.zLogin; |
| 419 | style_submenu_element("Cancel", "Cancel", "reportlist"); |
| 420 | if( rn>0 ){ |
| 421 | style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn); |
| 422 | } |
| 423 | style_header(rn>0 ? "Edit Report Format":"Create New Report Format"); |
| 424 | if( zErr ){ |
| 425 | @ <blockquote class="reportError">%h(zErr)</blockquote> |
| 426 | } |
| @@ -720,11 +723,11 @@ | |
| 720 | if( i==pState->iBg ) continue; |
| 721 | zData = azArg[i]; |
| 722 | if( zData==0 ) zData = ""; |
| 723 | if( pState->iNewRow>=0 && i>=pState->iNewRow ){ |
| 724 | if( zTid && g.perm.Write ){ |
| 725 | @ <td valign="top"><a href="tktedit/%h(zTid)">edit</a></td> |
| 726 | zTid = 0; |
| 727 | } |
| 728 | if( zData[0] ){ |
| 729 | Blob content; |
| 730 | @ </tr><tr style="background-color:%h(zBg)"><td colspan=%d(pState->nCol)> |
| @@ -732,25 +735,21 @@ | |
| 732 | wiki_convert(&content, 0, 0); |
| 733 | blob_reset(&content); |
| 734 | } |
| 735 | }else if( azName[i][0]=='#' ){ |
| 736 | zTid = zData; |
| 737 | if( g.perm.History ){ |
| 738 | @ <td valign="top"><a href="tktview?name=%h(zData)">%h(zData)</a></td> |
| 739 | }else{ |
| 740 | @ <td valign="top">%h(zData)</td> |
| 741 | } |
| 742 | }else if( zData[0]==0 ){ |
| 743 | @ <td valign="top"> </td> |
| 744 | }else{ |
| 745 | @ <td valign="top"> |
| 746 | @ %h(zData) |
| 747 | @ </td> |
| 748 | } |
| 749 | } |
| 750 | if( zTid && g.perm.Write ){ |
| 751 | @ <td valign="top"><a href="tktedit/%h(zTid)">edit</a></td> |
| 752 | } |
| 753 | @ </tr> |
| 754 | return 0; |
| 755 | } |
| 756 | |
| @@ -949,11 +948,11 @@ | |
| 949 | if( !tabs ){ |
| 950 | struct GenerateHTML sState; |
| 951 | |
| 952 | db_multi_exec("PRAGMA empty_result_callbacks=ON"); |
| 953 | style_submenu_element("Raw", "Raw", |
| 954 | "rptview?tablist=1&%h", PD("QUERY_STRING","")); |
| 955 | if( g.perm.Admin |
| 956 | || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){ |
| 957 | style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn); |
| 958 | } |
| 959 | if( g.perm.TktFmt ){ |
| 960 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -56,26 +56,29 @@ | |
| 56 | cnt++; |
| 57 | blob_appendf(&ril, "<li>"); |
| 58 | if( zTitle[0] == '_' ){ |
| 59 | blob_appendf(&ril, "%s", zTitle); |
| 60 | } else { |
| 61 | blob_appendf(&ril, "%z%h</a>", href("%R/rptview?rn=%d", rn), zTitle); |
| 62 | } |
| 63 | blob_appendf(&ril, " "); |
| 64 | if( g.perm.Write && zOwner && zOwner[0] ){ |
| 65 | blob_appendf(&ril, "(by <i>%h</i></i>) ", zOwner); |
| 66 | } |
| 67 | if( g.perm.TktFmt ){ |
| 68 | blob_appendf(&ril, "[%zcopy</a>] ", |
| 69 | href("%R/rptedit?rn=%d©=1", rn)); |
| 70 | } |
| 71 | if( g.perm.Admin |
| 72 | || (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0) |
| 73 | ){ |
| 74 | blob_appendf(&ril, "[%zedit</a>]", |
| 75 | href("%R/rptedit?rn=%d", rn)); |
| 76 | } |
| 77 | if( g.perm.TktFmt ){ |
| 78 | blob_appendf(&ril, "[%zsql</a>]", |
| 79 | href("%R/rptsql?rn=%d", rn)); |
| 80 | } |
| 81 | blob_appendf(&ril, "</li>\n"); |
| 82 | } |
| 83 | |
| 84 | Th_Store("report_items", blob_str(&ril)); |
| @@ -416,11 +419,11 @@ | |
| 419 | } |
| 420 | } |
| 421 | if( zOwner==0 ) zOwner = g.zLogin; |
| 422 | style_submenu_element("Cancel", "Cancel", "reportlist"); |
| 423 | if( rn>0 ){ |
| 424 | style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn); |
| 425 | } |
| 426 | style_header(rn>0 ? "Edit Report Format":"Create New Report Format"); |
| 427 | if( zErr ){ |
| 428 | @ <blockquote class="reportError">%h(zErr)</blockquote> |
| 429 | } |
| @@ -720,11 +723,11 @@ | |
| 723 | if( i==pState->iBg ) continue; |
| 724 | zData = azArg[i]; |
| 725 | if( zData==0 ) zData = ""; |
| 726 | if( pState->iNewRow>=0 && i>=pState->iNewRow ){ |
| 727 | if( zTid && g.perm.Write ){ |
| 728 | @ <td valign="top">%z(href("%R/tktedit/%h",zTid))edit</a></td> |
| 729 | zTid = 0; |
| 730 | } |
| 731 | if( zData[0] ){ |
| 732 | Blob content; |
| 733 | @ </tr><tr style="background-color:%h(zBg)"><td colspan=%d(pState->nCol)> |
| @@ -732,25 +735,21 @@ | |
| 735 | wiki_convert(&content, 0, 0); |
| 736 | blob_reset(&content); |
| 737 | } |
| 738 | }else if( azName[i][0]=='#' ){ |
| 739 | zTid = zData; |
| 740 | @ <td valign="top">%z(href("%R/tktview?name=%h",zData))%h(zData)</a></td> |
| 741 | }else if( zData[0]==0 ){ |
| 742 | @ <td valign="top"> </td> |
| 743 | }else{ |
| 744 | @ <td valign="top"> |
| 745 | @ %h(zData) |
| 746 | @ </td> |
| 747 | } |
| 748 | } |
| 749 | if( zTid && g.perm.Write ){ |
| 750 | @ <td valign="top">%z(href("%R/tktedit/%h",zTid))edit</a></td> |
| 751 | } |
| 752 | @ </tr> |
| 753 | return 0; |
| 754 | } |
| 755 | |
| @@ -949,11 +948,11 @@ | |
| 948 | if( !tabs ){ |
| 949 | struct GenerateHTML sState; |
| 950 | |
| 951 | db_multi_exec("PRAGMA empty_result_callbacks=ON"); |
| 952 | style_submenu_element("Raw", "Raw", |
| 953 | "rptview?tablist=1&%h", PD("QUERY_STRING","")); |
| 954 | if( g.perm.Admin |
| 955 | || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){ |
| 956 | style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn); |
| 957 | } |
| 958 | if( g.perm.TktFmt ){ |
| 959 |
+23
-15
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -524,11 +524,11 @@ | ||
| 524 | 524 | @ <input type="checkbox" name="ad"%s(oad) />%s(B('d'))Delete<br /> |
| 525 | 525 | @ <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br /> |
| 526 | 526 | @ <input type="checkbox" name="ap"%s(oap) />%s(B('p'))Password<br /> |
| 527 | 527 | @ <input type="checkbox" name="ai"%s(oai) />%s(B('i'))Check-In<br /> |
| 528 | 528 | @ <input type="checkbox" name="ao"%s(oao) />%s(B('o'))Check-Out<br /> |
| 529 | - @ <input type="checkbox" name="ah"%s(oah) />%s(B('h'))History<br /> | |
| 529 | + @ <input type="checkbox" name="ah"%s(oah) />%s(B('h'))Hyperlinks<br /> | |
| 530 | 530 | @ <input type="checkbox" name="au"%s(oau) />%s(B('u'))Reader<br /> |
| 531 | 531 | @ <input type="checkbox" name="av"%s(oav) />%s(B('v'))Developer<br /> |
| 532 | 532 | @ <input type="checkbox" name="ag"%s(oag) />%s(B('g'))Clone<br /> |
| 533 | 533 | @ <input type="checkbox" name="aj"%s(oaj) />%s(B('j'))Read Wiki<br /> |
| 534 | 534 | @ <input type="checkbox" name="af"%s(oaf) />%s(B('f'))New Wiki<br /> |
| @@ -625,24 +625,24 @@ | ||
| 625 | 625 | @ is first posted. The <span class="usertype">Setup</span> user can |
| 626 | 626 | @ delete anything at any time. |
| 627 | 627 | @ </p></li> |
| 628 | 628 | @ |
| 629 | 629 | @ <li><p> |
| 630 | - @ The <span class="capability">History</span> privilege allows a user | |
| 630 | + @ The <span class="capability">Hyperlinks</span> privilege allows a user | |
| 631 | 631 | @ to see most hyperlinks. This is recommended ON for most logged-in users |
| 632 | 632 | @ but OFF for user "nobody" to avoid problems with spiders trying to walk |
| 633 | - @ every historical version of every baseline and file. | |
| 633 | + @ every diff and annotation of every historical check-in and file. | |
| 634 | 634 | @ </p></li> |
| 635 | 635 | @ |
| 636 | 636 | @ <li><p> |
| 637 | 637 | @ The <span class="capability">Zip</span> privilege allows a user to |
| 638 | 638 | @ see the "download as ZIP" |
| 639 | 639 | @ hyperlink and permits access to the <tt>/zip</tt> page. This allows |
| 640 | 640 | @ users to download ZIP archives without granting other rights like |
| 641 | 641 | @ <span class="capability">Read</span> or |
| 642 | - @ <span class="capability">History</span>. This privilege is recommended for | |
| 643 | - @ user <span class="usertype">nobody</span> so that automatic package | |
| 642 | + @ <span class="capability">Hyperlink</span>. The "z" privilege is recommended | |
| 643 | + @ for user <span class="usertype">nobody</span> so that automatic package | |
| 644 | 644 | @ downloaders can obtain the sources without going through the login |
| 645 | 645 | @ procedure. |
| 646 | 646 | @ </p></li> |
| 647 | 647 | @ |
| 648 | 648 | @ <li><p> |
| @@ -704,12 +704,12 @@ | ||
| 704 | 704 | @ To disable universal access to the repository, make sure no user named |
| 705 | 705 | @ <span class="usertype">nobody</span> exists or that the |
| 706 | 706 | @ <span class="usertype">nobody</span> user has no capabilities |
| 707 | 707 | @ enabled. The password for <span class="usertype">nobody</span> is ignore. |
| 708 | 708 | @ To avoid problems with spiders overloading the server, it is recommended |
| 709 | - @ that the <span class="capability">h</span> (History) capability be turned | |
| 710 | - @ off for the <span class="usertype">nobody</span> user. | |
| 709 | + @ that the <span class="capability">h</span> (Hyperlinks) capability be | |
| 710 | + @ turned off for the <span class="usertype">nobody</span> user. | |
| 711 | 711 | @ </p></li> |
| 712 | 712 | @ |
| 713 | 713 | @ <li><p> |
| 714 | 714 | @ Login is required for user <span class="usertype">anonymous</span> but the |
| 715 | 715 | @ password is displayed on the login screen beside the password entry box |
| @@ -891,19 +891,27 @@ | ||
| 891 | 891 | @ than this, then the client will issue multiple HTTP requests. |
| 892 | 892 | @ Values below 1 million are not recommended. 5 million is a |
| 893 | 893 | @ reasonable number.</p> |
| 894 | 894 | |
| 895 | 895 | @ <hr /> |
| 896 | - onoff_attribute("Enable hyperlinks for \"nobody\" based on User-Agent", | |
| 897 | - "auto-enable-hyperlinks", "autohyperlink", 1); | |
| 896 | + onoff_attribute( | |
| 897 | + "Enable hyperlinks for \"nobody\" based on User-Agent and Javascript", | |
| 898 | + "auto-enable-hyperlinks", "autohyperlink", 1); | |
| 898 | 899 | @ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users |
| 899 | - @ including user "nobody", as long as the User-Agent string in the HTTP header | |
| 900 | - @ indicates that the request is coming from an actual human being and not a | |
| 901 | - @ a robot or script. Note: Bots can specify whatever User-Agent string they | |
| 902 | - @ that want. So a bot that wants to impersonate a human can easily do so. | |
| 903 | - @ Hence, this technique does not necessarily exclude malicious bots. | |
| 904 | - @ </p> | |
| 900 | + @ including user "nobody", as long as (1) the User-Agent string in the | |
| 901 | + @ HTTP header indicates that the request is coming from an actual human | |
| 902 | + @ being and not a a robot or spider and (2) the user agent is able to | |
| 903 | + @ run Javascript in order to set the href= attribute of hyperlinks. Bots | |
| 904 | + @ and spiders can specify whatever User-Agent string they that want and | |
| 905 | + @ they can run javascript just like browsers. But most bots don't go to | |
| 906 | + @ that much trouble so this is normally an effective defense.</p> | |
| 907 | + @ | |
| 908 | + @ <p>You do not normally want a bot to walk your entire repository because | |
| 909 | + @ if it does, your server will end up computing diffs and annotations for | |
| 910 | + @ every historical version of every file and creating ZIPs and tarballs of | |
| 911 | + @ every historical check-in, which can use a lot of CPU and bandwidth | |
| 912 | + @ even for relatively small projects.</p> | |
| 905 | 913 | |
| 906 | 914 | @ <hr /> |
| 907 | 915 | entry_attribute("Public pages", 30, "public-pages", |
| 908 | 916 | "pubpage", ""); |
| 909 | 917 | @ <p>A comma-separated list of glob patterns for pages that are accessible |
| 910 | 918 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -524,11 +524,11 @@ | |
| 524 | @ <input type="checkbox" name="ad"%s(oad) />%s(B('d'))Delete<br /> |
| 525 | @ <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br /> |
| 526 | @ <input type="checkbox" name="ap"%s(oap) />%s(B('p'))Password<br /> |
| 527 | @ <input type="checkbox" name="ai"%s(oai) />%s(B('i'))Check-In<br /> |
| 528 | @ <input type="checkbox" name="ao"%s(oao) />%s(B('o'))Check-Out<br /> |
| 529 | @ <input type="checkbox" name="ah"%s(oah) />%s(B('h'))History<br /> |
| 530 | @ <input type="checkbox" name="au"%s(oau) />%s(B('u'))Reader<br /> |
| 531 | @ <input type="checkbox" name="av"%s(oav) />%s(B('v'))Developer<br /> |
| 532 | @ <input type="checkbox" name="ag"%s(oag) />%s(B('g'))Clone<br /> |
| 533 | @ <input type="checkbox" name="aj"%s(oaj) />%s(B('j'))Read Wiki<br /> |
| 534 | @ <input type="checkbox" name="af"%s(oaf) />%s(B('f'))New Wiki<br /> |
| @@ -625,24 +625,24 @@ | |
| 625 | @ is first posted. The <span class="usertype">Setup</span> user can |
| 626 | @ delete anything at any time. |
| 627 | @ </p></li> |
| 628 | @ |
| 629 | @ <li><p> |
| 630 | @ The <span class="capability">History</span> privilege allows a user |
| 631 | @ to see most hyperlinks. This is recommended ON for most logged-in users |
| 632 | @ but OFF for user "nobody" to avoid problems with spiders trying to walk |
| 633 | @ every historical version of every baseline and file. |
| 634 | @ </p></li> |
| 635 | @ |
| 636 | @ <li><p> |
| 637 | @ The <span class="capability">Zip</span> privilege allows a user to |
| 638 | @ see the "download as ZIP" |
| 639 | @ hyperlink and permits access to the <tt>/zip</tt> page. This allows |
| 640 | @ users to download ZIP archives without granting other rights like |
| 641 | @ <span class="capability">Read</span> or |
| 642 | @ <span class="capability">History</span>. This privilege is recommended for |
| 643 | @ user <span class="usertype">nobody</span> so that automatic package |
| 644 | @ downloaders can obtain the sources without going through the login |
| 645 | @ procedure. |
| 646 | @ </p></li> |
| 647 | @ |
| 648 | @ <li><p> |
| @@ -704,12 +704,12 @@ | |
| 704 | @ To disable universal access to the repository, make sure no user named |
| 705 | @ <span class="usertype">nobody</span> exists or that the |
| 706 | @ <span class="usertype">nobody</span> user has no capabilities |
| 707 | @ enabled. The password for <span class="usertype">nobody</span> is ignore. |
| 708 | @ To avoid problems with spiders overloading the server, it is recommended |
| 709 | @ that the <span class="capability">h</span> (History) capability be turned |
| 710 | @ off for the <span class="usertype">nobody</span> user. |
| 711 | @ </p></li> |
| 712 | @ |
| 713 | @ <li><p> |
| 714 | @ Login is required for user <span class="usertype">anonymous</span> but the |
| 715 | @ password is displayed on the login screen beside the password entry box |
| @@ -891,19 +891,27 @@ | |
| 891 | @ than this, then the client will issue multiple HTTP requests. |
| 892 | @ Values below 1 million are not recommended. 5 million is a |
| 893 | @ reasonable number.</p> |
| 894 | |
| 895 | @ <hr /> |
| 896 | onoff_attribute("Enable hyperlinks for \"nobody\" based on User-Agent", |
| 897 | "auto-enable-hyperlinks", "autohyperlink", 1); |
| 898 | @ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users |
| 899 | @ including user "nobody", as long as the User-Agent string in the HTTP header |
| 900 | @ indicates that the request is coming from an actual human being and not a |
| 901 | @ a robot or script. Note: Bots can specify whatever User-Agent string they |
| 902 | @ that want. So a bot that wants to impersonate a human can easily do so. |
| 903 | @ Hence, this technique does not necessarily exclude malicious bots. |
| 904 | @ </p> |
| 905 | |
| 906 | @ <hr /> |
| 907 | entry_attribute("Public pages", 30, "public-pages", |
| 908 | "pubpage", ""); |
| 909 | @ <p>A comma-separated list of glob patterns for pages that are accessible |
| 910 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -524,11 +524,11 @@ | |
| 524 | @ <input type="checkbox" name="ad"%s(oad) />%s(B('d'))Delete<br /> |
| 525 | @ <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br /> |
| 526 | @ <input type="checkbox" name="ap"%s(oap) />%s(B('p'))Password<br /> |
| 527 | @ <input type="checkbox" name="ai"%s(oai) />%s(B('i'))Check-In<br /> |
| 528 | @ <input type="checkbox" name="ao"%s(oao) />%s(B('o'))Check-Out<br /> |
| 529 | @ <input type="checkbox" name="ah"%s(oah) />%s(B('h'))Hyperlinks<br /> |
| 530 | @ <input type="checkbox" name="au"%s(oau) />%s(B('u'))Reader<br /> |
| 531 | @ <input type="checkbox" name="av"%s(oav) />%s(B('v'))Developer<br /> |
| 532 | @ <input type="checkbox" name="ag"%s(oag) />%s(B('g'))Clone<br /> |
| 533 | @ <input type="checkbox" name="aj"%s(oaj) />%s(B('j'))Read Wiki<br /> |
| 534 | @ <input type="checkbox" name="af"%s(oaf) />%s(B('f'))New Wiki<br /> |
| @@ -625,24 +625,24 @@ | |
| 625 | @ is first posted. The <span class="usertype">Setup</span> user can |
| 626 | @ delete anything at any time. |
| 627 | @ </p></li> |
| 628 | @ |
| 629 | @ <li><p> |
| 630 | @ The <span class="capability">Hyperlinks</span> privilege allows a user |
| 631 | @ to see most hyperlinks. This is recommended ON for most logged-in users |
| 632 | @ but OFF for user "nobody" to avoid problems with spiders trying to walk |
| 633 | @ every diff and annotation of every historical check-in and file. |
| 634 | @ </p></li> |
| 635 | @ |
| 636 | @ <li><p> |
| 637 | @ The <span class="capability">Zip</span> privilege allows a user to |
| 638 | @ see the "download as ZIP" |
| 639 | @ hyperlink and permits access to the <tt>/zip</tt> page. This allows |
| 640 | @ users to download ZIP archives without granting other rights like |
| 641 | @ <span class="capability">Read</span> or |
| 642 | @ <span class="capability">Hyperlink</span>. The "z" privilege is recommended |
| 643 | @ for user <span class="usertype">nobody</span> so that automatic package |
| 644 | @ downloaders can obtain the sources without going through the login |
| 645 | @ procedure. |
| 646 | @ </p></li> |
| 647 | @ |
| 648 | @ <li><p> |
| @@ -704,12 +704,12 @@ | |
| 704 | @ To disable universal access to the repository, make sure no user named |
| 705 | @ <span class="usertype">nobody</span> exists or that the |
| 706 | @ <span class="usertype">nobody</span> user has no capabilities |
| 707 | @ enabled. The password for <span class="usertype">nobody</span> is ignore. |
| 708 | @ To avoid problems with spiders overloading the server, it is recommended |
| 709 | @ that the <span class="capability">h</span> (Hyperlinks) capability be |
| 710 | @ turned off for the <span class="usertype">nobody</span> user. |
| 711 | @ </p></li> |
| 712 | @ |
| 713 | @ <li><p> |
| 714 | @ Login is required for user <span class="usertype">anonymous</span> but the |
| 715 | @ password is displayed on the login screen beside the password entry box |
| @@ -891,19 +891,27 @@ | |
| 891 | @ than this, then the client will issue multiple HTTP requests. |
| 892 | @ Values below 1 million are not recommended. 5 million is a |
| 893 | @ reasonable number.</p> |
| 894 | |
| 895 | @ <hr /> |
| 896 | onoff_attribute( |
| 897 | "Enable hyperlinks for \"nobody\" based on User-Agent and Javascript", |
| 898 | "auto-enable-hyperlinks", "autohyperlink", 1); |
| 899 | @ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users |
| 900 | @ including user "nobody", as long as (1) the User-Agent string in the |
| 901 | @ HTTP header indicates that the request is coming from an actual human |
| 902 | @ being and not a a robot or spider and (2) the user agent is able to |
| 903 | @ run Javascript in order to set the href= attribute of hyperlinks. Bots |
| 904 | @ and spiders can specify whatever User-Agent string they that want and |
| 905 | @ they can run javascript just like browsers. But most bots don't go to |
| 906 | @ that much trouble so this is normally an effective defense.</p> |
| 907 | @ |
| 908 | @ <p>You do not normally want a bot to walk your entire repository because |
| 909 | @ if it does, your server will end up computing diffs and annotations for |
| 910 | @ every historical version of every file and creating ZIPs and tarballs of |
| 911 | @ every historical check-in, which can use a lot of CPU and bandwidth |
| 912 | @ even for relatively small projects.</p> |
| 913 | |
| 914 | @ <hr /> |
| 915 | entry_attribute("Public pages", 30, "public-pages", |
| 916 | "pubpage", ""); |
| 917 | @ <p>A comma-separated list of glob patterns for pages that are accessible |
| 918 |
+87
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -45,10 +45,94 @@ | ||
| 45 | 45 | /* |
| 46 | 46 | ** remember, if a sidebox was used |
| 47 | 47 | */ |
| 48 | 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.javascriptHyperlink | |
| 66 | +** variable. The href="URL" form is used if g.javascriptHyperlink is false. | |
| 67 | +** If g.javascriptHyperlink is true then the | |
| 68 | +** id="ID" form is used and javascript is generated in the footer to cause | |
| 69 | +** href values to be inserted after the page has loaded. If | |
| 70 | +** g.perm.History is false, then the <a id="ID"> form is still | |
| 71 | +** generated but the javascript is not generated so the links never | |
| 72 | +** activate. | |
| 73 | +** | |
| 74 | +** Filling in the href="URL" using javascript is a defense against bots. | |
| 75 | +** | |
| 76 | +** The name of this routine is deliberately kept short so that can be | |
| 77 | +** easily used within @-lines. Example: | |
| 78 | +** | |
| 79 | +** @ %z(href("%R/artifact/%s",zUuid))%h(zFN)</a> | |
| 80 | +** | |
| 81 | +** Note %z format. The string returned by this function is always | |
| 82 | +** obtained from fossil_malloc() so rendering it with %z will reclaim | |
| 83 | +** that memory space. | |
| 84 | +** | |
| 85 | +** There are two versions of this routine: href() does a plain hyperlink | |
| 86 | +** and xhref() adds extra attribute text. | |
| 87 | +*/ | |
| 88 | +char *xhref(const char *zExtra, const char *zFormat, ...){ | |
| 89 | + char *zUrl; | |
| 90 | + va_list ap; | |
| 91 | + va_start(ap, zFormat); | |
| 92 | + zUrl = vmprintf(zFormat, ap); | |
| 93 | + va_end(ap); | |
| 94 | + if( g.perm.Hyperlink && !g.javascriptHyperlink ){ | |
| 95 | + return mprintf("<a %s href=\"%z\">", zExtra, zUrl); | |
| 96 | + } | |
| 97 | + if( nHref>=nHrefAlloc ){ | |
| 98 | + nHrefAlloc = nHrefAlloc*2 + 10; | |
| 99 | + aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0])); | |
| 100 | + } | |
| 101 | + aHref[nHref++] = zUrl; | |
| 102 | + return mprintf("<a %s id=%d>", zExtra, nHref); | |
| 103 | +} | |
| 104 | +char *href(const char *zFormat, ...){ | |
| 105 | + char *zUrl; | |
| 106 | + va_list ap; | |
| 107 | + va_start(ap, zFormat); | |
| 108 | + zUrl = vmprintf(zFormat, ap); | |
| 109 | + va_end(ap); | |
| 110 | + if( g.perm.Hyperlink && !g.javascriptHyperlink ){ | |
| 111 | + return mprintf("<a href=\"%z\">", zUrl); | |
| 112 | + } | |
| 113 | + if( nHref>=nHrefAlloc ){ | |
| 114 | + nHrefAlloc = nHrefAlloc*2 + 10; | |
| 115 | + aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0])); | |
| 116 | + } | |
| 117 | + aHref[nHref++] = zUrl; | |
| 118 | + return mprintf("<a id=%d>", nHref); | |
| 119 | +} | |
| 120 | + | |
| 121 | +/* | |
| 122 | +** Generate javascript that will set the href= attribute on all anchors. | |
| 123 | +*/ | |
| 124 | +void style_resolve_href(void){ | |
| 125 | + int i; | |
| 126 | + if( !g.perm.Hyperlink || !g.javascriptHyperlink || nHref==0 ) return; | |
| 127 | + @ <script> | |
| 128 | + for(i=0; i<nHref; i++){ | |
| 129 | + @ document.getElementById(%d(i+1)).href="%s(aHref[i])"; | |
| 130 | + } | |
| 131 | + @ </script> | |
| 132 | +} | |
| 133 | + | |
| 50 | 134 | /* |
| 51 | 135 | ** Add a new element to the submenu |
| 52 | 136 | */ |
| 53 | 137 | void style_submenu_element( |
| 54 | 138 | const char *zLabel, |
| @@ -164,10 +248,13 @@ | ||
| 164 | 248 | if( g.thTrace ){ |
| 165 | 249 | cgi_append_content("<span class=\"thTrace\"><hr />\n", -1); |
| 166 | 250 | cgi_append_content(blob_str(&g.thLog), blob_size(&g.thLog)); |
| 167 | 251 | cgi_append_content("</span>\n", -1); |
| 168 | 252 | } |
| 253 | + | |
| 254 | + /* Set the href= field on hyperlinks */ | |
| 255 | + style_resolve_href(); | |
| 169 | 256 | } |
| 170 | 257 | |
| 171 | 258 | /* |
| 172 | 259 | ** Begin a side-box on the right-hand side of a page. The title and |
| 173 | 260 | ** the width of the box are given as arguments. The width is usually |
| 174 | 261 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -45,10 +45,94 @@ | |
| 45 | /* |
| 46 | ** remember, if a sidebox was used |
| 47 | */ |
| 48 | static int sideboxUsed = 0; |
| 49 | |
| 50 | /* |
| 51 | ** Add a new element to the submenu |
| 52 | */ |
| 53 | void style_submenu_element( |
| 54 | const char *zLabel, |
| @@ -164,10 +248,13 @@ | |
| 164 | if( g.thTrace ){ |
| 165 | cgi_append_content("<span class=\"thTrace\"><hr />\n", -1); |
| 166 | cgi_append_content(blob_str(&g.thLog), blob_size(&g.thLog)); |
| 167 | cgi_append_content("</span>\n", -1); |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | /* |
| 172 | ** Begin a side-box on the right-hand side of a page. The title and |
| 173 | ** the width of the box are given as arguments. The width is usually |
| 174 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -45,10 +45,94 @@ | |
| 45 | /* |
| 46 | ** remember, if a sidebox was used |
| 47 | */ |
| 48 | static int sideboxUsed = 0; |
| 49 | |
| 50 | |
| 51 | /* |
| 52 | ** List of hyperlinks that need to be resolved by javascript in |
| 53 | ** the footer. |
| 54 | */ |
| 55 | char **aHref = 0; |
| 56 | int nHref = 0; |
| 57 | int nHrefAlloc = 0; |
| 58 | |
| 59 | /* |
| 60 | ** Generate and return a anchor tag like this: |
| 61 | ** |
| 62 | ** <a href="URL"> |
| 63 | ** or <a id="ID"> |
| 64 | ** |
| 65 | ** The form of the anchor tag is determined by the g.javascriptHyperlink |
| 66 | ** variable. The href="URL" form is used if g.javascriptHyperlink is false. |
| 67 | ** If g.javascriptHyperlink is true then the |
| 68 | ** id="ID" form is used and javascript is generated in the footer to cause |
| 69 | ** href values to be inserted after the page has loaded. If |
| 70 | ** g.perm.History is false, then the <a id="ID"> form is still |
| 71 | ** generated but the javascript is not generated so the links never |
| 72 | ** activate. |
| 73 | ** |
| 74 | ** Filling in the href="URL" using javascript is a defense against bots. |
| 75 | ** |
| 76 | ** The name of this routine is deliberately kept short so that can be |
| 77 | ** easily used within @-lines. Example: |
| 78 | ** |
| 79 | ** @ %z(href("%R/artifact/%s",zUuid))%h(zFN)</a> |
| 80 | ** |
| 81 | ** Note %z format. The string returned by this function is always |
| 82 | ** obtained from fossil_malloc() so rendering it with %z will reclaim |
| 83 | ** that memory space. |
| 84 | ** |
| 85 | ** There are two versions of this routine: href() does a plain hyperlink |
| 86 | ** and xhref() adds extra attribute text. |
| 87 | */ |
| 88 | char *xhref(const char *zExtra, const char *zFormat, ...){ |
| 89 | char *zUrl; |
| 90 | va_list ap; |
| 91 | va_start(ap, zFormat); |
| 92 | zUrl = vmprintf(zFormat, ap); |
| 93 | va_end(ap); |
| 94 | if( g.perm.Hyperlink && !g.javascriptHyperlink ){ |
| 95 | return mprintf("<a %s href=\"%z\">", zExtra, zUrl); |
| 96 | } |
| 97 | if( nHref>=nHrefAlloc ){ |
| 98 | nHrefAlloc = nHrefAlloc*2 + 10; |
| 99 | aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0])); |
| 100 | } |
| 101 | aHref[nHref++] = zUrl; |
| 102 | return mprintf("<a %s id=%d>", zExtra, nHref); |
| 103 | } |
| 104 | char *href(const char *zFormat, ...){ |
| 105 | char *zUrl; |
| 106 | va_list ap; |
| 107 | va_start(ap, zFormat); |
| 108 | zUrl = vmprintf(zFormat, ap); |
| 109 | va_end(ap); |
| 110 | if( g.perm.Hyperlink && !g.javascriptHyperlink ){ |
| 111 | return mprintf("<a href=\"%z\">", zUrl); |
| 112 | } |
| 113 | if( nHref>=nHrefAlloc ){ |
| 114 | nHrefAlloc = nHrefAlloc*2 + 10; |
| 115 | aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0])); |
| 116 | } |
| 117 | aHref[nHref++] = zUrl; |
| 118 | return mprintf("<a id=%d>", nHref); |
| 119 | } |
| 120 | |
| 121 | /* |
| 122 | ** Generate javascript that will set the href= attribute on all anchors. |
| 123 | */ |
| 124 | void style_resolve_href(void){ |
| 125 | int i; |
| 126 | if( !g.perm.Hyperlink || !g.javascriptHyperlink || nHref==0 ) return; |
| 127 | @ <script> |
| 128 | for(i=0; i<nHref; i++){ |
| 129 | @ document.getElementById(%d(i+1)).href="%s(aHref[i])"; |
| 130 | } |
| 131 | @ </script> |
| 132 | } |
| 133 | |
| 134 | /* |
| 135 | ** Add a new element to the submenu |
| 136 | */ |
| 137 | void style_submenu_element( |
| 138 | const char *zLabel, |
| @@ -164,10 +248,13 @@ | |
| 248 | if( g.thTrace ){ |
| 249 | cgi_append_content("<span class=\"thTrace\"><hr />\n", -1); |
| 250 | cgi_append_content(blob_str(&g.thLog), blob_size(&g.thLog)); |
| 251 | cgi_append_content("</span>\n", -1); |
| 252 | } |
| 253 | |
| 254 | /* Set the href= field on hyperlinks */ |
| 255 | style_resolve_href(); |
| 256 | } |
| 257 | |
| 258 | /* |
| 259 | ** Begin a side-box on the right-hand side of a page. The title and |
| 260 | ** the width of the box are given as arguments. The width is usually |
| 261 |
+2
-2
| --- src/tag.c | ||
| +++ src/tag.c | ||
| @@ -548,12 +548,12 @@ | ||
| 548 | 548 | " ORDER BY tagname" |
| 549 | 549 | ); |
| 550 | 550 | @ <ul> |
| 551 | 551 | while( db_step(&q)==SQLITE_ROW ){ |
| 552 | 552 | const char *zName = db_column_text(&q, 0); |
| 553 | - if( g.perm.History ){ | |
| 554 | - @ <li><a class="tagLink" href="%s(g.zTop)/timeline?t=%T(zName)"> | |
| 553 | + if( g.perm.Hyperlink ){ | |
| 554 | + @ <li>%z(xhref("class='taglink'","%R/timeline?t=%T",zName)) | |
| 555 | 555 | @ %h(zName)</a></li> |
| 556 | 556 | }else{ |
| 557 | 557 | @ <li><span class="tagDsp">%h(zName)</span></li> |
| 558 | 558 | } |
| 559 | 559 | } |
| 560 | 560 |
| --- src/tag.c | |
| +++ src/tag.c | |
| @@ -548,12 +548,12 @@ | |
| 548 | " ORDER BY tagname" |
| 549 | ); |
| 550 | @ <ul> |
| 551 | while( db_step(&q)==SQLITE_ROW ){ |
| 552 | const char *zName = db_column_text(&q, 0); |
| 553 | if( g.perm.History ){ |
| 554 | @ <li><a class="tagLink" href="%s(g.zTop)/timeline?t=%T(zName)"> |
| 555 | @ %h(zName)</a></li> |
| 556 | }else{ |
| 557 | @ <li><span class="tagDsp">%h(zName)</span></li> |
| 558 | } |
| 559 | } |
| 560 |
| --- src/tag.c | |
| +++ src/tag.c | |
| @@ -548,12 +548,12 @@ | |
| 548 | " ORDER BY tagname" |
| 549 | ); |
| 550 | @ <ul> |
| 551 | while( db_step(&q)==SQLITE_ROW ){ |
| 552 | const char *zName = db_column_text(&q, 0); |
| 553 | if( g.perm.Hyperlink ){ |
| 554 | @ <li>%z(xhref("class='taglink'","%R/timeline?t=%T",zName)) |
| 555 | @ %h(zName)</a></li> |
| 556 | }else{ |
| 557 | @ <li><span class="tagDsp">%h(zName)</span></li> |
| 558 | } |
| 559 | } |
| 560 |
+33
-52
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -47,37 +47,37 @@ | ||
| 47 | 47 | ** Generate a hyperlink to a version. |
| 48 | 48 | */ |
| 49 | 49 | void hyperlink_to_uuid(const char *zUuid){ |
| 50 | 50 | char z[UUID_SIZE+1]; |
| 51 | 51 | shorten_uuid(z, zUuid); |
| 52 | - if( g.perm.History ){ | |
| 53 | - @ <a class="timelineHistLink" href="%s(g.zTop)/info/%s(z)">[%s(z)]</a> | |
| 52 | + if( g.perm.Hyperlink ){ | |
| 53 | + @ %z(xhref("class='timelineHistLink'","%R/info/%s",z))[%s(z)]</a> | |
| 54 | 54 | }else{ |
| 55 | 55 | @ <span class="timelineHistDsp">[%s(z)]</span> |
| 56 | 56 | } |
| 57 | 57 | } |
| 58 | 58 | |
| 59 | 59 | /* |
| 60 | 60 | ** Generate a hyperlink to a diff between two versions. |
| 61 | 61 | */ |
| 62 | 62 | void hyperlink_to_diff(const char *zV1, const char *zV2){ |
| 63 | - if( g.perm.History ){ | |
| 63 | + if( g.perm.Hyperlink ){ | |
| 64 | 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 | 66 | }else{ |
| 67 | - @ <a href="%s(g.zTop)/diff?v1=%s(zV1)&v2=%s(zV2)">[diff]</a> | |
| 67 | + @ %z(href("%R/diff?v1=%s&v2=%s",zV1,zV2))[diff]</a> | |
| 68 | 68 | } |
| 69 | 69 | } |
| 70 | 70 | } |
| 71 | 71 | |
| 72 | 72 | /* |
| 73 | 73 | ** Generate a hyperlink to a date & time. |
| 74 | 74 | */ |
| 75 | 75 | void hyperlink_to_date(const char *zDate, const char *zSuffix){ |
| 76 | 76 | if( zSuffix==0 ) zSuffix = ""; |
| 77 | - if( g.perm.History ){ | |
| 78 | - @ <a href="%s(g.zTop)/timeline?c=%T(zDate)">%s(zDate)</a>%s(zSuffix) | |
| 77 | + if( g.perm.Hyperlink ){ | |
| 78 | + @ %z(href("%R/timeline?c=%T",zDate))%s(zDate)</a>%s(zSuffix) | |
| 79 | 79 | }else{ |
| 80 | 80 | @ %s(zDate)%s(zSuffix) |
| 81 | 81 | } |
| 82 | 82 | } |
| 83 | 83 | |
| @@ -86,15 +86,15 @@ | ||
| 86 | 86 | ** events by that user. If the date+time is specified, then the timeline |
| 87 | 87 | ** is centered on that date+time. |
| 88 | 88 | */ |
| 89 | 89 | void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){ |
| 90 | 90 | if( zSuf==0 ) zSuf = ""; |
| 91 | - if( g.perm.History ){ | |
| 91 | + if( g.perm.Hyperlink ){ | |
| 92 | 92 | if( zD && zD[0] ){ |
| 93 | - @ <a href="%s(g.zTop)/timeline?c=%T(zD)&u=%T(zU)">%h(zU)</a>%s(zSuf) | |
| 93 | + @ %z(href("%R/timeline?c=%T&u=%T",zD,zU))%h(zU)</a>%s(zSuf) | |
| 94 | 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 | 97 | }else{ |
| 98 | 98 | @ %s(zU) |
| 99 | 99 | } |
| 100 | 100 | } |
| @@ -353,39 +353,37 @@ | ||
| 353 | 353 | |
| 354 | 354 | /* Generate the "user: USERNAME" at the end of the comment, together |
| 355 | 355 | ** with a hyperlink to another timeline for that user. |
| 356 | 356 | */ |
| 357 | 357 | if( zTagList && zTagList[0]==0 ) zTagList = 0; |
| 358 | - if( g.perm.History && fossil_strcmp(zUser, zThisUser)!=0 ){ | |
| 359 | - char *zLink = mprintf("%s/timeline?u=%h&c=%t&nd", | |
| 360 | - g.zTop, zUser, zDate); | |
| 361 | - @ (user: <a href="%s(zLink)">%h(zUser)</a>%s(zTagList?",":"\051") | |
| 362 | - fossil_free(zLink); | |
| 358 | + if( g.perm.Hyperlink && fossil_strcmp(zUser, zThisUser)!=0 ){ | |
| 359 | + char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd", zUser, zDate); | |
| 360 | + @ (user: %z(href("%z",zLink))%h(zUser)</a>%s(zTagList?",":"\051") | |
| 363 | 361 | }else{ |
| 364 | 362 | @ (user: %h(zUser)%s(zTagList?",":"\051") |
| 365 | 363 | } |
| 366 | 364 | |
| 367 | 365 | /* Generate a "detail" link for tags. */ |
| 368 | - if( zType[0]=='g' && g.perm.History ){ | |
| 369 | - @ [<a href="%s(g.zTop)/info/%S(zUuid)">details</a>] | |
| 366 | + if( zType[0]=='g' && g.perm.Hyperlink ){ | |
| 367 | + @ [%z(href("%R/info/%S",zUuid))details</a>] | |
| 370 | 368 | } |
| 371 | 369 | |
| 372 | 370 | /* Generate the "tags: TAGLIST" at the end of the comment, together |
| 373 | 371 | ** with hyperlinks to the tag list. |
| 374 | 372 | */ |
| 375 | 373 | if( zTagList ){ |
| 376 | - if( g.perm.History ){ | |
| 374 | + if( g.perm.Hyperlink ){ | |
| 377 | 375 | int i; |
| 378 | 376 | const char *z = zTagList; |
| 379 | 377 | Blob links; |
| 380 | 378 | blob_zero(&links); |
| 381 | 379 | while( z && z[0] ){ |
| 382 | 380 | for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){} |
| 383 | 381 | if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){ |
| 384 | 382 | blob_appendf(&links, |
| 385 | - "<a href=\"%s/timeline?r=%#t&nd&c=%s\">%#h</a>%.2s", | |
| 386 | - g.zTop, i, z, zDate, i, z, &z[i] | |
| 383 | + "%z%#h</a>%.2s", | |
| 384 | + href("%R/timeline?r=%#t&nd&c=%s",i,z,zDate), i,z, &z[i] | |
| 387 | 385 | ); |
| 388 | 386 | }else{ |
| 389 | 387 | blob_appendf(&links, "%#h", i+2, z); |
| 390 | 388 | } |
| 391 | 389 | if( z[i]==0 ) break; |
| @@ -403,11 +401,11 @@ | ||
| 403 | 401 | if( xExtra ){ |
| 404 | 402 | xExtra(rid); |
| 405 | 403 | } |
| 406 | 404 | |
| 407 | 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 | 407 | int inUl = 0; |
| 410 | 408 | if( !fchngQueryInit ){ |
| 411 | 409 | db_prepare(&fchngQuery, |
| 412 | 410 | "SELECT (pid==0) AS isnew," |
| 413 | 411 | " (fid==0) AS isdel," |
| @@ -433,26 +431,26 @@ | ||
| 433 | 431 | @ <ul class="filelist"> |
| 434 | 432 | inUl = 1; |
| 435 | 433 | } |
| 436 | 434 | if( isNew ){ |
| 437 | 435 | @ <li> %h(zFilename) (new file) |
| 438 | - @ <a href="%s(g.zTop)/artifact/%S(zNew)" | |
| 439 | - @ target="diffwindow">[view]</a></li> | |
| 436 | + @ %z(xhref("target='diffwindow'","%R/artifact/%S",zNew)) | |
| 437 | + @ [view]</a></li> | |
| 440 | 438 | }else if( isDel ){ |
| 441 | 439 | @ <li> %h(zFilename) (deleted)</li> |
| 442 | 440 | }else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){ |
| 443 | 441 | @ <li> %h(zOldName) → %h(zFilename) |
| 444 | - @ <a href="%s(g.zTop)/artifact/%S(zNew)" | |
| 445 | - @ target="diffwindow">[view]</a></li> | |
| 442 | + @ %z(xhref("target='diffwindow'","%R/artifact/%S",zNew)) | |
| 443 | + @ [view]</a></li> | |
| 446 | 444 | }else{ |
| 447 | 445 | if( zOldName!=0 ){ |
| 448 | 446 | @ <li> %h(zOldName) → %h(zFilename) |
| 449 | 447 | }else{ |
| 450 | 448 | @ <li> %h(zFilename) |
| 451 | 449 | } |
| 452 | - @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)" | |
| 453 | - @ target="diffwindow">[diff]</a></li> | |
| 450 | + @ %z(xhref("target='diffwindow'","%R/fdiff?v1=%S&v2=%S",zOld,zNew)) | |
| 451 | + @ [diff]</a></li> | |
| 454 | 452 | } |
| 455 | 453 | } |
| 456 | 454 | db_reset(&fchngQuery); |
| 457 | 455 | if( inUl ){ |
| 458 | 456 | @ </ul> |
| @@ -974,21 +972,13 @@ | ||
| 974 | 972 | p = p->u.pTo; |
| 975 | 973 | } |
| 976 | 974 | blob_append(&sql, ")", -1); |
| 977 | 975 | path_reset(); |
| 978 | 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); | |
| 983 | - } | |
| 977 | + blob_appendf(&desc, "%z%h</a>", href("%R/info/%h", zFrom), zFrom); | |
| 984 | 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); | |
| 989 | - } | |
| 979 | + blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h",zTo), zTo); | |
| 990 | 980 | tmFlags |= TIMELINE_DISJOINT; |
| 991 | 981 | db_multi_exec("%s", blob_str(&sql)); |
| 992 | 982 | }else if( (p_rid || d_rid) && g.perm.Read ){ |
| 993 | 983 | /* If p= or d= is present, ignore all other parameters other than n= */ |
| 994 | 984 | char *zUuid; |
| @@ -1021,16 +1011,12 @@ | ||
| 1021 | 1011 | blob_appendf(&desc, "%d ancestors", np); |
| 1022 | 1012 | db_multi_exec("%s", blob_str(&sql)); |
| 1023 | 1013 | } |
| 1024 | 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); | |
| 1031 | - } | |
| 1016 | + blob_appendf(&desc, " of %z[%.10s]</a>", | |
| 1017 | + href("%R/info/%s", zUuid), zUuid); | |
| 1032 | 1018 | }else if( f_rid && g.perm.Read ){ |
| 1033 | 1019 | /* If f= is present, ignore all other parameters other than n= */ |
| 1034 | 1020 | char *zUuid; |
| 1035 | 1021 | db_multi_exec( |
| 1036 | 1022 | "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);" |
| @@ -1042,16 +1028,11 @@ | ||
| 1042 | 1028 | blob_appendf(&sql, " AND event.objid IN ok"); |
| 1043 | 1029 | db_multi_exec("%s", blob_str(&sql)); |
| 1044 | 1030 | if( useDividers ) timeline_add_dividers(0, f_rid); |
| 1045 | 1031 | blob_appendf(&desc, "Parents and children of check-in "); |
| 1046 | 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); | |
| 1052 | - } | |
| 1033 | + blob_appendf(&desc, "%z[%.10s]</a>", href("%R/info/%s", zUuid), zUuid); | |
| 1053 | 1034 | }else{ |
| 1054 | 1035 | /* Otherwise, a timeline based on a span of time */ |
| 1055 | 1036 | int n; |
| 1056 | 1037 | const char *zEType = "timeline item"; |
| 1057 | 1038 | char *zDate; |
| @@ -1219,11 +1200,11 @@ | ||
| 1219 | 1200 | blob_appendf(&desc, " occurring around %h.<br />", zCirca); |
| 1220 | 1201 | } |
| 1221 | 1202 | if( zSearch ){ |
| 1222 | 1203 | blob_appendf(&desc, " matching \"%h\"", zSearch); |
| 1223 | 1204 | } |
| 1224 | - if( g.perm.History ){ | |
| 1205 | + if( g.perm.Hyperlink ){ | |
| 1225 | 1206 | if( zAfter || n==nEntry ){ |
| 1226 | 1207 | zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/"); |
| 1227 | 1208 | timeline_submenu(&url, "Older", "b", zDate, "a"); |
| 1228 | 1209 | free(zDate); |
| 1229 | 1210 | } |
| @@ -1623,11 +1604,11 @@ | ||
| 1623 | 1604 | */ |
| 1624 | 1605 | void test_timewarp_page(void){ |
| 1625 | 1606 | Stmt q; |
| 1626 | 1607 | |
| 1627 | 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 | 1610 | style_header("Instances of timewarp"); |
| 1630 | 1611 | @ <ul> |
| 1631 | 1612 | db_prepare(&q, |
| 1632 | 1613 | "SELECT blob.uuid " |
| 1633 | 1614 | " FROM plink p, plink c, blob" |
| @@ -1635,10 +1616,10 @@ | ||
| 1635 | 1616 | " AND blob.rid=c.cid" |
| 1636 | 1617 | ); |
| 1637 | 1618 | while( db_step(&q)==SQLITE_ROW ){ |
| 1638 | 1619 | const char *zUuid = db_column_text(&q, 0); |
| 1639 | 1620 | @ <li> |
| 1640 | - @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&d=%S(zUuid)">%S(zUuid)</a> | |
| 1621 | + @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&d=%S(zUuid)">%S(zUuid)</a> | |
| 1641 | 1622 | } |
| 1642 | 1623 | db_finalize(&q); |
| 1643 | 1624 | style_footer(); |
| 1644 | 1625 | } |
| 1645 | 1626 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -47,37 +47,37 @@ | |
| 47 | ** Generate a hyperlink to a version. |
| 48 | */ |
| 49 | void hyperlink_to_uuid(const char *zUuid){ |
| 50 | char z[UUID_SIZE+1]; |
| 51 | shorten_uuid(z, zUuid); |
| 52 | if( g.perm.History ){ |
| 53 | @ <a class="timelineHistLink" href="%s(g.zTop)/info/%s(z)">[%s(z)]</a> |
| 54 | }else{ |
| 55 | @ <span class="timelineHistDsp">[%s(z)]</span> |
| 56 | } |
| 57 | } |
| 58 | |
| 59 | /* |
| 60 | ** Generate a hyperlink to a diff between two versions. |
| 61 | */ |
| 62 | void hyperlink_to_diff(const char *zV1, const char *zV2){ |
| 63 | if( g.perm.History ){ |
| 64 | if( zV2==0 ){ |
| 65 | @ <a href="%s(g.zTop)/diff?v2=%s(zV1)">[diff]</a> |
| 66 | }else{ |
| 67 | @ <a href="%s(g.zTop)/diff?v1=%s(zV1)&v2=%s(zV2)">[diff]</a> |
| 68 | } |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | /* |
| 73 | ** Generate a hyperlink to a date & time. |
| 74 | */ |
| 75 | void hyperlink_to_date(const char *zDate, const char *zSuffix){ |
| 76 | if( zSuffix==0 ) zSuffix = ""; |
| 77 | if( g.perm.History ){ |
| 78 | @ <a href="%s(g.zTop)/timeline?c=%T(zDate)">%s(zDate)</a>%s(zSuffix) |
| 79 | }else{ |
| 80 | @ %s(zDate)%s(zSuffix) |
| 81 | } |
| 82 | } |
| 83 | |
| @@ -86,15 +86,15 @@ | |
| 86 | ** events by that user. If the date+time is specified, then the timeline |
| 87 | ** is centered on that date+time. |
| 88 | */ |
| 89 | void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){ |
| 90 | if( zSuf==0 ) zSuf = ""; |
| 91 | if( g.perm.History ){ |
| 92 | if( zD && zD[0] ){ |
| 93 | @ <a href="%s(g.zTop)/timeline?c=%T(zD)&u=%T(zU)">%h(zU)</a>%s(zSuf) |
| 94 | }else{ |
| 95 | @ <a href="%s(g.zTop)/timeline?u=%T(zU)">%h(zU)</a>%s(zSuf) |
| 96 | } |
| 97 | }else{ |
| 98 | @ %s(zU) |
| 99 | } |
| 100 | } |
| @@ -353,39 +353,37 @@ | |
| 353 | |
| 354 | /* Generate the "user: USERNAME" at the end of the comment, together |
| 355 | ** with a hyperlink to another timeline for that user. |
| 356 | */ |
| 357 | if( zTagList && zTagList[0]==0 ) zTagList = 0; |
| 358 | if( g.perm.History && fossil_strcmp(zUser, zThisUser)!=0 ){ |
| 359 | char *zLink = mprintf("%s/timeline?u=%h&c=%t&nd", |
| 360 | g.zTop, zUser, zDate); |
| 361 | @ (user: <a href="%s(zLink)">%h(zUser)</a>%s(zTagList?",":"\051") |
| 362 | fossil_free(zLink); |
| 363 | }else{ |
| 364 | @ (user: %h(zUser)%s(zTagList?",":"\051") |
| 365 | } |
| 366 | |
| 367 | /* Generate a "detail" link for tags. */ |
| 368 | if( zType[0]=='g' && g.perm.History ){ |
| 369 | @ [<a href="%s(g.zTop)/info/%S(zUuid)">details</a>] |
| 370 | } |
| 371 | |
| 372 | /* Generate the "tags: TAGLIST" at the end of the comment, together |
| 373 | ** with hyperlinks to the tag list. |
| 374 | */ |
| 375 | if( zTagList ){ |
| 376 | if( g.perm.History ){ |
| 377 | int i; |
| 378 | const char *z = zTagList; |
| 379 | Blob links; |
| 380 | blob_zero(&links); |
| 381 | while( z && z[0] ){ |
| 382 | for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){} |
| 383 | if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){ |
| 384 | blob_appendf(&links, |
| 385 | "<a href=\"%s/timeline?r=%#t&nd&c=%s\">%#h</a>%.2s", |
| 386 | g.zTop, i, z, zDate, i, z, &z[i] |
| 387 | ); |
| 388 | }else{ |
| 389 | blob_appendf(&links, "%#h", i+2, z); |
| 390 | } |
| 391 | if( z[i]==0 ) break; |
| @@ -403,11 +401,11 @@ | |
| 403 | if( xExtra ){ |
| 404 | xExtra(rid); |
| 405 | } |
| 406 | |
| 407 | /* Generate the file-change list if requested */ |
| 408 | if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' && g.perm.History ){ |
| 409 | int inUl = 0; |
| 410 | if( !fchngQueryInit ){ |
| 411 | db_prepare(&fchngQuery, |
| 412 | "SELECT (pid==0) AS isnew," |
| 413 | " (fid==0) AS isdel," |
| @@ -433,26 +431,26 @@ | |
| 433 | @ <ul class="filelist"> |
| 434 | inUl = 1; |
| 435 | } |
| 436 | if( isNew ){ |
| 437 | @ <li> %h(zFilename) (new file) |
| 438 | @ <a href="%s(g.zTop)/artifact/%S(zNew)" |
| 439 | @ target="diffwindow">[view]</a></li> |
| 440 | }else if( isDel ){ |
| 441 | @ <li> %h(zFilename) (deleted)</li> |
| 442 | }else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){ |
| 443 | @ <li> %h(zOldName) → %h(zFilename) |
| 444 | @ <a href="%s(g.zTop)/artifact/%S(zNew)" |
| 445 | @ target="diffwindow">[view]</a></li> |
| 446 | }else{ |
| 447 | if( zOldName!=0 ){ |
| 448 | @ <li> %h(zOldName) → %h(zFilename) |
| 449 | }else{ |
| 450 | @ <li> %h(zFilename) |
| 451 | } |
| 452 | @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)" |
| 453 | @ target="diffwindow">[diff]</a></li> |
| 454 | } |
| 455 | } |
| 456 | db_reset(&fchngQuery); |
| 457 | if( inUl ){ |
| 458 | @ </ul> |
| @@ -974,21 +972,13 @@ | |
| 974 | p = p->u.pTo; |
| 975 | } |
| 976 | blob_append(&sql, ")", -1); |
| 977 | path_reset(); |
| 978 | blob_append(&desc, "All nodes on the path from ", -1); |
| 979 | if( g.perm.History ){ |
| 980 | blob_appendf(&desc, "<a href='%s/info/%h'>[%h]</a>", g.zTop,zFrom,zFrom); |
| 981 | }else{ |
| 982 | blob_appendf(&desc, "[%h]", zFrom); |
| 983 | } |
| 984 | blob_append(&desc, " and ", -1); |
| 985 | if( g.perm.History ){ |
| 986 | blob_appendf(&desc, "<a href='%s/info/%h'>[%h]</a>.", g.zTop, zTo, zTo); |
| 987 | }else{ |
| 988 | blob_appendf(&desc, "[%h].", zTo); |
| 989 | } |
| 990 | tmFlags |= TIMELINE_DISJOINT; |
| 991 | db_multi_exec("%s", blob_str(&sql)); |
| 992 | }else if( (p_rid || d_rid) && g.perm.Read ){ |
| 993 | /* If p= or d= is present, ignore all other parameters other than n= */ |
| 994 | char *zUuid; |
| @@ -1021,16 +1011,12 @@ | |
| 1021 | blob_appendf(&desc, "%d ancestors", np); |
| 1022 | db_multi_exec("%s", blob_str(&sql)); |
| 1023 | } |
| 1024 | if( d_rid==0 && useDividers ) timeline_add_dividers(0, p_rid); |
| 1025 | } |
| 1026 | if( g.perm.History ){ |
| 1027 | blob_appendf(&desc, " of <a href='%s/info/%s'>[%.10s]</a>", |
| 1028 | g.zTop, zUuid, zUuid); |
| 1029 | }else{ |
| 1030 | blob_appendf(&desc, " of check-in [%.10s]", zUuid); |
| 1031 | } |
| 1032 | }else if( f_rid && g.perm.Read ){ |
| 1033 | /* If f= is present, ignore all other parameters other than n= */ |
| 1034 | char *zUuid; |
| 1035 | db_multi_exec( |
| 1036 | "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);" |
| @@ -1042,16 +1028,11 @@ | |
| 1042 | blob_appendf(&sql, " AND event.objid IN ok"); |
| 1043 | db_multi_exec("%s", blob_str(&sql)); |
| 1044 | if( useDividers ) timeline_add_dividers(0, f_rid); |
| 1045 | blob_appendf(&desc, "Parents and children of check-in "); |
| 1046 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid); |
| 1047 | if( g.perm.History ){ |
| 1048 | blob_appendf(&desc, "<a href='%s/info/%s'>[%.10s]</a>", |
| 1049 | g.zTop, zUuid, zUuid); |
| 1050 | }else{ |
| 1051 | blob_appendf(&desc, "[%.10s]", zUuid); |
| 1052 | } |
| 1053 | }else{ |
| 1054 | /* Otherwise, a timeline based on a span of time */ |
| 1055 | int n; |
| 1056 | const char *zEType = "timeline item"; |
| 1057 | char *zDate; |
| @@ -1219,11 +1200,11 @@ | |
| 1219 | blob_appendf(&desc, " occurring around %h.<br />", zCirca); |
| 1220 | } |
| 1221 | if( zSearch ){ |
| 1222 | blob_appendf(&desc, " matching \"%h\"", zSearch); |
| 1223 | } |
| 1224 | if( g.perm.History ){ |
| 1225 | if( zAfter || n==nEntry ){ |
| 1226 | zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/"); |
| 1227 | timeline_submenu(&url, "Older", "b", zDate, "a"); |
| 1228 | free(zDate); |
| 1229 | } |
| @@ -1623,11 +1604,11 @@ | |
| 1623 | */ |
| 1624 | void test_timewarp_page(void){ |
| 1625 | Stmt q; |
| 1626 | |
| 1627 | login_check_credentials(); |
| 1628 | if( !g.perm.Read || !g.perm.History ){ login_needed(); return; } |
| 1629 | style_header("Instances of timewarp"); |
| 1630 | @ <ul> |
| 1631 | db_prepare(&q, |
| 1632 | "SELECT blob.uuid " |
| 1633 | " FROM plink p, plink c, blob" |
| @@ -1635,10 +1616,10 @@ | |
| 1635 | " AND blob.rid=c.cid" |
| 1636 | ); |
| 1637 | while( db_step(&q)==SQLITE_ROW ){ |
| 1638 | const char *zUuid = db_column_text(&q, 0); |
| 1639 | @ <li> |
| 1640 | @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&d=%S(zUuid)">%S(zUuid)</a> |
| 1641 | } |
| 1642 | db_finalize(&q); |
| 1643 | style_footer(); |
| 1644 | } |
| 1645 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -47,37 +47,37 @@ | |
| 47 | ** Generate a hyperlink to a version. |
| 48 | */ |
| 49 | void hyperlink_to_uuid(const char *zUuid){ |
| 50 | char z[UUID_SIZE+1]; |
| 51 | shorten_uuid(z, zUuid); |
| 52 | if( g.perm.Hyperlink ){ |
| 53 | @ %z(xhref("class='timelineHistLink'","%R/info/%s",z))[%s(z)]</a> |
| 54 | }else{ |
| 55 | @ <span class="timelineHistDsp">[%s(z)]</span> |
| 56 | } |
| 57 | } |
| 58 | |
| 59 | /* |
| 60 | ** Generate a hyperlink to a diff between two versions. |
| 61 | */ |
| 62 | void hyperlink_to_diff(const char *zV1, const char *zV2){ |
| 63 | if( g.perm.Hyperlink ){ |
| 64 | if( zV2==0 ){ |
| 65 | @ %z(href("%R/diff?v2=%s",zV1))[diff]</a> |
| 66 | }else{ |
| 67 | @ %z(href("%R/diff?v1=%s&v2=%s",zV1,zV2))[diff]</a> |
| 68 | } |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | /* |
| 73 | ** Generate a hyperlink to a date & time. |
| 74 | */ |
| 75 | void hyperlink_to_date(const char *zDate, const char *zSuffix){ |
| 76 | if( zSuffix==0 ) zSuffix = ""; |
| 77 | if( g.perm.Hyperlink ){ |
| 78 | @ %z(href("%R/timeline?c=%T",zDate))%s(zDate)</a>%s(zSuffix) |
| 79 | }else{ |
| 80 | @ %s(zDate)%s(zSuffix) |
| 81 | } |
| 82 | } |
| 83 | |
| @@ -86,15 +86,15 @@ | |
| 86 | ** events by that user. If the date+time is specified, then the timeline |
| 87 | ** is centered on that date+time. |
| 88 | */ |
| 89 | void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){ |
| 90 | if( zSuf==0 ) zSuf = ""; |
| 91 | if( g.perm.Hyperlink ){ |
| 92 | if( zD && zD[0] ){ |
| 93 | @ %z(href("%R/timeline?c=%T&u=%T",zD,zU))%h(zU)</a>%s(zSuf) |
| 94 | }else{ |
| 95 | @ %z(href("%R/timeline?u=%T",zU))%h(zU)</a>%s(zSuf) |
| 96 | } |
| 97 | }else{ |
| 98 | @ %s(zU) |
| 99 | } |
| 100 | } |
| @@ -353,39 +353,37 @@ | |
| 353 | |
| 354 | /* Generate the "user: USERNAME" at the end of the comment, together |
| 355 | ** with a hyperlink to another timeline for that user. |
| 356 | */ |
| 357 | if( zTagList && zTagList[0]==0 ) zTagList = 0; |
| 358 | if( g.perm.Hyperlink && fossil_strcmp(zUser, zThisUser)!=0 ){ |
| 359 | char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd", zUser, zDate); |
| 360 | @ (user: %z(href("%z",zLink))%h(zUser)</a>%s(zTagList?",":"\051") |
| 361 | }else{ |
| 362 | @ (user: %h(zUser)%s(zTagList?",":"\051") |
| 363 | } |
| 364 | |
| 365 | /* Generate a "detail" link for tags. */ |
| 366 | if( zType[0]=='g' && g.perm.Hyperlink ){ |
| 367 | @ [%z(href("%R/info/%S",zUuid))details</a>] |
| 368 | } |
| 369 | |
| 370 | /* Generate the "tags: TAGLIST" at the end of the comment, together |
| 371 | ** with hyperlinks to the tag list. |
| 372 | */ |
| 373 | if( zTagList ){ |
| 374 | if( g.perm.Hyperlink ){ |
| 375 | int i; |
| 376 | const char *z = zTagList; |
| 377 | Blob links; |
| 378 | blob_zero(&links); |
| 379 | while( z && z[0] ){ |
| 380 | for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){} |
| 381 | if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){ |
| 382 | blob_appendf(&links, |
| 383 | "%z%#h</a>%.2s", |
| 384 | href("%R/timeline?r=%#t&nd&c=%s",i,z,zDate), i,z, &z[i] |
| 385 | ); |
| 386 | }else{ |
| 387 | blob_appendf(&links, "%#h", i+2, z); |
| 388 | } |
| 389 | if( z[i]==0 ) break; |
| @@ -403,11 +401,11 @@ | |
| 401 | if( xExtra ){ |
| 402 | xExtra(rid); |
| 403 | } |
| 404 | |
| 405 | /* Generate the file-change list if requested */ |
| 406 | if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' && g.perm.Hyperlink ){ |
| 407 | int inUl = 0; |
| 408 | if( !fchngQueryInit ){ |
| 409 | db_prepare(&fchngQuery, |
| 410 | "SELECT (pid==0) AS isnew," |
| 411 | " (fid==0) AS isdel," |
| @@ -433,26 +431,26 @@ | |
| 431 | @ <ul class="filelist"> |
| 432 | inUl = 1; |
| 433 | } |
| 434 | if( isNew ){ |
| 435 | @ <li> %h(zFilename) (new file) |
| 436 | @ %z(xhref("target='diffwindow'","%R/artifact/%S",zNew)) |
| 437 | @ [view]</a></li> |
| 438 | }else if( isDel ){ |
| 439 | @ <li> %h(zFilename) (deleted)</li> |
| 440 | }else if( fossil_strcmp(zOld,zNew)==0 && zOldName!=0 ){ |
| 441 | @ <li> %h(zOldName) → %h(zFilename) |
| 442 | @ %z(xhref("target='diffwindow'","%R/artifact/%S",zNew)) |
| 443 | @ [view]</a></li> |
| 444 | }else{ |
| 445 | if( zOldName!=0 ){ |
| 446 | @ <li> %h(zOldName) → %h(zFilename) |
| 447 | }else{ |
| 448 | @ <li> %h(zFilename) |
| 449 | } |
| 450 | @ %z(xhref("target='diffwindow'","%R/fdiff?v1=%S&v2=%S",zOld,zNew)) |
| 451 | @ [diff]</a></li> |
| 452 | } |
| 453 | } |
| 454 | db_reset(&fchngQuery); |
| 455 | if( inUl ){ |
| 456 | @ </ul> |
| @@ -974,21 +972,13 @@ | |
| 972 | p = p->u.pTo; |
| 973 | } |
| 974 | blob_append(&sql, ")", -1); |
| 975 | path_reset(); |
| 976 | blob_append(&desc, "All nodes on the path from ", -1); |
| 977 | blob_appendf(&desc, "%z%h</a>", href("%R/info/%h", zFrom), zFrom); |
| 978 | blob_append(&desc, " and ", -1); |
| 979 | blob_appendf(&desc, "%z[%h]</a>", href("%R/info/%h",zTo), zTo); |
| 980 | tmFlags |= TIMELINE_DISJOINT; |
| 981 | db_multi_exec("%s", blob_str(&sql)); |
| 982 | }else if( (p_rid || d_rid) && g.perm.Read ){ |
| 983 | /* If p= or d= is present, ignore all other parameters other than n= */ |
| 984 | char *zUuid; |
| @@ -1021,16 +1011,12 @@ | |
| 1011 | blob_appendf(&desc, "%d ancestors", np); |
| 1012 | db_multi_exec("%s", blob_str(&sql)); |
| 1013 | } |
| 1014 | if( d_rid==0 && useDividers ) timeline_add_dividers(0, p_rid); |
| 1015 | } |
| 1016 | blob_appendf(&desc, " of %z[%.10s]</a>", |
| 1017 | href("%R/info/%s", zUuid), zUuid); |
| 1018 | }else if( f_rid && g.perm.Read ){ |
| 1019 | /* If f= is present, ignore all other parameters other than n= */ |
| 1020 | char *zUuid; |
| 1021 | db_multi_exec( |
| 1022 | "CREATE TEMP TABLE IF NOT EXISTS ok(rid INTEGER PRIMARY KEY);" |
| @@ -1042,16 +1028,11 @@ | |
| 1028 | blob_appendf(&sql, " AND event.objid IN ok"); |
| 1029 | db_multi_exec("%s", blob_str(&sql)); |
| 1030 | if( useDividers ) timeline_add_dividers(0, f_rid); |
| 1031 | blob_appendf(&desc, "Parents and children of check-in "); |
| 1032 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", f_rid); |
| 1033 | blob_appendf(&desc, "%z[%.10s]</a>", href("%R/info/%s", zUuid), zUuid); |
| 1034 | }else{ |
| 1035 | /* Otherwise, a timeline based on a span of time */ |
| 1036 | int n; |
| 1037 | const char *zEType = "timeline item"; |
| 1038 | char *zDate; |
| @@ -1219,11 +1200,11 @@ | |
| 1200 | blob_appendf(&desc, " occurring around %h.<br />", zCirca); |
| 1201 | } |
| 1202 | if( zSearch ){ |
| 1203 | blob_appendf(&desc, " matching \"%h\"", zSearch); |
| 1204 | } |
| 1205 | if( g.perm.Hyperlink ){ |
| 1206 | if( zAfter || n==nEntry ){ |
| 1207 | zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/"); |
| 1208 | timeline_submenu(&url, "Older", "b", zDate, "a"); |
| 1209 | free(zDate); |
| 1210 | } |
| @@ -1623,11 +1604,11 @@ | |
| 1604 | */ |
| 1605 | void test_timewarp_page(void){ |
| 1606 | Stmt q; |
| 1607 | |
| 1608 | login_check_credentials(); |
| 1609 | if( !g.perm.Read || !g.perm.Hyperlink ){ login_needed(); return; } |
| 1610 | style_header("Instances of timewarp"); |
| 1611 | @ <ul> |
| 1612 | db_prepare(&q, |
| 1613 | "SELECT blob.uuid " |
| 1614 | " FROM plink p, plink c, blob" |
| @@ -1635,10 +1616,10 @@ | |
| 1616 | " AND blob.rid=c.cid" |
| 1617 | ); |
| 1618 | while( db_step(&q)==SQLITE_ROW ){ |
| 1619 | const char *zUuid = db_column_text(&q, 0); |
| 1620 | @ <li> |
| 1621 | @ <a href="%s(g.zTop)/timeline?p=%S(zUuid)&d=%S(zUuid)">%S(zUuid)</a> |
| 1622 | } |
| 1623 | db_finalize(&q); |
| 1624 | style_footer(); |
| 1625 | } |
| 1626 |
+12
-12
| --- src/tkt.c | ||
| +++ src/tkt.c | ||
| @@ -305,11 +305,11 @@ | ||
| 305 | 305 | if( !g.perm.RdTkt ){ login_needed(); return; } |
| 306 | 306 | if( g.perm.WrTkt || g.perm.ApndTkt ){ |
| 307 | 307 | style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T", |
| 308 | 308 | g.zTop, PD("name","")); |
| 309 | 309 | } |
| 310 | - if( g.perm.History ){ | |
| 310 | + if( g.perm.Hyperlink ){ | |
| 311 | 311 | style_submenu_element("History", "History Of This Ticket", |
| 312 | 312 | "%s/tkthistory/%T", g.zTop, zUuid); |
| 313 | 313 | style_submenu_element("Timeline", "Timeline Of This Ticket", |
| 314 | 314 | "%s/tkttimeline/%T", g.zTop, zUuid); |
| 315 | 315 | style_submenu_element("Check-ins", "Check-ins Of This Ticket", |
| @@ -319,11 +319,11 @@ | ||
| 319 | 319 | style_submenu_element("New Ticket", "Create a new ticket", |
| 320 | 320 | "%s/tktnew", g.zTop); |
| 321 | 321 | } |
| 322 | 322 | if( g.perm.ApndTkt && g.perm.Attach ){ |
| 323 | 323 | style_submenu_element("Attach", "Add An Attachment", |
| 324 | - "%s/attachadd?tkt=%T&from=%s/tktview/%t", | |
| 324 | + "%s/attachadd?tkt=%T&from=%s/tktview/%t", | |
| 325 | 325 | g.zTop, zUuid, g.zTop, zUuid); |
| 326 | 326 | } |
| 327 | 327 | style_header("View Ticket"); |
| 328 | 328 | if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1); |
| 329 | 329 | ticket_init(); |
| @@ -353,20 +353,20 @@ | ||
| 353 | 353 | @ <hr /><h2>Attachments:</h2> |
| 354 | 354 | @ <ul> |
| 355 | 355 | } |
| 356 | 356 | cnt++; |
| 357 | 357 | @ <li> |
| 358 | - if( g.perm.Read && g.perm.History ){ | |
| 359 | - @ <a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&file=%t(zFile)"> | |
| 358 | + if( g.perm.Read && g.perm.Hyperlink ){ | |
| 359 | + @ %z(href("%R/attachview?tkt=%s&file=%t",zFullName,zFile)) | |
| 360 | 360 | @ %h(zFile)</a> |
| 361 | 361 | }else{ |
| 362 | 362 | @ %h(zFile) |
| 363 | 363 | } |
| 364 | 364 | @ added by %h(zUser) on |
| 365 | 365 | hyperlink_to_date(zDate, "."); |
| 366 | 366 | if( g.perm.WrTkt && g.perm.Attach ){ |
| 367 | - @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&file=%t(zFile)&from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>] | |
| 367 | + @ [%z(href("%R/attachdelete?tkt=%s&file=%t&from=%R/tktview%%3fname=%s",zFullName,zFile,zFullName))delete</a>] | |
| 368 | 368 | } |
| 369 | 369 | @ </li> |
| 370 | 370 | } |
| 371 | 371 | if( cnt ){ |
| 372 | 372 | @ </ul> |
| @@ -647,11 +647,11 @@ | ||
| 647 | 647 | return 0; |
| 648 | 648 | } |
| 649 | 649 | |
| 650 | 650 | /* |
| 651 | 651 | ** WEBPAGE: tkttimeline |
| 652 | -** URL: /tkttimeline?name=TICKETUUID&y=TYPE | |
| 652 | +** URL: /tkttimeline?name=TICKETUUID&y=TYPE | |
| 653 | 653 | ** |
| 654 | 654 | ** Show the change history for a single ticket in timeline format. |
| 655 | 655 | */ |
| 656 | 656 | void tkttimeline_page(void){ |
| 657 | 657 | Stmt q; |
| @@ -662,16 +662,16 @@ | ||
| 662 | 662 | int tagid; |
| 663 | 663 | char zGlobPattern[50]; |
| 664 | 664 | const char *zType; |
| 665 | 665 | |
| 666 | 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 | 668 | zUuid = PD("name",""); |
| 669 | 669 | zType = PD("y","a"); |
| 670 | 670 | if( zType[0]!='c' ){ |
| 671 | 671 | style_submenu_element("Check-ins", "Check-ins", |
| 672 | - "%s/tkttimeline?name=%T&y=ci", g.zTop, zUuid); | |
| 672 | + "%s/tkttimeline?name=%T&y=ci", g.zTop, zUuid); | |
| 673 | 673 | }else{ |
| 674 | 674 | style_submenu_element("Timeline", "Timeline", |
| 675 | 675 | "%s/tkttimeline?name=%T", g.zTop, zUuid); |
| 676 | 676 | } |
| 677 | 677 | style_submenu_element("History", "History", |
| @@ -736,17 +736,17 @@ | ||
| 736 | 736 | char *zTitle; |
| 737 | 737 | const char *zUuid; |
| 738 | 738 | int tagid; |
| 739 | 739 | |
| 740 | 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 | 742 | zUuid = PD("name",""); |
| 743 | 743 | zTitle = mprintf("History Of Ticket %h", zUuid); |
| 744 | 744 | style_submenu_element("Status", "Status", |
| 745 | 745 | "%s/info/%s", g.zTop, zUuid); |
| 746 | 746 | style_submenu_element("Check-ins", "Check-ins", |
| 747 | - "%s/tkttimeline?name=%s&y=ci", g.zTop, zUuid); | |
| 747 | + "%s/tkttimeline?name=%s&y=ci", g.zTop, zUuid); | |
| 748 | 748 | style_submenu_element("Timeline", "Timeline", |
| 749 | 749 | "%s/tkttimeline?name=%s", g.zTop, zUuid); |
| 750 | 750 | style_header(zTitle); |
| 751 | 751 | free(zTitle); |
| 752 | 752 | |
| @@ -786,20 +786,20 @@ | ||
| 786 | 786 | @ <p>Delete attachment "%h(zFile)" |
| 787 | 787 | }else{ |
| 788 | 788 | @ |
| 789 | 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 | 792 | @ (rid %d(rid)) by |
| 793 | 793 | hyperlink_to_user(zUser,zDate," on"); |
| 794 | 794 | hyperlink_to_date(zDate, ".</p>"); |
| 795 | 795 | }else{ |
| 796 | 796 | pTicket = manifest_get(rid, CFTYPE_TICKET); |
| 797 | 797 | if( pTicket ){ |
| 798 | 798 | @ |
| 799 | 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 | 801 | @ (rid %d(rid)) by |
| 802 | 802 | hyperlink_to_user(pTicket->zUser,zDate," on"); |
| 803 | 803 | hyperlink_to_date(zDate, ":"); |
| 804 | 804 | @ </p> |
| 805 | 805 | ticket_output_change_artifact(pTicket); |
| 806 | 806 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -305,11 +305,11 @@ | |
| 305 | if( !g.perm.RdTkt ){ login_needed(); return; } |
| 306 | if( g.perm.WrTkt || g.perm.ApndTkt ){ |
| 307 | style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T", |
| 308 | g.zTop, PD("name","")); |
| 309 | } |
| 310 | if( g.perm.History ){ |
| 311 | style_submenu_element("History", "History Of This Ticket", |
| 312 | "%s/tkthistory/%T", g.zTop, zUuid); |
| 313 | style_submenu_element("Timeline", "Timeline Of This Ticket", |
| 314 | "%s/tkttimeline/%T", g.zTop, zUuid); |
| 315 | style_submenu_element("Check-ins", "Check-ins Of This Ticket", |
| @@ -319,11 +319,11 @@ | |
| 319 | style_submenu_element("New Ticket", "Create a new ticket", |
| 320 | "%s/tktnew", g.zTop); |
| 321 | } |
| 322 | if( g.perm.ApndTkt && g.perm.Attach ){ |
| 323 | style_submenu_element("Attach", "Add An Attachment", |
| 324 | "%s/attachadd?tkt=%T&from=%s/tktview/%t", |
| 325 | g.zTop, zUuid, g.zTop, zUuid); |
| 326 | } |
| 327 | style_header("View Ticket"); |
| 328 | if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1); |
| 329 | ticket_init(); |
| @@ -353,20 +353,20 @@ | |
| 353 | @ <hr /><h2>Attachments:</h2> |
| 354 | @ <ul> |
| 355 | } |
| 356 | cnt++; |
| 357 | @ <li> |
| 358 | if( g.perm.Read && g.perm.History ){ |
| 359 | @ <a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&file=%t(zFile)"> |
| 360 | @ %h(zFile)</a> |
| 361 | }else{ |
| 362 | @ %h(zFile) |
| 363 | } |
| 364 | @ added by %h(zUser) on |
| 365 | hyperlink_to_date(zDate, "."); |
| 366 | if( g.perm.WrTkt && g.perm.Attach ){ |
| 367 | @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&file=%t(zFile)&from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>] |
| 368 | } |
| 369 | @ </li> |
| 370 | } |
| 371 | if( cnt ){ |
| 372 | @ </ul> |
| @@ -647,11 +647,11 @@ | |
| 647 | return 0; |
| 648 | } |
| 649 | |
| 650 | /* |
| 651 | ** WEBPAGE: tkttimeline |
| 652 | ** URL: /tkttimeline?name=TICKETUUID&y=TYPE |
| 653 | ** |
| 654 | ** Show the change history for a single ticket in timeline format. |
| 655 | */ |
| 656 | void tkttimeline_page(void){ |
| 657 | Stmt q; |
| @@ -662,16 +662,16 @@ | |
| 662 | int tagid; |
| 663 | char zGlobPattern[50]; |
| 664 | const char *zType; |
| 665 | |
| 666 | login_check_credentials(); |
| 667 | if( !g.perm.History || !g.perm.RdTkt ){ login_needed(); return; } |
| 668 | zUuid = PD("name",""); |
| 669 | zType = PD("y","a"); |
| 670 | if( zType[0]!='c' ){ |
| 671 | style_submenu_element("Check-ins", "Check-ins", |
| 672 | "%s/tkttimeline?name=%T&y=ci", g.zTop, zUuid); |
| 673 | }else{ |
| 674 | style_submenu_element("Timeline", "Timeline", |
| 675 | "%s/tkttimeline?name=%T", g.zTop, zUuid); |
| 676 | } |
| 677 | style_submenu_element("History", "History", |
| @@ -736,17 +736,17 @@ | |
| 736 | char *zTitle; |
| 737 | const char *zUuid; |
| 738 | int tagid; |
| 739 | |
| 740 | login_check_credentials(); |
| 741 | if( !g.perm.History || !g.perm.RdTkt ){ login_needed(); return; } |
| 742 | zUuid = PD("name",""); |
| 743 | zTitle = mprintf("History Of Ticket %h", zUuid); |
| 744 | style_submenu_element("Status", "Status", |
| 745 | "%s/info/%s", g.zTop, zUuid); |
| 746 | style_submenu_element("Check-ins", "Check-ins", |
| 747 | "%s/tkttimeline?name=%s&y=ci", g.zTop, zUuid); |
| 748 | style_submenu_element("Timeline", "Timeline", |
| 749 | "%s/tkttimeline?name=%s", g.zTop, zUuid); |
| 750 | style_header(zTitle); |
| 751 | free(zTitle); |
| 752 | |
| @@ -786,20 +786,20 @@ | |
| 786 | @ <p>Delete attachment "%h(zFile)" |
| 787 | }else{ |
| 788 | @ |
| 789 | @ <p>Add attachment "%h(zFile)" |
| 790 | } |
| 791 | @ [<a href="%s(g.zTop)/artifact/%T(zChngUuid)">%s(zShort)</a>] |
| 792 | @ (rid %d(rid)) by |
| 793 | hyperlink_to_user(zUser,zDate," on"); |
| 794 | hyperlink_to_date(zDate, ".</p>"); |
| 795 | }else{ |
| 796 | pTicket = manifest_get(rid, CFTYPE_TICKET); |
| 797 | if( pTicket ){ |
| 798 | @ |
| 799 | @ <p>Ticket change |
| 800 | @ [<a href="%s(g.zTop)/artifact/%T(zChngUuid)">%s(zShort)</a>] |
| 801 | @ (rid %d(rid)) by |
| 802 | hyperlink_to_user(pTicket->zUser,zDate," on"); |
| 803 | hyperlink_to_date(zDate, ":"); |
| 804 | @ </p> |
| 805 | ticket_output_change_artifact(pTicket); |
| 806 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -305,11 +305,11 @@ | |
| 305 | if( !g.perm.RdTkt ){ login_needed(); return; } |
| 306 | if( g.perm.WrTkt || g.perm.ApndTkt ){ |
| 307 | style_submenu_element("Edit", "Edit The Ticket", "%s/tktedit?name=%T", |
| 308 | g.zTop, PD("name","")); |
| 309 | } |
| 310 | if( g.perm.Hyperlink ){ |
| 311 | style_submenu_element("History", "History Of This Ticket", |
| 312 | "%s/tkthistory/%T", g.zTop, zUuid); |
| 313 | style_submenu_element("Timeline", "Timeline Of This Ticket", |
| 314 | "%s/tkttimeline/%T", g.zTop, zUuid); |
| 315 | style_submenu_element("Check-ins", "Check-ins Of This Ticket", |
| @@ -319,11 +319,11 @@ | |
| 319 | style_submenu_element("New Ticket", "Create a new ticket", |
| 320 | "%s/tktnew", g.zTop); |
| 321 | } |
| 322 | if( g.perm.ApndTkt && g.perm.Attach ){ |
| 323 | style_submenu_element("Attach", "Add An Attachment", |
| 324 | "%s/attachadd?tkt=%T&from=%s/tktview/%t", |
| 325 | g.zTop, zUuid, g.zTop, zUuid); |
| 326 | } |
| 327 | style_header("View Ticket"); |
| 328 | if( g.thTrace ) Th_Trace("BEGIN_TKTVIEW<br />\n", -1); |
| 329 | ticket_init(); |
| @@ -353,20 +353,20 @@ | |
| 353 | @ <hr /><h2>Attachments:</h2> |
| 354 | @ <ul> |
| 355 | } |
| 356 | cnt++; |
| 357 | @ <li> |
| 358 | if( g.perm.Read && g.perm.Hyperlink ){ |
| 359 | @ %z(href("%R/attachview?tkt=%s&file=%t",zFullName,zFile)) |
| 360 | @ %h(zFile)</a> |
| 361 | }else{ |
| 362 | @ %h(zFile) |
| 363 | } |
| 364 | @ added by %h(zUser) on |
| 365 | hyperlink_to_date(zDate, "."); |
| 366 | if( g.perm.WrTkt && g.perm.Attach ){ |
| 367 | @ [%z(href("%R/attachdelete?tkt=%s&file=%t&from=%R/tktview%%3fname=%s",zFullName,zFile,zFullName))delete</a>] |
| 368 | } |
| 369 | @ </li> |
| 370 | } |
| 371 | if( cnt ){ |
| 372 | @ </ul> |
| @@ -647,11 +647,11 @@ | |
| 647 | return 0; |
| 648 | } |
| 649 | |
| 650 | /* |
| 651 | ** WEBPAGE: tkttimeline |
| 652 | ** URL: /tkttimeline?name=TICKETUUID&y=TYPE |
| 653 | ** |
| 654 | ** Show the change history for a single ticket in timeline format. |
| 655 | */ |
| 656 | void tkttimeline_page(void){ |
| 657 | Stmt q; |
| @@ -662,16 +662,16 @@ | |
| 662 | int tagid; |
| 663 | char zGlobPattern[50]; |
| 664 | const char *zType; |
| 665 | |
| 666 | login_check_credentials(); |
| 667 | if( !g.perm.Hyperlink || !g.perm.RdTkt ){ login_needed(); return; } |
| 668 | zUuid = PD("name",""); |
| 669 | zType = PD("y","a"); |
| 670 | if( zType[0]!='c' ){ |
| 671 | style_submenu_element("Check-ins", "Check-ins", |
| 672 | "%s/tkttimeline?name=%T&y=ci", g.zTop, zUuid); |
| 673 | }else{ |
| 674 | style_submenu_element("Timeline", "Timeline", |
| 675 | "%s/tkttimeline?name=%T", g.zTop, zUuid); |
| 676 | } |
| 677 | style_submenu_element("History", "History", |
| @@ -736,17 +736,17 @@ | |
| 736 | char *zTitle; |
| 737 | const char *zUuid; |
| 738 | int tagid; |
| 739 | |
| 740 | login_check_credentials(); |
| 741 | if( !g.perm.Hyperlink || !g.perm.RdTkt ){ login_needed(); return; } |
| 742 | zUuid = PD("name",""); |
| 743 | zTitle = mprintf("History Of Ticket %h", zUuid); |
| 744 | style_submenu_element("Status", "Status", |
| 745 | "%s/info/%s", g.zTop, zUuid); |
| 746 | style_submenu_element("Check-ins", "Check-ins", |
| 747 | "%s/tkttimeline?name=%s&y=ci", g.zTop, zUuid); |
| 748 | style_submenu_element("Timeline", "Timeline", |
| 749 | "%s/tkttimeline?name=%s", g.zTop, zUuid); |
| 750 | style_header(zTitle); |
| 751 | free(zTitle); |
| 752 | |
| @@ -786,20 +786,20 @@ | |
| 786 | @ <p>Delete attachment "%h(zFile)" |
| 787 | }else{ |
| 788 | @ |
| 789 | @ <p>Add attachment "%h(zFile)" |
| 790 | } |
| 791 | @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>] |
| 792 | @ (rid %d(rid)) by |
| 793 | hyperlink_to_user(zUser,zDate," on"); |
| 794 | hyperlink_to_date(zDate, ".</p>"); |
| 795 | }else{ |
| 796 | pTicket = manifest_get(rid, CFTYPE_TICKET); |
| 797 | if( pTicket ){ |
| 798 | @ |
| 799 | @ <p>Ticket change |
| 800 | @ [%z(href("%R/artifact/%T",zChngUuid))%s(zShort)</a>] |
| 801 | @ (rid %d(rid)) by |
| 802 | hyperlink_to_user(pTicket->zUser,zDate," on"); |
| 803 | hyperlink_to_date(zDate, ":"); |
| 804 | @ </p> |
| 805 | ticket_output_change_artifact(pTicket); |
| 806 |
+19
-21
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -104,11 +104,11 @@ | ||
| 104 | 104 | return; |
| 105 | 105 | } |
| 106 | 106 | style_header("Home"); |
| 107 | 107 | @ <p>This is a stub home-page for the project. |
| 108 | 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 | 110 | @ and establish a "Project Name". Then create a |
| 111 | 111 | @ wiki page with that name. The content of that wiki page |
| 112 | 112 | @ will be displayed in place of this message.</p> |
| 113 | 113 | style_footer(); |
| 114 | 114 | } |
| @@ -142,27 +142,25 @@ | ||
| 142 | 142 | if( zPageName==0 ){ |
| 143 | 143 | style_header("Wiki"); |
| 144 | 144 | @ <ul> |
| 145 | 145 | { char *zHomePageName = db_get("project-name",0); |
| 146 | 146 | if( zHomePageName ){ |
| 147 | - @ <li> <a href="%s(g.zTop)/wiki?name=%t(zHomePageName)"> | |
| 147 | + @ <li> %z(href("%R/wiki?name=%t",zHomePageName)) | |
| 148 | 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 | |
| 152 | - @ pages. </li> | |
| 153 | - @ <li> <a href="%s(g.zTop)/wiki_rules">Formatting rules</a> for | |
| 154 | - @ wiki.</li> | |
| 155 | - @ <li> Use the <a href="%s(g.zTop)/wiki?name=Sandbox">Sandbox</a> | |
| 151 | + @ <li> %z(href("%R/timeline?y=w"))Recent changes</a> to wiki pages.</li> | |
| 152 | + @ <li> %z(href("%R/wiki_rules"))Formatting rules</a> for wiki.</li> | |
| 153 | + @ <li> Use the %z(href("%R/wiki?name=Sandbox"))Sandbox</a> | |
| 156 | 154 | @ to experiment.</li> |
| 157 | 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 | 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 | 162 | @ available on this server.</li> |
| 165 | 163 | @ <li> <form method="get" action="%s(g.zTop)/wfind"><div> |
| 166 | 164 | @ Search wiki titles: <input type="text" name="title"/> |
| 167 | 165 | @ <input type="submit" /></div></form> |
| 168 | 166 | @ </li> |
| @@ -192,18 +190,18 @@ | ||
| 192 | 190 | style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T", |
| 193 | 191 | g.zTop, zPageName); |
| 194 | 192 | } |
| 195 | 193 | if( rid && g.perm.ApndWiki && g.perm.Attach ){ |
| 196 | 194 | style_submenu_element("Attach", "Add An Attachment", |
| 197 | - "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T", | |
| 195 | + "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T", | |
| 198 | 196 | g.zTop, zPageName, g.zTop, zPageName); |
| 199 | 197 | } |
| 200 | 198 | if( rid && g.perm.ApndWiki ){ |
| 201 | 199 | style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T", |
| 202 | 200 | g.zTop, zPageName); |
| 203 | 201 | } |
| 204 | - if( g.perm.History ){ | |
| 202 | + if( g.perm.Hyperlink ){ | |
| 205 | 203 | style_submenu_element("History", "History", "%s/whistory?name=%T", |
| 206 | 204 | g.zTop, zPageName); |
| 207 | 205 | } |
| 208 | 206 | } |
| 209 | 207 | style_header(zPageName); |
| @@ -225,20 +223,20 @@ | ||
| 225 | 223 | @ <hr /><h2>Attachments:</h2> |
| 226 | 224 | @ <ul> |
| 227 | 225 | } |
| 228 | 226 | cnt++; |
| 229 | 227 | @ <li> |
| 230 | - if( g.perm.History && g.perm.Read ){ | |
| 231 | - @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&file=%t(zFile)"> | |
| 228 | + if( g.perm.Hyperlink && g.perm.Read ){ | |
| 229 | + @ %z(href("%R/attachview?page=%T&file=%t",zPageName,zFile)) | |
| 232 | 230 | @ %h(zFile)</a> |
| 233 | 231 | }else{ |
| 234 | 232 | @ %h(zFile) |
| 235 | 233 | } |
| 236 | 234 | @ added by %h(zUser) on |
| 237 | 235 | hyperlink_to_date(zDate, "."); |
| 238 | 236 | if( g.perm.WrWiki && g.perm.Attach ){ |
| 239 | - @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&file=%t(zFile)&from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>] | |
| 237 | + @ [%z(href("%R/attachdelete?page=%t&file=%t&from=%R/wiki%%3fname=%f",zPageName,zFile,zPageName))delete</a>] | |
| 240 | 238 | } |
| 241 | 239 | @ </li> |
| 242 | 240 | } |
| 243 | 241 | if( cnt ){ |
| 244 | 242 | @ </ul> |
| @@ -544,11 +542,11 @@ | ||
| 544 | 542 | ** Function called to output extra text at the end of each line in |
| 545 | 543 | ** a wiki history listing. |
| 546 | 544 | */ |
| 547 | 545 | static void wiki_history_extra(int rid){ |
| 548 | 546 | if( db_exists("SELECT 1 FROM tagxref WHERE rid=%d", rid) ){ |
| 549 | - @ <a href="%s(g.zTop)/wdiff?name=%t(zWikiPageName)&a=%d(rid)">[diff]</a> | |
| 547 | + @ %z(href("%R/wdiff?name=%t&a=%d",zWikiPageName,rid))[diff]</a> | |
| 550 | 548 | } |
| 551 | 549 | } |
| 552 | 550 | |
| 553 | 551 | /* |
| 554 | 552 | ** WEBPAGE: whistory |
| @@ -560,11 +558,11 @@ | ||
| 560 | 558 | Stmt q; |
| 561 | 559 | char *zTitle; |
| 562 | 560 | char *zSQL; |
| 563 | 561 | const char *zPageName; |
| 564 | 562 | login_check_credentials(); |
| 565 | - if( !g.perm.History ){ login_needed(); return; } | |
| 563 | + if( !g.perm.Hyperlink ){ login_needed(); return; } | |
| 566 | 564 | zPageName = PD("name",""); |
| 567 | 565 | zTitle = mprintf("History Of %s", zPageName); |
| 568 | 566 | style_header(zTitle); |
| 569 | 567 | free(zTitle); |
| 570 | 568 | |
| @@ -597,11 +595,11 @@ | ||
| 597 | 595 | Blob w1, w2, d; |
| 598 | 596 | int diffFlags; |
| 599 | 597 | |
| 600 | 598 | login_check_credentials(); |
| 601 | 599 | rid1 = atoi(PD("a","0")); |
| 602 | - if( !g.perm.History ){ login_needed(); return; } | |
| 600 | + if( !g.perm.Hyperlink ){ login_needed(); return; } | |
| 603 | 601 | if( rid1==0 ) fossil_redirect_home(); |
| 604 | 602 | rid2 = atoi(PD("b","0")); |
| 605 | 603 | zPageName = PD("name",""); |
| 606 | 604 | zTitle = mprintf("Changes To %s", zPageName); |
| 607 | 605 | style_header(zTitle); |
| @@ -674,13 +672,13 @@ | ||
| 674 | 672 | wiki_prepare_page_list(&q); |
| 675 | 673 | while( db_step(&q)==SQLITE_ROW ){ |
| 676 | 674 | const char *zName = db_column_text(&q, 0); |
| 677 | 675 | int size = db_column_int(&q, 1); |
| 678 | 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 | 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 | 682 | db_finalize(&q); |
| 685 | 683 | @ </ul> |
| 686 | 684 | style_footer(); |
| @@ -704,11 +702,11 @@ | ||
| 704 | 702 | "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'" |
| 705 | 703 | " ORDER BY lower(tagname) /*sort*/" , |
| 706 | 704 | zTitle); |
| 707 | 705 | while( db_step(&q)==SQLITE_ROW ){ |
| 708 | 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 | 709 | db_finalize(&q); |
| 712 | 710 | @ </ul> |
| 713 | 711 | style_footer(); |
| 714 | 712 | } |
| 715 | 713 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -104,11 +104,11 @@ | |
| 104 | return; |
| 105 | } |
| 106 | style_header("Home"); |
| 107 | @ <p>This is a stub home-page for the project. |
| 108 | @ To fill in this page, first go to |
| 109 | @ <a href="%s(g.zTop)/setup_config">setup/config</a> |
| 110 | @ and establish a "Project Name". Then create a |
| 111 | @ wiki page with that name. The content of that wiki page |
| 112 | @ will be displayed in place of this message.</p> |
| 113 | style_footer(); |
| 114 | } |
| @@ -142,27 +142,25 @@ | |
| 142 | if( zPageName==0 ){ |
| 143 | style_header("Wiki"); |
| 144 | @ <ul> |
| 145 | { char *zHomePageName = db_get("project-name",0); |
| 146 | if( zHomePageName ){ |
| 147 | @ <li> <a href="%s(g.zTop)/wiki?name=%t(zHomePageName)"> |
| 148 | @ %h(zHomePageName)</a> wiki home page.</li> |
| 149 | } |
| 150 | } |
| 151 | @ <li> <a href="%s(g.zTop)/timeline?y=w">Recent changes</a> to wiki |
| 152 | @ pages. </li> |
| 153 | @ <li> <a href="%s(g.zTop)/wiki_rules">Formatting rules</a> for |
| 154 | @ wiki.</li> |
| 155 | @ <li> Use the <a href="%s(g.zTop)/wiki?name=Sandbox">Sandbox</a> |
| 156 | @ to experiment.</li> |
| 157 | if( g.perm.NewWiki ){ |
| 158 | @ <li> Create a <a href="%s(g.zTop)/wikinew">new wiki page</a>.</li> |
| 159 | if( g.perm.Write ){ |
| 160 | @ <li> Create a <a href="%s(g.zTop)/eventedit">new event</a>.</li> |
| 161 | } |
| 162 | } |
| 163 | @ <li> <a href="%s(g.zTop)/wcontent">List of All Wiki Pages</a> |
| 164 | @ available on this server.</li> |
| 165 | @ <li> <form method="get" action="%s(g.zTop)/wfind"><div> |
| 166 | @ Search wiki titles: <input type="text" name="title"/> |
| 167 | @ <input type="submit" /></div></form> |
| 168 | @ </li> |
| @@ -192,18 +190,18 @@ | |
| 192 | style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T", |
| 193 | g.zTop, zPageName); |
| 194 | } |
| 195 | if( rid && g.perm.ApndWiki && g.perm.Attach ){ |
| 196 | style_submenu_element("Attach", "Add An Attachment", |
| 197 | "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T", |
| 198 | g.zTop, zPageName, g.zTop, zPageName); |
| 199 | } |
| 200 | if( rid && g.perm.ApndWiki ){ |
| 201 | style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T", |
| 202 | g.zTop, zPageName); |
| 203 | } |
| 204 | if( g.perm.History ){ |
| 205 | style_submenu_element("History", "History", "%s/whistory?name=%T", |
| 206 | g.zTop, zPageName); |
| 207 | } |
| 208 | } |
| 209 | style_header(zPageName); |
| @@ -225,20 +223,20 @@ | |
| 225 | @ <hr /><h2>Attachments:</h2> |
| 226 | @ <ul> |
| 227 | } |
| 228 | cnt++; |
| 229 | @ <li> |
| 230 | if( g.perm.History && g.perm.Read ){ |
| 231 | @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&file=%t(zFile)"> |
| 232 | @ %h(zFile)</a> |
| 233 | }else{ |
| 234 | @ %h(zFile) |
| 235 | } |
| 236 | @ added by %h(zUser) on |
| 237 | hyperlink_to_date(zDate, "."); |
| 238 | if( g.perm.WrWiki && g.perm.Attach ){ |
| 239 | @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&file=%t(zFile)&from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>] |
| 240 | } |
| 241 | @ </li> |
| 242 | } |
| 243 | if( cnt ){ |
| 244 | @ </ul> |
| @@ -544,11 +542,11 @@ | |
| 544 | ** Function called to output extra text at the end of each line in |
| 545 | ** a wiki history listing. |
| 546 | */ |
| 547 | static void wiki_history_extra(int rid){ |
| 548 | if( db_exists("SELECT 1 FROM tagxref WHERE rid=%d", rid) ){ |
| 549 | @ <a href="%s(g.zTop)/wdiff?name=%t(zWikiPageName)&a=%d(rid)">[diff]</a> |
| 550 | } |
| 551 | } |
| 552 | |
| 553 | /* |
| 554 | ** WEBPAGE: whistory |
| @@ -560,11 +558,11 @@ | |
| 560 | Stmt q; |
| 561 | char *zTitle; |
| 562 | char *zSQL; |
| 563 | const char *zPageName; |
| 564 | login_check_credentials(); |
| 565 | if( !g.perm.History ){ login_needed(); return; } |
| 566 | zPageName = PD("name",""); |
| 567 | zTitle = mprintf("History Of %s", zPageName); |
| 568 | style_header(zTitle); |
| 569 | free(zTitle); |
| 570 | |
| @@ -597,11 +595,11 @@ | |
| 597 | Blob w1, w2, d; |
| 598 | int diffFlags; |
| 599 | |
| 600 | login_check_credentials(); |
| 601 | rid1 = atoi(PD("a","0")); |
| 602 | if( !g.perm.History ){ login_needed(); return; } |
| 603 | if( rid1==0 ) fossil_redirect_home(); |
| 604 | rid2 = atoi(PD("b","0")); |
| 605 | zPageName = PD("name",""); |
| 606 | zTitle = mprintf("Changes To %s", zPageName); |
| 607 | style_header(zTitle); |
| @@ -674,13 +672,13 @@ | |
| 674 | wiki_prepare_page_list(&q); |
| 675 | while( db_step(&q)==SQLITE_ROW ){ |
| 676 | const char *zName = db_column_text(&q, 0); |
| 677 | int size = db_column_int(&q, 1); |
| 678 | if( size>0 ){ |
| 679 | @ <li><a href="%s(g.zTop)/wiki?name=%T(zName)">%h(zName)</a></li> |
| 680 | }else if( showAll ){ |
| 681 | @ <li><a href="%s(g.zTop)/wiki?name=%T(zName)"><s>%h(zName)</s></a></li> |
| 682 | } |
| 683 | } |
| 684 | db_finalize(&q); |
| 685 | @ </ul> |
| 686 | style_footer(); |
| @@ -704,11 +702,11 @@ | |
| 704 | "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'" |
| 705 | " ORDER BY lower(tagname) /*sort*/" , |
| 706 | zTitle); |
| 707 | while( db_step(&q)==SQLITE_ROW ){ |
| 708 | const char *zName = db_column_text(&q, 0); |
| 709 | @ <li><a href="%s(g.zTop)/wiki?name=%T(zName)">%h(zName)</a></li> |
| 710 | } |
| 711 | db_finalize(&q); |
| 712 | @ </ul> |
| 713 | style_footer(); |
| 714 | } |
| 715 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -104,11 +104,11 @@ | |
| 104 | return; |
| 105 | } |
| 106 | style_header("Home"); |
| 107 | @ <p>This is a stub home-page for the project. |
| 108 | @ To fill in this page, first go to |
| 109 | @ %z(href("%R/setup_config"))setup/config</a> |
| 110 | @ and establish a "Project Name". Then create a |
| 111 | @ wiki page with that name. The content of that wiki page |
| 112 | @ will be displayed in place of this message.</p> |
| 113 | style_footer(); |
| 114 | } |
| @@ -142,27 +142,25 @@ | |
| 142 | if( zPageName==0 ){ |
| 143 | style_header("Wiki"); |
| 144 | @ <ul> |
| 145 | { char *zHomePageName = db_get("project-name",0); |
| 146 | if( zHomePageName ){ |
| 147 | @ <li> %z(href("%R/wiki?name=%t",zHomePageName)) |
| 148 | @ %h(zHomePageName)</a> wiki home page.</li> |
| 149 | } |
| 150 | } |
| 151 | @ <li> %z(href("%R/timeline?y=w"))Recent changes</a> to wiki pages.</li> |
| 152 | @ <li> %z(href("%R/wiki_rules"))Formatting rules</a> for wiki.</li> |
| 153 | @ <li> Use the %z(href("%R/wiki?name=Sandbox"))Sandbox</a> |
| 154 | @ to experiment.</li> |
| 155 | if( g.perm.NewWiki ){ |
| 156 | @ <li> Create a %z(href("%R/wikinew"))new wiki page</a>.</li> |
| 157 | if( g.perm.Write ){ |
| 158 | @ <li> Create a %z(href("%R/eventedit"))new event</a>.</li> |
| 159 | } |
| 160 | } |
| 161 | @ <li> %z(href("%R/wcontent"))List of All Wiki Pages</a> |
| 162 | @ available on this server.</li> |
| 163 | @ <li> <form method="get" action="%s(g.zTop)/wfind"><div> |
| 164 | @ Search wiki titles: <input type="text" name="title"/> |
| 165 | @ <input type="submit" /></div></form> |
| 166 | @ </li> |
| @@ -192,18 +190,18 @@ | |
| 190 | style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T", |
| 191 | g.zTop, zPageName); |
| 192 | } |
| 193 | if( rid && g.perm.ApndWiki && g.perm.Attach ){ |
| 194 | style_submenu_element("Attach", "Add An Attachment", |
| 195 | "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T", |
| 196 | g.zTop, zPageName, g.zTop, zPageName); |
| 197 | } |
| 198 | if( rid && g.perm.ApndWiki ){ |
| 199 | style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T", |
| 200 | g.zTop, zPageName); |
| 201 | } |
| 202 | if( g.perm.Hyperlink ){ |
| 203 | style_submenu_element("History", "History", "%s/whistory?name=%T", |
| 204 | g.zTop, zPageName); |
| 205 | } |
| 206 | } |
| 207 | style_header(zPageName); |
| @@ -225,20 +223,20 @@ | |
| 223 | @ <hr /><h2>Attachments:</h2> |
| 224 | @ <ul> |
| 225 | } |
| 226 | cnt++; |
| 227 | @ <li> |
| 228 | if( g.perm.Hyperlink && g.perm.Read ){ |
| 229 | @ %z(href("%R/attachview?page=%T&file=%t",zPageName,zFile)) |
| 230 | @ %h(zFile)</a> |
| 231 | }else{ |
| 232 | @ %h(zFile) |
| 233 | } |
| 234 | @ added by %h(zUser) on |
| 235 | hyperlink_to_date(zDate, "."); |
| 236 | if( g.perm.WrWiki && g.perm.Attach ){ |
| 237 | @ [%z(href("%R/attachdelete?page=%t&file=%t&from=%R/wiki%%3fname=%f",zPageName,zFile,zPageName))delete</a>] |
| 238 | } |
| 239 | @ </li> |
| 240 | } |
| 241 | if( cnt ){ |
| 242 | @ </ul> |
| @@ -544,11 +542,11 @@ | |
| 542 | ** Function called to output extra text at the end of each line in |
| 543 | ** a wiki history listing. |
| 544 | */ |
| 545 | static void wiki_history_extra(int rid){ |
| 546 | if( db_exists("SELECT 1 FROM tagxref WHERE rid=%d", rid) ){ |
| 547 | @ %z(href("%R/wdiff?name=%t&a=%d",zWikiPageName,rid))[diff]</a> |
| 548 | } |
| 549 | } |
| 550 | |
| 551 | /* |
| 552 | ** WEBPAGE: whistory |
| @@ -560,11 +558,11 @@ | |
| 558 | Stmt q; |
| 559 | char *zTitle; |
| 560 | char *zSQL; |
| 561 | const char *zPageName; |
| 562 | login_check_credentials(); |
| 563 | if( !g.perm.Hyperlink ){ login_needed(); return; } |
| 564 | zPageName = PD("name",""); |
| 565 | zTitle = mprintf("History Of %s", zPageName); |
| 566 | style_header(zTitle); |
| 567 | free(zTitle); |
| 568 | |
| @@ -597,11 +595,11 @@ | |
| 595 | Blob w1, w2, d; |
| 596 | int diffFlags; |
| 597 | |
| 598 | login_check_credentials(); |
| 599 | rid1 = atoi(PD("a","0")); |
| 600 | if( !g.perm.Hyperlink ){ login_needed(); return; } |
| 601 | if( rid1==0 ) fossil_redirect_home(); |
| 602 | rid2 = atoi(PD("b","0")); |
| 603 | zPageName = PD("name",""); |
| 604 | zTitle = mprintf("Changes To %s", zPageName); |
| 605 | style_header(zTitle); |
| @@ -674,13 +672,13 @@ | |
| 672 | wiki_prepare_page_list(&q); |
| 673 | while( db_step(&q)==SQLITE_ROW ){ |
| 674 | const char *zName = db_column_text(&q, 0); |
| 675 | int size = db_column_int(&q, 1); |
| 676 | if( size>0 ){ |
| 677 | @ <li>%z(href("%R/wiki?name=%T",zName))%h(zName)</a></li> |
| 678 | }else if( showAll ){ |
| 679 | @ <li>%z(href("%R/wiki?name=%T",zName))<s>%h(zName)</s></a></li> |
| 680 | } |
| 681 | } |
| 682 | db_finalize(&q); |
| 683 | @ </ul> |
| 684 | style_footer(); |
| @@ -704,11 +702,11 @@ | |
| 702 | "SELECT substr(tagname, 6, 1000) FROM tag WHERE tagname like 'wiki-%%%q%%'" |
| 703 | " ORDER BY lower(tagname) /*sort*/" , |
| 704 | zTitle); |
| 705 | while( db_step(&q)==SQLITE_ROW ){ |
| 706 | const char *zName = db_column_text(&q, 0); |
| 707 | @ <li>%z(href("%R/wiki?name=%T",zName))%h(zName)</a></li> |
| 708 | } |
| 709 | db_finalize(&q); |
| 710 | @ </ul> |
| 711 | style_footer(); |
| 712 | } |
| 713 |
+9
-15
| --- src/wikiformat.c | ||
| +++ src/wikiformat.c | ||
| @@ -1043,17 +1043,13 @@ | ||
| 1043 | 1043 | || strncmp(zTarget, "mailto:", 7)==0 |
| 1044 | 1044 | ){ |
| 1045 | 1045 | blob_appendf(p->pOut, "<a href=\"%s\">", zTarget); |
| 1046 | 1046 | /* zTerm = "⟾</a>"; // doesn't work on windows */ |
| 1047 | 1047 | }else if( zTarget[0]=='/' ){ |
| 1048 | - if( 1 /* g.perm.History */ ){ | |
| 1049 | - blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zTop, zTarget); | |
| 1050 | - }else{ | |
| 1051 | - zTerm = ""; | |
| 1052 | - } | |
| 1048 | + blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zTop, zTarget); | |
| 1053 | 1049 | }else if( zTarget[0]=='.' || zTarget[0]=='#' ){ |
| 1054 | - if( 1 /* g.perm.History */ ){ | |
| 1050 | + if( 1 ){ | |
| 1055 | 1051 | blob_appendf(p->pOut, "<a href=\"%h\">", zTarget); |
| 1056 | 1052 | }else{ |
| 1057 | 1053 | zTerm = ""; |
| 1058 | 1054 | } |
| 1059 | 1055 | }else if( is_valid_uuid(zTarget) ){ |
| @@ -1061,36 +1057,34 @@ | ||
| 1061 | 1057 | if( is_ticket(zTarget, &isClosed) ){ |
| 1062 | 1058 | /* Special display processing for tickets. Display the hyperlink |
| 1063 | 1059 | ** as crossed out if the ticket is closed. |
| 1064 | 1060 | */ |
| 1065 | 1061 | if( isClosed ){ |
| 1066 | - if( g.perm.History ){ | |
| 1062 | + if( g.perm.Hyperlink ){ | |
| 1067 | 1063 | blob_appendf(p->pOut, |
| 1068 | - "<a href=\"%s/info/%s\"><span class=\"wikiTagCancelled\">[", | |
| 1069 | - g.zTop, zTarget | |
| 1064 | + "%z<span class=\"wikiTagCancelled\">[", | |
| 1065 | + href("%R/info/%s",zTarget) | |
| 1070 | 1066 | ); |
| 1071 | 1067 | zTerm = "]</span></a>"; |
| 1072 | 1068 | }else{ |
| 1073 | 1069 | blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">["); |
| 1074 | 1070 | zTerm = "]</span>"; |
| 1075 | 1071 | } |
| 1076 | 1072 | }else{ |
| 1077 | - if( g.perm.History ){ | |
| 1078 | - blob_appendf(p->pOut,"<a href=\"%s/info/%s\">[", | |
| 1079 | - g.zTop, zTarget | |
| 1080 | - ); | |
| 1073 | + if( g.perm.Hyperlink ){ | |
| 1074 | + blob_appendf(p->pOut,"%z[", href("%R/info/%s", zTarget)); | |
| 1081 | 1075 | zTerm = "]</a>"; |
| 1082 | 1076 | }else{ |
| 1083 | 1077 | blob_appendf(p->pOut, "["); |
| 1084 | 1078 | zTerm = "]"; |
| 1085 | 1079 | } |
| 1086 | 1080 | } |
| 1087 | 1081 | }else if( !in_this_repo(zTarget) ){ |
| 1088 | 1082 | blob_appendf(p->pOut, "<span class=\"brokenlink\">[", zTarget); |
| 1089 | 1083 | zTerm = "]</span>"; |
| 1090 | - }else if( g.perm.History ){ | |
| 1091 | - blob_appendf(p->pOut, "<a href=\"%s/info/%s\">[", g.zTop, zTarget); | |
| 1084 | + }else if( g.perm.Hyperlink ){ | |
| 1085 | + blob_appendf(p->pOut, "%z[",href("%R/info/%s", zTarget)); | |
| 1092 | 1086 | zTerm = "]</a>"; |
| 1093 | 1087 | } |
| 1094 | 1088 | }else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-' |
| 1095 | 1089 | && db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){ |
| 1096 | 1090 | blob_appendf(p->pOut, "<a href=\"%s/timeline?c=%T\">", g.zTop, zTarget); |
| 1097 | 1091 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -1043,17 +1043,13 @@ | |
| 1043 | || strncmp(zTarget, "mailto:", 7)==0 |
| 1044 | ){ |
| 1045 | blob_appendf(p->pOut, "<a href=\"%s\">", zTarget); |
| 1046 | /* zTerm = "⟾</a>"; // doesn't work on windows */ |
| 1047 | }else if( zTarget[0]=='/' ){ |
| 1048 | if( 1 /* g.perm.History */ ){ |
| 1049 | blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zTop, zTarget); |
| 1050 | }else{ |
| 1051 | zTerm = ""; |
| 1052 | } |
| 1053 | }else if( zTarget[0]=='.' || zTarget[0]=='#' ){ |
| 1054 | if( 1 /* g.perm.History */ ){ |
| 1055 | blob_appendf(p->pOut, "<a href=\"%h\">", zTarget); |
| 1056 | }else{ |
| 1057 | zTerm = ""; |
| 1058 | } |
| 1059 | }else if( is_valid_uuid(zTarget) ){ |
| @@ -1061,36 +1057,34 @@ | |
| 1061 | if( is_ticket(zTarget, &isClosed) ){ |
| 1062 | /* Special display processing for tickets. Display the hyperlink |
| 1063 | ** as crossed out if the ticket is closed. |
| 1064 | */ |
| 1065 | if( isClosed ){ |
| 1066 | if( g.perm.History ){ |
| 1067 | blob_appendf(p->pOut, |
| 1068 | "<a href=\"%s/info/%s\"><span class=\"wikiTagCancelled\">[", |
| 1069 | g.zTop, zTarget |
| 1070 | ); |
| 1071 | zTerm = "]</span></a>"; |
| 1072 | }else{ |
| 1073 | blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">["); |
| 1074 | zTerm = "]</span>"; |
| 1075 | } |
| 1076 | }else{ |
| 1077 | if( g.perm.History ){ |
| 1078 | blob_appendf(p->pOut,"<a href=\"%s/info/%s\">[", |
| 1079 | g.zTop, zTarget |
| 1080 | ); |
| 1081 | zTerm = "]</a>"; |
| 1082 | }else{ |
| 1083 | blob_appendf(p->pOut, "["); |
| 1084 | zTerm = "]"; |
| 1085 | } |
| 1086 | } |
| 1087 | }else if( !in_this_repo(zTarget) ){ |
| 1088 | blob_appendf(p->pOut, "<span class=\"brokenlink\">[", zTarget); |
| 1089 | zTerm = "]</span>"; |
| 1090 | }else if( g.perm.History ){ |
| 1091 | blob_appendf(p->pOut, "<a href=\"%s/info/%s\">[", g.zTop, zTarget); |
| 1092 | zTerm = "]</a>"; |
| 1093 | } |
| 1094 | }else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-' |
| 1095 | && db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){ |
| 1096 | blob_appendf(p->pOut, "<a href=\"%s/timeline?c=%T\">", g.zTop, zTarget); |
| 1097 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -1043,17 +1043,13 @@ | |
| 1043 | || strncmp(zTarget, "mailto:", 7)==0 |
| 1044 | ){ |
| 1045 | blob_appendf(p->pOut, "<a href=\"%s\">", zTarget); |
| 1046 | /* zTerm = "⟾</a>"; // doesn't work on windows */ |
| 1047 | }else if( zTarget[0]=='/' ){ |
| 1048 | blob_appendf(p->pOut, "<a href=\"%s%h\">", g.zTop, zTarget); |
| 1049 | }else if( zTarget[0]=='.' || zTarget[0]=='#' ){ |
| 1050 | if( 1 ){ |
| 1051 | blob_appendf(p->pOut, "<a href=\"%h\">", zTarget); |
| 1052 | }else{ |
| 1053 | zTerm = ""; |
| 1054 | } |
| 1055 | }else if( is_valid_uuid(zTarget) ){ |
| @@ -1061,36 +1057,34 @@ | |
| 1057 | if( is_ticket(zTarget, &isClosed) ){ |
| 1058 | /* Special display processing for tickets. Display the hyperlink |
| 1059 | ** as crossed out if the ticket is closed. |
| 1060 | */ |
| 1061 | if( isClosed ){ |
| 1062 | if( g.perm.Hyperlink ){ |
| 1063 | blob_appendf(p->pOut, |
| 1064 | "%z<span class=\"wikiTagCancelled\">[", |
| 1065 | href("%R/info/%s",zTarget) |
| 1066 | ); |
| 1067 | zTerm = "]</span></a>"; |
| 1068 | }else{ |
| 1069 | blob_appendf(p->pOut,"<span class=\"wikiTagCancelled\">["); |
| 1070 | zTerm = "]</span>"; |
| 1071 | } |
| 1072 | }else{ |
| 1073 | if( g.perm.Hyperlink ){ |
| 1074 | blob_appendf(p->pOut,"%z[", href("%R/info/%s", zTarget)); |
| 1075 | zTerm = "]</a>"; |
| 1076 | }else{ |
| 1077 | blob_appendf(p->pOut, "["); |
| 1078 | zTerm = "]"; |
| 1079 | } |
| 1080 | } |
| 1081 | }else if( !in_this_repo(zTarget) ){ |
| 1082 | blob_appendf(p->pOut, "<span class=\"brokenlink\">[", zTarget); |
| 1083 | zTerm = "]</span>"; |
| 1084 | }else if( g.perm.Hyperlink ){ |
| 1085 | blob_appendf(p->pOut, "%z[",href("%R/info/%s", zTarget)); |
| 1086 | zTerm = "]</a>"; |
| 1087 | } |
| 1088 | }else if( strlen(zTarget)>=10 && fossil_isdigit(zTarget[0]) && zTarget[4]=='-' |
| 1089 | && db_int(0, "SELECT datetime(%Q) NOT NULL", zTarget) ){ |
| 1090 | blob_appendf(p->pOut, "<a href=\"%s/timeline?c=%T\">", g.zTop, zTarget); |
| 1091 |