Fossil SCM
Refinements to the new hyperlink logic and spider defense.
Commit
d9c8a7dd73a7718527a8b95eb6971b059ce99636
Parent
8ae52fc4183f310…
18 files changed
+2
-2
+6
-6
+1
-1
+4
-4
+3
-3
+7
-7
+1
-1
+2
-2
+1
-1
+15
-16
+3
-11
+3
-3
+19
-20
+13
-12
+3
-3
+6
-6
+4
-4
+1
-5
+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 |
+6
-6
| --- src/browse.c | ||
| +++ src/browse.c | ||
| @@ -77,13 +77,13 @@ | ||
| 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 | - char *zLink = href("%R/dir?ci=%S&name=%#T", zCI, j, zPath); | |
| 84 | + char *zLink = href("%R/dir?ci=%S&name=%#T", zCI, j, zPath); | |
| 85 | 85 | blob_appendf(pOut, "%s%z%#h</a>", |
| 86 | 86 | zSep, zLink, j-i, &zPath[i]); |
| 87 | 87 | }else{ |
| 88 | 88 | char *zLink = href("%R/dir?name=%#T", j, zPath); |
| 89 | 89 | blob_appendf(pOut, "%s%z%#h</a>", |
| @@ -120,11 +120,11 @@ | ||
| 120 | 120 | Blob dirname; |
| 121 | 121 | Manifest *pM = 0; |
| 122 | 122 | const char *zSubdirLink; |
| 123 | 123 | |
| 124 | 124 | login_check_credentials(); |
| 125 | - if( !g.perm.History ){ login_needed(); return; } | |
| 125 | + if( !g.perm.Hyperlink ){ login_needed(); return; } | |
| 126 | 126 | while( nD>1 && zD[nD-2]=='/' ){ zD[(--nD)-1] = 0; } |
| 127 | 127 | style_header("File List"); |
| 128 | 128 | sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0, |
| 129 | 129 | pathelementFunc, 0, 0); |
| 130 | 130 | |
| @@ -159,11 +159,11 @@ | ||
| 159 | 159 | char zShort[20]; |
| 160 | 160 | memcpy(zShort, zUuid, 10); |
| 161 | 161 | zShort[10] = 0; |
| 162 | 162 | @ <h2>Files of check-in [%z(href("vinfo?name=%T",zUuid))%s(zShort)</a>] |
| 163 | 163 | @ %s(blob_str(&dirname))</h2> |
| 164 | - zSubdirLink = mprintf("%R/dir?ci=%S&name=%T", zUuid, zPrefix); | |
| 164 | + zSubdirLink = mprintf("%R/dir?ci=%S&name=%T", zUuid, zPrefix); | |
| 165 | 165 | if( zD ){ |
| 166 | 166 | style_submenu_element("Top", "Top", "%R/dir?ci=%S", zUuid); |
| 167 | 167 | style_submenu_element("All", "All", "%R/dir?name=%t", zD); |
| 168 | 168 | }else{ |
| 169 | 169 | style_submenu_element("All", "All", "%R/dir"); |
| @@ -176,13 +176,13 @@ | ||
| 176 | 176 | "SELECT 1 FROM tagxref WHERE tagid=%d AND value='trunk'", |
| 177 | 177 | TAG_BRANCH); |
| 178 | 178 | zSubdirLink = mprintf("%R/dir?name=%T", zPrefix); |
| 179 | 179 | if( zD ){ |
| 180 | 180 | style_submenu_element("Top", "Top", "%R/dir"); |
| 181 | - style_submenu_element("Tip", "Tip", "%R/dir?name=%t&ci=tip", zD); | |
| 181 | + style_submenu_element("Tip", "Tip", "%R/dir?name=%t&ci=tip", zD); | |
| 182 | 182 | if( hasTrunk ){ |
| 183 | - style_submenu_element("Trunk", "Trunk", "%R/dir?name=%t&ci=trunk", | |
| 183 | + style_submenu_element("Trunk", "Trunk", "%R/dir?name=%t&ci=trunk", | |
| 184 | 184 | zD); |
| 185 | 185 | } |
| 186 | 186 | }else{ |
| 187 | 187 | style_submenu_element("Tip", "Tip", "%R/dir?ci=tip"); |
| 188 | 188 | if( hasTrunk ){ |
| 189 | 189 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -77,13 +77,13 @@ | |
| 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 | 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>", |
| @@ -120,11 +120,11 @@ | |
| 120 | Blob dirname; |
| 121 | Manifest *pM = 0; |
| 122 | const char *zSubdirLink; |
| 123 | |
| 124 | login_check_credentials(); |
| 125 | if( !g.perm.History ){ 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 | |
| @@ -159,11 +159,11 @@ | |
| 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"); |
| @@ -176,13 +176,13 @@ | |
| 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 |
| --- src/browse.c | |
| +++ src/browse.c | |
| @@ -77,13 +77,13 @@ | |
| 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>", |
| @@ -120,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 | |
| @@ -159,11 +159,11 @@ | |
| 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"); |
| @@ -176,13 +176,13 @@ | |
| 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 |
+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 |
+4
-4
| --- src/event.c | ||
| +++ src/event.c | ||
| @@ -125,31 +125,31 @@ | ||
| 125 | 125 | zETime = db_text(0, "SELECT datetime(%.17g)", pEvent->rEventDate); |
| 126 | 126 | style_submenu_element("Context", "Context", "%s/timeline?c=%T", |
| 127 | 127 | g.zTop, zETime); |
| 128 | 128 | if( g.perm.Hyperlink ){ |
| 129 | 129 | if( showDetail ){ |
| 130 | - style_submenu_element("Plain", "Plain", "%s/event?name=%s&aid=%s", | |
| 130 | + style_submenu_element("Plain", "Plain", "%s/event?name=%s&aid=%s", | |
| 131 | 131 | g.zTop, zEventId, zUuid); |
| 132 | 132 | if( nextRid ){ |
| 133 | 133 | char *zNext; |
| 134 | 134 | zNext = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", nextRid); |
| 135 | 135 | style_submenu_element("Next", "Next", |
| 136 | - "%s/event?name=%s&aid=%s&detail=1", | |
| 136 | + "%s/event?name=%s&aid=%s&detail=1", | |
| 137 | 137 | g.zTop, zEventId, zNext); |
| 138 | 138 | free(zNext); |
| 139 | 139 | } |
| 140 | 140 | if( prevRid ){ |
| 141 | 141 | char *zPrev; |
| 142 | 142 | zPrev = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", prevRid); |
| 143 | 143 | style_submenu_element("Prev", "Prev", |
| 144 | - "%s/event?name=%s&aid=%s&detail=1", | |
| 144 | + "%s/event?name=%s&aid=%s&detail=1", | |
| 145 | 145 | g.zTop, zEventId, zPrev); |
| 146 | 146 | free(zPrev); |
| 147 | 147 | } |
| 148 | 148 | }else{ |
| 149 | 149 | style_submenu_element("Detail", "Detail", |
| 150 | - "%s/event?name=%s&aid=%s&detail=1", | |
| 150 | + "%s/event?name=%s&aid=%s&detail=1", | |
| 151 | 151 | g.zTop, zEventId, zUuid); |
| 152 | 152 | } |
| 153 | 153 | } |
| 154 | 154 | |
| 155 | 155 | if( showDetail && g.perm.Hyperlink ){ |
| 156 | 156 |
| --- src/event.c | |
| +++ src/event.c | |
| @@ -125,31 +125,31 @@ | |
| 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 |
| --- src/event.c | |
| +++ src/event.c | |
| @@ -125,31 +125,31 @@ | |
| 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 |
+3
-3
| --- src/finfo.c | ||
| +++ src/finfo.c | ||
| @@ -323,16 +323,16 @@ | ||
| 323 | 323 | } |
| 324 | 324 | hyperlink_to_uuid(zShortCkin); |
| 325 | 325 | @ %h(zCom) (user: |
| 326 | 326 | hyperlink_to_user(zUser, zDate, ""); |
| 327 | 327 | @ branch: %h(zBr)) |
| 328 | - if( g.perm.History && zUuid ){ | |
| 328 | + if( g.perm.Hyperlink && zUuid ){ | |
| 329 | 329 | const char *z = zFilename; |
| 330 | 330 | if( fpid ){ |
| 331 | - @ %z(href("%R/fdiff?v1=%s&v2=%s",zPUuid,zUuid))[diff]</a> | |
| 331 | + @ %z(href("%R/fdiff?v1=%s&v2=%s",zPUuid,zUuid))[diff]</a> | |
| 332 | 332 | } |
| 333 | - @ %z(href("%R/annotate?checkin=%S&filename=%h",zCkin,z)) | |
| 333 | + @ %z(href("%R/annotate?checkin=%S&filename=%h",zCkin,z)) | |
| 334 | 334 | @ [annotate]</a> |
| 335 | 335 | } |
| 336 | 336 | @ </td></tr> |
| 337 | 337 | } |
| 338 | 338 | db_finalize(&q); |
| 339 | 339 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -323,16 +323,16 @@ | |
| 323 | } |
| 324 | hyperlink_to_uuid(zShortCkin); |
| 325 | @ %h(zCom) (user: |
| 326 | hyperlink_to_user(zUser, zDate, ""); |
| 327 | @ branch: %h(zBr)) |
| 328 | if( g.perm.History && zUuid ){ |
| 329 | const char *z = zFilename; |
| 330 | if( fpid ){ |
| 331 | @ %z(href("%R/fdiff?v1=%s&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 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -323,16 +323,16 @@ | |
| 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 |
+7
-7
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -378,11 +378,11 @@ | ||
| 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 | - @ %z(href("%R/fdiff?v1=%S&v2=%S",zOld,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 | |
| @@ -622,11 +622,11 @@ | ||
| 622 | 622 | @ show unified diffs</a> |
| 623 | 623 | @ %z(xhref("class='button'","%R/vinfo/%T?sbs=1",zName)) |
| 624 | 624 | @ show side-by-side diffs</a> |
| 625 | 625 | } |
| 626 | 626 | } |
| 627 | - @ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,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)," |
| @@ -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; |
| @@ -1258,11 +1258,11 @@ | ||
| 1258 | 1258 | if( !g.perm.Read ){ login_needed(); return; } |
| 1259 | 1259 | if( rid==0 ) fossil_redirect_home(); |
| 1260 | 1260 | if( g.perm.Admin ){ |
| 1261 | 1261 | const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1262 | 1262 | if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ |
| 1263 | - style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", | |
| 1263 | + style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", | |
| 1264 | 1264 | g.zTop, zUuid); |
| 1265 | 1265 | }else{ |
| 1266 | 1266 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1267 | 1267 | g.zTop, zUuid); |
| 1268 | 1268 | } |
| @@ -1405,11 +1405,11 @@ | ||
| 1405 | 1405 | if( !g.perm.Read ){ login_needed(); return; } |
| 1406 | 1406 | if( rid==0 ) fossil_redirect_home(); |
| 1407 | 1407 | if( g.perm.Admin ){ |
| 1408 | 1408 | const char *zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1409 | 1409 | if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ |
| 1410 | - style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", | |
| 1410 | + style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", | |
| 1411 | 1411 | g.zTop, zUuid); |
| 1412 | 1412 | }else{ |
| 1413 | 1413 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1414 | 1414 | g.zTop, zUuid); |
| 1415 | 1415 | } |
| @@ -1464,11 +1464,11 @@ | ||
| 1464 | 1464 | @ <pre> |
| 1465 | 1465 | @ %h(z) |
| 1466 | 1466 | @ </pre> |
| 1467 | 1467 | } |
| 1468 | 1468 | }else if( strncmp(zMime, "image/", 6)==0 ){ |
| 1469 | - @ <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> | |
| 1470 | 1470 | }else{ |
| 1471 | 1471 | @ <i>(file is %d(blob_size(&content)) bytes of binary data)</i> |
| 1472 | 1472 | } |
| 1473 | 1473 | @ </blockquote> |
| 1474 | 1474 | } |
| @@ -1493,11 +1493,11 @@ | ||
| 1493 | 1493 | rid = name_to_rid_www("name"); |
| 1494 | 1494 | if( rid==0 ){ fossil_redirect_home(); } |
| 1495 | 1495 | zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1496 | 1496 | if( g.perm.Admin ){ |
| 1497 | 1497 | if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ |
| 1498 | - style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", | |
| 1498 | + style_submenu_element("Unshun","Unshun", "%s/shun?uuid=%s&sub=1", | |
| 1499 | 1499 | g.zTop, zUuid); |
| 1500 | 1500 | }else{ |
| 1501 | 1501 | style_submenu_element("Shun","Shun", "%s/shun?shun=%s#addshun", |
| 1502 | 1502 | g.zTop, zUuid); |
| 1503 | 1503 | } |
| 1504 | 1504 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -378,11 +378,11 @@ | |
| 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 | |
| @@ -622,11 +622,11 @@ | |
| 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)," |
| @@ -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; |
| @@ -1258,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 | } |
| @@ -1405,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 | } |
| @@ -1464,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 | } |
| @@ -1493,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 | } |
| 1504 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -378,11 +378,11 @@ | |
| 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 | |
| @@ -622,11 +622,11 @@ | |
| 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)," |
| @@ -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; |
| @@ -1258,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 | } |
| @@ -1405,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 | } |
| @@ -1464,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 | } |
| @@ -1493,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 | } |
| 1504 |
+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 |
+15
-16
| --- 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,14 +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 && !g.perm.Link | |
| 916 | + if( zCap[0] && !g.perm.Hyperlink | |
| 917 | 917 | && db_get_boolean("auto-enable-hyperlinks",1) |
| 918 | 918 | && isHuman(P("HTTP_USER_AGENT")) ){ |
| 919 | - g.perm.History = 1; | |
| 919 | + g.perm.Hyperlink = 1; | |
| 920 | + g.javascriptHyperlink = 1; | |
| 920 | 921 | } |
| 921 | 922 | |
| 922 | 923 | /* If the public-pages glob pattern is defined and REQUEST_URI matches |
| 923 | 924 | ** one of the globs in public-pages, then also add in all default-perms |
| 924 | 925 | ** permissions. |
| @@ -974,22 +975,21 @@ | ||
| 974 | 975 | } |
| 975 | 976 | for(i=0; zCap[i]; i++){ |
| 976 | 977 | switch( zCap[i] ){ |
| 977 | 978 | case 's': g.perm.Setup = 1; /* Fall thru into Admin */ |
| 978 | 979 | case 'a': g.perm.Admin = g.perm.RdTkt = g.perm.WrTkt = g.perm.Zip = |
| 979 | - g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki = | |
| 980 | - g.perm.ApndWiki = g.perm.History = g.perm.Clone = | |
| 981 | - g.perm.NewTkt = g.perm.Password = g.perm.RdAddr = | |
| 982 | - g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt = 1; | |
| 983 | - /* 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 */ | |
| 984 | 985 | case 'i': g.perm.Read = g.perm.Write = 1; break; |
| 985 | 986 | case 'o': g.perm.Read = 1; break; |
| 986 | 987 | case 'z': g.perm.Zip = 1; break; |
| 987 | 988 | |
| 988 | 989 | case 'd': g.perm.Delete = 1; break; |
| 989 | - case 'h': g.perm.History = g.perm.Hyperlink = 1; break; | |
| 990 | - case 'l': g.perm.Link = g.perm.Hyperlink = 1; break; | |
| 990 | + case 'h': g.perm.Hyperlink = 1; break; | |
| 991 | 991 | case 'g': g.perm.Clone = 1; break; |
| 992 | 992 | case 'p': g.perm.Password = 1; break; |
| 993 | 993 | |
| 994 | 994 | case 'j': g.perm.RdWiki = 1; break; |
| 995 | 995 | case 'k': g.perm.WrWiki = g.perm.RdWiki = g.perm.ApndWiki =1; break; |
| @@ -1055,15 +1055,14 @@ | ||
| 1055 | 1055 | case 'c': rc = g.perm.ApndTkt; break; |
| 1056 | 1056 | case 'd': rc = g.perm.Delete; break; |
| 1057 | 1057 | case 'e': rc = g.perm.RdAddr; break; |
| 1058 | 1058 | case 'f': rc = g.perm.NewWiki; break; |
| 1059 | 1059 | case 'g': rc = g.perm.Clone; break; |
| 1060 | - case 'h': rc = g.perm.History; break; | |
| 1060 | + case 'h': rc = g.perm.Hyperlink; break; | |
| 1061 | 1061 | case 'i': rc = g.perm.Write; break; |
| 1062 | 1062 | case 'j': rc = g.perm.RdWiki; break; |
| 1063 | 1063 | case 'k': rc = g.perm.WrWiki; break; |
| 1064 | - case 'l': rc = g.perm.Link; break; | |
| 1065 | 1064 | case 'm': rc = g.perm.ApndWiki; break; |
| 1066 | 1065 | case 'n': rc = g.perm.NewTkt; break; |
| 1067 | 1066 | case 'o': rc = g.perm.Read; break; |
| 1068 | 1067 | case 'p': rc = g.perm.Password; break; |
| 1069 | 1068 | /* case 'q': */ |
| @@ -1131,23 +1130,23 @@ | ||
| 1131 | 1130 | assert(0); |
| 1132 | 1131 | } |
| 1133 | 1132 | } |
| 1134 | 1133 | |
| 1135 | 1134 | /* |
| 1136 | -** Call this routine if the user lacks okHistory permission. If | |
| 1137 | -** 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 | |
| 1138 | 1137 | ** to inform the user that much more information is available by |
| 1139 | 1138 | ** logging in as anonymous. |
| 1140 | 1139 | */ |
| 1141 | 1140 | void login_anonymous_available(void){ |
| 1142 | - if( !g.perm.History && !g.perm.Link && | |
| 1141 | + if( !g.perm.Hyperlink && | |
| 1143 | 1142 | db_exists("SELECT 1 FROM user" |
| 1144 | 1143 | " WHERE login='anonymous'" |
| 1145 | 1144 | " AND cap LIKE '%%h%%'") ){ |
| 1146 | 1145 | const char *zUrl = PD("REQUEST_URI", "index"); |
| 1147 | 1146 | @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br /> |
| 1148 | - @ 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> | |
| 1149 | 1148 | @ to enable hyperlinks.</p> |
| 1150 | 1149 | } |
| 1151 | 1150 | } |
| 1152 | 1151 | |
| 1153 | 1152 | /* |
| 1154 | 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,14 +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 && !g.perm.Link |
| 917 | && db_get_boolean("auto-enable-hyperlinks",1) |
| 918 | && isHuman(P("HTTP_USER_AGENT")) ){ |
| 919 | g.perm.History = 1; |
| 920 | } |
| 921 | |
| 922 | /* If the public-pages glob pattern is defined and REQUEST_URI matches |
| 923 | ** one of the globs in public-pages, then also add in all default-perms |
| 924 | ** permissions. |
| @@ -974,22 +975,21 @@ | |
| 974 | } |
| 975 | for(i=0; zCap[i]; i++){ |
| 976 | switch( zCap[i] ){ |
| 977 | case 's': g.perm.Setup = 1; /* Fall thru into Admin */ |
| 978 | case 'a': g.perm.Admin = g.perm.RdTkt = g.perm.WrTkt = g.perm.Zip = |
| 979 | g.perm.RdWiki = g.perm.WrWiki = g.perm.NewWiki = |
| 980 | g.perm.ApndWiki = g.perm.History = g.perm.Clone = |
| 981 | g.perm.NewTkt = g.perm.Password = g.perm.RdAddr = |
| 982 | g.perm.TktFmt = g.perm.Attach = g.perm.ApndTkt = 1; |
| 983 | /* Fall thru into Read/Write */ |
| 984 | case 'i': g.perm.Read = g.perm.Write = 1; break; |
| 985 | case 'o': g.perm.Read = 1; break; |
| 986 | case 'z': g.perm.Zip = 1; break; |
| 987 | |
| 988 | case 'd': g.perm.Delete = 1; break; |
| 989 | case 'h': g.perm.History = g.perm.Hyperlink = 1; break; |
| 990 | case 'l': g.perm.Link = g.perm.Hyperlink = 1; break; |
| 991 | case 'g': g.perm.Clone = 1; break; |
| 992 | case 'p': g.perm.Password = 1; break; |
| 993 | |
| 994 | case 'j': g.perm.RdWiki = 1; break; |
| 995 | case 'k': g.perm.WrWiki = g.perm.RdWiki = g.perm.ApndWiki =1; break; |
| @@ -1055,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.History; break; |
| 1061 | case 'i': rc = g.perm.Write; break; |
| 1062 | case 'j': rc = g.perm.RdWiki; break; |
| 1063 | case 'k': rc = g.perm.WrWiki; break; |
| 1064 | case 'l': rc = g.perm.Link; break; |
| 1065 | case 'm': rc = g.perm.ApndWiki; break; |
| 1066 | case 'n': rc = g.perm.NewTkt; break; |
| 1067 | case 'o': rc = g.perm.Read; break; |
| 1068 | case 'p': rc = g.perm.Password; break; |
| 1069 | /* case 'q': */ |
| @@ -1131,23 +1130,23 @@ | |
| 1131 | assert(0); |
| 1132 | } |
| 1133 | } |
| 1134 | |
| 1135 | /* |
| 1136 | ** Call this routine if the user lacks okHistory permission. If |
| 1137 | ** the anonymous user has okHistory permission, then paint a mesage |
| 1138 | ** to inform the user that much more information is available by |
| 1139 | ** logging in as anonymous. |
| 1140 | */ |
| 1141 | void login_anonymous_available(void){ |
| 1142 | if( !g.perm.History && !g.perm.Link && |
| 1143 | db_exists("SELECT 1 FROM user" |
| 1144 | " WHERE login='anonymous'" |
| 1145 | " AND cap LIKE '%%h%%'") ){ |
| 1146 | const char *zUrl = PD("REQUEST_URI", "index"); |
| 1147 | @ <p>Many <span class="disabled">hyperlinks are disabled.</span><br /> |
| 1148 | @ Use <a href="%s(g.zTop)/login?anon=1&g=%T(zUrl)">anonymous login</a> |
| 1149 | @ to enable hyperlinks.</p> |
| 1150 | } |
| 1151 | } |
| 1152 | |
| 1153 | /* |
| 1154 |
| --- 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,14 +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. |
| @@ -974,22 +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; |
| @@ -1055,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': */ |
| @@ -1131,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
-11
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -51,28 +51,20 @@ | ||
| 51 | 51 | */ |
| 52 | 52 | #define MX_AUX 5 |
| 53 | 53 | |
| 54 | 54 | /* |
| 55 | 55 | ** Holds flags for fossil user permissions. |
| 56 | -** | |
| 57 | -** History enables various hyperlinks directly, with an href= attribute | |
| 58 | -** in the HTML. Link puts an id= attribute in HTML and then adds the | |
| 59 | -** href= attribute using javascript. The Link option is designed to make | |
| 60 | -** it harder for bots and spiders to follow hyperlinks, and yet give the | |
| 61 | -** same experience to users. the Hyperlink permission is a composite which | |
| 62 | -** is enabled if either History or Hyperlink is turned on. | |
| 63 | 56 | */ |
| 64 | 57 | struct FossilUserPerms { |
| 65 | 58 | char Setup; /* s: use Setup screens on web interface */ |
| 66 | 59 | char Admin; /* a: administrative permission */ |
| 67 | 60 | char Delete; /* d: delete wiki or tickets */ |
| 68 | 61 | char Password; /* p: change password */ |
| 69 | 62 | char Query; /* q: create new reports */ |
| 70 | 63 | char Write; /* i: xfer inbound. checkin */ |
| 71 | 64 | char Read; /* o: xfer outbound. checkout */ |
| 72 | - char History; /* h: access historical information. */ | |
| 73 | - char Link; /* l: enable href= using javascript */ | |
| 65 | + char Hyperlink; /* h: enable the display of hyperlinks */ | |
| 74 | 66 | char Clone; /* g: clone */ |
| 75 | 67 | char RdWiki; /* j: view wiki via web */ |
| 76 | 68 | char NewWiki; /* f: create new wiki via web */ |
| 77 | 69 | char ApndWiki; /* m: append to wiki via web */ |
| 78 | 70 | char WrWiki; /* k: edit wiki via web */ |
| @@ -83,11 +75,10 @@ | ||
| 83 | 75 | char Attach; /* b: add attachments */ |
| 84 | 76 | char TktFmt; /* t: create new ticket report formats */ |
| 85 | 77 | char RdAddr; /* e: read email addresses or other private data */ |
| 86 | 78 | char Zip; /* z: download zipped artifact via /zip URL */ |
| 87 | 79 | char Private; /* x: can send and receive private content */ |
| 88 | - char Hyperlink; /* "h" or "l" */ | |
| 89 | 80 | }; |
| 90 | 81 | |
| 91 | 82 | #ifdef FOSSIL_ENABLE_TCL |
| 92 | 83 | /* |
| 93 | 84 | ** All Tcl related context information is in this structure. This structure |
| @@ -144,11 +135,12 @@ | ||
| 144 | 135 | int xlinkClusterOnly; /* Set when cloning. Only process clusters */ |
| 145 | 136 | int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */ |
| 146 | 137 | int *aCommitFile; /* Array of files to be committed */ |
| 147 | 138 | int markPrivate; /* All new artifacts are private if true */ |
| 148 | 139 | int clockSkewSeen; /* True if clocks on client and server out of sync */ |
| 149 | - 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 */ | |
| 150 | 142 | |
| 151 | 143 | int urlIsFile; /* True if a "file:" url */ |
| 152 | 144 | int urlIsHttps; /* True if a "https:" url */ |
| 153 | 145 | int urlIsSsh; /* True if an "ssh:" url */ |
| 154 | 146 | char *urlName; /* Hostname for http: or filename for file: */ |
| 155 | 147 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -51,28 +51,20 @@ | |
| 51 | */ |
| 52 | #define MX_AUX 5 |
| 53 | |
| 54 | /* |
| 55 | ** Holds flags for fossil user permissions. |
| 56 | ** |
| 57 | ** History enables various hyperlinks directly, with an href= attribute |
| 58 | ** in the HTML. Link puts an id= attribute in HTML and then adds the |
| 59 | ** href= attribute using javascript. The Link option is designed to make |
| 60 | ** it harder for bots and spiders to follow hyperlinks, and yet give the |
| 61 | ** same experience to users. the Hyperlink permission is a composite which |
| 62 | ** is enabled if either History or Hyperlink is turned on. |
| 63 | */ |
| 64 | struct FossilUserPerms { |
| 65 | char Setup; /* s: use Setup screens on web interface */ |
| 66 | char Admin; /* a: administrative permission */ |
| 67 | char Delete; /* d: delete wiki or tickets */ |
| 68 | char Password; /* p: change password */ |
| 69 | char Query; /* q: create new reports */ |
| 70 | char Write; /* i: xfer inbound. checkin */ |
| 71 | char Read; /* o: xfer outbound. checkout */ |
| 72 | char History; /* h: access historical information. */ |
| 73 | char Link; /* l: enable href= using javascript */ |
| 74 | char Clone; /* g: clone */ |
| 75 | char RdWiki; /* j: view wiki via web */ |
| 76 | char NewWiki; /* f: create new wiki via web */ |
| 77 | char ApndWiki; /* m: append to wiki via web */ |
| 78 | char WrWiki; /* k: edit wiki via web */ |
| @@ -83,11 +75,10 @@ | |
| 83 | char Attach; /* b: add attachments */ |
| 84 | char TktFmt; /* t: create new ticket report formats */ |
| 85 | char RdAddr; /* e: read email addresses or other private data */ |
| 86 | char Zip; /* z: download zipped artifact via /zip URL */ |
| 87 | char Private; /* x: can send and receive private content */ |
| 88 | char Hyperlink; /* "h" or "l" */ |
| 89 | }; |
| 90 | |
| 91 | #ifdef FOSSIL_ENABLE_TCL |
| 92 | /* |
| 93 | ** All Tcl related context information is in this structure. This structure |
| @@ -144,11 +135,12 @@ | |
| 144 | int xlinkClusterOnly; /* Set when cloning. Only process clusters */ |
| 145 | int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */ |
| 146 | int *aCommitFile; /* Array of files to be committed */ |
| 147 | int markPrivate; /* All new artifacts are private if true */ |
| 148 | int clockSkewSeen; /* True if clocks on client and server out of sync */ |
| 149 | int isHTTP; /* True if running in server/CGI modes, else assume CLI. */ |
| 150 | |
| 151 | int urlIsFile; /* True if a "file:" url */ |
| 152 | int urlIsHttps; /* True if a "https:" url */ |
| 153 | int urlIsSsh; /* True if an "ssh:" url */ |
| 154 | char *urlName; /* Hostname for http: or filename for file: */ |
| 155 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -51,28 +51,20 @@ | |
| 51 | */ |
| 52 | #define MX_AUX 5 |
| 53 | |
| 54 | /* |
| 55 | ** Holds flags for fossil user permissions. |
| 56 | */ |
| 57 | struct FossilUserPerms { |
| 58 | char Setup; /* s: use Setup screens on web interface */ |
| 59 | char Admin; /* a: administrative permission */ |
| 60 | char Delete; /* d: delete wiki or tickets */ |
| 61 | 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 */ |
| @@ -83,11 +75,10 @@ | |
| 75 | char Attach; /* b: add attachments */ |
| 76 | char TktFmt; /* t: create new ticket report formats */ |
| 77 | char RdAddr; /* e: read email addresses or other private data */ |
| 78 | char Zip; /* z: download zipped artifact via /zip URL */ |
| 79 | char Private; /* x: can send and receive private content */ |
| 80 | }; |
| 81 | |
| 82 | #ifdef FOSSIL_ENABLE_TCL |
| 83 | /* |
| 84 | ** All Tcl related context information is in this structure. This structure |
| @@ -144,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 |
+3
-3
| --- src/report.c | ||
| +++ src/report.c | ||
| @@ -64,11 +64,11 @@ | ||
| 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 | 68 | blob_appendf(&ril, "[%zcopy</a>] ", |
| 69 | - href("%R/rptedit?rn=%d&copy=1", rn)); | |
| 69 | + href("%R/rptedit?rn=%d©=1", rn)); | |
| 70 | 70 | } |
| 71 | 71 | if( g.perm.Admin |
| 72 | 72 | || (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0) |
| 73 | 73 | ){ |
| 74 | 74 | blob_appendf(&ril, "[%zedit</a>]", |
| @@ -419,11 +419,11 @@ | ||
| 419 | 419 | } |
| 420 | 420 | } |
| 421 | 421 | if( zOwner==0 ) zOwner = g.zLogin; |
| 422 | 422 | style_submenu_element("Cancel", "Cancel", "reportlist"); |
| 423 | 423 | if( rn>0 ){ |
| 424 | - style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn); | |
| 424 | + style_submenu_element("Delete", "Delete", "rptedit?rn=%d&del1=1", rn); | |
| 425 | 425 | } |
| 426 | 426 | style_header(rn>0 ? "Edit Report Format":"Create New Report Format"); |
| 427 | 427 | if( zErr ){ |
| 428 | 428 | @ <blockquote class="reportError">%h(zErr)</blockquote> |
| 429 | 429 | } |
| @@ -948,11 +948,11 @@ | ||
| 948 | 948 | if( !tabs ){ |
| 949 | 949 | struct GenerateHTML sState; |
| 950 | 950 | |
| 951 | 951 | db_multi_exec("PRAGMA empty_result_callbacks=ON"); |
| 952 | 952 | style_submenu_element("Raw", "Raw", |
| 953 | - "rptview?tablist=1&%h", PD("QUERY_STRING","")); | |
| 953 | + "rptview?tablist=1&%h", PD("QUERY_STRING","")); | |
| 954 | 954 | if( g.perm.Admin |
| 955 | 955 | || (g.perm.TktFmt && g.zLogin && fossil_strcmp(g.zLogin,zOwner)==0) ){ |
| 956 | 956 | style_submenu_element("Edit", "Edit", "rptedit?rn=%d", rn); |
| 957 | 957 | } |
| 958 | 958 | if( g.perm.TktFmt ){ |
| 959 | 959 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -64,11 +64,11 @@ | |
| 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&copy=1", rn)); |
| 70 | } |
| 71 | if( g.perm.Admin |
| 72 | || (g.perm.WrTkt && zOwner && fossil_strcmp(g.zLogin,zOwner)==0) |
| 73 | ){ |
| 74 | blob_appendf(&ril, "[%zedit</a>]", |
| @@ -419,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 | } |
| @@ -948,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 |
| --- src/report.c | |
| +++ src/report.c | |
| @@ -64,11 +64,11 @@ | |
| 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>]", |
| @@ -419,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 | } |
| @@ -948,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 |
+19
-20
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -170,13 +170,10 @@ | ||
| 170 | 170 | @ <td><i>Check-In:</i> Commit new versions in the repository</td></tr> |
| 171 | 171 | @ <tr><td valign="top"><b>j</b></td> |
| 172 | 172 | @ <td><i>Read-Wiki:</i> View wiki pages</td></tr> |
| 173 | 173 | @ <tr><td valign="top"><b>k</b></td> |
| 174 | 174 | @ <td><i>Write-Wiki:</i> Edit wiki pages</td></tr> |
| 175 | - @ <tr><td valign="top"><b>l</b></td> | |
| 176 | - @ <td><i>Link-Late:</i> Use javascript for hyperlinks to | |
| 177 | - @ discourage bots</td></tr> | |
| 178 | 175 | @ <tr><td valign="top"><b>m</b></td> |
| 179 | 176 | @ <td><i>Append-Wiki:</i> Append to wiki pages</td></tr> |
| 180 | 177 | @ <tr><td valign="top"><b>n</b></td> |
| 181 | 178 | @ <td><i>New-Tkt:</i> Create new tickets</td></tr> |
| 182 | 179 | @ <tr><td valign="top"><b>o</b></td> |
| @@ -251,11 +248,11 @@ | ||
| 251 | 248 | ** WEBPAGE: /setup_uedit |
| 252 | 249 | */ |
| 253 | 250 | void user_edit(void){ |
| 254 | 251 | const char *zId, *zLogin, *zInfo, *zCap, *zPw; |
| 255 | 252 | char *oaa, *oas, *oar, *oaw, *oan, *oai, *oaj, *oao, *oap; |
| 256 | - char *oak, *oad, *oac, *oaf, *oam, *oah, *oal, *oag, *oae; | |
| 253 | + char *oak, *oad, *oac, *oaf, *oam, *oah, *oag, *oae; | |
| 257 | 254 | char *oat, *oau, *oav, *oab, *oax, *oaz; |
| 258 | 255 | const char *zGroup; |
| 259 | 256 | const char *zOldLogin; |
| 260 | 257 | char *inherit[128]; |
| 261 | 258 | int doWrite; |
| @@ -307,11 +304,10 @@ | ||
| 307 | 304 | int aw = P("aw")!=0; |
| 308 | 305 | int ac = P("ac")!=0; |
| 309 | 306 | int af = P("af")!=0; |
| 310 | 307 | int am = P("am")!=0; |
| 311 | 308 | int ah = P("ah")!=0; |
| 312 | - int al = P("al")!=0; | |
| 313 | 309 | int ag = P("ag")!=0; |
| 314 | 310 | int at = P("at")!=0; |
| 315 | 311 | int au = P("au")!=0; |
| 316 | 312 | int av = P("av")!=0; |
| 317 | 313 | int ax = P("ax")!=0; |
| @@ -325,11 +321,10 @@ | ||
| 325 | 321 | if( ah ){ zCap[i++] = 'h'; } |
| 326 | 322 | if( ag ){ zCap[i++] = 'g'; } |
| 327 | 323 | if( ai ){ zCap[i++] = 'i'; } |
| 328 | 324 | if( aj ){ zCap[i++] = 'j'; } |
| 329 | 325 | if( ak ){ zCap[i++] = 'k'; } |
| 330 | - if( al ){ zCap[i++] = 'l'; } | |
| 331 | 326 | if( am ){ zCap[i++] = 'm'; } |
| 332 | 327 | if( an ){ zCap[i++] = 'n'; } |
| 333 | 328 | if( ao ){ zCap[i++] = 'o'; } |
| 334 | 329 | if( ap ){ zCap[i++] = 'p'; } |
| 335 | 330 | if( ar ){ zCap[i++] = 'r'; } |
| @@ -417,11 +412,11 @@ | ||
| 417 | 412 | */ |
| 418 | 413 | zLogin = ""; |
| 419 | 414 | zInfo = ""; |
| 420 | 415 | zCap = ""; |
| 421 | 416 | zPw = ""; |
| 422 | - oaa = oab = oac = oad = oae = oaf = oag = oah = oai = oaj = oak = oal = oam = | |
| 417 | + oaa = oab = oac = oad = oae = oaf = oag = oah = oai = oaj = oak = oam = | |
| 423 | 418 | oan = oao = oap = oar = oas = oat = oau = oav = oaw = oax = oaz = ""; |
| 424 | 419 | if( uid ){ |
| 425 | 420 | zLogin = db_text("", "SELECT login FROM user WHERE uid=%d", uid); |
| 426 | 421 | zInfo = db_text("", "SELECT info FROM user WHERE uid=%d", uid); |
| 427 | 422 | zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", uid); |
| @@ -435,11 +430,10 @@ | ||
| 435 | 430 | if( strchr(zCap, 'g') ) oag = " checked=\"checked\""; |
| 436 | 431 | if( strchr(zCap, 'h') ) oah = " checked=\"checked\""; |
| 437 | 432 | if( strchr(zCap, 'i') ) oai = " checked=\"checked\""; |
| 438 | 433 | if( strchr(zCap, 'j') ) oaj = " checked=\"checked\""; |
| 439 | 434 | if( strchr(zCap, 'k') ) oak = " checked=\"checked\""; |
| 440 | - if( strchr(zCap, 'l') ) oal = " checked=\"checked\""; | |
| 441 | 435 | if( strchr(zCap, 'm') ) oam = " checked=\"checked\""; |
| 442 | 436 | if( strchr(zCap, 'n') ) oan = " checked=\"checked\""; |
| 443 | 437 | if( strchr(zCap, 'o') ) oao = " checked=\"checked\""; |
| 444 | 438 | if( strchr(zCap, 'p') ) oap = " checked=\"checked\""; |
| 445 | 439 | if( strchr(zCap, 'r') ) oar = " checked=\"checked\""; |
| @@ -531,11 +525,10 @@ | ||
| 531 | 525 | @ <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br /> |
| 532 | 526 | @ <input type="checkbox" name="ap"%s(oap) />%s(B('p'))Password<br /> |
| 533 | 527 | @ <input type="checkbox" name="ai"%s(oai) />%s(B('i'))Check-In<br /> |
| 534 | 528 | @ <input type="checkbox" name="ao"%s(oao) />%s(B('o'))Check-Out<br /> |
| 535 | 529 | @ <input type="checkbox" name="ah"%s(oah) />%s(B('h'))Hyperlinks<br /> |
| 536 | - @ <input type="checkbox" name="al"%s(oal) />%s(B('l'))Links-deferred<br /> | |
| 537 | 530 | @ <input type="checkbox" name="au"%s(oau) />%s(B('u'))Reader<br /> |
| 538 | 531 | @ <input type="checkbox" name="av"%s(oav) />%s(B('v'))Developer<br /> |
| 539 | 532 | @ <input type="checkbox" name="ag"%s(oag) />%s(B('g'))Clone<br /> |
| 540 | 533 | @ <input type="checkbox" name="aj"%s(oaj) />%s(B('j'))Read Wiki<br /> |
| 541 | 534 | @ <input type="checkbox" name="af"%s(oaf) />%s(B('f'))New Wiki<br /> |
| @@ -635,13 +628,11 @@ | ||
| 635 | 628 | @ |
| 636 | 629 | @ <li><p> |
| 637 | 630 | @ The <span class="capability">Hyperlinks</span> privilege allows a user |
| 638 | 631 | @ to see most hyperlinks. This is recommended ON for most logged-in users |
| 639 | 632 | @ but OFF for user "nobody" to avoid problems with spiders trying to walk |
| 640 | - @ every historical version of every baseline and file. The | |
| 641 | - @ <span class="capability">Link-deferred</span> privilege enables hyperlinks | |
| 642 | - @ using javascript, which makes them harder for bots and spiders to find. | |
| 633 | + @ every diff and annotation of every historical check-in and file. | |
| 643 | 634 | @ </p></li> |
| 644 | 635 | @ |
| 645 | 636 | @ <li><p> |
| 646 | 637 | @ The <span class="capability">Zip</span> privilege allows a user to |
| 647 | 638 | @ see the "download as ZIP" |
| @@ -900,19 +891,27 @@ | ||
| 900 | 891 | @ than this, then the client will issue multiple HTTP requests. |
| 901 | 892 | @ Values below 1 million are not recommended. 5 million is a |
| 902 | 893 | @ reasonable number.</p> |
| 903 | 894 | |
| 904 | 895 | @ <hr /> |
| 905 | - onoff_attribute("Enable hyperlinks for \"nobody\" based on User-Agent", | |
| 906 | - "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); | |
| 907 | 899 | @ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users |
| 908 | - @ including user "nobody", as long as the User-Agent string in the HTTP header | |
| 909 | - @ indicates that the request is coming from an actual human being and not a | |
| 910 | - @ a robot or script. Note: Bots can specify whatever User-Agent string they | |
| 911 | - @ that want. So a bot that wants to impersonate a human can easily do so. | |
| 912 | - @ Hence, this technique does not necessarily exclude malicious bots. | |
| 913 | - @ </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> | |
| 914 | 913 | |
| 915 | 914 | @ <hr /> |
| 916 | 915 | entry_attribute("Public pages", 30, "public-pages", |
| 917 | 916 | "pubpage", ""); |
| 918 | 917 | @ <p>A comma-separated list of glob patterns for pages that are accessible |
| 919 | 918 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -170,13 +170,10 @@ | |
| 170 | @ <td><i>Check-In:</i> Commit new versions in the repository</td></tr> |
| 171 | @ <tr><td valign="top"><b>j</b></td> |
| 172 | @ <td><i>Read-Wiki:</i> View wiki pages</td></tr> |
| 173 | @ <tr><td valign="top"><b>k</b></td> |
| 174 | @ <td><i>Write-Wiki:</i> Edit wiki pages</td></tr> |
| 175 | @ <tr><td valign="top"><b>l</b></td> |
| 176 | @ <td><i>Link-Late:</i> Use javascript for hyperlinks to |
| 177 | @ discourage bots</td></tr> |
| 178 | @ <tr><td valign="top"><b>m</b></td> |
| 179 | @ <td><i>Append-Wiki:</i> Append to wiki pages</td></tr> |
| 180 | @ <tr><td valign="top"><b>n</b></td> |
| 181 | @ <td><i>New-Tkt:</i> Create new tickets</td></tr> |
| 182 | @ <tr><td valign="top"><b>o</b></td> |
| @@ -251,11 +248,11 @@ | |
| 251 | ** WEBPAGE: /setup_uedit |
| 252 | */ |
| 253 | void user_edit(void){ |
| 254 | const char *zId, *zLogin, *zInfo, *zCap, *zPw; |
| 255 | char *oaa, *oas, *oar, *oaw, *oan, *oai, *oaj, *oao, *oap; |
| 256 | char *oak, *oad, *oac, *oaf, *oam, *oah, *oal, *oag, *oae; |
| 257 | char *oat, *oau, *oav, *oab, *oax, *oaz; |
| 258 | const char *zGroup; |
| 259 | const char *zOldLogin; |
| 260 | char *inherit[128]; |
| 261 | int doWrite; |
| @@ -307,11 +304,10 @@ | |
| 307 | int aw = P("aw")!=0; |
| 308 | int ac = P("ac")!=0; |
| 309 | int af = P("af")!=0; |
| 310 | int am = P("am")!=0; |
| 311 | int ah = P("ah")!=0; |
| 312 | int al = P("al")!=0; |
| 313 | int ag = P("ag")!=0; |
| 314 | int at = P("at")!=0; |
| 315 | int au = P("au")!=0; |
| 316 | int av = P("av")!=0; |
| 317 | int ax = P("ax")!=0; |
| @@ -325,11 +321,10 @@ | |
| 325 | if( ah ){ zCap[i++] = 'h'; } |
| 326 | if( ag ){ zCap[i++] = 'g'; } |
| 327 | if( ai ){ zCap[i++] = 'i'; } |
| 328 | if( aj ){ zCap[i++] = 'j'; } |
| 329 | if( ak ){ zCap[i++] = 'k'; } |
| 330 | if( al ){ zCap[i++] = 'l'; } |
| 331 | if( am ){ zCap[i++] = 'm'; } |
| 332 | if( an ){ zCap[i++] = 'n'; } |
| 333 | if( ao ){ zCap[i++] = 'o'; } |
| 334 | if( ap ){ zCap[i++] = 'p'; } |
| 335 | if( ar ){ zCap[i++] = 'r'; } |
| @@ -417,11 +412,11 @@ | |
| 417 | */ |
| 418 | zLogin = ""; |
| 419 | zInfo = ""; |
| 420 | zCap = ""; |
| 421 | zPw = ""; |
| 422 | oaa = oab = oac = oad = oae = oaf = oag = oah = oai = oaj = oak = oal = oam = |
| 423 | oan = oao = oap = oar = oas = oat = oau = oav = oaw = oax = oaz = ""; |
| 424 | if( uid ){ |
| 425 | zLogin = db_text("", "SELECT login FROM user WHERE uid=%d", uid); |
| 426 | zInfo = db_text("", "SELECT info FROM user WHERE uid=%d", uid); |
| 427 | zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", uid); |
| @@ -435,11 +430,10 @@ | |
| 435 | if( strchr(zCap, 'g') ) oag = " checked=\"checked\""; |
| 436 | if( strchr(zCap, 'h') ) oah = " checked=\"checked\""; |
| 437 | if( strchr(zCap, 'i') ) oai = " checked=\"checked\""; |
| 438 | if( strchr(zCap, 'j') ) oaj = " checked=\"checked\""; |
| 439 | if( strchr(zCap, 'k') ) oak = " checked=\"checked\""; |
| 440 | if( strchr(zCap, 'l') ) oal = " checked=\"checked\""; |
| 441 | if( strchr(zCap, 'm') ) oam = " checked=\"checked\""; |
| 442 | if( strchr(zCap, 'n') ) oan = " checked=\"checked\""; |
| 443 | if( strchr(zCap, 'o') ) oao = " checked=\"checked\""; |
| 444 | if( strchr(zCap, 'p') ) oap = " checked=\"checked\""; |
| 445 | if( strchr(zCap, 'r') ) oar = " checked=\"checked\""; |
| @@ -531,11 +525,10 @@ | |
| 531 | @ <input type="checkbox" name="ae"%s(oae) />%s(B('e'))Email<br /> |
| 532 | @ <input type="checkbox" name="ap"%s(oap) />%s(B('p'))Password<br /> |
| 533 | @ <input type="checkbox" name="ai"%s(oai) />%s(B('i'))Check-In<br /> |
| 534 | @ <input type="checkbox" name="ao"%s(oao) />%s(B('o'))Check-Out<br /> |
| 535 | @ <input type="checkbox" name="ah"%s(oah) />%s(B('h'))Hyperlinks<br /> |
| 536 | @ <input type="checkbox" name="al"%s(oal) />%s(B('l'))Links-deferred<br /> |
| 537 | @ <input type="checkbox" name="au"%s(oau) />%s(B('u'))Reader<br /> |
| 538 | @ <input type="checkbox" name="av"%s(oav) />%s(B('v'))Developer<br /> |
| 539 | @ <input type="checkbox" name="ag"%s(oag) />%s(B('g'))Clone<br /> |
| 540 | @ <input type="checkbox" name="aj"%s(oaj) />%s(B('j'))Read Wiki<br /> |
| 541 | @ <input type="checkbox" name="af"%s(oaf) />%s(B('f'))New Wiki<br /> |
| @@ -635,13 +628,11 @@ | |
| 635 | @ |
| 636 | @ <li><p> |
| 637 | @ The <span class="capability">Hyperlinks</span> privilege allows a user |
| 638 | @ to see most hyperlinks. This is recommended ON for most logged-in users |
| 639 | @ but OFF for user "nobody" to avoid problems with spiders trying to walk |
| 640 | @ every historical version of every baseline and file. The |
| 641 | @ <span class="capability">Link-deferred</span> privilege enables hyperlinks |
| 642 | @ using javascript, which makes them harder for bots and spiders to find. |
| 643 | @ </p></li> |
| 644 | @ |
| 645 | @ <li><p> |
| 646 | @ The <span class="capability">Zip</span> privilege allows a user to |
| 647 | @ see the "download as ZIP" |
| @@ -900,19 +891,27 @@ | |
| 900 | @ than this, then the client will issue multiple HTTP requests. |
| 901 | @ Values below 1 million are not recommended. 5 million is a |
| 902 | @ reasonable number.</p> |
| 903 | |
| 904 | @ <hr /> |
| 905 | onoff_attribute("Enable hyperlinks for \"nobody\" based on User-Agent", |
| 906 | "auto-enable-hyperlinks", "autohyperlink", 1); |
| 907 | @ <p>Enable hyperlinks (the equivalent of the "h" permission) for all users |
| 908 | @ including user "nobody", as long as the User-Agent string in the HTTP header |
| 909 | @ indicates that the request is coming from an actual human being and not a |
| 910 | @ a robot or script. Note: Bots can specify whatever User-Agent string they |
| 911 | @ that want. So a bot that wants to impersonate a human can easily do so. |
| 912 | @ Hence, this technique does not necessarily exclude malicious bots. |
| 913 | @ </p> |
| 914 | |
| 915 | @ <hr /> |
| 916 | entry_attribute("Public pages", 30, "public-pages", |
| 917 | "pubpage", ""); |
| 918 | @ <p>A comma-separated list of glob patterns for pages that are accessible |
| 919 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -170,13 +170,10 @@ | |
| 170 | @ <td><i>Check-In:</i> Commit new versions in the repository</td></tr> |
| 171 | @ <tr><td valign="top"><b>j</b></td> |
| 172 | @ <td><i>Read-Wiki:</i> View wiki pages</td></tr> |
| 173 | @ <tr><td valign="top"><b>k</b></td> |
| 174 | @ <td><i>Write-Wiki:</i> Edit wiki pages</td></tr> |
| 175 | @ <tr><td valign="top"><b>m</b></td> |
| 176 | @ <td><i>Append-Wiki:</i> Append to wiki pages</td></tr> |
| 177 | @ <tr><td valign="top"><b>n</b></td> |
| 178 | @ <td><i>New-Tkt:</i> Create new tickets</td></tr> |
| 179 | @ <tr><td valign="top"><b>o</b></td> |
| @@ -251,11 +248,11 @@ | |
| 248 | ** WEBPAGE: /setup_uedit |
| 249 | */ |
| 250 | void user_edit(void){ |
| 251 | const char *zId, *zLogin, *zInfo, *zCap, *zPw; |
| 252 | char *oaa, *oas, *oar, *oaw, *oan, *oai, *oaj, *oao, *oap; |
| 253 | char *oak, *oad, *oac, *oaf, *oam, *oah, *oag, *oae; |
| 254 | char *oat, *oau, *oav, *oab, *oax, *oaz; |
| 255 | const char *zGroup; |
| 256 | const char *zOldLogin; |
| 257 | char *inherit[128]; |
| 258 | int doWrite; |
| @@ -307,11 +304,10 @@ | |
| 304 | int aw = P("aw")!=0; |
| 305 | int ac = P("ac")!=0; |
| 306 | int af = P("af")!=0; |
| 307 | int am = P("am")!=0; |
| 308 | int ah = P("ah")!=0; |
| 309 | int ag = P("ag")!=0; |
| 310 | int at = P("at")!=0; |
| 311 | int au = P("au")!=0; |
| 312 | int av = P("av")!=0; |
| 313 | int ax = P("ax")!=0; |
| @@ -325,11 +321,10 @@ | |
| 321 | if( ah ){ zCap[i++] = 'h'; } |
| 322 | if( ag ){ zCap[i++] = 'g'; } |
| 323 | if( ai ){ zCap[i++] = 'i'; } |
| 324 | if( aj ){ zCap[i++] = 'j'; } |
| 325 | if( ak ){ zCap[i++] = 'k'; } |
| 326 | if( am ){ zCap[i++] = 'm'; } |
| 327 | if( an ){ zCap[i++] = 'n'; } |
| 328 | if( ao ){ zCap[i++] = 'o'; } |
| 329 | if( ap ){ zCap[i++] = 'p'; } |
| 330 | if( ar ){ zCap[i++] = 'r'; } |
| @@ -417,11 +412,11 @@ | |
| 412 | */ |
| 413 | zLogin = ""; |
| 414 | zInfo = ""; |
| 415 | zCap = ""; |
| 416 | zPw = ""; |
| 417 | oaa = oab = oac = oad = oae = oaf = oag = oah = oai = oaj = oak = oam = |
| 418 | oan = oao = oap = oar = oas = oat = oau = oav = oaw = oax = oaz = ""; |
| 419 | if( uid ){ |
| 420 | zLogin = db_text("", "SELECT login FROM user WHERE uid=%d", uid); |
| 421 | zInfo = db_text("", "SELECT info FROM user WHERE uid=%d", uid); |
| 422 | zCap = db_text("", "SELECT cap FROM user WHERE uid=%d", uid); |
| @@ -435,11 +430,10 @@ | |
| 430 | if( strchr(zCap, 'g') ) oag = " checked=\"checked\""; |
| 431 | if( strchr(zCap, 'h') ) oah = " checked=\"checked\""; |
| 432 | if( strchr(zCap, 'i') ) oai = " checked=\"checked\""; |
| 433 | if( strchr(zCap, 'j') ) oaj = " checked=\"checked\""; |
| 434 | if( strchr(zCap, 'k') ) oak = " checked=\"checked\""; |
| 435 | if( strchr(zCap, 'm') ) oam = " checked=\"checked\""; |
| 436 | if( strchr(zCap, 'n') ) oan = " checked=\"checked\""; |
| 437 | if( strchr(zCap, 'o') ) oao = " checked=\"checked\""; |
| 438 | if( strchr(zCap, 'p') ) oap = " checked=\"checked\""; |
| 439 | if( strchr(zCap, 'r') ) oar = " checked=\"checked\""; |
| @@ -531,11 +525,10 @@ | |
| 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 /> |
| @@ -635,13 +628,11 @@ | |
| 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" |
| @@ -900,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 |
+13
-12
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -60,39 +60,40 @@ | ||
| 60 | 60 | ** Generate and return a anchor tag like this: |
| 61 | 61 | ** |
| 62 | 62 | ** <a href="URL"> |
| 63 | 63 | ** or <a id="ID"> |
| 64 | 64 | ** |
| 65 | -** The form of the anchor tag is determined by the g.perm.History | |
| 66 | -** variable. The href="URL" form is used if g.perm.History is true. | |
| 67 | -** If g.perm.History is false and g.perm.Link is true then the | |
| 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 | 68 | ** id="ID" form is used and javascript is generated in the footer to cause |
| 69 | -** href values to be inserted after the page has loaded. If both | |
| 70 | -** g.perm.History and g.perm.Link are false, then the <a id="ID"> form is | |
| 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 | 71 | ** generated but the javascript is not generated so the links never |
| 72 | 72 | ** activate. |
| 73 | 73 | ** |
| 74 | -** Handling the href="URL" using javascript is a defense against bots. | |
| 74 | +** Filling in the href="URL" using javascript is a defense against bots. | |
| 75 | 75 | ** |
| 76 | 76 | ** The name of this routine is deliberately kept short so that can be |
| 77 | 77 | ** easily used within @-lines. Example: |
| 78 | 78 | ** |
| 79 | -** @ %z(href("%s/artifact/%s",g.zTop,zUuid))%h(zFN)</a> | |
| 79 | +** @ %z(href("%R/artifact/%s",zUuid))%h(zFN)</a> | |
| 80 | 80 | ** |
| 81 | 81 | ** Note %z format. The string returned by this function is always |
| 82 | -** obtained from fossil_malloc(). | |
| 82 | +** obtained from fossil_malloc() so rendering it with %z will reclaim | |
| 83 | +** that memory space. | |
| 83 | 84 | ** |
| 84 | -** There are two versions of this routine href() does a plain hyperlink | |
| 85 | +** There are two versions of this routine: href() does a plain hyperlink | |
| 85 | 86 | ** and xhref() adds extra attribute text. |
| 86 | 87 | */ |
| 87 | 88 | char *xhref(const char *zExtra, const char *zFormat, ...){ |
| 88 | 89 | char *zUrl; |
| 89 | 90 | va_list ap; |
| 90 | 91 | va_start(ap, zFormat); |
| 91 | 92 | zUrl = vmprintf(zFormat, ap); |
| 92 | 93 | va_end(ap); |
| 93 | - if( g.perm.History ){ | |
| 94 | + if( g.perm.Hyperlink && !g.javascriptHyperlink ){ | |
| 94 | 95 | return mprintf("<a %s href=\"%z\">", zExtra, zUrl); |
| 95 | 96 | } |
| 96 | 97 | if( nHref>=nHrefAlloc ){ |
| 97 | 98 | nHrefAlloc = nHrefAlloc*2 + 10; |
| 98 | 99 | aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0])); |
| @@ -104,11 +105,11 @@ | ||
| 104 | 105 | char *zUrl; |
| 105 | 106 | va_list ap; |
| 106 | 107 | va_start(ap, zFormat); |
| 107 | 108 | zUrl = vmprintf(zFormat, ap); |
| 108 | 109 | va_end(ap); |
| 109 | - if( g.perm.History ){ | |
| 110 | + if( g.perm.Hyperlink && !g.javascriptHyperlink ){ | |
| 110 | 111 | return mprintf("<a href=\"%z\">", zUrl); |
| 111 | 112 | } |
| 112 | 113 | if( nHref>=nHrefAlloc ){ |
| 113 | 114 | nHrefAlloc = nHrefAlloc*2 + 10; |
| 114 | 115 | aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0])); |
| @@ -120,11 +121,11 @@ | ||
| 120 | 121 | /* |
| 121 | 122 | ** Generate javascript that will set the href= attribute on all anchors. |
| 122 | 123 | */ |
| 123 | 124 | void style_resolve_href(void){ |
| 124 | 125 | int i; |
| 125 | - if( !g.perm.Link || nHref==0 ) return; | |
| 126 | + if( !g.perm.Hyperlink || !g.javascriptHyperlink || nHref==0 ) return; | |
| 126 | 127 | @ <script> |
| 127 | 128 | for(i=0; i<nHref; i++){ |
| 128 | 129 | @ document.getElementById(%d(i+1)).href="%s(aHref[i])"; |
| 129 | 130 | } |
| 130 | 131 | @ </script> |
| 131 | 132 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -60,39 +60,40 @@ | |
| 60 | ** Generate and return a anchor tag like this: |
| 61 | ** |
| 62 | ** <a href="URL"> |
| 63 | ** or <a id="ID"> |
| 64 | ** |
| 65 | ** The form of the anchor tag is determined by the g.perm.History |
| 66 | ** variable. The href="URL" form is used if g.perm.History is true. |
| 67 | ** If g.perm.History is false and g.perm.Link is true then the |
| 68 | ** id="ID" form is used and javascript is generated in the footer to cause |
| 69 | ** href values to be inserted after the page has loaded. If both |
| 70 | ** g.perm.History and g.perm.Link are false, then the <a id="ID"> form is |
| 71 | ** generated but the javascript is not generated so the links never |
| 72 | ** activate. |
| 73 | ** |
| 74 | ** Handling the href="URL" using javascript is a defense against bots. |
| 75 | ** |
| 76 | ** The name of this routine is deliberately kept short so that can be |
| 77 | ** easily used within @-lines. Example: |
| 78 | ** |
| 79 | ** @ %z(href("%s/artifact/%s",g.zTop,zUuid))%h(zFN)</a> |
| 80 | ** |
| 81 | ** Note %z format. The string returned by this function is always |
| 82 | ** obtained from fossil_malloc(). |
| 83 | ** |
| 84 | ** There are two versions of this routine href() does a plain hyperlink |
| 85 | ** and xhref() adds extra attribute text. |
| 86 | */ |
| 87 | char *xhref(const char *zExtra, const char *zFormat, ...){ |
| 88 | char *zUrl; |
| 89 | va_list ap; |
| 90 | va_start(ap, zFormat); |
| 91 | zUrl = vmprintf(zFormat, ap); |
| 92 | va_end(ap); |
| 93 | if( g.perm.History ){ |
| 94 | return mprintf("<a %s href=\"%z\">", zExtra, zUrl); |
| 95 | } |
| 96 | if( nHref>=nHrefAlloc ){ |
| 97 | nHrefAlloc = nHrefAlloc*2 + 10; |
| 98 | aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0])); |
| @@ -104,11 +105,11 @@ | |
| 104 | char *zUrl; |
| 105 | va_list ap; |
| 106 | va_start(ap, zFormat); |
| 107 | zUrl = vmprintf(zFormat, ap); |
| 108 | va_end(ap); |
| 109 | if( g.perm.History ){ |
| 110 | return mprintf("<a href=\"%z\">", zUrl); |
| 111 | } |
| 112 | if( nHref>=nHrefAlloc ){ |
| 113 | nHrefAlloc = nHrefAlloc*2 + 10; |
| 114 | aHref = fossil_realloc(aHref, nHrefAlloc*sizeof(aHref[0])); |
| @@ -120,11 +121,11 @@ | |
| 120 | /* |
| 121 | ** Generate javascript that will set the href= attribute on all anchors. |
| 122 | */ |
| 123 | void style_resolve_href(void){ |
| 124 | int i; |
| 125 | if( !g.perm.Link || nHref==0 ) return; |
| 126 | @ <script> |
| 127 | for(i=0; i<nHref; i++){ |
| 128 | @ document.getElementById(%d(i+1)).href="%s(aHref[i])"; |
| 129 | } |
| 130 | @ </script> |
| 131 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -60,39 +60,40 @@ | |
| 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])); |
| @@ -104,11 +105,11 @@ | |
| 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])); |
| @@ -120,11 +121,11 @@ | |
| 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 |
+3
-3
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -62,11 +62,11 @@ | ||
| 62 | 62 | void hyperlink_to_diff(const char *zV1, const char *zV2){ |
| 63 | 63 | if( g.perm.Hyperlink ){ |
| 64 | 64 | if( zV2==0 ){ |
| 65 | 65 | @ %z(href("%R/diff?v2=%s",zV1))[diff]</a> |
| 66 | 66 | }else{ |
| 67 | - @ %z(href("%R/diff?v1=%s&v2=%s",zV1,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 | /* |
| @@ -88,11 +88,11 @@ | ||
| 88 | 88 | */ |
| 89 | 89 | void hyperlink_to_user(const char *zU, const char *zD, const char *zSuf){ |
| 90 | 90 | if( zSuf==0 ) zSuf = ""; |
| 91 | 91 | if( g.perm.Hyperlink ){ |
| 92 | 92 | if( zD && zD[0] ){ |
| 93 | - @ %z(href("%R/timeline?c=%T&u=%T",zD,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 | 95 | @ %z(href("%R/timeline?u=%T",zU))%h(zU)</a>%s(zSuf) |
| 96 | 96 | } |
| 97 | 97 | }else{ |
| 98 | 98 | @ %s(zU) |
| @@ -1616,10 +1616,10 @@ | ||
| 1616 | 1616 | " AND blob.rid=c.cid" |
| 1617 | 1617 | ); |
| 1618 | 1618 | while( db_step(&q)==SQLITE_ROW ){ |
| 1619 | 1619 | const char *zUuid = db_column_text(&q, 0); |
| 1620 | 1620 | @ <li> |
| 1621 | - @ <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> | |
| 1622 | 1622 | } |
| 1623 | 1623 | db_finalize(&q); |
| 1624 | 1624 | style_footer(); |
| 1625 | 1625 | } |
| 1626 | 1626 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -62,11 +62,11 @@ | |
| 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 | /* |
| @@ -88,11 +88,11 @@ | |
| 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) |
| @@ -1616,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 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -62,11 +62,11 @@ | |
| 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 | /* |
| @@ -88,11 +88,11 @@ | |
| 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) |
| @@ -1616,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 |
+6
-6
| --- src/tkt.c | ||
| +++ src/tkt.c | ||
| @@ -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(); |
| @@ -354,19 +354,19 @@ | ||
| 354 | 354 | @ <ul> |
| 355 | 355 | } |
| 356 | 356 | cnt++; |
| 357 | 357 | @ <li> |
| 358 | 358 | if( g.perm.Read && g.perm.Hyperlink ){ |
| 359 | - @ %z(href("%R/attachview?tkt=%s&file=%t",zFullName,zFile)) | |
| 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 | - @ [%z(href("%R/attachdelete?tkt=%s&file=%t&from=%R/tktview%%3fname=%s",zFullName,zFile,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; |
| @@ -667,11 +667,11 @@ | ||
| 667 | 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", |
| @@ -742,11 +742,11 @@ | ||
| 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 | |
| 753 | 753 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -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(); |
| @@ -354,19 +354,19 @@ | |
| 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; |
| @@ -667,11 +667,11 @@ | |
| 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", |
| @@ -742,11 +742,11 @@ | |
| 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 | |
| 753 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -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(); |
| @@ -354,19 +354,19 @@ | |
| 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; |
| @@ -667,11 +667,11 @@ | |
| 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", |
| @@ -742,11 +742,11 @@ | |
| 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 | |
| 753 |
+4
-4
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -190,11 +190,11 @@ | ||
| 190 | 190 | style_submenu_element("Edit", "Edit Wiki Page", "%s/wikiedit?name=%T", |
| 191 | 191 | g.zTop, zPageName); |
| 192 | 192 | } |
| 193 | 193 | if( rid && g.perm.ApndWiki && g.perm.Attach ){ |
| 194 | 194 | style_submenu_element("Attach", "Add An Attachment", |
| 195 | - "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T", | |
| 195 | + "%s/attachadd?page=%T&from=%s/wiki%%3fname=%T", | |
| 196 | 196 | g.zTop, zPageName, g.zTop, zPageName); |
| 197 | 197 | } |
| 198 | 198 | if( rid && g.perm.ApndWiki ){ |
| 199 | 199 | style_submenu_element("Append", "Add A Comment", "%s/wikiappend?name=%T", |
| 200 | 200 | g.zTop, zPageName); |
| @@ -224,19 +224,19 @@ | ||
| 224 | 224 | @ <ul> |
| 225 | 225 | } |
| 226 | 226 | cnt++; |
| 227 | 227 | @ <li> |
| 228 | 228 | if( g.perm.Hyperlink && g.perm.Read ){ |
| 229 | - @ %z(href("%R/attachview?page=%T&file=%t",zPageName,zFile)) | |
| 229 | + @ %z(href("%R/attachview?page=%T&file=%t",zPageName,zFile)) | |
| 230 | 230 | @ %h(zFile)</a> |
| 231 | 231 | }else{ |
| 232 | 232 | @ %h(zFile) |
| 233 | 233 | } |
| 234 | 234 | @ added by %h(zUser) on |
| 235 | 235 | hyperlink_to_date(zDate, "."); |
| 236 | 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>] | |
| 237 | + @ [%z(href("%R/attachdelete?page=%t&file=%t&from=%R/wiki%%3fname=%f",zPageName,zFile,zPageName))delete</a>] | |
| 238 | 238 | } |
| 239 | 239 | @ </li> |
| 240 | 240 | } |
| 241 | 241 | if( cnt ){ |
| 242 | 242 | @ </ul> |
| @@ -542,11 +542,11 @@ | ||
| 542 | 542 | ** Function called to output extra text at the end of each line in |
| 543 | 543 | ** a wiki history listing. |
| 544 | 544 | */ |
| 545 | 545 | static void wiki_history_extra(int rid){ |
| 546 | 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> | |
| 547 | + @ %z(href("%R/wdiff?name=%t&a=%d",zWikiPageName,rid))[diff]</a> | |
| 548 | 548 | } |
| 549 | 549 | } |
| 550 | 550 | |
| 551 | 551 | /* |
| 552 | 552 | ** WEBPAGE: whistory |
| 553 | 553 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -190,11 +190,11 @@ | |
| 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); |
| @@ -224,19 +224,19 @@ | |
| 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> |
| @@ -542,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 |
| 553 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -190,11 +190,11 @@ | |
| 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); |
| @@ -224,19 +224,19 @@ | |
| 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> |
| @@ -542,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 |
| 553 |
+1
-5
| --- src/wikiformat.c | ||
| +++ src/wikiformat.c | ||
| @@ -1043,15 +1043,11 @@ | ||
| 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 | 1050 | if( 1 ){ |
| 1055 | 1051 | blob_appendf(p->pOut, "<a href=\"%h\">", zTarget); |
| 1056 | 1052 | }else{ |
| 1057 | 1053 | zTerm = ""; |
| 1058 | 1054 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -1043,15 +1043,11 @@ | |
| 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 ){ |
| 1055 | blob_appendf(p->pOut, "<a href=\"%h\">", zTarget); |
| 1056 | }else{ |
| 1057 | zTerm = ""; |
| 1058 |
| --- src/wikiformat.c | |
| +++ src/wikiformat.c | |
| @@ -1043,15 +1043,11 @@ | |
| 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 |