Fossil SCM
Add the website_assert() macro. Fixes to forum post editing.
Commit
e67efdd784156e6af05dee43e873e0f208f7580aacfc13a3fd9981925a664bd4
Parent
b48068ded310828…
2 files changed
+102
-63
+42
-37
+102
-63
| --- src/forum.c | ||
| +++ src/forum.c | ||
| @@ -22,16 +22,25 @@ | ||
| 22 | 22 | #include "forum.h" |
| 23 | 23 | |
| 24 | 24 | /* |
| 25 | 25 | ** Render a forum post for display |
| 26 | 26 | */ |
| 27 | -void forum_render(const char *zMimetype, const char *zContent){ | |
| 27 | +void forum_render( | |
| 28 | + const char *zTitle, | |
| 29 | + const char *zMimetype, | |
| 30 | + const char *zContent | |
| 31 | +){ | |
| 28 | 32 | Blob x; |
| 33 | + @ <div style='border: 1px solid black;padding: 1ex;'> | |
| 34 | + if( zTitle ){ | |
| 35 | + @ <h1>%h(zTitle)</h1> | |
| 36 | + } | |
| 29 | 37 | blob_init(&x, 0, 0); |
| 30 | 38 | blob_append(&x, zContent, -1); |
| 31 | 39 | wiki_render_by_mimetype(&x, zMimetype); |
| 32 | 40 | blob_reset(&x); |
| 41 | + @ </div> | |
| 33 | 42 | } |
| 34 | 43 | |
| 35 | 44 | /* |
| 36 | 45 | ** Display all posts in a forum thread in chronological order |
| 37 | 46 | */ |
| @@ -65,13 +74,13 @@ | ||
| 65 | 74 | if( firt ){ |
| 66 | 75 | @ reply to %d(firt) |
| 67 | 76 | } |
| 68 | 77 | if( g.perm.Debug ){ |
| 69 | 78 | @ <span class="debug">\ |
| 70 | - @ <a href="%R/artifact/%h(zUuid)">raw artifact</a></span> | |
| 79 | + @ <a href="%R/artifact/%h(zUuid)">artifact</a></span> | |
| 71 | 80 | } |
| 72 | - forum_render(pPost->zMimetype, pPost->zWiki); | |
| 81 | + forum_render(0, pPost->zMimetype, pPost->zWiki); | |
| 73 | 82 | if( g.perm.WrForum ){ |
| 74 | 83 | int sameUser = login_is_individual() |
| 75 | 84 | && fossil_strcmp(pPost->zUser, g.zLogin)==0; |
| 76 | 85 | int isPrivate = content_is_private(fpid); |
| 77 | 86 | @ <p><form action="%R/forumedit" method="POST"> |
| @@ -161,39 +170,51 @@ | ||
| 161 | 170 | int iEdit, /* Post being edited, or zero for a new post */ |
| 162 | 171 | const char *zUser, /* Username. NULL means use login name */ |
| 163 | 172 | const char *zMimetype, /* Mimetype of content. */ |
| 164 | 173 | const char *zContent /* Content */ |
| 165 | 174 | ){ |
| 166 | - Blob x, cksum; | |
| 167 | 175 | char *zDate; |
| 176 | + char *zI; | |
| 177 | + char *zG; | |
| 178 | + int iBasis; | |
| 179 | + Blob x, cksum, formatCheck, errMsg; | |
| 180 | + Manifest *pPost; | |
| 181 | + | |
| 168 | 182 | schema_forum(); |
| 183 | + if( iInReplyTo==0 && iEdit>0 ){ | |
| 184 | + iBasis = iEdit; | |
| 185 | + iInReplyTo = db_int(0, "SELECT firt FROM forumpost WHERE fpid=%d", iEdit); | |
| 186 | + }else{ | |
| 187 | + iBasis = iInReplyTo; | |
| 188 | + } | |
| 189 | + webpage_assert( (zTitle==0)+(iInReplyTo==0)==1 ); | |
| 169 | 190 | blob_init(&x, 0, 0); |
| 170 | 191 | zDate = date_in_standard_format("now"); |
| 171 | 192 | blob_appendf(&x, "D %s\n", zDate); |
| 172 | 193 | fossil_free(zDate); |
| 173 | - if( zTitle ){ | |
| 174 | - blob_appendf(&x, "H %F\n", zTitle); | |
| 175 | - }else{ | |
| 176 | - char *zG = db_text(0, | |
| 177 | - "SELECT uuid FROM blob, forumpost" | |
| 178 | - " WHERE blob.rid==forumpost.froot" | |
| 179 | - " AND forumpost.fpid=%d", iInReplyTo); | |
| 180 | - char *zI; | |
| 181 | - if( zG==0 ) goto forum_post_error; | |
| 194 | + zG = db_text(0, | |
| 195 | + "SELECT uuid FROM blob, forumpost" | |
| 196 | + " WHERE blob.rid==forumpost.froot" | |
| 197 | + " AND forumpost.fpid=%d", iBasis); | |
| 198 | + if( zG ){ | |
| 182 | 199 | blob_appendf(&x, "G %s\n", zG); |
| 183 | 200 | fossil_free(zG); |
| 184 | - zI = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", iInReplyTo); | |
| 185 | - if( zI==0 ) goto forum_post_error; | |
| 201 | + } | |
| 202 | + if( zTitle ){ | |
| 203 | + blob_appendf(&x, "H %F\n", zTitle); | |
| 204 | + } | |
| 205 | + zI = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", iInReplyTo); | |
| 206 | + if( zI ){ | |
| 186 | 207 | blob_appendf(&x, "I %s\n", zI); |
| 187 | 208 | fossil_free(zI); |
| 188 | 209 | } |
| 189 | 210 | if( fossil_strcmp(zMimetype,"text/x-fossil-wiki")!=0 ){ |
| 190 | 211 | blob_appendf(&x, "N %s\n", zMimetype); |
| 191 | 212 | } |
| 192 | 213 | if( iEdit>0 ){ |
| 193 | 214 | char *zP = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", iEdit); |
| 194 | - if( zP==0 ) goto forum_post_error; | |
| 215 | + if( zP==0 ) webpage_error("missing edit artifact %d", iEdit); | |
| 195 | 216 | blob_appendf(&x, "P %s\n", zP); |
| 196 | 217 | fossil_free(zP); |
| 197 | 218 | } |
| 198 | 219 | if( zUser==0 ){ |
| 199 | 220 | if( login_is_nobody() ){ |
| @@ -205,24 +226,36 @@ | ||
| 205 | 226 | blob_appendf(&x, "U %F\n", zUser); |
| 206 | 227 | blob_appendf(&x, "W %d\n%s\n", strlen(zContent), zContent); |
| 207 | 228 | md5sum_blob(&x, &cksum); |
| 208 | 229 | blob_appendf(&x, "Z %b\n", &cksum); |
| 209 | 230 | blob_reset(&cksum); |
| 231 | + | |
| 232 | + /* Verify that the artifact we are creating is well-formed */ | |
| 233 | + blob_init(&formatCheck, 0, 0); | |
| 234 | + blob_init(&errMsg, 0, 0); | |
| 235 | + blob_copy(&formatCheck, &x); | |
| 236 | + pPost = manifest_parse(&formatCheck, 0, &errMsg); | |
| 237 | + if( pPost==0 ){ | |
| 238 | + webpage_error("malformed forum post artifact - %s", blob_str(&errMsg)); | |
| 239 | + } | |
| 240 | + if( pPost->type!=CFTYPE_FORUM ){ | |
| 241 | + webpage_error("forum post artifact malformed"); | |
| 242 | + } | |
| 243 | + manifest_destroy(pPost); | |
| 244 | + | |
| 210 | 245 | if( P("dryrun") ){ |
| 211 | 246 | @ <div class='debug'> |
| 212 | 247 | @ This is the artifact that would have been generated: |
| 213 | 248 | @ <pre>%h(blob_str(&x))</pre> |
| 214 | 249 | @ </div> |
| 250 | + blob_reset(&x); | |
| 251 | + return 0; | |
| 215 | 252 | }else{ |
| 216 | 253 | int nrid = wiki_put(&x, 0, forum_need_moderation()); |
| 217 | 254 | cgi_redirectf("%R/forumthread/%S", rid_to_uuid(nrid)); |
| 218 | 255 | return 1; |
| 219 | 256 | } |
| 220 | - | |
| 221 | -forum_post_error: | |
| 222 | - blob_reset(&x); | |
| 223 | - return 0; | |
| 224 | 257 | } |
| 225 | 258 | |
| 226 | 259 | /* |
| 227 | 260 | ** Paint the form elements for entering a Forum post |
| 228 | 261 | */ |
| @@ -256,13 +289,12 @@ | ||
| 256 | 289 | } |
| 257 | 290 | if( P("submit") ){ |
| 258 | 291 | if( forum_post(zTitle, 0, 0, 0, zMimetype, zContent) ) return; |
| 259 | 292 | } |
| 260 | 293 | if( P("preview") ){ |
| 261 | - @ <h1>%h(zTitle)</h1> | |
| 262 | - forum_render(zMimetype, zContent); | |
| 263 | - @ <hr> | |
| 294 | + @ <h1>Preview:</h1> | |
| 295 | + forum_render(zTitle, zMimetype, zContent); | |
| 264 | 296 | } |
| 265 | 297 | style_header("New Forum Thread"); |
| 266 | 298 | @ <form action="%R/%s(g.zPath)" method="POST"> |
| 267 | 299 | forum_entry_widget(zTitle, zMimetype, zContent); |
| 268 | 300 | @ <input type="submit" name="preview" value="Preview"> |
| @@ -284,24 +316,10 @@ | ||
| 284 | 316 | } |
| 285 | 317 | @ </form> |
| 286 | 318 | style_footer(); |
| 287 | 319 | } |
| 288 | 320 | |
| 289 | -/* | |
| 290 | -** WEBPAGE: forumreply | |
| 291 | -** | |
| 292 | -** Reply to a forum message. | |
| 293 | -** Query parameters: | |
| 294 | -** | |
| 295 | -** name=X Hash of the post to reply to. REQUIRED | |
| 296 | -*/ | |
| 297 | -void forumreply_page(void){ | |
| 298 | - style_header("Pending"); | |
| 299 | - @ TBD... | |
| 300 | - style_footer(); | |
| 301 | -} | |
| 302 | - | |
| 303 | 321 | /* |
| 304 | 322 | ** WEBPAGE: forumedit |
| 305 | 323 | ** |
| 306 | 324 | ** Edit an existing forum message. |
| 307 | 325 | ** Query parameters: |
| @@ -309,20 +327,22 @@ | ||
| 309 | 327 | ** name=X Hash of the post to be editted. REQUIRED |
| 310 | 328 | */ |
| 311 | 329 | void forumedit_page(void){ |
| 312 | 330 | int fpid; |
| 313 | 331 | Manifest *pPost; |
| 332 | + const char *zMimetype = 0; | |
| 333 | + const char *zContent = 0; | |
| 334 | + const char *zTitle = 0; | |
| 314 | 335 | |
| 315 | 336 | login_check_credentials(); |
| 316 | 337 | if( !g.perm.WrForum ){ |
| 317 | 338 | login_needed(g.anon.WrForum); |
| 318 | 339 | return; |
| 319 | 340 | } |
| 320 | 341 | fpid = symbolic_name_to_rid(PD("fpid",""), "f"); |
| 321 | 342 | if( fpid<=0 || (pPost = manifest_get(fpid, CFTYPE_FORUM, 0))==0 ){ |
| 322 | 343 | webpage_error("Missing or invalid fpid query parameter"); |
| 323 | - return; | |
| 324 | 344 | } |
| 325 | 345 | if( g.perm.ModForum ){ |
| 326 | 346 | if( P("approve") ){ |
| 327 | 347 | webpage_not_yet_implemented(); |
| 328 | 348 | return; |
| @@ -337,49 +357,68 @@ | ||
| 337 | 357 | const char *zMimetype = PD("mimetype","text/x-fossil-wiki"); |
| 338 | 358 | const char *zContent = PDT("content",""); |
| 339 | 359 | if( P("reply") ){ |
| 340 | 360 | done = forum_post(0, fpid, 0, 0, zMimetype, zContent); |
| 341 | 361 | }else if( P("edit") ){ |
| 342 | - done = forum_post(0, 0, fpid, 0, zMimetype, zContent); | |
| 362 | + done = forum_post(P("title"), 0, fpid, 0, zMimetype, zContent); | |
| 343 | 363 | }else{ |
| 344 | - webpage_error("Need one of 'edit' or 'reply' query parameters"); | |
| 364 | + webpage_error("Missing 'reply' query parameter"); | |
| 345 | 365 | } |
| 346 | 366 | if( done ) return; |
| 347 | 367 | } |
| 348 | 368 | if( P("edit") ){ |
| 349 | 369 | /* Provide an edit to the fpid post */ |
| 350 | - webpage_not_yet_implemented(); | |
| 351 | - return; | |
| 370 | + zMimetype = P("mimetype"); | |
| 371 | + zContent = PT("content"); | |
| 372 | + zTitle = P("title"); | |
| 373 | + if( zContent==0 ) zContent = fossil_strdup(pPost->zWiki); | |
| 374 | + if( zMimetype==0 ) zMimetype = fossil_strdup(pPost->zMimetype); | |
| 375 | + if( zTitle==0 && pPost->zThreadTitle!=0 ){ | |
| 376 | + zTitle = fossil_strdup(pPost->zThreadTitle); | |
| 377 | + } | |
| 378 | + style_header("Forum Edit"); | |
| 379 | + @ <h1>Original Post:</h1> | |
| 380 | + forum_render(pPost->zThreadTitle, pPost->zMimetype, pPost->zWiki); | |
| 381 | + if( P("preview") ){ | |
| 382 | + @ <h1>Preview Of Editted Post:</h1> | |
| 383 | + forum_render(zTitle, zMimetype, zContent); | |
| 384 | + } | |
| 385 | + @ <h1> | |
| 386 | + @ <h1>Enter A Reply:</h1> | |
| 387 | + @ <form action="%R/forumedit" method="POST"> | |
| 388 | + @ <input type="hidden" name="fpid" value="%h(P("fpid"))"> | |
| 389 | + @ <input type="hidden" name="edit" value="1"> | |
| 390 | + forum_entry_widget(zTitle, zMimetype, zContent); | |
| 352 | 391 | }else{ |
| 353 | - const char *zMimetype = PD("mimetype","text/x-fossil-wiki"); | |
| 354 | - const char *zContent = PDT("content",""); | |
| 392 | + zMimetype = PD("mimetype","text/x-fossil-wiki"); | |
| 393 | + zContent = PDT("content",""); | |
| 355 | 394 | style_header("Forum Reply"); |
| 356 | 395 | @ <h1>Replying To:</h1> |
| 357 | - forum_render(pPost->zMimetype, pPost->zWiki); | |
| 396 | + forum_render(0, pPost->zMimetype, pPost->zWiki); | |
| 358 | 397 | if( P("preview") ){ |
| 359 | 398 | @ <h1>Preview:</h1> |
| 360 | - forum_render(zMimetype,zContent); | |
| 399 | + forum_render(0, zMimetype,zContent); | |
| 361 | 400 | } |
| 362 | 401 | @ <h1>Enter A Reply:</h1> |
| 363 | 402 | @ <form action="%R/forumedit" method="POST"> |
| 364 | 403 | @ <input type="hidden" name="fpid" value="%h(P("fpid"))"> |
| 365 | 404 | @ <input type="hidden" name="reply" value="1"> |
| 366 | 405 | forum_entry_widget(0, zMimetype, zContent); |
| 367 | - @ <input type="submit" name="preview" value="Preview"> | |
| 368 | - if( P("preview") ){ | |
| 369 | - @ <input type="submit" name="submit" value="Submit"> | |
| 370 | - } | |
| 371 | - if( g.perm.Debug ){ | |
| 372 | - /* For the test-forumnew page add these extra debugging controls */ | |
| 373 | - @ <div class="debug"> | |
| 374 | - @ <label><input type="checkbox" name="dryrun" %s(PCK("dryrun"))> \ | |
| 375 | - @ Dry run</label> | |
| 376 | - @ <br><label><input type="checkbox" name="domod" %s(PCK("domod"))> \ | |
| 377 | - @ Require moderator approval</label> | |
| 378 | - @ <br><label><input type="checkbox" name="showqp" %s(PCK("showqp"))> \ | |
| 379 | - @ Show query parameters</label> | |
| 380 | - @ </div> | |
| 381 | - } | |
| 382 | - @ </form> | |
| 383 | - } | |
| 406 | + } | |
| 407 | + @ <input type="submit" name="preview" value="Preview"> | |
| 408 | + if( P("preview") ){ | |
| 409 | + @ <input type="submit" name="submit" value="Submit"> | |
| 410 | + } | |
| 411 | + if( g.perm.Debug ){ | |
| 412 | + /* For the test-forumnew page add these extra debugging controls */ | |
| 413 | + @ <div class="debug"> | |
| 414 | + @ <label><input type="checkbox" name="dryrun" %s(PCK("dryrun"))> \ | |
| 415 | + @ Dry run</label> | |
| 416 | + @ <br><label><input type="checkbox" name="domod" %s(PCK("domod"))> \ | |
| 417 | + @ Require moderator approval</label> | |
| 418 | + @ <br><label><input type="checkbox" name="showqp" %s(PCK("showqp"))> \ | |
| 419 | + @ Show query parameters</label> | |
| 420 | + @ </div> | |
| 421 | + } | |
| 422 | + @ </form> | |
| 384 | 423 | style_footer(); |
| 385 | 424 | } |
| 386 | 425 |
| --- src/forum.c | |
| +++ src/forum.c | |
| @@ -22,16 +22,25 @@ | |
| 22 | #include "forum.h" |
| 23 | |
| 24 | /* |
| 25 | ** Render a forum post for display |
| 26 | */ |
| 27 | void forum_render(const char *zMimetype, const char *zContent){ |
| 28 | Blob x; |
| 29 | blob_init(&x, 0, 0); |
| 30 | blob_append(&x, zContent, -1); |
| 31 | wiki_render_by_mimetype(&x, zMimetype); |
| 32 | blob_reset(&x); |
| 33 | } |
| 34 | |
| 35 | /* |
| 36 | ** Display all posts in a forum thread in chronological order |
| 37 | */ |
| @@ -65,13 +74,13 @@ | |
| 65 | if( firt ){ |
| 66 | @ reply to %d(firt) |
| 67 | } |
| 68 | if( g.perm.Debug ){ |
| 69 | @ <span class="debug">\ |
| 70 | @ <a href="%R/artifact/%h(zUuid)">raw artifact</a></span> |
| 71 | } |
| 72 | forum_render(pPost->zMimetype, pPost->zWiki); |
| 73 | if( g.perm.WrForum ){ |
| 74 | int sameUser = login_is_individual() |
| 75 | && fossil_strcmp(pPost->zUser, g.zLogin)==0; |
| 76 | int isPrivate = content_is_private(fpid); |
| 77 | @ <p><form action="%R/forumedit" method="POST"> |
| @@ -161,39 +170,51 @@ | |
| 161 | int iEdit, /* Post being edited, or zero for a new post */ |
| 162 | const char *zUser, /* Username. NULL means use login name */ |
| 163 | const char *zMimetype, /* Mimetype of content. */ |
| 164 | const char *zContent /* Content */ |
| 165 | ){ |
| 166 | Blob x, cksum; |
| 167 | char *zDate; |
| 168 | schema_forum(); |
| 169 | blob_init(&x, 0, 0); |
| 170 | zDate = date_in_standard_format("now"); |
| 171 | blob_appendf(&x, "D %s\n", zDate); |
| 172 | fossil_free(zDate); |
| 173 | if( zTitle ){ |
| 174 | blob_appendf(&x, "H %F\n", zTitle); |
| 175 | }else{ |
| 176 | char *zG = db_text(0, |
| 177 | "SELECT uuid FROM blob, forumpost" |
| 178 | " WHERE blob.rid==forumpost.froot" |
| 179 | " AND forumpost.fpid=%d", iInReplyTo); |
| 180 | char *zI; |
| 181 | if( zG==0 ) goto forum_post_error; |
| 182 | blob_appendf(&x, "G %s\n", zG); |
| 183 | fossil_free(zG); |
| 184 | zI = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", iInReplyTo); |
| 185 | if( zI==0 ) goto forum_post_error; |
| 186 | blob_appendf(&x, "I %s\n", zI); |
| 187 | fossil_free(zI); |
| 188 | } |
| 189 | if( fossil_strcmp(zMimetype,"text/x-fossil-wiki")!=0 ){ |
| 190 | blob_appendf(&x, "N %s\n", zMimetype); |
| 191 | } |
| 192 | if( iEdit>0 ){ |
| 193 | char *zP = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", iEdit); |
| 194 | if( zP==0 ) goto forum_post_error; |
| 195 | blob_appendf(&x, "P %s\n", zP); |
| 196 | fossil_free(zP); |
| 197 | } |
| 198 | if( zUser==0 ){ |
| 199 | if( login_is_nobody() ){ |
| @@ -205,24 +226,36 @@ | |
| 205 | blob_appendf(&x, "U %F\n", zUser); |
| 206 | blob_appendf(&x, "W %d\n%s\n", strlen(zContent), zContent); |
| 207 | md5sum_blob(&x, &cksum); |
| 208 | blob_appendf(&x, "Z %b\n", &cksum); |
| 209 | blob_reset(&cksum); |
| 210 | if( P("dryrun") ){ |
| 211 | @ <div class='debug'> |
| 212 | @ This is the artifact that would have been generated: |
| 213 | @ <pre>%h(blob_str(&x))</pre> |
| 214 | @ </div> |
| 215 | }else{ |
| 216 | int nrid = wiki_put(&x, 0, forum_need_moderation()); |
| 217 | cgi_redirectf("%R/forumthread/%S", rid_to_uuid(nrid)); |
| 218 | return 1; |
| 219 | } |
| 220 | |
| 221 | forum_post_error: |
| 222 | blob_reset(&x); |
| 223 | return 0; |
| 224 | } |
| 225 | |
| 226 | /* |
| 227 | ** Paint the form elements for entering a Forum post |
| 228 | */ |
| @@ -256,13 +289,12 @@ | |
| 256 | } |
| 257 | if( P("submit") ){ |
| 258 | if( forum_post(zTitle, 0, 0, 0, zMimetype, zContent) ) return; |
| 259 | } |
| 260 | if( P("preview") ){ |
| 261 | @ <h1>%h(zTitle)</h1> |
| 262 | forum_render(zMimetype, zContent); |
| 263 | @ <hr> |
| 264 | } |
| 265 | style_header("New Forum Thread"); |
| 266 | @ <form action="%R/%s(g.zPath)" method="POST"> |
| 267 | forum_entry_widget(zTitle, zMimetype, zContent); |
| 268 | @ <input type="submit" name="preview" value="Preview"> |
| @@ -284,24 +316,10 @@ | |
| 284 | } |
| 285 | @ </form> |
| 286 | style_footer(); |
| 287 | } |
| 288 | |
| 289 | /* |
| 290 | ** WEBPAGE: forumreply |
| 291 | ** |
| 292 | ** Reply to a forum message. |
| 293 | ** Query parameters: |
| 294 | ** |
| 295 | ** name=X Hash of the post to reply to. REQUIRED |
| 296 | */ |
| 297 | void forumreply_page(void){ |
| 298 | style_header("Pending"); |
| 299 | @ TBD... |
| 300 | style_footer(); |
| 301 | } |
| 302 | |
| 303 | /* |
| 304 | ** WEBPAGE: forumedit |
| 305 | ** |
| 306 | ** Edit an existing forum message. |
| 307 | ** Query parameters: |
| @@ -309,20 +327,22 @@ | |
| 309 | ** name=X Hash of the post to be editted. REQUIRED |
| 310 | */ |
| 311 | void forumedit_page(void){ |
| 312 | int fpid; |
| 313 | Manifest *pPost; |
| 314 | |
| 315 | login_check_credentials(); |
| 316 | if( !g.perm.WrForum ){ |
| 317 | login_needed(g.anon.WrForum); |
| 318 | return; |
| 319 | } |
| 320 | fpid = symbolic_name_to_rid(PD("fpid",""), "f"); |
| 321 | if( fpid<=0 || (pPost = manifest_get(fpid, CFTYPE_FORUM, 0))==0 ){ |
| 322 | webpage_error("Missing or invalid fpid query parameter"); |
| 323 | return; |
| 324 | } |
| 325 | if( g.perm.ModForum ){ |
| 326 | if( P("approve") ){ |
| 327 | webpage_not_yet_implemented(); |
| 328 | return; |
| @@ -337,49 +357,68 @@ | |
| 337 | const char *zMimetype = PD("mimetype","text/x-fossil-wiki"); |
| 338 | const char *zContent = PDT("content",""); |
| 339 | if( P("reply") ){ |
| 340 | done = forum_post(0, fpid, 0, 0, zMimetype, zContent); |
| 341 | }else if( P("edit") ){ |
| 342 | done = forum_post(0, 0, fpid, 0, zMimetype, zContent); |
| 343 | }else{ |
| 344 | webpage_error("Need one of 'edit' or 'reply' query parameters"); |
| 345 | } |
| 346 | if( done ) return; |
| 347 | } |
| 348 | if( P("edit") ){ |
| 349 | /* Provide an edit to the fpid post */ |
| 350 | webpage_not_yet_implemented(); |
| 351 | return; |
| 352 | }else{ |
| 353 | const char *zMimetype = PD("mimetype","text/x-fossil-wiki"); |
| 354 | const char *zContent = PDT("content",""); |
| 355 | style_header("Forum Reply"); |
| 356 | @ <h1>Replying To:</h1> |
| 357 | forum_render(pPost->zMimetype, pPost->zWiki); |
| 358 | if( P("preview") ){ |
| 359 | @ <h1>Preview:</h1> |
| 360 | forum_render(zMimetype,zContent); |
| 361 | } |
| 362 | @ <h1>Enter A Reply:</h1> |
| 363 | @ <form action="%R/forumedit" method="POST"> |
| 364 | @ <input type="hidden" name="fpid" value="%h(P("fpid"))"> |
| 365 | @ <input type="hidden" name="reply" value="1"> |
| 366 | forum_entry_widget(0, zMimetype, zContent); |
| 367 | @ <input type="submit" name="preview" value="Preview"> |
| 368 | if( P("preview") ){ |
| 369 | @ <input type="submit" name="submit" value="Submit"> |
| 370 | } |
| 371 | if( g.perm.Debug ){ |
| 372 | /* For the test-forumnew page add these extra debugging controls */ |
| 373 | @ <div class="debug"> |
| 374 | @ <label><input type="checkbox" name="dryrun" %s(PCK("dryrun"))> \ |
| 375 | @ Dry run</label> |
| 376 | @ <br><label><input type="checkbox" name="domod" %s(PCK("domod"))> \ |
| 377 | @ Require moderator approval</label> |
| 378 | @ <br><label><input type="checkbox" name="showqp" %s(PCK("showqp"))> \ |
| 379 | @ Show query parameters</label> |
| 380 | @ </div> |
| 381 | } |
| 382 | @ </form> |
| 383 | } |
| 384 | style_footer(); |
| 385 | } |
| 386 |
| --- src/forum.c | |
| +++ src/forum.c | |
| @@ -22,16 +22,25 @@ | |
| 22 | #include "forum.h" |
| 23 | |
| 24 | /* |
| 25 | ** Render a forum post for display |
| 26 | */ |
| 27 | void forum_render( |
| 28 | const char *zTitle, |
| 29 | const char *zMimetype, |
| 30 | const char *zContent |
| 31 | ){ |
| 32 | Blob x; |
| 33 | @ <div style='border: 1px solid black;padding: 1ex;'> |
| 34 | if( zTitle ){ |
| 35 | @ <h1>%h(zTitle)</h1> |
| 36 | } |
| 37 | blob_init(&x, 0, 0); |
| 38 | blob_append(&x, zContent, -1); |
| 39 | wiki_render_by_mimetype(&x, zMimetype); |
| 40 | blob_reset(&x); |
| 41 | @ </div> |
| 42 | } |
| 43 | |
| 44 | /* |
| 45 | ** Display all posts in a forum thread in chronological order |
| 46 | */ |
| @@ -65,13 +74,13 @@ | |
| 74 | if( firt ){ |
| 75 | @ reply to %d(firt) |
| 76 | } |
| 77 | if( g.perm.Debug ){ |
| 78 | @ <span class="debug">\ |
| 79 | @ <a href="%R/artifact/%h(zUuid)">artifact</a></span> |
| 80 | } |
| 81 | forum_render(0, pPost->zMimetype, pPost->zWiki); |
| 82 | if( g.perm.WrForum ){ |
| 83 | int sameUser = login_is_individual() |
| 84 | && fossil_strcmp(pPost->zUser, g.zLogin)==0; |
| 85 | int isPrivate = content_is_private(fpid); |
| 86 | @ <p><form action="%R/forumedit" method="POST"> |
| @@ -161,39 +170,51 @@ | |
| 170 | int iEdit, /* Post being edited, or zero for a new post */ |
| 171 | const char *zUser, /* Username. NULL means use login name */ |
| 172 | const char *zMimetype, /* Mimetype of content. */ |
| 173 | const char *zContent /* Content */ |
| 174 | ){ |
| 175 | char *zDate; |
| 176 | char *zI; |
| 177 | char *zG; |
| 178 | int iBasis; |
| 179 | Blob x, cksum, formatCheck, errMsg; |
| 180 | Manifest *pPost; |
| 181 | |
| 182 | schema_forum(); |
| 183 | if( iInReplyTo==0 && iEdit>0 ){ |
| 184 | iBasis = iEdit; |
| 185 | iInReplyTo = db_int(0, "SELECT firt FROM forumpost WHERE fpid=%d", iEdit); |
| 186 | }else{ |
| 187 | iBasis = iInReplyTo; |
| 188 | } |
| 189 | webpage_assert( (zTitle==0)+(iInReplyTo==0)==1 ); |
| 190 | blob_init(&x, 0, 0); |
| 191 | zDate = date_in_standard_format("now"); |
| 192 | blob_appendf(&x, "D %s\n", zDate); |
| 193 | fossil_free(zDate); |
| 194 | zG = db_text(0, |
| 195 | "SELECT uuid FROM blob, forumpost" |
| 196 | " WHERE blob.rid==forumpost.froot" |
| 197 | " AND forumpost.fpid=%d", iBasis); |
| 198 | if( zG ){ |
| 199 | blob_appendf(&x, "G %s\n", zG); |
| 200 | fossil_free(zG); |
| 201 | } |
| 202 | if( zTitle ){ |
| 203 | blob_appendf(&x, "H %F\n", zTitle); |
| 204 | } |
| 205 | zI = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", iInReplyTo); |
| 206 | if( zI ){ |
| 207 | blob_appendf(&x, "I %s\n", zI); |
| 208 | fossil_free(zI); |
| 209 | } |
| 210 | if( fossil_strcmp(zMimetype,"text/x-fossil-wiki")!=0 ){ |
| 211 | blob_appendf(&x, "N %s\n", zMimetype); |
| 212 | } |
| 213 | if( iEdit>0 ){ |
| 214 | char *zP = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", iEdit); |
| 215 | if( zP==0 ) webpage_error("missing edit artifact %d", iEdit); |
| 216 | blob_appendf(&x, "P %s\n", zP); |
| 217 | fossil_free(zP); |
| 218 | } |
| 219 | if( zUser==0 ){ |
| 220 | if( login_is_nobody() ){ |
| @@ -205,24 +226,36 @@ | |
| 226 | blob_appendf(&x, "U %F\n", zUser); |
| 227 | blob_appendf(&x, "W %d\n%s\n", strlen(zContent), zContent); |
| 228 | md5sum_blob(&x, &cksum); |
| 229 | blob_appendf(&x, "Z %b\n", &cksum); |
| 230 | blob_reset(&cksum); |
| 231 | |
| 232 | /* Verify that the artifact we are creating is well-formed */ |
| 233 | blob_init(&formatCheck, 0, 0); |
| 234 | blob_init(&errMsg, 0, 0); |
| 235 | blob_copy(&formatCheck, &x); |
| 236 | pPost = manifest_parse(&formatCheck, 0, &errMsg); |
| 237 | if( pPost==0 ){ |
| 238 | webpage_error("malformed forum post artifact - %s", blob_str(&errMsg)); |
| 239 | } |
| 240 | if( pPost->type!=CFTYPE_FORUM ){ |
| 241 | webpage_error("forum post artifact malformed"); |
| 242 | } |
| 243 | manifest_destroy(pPost); |
| 244 | |
| 245 | if( P("dryrun") ){ |
| 246 | @ <div class='debug'> |
| 247 | @ This is the artifact that would have been generated: |
| 248 | @ <pre>%h(blob_str(&x))</pre> |
| 249 | @ </div> |
| 250 | blob_reset(&x); |
| 251 | return 0; |
| 252 | }else{ |
| 253 | int nrid = wiki_put(&x, 0, forum_need_moderation()); |
| 254 | cgi_redirectf("%R/forumthread/%S", rid_to_uuid(nrid)); |
| 255 | return 1; |
| 256 | } |
| 257 | } |
| 258 | |
| 259 | /* |
| 260 | ** Paint the form elements for entering a Forum post |
| 261 | */ |
| @@ -256,13 +289,12 @@ | |
| 289 | } |
| 290 | if( P("submit") ){ |
| 291 | if( forum_post(zTitle, 0, 0, 0, zMimetype, zContent) ) return; |
| 292 | } |
| 293 | if( P("preview") ){ |
| 294 | @ <h1>Preview:</h1> |
| 295 | forum_render(zTitle, zMimetype, zContent); |
| 296 | } |
| 297 | style_header("New Forum Thread"); |
| 298 | @ <form action="%R/%s(g.zPath)" method="POST"> |
| 299 | forum_entry_widget(zTitle, zMimetype, zContent); |
| 300 | @ <input type="submit" name="preview" value="Preview"> |
| @@ -284,24 +316,10 @@ | |
| 316 | } |
| 317 | @ </form> |
| 318 | style_footer(); |
| 319 | } |
| 320 | |
| 321 | /* |
| 322 | ** WEBPAGE: forumedit |
| 323 | ** |
| 324 | ** Edit an existing forum message. |
| 325 | ** Query parameters: |
| @@ -309,20 +327,22 @@ | |
| 327 | ** name=X Hash of the post to be editted. REQUIRED |
| 328 | */ |
| 329 | void forumedit_page(void){ |
| 330 | int fpid; |
| 331 | Manifest *pPost; |
| 332 | const char *zMimetype = 0; |
| 333 | const char *zContent = 0; |
| 334 | const char *zTitle = 0; |
| 335 | |
| 336 | login_check_credentials(); |
| 337 | if( !g.perm.WrForum ){ |
| 338 | login_needed(g.anon.WrForum); |
| 339 | return; |
| 340 | } |
| 341 | fpid = symbolic_name_to_rid(PD("fpid",""), "f"); |
| 342 | if( fpid<=0 || (pPost = manifest_get(fpid, CFTYPE_FORUM, 0))==0 ){ |
| 343 | webpage_error("Missing or invalid fpid query parameter"); |
| 344 | } |
| 345 | if( g.perm.ModForum ){ |
| 346 | if( P("approve") ){ |
| 347 | webpage_not_yet_implemented(); |
| 348 | return; |
| @@ -337,49 +357,68 @@ | |
| 357 | const char *zMimetype = PD("mimetype","text/x-fossil-wiki"); |
| 358 | const char *zContent = PDT("content",""); |
| 359 | if( P("reply") ){ |
| 360 | done = forum_post(0, fpid, 0, 0, zMimetype, zContent); |
| 361 | }else if( P("edit") ){ |
| 362 | done = forum_post(P("title"), 0, fpid, 0, zMimetype, zContent); |
| 363 | }else{ |
| 364 | webpage_error("Missing 'reply' query parameter"); |
| 365 | } |
| 366 | if( done ) return; |
| 367 | } |
| 368 | if( P("edit") ){ |
| 369 | /* Provide an edit to the fpid post */ |
| 370 | zMimetype = P("mimetype"); |
| 371 | zContent = PT("content"); |
| 372 | zTitle = P("title"); |
| 373 | if( zContent==0 ) zContent = fossil_strdup(pPost->zWiki); |
| 374 | if( zMimetype==0 ) zMimetype = fossil_strdup(pPost->zMimetype); |
| 375 | if( zTitle==0 && pPost->zThreadTitle!=0 ){ |
| 376 | zTitle = fossil_strdup(pPost->zThreadTitle); |
| 377 | } |
| 378 | style_header("Forum Edit"); |
| 379 | @ <h1>Original Post:</h1> |
| 380 | forum_render(pPost->zThreadTitle, pPost->zMimetype, pPost->zWiki); |
| 381 | if( P("preview") ){ |
| 382 | @ <h1>Preview Of Editted Post:</h1> |
| 383 | forum_render(zTitle, zMimetype, zContent); |
| 384 | } |
| 385 | @ <h1> |
| 386 | @ <h1>Enter A Reply:</h1> |
| 387 | @ <form action="%R/forumedit" method="POST"> |
| 388 | @ <input type="hidden" name="fpid" value="%h(P("fpid"))"> |
| 389 | @ <input type="hidden" name="edit" value="1"> |
| 390 | forum_entry_widget(zTitle, zMimetype, zContent); |
| 391 | }else{ |
| 392 | zMimetype = PD("mimetype","text/x-fossil-wiki"); |
| 393 | zContent = PDT("content",""); |
| 394 | style_header("Forum Reply"); |
| 395 | @ <h1>Replying To:</h1> |
| 396 | forum_render(0, pPost->zMimetype, pPost->zWiki); |
| 397 | if( P("preview") ){ |
| 398 | @ <h1>Preview:</h1> |
| 399 | forum_render(0, zMimetype,zContent); |
| 400 | } |
| 401 | @ <h1>Enter A Reply:</h1> |
| 402 | @ <form action="%R/forumedit" method="POST"> |
| 403 | @ <input type="hidden" name="fpid" value="%h(P("fpid"))"> |
| 404 | @ <input type="hidden" name="reply" value="1"> |
| 405 | forum_entry_widget(0, zMimetype, zContent); |
| 406 | } |
| 407 | @ <input type="submit" name="preview" value="Preview"> |
| 408 | if( P("preview") ){ |
| 409 | @ <input type="submit" name="submit" value="Submit"> |
| 410 | } |
| 411 | if( g.perm.Debug ){ |
| 412 | /* For the test-forumnew page add these extra debugging controls */ |
| 413 | @ <div class="debug"> |
| 414 | @ <label><input type="checkbox" name="dryrun" %s(PCK("dryrun"))> \ |
| 415 | @ Dry run</label> |
| 416 | @ <br><label><input type="checkbox" name="domod" %s(PCK("domod"))> \ |
| 417 | @ Require moderator approval</label> |
| 418 | @ <br><label><input type="checkbox" name="showqp" %s(PCK("showqp"))> \ |
| 419 | @ Show query parameters</label> |
| 420 | @ </div> |
| 421 | } |
| 422 | @ </form> |
| 423 | style_footer(); |
| 424 | } |
| 425 |
+42
-37
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -936,11 +936,11 @@ | ||
| 936 | 936 | ** If zFormat is an empty string, then this is the /test_env page. |
| 937 | 937 | */ |
| 938 | 938 | void webpage_error(const char *zFormat, ...){ |
| 939 | 939 | int i; |
| 940 | 940 | int showAll; |
| 941 | - char *zErr; | |
| 941 | + char *zErr = 0; | |
| 942 | 942 | int isAuth = 0; |
| 943 | 943 | char zCap[100]; |
| 944 | 944 | static const char *const azCgiVars[] = { |
| 945 | 945 | "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE", |
| 946 | 946 | "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET", "HTTP_ACCEPT_ENCODING", |
| @@ -969,16 +969,11 @@ | ||
| 969 | 969 | va_start(ap, zFormat); |
| 970 | 970 | zErr = vmprintf(zFormat, ap); |
| 971 | 971 | va_end(ap); |
| 972 | 972 | style_header("Bad Request"); |
| 973 | 973 | @ <h1>/%h(g.zPath): %h(zErr)</h1> |
| 974 | - fossil_free(zErr); | |
| 975 | 974 | showAll = 0; |
| 976 | - if( !isAuth ){ | |
| 977 | - style_footer(); | |
| 978 | - return; | |
| 979 | - } | |
| 980 | 975 | }else if( !isAuth ){ |
| 981 | 976 | login_needed(0); |
| 982 | 977 | return; |
| 983 | 978 | }else{ |
| 984 | 979 | style_header("Environment Test"); |
| @@ -985,46 +980,56 @@ | ||
| 985 | 980 | showAll = PB("showall"); |
| 986 | 981 | style_submenu_checkbox("showall", "Cookies", 0, 0); |
| 987 | 982 | style_submenu_element("Stats", "%R/stat"); |
| 988 | 983 | } |
| 989 | 984 | |
| 990 | -#if !defined(_WIN32) | |
| 991 | - @ uid=%d(getuid()), gid=%d(getgid())<br /> | |
| 992 | -#endif | |
| 993 | - @ g.zBaseURL = %h(g.zBaseURL)<br /> | |
| 994 | - @ g.zHttpsURL = %h(g.zHttpsURL)<br /> | |
| 995 | - @ g.zTop = %h(g.zTop)<br /> | |
| 996 | - @ g.zPath = %h(g.zPath)<br /> | |
| 997 | - @ g.userUid = %d(g.userUid)<br /> | |
| 998 | - @ g.zLogin = %h(g.zLogin)<br /> | |
| 999 | - @ g.isHuman = %d(g.isHuman)<br /> | |
| 1000 | - if( g.nRequest ){ | |
| 1001 | - @ g.nRequest = %d(g.nRequest)<br /> | |
| 1002 | - } | |
| 1003 | - if( g.nPendingRequest>1 ){ | |
| 1004 | - @ g.nPendingRequest = %d(g.nPendingRequest)<br /> | |
| 1005 | - } | |
| 1006 | - @ capabilities = %s(find_capabilities(zCap))<br /> | |
| 1007 | - if( zCap[0] ){ | |
| 1008 | - @ anonymous-adds = %s(find_anon_capabilities(zCap))<br /> | |
| 1009 | - } | |
| 1010 | - @ g.zRepositoryName = %h(g.zRepositoryName)<br /> | |
| 1011 | - @ load_average() = %f(load_average())<br /> | |
| 1012 | - @ cgi_csrf_safe(0) = %d(cgi_csrf_safe(0))<br /> | |
| 1013 | - @ <hr /> | |
| 1014 | - P("HTTP_USER_AGENT"); | |
| 1015 | - cgi_print_all(showAll, 0); | |
| 1016 | - if( showAll && blob_size(&g.httpHeader)>0 ){ | |
| 1017 | - @ <hr /> | |
| 1018 | - @ <pre> | |
| 1019 | - @ %h(blob_str(&g.httpHeader)) | |
| 1020 | - @ </pre> | |
| 985 | + if( isAuth ){ | |
| 986 | + #if !defined(_WIN32) | |
| 987 | + @ uid=%d(getuid()), gid=%d(getgid())<br /> | |
| 988 | + #endif | |
| 989 | + @ g.zBaseURL = %h(g.zBaseURL)<br /> | |
| 990 | + @ g.zHttpsURL = %h(g.zHttpsURL)<br /> | |
| 991 | + @ g.zTop = %h(g.zTop)<br /> | |
| 992 | + @ g.zPath = %h(g.zPath)<br /> | |
| 993 | + @ g.userUid = %d(g.userUid)<br /> | |
| 994 | + @ g.zLogin = %h(g.zLogin)<br /> | |
| 995 | + @ g.isHuman = %d(g.isHuman)<br /> | |
| 996 | + if( g.nRequest ){ | |
| 997 | + @ g.nRequest = %d(g.nRequest)<br /> | |
| 998 | + } | |
| 999 | + if( g.nPendingRequest>1 ){ | |
| 1000 | + @ g.nPendingRequest = %d(g.nPendingRequest)<br /> | |
| 1001 | + } | |
| 1002 | + @ capabilities = %s(find_capabilities(zCap))<br /> | |
| 1003 | + if( zCap[0] ){ | |
| 1004 | + @ anonymous-adds = %s(find_anon_capabilities(zCap))<br /> | |
| 1005 | + } | |
| 1006 | + @ g.zRepositoryName = %h(g.zRepositoryName)<br /> | |
| 1007 | + @ load_average() = %f(load_average())<br /> | |
| 1008 | + @ cgi_csrf_safe(0) = %d(cgi_csrf_safe(0))<br /> | |
| 1009 | + @ <hr /> | |
| 1010 | + P("HTTP_USER_AGENT"); | |
| 1011 | + cgi_print_all(showAll, 0); | |
| 1012 | + if( showAll && blob_size(&g.httpHeader)>0 ){ | |
| 1013 | + @ <hr /> | |
| 1014 | + @ <pre> | |
| 1015 | + @ %h(blob_str(&g.httpHeader)) | |
| 1016 | + @ </pre> | |
| 1017 | + } | |
| 1021 | 1018 | } |
| 1022 | 1019 | style_footer(); |
| 1020 | + if( zErr ){ | |
| 1021 | + fossil_panic("webpage_error: %s", zErr); | |
| 1022 | + } | |
| 1023 | 1023 | } |
| 1024 | 1024 | |
| 1025 | 1025 | /* |
| 1026 | 1026 | ** Generate a Not Yet Implemented error page. |
| 1027 | 1027 | */ |
| 1028 | 1028 | void webpage_not_yet_implemented(void){ |
| 1029 | 1029 | webpage_error("Not yet implemented"); |
| 1030 | 1030 | } |
| 1031 | + | |
| 1032 | +#if INTERFACE | |
| 1033 | +# define webpage_assert(T) \ | |
| 1034 | + if(!(T)){webpage_error("assertion failed %s:%d: %s",__FILE__,__LINE__,#T);} | |
| 1035 | +#endif | |
| 1031 | 1036 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -936,11 +936,11 @@ | |
| 936 | ** If zFormat is an empty string, then this is the /test_env page. |
| 937 | */ |
| 938 | void webpage_error(const char *zFormat, ...){ |
| 939 | int i; |
| 940 | int showAll; |
| 941 | char *zErr; |
| 942 | int isAuth = 0; |
| 943 | char zCap[100]; |
| 944 | static const char *const azCgiVars[] = { |
| 945 | "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE", |
| 946 | "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET", "HTTP_ACCEPT_ENCODING", |
| @@ -969,16 +969,11 @@ | |
| 969 | va_start(ap, zFormat); |
| 970 | zErr = vmprintf(zFormat, ap); |
| 971 | va_end(ap); |
| 972 | style_header("Bad Request"); |
| 973 | @ <h1>/%h(g.zPath): %h(zErr)</h1> |
| 974 | fossil_free(zErr); |
| 975 | showAll = 0; |
| 976 | if( !isAuth ){ |
| 977 | style_footer(); |
| 978 | return; |
| 979 | } |
| 980 | }else if( !isAuth ){ |
| 981 | login_needed(0); |
| 982 | return; |
| 983 | }else{ |
| 984 | style_header("Environment Test"); |
| @@ -985,46 +980,56 @@ | |
| 985 | showAll = PB("showall"); |
| 986 | style_submenu_checkbox("showall", "Cookies", 0, 0); |
| 987 | style_submenu_element("Stats", "%R/stat"); |
| 988 | } |
| 989 | |
| 990 | #if !defined(_WIN32) |
| 991 | @ uid=%d(getuid()), gid=%d(getgid())<br /> |
| 992 | #endif |
| 993 | @ g.zBaseURL = %h(g.zBaseURL)<br /> |
| 994 | @ g.zHttpsURL = %h(g.zHttpsURL)<br /> |
| 995 | @ g.zTop = %h(g.zTop)<br /> |
| 996 | @ g.zPath = %h(g.zPath)<br /> |
| 997 | @ g.userUid = %d(g.userUid)<br /> |
| 998 | @ g.zLogin = %h(g.zLogin)<br /> |
| 999 | @ g.isHuman = %d(g.isHuman)<br /> |
| 1000 | if( g.nRequest ){ |
| 1001 | @ g.nRequest = %d(g.nRequest)<br /> |
| 1002 | } |
| 1003 | if( g.nPendingRequest>1 ){ |
| 1004 | @ g.nPendingRequest = %d(g.nPendingRequest)<br /> |
| 1005 | } |
| 1006 | @ capabilities = %s(find_capabilities(zCap))<br /> |
| 1007 | if( zCap[0] ){ |
| 1008 | @ anonymous-adds = %s(find_anon_capabilities(zCap))<br /> |
| 1009 | } |
| 1010 | @ g.zRepositoryName = %h(g.zRepositoryName)<br /> |
| 1011 | @ load_average() = %f(load_average())<br /> |
| 1012 | @ cgi_csrf_safe(0) = %d(cgi_csrf_safe(0))<br /> |
| 1013 | @ <hr /> |
| 1014 | P("HTTP_USER_AGENT"); |
| 1015 | cgi_print_all(showAll, 0); |
| 1016 | if( showAll && blob_size(&g.httpHeader)>0 ){ |
| 1017 | @ <hr /> |
| 1018 | @ <pre> |
| 1019 | @ %h(blob_str(&g.httpHeader)) |
| 1020 | @ </pre> |
| 1021 | } |
| 1022 | style_footer(); |
| 1023 | } |
| 1024 | |
| 1025 | /* |
| 1026 | ** Generate a Not Yet Implemented error page. |
| 1027 | */ |
| 1028 | void webpage_not_yet_implemented(void){ |
| 1029 | webpage_error("Not yet implemented"); |
| 1030 | } |
| 1031 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -936,11 +936,11 @@ | |
| 936 | ** If zFormat is an empty string, then this is the /test_env page. |
| 937 | */ |
| 938 | void webpage_error(const char *zFormat, ...){ |
| 939 | int i; |
| 940 | int showAll; |
| 941 | char *zErr = 0; |
| 942 | int isAuth = 0; |
| 943 | char zCap[100]; |
| 944 | static const char *const azCgiVars[] = { |
| 945 | "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE", |
| 946 | "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET", "HTTP_ACCEPT_ENCODING", |
| @@ -969,16 +969,11 @@ | |
| 969 | va_start(ap, zFormat); |
| 970 | zErr = vmprintf(zFormat, ap); |
| 971 | va_end(ap); |
| 972 | style_header("Bad Request"); |
| 973 | @ <h1>/%h(g.zPath): %h(zErr)</h1> |
| 974 | showAll = 0; |
| 975 | }else if( !isAuth ){ |
| 976 | login_needed(0); |
| 977 | return; |
| 978 | }else{ |
| 979 | style_header("Environment Test"); |
| @@ -985,46 +980,56 @@ | |
| 980 | showAll = PB("showall"); |
| 981 | style_submenu_checkbox("showall", "Cookies", 0, 0); |
| 982 | style_submenu_element("Stats", "%R/stat"); |
| 983 | } |
| 984 | |
| 985 | if( isAuth ){ |
| 986 | #if !defined(_WIN32) |
| 987 | @ uid=%d(getuid()), gid=%d(getgid())<br /> |
| 988 | #endif |
| 989 | @ g.zBaseURL = %h(g.zBaseURL)<br /> |
| 990 | @ g.zHttpsURL = %h(g.zHttpsURL)<br /> |
| 991 | @ g.zTop = %h(g.zTop)<br /> |
| 992 | @ g.zPath = %h(g.zPath)<br /> |
| 993 | @ g.userUid = %d(g.userUid)<br /> |
| 994 | @ g.zLogin = %h(g.zLogin)<br /> |
| 995 | @ g.isHuman = %d(g.isHuman)<br /> |
| 996 | if( g.nRequest ){ |
| 997 | @ g.nRequest = %d(g.nRequest)<br /> |
| 998 | } |
| 999 | if( g.nPendingRequest>1 ){ |
| 1000 | @ g.nPendingRequest = %d(g.nPendingRequest)<br /> |
| 1001 | } |
| 1002 | @ capabilities = %s(find_capabilities(zCap))<br /> |
| 1003 | if( zCap[0] ){ |
| 1004 | @ anonymous-adds = %s(find_anon_capabilities(zCap))<br /> |
| 1005 | } |
| 1006 | @ g.zRepositoryName = %h(g.zRepositoryName)<br /> |
| 1007 | @ load_average() = %f(load_average())<br /> |
| 1008 | @ cgi_csrf_safe(0) = %d(cgi_csrf_safe(0))<br /> |
| 1009 | @ <hr /> |
| 1010 | P("HTTP_USER_AGENT"); |
| 1011 | cgi_print_all(showAll, 0); |
| 1012 | if( showAll && blob_size(&g.httpHeader)>0 ){ |
| 1013 | @ <hr /> |
| 1014 | @ <pre> |
| 1015 | @ %h(blob_str(&g.httpHeader)) |
| 1016 | @ </pre> |
| 1017 | } |
| 1018 | } |
| 1019 | style_footer(); |
| 1020 | if( zErr ){ |
| 1021 | fossil_panic("webpage_error: %s", zErr); |
| 1022 | } |
| 1023 | } |
| 1024 | |
| 1025 | /* |
| 1026 | ** Generate a Not Yet Implemented error page. |
| 1027 | */ |
| 1028 | void webpage_not_yet_implemented(void){ |
| 1029 | webpage_error("Not yet implemented"); |
| 1030 | } |
| 1031 | |
| 1032 | #if INTERFACE |
| 1033 | # define webpage_assert(T) \ |
| 1034 | if(!(T)){webpage_error("assertion failed %s:%d: %s",__FILE__,__LINE__,#T);} |
| 1035 | #endif |
| 1036 |