| | @@ -52,32 +52,44 @@ |
| 52 | 52 | if( pPost==0 ) continue; |
| 53 | 53 | if( i>0 ){ |
| 54 | 54 | @ <hr> |
| 55 | 55 | } |
| 56 | 56 | i++; |
| 57 | | - @ <p>%d(fpid) %h(zUuid)<br> |
| 58 | | - @ By %h(pPost->zUser) on %h(zDate) |
| 57 | + if( pPost->zThreadTitle ){ |
| 58 | + @ <h1>%h(pPost->zThreadTitle)</h1> |
| 59 | + } |
| 60 | + @ <p>By %h(pPost->zUser) on %h(zDate) |
| 59 | 61 | if( fprev ){ |
| 60 | 62 | @ edit of %d(fprev) %h(pPost->azParent[0]) |
| 61 | 63 | } |
| 62 | 64 | if( firt ){ |
| 63 | 65 | @ in reply to %d(firt) %h(pPost->zInReplyTo) |
| 64 | 66 | } |
| 65 | | - if( pPost->zThreadTitle ){ |
| 66 | | - @ <h1>%h(pPost->zThreadTitle)</h1> |
| 67 | | - } |
| 68 | 67 | forum_render(pPost->zMimetype, pPost->zWiki); |
| 69 | 68 | if( g.perm.WrForum ){ |
| 69 | + int sameUser = login_is_individual() |
| 70 | + && fossil_strcmp(pPost->zUser, g.zLogin)==0; |
| 71 | + int isPrivate = content_is_private(fpid); |
| 70 | 72 | @ <p><form action="%R/forumedit" method="POST"> |
| 71 | 73 | @ <input type="hidden" name="fpid" value="%s(zUuid)"> |
| 72 | | - @ <input type="submit" name="reply" value="Reply"> |
| 73 | | - if( g.perm.Admin || fossil_strcmp(pPost->zUser,g.zLogin)==0 ){ |
| 74 | | - @ <input type="submit" name="edit" value="Edit"> |
| 75 | | - } |
| 76 | | - if( g.perm.ModForum && content_is_private(fpid) ){ |
| 74 | + if( !isPrivate ){ |
| 75 | + /* Reply and Edit are only available if the post has already |
| 76 | + ** been approved */ |
| 77 | + @ <input type="submit" name="reply" value="Reply"> |
| 78 | + if( g.perm.Admin || sameUser ){ |
| 79 | + @ <input type="submit" name="edit" value="Edit"> |
| 80 | + @ <input type="submit" name="nullout" value="Delete"> |
| 81 | + } |
| 82 | + }else if( g.perm.ModForum ){ |
| 83 | + /* Provide moderators with moderation buttons for posts that |
| 84 | + ** are pending moderation */ |
| 77 | 85 | @ <input type="submit" name="approve" value="Approve"> |
| 78 | 86 | @ <input type="submit" name="reject" value="Reject"> |
| 87 | + }else if( sameUser ){ |
| 88 | + /* A post that is pending moderation can be deleted by the |
| 89 | + ** person who originally submitted the post */ |
| 90 | + @ <input type="submit" name="reject" value="Delete"> |
| 79 | 91 | } |
| 80 | 92 | @ </form></p> |
| 81 | 93 | } |
| 82 | 94 | manifest_destroy(pPost); |
| 83 | 95 | } |
| | @@ -200,10 +212,27 @@ |
| 200 | 212 | |
| 201 | 213 | forum_post_error: |
| 202 | 214 | blob_reset(&x); |
| 203 | 215 | return 0; |
| 204 | 216 | } |
| 217 | + |
| 218 | +/* |
| 219 | +** Paint the form elements for entering a Forum post |
| 220 | +*/ |
| 221 | +static void forum_entry_widget( |
| 222 | + const char *zTitle, |
| 223 | + const char *zMimetype, |
| 224 | + const char *zContent |
| 225 | +){ |
| 226 | + if( zTitle ){ |
| 227 | + @ Title: <input type="input" name="title" value="%h(zTitle)" size="50"><br> |
| 228 | + } |
| 229 | + @ Markup style: |
| 230 | + mimetype_option_menu(zMimetype); |
| 231 | + @ <br><textarea name="content" class="wikiedit" cols="80" \ |
| 232 | + @ rows="25" wrap="virtual">%h(zContent)</textarea><br> |
| 233 | +} |
| 205 | 234 | |
| 206 | 235 | /* |
| 207 | 236 | ** WEBPAGE: forumnew |
| 208 | 237 | ** WEBPAGE: test-forumnew |
| 209 | 238 | ** |
| | @@ -210,13 +239,13 @@ |
| 210 | 239 | ** Start a new forum thread. The /test-forumnew works just like |
| 211 | 240 | ** /forumnew except that it provides additional controls for testing |
| 212 | 241 | ** and debugging. |
| 213 | 242 | */ |
| 214 | 243 | void forumnew_page(void){ |
| 215 | | - const char *zTitle = PDT("t",""); |
| 216 | | - const char *zMimetype = PD("mt","text/x-fossil-wiki"); |
| 217 | | - const char *zContent = PDT("x",""); |
| 244 | + const char *zTitle = PDT("title",""); |
| 245 | + const char *zMimetype = PD("mimetype","text/x-fossil-wiki"); |
| 246 | + const char *zContent = PDT("content",""); |
| 218 | 247 | login_check_credentials(); |
| 219 | 248 | if( !g.perm.WrForum ){ |
| 220 | 249 | login_needed(g.anon.WrForum); |
| 221 | 250 | return; |
| 222 | 251 | } |
| | @@ -228,15 +257,11 @@ |
| 228 | 257 | forum_render(zMimetype, zContent); |
| 229 | 258 | @ <hr> |
| 230 | 259 | } |
| 231 | 260 | style_header("New Forum Thread"); |
| 232 | 261 | @ <form action="%R/%s(g.zPath)" method="POST"> |
| 233 | | - @ Title: <input type="input" name="t" value="%h(zTitle)" size="50"><br> |
| 234 | | - @ Markup style: |
| 235 | | - mimetype_option_menu(zMimetype); |
| 236 | | - @ <br><textarea name="x" class="wikiedit" cols="80" \ |
| 237 | | - @ rows="25" wrap="virtual">%h(zContent)</textarea><br> |
| 262 | + forum_entry_widget(zTitle, zMimetype, zContent); |
| 238 | 263 | @ <input type="submit" name="preview" value="Preview"> |
| 239 | 264 | if( P("preview") ){ |
| 240 | 265 | @ <input type="submit" name="submit" value="Submit"> |
| 241 | 266 | }else{ |
| 242 | 267 | @ <input type="submit" name="submit" value="Submit" disabled> |
| | @@ -276,22 +301,29 @@ |
| 276 | 301 | */ |
| 277 | 302 | void forumedit_page(void){ |
| 278 | 303 | int fpid; |
| 279 | 304 | Manifest *pPost; |
| 280 | 305 | |
| 281 | | - fpid = symbolic_name_to_rid(PD("fpid",""), "f"); |
| 282 | 306 | login_check_credentials(); |
| 283 | 307 | if( !g.perm.WrForum ){ |
| 284 | 308 | login_needed(g.anon.WrForum); |
| 285 | 309 | return; |
| 286 | 310 | } |
| 311 | + fpid = symbolic_name_to_rid(PD("fpid",""), "f"); |
| 287 | 312 | if( fpid<=0 || (pPost = manifest_get(fpid, CFTYPE_FORUM, 0))==0 ){ |
| 288 | 313 | webpage_error("Missing or invalid fpid query parameter"); |
| 289 | 314 | return; |
| 290 | 315 | } |
| 291 | | -#if 0 |
| 292 | 316 | if( g.perm.ModForum ){ |
| 293 | 317 | if( P("approve") ){ |
| 318 | + webpage_not_yet_implemented(); |
| 319 | + return; |
| 294 | 320 | } |
| 295 | 321 | if( P("reject") ){ |
| 322 | + webpage_not_yet_implemented(); |
| 323 | + return; |
| 296 | 324 | } |
| 297 | 325 | } |
| 326 | + if( P("submitdryrun") ){ |
| 327 | + cgi_set_parameter_nocopy("dryrun","1",1); |
| 328 | + cgi_set_parameter_nocopy("submit","1",1); |
| 329 | + } |
| | @@ -298,10 +330,43 @@ |
| 298 | | - if( P("submit") ){ |
| 330 | + if( P("submit") && cgi_csrf_safe(1) ){ |
| 331 | + int done = 1; |
| 332 | + const char *zMimetype = PD("mimetype","text/x-fossil-wiki"); |
| 333 | + const char *zContent = PDT("content",""); |
| 334 | + if( P("reply") ){ |
| 335 | + done = forum_post(0, fpid, 0, 0, zMimetype, zContent); |
| 336 | + }else if( P("edit") ){ |
| 337 | + done = forum_post(0, 0, fpid, 0, zMimetype, zContent); |
| 338 | + }else{ |
| 339 | + webpage_error("Need one of 'edit' or 'reply' query parameters"); |
| 340 | + } |
| 341 | + if( done ) return; |
| 299 | 342 | } |
| 300 | 343 | if( P("edit") ){ |
| 301 | | - } |
| 302 | | - if( P("reply") ){ |
| 344 | + /* Provide an edit to the fpid post */ |
| 345 | + webpage_not_yet_implemented(); |
| 346 | + return; |
| 347 | + }else{ |
| 348 | + const char *zMimetype = PD("mimetype","text/x-fossil-wiki"); |
| 349 | + const char *zContent = PDT("content",""); |
| 350 | + style_header("Forum Reply"); |
| 351 | + @ <h1>Replying To:</h1> |
| 352 | + forum_render(pPost->zMimetype, pPost->zWiki); |
| 353 | + if( P("preview") ){ |
| 354 | + @ <h1>Preview:</h1> |
| 355 | + forum_render(zMimetype,zContent); |
| 356 | + } |
| 357 | + @ <h1>Enter A Reply:</h1> |
| 358 | + @ <form action="%R/forumedit" method="POST"> |
| 359 | + @ <input type="hidden" name="fpid" value="%h(P("fpid"))"> |
| 360 | + @ <input type="hidden" name="reply" value="1"> |
| 361 | + forum_entry_widget(0, zMimetype, zContent); |
| 362 | + @ <input type="submit" name="preview" value="Preview"> |
| 363 | + if( P("preview") ){ |
| 364 | + @ <input type="submit" name="submit" value="Submit"> |
| 365 | + if( g.perm.Setup ){ |
| 366 | + @ <input type="submit" name="submitdryrun" value="Dry Run"> |
| 367 | + } |
| 368 | + } |
| 369 | + @ </form> |
| 303 | 370 | } |
| 304 | 371 | style_footer(); |
| 305 | | -#endif |
| 306 | | - webpage_error("Not yet implemented"); |
| 307 | 372 | } |
| 308 | 373 | |