Fossil SCM

Correct /attachlist's linking to the proper attachment-target page. For forumpost attachments, have /attachadd redirect to /attachview for the time being, and that page has a link back to the forum post(s).

stephan 2026-05-22 20:36 UTC forum-attachments
Commit f1a04c3ada69fc8cc231f3ecbf91918774774b1667b8c025a838419c89cddbfb
+39 -14
--- src/attach.c
+++ src/attach.c
@@ -55,11 +55,11 @@
5555
** tkt=HASH
5656
** page=WIKIPAGE
5757
** technote=HASH
5858
** forumpost=HASH
5959
**
60
-** At most one of technote=, tkt= or page= may be supplied.
60
+** At most one of technote=, tkt=, forumpost=, or page= may be supplied.
6161
**
6262
** If none are given, all attachments are listed. If one is given, only
6363
** attachments for the designated technote, ticket or wiki page are shown.
6464
**
6565
** HASH may be just a prefix of the relevant technical note or ticket
@@ -130,23 +130,30 @@
130130
const int attachid = db_column_int(&q, 7);
131131
/* type 0 is a wiki page, 1 is a ticket, 2 is a tech note */
132132
const int type = attachment_target_type(zTarget);
133133
const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
134134
int i;
135
- char *zUrlTail;
135
+ char *zUrlTail = 0;
136136
for(i=0; zFilename[i]; i++){
137137
if( zFilename[i]=='/' && zFilename[i+1]!=0 ){
138138
zFilename = &zFilename[i+1];
139139
i = -1;
140140
}
141141
}
142
- if( type==1 ){
143
- zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
144
- }else if( type==2 ){
145
- zUrlTail = mprintf("technote=%s&file=%t", zTarget, zFilename);
146
- }else{
147
- zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename);
142
+ switch( type ){
143
+ case CFTYPE_TICKET:
144
+ zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
145
+ break;
146
+ case CFTYPE_TECHNOTE:
147
+ zUrlTail = mprintf("technote=%s&file=%t", zTarget, zFilename);
148
+ break;
149
+ case CFTYPE_FORUM:
150
+ zUrlTail = mprintf("forumpost=%t&file=%t", zTarget, zFilename);
151
+ break;
152
+ case CFTYPE_WIKI:
153
+ zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename);
154
+ break;
148155
}
149156
@ <li><p>
150157
@ Attachment %z(href("%R/ainfo/%!S",zUuid))%S(zUuid)</a>
151158
moderation_pending_www(attachid);
152159
@ <br><a href="%R/attachview?%s(zUrlTail)">%h(zFilename)</a>
@@ -210,27 +217,36 @@
210217
** Query parameters:
211218
**
212219
** tkt=HASH
213220
** page=WIKIPAGE
214221
** technote=HASH
222
+** forumpost=HASH
215223
** file=FILENAME
216224
** attachid=ID
217225
**
218226
*/
219227
void attachview_page(void){
220228
const char *zPage = P("page");
221229
const char *zTkt = P("tkt");
222230
const char *zTechNote = P("technote");
231
+ const char *zForumPost = P("forumpost");
223232
const char *zFile = P("file");
224233
const char *zTarget = 0;
225234
int attachid = atoi(PD("attachid","0"));
226
- char *zUUID;
235
+ char *zUUID = 0;
227236
228237
if( zFile==0 ) fossil_redirect_home();
229238
login_check_credentials();
230239
style_set_current_feature("attach");
231
- if( zPage ){
240
+ if( zForumPost ){
241
+ int fnid;
242
+ if( g.perm.RdForum==0 ){ login_needed(g.anon.RdForum); return; }
243
+ /* Forum attachments are always tied to the post's initial version */
244
+ fnid = forumpost_head_rid2(zForumPost);
245
+ if( fnid>0 ) zTarget = rid_to_uuid(fnid);
246
+ @ DEBUG: fnid=%d(fnid) zForumPost=%h(zForumPost) zUUID=%s(zUUID)<br>
247
+ }else if( zPage ){
232248
if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
233249
zTarget = zPage;
234250
}else if( zTkt ){
235251
if( g.perm.RdTkt==0 ){ login_needed(g.anon.RdTkt); return; }
236252
zTarget = zTkt;
@@ -375,27 +391,27 @@
375391
const char *zTechNote = P("technote");
376392
const char *zFrom = P("from");
377393
const char *aContent = P("f");
378394
const char *zName = PD("f:filename","unknown");
379395
const char *zTarget;
396
+ char * zTo = 0;
380397
char *zTargetType;
381398
char *zExtraFree = 0;
382399
int szContent = atoi(PD("f:bytes","0"));
383400
int goodCaptcha = 1;
384401
int szLimit = 0;
385402
386403
if( zFrom==0 ) zFrom = mprintf("%R/home");
387404
if( P("cancel") ) cgi_redirect(zFrom);
388405
if( (!!zPage + !!zTkt + !!zTechNote + !!zForumPost)!=1 ){
389
- //fossil_redirect_home();
390406
fossil_fatal("Requires exactly one one: page=X, tkt=X, forumpost=X, or technote=X");
391407
}
392408
login_check_credentials();
393409
szLimit = db_get_int("attachment-size-limit", 0);
394410
if( szContent<0 || (szLimit && szContent>szLimit) ){
395411
fossil_fatal("Attachment %s is too large. Limit is %d bytes.", zName,
396
- (szLimit>0 && szContent>0) ? szLimit : 0x7fffffff);
412
+ szLimit ? szLimit : 0x7fffffff);
397413
}
398414
if( zForumPost ){
399415
int fpid;
400416
if( g.perm.AttachForum==0 ){
401417
login_needed(g.anon.AttachForum);
@@ -402,14 +418,19 @@
402418
return;
403419
}
404420
fpid = forumpost_head_rid2(zForumPost);
405421
if( fpid<=0 ){
406422
fossil_fatal("Invalid forum post ID: %h", zForumPost);
423
+ }else if( !g.perm.Admin && !forumpost_is_owner(fpid, 0) ){
424
+ fossil_fatal("Only admins can attach files to other users' "
425
+ "forum posts.");
407426
}
408427
zTarget = zExtraFree = rid_to_uuid(fpid);
409428
zTargetType = mprintf("Forum post <a href=\"%R/forumpost/%S\">%h</a>",
410429
zTarget, zForumPost);
430
+ zTo = mprintf("%R/attachview?forumpost=%T&file=%T",
431
+ zTarget, zName);
411432
}else if( zPage ){
412433
if( g.perm.ApndWiki==0 || g.perm.Attach==0 ){
413434
login_needed(g.anon.ApndWiki && g.anon.Attach);
414435
return;
415436
}
@@ -452,11 +473,11 @@
452473
int needModerator = (zForumPost!=0 && forum_need_moderation()) ||
453474
(zTkt!=0 && ticket_need_moderation(0)) ||
454475
(zPage!=0 && wiki_need_moderation(0));
455476
const char *zComment = PD("comment", "");
456477
attach_commit(zName, zTarget, aContent, szContent, needModerator, zComment);
457
- cgi_redirect(zFrom);
478
+ cgi_redirect(zTo ? zTo : zFrom);
458479
}
459480
style_set_current_feature("attach");
460481
style_header("Add Attachment");
461482
if( !goodCaptcha ){
462483
@ <p class="generalError">Error: Incorrect security code.</p>
@@ -512,11 +533,11 @@
512533
const char *zModAction; /* Moderation action or NULL */
513534
int isModerator; /* TRUE if user is the moderator */
514535
const char *zMime; /* MIME Type */
515536
Blob attach; /* Content of the attachment */
516537
int fShowContent = 0;
517
- int bUserIsOwner = 0;
538
+ int bUserIsOwner = 0; /* True if pAttach->zUser is login_name() */
518539
int showDelMenu = 0;
519540
const char *zLn = P("ln");
520541
521542
login_check_credentials();
522543
if( !g.perm.RdTkt && !g.perm.RdWiki ){
@@ -572,10 +593,14 @@
572593
char *zNewDate;
573594
Blob manifest;
574595
Blob cksum;
575596
const char *zFile = zName;
576597
598
+ if( !g.perm.Admin && !bUserIsOwner ){
599
+ fossil_fatal("Only admins can delete other users' attachments from "
600
+ "forum posts.");
601
+ }
577602
db_begin_transaction();
578603
blob_zero(&manifest);
579604
for(i=n=0; zFile[i]; i++){
580605
if( zFile[i]=='/' || zFile[i]=='\\' ) n = i;
581606
}
582607
--- src/attach.c
+++ src/attach.c
@@ -55,11 +55,11 @@
55 ** tkt=HASH
56 ** page=WIKIPAGE
57 ** technote=HASH
58 ** forumpost=HASH
59 **
60 ** At most one of technote=, tkt= or page= may be supplied.
61 **
62 ** If none are given, all attachments are listed. If one is given, only
63 ** attachments for the designated technote, ticket or wiki page are shown.
64 **
65 ** HASH may be just a prefix of the relevant technical note or ticket
@@ -130,23 +130,30 @@
130 const int attachid = db_column_int(&q, 7);
131 /* type 0 is a wiki page, 1 is a ticket, 2 is a tech note */
132 const int type = attachment_target_type(zTarget);
133 const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
134 int i;
135 char *zUrlTail;
136 for(i=0; zFilename[i]; i++){
137 if( zFilename[i]=='/' && zFilename[i+1]!=0 ){
138 zFilename = &zFilename[i+1];
139 i = -1;
140 }
141 }
142 if( type==1 ){
143 zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
144 }else if( type==2 ){
145 zUrlTail = mprintf("technote=%s&file=%t", zTarget, zFilename);
146 }else{
147 zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename);
 
 
 
 
 
 
 
148 }
149 @ <li><p>
150 @ Attachment %z(href("%R/ainfo/%!S",zUuid))%S(zUuid)</a>
151 moderation_pending_www(attachid);
152 @ <br><a href="%R/attachview?%s(zUrlTail)">%h(zFilename)</a>
@@ -210,27 +217,36 @@
210 ** Query parameters:
211 **
212 ** tkt=HASH
213 ** page=WIKIPAGE
214 ** technote=HASH
 
215 ** file=FILENAME
216 ** attachid=ID
217 **
218 */
219 void attachview_page(void){
220 const char *zPage = P("page");
221 const char *zTkt = P("tkt");
222 const char *zTechNote = P("technote");
 
223 const char *zFile = P("file");
224 const char *zTarget = 0;
225 int attachid = atoi(PD("attachid","0"));
226 char *zUUID;
227
228 if( zFile==0 ) fossil_redirect_home();
229 login_check_credentials();
230 style_set_current_feature("attach");
231 if( zPage ){
 
 
 
 
 
 
 
232 if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
233 zTarget = zPage;
234 }else if( zTkt ){
235 if( g.perm.RdTkt==0 ){ login_needed(g.anon.RdTkt); return; }
236 zTarget = zTkt;
@@ -375,27 +391,27 @@
375 const char *zTechNote = P("technote");
376 const char *zFrom = P("from");
377 const char *aContent = P("f");
378 const char *zName = PD("f:filename","unknown");
379 const char *zTarget;
 
380 char *zTargetType;
381 char *zExtraFree = 0;
382 int szContent = atoi(PD("f:bytes","0"));
383 int goodCaptcha = 1;
384 int szLimit = 0;
385
386 if( zFrom==0 ) zFrom = mprintf("%R/home");
387 if( P("cancel") ) cgi_redirect(zFrom);
388 if( (!!zPage + !!zTkt + !!zTechNote + !!zForumPost)!=1 ){
389 //fossil_redirect_home();
390 fossil_fatal("Requires exactly one one: page=X, tkt=X, forumpost=X, or technote=X");
391 }
392 login_check_credentials();
393 szLimit = db_get_int("attachment-size-limit", 0);
394 if( szContent<0 || (szLimit && szContent>szLimit) ){
395 fossil_fatal("Attachment %s is too large. Limit is %d bytes.", zName,
396 (szLimit>0 && szContent>0) ? szLimit : 0x7fffffff);
397 }
398 if( zForumPost ){
399 int fpid;
400 if( g.perm.AttachForum==0 ){
401 login_needed(g.anon.AttachForum);
@@ -402,14 +418,19 @@
402 return;
403 }
404 fpid = forumpost_head_rid2(zForumPost);
405 if( fpid<=0 ){
406 fossil_fatal("Invalid forum post ID: %h", zForumPost);
 
 
 
407 }
408 zTarget = zExtraFree = rid_to_uuid(fpid);
409 zTargetType = mprintf("Forum post <a href=\"%R/forumpost/%S\">%h</a>",
410 zTarget, zForumPost);
 
 
411 }else if( zPage ){
412 if( g.perm.ApndWiki==0 || g.perm.Attach==0 ){
413 login_needed(g.anon.ApndWiki && g.anon.Attach);
414 return;
415 }
@@ -452,11 +473,11 @@
452 int needModerator = (zForumPost!=0 && forum_need_moderation()) ||
453 (zTkt!=0 && ticket_need_moderation(0)) ||
454 (zPage!=0 && wiki_need_moderation(0));
455 const char *zComment = PD("comment", "");
456 attach_commit(zName, zTarget, aContent, szContent, needModerator, zComment);
457 cgi_redirect(zFrom);
458 }
459 style_set_current_feature("attach");
460 style_header("Add Attachment");
461 if( !goodCaptcha ){
462 @ <p class="generalError">Error: Incorrect security code.</p>
@@ -512,11 +533,11 @@
512 const char *zModAction; /* Moderation action or NULL */
513 int isModerator; /* TRUE if user is the moderator */
514 const char *zMime; /* MIME Type */
515 Blob attach; /* Content of the attachment */
516 int fShowContent = 0;
517 int bUserIsOwner = 0;
518 int showDelMenu = 0;
519 const char *zLn = P("ln");
520
521 login_check_credentials();
522 if( !g.perm.RdTkt && !g.perm.RdWiki ){
@@ -572,10 +593,14 @@
572 char *zNewDate;
573 Blob manifest;
574 Blob cksum;
575 const char *zFile = zName;
576
 
 
 
 
577 db_begin_transaction();
578 blob_zero(&manifest);
579 for(i=n=0; zFile[i]; i++){
580 if( zFile[i]=='/' || zFile[i]=='\\' ) n = i;
581 }
582
--- src/attach.c
+++ src/attach.c
@@ -55,11 +55,11 @@
55 ** tkt=HASH
56 ** page=WIKIPAGE
57 ** technote=HASH
58 ** forumpost=HASH
59 **
60 ** At most one of technote=, tkt=, forumpost=, or page= may be supplied.
61 **
62 ** If none are given, all attachments are listed. If one is given, only
63 ** attachments for the designated technote, ticket or wiki page are shown.
64 **
65 ** HASH may be just a prefix of the relevant technical note or ticket
@@ -130,23 +130,30 @@
130 const int attachid = db_column_int(&q, 7);
131 /* type 0 is a wiki page, 1 is a ticket, 2 is a tech note */
132 const int type = attachment_target_type(zTarget);
133 const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
134 int i;
135 char *zUrlTail = 0;
136 for(i=0; zFilename[i]; i++){
137 if( zFilename[i]=='/' && zFilename[i+1]!=0 ){
138 zFilename = &zFilename[i+1];
139 i = -1;
140 }
141 }
142 switch( type ){
143 case CFTYPE_TICKET:
144 zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
145 break;
146 case CFTYPE_TECHNOTE:
147 zUrlTail = mprintf("technote=%s&file=%t", zTarget, zFilename);
148 break;
149 case CFTYPE_FORUM:
150 zUrlTail = mprintf("forumpost=%t&file=%t", zTarget, zFilename);
151 break;
152 case CFTYPE_WIKI:
153 zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename);
154 break;
155 }
156 @ <li><p>
157 @ Attachment %z(href("%R/ainfo/%!S",zUuid))%S(zUuid)</a>
158 moderation_pending_www(attachid);
159 @ <br><a href="%R/attachview?%s(zUrlTail)">%h(zFilename)</a>
@@ -210,27 +217,36 @@
217 ** Query parameters:
218 **
219 ** tkt=HASH
220 ** page=WIKIPAGE
221 ** technote=HASH
222 ** forumpost=HASH
223 ** file=FILENAME
224 ** attachid=ID
225 **
226 */
227 void attachview_page(void){
228 const char *zPage = P("page");
229 const char *zTkt = P("tkt");
230 const char *zTechNote = P("technote");
231 const char *zForumPost = P("forumpost");
232 const char *zFile = P("file");
233 const char *zTarget = 0;
234 int attachid = atoi(PD("attachid","0"));
235 char *zUUID = 0;
236
237 if( zFile==0 ) fossil_redirect_home();
238 login_check_credentials();
239 style_set_current_feature("attach");
240 if( zForumPost ){
241 int fnid;
242 if( g.perm.RdForum==0 ){ login_needed(g.anon.RdForum); return; }
243 /* Forum attachments are always tied to the post's initial version */
244 fnid = forumpost_head_rid2(zForumPost);
245 if( fnid>0 ) zTarget = rid_to_uuid(fnid);
246 @ DEBUG: fnid=%d(fnid) zForumPost=%h(zForumPost) zUUID=%s(zUUID)<br>
247 }else if( zPage ){
248 if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
249 zTarget = zPage;
250 }else if( zTkt ){
251 if( g.perm.RdTkt==0 ){ login_needed(g.anon.RdTkt); return; }
252 zTarget = zTkt;
@@ -375,27 +391,27 @@
391 const char *zTechNote = P("technote");
392 const char *zFrom = P("from");
393 const char *aContent = P("f");
394 const char *zName = PD("f:filename","unknown");
395 const char *zTarget;
396 char * zTo = 0;
397 char *zTargetType;
398 char *zExtraFree = 0;
399 int szContent = atoi(PD("f:bytes","0"));
400 int goodCaptcha = 1;
401 int szLimit = 0;
402
403 if( zFrom==0 ) zFrom = mprintf("%R/home");
404 if( P("cancel") ) cgi_redirect(zFrom);
405 if( (!!zPage + !!zTkt + !!zTechNote + !!zForumPost)!=1 ){
 
406 fossil_fatal("Requires exactly one one: page=X, tkt=X, forumpost=X, or technote=X");
407 }
408 login_check_credentials();
409 szLimit = db_get_int("attachment-size-limit", 0);
410 if( szContent<0 || (szLimit && szContent>szLimit) ){
411 fossil_fatal("Attachment %s is too large. Limit is %d bytes.", zName,
412 szLimit ? szLimit : 0x7fffffff);
413 }
414 if( zForumPost ){
415 int fpid;
416 if( g.perm.AttachForum==0 ){
417 login_needed(g.anon.AttachForum);
@@ -402,14 +418,19 @@
418 return;
419 }
420 fpid = forumpost_head_rid2(zForumPost);
421 if( fpid<=0 ){
422 fossil_fatal("Invalid forum post ID: %h", zForumPost);
423 }else if( !g.perm.Admin && !forumpost_is_owner(fpid, 0) ){
424 fossil_fatal("Only admins can attach files to other users' "
425 "forum posts.");
426 }
427 zTarget = zExtraFree = rid_to_uuid(fpid);
428 zTargetType = mprintf("Forum post <a href=\"%R/forumpost/%S\">%h</a>",
429 zTarget, zForumPost);
430 zTo = mprintf("%R/attachview?forumpost=%T&file=%T",
431 zTarget, zName);
432 }else if( zPage ){
433 if( g.perm.ApndWiki==0 || g.perm.Attach==0 ){
434 login_needed(g.anon.ApndWiki && g.anon.Attach);
435 return;
436 }
@@ -452,11 +473,11 @@
473 int needModerator = (zForumPost!=0 && forum_need_moderation()) ||
474 (zTkt!=0 && ticket_need_moderation(0)) ||
475 (zPage!=0 && wiki_need_moderation(0));
476 const char *zComment = PD("comment", "");
477 attach_commit(zName, zTarget, aContent, szContent, needModerator, zComment);
478 cgi_redirect(zTo ? zTo : zFrom);
479 }
480 style_set_current_feature("attach");
481 style_header("Add Attachment");
482 if( !goodCaptcha ){
483 @ <p class="generalError">Error: Incorrect security code.</p>
@@ -512,11 +533,11 @@
533 const char *zModAction; /* Moderation action or NULL */
534 int isModerator; /* TRUE if user is the moderator */
535 const char *zMime; /* MIME Type */
536 Blob attach; /* Content of the attachment */
537 int fShowContent = 0;
538 int bUserIsOwner = 0; /* True if pAttach->zUser is login_name() */
539 int showDelMenu = 0;
540 const char *zLn = P("ln");
541
542 login_check_credentials();
543 if( !g.perm.RdTkt && !g.perm.RdWiki ){
@@ -572,10 +593,14 @@
593 char *zNewDate;
594 Blob manifest;
595 Blob cksum;
596 const char *zFile = zName;
597
598 if( !g.perm.Admin && !bUserIsOwner ){
599 fossil_fatal("Only admins can delete other users' attachments from "
600 "forum posts.");
601 }
602 db_begin_transaction();
603 blob_zero(&manifest);
604 for(i=n=0; zFile[i]; i++){
605 if( zFile[i]=='/' || zFile[i]=='\\' ) n = i;
606 }
607
+14 -2
--- src/forum.c
+++ src/forum.c
@@ -112,10 +112,22 @@
112112
return fpid>0
113113
? forumpost_head_rid(fpid)
114114
: 0;
115115
}
116116
117
+/*
118
+** Given a forum post RID and user name, returns true if zUserName
119
+** matches the event.(euser,user) field for a formpost entry with the
120
+** matching RID. Returns false if no match is found. If zUserName is
121
+** 0 then login_name() is used.
122
+*/
123
+int forumpost_is_owner(int rid, const char *zUserName){
124
+ return db_int(0, "SELECT 1 FROM event "
125
+ "WHERE type='f' AND objid=%d "
126
+ "AND coalesce(euser,user)=%Q",
127
+ rid, zUserName ? zUserName : login_name());
128
+}
117129
118130
/*
119131
** Returns true if p, or any parent of p, has a non-zero iClosed
120132
** value. Returns 0 if !p. For an edited chain of post, the tag is
121133
** checked on the pEditHead entry, to simplify subsequent unlocking of
@@ -1828,12 +1840,12 @@
18281840
** default is just "Forum". But in some setups, admins might want to
18291841
** change it to "Developer Forum" or "User Forum" or whatever other name
18301842
** seems more appropriate for the particular usage.
18311843
**
18321844
** SETTING: attachment-size-limit width=16
1833
-** The maximum number of bytes for an attachment. The default is unlimited
1834
-** but a limit may be imposed by the web server or proxy.
1845
+** The maximum number of bytes for an attachment. The default (or 0) is
1846
+** unlimited but a limit may be imposed by the web server or a proxy.
18351847
*/
18361848
18371849
/*
18381850
** WEBPAGE: setup_forum
18391851
**
18401852
--- src/forum.c
+++ src/forum.c
@@ -112,10 +112,22 @@
112 return fpid>0
113 ? forumpost_head_rid(fpid)
114 : 0;
115 }
116
 
 
 
 
 
 
 
 
 
 
 
 
117
118 /*
119 ** Returns true if p, or any parent of p, has a non-zero iClosed
120 ** value. Returns 0 if !p. For an edited chain of post, the tag is
121 ** checked on the pEditHead entry, to simplify subsequent unlocking of
@@ -1828,12 +1840,12 @@
1828 ** default is just "Forum". But in some setups, admins might want to
1829 ** change it to "Developer Forum" or "User Forum" or whatever other name
1830 ** seems more appropriate for the particular usage.
1831 **
1832 ** SETTING: attachment-size-limit width=16
1833 ** The maximum number of bytes for an attachment. The default is unlimited
1834 ** but a limit may be imposed by the web server or proxy.
1835 */
1836
1837 /*
1838 ** WEBPAGE: setup_forum
1839 **
1840
--- src/forum.c
+++ src/forum.c
@@ -112,10 +112,22 @@
112 return fpid>0
113 ? forumpost_head_rid(fpid)
114 : 0;
115 }
116
117 /*
118 ** Given a forum post RID and user name, returns true if zUserName
119 ** matches the event.(euser,user) field for a formpost entry with the
120 ** matching RID. Returns false if no match is found. If zUserName is
121 ** 0 then login_name() is used.
122 */
123 int forumpost_is_owner(int rid, const char *zUserName){
124 return db_int(0, "SELECT 1 FROM event "
125 "WHERE type='f' AND objid=%d "
126 "AND coalesce(euser,user)=%Q",
127 rid, zUserName ? zUserName : login_name());
128 }
129
130 /*
131 ** Returns true if p, or any parent of p, has a non-zero iClosed
132 ** value. Returns 0 if !p. For an edited chain of post, the tag is
133 ** checked on the pEditHead entry, to simplify subsequent unlocking of
@@ -1828,12 +1840,12 @@
1840 ** default is just "Forum". But in some setups, admins might want to
1841 ** change it to "Developer Forum" or "User Forum" or whatever other name
1842 ** seems more appropriate for the particular usage.
1843 **
1844 ** SETTING: attachment-size-limit width=16
1845 ** The maximum number of bytes for an attachment. The default (or 0) is
1846 ** unlimited but a limit may be imposed by the web server or a proxy.
1847 */
1848
1849 /*
1850 ** WEBPAGE: setup_forum
1851 **
1852
--- www/changes.wiki
+++ www/changes.wiki
@@ -14,10 +14,13 @@
1414
the unmanaged file, even if that unmanaged file is read-only.
1515
<li> Improve the default prompts used by the
1616
"[/help/sqlite3|fossil sql]" command.
1717
<li> The captcha now uses light-gray boxes as the background, instead of
1818
spaces, to work around width inconsistencies in some fonts.
19
+ <li> Add the "[/help/attachment-size-limit|attachment-size-limit]" setting
20
+ to limit the size of file attachments to wiki pages, tech notes, and
21
+ tickets.
1922
</ol>
2023
2124
<h2 id='v2_28'>Changes for version 2.28 (2026-03-11)</h2><ol>
2225
<li> Improvements to [./antibot.wiki|anti-robot defenses]:<ol type="a">
2326
<li> The default configuration now allows robots to download any tarball
2427
--- www/changes.wiki
+++ www/changes.wiki
@@ -14,10 +14,13 @@
14 the unmanaged file, even if that unmanaged file is read-only.
15 <li> Improve the default prompts used by the
16 "[/help/sqlite3|fossil sql]" command.
17 <li> The captcha now uses light-gray boxes as the background, instead of
18 spaces, to work around width inconsistencies in some fonts.
 
 
 
19 </ol>
20
21 <h2 id='v2_28'>Changes for version 2.28 (2026-03-11)</h2><ol>
22 <li> Improvements to [./antibot.wiki|anti-robot defenses]:<ol type="a">
23 <li> The default configuration now allows robots to download any tarball
24
--- www/changes.wiki
+++ www/changes.wiki
@@ -14,10 +14,13 @@
14 the unmanaged file, even if that unmanaged file is read-only.
15 <li> Improve the default prompts used by the
16 "[/help/sqlite3|fossil sql]" command.
17 <li> The captcha now uses light-gray boxes as the background, instead of
18 spaces, to work around width inconsistencies in some fonts.
19 <li> Add the "[/help/attachment-size-limit|attachment-size-limit]" setting
20 to limit the size of file attachments to wiki pages, tech notes, and
21 tickets.
22 </ol>
23
24 <h2 id='v2_28'>Changes for version 2.28 (2026-03-11)</h2><ol>
25 <li> Improvements to [./antibot.wiki|anti-robot defenses]:<ol type="a">
26 <li> The default configuration now allows robots to download any tarball
27

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button