@@ -22,41 +22,188 @@
22 22 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#include <assert.h>
23 23 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
24 24 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/*
25 25 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** Given a presumedly legal attachment target name, this guesses the
26 26 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** target type and returns one of CFTYPE_FORUM, CFTYPE_WIKI,
27 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** CFTYPE_TICKET, or CFTYPE_EVENT. Returns 0 if it cannot
28 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** distinguish the target type.
27 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** CFTYPE_TICKET, or CFTYPE_EVENT. Returns 0 if it cannot distinguish
28 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** the target type.
29 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
30 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** zTarget is an attachment target name: wiki page name, tech-note ID,
31 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** ticket ID, or forumpost hash.
32 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
33 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** If bFull is true then it requires zTarget to be a full ID for
34 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** tech-notes and tickets, otherwise such IDs may be prefixes. If
35 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** bFull is false then tech-notes and tickets will perform a prefix
36 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** match, but it is up to the caller to provide enough of a prefix to
37 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** rule out ambiguity[^1]. When called repeatedly, this routine can
38 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** run a bit faster and more efficiently if bFull is true, but some
39 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** historical use cases call for prefix matches.
40 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
41 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Wiki page names always require an exact match.
42 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
43 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Forum posts are a special case:
44 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
45 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** - They ignore the bFull flag. That is, they will do prefix matches
46 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** but will not match an ambiguous prefix.
47 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
48 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** - It is up to the caller to, if needed, resolve zTarget using
49 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** forumpost_head_rid2() to resolve the RID of the earliest version
50 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** of the post, as that is the only one which attachments should
51 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** target.
29 52 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
**
30 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** In the case of CFTYPE_FORUM, it is up to the caller to ensure that,
31 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** if needed, they resolve zTarget using forumpost_head_rid2() so that
32 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** they get the RID of the earliest version of the post, as that is
33 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** the only one which attachments should target.
53 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** [^1]: Historically (from the perspective of 2026-06) attachment
54 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** target lookups have used GLOB prefix matching but have taken no
55 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** measures to ensure that the prefix is unambiguous. Ergo we do the
56 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** same here. It is assumed that the caller passes enough of a prefix
57 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** to be unambiguous and that's worked out fine so far.
34 58 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
*/
35 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- int attachment_target_type(const char *zTarget){
36 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- static Stmt q = empty_Stmt_m;
37 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- int rc = 0;
38 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if( forumpost_head_rid2(zTarget)>0 ){
59 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int attachment_target_type(const char *zTarget, int bFull){
60 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( !zTarget || !zTarget[0] || strlen(zTarget)>64/*vs. abuse*/ ){
61 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return 0;
62 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
63 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( symbolic_name_to_rid(zTarget, "f")>0 ){
64 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* Check forum posts first because they are the most likely target
65 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** as of 2026. We should arguably use something more
66 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** specialized/efficient than symbolic_name_to_rid(). */
39 67 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return CFTYPE_FORUM;
40 68 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
41 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if( !q.pStmt ){
42 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- db_static_prepare(
43 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- &q,
69 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( bFull ){
70 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ static Stmt q = empty_Stmt_m;
71 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int rc = 0;
72 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( !q.pStmt ){
73 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_static_prepare(
74 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ &q,
75 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "SELECT CASE "
76 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* Ordered by presumed likelihood of attachments. */
77 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WHEN (SELECT 1 FROM tag WHERE tagname='tkt-'||:tgt) THEN %d\n"
78 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WHEN (SELECT 1 FROM tag WHERE tagname='wiki-'||:tgt) THEN %d\n"
79 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WHEN (SELECT 1 FROM tag WHERE tagname='event-'||:tgt) THEN %d\n"
80 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "ELSE 0 END",
81 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ CFTYPE_TICKET, CFTYPE_WIKI, CFTYPE_EVENT
82 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ );
83 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
84 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_bind_text(&q, ":tgt", zTarget);
85 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( SQLITE_ROW==db_step(&q) ){
86 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ rc = db_column_int(&q, 0);
87 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
88 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_reset(&q);
89 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return rc;
90 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else{
91 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return db_int(
92 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ 0,
44 93 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"SELECT CASE "
45 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "WHEN 'tkt-'||:tgt IN (SELECT tagname FROM tag) THEN %d "
46 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "WHEN 'event-'||:tgt IN (SELECT tagname FROM tag) THEN %d "
47 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "WHEN 'wiki-'||:tgt IN (SELECT tagname FROM tag) THEN %d "
94 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WHEN (SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*')"
95 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " THEN %d\n"
96 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WHEN (SELECT tagid FROM tag WHERE tagname='wiki-%q')"
97 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " THEN %d\n"
98 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WHEN (SELECT tagid FROM tag WHERE tagname GLOB 'event-%q*')"
99 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " THEN %d\n"
48 100 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"ELSE 0 END",
49 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- CFTYPE_TICKET, CFTYPE_EVENT, CFTYPE_WIKI
101 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget, CFTYPE_TICKET,
102 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget, CFTYPE_WIKI,
103 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget, CFTYPE_EVENT
50 104 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
);
51 105 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
52 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- db_bind_text(&q, ":tgt", zTarget);
53 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if( SQLITE_ROW==db_step(&q) ){
54 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- rc = db_column_int(&q, 0);
106 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
107 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
108 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
109 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Given an attachment target name, returns the target's blob.rid.
110 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** zTarget and bFull work as described for attachment_target_type().
111 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
112 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** For forum posts, this always returns the RID of the first version
113 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** of the post, as attachments should always target that instance.
114 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
115 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int attachment_target_rid(const char *zTarget, int bFull){
116 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int rid = 0;
117 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const int eType = attachment_target_type(zTarget, bFull);
118 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ switch(eType){
119 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_TICKET:
120 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_EVENT:{
121 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zTagPrefix = (eType==CFTYPE_EVENT) ? "event" : "tkt";
122 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ rid = db_int(
123 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ 0, "SELECT b.rid FROM blob b, tag t, tagxref x\n"
124 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WHERE tagname %s '%s-%q%s'\n"
125 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "AND x.tagtype>0\n"
126 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "AND x.tagid=t.tagid\n"
127 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "AND x.rid=b.rid\n"
128 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "ORDER BY x.mtime DESC",
129 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ bFull ? "=" : "GLOB"/*safe-for-%s*/,
130 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTagPrefix/*safe-for-%s*/,
131 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget,
132 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ bFull ? "" : "*"/*safe-for-%s*/
133 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ );
134 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
135 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
136 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_FORUM:
137 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ rid = db_int(
138 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ 0, "SELECT f.fpid FROM forumpost f, blob b\n"
139 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WHERE f.fpid=b.rid\n"
140 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "AND b.uuid %s '%q%s'",
141 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ bFull ? "=" : "GLOB"/*safe-for-%s*/,
142 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget,
143 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ bFull ? "" : "*"/*safe-for-%s*/
144 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ );
145 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( rid>0 ){
146 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ rid = forumpost_head_rid(rid);
147 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
148 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
149 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_WIKI:
150 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ rid = db_int(
151 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ 0, "SELECT b.rid FROM blob b, tag t, tagxref x\n"
152 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WHERE tagname='wiki-%q'\n"
153 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "AND x.tagtype>0\n"
154 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "AND x.tagid=t.tagid\n"
155 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "AND x.rid=b.rid\n"
156 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "ORDER BY x.mtime DESC",
157 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget
158 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ );
159 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
160 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ default:
161 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
162 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
163 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return rid;
164 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
165 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
166 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
167 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** For a given aritfact ID and type (from the CFTYPE_xyz enum),
168 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** returns true if the current user could hypothetically apply and
169 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** attachment to it, else returns 0.
170 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
171 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** The rid is currently only relevant when eArtifactType is
172 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** CFTYPE_FORUM. For forum posts, it checks precisely the rid given,
173 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** not the head RID, to keep non-admins from attaching files to
174 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** threads which have since been taken over by another user (this
175 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** happens when an admin edits another user's post).
176 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
177 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int attach_user_may(int rid, int eArtifactType){
178 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( g.perm.Admin ) return 1;
179 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( !login_is_individual() ) return 0;
180 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ switch(eArtifactType){
181 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_FORUM:
182 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return g.perm.AttachForum && forumpost_is_owner(rid, 0);
183 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_WIKI:
184 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return g.perm.ApndWiki && g.perm.Attach;
185 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_TICKET:
186 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return g.perm.ApndTkt && g.perm.Attach;
187 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_EVENT:
188 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return g.perm.Write && g.perm.ApndWiki && g.perm.Attach;
189 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ default:
190 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return 0;
55 191 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
56 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- db_reset(&q);
57 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- return rc;
192 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
193 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
194 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
195 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Emits a single-button FORM which invokes
196 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** /attachadd with target=$zTarget.
197 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
198 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ void attach_render_attachadd_button(const char *zTarget){
199 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* This could be changed from POST to GET, and arguably should so
200 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** that the target=X part becomes part of the resulting URL. */
201 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <form method="post" action="%R/attachadd">\
202 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <input type="hidden" name="target" value="%T(zTarget)">\
203 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <input type="submit" value="Attach...">
204 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ </form>\
58 205 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
59 206 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
60 207 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/*
61 208 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** WEBPAGE: attachlist
62 209 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** List attachments.
@@ -69,20 +216,21 @@
69 216 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** At most one of technote=, tkt=, forumpost=, or page= may be supplied.
70 217 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
**
71 218 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** If none are given, all attachments are listed. If one is given, only
72 219 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** attachments for the designated technote, ticket or wiki page are shown.
73 220 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
**
74 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** HASH may be just a prefix of the relevant technical note or ticket
75 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** artifact hash, in which case all attachments of all technical notes or
76 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** tickets with the prefix will be listed. Forum posts, on the other hand,
77 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** require a unique hash prefix.
221 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** HASH may be just a prefix of the relevant forum post, technical
222 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** note, or ticket artifact hash, in which case all attachments of all
223 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** technical notes or tickets with the prefix will be listed. Forum
224 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** posts, on the other hand, require a unique hash or hash prefix.
78 225 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
*/
79 226 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
void attachlist_page(void){
80 227 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zPage = P("page");
81 228 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zTkt = P("tkt");
82 229 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zTechNote = P("technote");
83 230 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zForumPost = P("forumpost");
231 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char *zLink = 0;
84 232 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
Blob sql;
85 233 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
Stmt q;
86 234 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
87 235 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( zPage && zTkt ) zTkt = 0;
88 236 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
login_check_credentials();
@@ -102,32 +250,47 @@
102 250 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( fnid<=0 ){
103 251 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
webpage_error("Invalid forum post ID: %h", zForumPost);
104 252 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
105 253 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_append_sql(&sql, " WHERE target="
106 254 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"(SELECT uuid FROM blob WHERE rid=%d)", fnid);
255 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zLink = mprintf("forum post <a href='%R/forumpost/%t'>%#h</a>",
256 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zForumPost, hash_digits(0), zForumPost);
107 257 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}else if( zPage ){
108 258 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
109 259 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
style_header("Attachments To Wiki page %h", zPage);
110 260 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_append_sql(&sql, " WHERE target=%Q", zPage);
261 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zLink = mprintf("wiki page <a href='%R/wiki?name=%t'>%h</a>",
262 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zPage, zPage);
111 263 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}else if( zTkt ){
112 264 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( g.perm.RdTkt==0 ){ login_needed(g.anon.RdTkt); return; }
113 265 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
style_header("Attachments To Ticket %S", zTkt);
114 266 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_append_sql(&sql, " WHERE target GLOB '%q*'", zTkt);
267 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zLink = mprintf("ticket <a href='%R/tktview?name=%t'>%#h</a>",
268 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTkt, hash_digits(0), zTkt);
115 269 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}else if( zTechNote ){
116 270 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
117 271 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
style_header("Attachments To Tech Note %S", zTechNote);
118 272 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_append_sql(&sql, " WHERE target GLOB '%q*'",
119 273 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zTechNote);
274 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zLink = mprintf("tech-note <a href='%R/technote?name=%t'>%#h</a>",
275 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTechNote, hash_digits(0), zTechNote);
120 276 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}else{
121 277 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( g.perm.RdTkt==0 && g.perm.RdWiki==0 ){
122 278 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
login_needed(g.anon.RdTkt || g.anon.RdWiki);
123 279 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return;
124 280 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
125 281 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
style_header("All Attachments");
126 282 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
127 283 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_append_sql(&sql, " ORDER BY mtime DESC");
128 284 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
db_prepare(&q, "%s", blob_sql_text(&sql));
285 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
286 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( zLink ){
287 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <h2>Attachments for %s(zLink)</h2>
288 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_free(zLink);
289 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zLink = 0;
290 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
291 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
129 292 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <ol>
130 293 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
while( db_step(&q)==SQLITE_ROW ){
131 294 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zDate;
132 295 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zSrc;
133 296 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zTarget;
@@ -137,10 +300,11 @@
137 300 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zUuid;
138 301 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zDispUser;
139 302 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const int attachid = db_column_int(&q, 7);
140 303 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
int type;
141 304 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
int i;
305 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int bDeleted;
142 306 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
char *zUrlTail = 0;
143 307 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
144 308 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( moderation_pending(attachid)
145 309 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
&& !moderation_user_could(attachid, 1, 0) ){
146 310 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/* Elide entries which are currently pending moderation unless
@@ -160,11 +324,12 @@
160 324 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( zFilename[i]=='/' && zFilename[i+1]!=0 ){
161 325 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zFilename = &zFilename[i+1];
162 326 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
i = -1;
163 327 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
164 328 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
165 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- type = attachment_target_type(zTarget);
329 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ bDeleted = 0==zSrc || 0==zSrc[0];
330 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ type = attachment_target_type(zTarget, 1);
166 331 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
switch( type ){
167 332 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
case CFTYPE_TICKET:
168 333 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
169 334 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
break;
170 335 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
case CFTYPE_EVENT:
@@ -176,20 +341,32 @@
176 341 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
case CFTYPE_WIKI:
177 342 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zUrlTail = mprintf("page=%t&file=%t", zTarget, zFilename);
178 343 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
break;
179 344 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
180 345 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <li><p>
181 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ Attachment %z(href("%R/ainfo/%!S",zUuid))%S(zUuid)</a>
346 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( bDeleted ){
347 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <s>\
348 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
349 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ Attachment %z(href("%R/ainfo/%!S",zUuid))%S(zUuid)</a>\
182 350 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
moderation_pending_www(attachid);
183 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ <br><a href="%R/attachview?%s(zUrlTail)">%h(zFilename)</a>
184 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ [<a href="%R/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]<br>
351 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <br>\
352 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <a href="%R/attachview?%s(zUrlTail)">%h(zFilename)</a>
353 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ [<a href="%R/attachdownload/%t(zFilename)?%s(zUrlTail)">download</a>]\
354 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( bDeleted ){
355 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ </s>
356 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
357 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <br>
185 358 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( zComment ) while( fossil_isspace(zComment[0]) ) zComment++;
186 359 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( zComment && zComment[0] ){
187 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ %!W(zComment)<br>
360 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* FIXME (2026-06-05): Honor the N-card (comment mimetype). %W
361 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** (historically used here) assumes fossil-wiki and the
362 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** fileformat.wiki doc has always claimed that it defaults to
363 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** text/plain. /ainfo assumes it is plain text. */
364 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ %h(zComment)<br>
188 365 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
189 366 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( zForumPost==0 && zPage==0 && zTkt==0 && zTechNote==0 ){
190 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if( zSrc==0 || zSrc[0]==0 ){
367 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( bDeleted ){
191 368 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zSrc = "Deleted from";
192 369 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}else {
193 370 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zSrc = "Added to";
194 371 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
195 372 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
switch( type ){
@@ -362,41 +539,81 @@
362 539 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
Manifest *pManifest;
363 540 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
364 541 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
db_begin_transaction();
365 542 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_init(&content, aContent, szContent);
366 543 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
pManifest = manifest_parse(&content, 0, 0);
544 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ addCompress = pManifest!=0;
367 545 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
manifest_destroy(pManifest);
368 546 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_init(&content, aContent, szContent);
369 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if( pManifest ){
547 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( addCompress ){
370 548 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_compress(&content, &content);
371 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- addCompress = 1;
372 549 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
373 550 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
rid = content_put_ex(&content, 0, 0, 0, needModerator);
374 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- zUUID = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
551 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zUUID = rid_to_uuid(rid);
375 552 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_zero(&manifest);
376 553 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
for(i=n=0; zName[i]; i++){
377 554 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( zName[i]=='/' || zName[i]=='\\' ) n = i+1;
378 555 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
379 556 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zName += n;
380 557 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( zName[0]==0 ) zName = "unknown";
381 558 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_appendf(&manifest, "A %F%s %F %s\n",
382 559 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zName, addCompress ? ".gz" : "", zTarget, zUUID);
383 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- while( fossil_isspace(zComment[0]) ) zComment++;
384 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- n = strlen(zComment);
385 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- while( n>0 && fossil_isspace(zComment[n-1]) ){ n--; }
386 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if( n>0 ){
387 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- blob_appendf(&manifest, "C %#F\n", n, zComment);
560 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( zComment!=0 && zComment[0]!=0 ){
561 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ while( fossil_isspace(zComment[0]) ) zComment++;
562 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ n = strlen(zComment);
563 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ while( n>0 && fossil_isspace(zComment[n-1]) ){ n--; }
564 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( n>0 ){
565 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_appendf(&manifest, "C %#F\n", n, zComment);
566 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
388 567 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
389 568 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zDate = date_in_standard_format("now");
390 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- blob_appendf(&manifest, "D %s\n", zDate);
569 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_appendf(&manifest, "D %z\n", zDate);
391 570 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_appendf(&manifest, "U %F\n", login_name());
392 571 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
md5sum_blob(&manifest, &cksum);
393 572 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_appendf(&manifest, "Z %b\n", &cksum);
394 573 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
attach_put(&manifest, rid, needModerator);
395 574 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
assert( blob_is_reset(&manifest) );
396 575 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
db_end_transaction(0);
397 576 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
577 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
578 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
579 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Renders the "legacy" (static) /attachadd form. One of the first
580 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** four arguments must be non-NULL and the other three must be NULL.
581 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** zComment may be NULL, as may zFrom. See the call sites for more
582 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** context.
583 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
584 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ static void attach_render_legacy_form(const char *zForumPost,
585 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zTechNote,
586 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zTicket,
587 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zWikiPage,
588 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zComment,
589 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zFrom){
590 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ form_begin("enctype='multipart/form-data' id='attachadd-legacy-form'",
591 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "%R/attachadd");
592 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <div>\
593 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ File to Attach:
594 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <input type="file" name="f" size="60"><br>
595 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ Description:<br>
596 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <textarea name="comment" cols="80" rows="5" wrap="virtual"\
597 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ >%h(zComment)</textarea><br>
598 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( zForumPost ){
599 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <input type="hidden" name="forumpost" value="%h(zForumPost)">\
600 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else if( zTicket ){
601 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <input type="hidden" name="tkt" value="%h(zTicket)">\
602 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else if( zTechNote ){
603 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <input type="hidden" name="technote" value="%h(zTechNote)">\
604 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else if( zWikiPage ){
605 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <input type="hidden" name="page" value="%h(zWikiPage)">\
606 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
607 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <input type="hidden" name="from" value="%h(zFrom)">\
608 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <input type="submit" name="ok" value="Add Attachment">\
609 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <input type="submit" name="cancel" value="Cancel">\
610 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ </div>
611 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ captcha_generate(0);
612 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ login_insert_csrf_secret();
613 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ </form>
614 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
398 615 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
399 616 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/*
400 617 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** WEBPAGE: attachadd
401 618 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** Add a new attachment.
402 619 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
**
@@ -404,33 +621,54 @@
404 621 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** page=WIKIPAGE
405 622 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** technote=HASH
406 623 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** forumpost=HASH
407 624 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** from=URL
408 625 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
**
626 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Adds a POSTed file attachment to the given target.
627 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
628 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Or the "version 2" interface:
629 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
630 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** target=ATTACHMENT_TARGET
631 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
632 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Behaves as documented for attachaddV2_page().
409 633 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
*/
410 634 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
void attachadd_page(void){
411 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- const char *zPage = P("page");
412 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- const char *zForumPost = P("forumpost");
413 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- const char *zTkt = P("tkt");
414 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- const char *zTechNote = P("technote");
415 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- const char *zFrom = P("from");
416 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- const char *aContent = P("f");
417 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- const char *zName = PD("f:filename","unknown");
418 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- const char *zComment = PD("comment", "");
635 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zPage;
636 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zForumPost;
637 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zTkt;
638 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zTechNote;
639 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *aContent;
640 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zName;
641 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zComment;
419 642 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zTarget;
420 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- char * zTo = 0;
643 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zFrom; /* Origin page - redirect here after saving */
644 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char *zTo = 0; /* Optionally redirect here after saving */
421 645 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
char *zTargetType = 0;
422 646 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
char *zExtraFree = 0;
423 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- int szContent = atoi(PD("f:bytes","0"));
647 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int szContent;
424 648 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
int goodCaptcha = 1;
425 649 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
int szLimit = 0;
426 650 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
651 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( P("target")!=0 ){
652 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ attachaddV2_page();
653 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return;
654 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
655 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zPage = P("page");
656 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zForumPost = P("forumpost");
657 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTkt = P("tkt");
658 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTechNote = P("technote");
659 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zFrom = P("from");
660 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ aContent = P("f");
661 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zName = PD("f:filename","unknown");
662 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zComment = PD("comment", "");
663 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ szContent = atoi(PD("f:bytes","0"));
664 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
427 665 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( zFrom==0 ) zFrom = mprintf("%R/home");
428 666 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( P("cancel") ) cgi_redirect(zFrom);
429 667 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( (!!zPage + !!zTkt + !!zTechNote + !!zForumPost)!=1 ){
430 668 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
webpage_error("Requires exactly one one: page=X, tkt=X, forumpost=X,"
431 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- " or technote=X");
669 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " technote=X, or target=X");
432 670 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
433 671 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
login_check_credentials();
434 672 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( zForumPost ){
435 673 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
int fpid;
436 674 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( g.perm.AttachForum==0 ){
@@ -445,26 +683,23 @@
445 683 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"forum posts.");
446 684 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
447 685 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zTarget = zExtraFree = rid_to_uuid(fpid);
448 686 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zTargetType = mprintf("Forum post <a href=\"%R/forumpost/%S\">%h</a>",
449 687 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zTarget, zForumPost);
450 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- zTo = 1
451 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ? mprintf("%R/forumpost/%S", zTarget)
452 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- : mprintf("%R/attachview?forumpost=%T&file=%T",
453 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- zTarget, zName)
454 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- /* Or we could return directly to the forum post. */;
688 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTo = zFrom ? 0 : mprintf("%R/forumpost/%S", zTarget);
455 689 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}else if( zPage ){
456 690 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( g.perm.ApndWiki==0 || g.perm.Attach==0 ){
457 691 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
login_needed(g.anon.ApndWiki && g.anon.Attach);
458 692 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return;
459 693 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
460 694 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( !db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'", zPage) ){
461 695 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
fossil_redirect_home();
462 696 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
463 697 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zTarget = zPage;
464 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- zTargetType = mprintf("Wiki Page <a href=\"%R/wiki?name=%h\">%h</a>",
698 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTargetType = mprintf("Wiki Page <a href=\"%R/wiki?name=%t\">%h</a>",
465 699 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zPage, zPage);
700 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTo = zFrom ? 0 : mprintf("%R/wiki?name=%T", zTarget);
466 701 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}else if ( zTechNote ){
467 702 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( g.perm.Write==0 || g.perm.ApndWiki==0 || g.perm.Attach==0 ){
468 703 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
login_needed(g.anon.Write && g.anon.ApndWiki && g.anon.Attach);
469 704 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return;
470 705 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
@@ -474,11 +709,11 @@
474 709 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( zTechNote==0) fossil_redirect_home();
475 710 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
476 711 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zTarget = zTechNote;
477 712 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zTargetType = mprintf("Tech Note <a href=\"%R/technote/%s\">%S</a>",
478 713 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zTechNote, zTechNote);
479 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
714 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTo = zFrom ? 0 : mprintf("%R/technote/%S", zTarget);
480 715 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}else{
481 716 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
assert( zTkt );
482 717 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( g.perm.ApndTkt==0 || g.perm.Attach==0 ){
483 718 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
login_needed(g.anon.ApndTkt && g.anon.Attach);
484 719 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return;
@@ -487,21 +722,25 @@
487 722 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zTkt = db_text(0, "SELECT substr(tagname,5) FROM tag"
488 723 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
" WHERE tagname GLOB 'tkt-%q*'", zTkt);
489 724 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( zTkt==0 ) fossil_redirect_home();
490 725 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
491 726 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zTarget = zTkt;
492 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- zTargetType = mprintf("Ticket <a href=\"%R/tktview/%s\">%S</a>",
727 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTargetType = mprintf("Ticket <a href=\"%R/tktview/%S\">%S</a>",
493 728 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zTkt, zTkt);
729 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTo = zFrom ? 0 : mprintf("%R/tktview/%S", zTarget);
494 730 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
495 731 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
szLimit = db_get_int("attachment-size-limit", 0);
496 732 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( szContent<0 || (szLimit && szContent>szLimit) ){
497 733 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/* This check must be done late so that zTargetType is set up. */
498 734 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <p class="generalError">Attachment %h(zName) is too large.
499 735 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <a href="%R/help/attachment-size-limit">Limit</a> is
500 736 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ %d(szLimit ? szLimit : 0x7fffffff) bytes</p>
501 737 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/* Fall through and render form. */
502 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- }else if( P("ok") && szContent>0 && (goodCaptcha = captcha_is_correct(0)) ){
738 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else if( P("ok")
739 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ && cgi_csrf_safe(2)
740 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ && szContent>0
741 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ && (goodCaptcha = captcha_is_correct(0)) ){
503 742 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
int needModerator = (zForumPost!=0 && forum_need_moderation()) ||
504 743 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
(zTkt!=0 && ticket_need_moderation(0)) ||
505 744 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
(zPage!=0 && wiki_need_moderation(0));
506 745 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
attach_commit(zName, zTarget, aContent, szContent, needModerator, zComment);
507 746 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
cgi_redirect(zTo ? zTo : zFrom);
@@ -511,35 +750,374 @@
511 750 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
style_header("Add Attachment");
512 751 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( !goodCaptcha ){
513 752 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <p class="generalError">Error: Incorrect security code.</p>
514 753 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
515 754 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <h2>Add Attachment To %s(zTargetType)</h2>
516 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- form_begin("enctype='multipart/form-data'", "%R/attachadd");
517 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ <div>
518 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ File to Attach:
519 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ <input type="file" name="f" size="60"><br>
520 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ Description:<br>
521 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ <textarea name="comment" cols="80" rows="5" wrap="virtual"\
522 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ >%h(zComment)</textarea><br>
523 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if( zForumPost ){
524 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ <input type="hidden" name="forumpost" value="%h(zTarget)">
525 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- }else if( zTkt ){
526 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ <input type="hidden" name="tkt" value="%h(zTkt)">
527 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- }else if( zTechNote ){
528 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ <input type="hidden" name="technote" value="%h(zTechNote)">
755 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ attach_render_legacy_form(zForumPost, zTechNote, zTkt, zPage,
756 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zComment, zFrom);
757 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ builtin_fossil_js_bundle_or("attach", NULL);
758 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ style_finish_page();
759 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_free(zTargetType);
760 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_free(zExtraFree);
761 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
762 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
763 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
764 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** WEBPAGE: attachadd_ajax_post hidden
765 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
766 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Used by attachadd V2 to handle attachments via POST requests with:
767 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
768 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** target=ATTACHMENT_TARGET
769 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** file1..fileN=FILE_OBJECTS
770 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** dryrun=0|1
771 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
772 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Each posted file in the set file1..fileN gets attached to the given
773 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** target, permissions permitting. If dryrun>0 then the change is
774 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** rolled back instead of committed. target=X must refer to a full
775 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** target ID, not a prefix.
776 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
777 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Responds with JSON: an empty object on success and
778 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** {error:"message"} on error. The on-success response structure is
779 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** subject to amendment.
780 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
781 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ void attachadd_ajax_post(void){
782 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zTarget;
783 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char *zExtraFree = 0;
784 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int eTgtType = 0;
785 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int bNeedsModeration = 0;
786 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int goodCaptcha = 1;
787 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int bRollback = 0; /* Roll back if true. */
788 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
789 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( ! ajax_route_bootstrap(0, 1) ){
790 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return;
791 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else if( !(goodCaptcha = captcha_is_correct(0)) ){
792 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ goto ajax_err_403;
793 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else if( !ajax_check_csrf(2) ){
794 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return;
795 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
796 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_begin_transaction();
797 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget = P("target");
798 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ eTgtType = attachment_target_type(zTarget, 1);
799 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ CX("{");
800 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ switch( eTgtType ){
801 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ default:
802 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case 0:
803 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ajax_route_error(400, "Invalid attachment target.");
804 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_rollback_transaction();
805 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return;
806 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_FORUM:{
807 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int fpid;
808 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( g.perm.AttachForum==0 ){
809 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ goto ajax_err_403;
810 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
811 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fpid = forumpost_head_rid2(zTarget);
812 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( fpid<=0 ){
813 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ goto ajax_err_404;
814 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else if( !g.perm.Admin && !forumpost_is_owner(fpid, 0) ){
815 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ajax_route_error(403, "Only admins can attach files to "
816 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "other users' forum posts.");
817 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_rollback_transaction();
818 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return;
819 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
820 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget = zExtraFree = rid_to_uuid(fpid);
821 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ bNeedsModeration = forum_need_moderation();
822 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
823 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
824 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_EVENT:{
825 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( g.perm.Write==0 || g.perm.ApndWiki==0 || g.perm.Attach==0 ){
826 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ goto ajax_err_403;
827 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
828 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( !db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'",
829 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget) ){
830 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget = zExtraFree =
831 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_text(0, "SELECT substr(tagname,7) FROM tag"
832 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " WHERE tagname GLOB 'event-%q*'", zTarget);
833 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( zTarget==0){
834 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ goto ajax_err_404;
835 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
836 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
837 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ bNeedsModeration = 0;
838 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
839 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
840 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_TICKET:{
841 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( g.perm.ApndTkt==0 || g.perm.Attach==0 ){
842 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ goto ajax_err_403;
843 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
844 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( !db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
845 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget) ){
846 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget = db_text(0, "SELECT substr(tagname,5) FROM tag"
847 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " WHERE tagname GLOB 'tkt-%q*'", zTarget);
848 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( zTarget==0 ){
849 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ goto ajax_err_404;
850 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
851 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
852 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ bNeedsModeration = ticket_need_moderation(0);
853 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
854 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
855 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_WIKI:{
856 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( g.perm.ApndWiki==0 || g.perm.Attach==0 ){
857 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ goto ajax_err_403;
858 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
859 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( !db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'",
860 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget) ){
861 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ goto ajax_err_404;
862 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
863 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ bNeedsModeration = wiki_need_moderation(0);
864 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
865 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
866 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
867 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
868 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( attachments_ajax_from_POST(zTarget, bNeedsModeration)>=0 ){
869 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ CX("}");
870 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( atoi(PD("dryrun","0"))>0 ){
871 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ bRollback = 1;
872 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
873 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }/*else error response was set up*/
874 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_free(zExtraFree);
875 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_end_transaction(bRollback);
876 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return;
877 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ajax_err_403:
878 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( db_transaction_nesting_depth()>0 ){
879 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_rollback_transaction();
880 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
881 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ajax_route_error_forbidden();
882 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return;
883 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ajax_err_404:
884 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ assert( db_transaction_nesting_depth()>0 );
885 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_rollback_transaction();
886 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ajax_route_error(404, "Target not found.");
887 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return;
888 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
889 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
890 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
891 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** A helper for AJAX-style routines which accept file attachments via
892 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** POST. zTarget must be a full attachment target. bNeedsModeration
893 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** must be true if the attachment requires moderation.
894 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
895 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** It is up to the caller to have validated all security measures
896 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** before calling this.
897 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
898 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** This looks for POSTed files names "file1".."fileN", stopping when
899 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** it finds no entry. Returns the number of entries attached to the
900 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** target or a negative value on error (in which case the current db
901 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** transaction will be in a rollback state).
902 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
903 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** The only errors are currently attachment size limit violations:
904 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** attachments must have a non-0 size and if the attachment-size-limit
905 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** setting is >0 then each file's size must be <= that.
906 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
907 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** If this returns a negative value, it will have populated an error
908 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** response using ajax_route_error(). On success it produces no
909 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** output.
910 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
911 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** ACHTUNG: if zTarget is a forum post, it "really should" be the ID
912 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** of the first version of that post, as that's where attachments are
913 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** intended to be applied so that they can be found and removed
914 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** consistently. Potential TODO is have this function do that if
915 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** attachment_target_type(zTarget,1)!=0 but it would (for current
916 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** uses) require duplicating work already done in the callers.
917 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
918 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int attachments_ajax_from_POST(const char *zTarget, int bNeedsModeration){
919 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int i;
920 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int rc = 0;
921 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int n = 0;
922 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int szLimit; /* attachment-max-size setting */
923 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char aKeyPrefix[20]; /* Buffer for key "file%d" */
924 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char aKeySize[30]; /* Buffer for key "file%d:bytes" */
925 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char aKeyName[30]; /* Buffer for key "file%d:filename" */
926 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char aKeyDesc[30]; /* Buffer for key "file%d_desc" */
927 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
928 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_begin_transaction();
929 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ szLimit = db_get_int("attachment-size-limit", 0);
930 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
931 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for(i = 1; ; ++i, ++n){
932 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* Look for P("fileN"), where N=1..n */
933 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zContent;
934 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zFilename;
935 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int szContent;
936 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sqlite3_snprintf(sizeof(aKeyPrefix), aKeyPrefix, "file%d", i);
937 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zContent = P(aKeyPrefix);
938 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( !zContent ){
939 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* End of the list. */
940 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
941 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
942 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sqlite3_snprintf(sizeof(aKeySize), aKeySize, "%s:bytes",
943 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ aKeyPrefix);
944 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ szContent = atoi(PD(aKeySize,"-1"));
945 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( szContent<=0 ){
946 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ rc = -ajax_route_error(400,"Invalid file size: %d", szContent);
947 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
948 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else if( szLimit>0 && szContent>szLimit ){
949 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ rc = -ajax_route_error(413, "File size limit is %d bytes.", szLimit);
950 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
951 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else{
952 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sqlite3_snprintf(sizeof(aKeyName), aKeyName, "%s:filename",
953 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ aKeyPrefix);
954 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ sqlite3_snprintf(sizeof(aKeyDesc), aKeyDesc, "%s_desc",
955 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ aKeyPrefix);
956 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( 0==(zFilename=P(aKeyName)) ){
957 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ rc = -ajax_route_error(400, "Missing filename.");
958 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
959 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
960 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ attach_commit(zFilename, zTarget, zContent, szContent,
961 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ bNeedsModeration, P(aKeyDesc));
962 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
963 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
964 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( rc<0 ){
965 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_rollback_transaction();
966 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return rc;
529 967 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}else{
530 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ <input type="hidden" name="page" value="%h(zPage)">
968 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_commit_transaction();
969 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return n;
970 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
971 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
972 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
973 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
974 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Proxy for /attachadd?target=X
975 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
976 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Lists attachments for, and can add them to, a target artifact.
977 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
978 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** target=TKT_HASH|WIKIPAGE_NAME|TECHNOTE_HASH|FORUMPOST_HASH
979 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** from=ORIGINATING_URL
980 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
981 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Works like /attachadd but uses a JS-based interactive attachment
982 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** selector.
983 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
984 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** from=X tells it where to redirect to when it's done.
985 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
986 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** This page requires a post-2018-ish JS-capable browser.
987 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
988 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ void attachaddV2_page(void){
989 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zFrom = P("from");
990 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zTarget = P("target");
991 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char *zTo = 0;
992 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char *zTargetType = 0;
993 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char *zExtraFree = 0;
994 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int eTgtType = 0;
995 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int goodCaptcha = 1;
996 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char const * noJsArgs[] = {0,0,0,0}; /* Args for noscript form */
997 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
998 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( P("cancel") ) cgi_redirect(zFrom);
999 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( 0==zTarget ){
1000 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ webpage_error("Requires target=X");
1001 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1002 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ login_check_credentials();
1003 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ eTgtType = attachment_target_type(zTarget, 1);
1004 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ switch( eTgtType ){
1005 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ default:
1006 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case 0:
1007 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ webpage_error("Cannot resolve target=%h.", zTarget);
1008 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
1009 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_FORUM:{
1010 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int fpid;
1011 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( g.perm.AttachForum==0 ){
1012 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ login_needed(g.anon.AttachForum);
1013 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return;
1014 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1015 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fpid = forumpost_head_rid2(zTarget);
1016 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( fpid<=0 ){
1017 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ webpage_error("Invalid forum post ID: %h", zTarget);
1018 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else if( !g.perm.Admin && !forumpost_is_owner(fpid, 0) ){
1019 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ webpage_error("Only admins can attach files to other users' "
1020 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "forum posts.");
1021 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1022 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget = zExtraFree = rid_to_uuid(fpid);
1023 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ noJsArgs[0] = zTarget;
1024 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTargetType = mprintf(
1025 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "Forum post <a href=\"%R/forumpost/%S\">%.16h</a>",
1026 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget, zTarget
1027 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ );
1028 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTo = mprintf("%R/forumpost/%S", zTarget);
1029 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
1030 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1031 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_EVENT:{
1032 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( g.perm.Write==0 || g.perm.ApndWiki==0 || g.perm.Attach==0 ){
1033 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ login_needed(g.anon.Write && g.anon.ApndWiki && g.anon.Attach);
1034 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return;
1035 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1036 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( !db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'",
1037 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget) ){
1038 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget = db_text(0, "SELECT substr(tagname,7) FROM tag"
1039 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " WHERE tagname GLOB 'event-%q*'",
1040 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget);
1041 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( zTarget==0) fossil_redirect_home();
1042 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1043 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTo = zFrom ? 0 : mprintf("%R/technote?name=%T", zTarget);
1044 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTargetType = mprintf("Tech-note <a href=\"%R/technote/%s\">%S</a>",
1045 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget, zTarget);
1046 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ noJsArgs[1] = zTarget;
1047 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
1048 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1049 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_TICKET:{
1050 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( g.perm.ApndTkt==0 || g.perm.Attach==0 ){
1051 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ login_needed(g.anon.ApndTkt && g.anon.Attach);
1052 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return;
1053 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1054 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( !db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'",
1055 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget) ){
1056 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget = db_text(0, "SELECT substr(tagname,5) FROM tag"
1057 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " WHERE tagname GLOB 'tkt-%q*'", zTarget);
1058 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( zTarget==0 ) fossil_redirect_home();
1059 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1060 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTo = zFrom ? 0 : mprintf("%R/tktview/%t", zTarget);
1061 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTargetType = mprintf("Ticket <a href=\"%R/tktview/%s\">%S</a>",
1062 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget, zTarget);
1063 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ noJsArgs[2] = zTarget;
1064 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
1065 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1066 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_WIKI:{
1067 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( g.perm.ApndWiki==0 || g.perm.Attach==0 ){
1068 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ login_needed(g.anon.ApndWiki && g.anon.Attach);
1069 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return;
1070 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1071 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( !db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'",
1072 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget) ){
1073 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_redirect_home();
1074 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1075 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTo = zFrom ? 0 : mprintf("%R/wiki?name=%T", zTarget);
1076 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTargetType = mprintf(
1077 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "Wiki page <a href=\"%R/wiki?name=%h\">%h</a>",
1078 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget, zTarget
1079 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ );
1080 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ noJsArgs[3] = zTarget;
1081 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
1082 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1083 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1084 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1085 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_begin_transaction();
1086 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1087 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ style_set_current_feature("attach");
1088 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ style_header("Add Attachment");
1089 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( !goodCaptcha ){
1090 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <p class="generalError">Error: Incorrect security code.</p>
1091 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1092 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <h2>Attachments for %s(zTargetType)</h2>
1093 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ attachment_list(zTarget, NULL,
1094 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ATTACHLIST_SIZE | ATTACHLIST_HIDE_UNAPPROVED);
1095 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ attach_render_legacy_form(
1096 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ noJsArgs[0], noJsArgs[1], noJsArgs[2],
1097 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ noJsArgs[3], 0,
1098 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zFrom ? zFrom : (zTo ? zTo : (zTo=mprintf("%R/home")))
1099 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ );
1100 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <div id='attachadd-form-wrapper' class='hidden'>
1101 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* fossil.attach.js populates this DIV with the attachment widget,
1102 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** imports these hidden fields, and removes the legacy form. */
1103 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <input type="hidden" name="target" value="%h(zTarget)">
1104 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( zFrom ){
1105 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <input type="hidden" name="from" value="%h(zFrom)">
531 1106 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
532 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ <input type="hidden" name="from" value="%h(zFrom)">
533 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ <input type="submit" name="ok" value="Add Attachment">
534 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ <input type="submit" name="cancel" value="Cancel">
535 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ </div>
1107 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( zTo ){
1108 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <input type="hidden" name="to" value="%h(zTo)">
1109 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
536 1110 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
captcha_generate(0);
537 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ </form>
1111 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ login_insert_csrf_secret();
1112 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ </div>
1113 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ builtin_fossil_js_bundle_or("attach", NULL);
1114 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_end_transaction(0);
538 1115 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
style_finish_page();
539 1116 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
fossil_free(zTargetType);
540 1117 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
fossil_free(zExtraFree);
1118 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_free(zTo);
541 1119 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
542 1120 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
543 1121 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/*
544 1122 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** WEBPAGE: ainfo
545 1123 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** URL: /ainfo?name=ARTIFACTID
@@ -600,15 +1178,17 @@
600 1178 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
&& db_exists("SELECT 1 FROM ticket WHERE tkt_uuid='%q'", zTarget)
601 1179 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
){
602 1180 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( !g.perm.RdTkt ){ login_needed(g.anon.RdTkt); return; }
603 1181 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zTktUuid = zTarget;
604 1182 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
showDelMenu = g.perm.WrTkt;
605 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- }else if( db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'",zTarget) ){
1183 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else if( db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'",
1184 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget) ){
606 1185 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
607 1186 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zWikiName = zTarget;
608 1187 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
showDelMenu = g.perm.WrWiki;
609 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- }else if( db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'",zTarget) ){
1188 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else if( db_exists("SELECT 1 FROM tag WHERE tagname='event-%q'",
1189 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget) ){
610 1190 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( !g.perm.RdWiki ){ login_needed(g.anon.RdWiki); return; }
611 1191 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zTNUuid = zTarget;
612 1192 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
showDelMenu = g.perm.Write && g.perm.WrWiki;
613 1193 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
614 1194 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( showDelMenu ){
@@ -632,11 +1212,13 @@
632 1212 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
Blob cksum;
633 1213 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zFile = zName;
634 1214 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
635 1215 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( !bUserIsOwner ){
636 1216 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( zForumPost ? !forumpost_may_close() : !g.perm.Admin ){
637 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- webpage_error("Only admins can delete other users' attachments.");
1217 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ webpage_error(
1218 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "Only admins can delete other users' attachments."
1219 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ );
638 1220 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
639 1221 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
640 1222 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
db_begin_transaction();
641 1223 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_zero(&manifest);
642 1224 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
for(i=n=0; zFile[i]; i++){
@@ -656,14 +1238,14 @@
656 1238 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <p>The attachment below has been deleted.</p>
657 1239 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
fossil_free(zNewDate);
658 1240 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
659 1241 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
660 1242 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( P("del")
661 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- && ((zForumPost && (bUserIsOwner || forumpost_may_close())) ||
662 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- (zTktUuid && g.perm.WrTkt) ||
663 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- (zWikiName && g.perm.WrWiki) ||
664 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- (zTNUuid && g.perm.Write && g.perm.WrWiki))
1243 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ && ((zForumPost && (bUserIsOwner || forumpost_may_close()))
1244 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ || (zTktUuid && g.perm.WrTkt)
1245 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ || (zWikiName && g.perm.WrWiki)
1246 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ || (zTNUuid && g.perm.Write && g.perm.WrWiki))
665 1247 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
){
666 1248 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
form_begin(0, "%R/ainfo/%!S", zUuid);
667 1249 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <p>Confirm you want to delete the attachment shown below.
668 1250 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <input type="submit" name="confirm" value="Confirm">
669 1251 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
login_insert_csrf_secret();
@@ -711,20 +1293,22 @@
711 1293 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ (%d(rid))
712 1294 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
713 1295 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
modPending = moderation_pending_www(rid);
714 1296 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( zForumPost ){
715 1297 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <tr><th>Forum Post:</th>
716 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ <td>%z(href("%R/forumpost/%s",zForumPost))%h(zForumPost)</a></td></tr>
1298 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <td>%z(href("%R/forumpost/%s",zForumPost))%h(zForumPost)</a>\
1299 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ </td></tr>
717 1300 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}else if( zTktUuid ){
718 1301 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <tr><th>Ticket:</th>
719 1302 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <td>%z(href("%R/tktview/%s",zTktUuid))%s(zTktUuid)</a></td></tr>
720 1303 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}else if( zTNUuid ){
721 1304 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <tr><th>Tech Note:</th>
722 1305 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <td>%z(href("%R/technote/%s",zTNUuid))%s(zTNUuid)</a></td></tr>
723 1306 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}else if( zWikiName ){
724 1307 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <tr><th>Wiki Page:</th>
725 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ <td>%z(href("%R/wiki?name=%t",zWikiName))%h(zWikiName)</a></td></tr>
1308 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <td>%z(href("%R/wiki?name=%t",zWikiName))%h(zWikiName)</a>\
1309 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ </td></tr>
726 1310 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
727 1311 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <tr><th>Date:</th><td>
728 1312 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
hyperlink_to_date(zDate, "</td></tr>");
729 1313 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <tr><th>User:</th><td>
730 1314 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
hyperlink_to_user(pAttach->zUser, zDate, "</td></tr>");
@@ -735,22 +1319,42 @@
735 1319 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
736 1320 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <tr><th>Filename:</th><td>%h(zName)</td></tr>
737 1321 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( g.perm.Setup ){
738 1322 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <tr><th>MIME-Type:</th><td>%h(zMime)</td></tr>
739 1323 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
740 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ <tr><th valign="top">Description:</th><td valign="top">%h(zDesc)</td></tr>
1324 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <tr><th valign="top">Description:</th>\
1325 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* FIXME (2026-06-05): Honor the N-card (comment mimetype). */
1326 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <td valign="top">%h(zDesc)</td></tr>
741 1327 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ </table>
742 1328 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
743 1329 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( modPending && (isModerator || bUserIsOwner) ){
744 1330 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <div class="section">Moderation</div>
745 1331 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <blockquote>
746 1332 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
form_begin(0, "%R/ainfo/%s", zUuid);
747 1333 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <label><input type="radio" name="modaction" value="delete">
748 1334 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ Delete this attachment</label><br>
749 1335 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( isModerator ){
750 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ <label><input type="radio" name="modaction" value="approve">
751 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ Approve this attachment</label><br>
1336 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ #if 0
1337 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* TODO/FIXME (2026-06-03): only allow approval of an attachment
1338 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** if its target has been approved. Without this, we can end up
1339 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** with stale attachments which refer to rejected targets. We
1340 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** need a type-specific RID/UUID here, which requires
1341 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** refactoring above to get it. */
1342 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const int tgtid = 0;
1343 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( moderation_pending(tgtid) ){
1344 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <label><input type="radio" name="modaction" \
1345 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ disabled value="approve">
1346 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <span class='modpending'>Cannot approve:
1347 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ target is pending moderation</span>\
1348 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ </label><br>
1349 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else
1350 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ #else
1351 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ {
1352 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <label><input type="radio" name="modaction" value="approve">
1353 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ Approve this attachment</label><br>
1354 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1355 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ #endif
752 1356 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
753 1357 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <input type="submit" value="Submit">
754 1358 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
login_insert_csrf_secret();
755 1359 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ </form>
756 1360 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ </blockquote>
@@ -767,11 +1371,12 @@
767 1371 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *z;
768 1372 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
content_get(ridSrc, &attach);
769 1373 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_to_utf8_no_bom(&attach, 0);
770 1374 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
z = blob_str(&attach);
771 1375 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( zLn ){
772 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- output_text_with_line_numbers(z, blob_size(&attach), zName, zLn, 1);
1376 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ output_text_with_line_numbers(z, blob_size(&attach),
1377 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zName, zLn, 1);
773 1378 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}else{
774 1379 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <pre>
775 1380 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ %h(z)
776 1381 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ </pre>
777 1382 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
@@ -798,10 +1403,13 @@
798 1403 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
*/
799 1404 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#define ATTACHLIST_HRULE_ABOVE 0x01 /* Insert <hr> above header */
800 1405 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#define ATTACHLIST_TARGET_BLANK 0x02 /* use target=_blank for links */
801 1406 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#define ATTACHLIST_SIZE 0x04 /* add size */
802 1407 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#define ATTACHLIST_HIDE_UNAPPROVED 0x08 /* Hide pending-moderation files */
1408 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ #define ATTACHLIST_DETAILS_CLOSED 0x10 /* Wrap in a closed DETAILS element */
1409 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ #define ATTACHLIST_DETAILS_OPEN 0x20 /* Wrap in an open DETAILS element */
1410 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ #define ATTACHLIST_HIDE_EMPTY 0x40 /* Skip if size<1 */
803 1411 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
#endif
804 1412 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
805 1413 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/*
806 1414 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** Output HTML to show a list of attachments.
807 1415 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
*/
@@ -810,19 +1418,25 @@
810 1418 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zHeader, /* Header to display with attachments */
811 1419 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const int flags /* ATTACHLIST_... flags */
812 1420 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
){
813 1421 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
int cnt = 0;
814 1422 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
char szBuf[36] = {0}; /* scratchpad for attachment size value */
815 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- const char * zLinkTgt = (ATTACHLIST_TARGET_BLANK & flags)
1423 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zLinkTgt = (ATTACHLIST_TARGET_BLANK & flags)
816 1424 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
? " target=\"_blank\"" : "";
1425 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const int bUseDetail = flags &
1426 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ (ATTACHLIST_DETAILS_CLOSED | ATTACHLIST_DETAILS_OPEN);
817 1427 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
Stmt q;
1428 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
818 1429 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
db_prepare(&q,
819 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "SELECT datetime(mtime,toLocal()), filename, user,"
820 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- " (SELECT uuid FROM blob WHERE rid=attachid), src, target, "
821 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- " attachid "
822 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- " FROM attachment"
823 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- " WHERE isLatest AND src!='' AND target=%Q"
1430 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "SELECT datetime(mtime,toLocal()), a.filename, a.user,"
1431 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " b1.uuid, a.src, a.target, a.attachid, b2.size\n"
1432 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " FROM attachment a, blob b1, blob b2\n"
1433 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " WHERE a.isLatest\n"
1434 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " AND a.src IS NOT NULL\n"
1435 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " AND a.target=%Q\n"
1436 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " AND b1.rid=a.attachid\n"
1437 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " AND b2.uuid=a.src\n"
824 1438 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
" ORDER BY mtime DESC",
825 1439 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zTarget
826 1440 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
);
827 1441 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
while( db_step(&q)==SQLITE_ROW ){
828 1442 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zDate = db_column_text(&q, 0);
@@ -832,36 +1446,51 @@
832 1446 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zSrc = db_column_text(&q, 4);
833 1447 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zTarget = db_column_text(&q, 5);
834 1448 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
835 1449 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zTypeArg = 0; /* URL arg name for /attachdownload */
836 1450 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const int aid = db_column_int(&q, 6);
837 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- const int iAType = attachment_target_type(zTarget);
1451 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const int sz = db_column_int(&q, 7);
838 1452 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( (flags & ATTACHLIST_HIDE_UNAPPROVED)
839 1453 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
&& moderation_pending(aid)
840 1454 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
&& !moderation_user_could(aid, 1, 0) ){
841 1455 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
continue;
1456 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1457 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( sz<1 && (flags & ATTACHLIST_HIDE_EMPTY) ){
1458 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* Deleted or phantom items. */
1459 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ continue;
842 1460 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
843 1461 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( cnt==0 ){
844 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ <section class='attachlist'>
1462 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( bUseDetail ){
1463 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <details class='attachlist'
1464 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( ATTACHLIST_DETAILS_OPEN & flags ){
1465 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ open
1466 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1467 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ >
1468 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else{
1469 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <section class='attachlist'>
1470 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
845 1471 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( flags & ATTACHLIST_HRULE_ABOVE ){
846 1472 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <hr>
847 1473 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
848 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ %s(zHeader)
1474 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( bUseDetail ){
1475 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ <summary>%s(zHeader)</summary>
1476 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else{
1477 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ %s(zHeader)
1478 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
849 1479 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <ul>
850 1480 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
851 1481 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
cnt++;
852 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- switch( iAType ){
1482 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ switch( attachment_target_type(zTarget, 1) ){
853 1483 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
case CFTYPE_TICKET: zTypeArg = "tkt"; break;
854 1484 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
case CFTYPE_FORUM: zTypeArg = "forumpost"; break;
855 1485 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
case CFTYPE_EVENT: zTypeArg = "technote"; break;
856 1486 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
case CFTYPE_WIKI:
857 1487 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
default: zTypeArg = "page"; break;
858 1488 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
859 1489 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <li>
860 1490 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <a href="%R/artifact/%!S(zSrc)"%s(zLinkTgt)>%h(zFile)</a>
861 1491 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( flags & ATTACHLIST_SIZE ){
862 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- const int sz = db_int(0,"SELECT size FROM blob WHERE uuid=%Q", zSrc);
863 1492 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
sqlite3_snprintf(sizeof(szBuf), szBuf, " %d bytes", sz);
864 1493 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
865 1494 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ [<a href="%R/attachdownload/%t(zFile)?%s(zTypeArg)=%t(zTarget)\
866 1495 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@&file=%t(zFile)%s(zLinkTgt)">download</a>%s(szBuf)]
867 1496 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ added by %h(zDispUser) on
@@ -870,11 +1499,15 @@
870 1499 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
moderation_pending_www(aid);
871 1500 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ </li>
872 1501 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
873 1502 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( cnt ){
874 1503 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ </ul>
875 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- @ </section>
1504 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( bUseDetail ){
1505 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ </details>
1506 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else{
1507 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ @ </section>
1508 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
876 1509 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
877 1510 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
db_finalize(&q);
878 1511 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
879 1512 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
880 1513 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/*
@@ -1023,15 +1656,204 @@
1023 1656 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
1024 1657 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
for(i = 2; i < g.argc; ++i){
1025 1658 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zPage = g.argv[i];
1026 1659 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
db_bind_text(&q, ":tgtname", zPage);
1027 1660 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
while(SQLITE_ROW == db_step(&q)){
1028 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- const char * zTime = db_column_text(&q, 0);
1029 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- const char * zSrc = db_column_text(&q, 1);
1030 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- const char * zTarget = db_column_text(&q, 2);
1031 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- const char * zName = db_column_text(&q, 3);
1661 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zTime = db_column_text(&q, 0);
1662 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zSrc = db_column_text(&q, 1);
1663 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zTarget = db_column_text(&q, 2);
1664 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zName = db_column_text(&q, 3);
1032 1665 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
printf("%-20s %s %.12s %s\n", zTarget, zTime, zSrc, zName);
1033 1666 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
1034 1667 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
db_reset(&q);
1035 1668 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
1036 1669 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
db_finalize(&q);
1037 1670 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
1671 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1672 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
1673 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Renders the list of attachments for artifact pManifest as JSON to
1674 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** blob pOut. If pManifest->type is not one of (CFTYPE_TICKET,
1675 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** CFTYPE_FORUM, CFTYPE_EVENT, CFTYPE_WIKI) then it behaves as if the
1676 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** result set is empty.
1677 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
1678 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** If there are no matching attachments then its behavior depends on
1679 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** emptyPolicy:
1680 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
1681 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** <0 = emit a JSON NULL
1682 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** 0 = emit no output
1683 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** >0 = emit an empty JSON array
1684 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
1685 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** If bLatestOnly is true then only the most recent entry for a given
1686 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** attachment is emitted, else all versions are emitted in descending
1687 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** mtime order.
1688 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
1689 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Returns the number of attachments.
1690 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
1691 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Output format:
1692 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
1693 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** [{
1694 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** "uuid": attachment artifact hash,
1695 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** "src": hash of the attachment blob,
1696 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** "target": wiki page name or ticket/event ID,
1697 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** "filename": filename of attachment,
1698 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** "mtime": ISO-8601 timestamp UTC,
1699 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** "isLatest": true if this is the latest version of this file
1700 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** else false,
1701 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** }, ...once per attachment]
1702 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
1703 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
1704 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int attachments_to_json(const Manifest *pManifest,
1705 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Blob *pOut, int bLatestOnly,
1706 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int emptyPolicy){
1707 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int i = 0;
1708 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Stmt q = empty_Stmt;
1709 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char *zToFree = 0;
1710 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zTgt = 0;
1711 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ switch(pManifest->type){
1712 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_FORUM: zTgt = zToFree = rid_to_uuid(pManifest->rid);
1713 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
1714 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_WIKI: zTgt = pManifest->zWikiTitle; break;
1715 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_EVENT: zTgt = pManifest->zEventId; break;
1716 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_TICKET: zTgt = pManifest->zTicketUuid; break;
1717 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ default:
1718 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ goto empty_result;
1719 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1720 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_prepare(&q,
1721 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "SELECT datetime(mtime), a.src, a.target, a.filename, a.isLatest,\n"
1722 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " b2.size, b1.uuid, a.user, a.comment\n"
1723 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " FROM attachment a, blob b1, blob b2\n"
1724 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " WHERE a.target=%Q\n"
1725 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " AND a.src IS NOT NULL\n"
1726 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " AND b1.rid=a.attachid\n"
1727 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " AND b2.uuid=a.src\n"
1728 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " AND (a.isLatest OR %d)\n"
1729 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " ORDER BY a.target, a.isLatest DESC, a.mtime DESC\n",
1730 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTgt, !bLatestOnly
1731 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ );
1732 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ while(SQLITE_ROW == db_step(&q)){
1733 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zTime = db_column_text(&q, 0);
1734 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zSrc = db_column_text(&q, 1);
1735 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zTarget = db_column_text(&q, 2);
1736 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zName = db_column_text(&q, 3);
1737 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const int isLatest = db_column_int(&q, 4);
1738 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const int sz = db_column_int(&q, 5);
1739 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zUuid = db_column_text(&q, 6);
1740 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zUser = db_column_text(&q, 7);
1741 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zComment = db_column_text(&q, 8);
1742 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if(!i++){
1743 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append_char(pOut, '[');
1744 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else{
1745 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append_char(pOut, ',');
1746 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1747 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_appendf(
1748 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ pOut,
1749 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "{\"uuid\": %!j, \"src\": %!j, \"target\": %!j, "
1750 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "\"filename\": %!j, \"size\":%d, \"mtime\": %!j, "
1751 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "\"isLatest\": %s, \"user\": %!j, \"comment\": ",
1752 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zUuid, zSrc, zTarget,
1753 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zName, sz, zTime, isLatest ? "true" : "false",
1754 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zUser
1755 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ );
1756 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( zComment && zComment[0] ){
1757 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_appendf(pOut, "%!j", zComment);
1758 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else{
1759 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append_literal(pOut, "null");
1760 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1761 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append_char(pOut, '}');
1762 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1763 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_free(zToFree);
1764 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_finalize(&q);
1765 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if(!i){
1766 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ empty_result:
1767 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( emptyPolicy>0 ){
1768 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append_literal(pOut, "[]");
1769 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else if( emptyPolicy<0 ){
1770 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append_literal(pOut, "null");
1771 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1772 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else{
1773 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_append_char(pOut, ']');
1774 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1775 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return i;
1776 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1777 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1778 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
1779 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** COMMAND: test-attachment-target
1780 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
1781 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Usage: %fossil test-attachment-target TARGET_ID...
1782 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
1783 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ void test_attachment_target_type_cmd(void){
1784 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int i;
1785 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ verify_all_options();
1786 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_find_and_open_repository(0, 0);
1787 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( g.argc<3 ){
1788 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ usage("test-attachment-target TARGET_ID");
1789 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return;
1790 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1791 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for( i = 2; i < g.argc; ++i ){
1792 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zTarget = g.argv[i];
1793 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const int rid = attachment_target_rid(zTarget, 0);
1794 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const int type = attachment_target_type(zTarget, 0);
1795 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zType = "<invalid>";
1796 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ switch(type){
1797 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_EVENT: zType = "technote"; break;
1798 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_FORUM: zType = "forumpost"; break;
1799 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_TICKET: zType = "ticket"; break;
1800 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_WIKI: zType = "wiki"; break;
1801 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1802 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_print("%-20s = %-9s #%d %z\n",
1803 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget, zType, rid,
1804 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ rid>0 ? rid_to_uuid(rid) : 0);
1805 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1806 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1807 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1808 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1809 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
1810 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** COMMAND: test-attachments-to-json
1811 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
1812 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Usage: %fossil test-attachments-to-json TARGET_ID...
1813 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
1814 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Options:
1815 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** --old List all versions of attachments. Default is to
1816 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** list only the latest.
1817 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** --full Require a full target ID, not a prefix.
1818 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
1819 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Emits a JSON array of attachments for the given attachment targets.
1820 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** The given IDs must be wiki page names, ticket hashes, tech-note
1821 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** hashes, or forum post hashes. By default it accepts hash prefixes
1822 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** but does no detection of ambiguity or cross-type prefix collisions
1823 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** so may emit curious results if given short, colliding IDs.
1824 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
1825 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ void test_attachments_to_json_cmd(void){
1826 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const int emptyPolicy = 1;
1827 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const int bLatestOnly = find_option("old",0,0)==0;
1828 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const int bFullId = find_option("full",0,0)!=0;
1829 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int i;
1830 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
1831 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ verify_all_options();
1832 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_find_and_open_repository(0, 0);
1833 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( g.argc<3 ){
1834 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ usage("test-attachments-to-json TARGET_ID");
1835 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return;
1836 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1837 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ for( i = 2; i < g.argc; ++i ){
1838 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zTarget = g.argv[i];
1839 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const int rid = attachment_target_rid(zTarget, bFullId);
1840 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( 0==rid ){
1841 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_print("** cannot resolve %s\n", zTarget);
1842 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else{
1843 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Blob b = BLOB_INITIALIZER;
1844 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ Manifest *pManifest = manifest_get(rid, CFTYPE_ANY, NULL);
1845 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ assert( pManifest );
1846 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ attachments_to_json(pManifest, &b, bLatestOnly, emptyPolicy);
1847 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_print("Attachments for %s: ", zTarget);
1848 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( b.nUsed ){
1849 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ char *zPretty = db_text(0,"SELECT json_pretty(%B)", &b);
1850 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_print("%s\n", zPretty);
1851 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_free(zPretty);
1852 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else{
1853 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ fossil_print("none\n");
1854 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1855 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ blob_reset(&b);
1856 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ manifest_destroy(pManifest);
1857 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1858 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1859 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
1038 1860 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!