@@ -24,87 +24,115 @@
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 27 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** CFTYPE_TICKET, or CFTYPE_EVENT. Returns 0 if it cannot
28 28 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** distinguish 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!
+ ** If bFull is true then it requires zTarget to be an exact matches
31 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** for wiki, tech-note, and ticket IDs. If bFull is false then
32 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** tech-notes and tickets will perform a prefix match, but it is up to
33 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** the caller to provide enough of a prefix to rule out a
34 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** collision[^1]. Forum posts are a special case and ignore the bFull
35 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** flag. When called repeatedly, this routine can run a bit faster and
36 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** more efficiently if bFull is true, but some historical use cases
37 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** call for prefix matches.
29 38 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
**
30 39 { 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 40 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** if needed, they resolve zTarget using forumpost_head_rid2() so that
32 41 { 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 42 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** the only one which attachments should target.
34 43 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
**
35 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** FIXME (2026-06-03)? Figuring out if an event or a ticket are a
36 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** unique prefix is more work than this function performs. This makes
37 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** it unsuitable as a drop-in replacement for legacy
38 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** /attachadd?x=SHORT_ID links using newer /attachadd?target=ID URLs
39 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** because the the former, via /attachadd?technote=ID or ?ticket=ID,
40 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** accept unique prefixes whereas the latter, via this function, does
41 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** not.
42 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- */
43 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- int attachment_target_type(const char *zTarget){
44 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- static Stmt q = empty_Stmt_m;
45 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- int rc = 0;
46 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if( !zTarget || !zTarget[0] || strlen(zTarget)>64/*vs. abuse*/ ){
47 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- return 0;
48 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- }else if( forumpost_head_rid2(zTarget)>0 ){
49 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- return CFTYPE_FORUM;
50 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- }else if( !q.pStmt ){
51 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- db_static_prepare(
52 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- &q,
53 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "SELECT CASE "
54 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "WHEN 'tkt-'||:tgt IN (SELECT tagname FROM tag) THEN %d "
55 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "WHEN 'event-'||:tgt IN (SELECT tagname FROM tag) THEN %d "
56 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "WHEN 'wiki-'||:tgt IN (SELECT tagname FROM tag) THEN %d "
57 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "ELSE 0 END",
58 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- CFTYPE_TICKET, CFTYPE_EVENT, CFTYPE_WIKI
59 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- );
60 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- }
61 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- db_bind_text(&q, ":tgt", zTarget);
62 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- if( SQLITE_ROW==db_step(&q) ){
63 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- rc = db_column_int(&q, 0);
64 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- }
65 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- db_reset(&q);
66 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- return rc;
67 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- }
68 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
-
69 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- /*
70 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** Given a full attachment target ID, returns its blob.rid. zTarget
71 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** must be a full wiki page name, tech-note ID, ticket ID, or forum
72 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** post hash. Returns 0 if no match is found.
73 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- */
74 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- int attachment_resolve_target(const char *zTarget){
75 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- int rid = 0;
76 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- int eType = attachment_target_type(zTarget);
77 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- switch(eType){
78 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- case CFTYPE_EVENT:
79 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- rid = db_int(
80 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- 0, "SELECT b.rid FROM blob b, tag t, tagxref x\n"
81 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "WHERE tagname='event-%q'\n"
82 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "AND x.tagtype>0\n"
83 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "AND x.tagid=t.tagid\n"
84 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "AND x.rid=b.rid\n"
85 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "ORDER BY x.mtime DESC",
86 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- zTarget
87 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- );
88 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- break;
89 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- case CFTYPE_FORUM:
90 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- rid = db_int(
91 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- 0, "SELECT f.fpid FROM forumpost f, blob b\n"
92 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "WHERE f.fpid=b.rid\n"
93 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "AND b.uuid=%Q",
94 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- zTarget
95 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- );
96 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- break;
97 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- case CFTYPE_TICKET:
98 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- rid = db_int(
99 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- 0, "SELECT b.rid FROM blob b, tag t, tagxref x\n"
100 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "WHERE tagname='tkt-%q'\n"
101 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "AND x.tagtype>0\n"
102 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "AND x.tagid=t.tagid\n"
103 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "AND x.rid=b.rid\n"
104 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "ORDER BY x.mtime DESC",
105 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- zTarget
44 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** [^1]: Historically (as of 2026-06) attachment target lookups have
45 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** used GLOB prefix matching but taken no measures to ensure that the
46 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** prefix is unambiguous. Ergo we don't here, either. It is assumed
47 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** that the caller passes enough of a prefix to be unambiguous and
48 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** that's worked out fine so far.
49 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
50 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int attachment_target_type(const char *zTarget, int bFull){
51 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( !zTarget || !zTarget[0] || strlen(zTarget)>64/*vs. abuse*/ ){
52 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return 0;
53 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
54 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( symbolic_name_to_rid(zTarget, "f")>0 ){
55 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* Check forum posts first because they are the most likely target
56 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** as of 2026. */
57 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return CFTYPE_FORUM;
58 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
59 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( bFull ){
60 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ static Stmt q = empty_Stmt_m;
61 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int rc = 0;
62 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( !q.pStmt ){
63 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_static_prepare(
64 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ &q,
65 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "SELECT CASE "
66 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /* Ordered by presumed likelihood of attachments. */
67 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WHEN (SELECT 1 FROM tag WHERE tagname='tkt-'||:tgt) THEN %d\n"
68 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WHEN (SELECT 1 FROM tag WHERE tagname='wiki-'||:tgt) THEN %d\n"
69 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WHEN (SELECT 1 FROM tag WHERE tagname='event-'||:tgt) THEN %d\n"
70 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "ELSE 0 END",
71 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ CFTYPE_TICKET, CFTYPE_WIKI, CFTYPE_EVENT
72 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ );
73 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
74 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_bind_text(&q, ":tgt", zTarget);
75 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ if( SQLITE_ROW==db_step(&q) ){
76 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ rc = db_column_int(&q, 0);
77 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
78 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ db_reset(&q);
79 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return rc;
80 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }else{
81 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ return db_int(
82 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ 0,
83 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "SELECT CASE "
84 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WHEN (SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*')"
85 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " THEN %d\n"
86 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WHEN (SELECT tagid FROM tag WHERE tagname='wiki-%q')"
87 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " THEN %d\n"
88 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WHEN (SELECT tagid FROM tag WHERE tagname GLOB 'event-%q*')"
89 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " THEN %d\n"
90 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "ELSE 0 END",
91 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget, CFTYPE_TICKET,
92 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget, CFTYPE_WIKI,
93 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget, CFTYPE_EVENT
94 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ );
95 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
96 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
97 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+
98 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ /*
99 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Given an attachment target name, returns the target's blob.rid.
100 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** zTarget must be a full wiki page name, tech-note ID, ticket ID, or
101 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** forum post hash. Returns 0 if no match is found.
102 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ **
103 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** bFull is interpreted as per attachment_target_type().
104 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ */
105 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int attachment_target_rid(const char *zTarget, int bFull){
106 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int rid = 0;
107 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const int eType = attachment_target_type(zTarget, bFull);
108 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ switch(eType){
109 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_TICKET:
110 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_EVENT:{
111 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zTagPrefix = (eType==CFTYPE_EVENT) ? "event" : "tkt";
112 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ rid = db_int(
113 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ 0, "SELECT b.rid FROM blob b, tag t, tagxref x\n"
114 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WHERE tagname %s '%s-%q%s'\n"
115 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "AND x.tagtype>0\n"
116 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "AND x.tagid=t.tagid\n"
117 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "AND x.rid=b.rid\n"
118 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "ORDER BY x.mtime DESC",
119 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ bFull ? "=" : "GLOB"/*safe-for-%s*/,
120 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTagPrefix/*safe-for-%s*/,
121 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget,
122 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ bFull ? "" : "*"/*safe-for-%s*/
123 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ );
124 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ break;
125 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ }
126 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ case CFTYPE_FORUM:
127 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ rid = db_int(
128 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ 0, "SELECT f.fpid FROM forumpost f, blob b\n"
129 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "WHERE f.fpid=b.rid\n"
130 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "AND b.uuid %s '%q%s'",
131 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ bFull ? "=" : "GLOB"/*safe-for-%s*/,
132 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zTarget,
133 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ bFull ? "" : "*"/*safe-for-%s*/
106 134 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
);
107 135 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
break;
108 136 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
case CFTYPE_WIKI:
109 137 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
rid = db_int(
110 138 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
0, "SELECT b.rid FROM blob b, tag t, tagxref x\n"
@@ -122,12 +150,12 @@
122 150 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return rid;
123 151 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
124 152 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
125 153 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/*
126 154 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** For a given aritfact ID and type (from the CFTYPE_xyz enum),
127 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** returns true if the current user could hypothetically attach
128 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** something to it, else returns 0.
155 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** returns true if the current user could hypothetically apply and
156 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** attachment to it, else returns 0.
129 157 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
**
130 158 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** The rid is currently only relevant when eArtifactType is
131 159 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** CFTYPE_FORUM. For forum posts, it checks precisely the rid given,
132 160 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** not the head RID, to keep non-admins from attaching files to
133 161 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** threads which have since been taken over by another user (this
@@ -150,11 +178,11 @@
150 178 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
151 179 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
152 180 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
153 181 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/*
154 182 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** Emits a single-button FORM which invokes
155 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** /attachadd?target=$zTarget.
183 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** /attachadd with target=$zTarget.
156 184 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
*/
157 185 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
void attach_render_attachadd_button(const char *zTarget){
158 186 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/* This could be changed from POST to GET, and arguably should so
159 187 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** that the target=X part becomes part of the resulting URL. */
160 188 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
@ <form method="post" action="%R/attachadd">\
@@ -266,11 +294,11 @@
266 294 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( zFilename[i]=='/' && zFilename[i+1]!=0 ){
267 295 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zFilename = &zFilename[i+1];
268 296 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
i = -1;
269 297 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
270 298 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
271 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- type = attachment_target_type(zTarget);
299 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ type = attachment_target_type(zTarget, 1);
272 300 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
switch( type ){
273 301 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
case CFTYPE_TICKET:
274 302 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
275 303 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
break;
276 304 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
case CFTYPE_EVENT:
@@ -728,11 +756,11 @@
728 756 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
ajax_route_error(403, "Invalid CSRF signature.");
729 757 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return;
730 758 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
731 759 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
db_begin_transaction();
732 760 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zTarget = P("target");
733 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- iTgtType = attachment_target_type(zTarget);
761 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ iTgtType = attachment_target_type(zTarget, 1);
734 762 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
CX("{");
735 763 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
switch( iTgtType ){
736 764 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
default:
737 765 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
case 0:
738 766 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
ajax_route_error(400, "Invalid attachment target.");
@@ -877,11 +905,11 @@
877 905 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( P("cancel") ) cgi_redirect(zFrom);
878 906 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( 0==zTarget ){
879 907 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
webpage_error("Requires target=X");
880 908 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
881 909 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
login_check_credentials();
882 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- eTgtType = attachment_target_type(zTarget);
910 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ eTgtType = attachment_target_type(zTarget, 1);
883 911 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
switch( eTgtType ){
884 912 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
default:
885 913 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
case 0:
886 914 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
webpage_error("Cannot resolve target=%h.", zTarget);
887 915 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
break;
@@ -1300,11 +1328,11 @@
1300 1328 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zSrc = db_column_text(&q, 4);
1301 1329 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zTarget = db_column_text(&q, 5);
1302 1330 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zDispUser = zUser && zUser[0] ? zUser : "anonymous";
1303 1331 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zTypeArg = 0; /* URL arg name for /attachdownload */
1304 1332 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const int aid = db_column_int(&q, 6);
1305 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- const int iAType = attachment_target_type(zTarget);
1333 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const int iAType = attachment_target_type(zTarget, 1);
1306 1334 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( (flags & ATTACHLIST_HIDE_UNAPPROVED)
1307 1335 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
&& moderation_pending(aid)
1308 1336 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
&& !moderation_user_could(aid, 1, 0) ){
1309 1337 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
continue;
1310 1338 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
@@ -1552,11 +1580,11 @@
1552 1580 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
default:
1553 1581 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
goto empty_result;
1554 1582 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
1555 1583 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
db_prepare(&q,
1556 1584 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"SELECT datetime(mtime), a.src, a.target, a.filename, a.isLatest,\n"
1557 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- " b2.size, b1.uuid, a.comment\n"
1585 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ " b2.size, b1.uuid, a.user, a.comment\n"
1558 1586 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
" FROM attachment a, blob b1, blob b2\n"
1559 1587 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
" WHERE a.target=%Q\n"
1560 1588 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
" AND b1.rid=a.attachid\n"
1561 1589 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
" AND b2.uuid=a.src\n"
1562 1590 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
" AND b2.size>0\n"
@@ -1570,23 +1598,25 @@
1570 1598 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zTarget = db_column_text(&q, 2);
1571 1599 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zName = db_column_text(&q, 3);
1572 1600 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const int isLatest = db_column_int(&q, 4);
1573 1601 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const int sz = db_column_int(&q, 5);
1574 1602 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zUuid = db_column_text(&q, 6);
1575 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- const char *zComment = db_column_text(&q, 7);
1603 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zUser = db_column_text(&q, 7);
1604 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ const char *zComment = db_column_text(&q, 8);
1576 1605 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if(!i++){
1577 1606 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_append_char(pOut, '[');
1578 1607 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}else{
1579 1608 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_append_char(pOut, ',');
1580 1609 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
1581 1610 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_appendf(
1582 1611 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
pOut,
1583 1612 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"{\"uuid\": %!j, \"src\": %!j, \"target\": %!j, "
1584 1613 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
"\"filename\": %!j, \"size\":%d, \"mtime\": %!j, "
1585 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- "\"isLatest\": %s,\"comment\": ",
1614 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ "\"isLatest\": %s, \"user\": %!j, \"comment\": ",
1586 1615 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zUuid, zSrc, zTarget,
1587 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- zName, sz, zTime, isLatest ? "true" : "false"
1616 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zName, sz, zTime, isLatest ? "true" : "false",
1617 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ zUser
1588 1618 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
);
1589 1619 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( zComment && zComment[0] ){
1590 1620 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_appendf(pOut, "%!j", zComment);
1591 1621 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}else{
1592 1622 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
blob_append_literal(pOut, "null");
@@ -1609,35 +1639,39 @@
1609 1639 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
1610 1640 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
1611 1641 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
/*
1612 1642 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** COMMAND: test-attachments-to-json
1613 1643 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
**
1614 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** Usage: %fossil test-attachments-to-json FULL_TARGET_ID
1644 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** Usage: %fossil test-attachments-to-json TARGET_ID
1615 1645 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
**
1616 1646 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** Options:
1617 1647 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** --old List all versions of attachments. Default is to
1618 1648 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** list only the latest.
1649 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** --full Require a full target ID, not a prefix.
1619 1650 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
**
1620 1651 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
** Emits a JSON array of attachments for the given attachment target.
1621 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** The given ID must be a full wiki page name, ticket hash, tech-note
1622 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- ** hash, or forum post hash. It does not accept partial prefixes.
1652 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** The given ID must be a wiki page name, ticket hash, tech-note hash,
1653 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** or forum post hash. By default it accepts prefixes but does not
1654 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** detection of ambiguity or cross-type prefix collisions so may emit
1655 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ ** curious results if given short/colliding IDs.
1623 1656 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
*/
1624 1657 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
void test_attachments_to_json_cmd(void){
1625 1658 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
Manifest *pManifest;
1626 1659 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
Blob b = BLOB_INITIALIZER;
1627 1660 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
int bLatestOnly = find_option("old",0,0)==0;
1628 1661 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
int emptyPolicy = 1;
1629 1662 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
int rid;
1663 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ int bFullId = find_option("full",0,0)!=0;
1630 1664 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
const char *zTarget;
1631 1665 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
verify_all_options();
1632 1666 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
db_find_and_open_repository(0, 0);
1633 1667 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( g.argc<3 ){
1634 1668 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
usage("test-attachments-to-json TARGET_ID");
1635 1669 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
return;
1636 1670 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
1637 1671 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
zTarget = g.argv[2];
1638 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
- rid = attachment_resolve_target(zTarget);
1672 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
+ rid = attachment_target_rid(zTarget, bFullId);
1639 1673 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
if( 0==rid ){
1640 1674 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
fossil_fatal("Cannot resolve ID.");
1641 1675 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
}
1642 1676 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
pManifest = manifest_get(rid, CFTYPE_ANY, NULL);
1643 1677 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!
attachments_to_json(pManifest, &b, bLatestOnly, emptyPolicy);
1644 1678 { copied = false; pop = false }, 1000)" :class="copied && 'copied'">Copy link Copied!