| | @@ -55,10 +55,48 @@ |
| 55 | 55 | rc = db_column_int(&q, 0); |
| 56 | 56 | } |
| 57 | 57 | db_reset(&q); |
| 58 | 58 | return rc; |
| 59 | 59 | } |
| 60 | + |
| 61 | +/* |
| 62 | +** For a given aritfact ID and type, returns true if the current user |
| 63 | +** could hypothetically attach something to it, else returns 0. |
| 64 | +** |
| 65 | +** The rid is currently only relevant when iArtifactType is |
| 66 | +** CFTYPE_FORUM. For forum posts, it checks precisely the rid given, |
| 67 | +** not the head RID, to keep non-admins from attaching files to |
| 68 | +** threads which have since been taken over by another user (this |
| 69 | +** happens when an admin edits another user's post). |
| 70 | +*/ |
| 71 | +int attach_user_may(int rid, int iArtifactType){ |
| 72 | + if( g.perm.Admin ) return 1; |
| 73 | + if( !login_is_individual() ) return 0; |
| 74 | + switch(iArtifactType){ |
| 75 | + case CFTYPE_FORUM: |
| 76 | + return forumpost_is_owner(rid, 0); |
| 77 | + case CFTYPE_WIKI: |
| 78 | + return g.perm.ApndWiki && g.perm.Attach==0; |
| 79 | + case CFTYPE_TICKET: |
| 80 | + return g.perm.ApndTkt && g.perm.Attach==0; |
| 81 | + case CFTYPE_EVENT: |
| 82 | + return g.perm.Write && g.perm.ApndWiki && g.perm.Attach; |
| 83 | + default: |
| 84 | + return 0; |
| 85 | + } |
| 86 | +} |
| 87 | + |
| 88 | +/* |
| 89 | +** Emits a single-button FORM which invokes |
| 90 | +** /attachadd?target=$zTarget. |
| 91 | +*/ |
| 92 | +void attach_emit_attachadd_button(const char *zTarget){ |
| 93 | + @ <form method="post" action="%R/attachadd">\ |
| 94 | + @ <input type="hidden" name="target" value="%T(zTarget)">\ |
| 95 | + @ <input type="submit" value="Attach..."> |
| 96 | + @ </form>\ |
| 97 | +} |
| 60 | 98 | |
| 61 | 99 | /* |
| 62 | 100 | ** WEBPAGE: attachlist |
| 63 | 101 | ** List attachments. |
| 64 | 102 | ** |
| | @@ -519,11 +557,14 @@ |
| 519 | 557 | /* This check must be done late so that zTargetType is set up. */ |
| 520 | 558 | @ <p class="generalError">Attachment %h(zName) is too large. |
| 521 | 559 | @ <a href="%R/help/attachment-size-limit">Limit</a> is |
| 522 | 560 | @ %d(szLimit ? szLimit : 0x7fffffff) bytes</p> |
| 523 | 561 | /* Fall through and render form. */ |
| 524 | | - }else if( P("ok") && szContent>0 && (goodCaptcha = captcha_is_correct(0)) ){ |
| 562 | + }else if( P("ok") |
| 563 | + && cgi_csrf_safe(2) |
| 564 | + && szContent>0 |
| 565 | + && (goodCaptcha = captcha_is_correct(0)) ){ |
| 525 | 566 | int needModerator = (zForumPost!=0 && forum_need_moderation()) || |
| 526 | 567 | (zTkt!=0 && ticket_need_moderation(0)) || |
| 527 | 568 | (zPage!=0 && wiki_need_moderation(0)); |
| 528 | 569 | attach_commit(zName, zTarget, aContent, szContent, needModerator, zComment); |
| 529 | 570 | cgi_redirect(zTo ? zTo : zFrom); |
| | @@ -554,10 +595,11 @@ |
| 554 | 595 | @ <input type="hidden" name="from" value="%h(zFrom)"> |
| 555 | 596 | @ <input type="submit" name="ok" value="Add Attachment"> |
| 556 | 597 | @ <input type="submit" name="cancel" value="Cancel"> |
| 557 | 598 | @ </div> |
| 558 | 599 | captcha_generate(0); |
| 600 | + login_insert_csrf_secret(); |
| 559 | 601 | @ </form> |
| 560 | 602 | builtin_fossil_js_bundle_or("attach", NULL); |
| 561 | 603 | style_finish_page(); |
| 562 | 604 | fossil_free(zTargetType); |
| 563 | 605 | fossil_free(zExtraFree); |
| | @@ -742,11 +784,10 @@ |
| 742 | 784 | const char *zTarget = P("target"); |
| 743 | 785 | char *zTo = 0; |
| 744 | 786 | char *zTargetType = 0; |
| 745 | 787 | char *zExtraFree = 0; |
| 746 | 788 | int iTgtType = 0; |
| 747 | | - int szContent = 0; |
| 748 | 789 | int goodCaptcha = 1; |
| 749 | 790 | |
| 750 | 791 | if( zFrom==0 ) zFrom = mprintf("%R/home"); |
| 751 | 792 | if( P("cancel") ) cgi_redirect(zFrom); |
| 752 | 793 | if( 0==zTarget ){ |
| | @@ -828,14 +869,16 @@ |
| 828 | 869 | @ <p class="generalError">Error: Incorrect security code.</p> |
| 829 | 870 | } |
| 830 | 871 | @ <h2>Attachments for %s(zTargetType)</h2> |
| 831 | 872 | attachment_list(zTarget, NULL, |
| 832 | 873 | ATTACHLIST_SIZE | ATTACHLIST_HIDE_UNAPPROVED); |
| 833 | | - /* Form gets fleshed out and activate from fossil.attach.js. */ |
| 834 | 874 | @ <div id='attachadd-form-wrapper'> |
| 875 | + /* JS code imports these hidden fields into a form it generates. */ |
| 835 | 876 | @ <input type="hidden" name="target" value="%h(zTarget)"> |
| 836 | | - @ <input type="hidden" name="from" value="%h(zFrom)"> |
| 877 | + if( zFrom ){ |
| 878 | + @ <input type="hidden" name="from" value="%h(zFrom)"> |
| 879 | + } |
| 837 | 880 | if( zTo ){ |
| 838 | 881 | @ <input type="hidden" name="to" value="%h(zTo)"> |
| 839 | 882 | } |
| 840 | 883 | captcha_generate(0); |
| 841 | 884 | login_insert_csrf_secret(); |
| | @@ -1340,5 +1383,6 @@ |
| 1340 | 1383 | } |
| 1341 | 1384 | db_reset(&q); |
| 1342 | 1385 | } |
| 1343 | 1386 | db_finalize(&q); |
| 1344 | 1387 | } |
| 1388 | + |
| 1345 | 1389 | |