| | @@ -76,19 +76,140 @@ |
| 76 | 76 | return; |
| 77 | 77 | } |
| 78 | 78 | forum_thread_chronological(froot); |
| 79 | 79 | style_footer(); |
| 80 | 80 | } |
| 81 | + |
| 82 | +/* |
| 83 | +** Return true if a forum post should be moderated. |
| 84 | +*/ |
| 85 | +static int forum_need_moderation(void){ |
| 86 | + return !g.perm.WrTForum && !g.perm.ModForum && P("domod")==0; |
| 87 | +} |
| 88 | + |
| 89 | +/* |
| 90 | +** Add a new Forum Post artifact to the repository. |
| 91 | +*/ |
| 92 | +static void forum_post( |
| 93 | + const char *zTitle, /* Title. NULL for replies */ |
| 94 | + int iInReplyTo, /* Post replying to. 0 for new threads */ |
| 95 | + int iEdit, /* Post being edited, or zero for a new post */ |
| 96 | + const char *zUser, /* Username. NULL means use login name */ |
| 97 | + const char *zMimetype, /* Mimetype of content. */ |
| 98 | + const char *zContent /* Content */ |
| 99 | +){ |
| 100 | + Blob x, cksum; |
| 101 | + char *zDate; |
| 102 | + schema_forum(); |
| 103 | + blob_init(&x, 0, 0); |
| 104 | + zDate = date_in_standard_format("now"); |
| 105 | + blob_appendf(&x, "D %s\n", zDate); |
| 106 | + fossil_free(zDate); |
| 107 | + if( zTitle ){ |
| 108 | + blob_appendf(&x, "H %F\n", zTitle); |
| 109 | + }else{ |
| 110 | + char *zG = db_text(0, |
| 111 | + "SELECT uuid FROM blob, forumpost" |
| 112 | + " WHERE blob.rid==forumpost.froot" |
| 113 | + " AND forumpost.fpid=%d", iInReplyTo); |
| 114 | + char *zI; |
| 115 | + if( zG==0 ) goto forum_post_error; |
| 116 | + blob_appendf(&x, "G %s\n", zG); |
| 117 | + fossil_free(zG); |
| 118 | + zI = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", iInReplyTo); |
| 119 | + if( zI==0 ) goto forum_post_error; |
| 120 | + blob_appendf(&x, "I %s\n", zI); |
| 121 | + fossil_free(zI); |
| 122 | + } |
| 123 | + if( fossil_strcmp(zMimetype,"text/x-fossil-wiki")!=0 ){ |
| 124 | + blob_appendf(&x, "N %s\n", zMimetype); |
| 125 | + } |
| 126 | + if( iEdit>0 ){ |
| 127 | + char *zP = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", iEdit); |
| 128 | + if( zP==0 ) goto forum_post_error; |
| 129 | + blob_appendf(&x, "P %s\n", zP); |
| 130 | + fossil_free(zP); |
| 131 | + } |
| 132 | + if( zUser==0 ){ |
| 133 | + if( login_is_nobody() ){ |
| 134 | + zUser = "anonymous"; |
| 135 | + }else{ |
| 136 | + zUser = login_name(); |
| 137 | + } |
| 138 | + } |
| 139 | + blob_appendf(&x, "U %F\n", zUser); |
| 140 | + blob_appendf(&x, "W %d\n%s\n", strlen(zContent), zContent); |
| 141 | + md5sum_blob(&x, &cksum); |
| 142 | + blob_appendf(&x, "Z %b\n", &cksum); |
| 143 | + blob_reset(&cksum); |
| 144 | + if( P("dryrun") ){ |
| 145 | + @ <pre>%h(blob_str(&x))</pre><hr> |
| 146 | + }else{ |
| 147 | + wiki_put(&x, 0, forum_need_moderation()); |
| 148 | + return; |
| 149 | + } |
| 150 | + |
| 151 | +forum_post_error: |
| 152 | + blob_reset(&x); |
| 153 | +} |
| 154 | + |
| 155 | +/* |
| 156 | +** Render a forum post for display |
| 157 | +*/ |
| 158 | +void forum_render(const char *zMimetype, const char *zContent){ |
| 159 | + Blob x; |
| 160 | + blob_init(&x, zContent, -1); |
| 161 | + wiki_render_by_mimetype(&x, zMimetype); |
| 162 | + blob_reset(&x); |
| 163 | +} |
| 81 | 164 | |
| 82 | 165 | /* |
| 83 | 166 | ** WEBPAGE: forumnew |
| 167 | +** WEBPAGE: test-forumnew |
| 84 | 168 | ** |
| 85 | | -** Start a new forum thread. |
| 169 | +** Start a new forum thread. The /test-forumnew works just like |
| 170 | +** /forumnew except that it provides additional controls for testing |
| 171 | +** and debugging. |
| 86 | 172 | */ |
| 87 | 173 | void forumnew_page(void){ |
| 88 | | - style_header("Pending"); |
| 89 | | - @ TBD... |
| 174 | + const char *zTitle = PDT("t",""); |
| 175 | + const char *zMimetype = PD("mt","text/x-fossil-wiki"); |
| 176 | + const char *zContent = PDT("x",""); |
| 177 | + login_check_credentials(); |
| 178 | + if( !g.perm.WrForum ){ |
| 179 | + login_needed(g.anon.WrForum); |
| 180 | + return; |
| 181 | + } |
| 182 | + if( P("submit") ){ |
| 183 | + forum_post(zTitle, 0, 0, 0, zMimetype, zContent); |
| 184 | + } |
| 185 | + if( P("preview") ){ |
| 186 | + @ <h1>%h(zTitle)</h1> |
| 187 | + forum_render(zMimetype, zContent); |
| 188 | + @ <hr> |
| 189 | + } |
| 190 | + style_header("New Forum Thread"); |
| 191 | + @ <form action="%R/%s(g.zPath)" method="POST"> |
| 192 | + @ Title: <input type="input" name="t" value="%h(zTitle)" size="50"><br> |
| 193 | + @ Markup style: |
| 194 | + mimetype_option_menu(zMimetype); |
| 195 | + @ <br><textarea name="x" class="wikiedit" cols="80" \ |
| 196 | + @ rows="25" wrap="virtual">%h(zContent)</textarea><br> |
| 197 | + @ <input type="submit" name="preview" value="Preview"> |
| 198 | + if( P("preview") ){ |
| 199 | + @ <input type="submit" name="submit" value="Submit"> |
| 200 | + }else{ |
| 201 | + @ <input type="submit" name="submit" value="Submit" disabled> |
| 202 | + } |
| 203 | + if( g.zPath[0]=='t' ){ |
| 204 | + /* For the test-forumnew page add these extra debugging controls */ |
| 205 | + @ <br><label><input type="checkbox" name="dryrun" %s(PCK("dryrun"))> \ |
| 206 | + @ Dry run</label> |
| 207 | + @ <br><label><input type="checkbox" name="domod" %s(PCK("domod"))> \ |
| 208 | + @ Require moderator approval</label> |
| 209 | + } |
| 210 | + @ </form> |
| 90 | 211 | style_footer(); |
| 91 | 212 | } |
| 92 | 213 | |
| 93 | 214 | /* |
| 94 | 215 | ** WEBPAGE: forumreply |
| 95 | 216 | |