Fossil SCM

Add some formatting flags to attachment_list() so it can optionally show each download link's size. This adds an ugly extra space which still needs to be eliminated. Fix the attachment-target-type-dependent URL flag being passed to /attachdownload links (was previously always page=X, regardless of the attachment type).

stephan 2026-05-22 22:26 UTC forum-attachments
Commit fbab27b0b742ac5e4c73116c562c5ab6ab11ca6ef779d59714ccedfc063dc4b4
2 files changed +35 -6 +1 -1
+35 -6
--- src/attach.c
+++ src/attach.c
@@ -741,23 +741,35 @@
741741
manifest_destroy(pAttach);
742742
blob_reset(&attach);
743743
style_finish_page();
744744
}
745745
746
+#if INTERFACE
747
+/*
748
+** Flags for use with attachment_list(). ATTACHLIST_HRULE_ABOVE
749
+** must have a value of 1 for historical call compatibility.
750
+*/
751
+#define ATTACHLIST_HRULE_ABOVE 0x01 /* Insert <hr> above header. */
752
+#define ATTACHLIST_TARGET_BLANK 0x02 /* use target=_blank for links */
753
+#define ATTACHLIST_SIZE 0x04 /* add size */
754
+#endif
755
+
746756
/*
747757
** Output HTML to show a list of attachments.
748758
*/
749759
void attachment_list(
750760
const char *zTarget, /* Object that things are attached to */
751761
const char *zHeader, /* Header to display with attachments */
752
- int fHorizontalRule /* Insert <hr> separator above header */
762
+ int flags /* ATTACHLIST_... flags */
753763
){
754764
int cnt = 0;
765
+ const char * zLinkTgt = (ATTACHLIST_TARGET_BLANK & flags)
766
+ ? " target=\"_blank\"" : "";
755767
Stmt q;
756768
db_prepare(&q,
757769
"SELECT datetime(mtime,toLocal()), filename, user,"
758
- " (SELECT uuid FROM blob WHERE rid=attachid), src"
770
+ " (SELECT uuid FROM blob WHERE rid=attachid), src, target"
759771
" FROM attachment"
760772
" WHERE isLatest AND src!='' AND target=%Q"
761773
" ORDER BY mtime DESC",
762774
zTarget
763775
);
@@ -765,26 +777,43 @@
765777
const char *zDate = db_column_text(&q, 0);
766778
const char *zFile = db_column_text(&q, 1);
767779
const char *zUser = db_column_text(&q, 2);
768780
const char *zUuid = db_column_text(&q, 3);
769781
const char *zSrc = db_column_text(&q, 4);
782
+ const char *zTarget = db_column_text(&q, 5);
770783
const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
784
+ const char *zTypeArg = 0; /* URL arg name for /attachdownload */
771785
if( cnt==0 ){
772786
@ <section class='attachlist'>
773
- if( fHorizontalRule ){
787
+ if( flags & ATTACHLIST_HRULE_ABOVE ){
774788
@ <hr>
775789
}
776790
@ %s(zHeader)
777791
@ <ul>
778792
}
779793
cnt++;
794
+ switch( attachment_target_type(zTarget) ){
795
+ case CFTYPE_TICKET: zTypeArg = "tkt"; break;
796
+ case CFTYPE_FORUM: zTypeArg = "forumpost"; break;
797
+ case CFTYPE_EVENT: zTypeArg = "event"; break;
798
+ case CFTYPE_WIKI:
799
+ default: zTypeArg = "page"; break;
800
+ }
780801
@ <li>
781
- @ %z(href("%R/artifact/%!S",zSrc))%h(zFile)</a>
782
- @ [<a href="%R/attachdownload/%t(zFile)?page=%t(zTarget)&file=%t(zFile)">download</a>]
802
+ @ <a href="%R/artifact/%!S(zSrc)"%s(zLinkTgt)>%h(zFile)</a>
803
+ @ [<a href="%R/attachdownload/%t(zFile)?%s(zTypeArg)=%t(zTarget)&file=%t(zFile)" \
804
+ @ %s(zLinkTgt)>download</a>
805
+ if( flags & ATTACHLIST_SIZE ){
806
+ /* FIXME: this block causes us to interupt the @ lines and
807
+ ** introduces an extra space before the closing ']'. */
808
+ const int sz = db_int(0,"SELECT size FROM blob WHERE uuid=%Q", zSrc);
809
+ @ %d(sz) bytes
810
+ }
811
+ @ ]
783812
@ added by %h(zDispUser) on
784813
hyperlink_to_date(zDate, ".");
785
- @ [%z(href("%R/ainfo/%!S",zUuid))details</a>]
814
+ @ [<a href="%R/ainfo/%!S(zUuid)"%s(zLinkTgt)>details</a>]
786815
@ </li>
787816
}
788817
if( cnt ){
789818
@ </ul>
790819
@ </section>
791820
--- src/attach.c
+++ src/attach.c
@@ -741,23 +741,35 @@
741 manifest_destroy(pAttach);
742 blob_reset(&attach);
743 style_finish_page();
744 }
745
 
 
 
 
 
 
 
 
 
 
746 /*
747 ** Output HTML to show a list of attachments.
748 */
749 void attachment_list(
750 const char *zTarget, /* Object that things are attached to */
751 const char *zHeader, /* Header to display with attachments */
752 int fHorizontalRule /* Insert <hr> separator above header */
753 ){
754 int cnt = 0;
 
 
755 Stmt q;
756 db_prepare(&q,
757 "SELECT datetime(mtime,toLocal()), filename, user,"
758 " (SELECT uuid FROM blob WHERE rid=attachid), src"
759 " FROM attachment"
760 " WHERE isLatest AND src!='' AND target=%Q"
761 " ORDER BY mtime DESC",
762 zTarget
763 );
@@ -765,26 +777,43 @@
765 const char *zDate = db_column_text(&q, 0);
766 const char *zFile = db_column_text(&q, 1);
767 const char *zUser = db_column_text(&q, 2);
768 const char *zUuid = db_column_text(&q, 3);
769 const char *zSrc = db_column_text(&q, 4);
 
770 const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
 
771 if( cnt==0 ){
772 @ <section class='attachlist'>
773 if( fHorizontalRule ){
774 @ <hr>
775 }
776 @ %s(zHeader)
777 @ <ul>
778 }
779 cnt++;
 
 
 
 
 
 
 
780 @ <li>
781 @ %z(href("%R/artifact/%!S",zSrc))%h(zFile)</a>
782 @ [<a href="%R/attachdownload/%t(zFile)?page=%t(zTarget)&file=%t(zFile)">download</a>]
 
 
 
 
 
 
 
 
783 @ added by %h(zDispUser) on
784 hyperlink_to_date(zDate, ".");
785 @ [%z(href("%R/ainfo/%!S",zUuid))details</a>]
786 @ </li>
787 }
788 if( cnt ){
789 @ </ul>
790 @ </section>
791
--- src/attach.c
+++ src/attach.c
@@ -741,23 +741,35 @@
741 manifest_destroy(pAttach);
742 blob_reset(&attach);
743 style_finish_page();
744 }
745
746 #if INTERFACE
747 /*
748 ** Flags for use with attachment_list(). ATTACHLIST_HRULE_ABOVE
749 ** must have a value of 1 for historical call compatibility.
750 */
751 #define ATTACHLIST_HRULE_ABOVE 0x01 /* Insert <hr> above header. */
752 #define ATTACHLIST_TARGET_BLANK 0x02 /* use target=_blank for links */
753 #define ATTACHLIST_SIZE 0x04 /* add size */
754 #endif
755
756 /*
757 ** Output HTML to show a list of attachments.
758 */
759 void attachment_list(
760 const char *zTarget, /* Object that things are attached to */
761 const char *zHeader, /* Header to display with attachments */
762 int flags /* ATTACHLIST_... flags */
763 ){
764 int cnt = 0;
765 const char * zLinkTgt = (ATTACHLIST_TARGET_BLANK & flags)
766 ? " target=\"_blank\"" : "";
767 Stmt q;
768 db_prepare(&q,
769 "SELECT datetime(mtime,toLocal()), filename, user,"
770 " (SELECT uuid FROM blob WHERE rid=attachid), src, target"
771 " FROM attachment"
772 " WHERE isLatest AND src!='' AND target=%Q"
773 " ORDER BY mtime DESC",
774 zTarget
775 );
@@ -765,26 +777,43 @@
777 const char *zDate = db_column_text(&q, 0);
778 const char *zFile = db_column_text(&q, 1);
779 const char *zUser = db_column_text(&q, 2);
780 const char *zUuid = db_column_text(&q, 3);
781 const char *zSrc = db_column_text(&q, 4);
782 const char *zTarget = db_column_text(&q, 5);
783 const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
784 const char *zTypeArg = 0; /* URL arg name for /attachdownload */
785 if( cnt==0 ){
786 @ <section class='attachlist'>
787 if( flags & ATTACHLIST_HRULE_ABOVE ){
788 @ <hr>
789 }
790 @ %s(zHeader)
791 @ <ul>
792 }
793 cnt++;
794 switch( attachment_target_type(zTarget) ){
795 case CFTYPE_TICKET: zTypeArg = "tkt"; break;
796 case CFTYPE_FORUM: zTypeArg = "forumpost"; break;
797 case CFTYPE_EVENT: zTypeArg = "event"; break;
798 case CFTYPE_WIKI:
799 default: zTypeArg = "page"; break;
800 }
801 @ <li>
802 @ <a href="%R/artifact/%!S(zSrc)"%s(zLinkTgt)>%h(zFile)</a>
803 @ [<a href="%R/attachdownload/%t(zFile)?%s(zTypeArg)=%t(zTarget)&file=%t(zFile)" \
804 @ %s(zLinkTgt)>download</a>
805 if( flags & ATTACHLIST_SIZE ){
806 /* FIXME: this block causes us to interupt the @ lines and
807 ** introduces an extra space before the closing ']'. */
808 const int sz = db_int(0,"SELECT size FROM blob WHERE uuid=%Q", zSrc);
809 @ %d(sz) bytes
810 }
811 @ ]
812 @ added by %h(zDispUser) on
813 hyperlink_to_date(zDate, ".");
814 @ [<a href="%R/ainfo/%!S(zUuid)"%s(zLinkTgt)>details</a>]
815 @ </li>
816 }
817 if( cnt ){
818 @ </ul>
819 @ </section>
820
+1 -1
--- src/forum.c
+++ src/forum.c
@@ -780,11 +780,11 @@
780780
return p->zDisplayName;
781781
}
782782
783783
static void forum_render_attachment_list(ForumPost *p){
784784
if( p->pEditHead ) p = p->pEditHead;
785
- attachment_list(p->zUuid, "Attachments:", 1);
785
+ attachment_list(p->zUuid, "Attachments:", ATTACHLIST_SIZE);
786786
}
787787
788788
/*
789789
** Display a single post in a forum thread.
790790
*/
791791
--- src/forum.c
+++ src/forum.c
@@ -780,11 +780,11 @@
780 return p->zDisplayName;
781 }
782
783 static void forum_render_attachment_list(ForumPost *p){
784 if( p->pEditHead ) p = p->pEditHead;
785 attachment_list(p->zUuid, "Attachments:", 1);
786 }
787
788 /*
789 ** Display a single post in a forum thread.
790 */
791
--- src/forum.c
+++ src/forum.c
@@ -780,11 +780,11 @@
780 return p->zDisplayName;
781 }
782
783 static void forum_render_attachment_list(ForumPost *p){
784 if( p->pEditHead ) p = p->pEditHead;
785 attachment_list(p->zUuid, "Attachments:", ATTACHLIST_SIZE);
786 }
787
788 /*
789 ** Display a single post in a forum thread.
790 */
791

Keyboard Shortcuts

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