Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| SHA1 Hash: | 1fcfa000b4a1f014d4f9ec05096f1895b15c65ab |
|---|---|
| Date: | 2010-03-17 19:57:01 |
| User: | drh |
| Comment: | Added screens for adding and listing attachments. |
Tags And Properties
- bgcolor=#c0ffc0 inherited from [c3d7df650b]
- branch=experimental inherited from [c3d7df650b]
- sym-experimental inherited from [c3d7df650b]
Changes
Changes to src/attach.c
41 Blob sql; 41 Blob sql;
42 Stmt q; 42 Stmt q;
43 43
44 if( zPage && zTkt ) zTkt = 0; 44 if( zPage && zTkt ) zTkt = 0;
45 login_check_credentials(); 45 login_check_credentials();
46 blob_zero(&sql); 46 blob_zero(&sql);
47 blob_append(&sql, 47 blob_append(&sql,
48 "SELECT datetime(mtime,'localtime'), src, filename, comment, user" | 48 "SELECT datetime(mtime,'localtime'), src, target, filename, comment, user"
49 " FROM attachment", 49 " FROM attachment",
50 -1 50 -1
51 ); 51 );
52 if( zPage ){ 52 if( zPage ){
53 if( g.okRdWiki==0 ) login_needed(); 53 if( g.okRdWiki==0 ) login_needed();
54 style_header("Attachments To %h", zPage); 54 style_header("Attachments To %h", zPage);
55 blob_appendf(&sql, " WHERE target=%Q", zPage); 55 blob_appendf(&sql, " WHERE target=%Q", zPage);
................................................................................................................................................................................
61 if( g.okRdTkt==0 && g.okRdWiki==0 ) login_needed(); 61 if( g.okRdTkt==0 && g.okRdWiki==0 ) login_needed();
62 style_header("All Attachments"); 62 style_header("All Attachments");
63 } 63 }
64 blob_appendf(&sql, " ORDER BY mtime DESC"); 64 blob_appendf(&sql, " ORDER BY mtime DESC");
65 db_prepare(&q, "%s", blob_str(&sql)); 65 db_prepare(&q, "%s", blob_str(&sql));
66 while( db_step(&q)==SQLITE_ROW ){ 66 while( db_step(&q)==SQLITE_ROW ){
67 const char *zDate = db_column_text(&q, 0); 67 const char *zDate = db_column_text(&q, 0);
68 const char *zSrc = db_column_text(&q, 1); | 68 /* const char *zSrc = db_column_text(&q, 1); */
69 const char *zFilename = db_column_text(&q, 2); | 69 const char *zTarget = db_column_text(&q, 2);
70 const char *zComment = db_column_text(&q, 3); | 70 const char *zFilename = db_column_text(&q, 3);
71 const char *zUser = db_column_text(&q, 4); | 71 const char *zComment = db_column_text(&q, 4);
> 72 const char *zUser = db_column_text(&q, 5);
72 int i; 73 int i;
> 74 char *zUrlTail;
73 for(i=0; zFilename[i]; i++){ 75 for(i=0; zFilename[i]; i++){
74 if( zFilename[i]=='/' && zFilename[i+1]!=0 ){ 76 if( zFilename[i]=='/' && zFilename[i+1]!=0 ){
75 zFilename = &zFilename[i+1]; 77 zFilename = &zFilename[i+1];
76 i = -1; 78 i = -1;
77 } 79 }
78 } 80 }
79 @ <p><b>%h(zFilename)</b> | 81 if( strlen(zTarget)==UUID_SIZE && validate16(zTarget,UUID_SIZE) ){
> 82 zUrlTail = mprintf("tkt=%s&file=%t", zTarget, zFilename);
> 83 }else{
> 84 zUrlTail = mprintf("page=%s&file=%t", zTarget, zFilename);
> 85 }
> 86 @ <p><a href="/attachview?%s(zUrlTail)">%h(zFilename)</a>
> 87 @ [<a href="/attachdownload?%s(zUrlTail)">download</a>]<br>
80 @ %w(zComment)<br> 88 @ %w(zComment)<br>
81 @ Added by %h(zUser) on %s(zDate)</p> 89 @ Added by %h(zUser) on %s(zDate)</p>
82 @ 90 @
> 91 free(zUrlTail);
83 } 92 }
84 db_finalize(&q); 93 db_finalize(&q);
85 style_footer(); 94 style_footer();
86 <
87 return; 95 return;
> 96 }
> 97
> 98 /*
> 99 ** WEBPAGE: attachadd
> 100 **
> 101 ** tkt=TICKETUUID
> 102 ** page=WIKIPAGE
> 103 ** from=URL
> 104 **
> 105 ** Add a new attachment.
> 106 */
> 107 void attachadd_page(void){
> 108 const char *zPage = P("page");
> 109 const char *zTkt = P("tkt");
> 110 const char *zFrom = PD("from", "/home");
> 111 const char *aContent = P("f");
> 112 const char *zName = PD("f:filename","unknown");
> 113 const char *zTarget;
> 114 const char *zTargetType;
> 115 int szContent = atoi(PD("f:bytes","0"));
> 116
> 117 if( P("cancel") ) cgi_redirect(zFrom);
> 118 if( zPage && zTkt ) fossil_redirect_home();
> 119 if( zPage==0 && zTkt==0 ) fossil_redirect_home();
> 120 login_check_credentials();
> 121 if( zPage ){
> 122 if( g.okApndWiki==0 || g.okAttach==0 ) login_needed();
> 123 if( !db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'", zPage) ){
> 124 fossil_redirect_home();
> 125 }
> 126 zTarget = zPage;
> 127 zTargetType = mprintf("Wiki Page <a href=\"%s/wiki?name=%h\">%h</a>",
> 128 g.zTop, zPage, zPage);
> 129 }else{
> 130 if( g.okApndTkt==0 || g.okAttach==0 ) login_needed();
> 131 if( !db_exists("SELECT 1 FROM tag WHERE tagname='tkt-%q'", zTkt) ){
> 132 fossil_redirect_home();
> 133 }
> 134 zTarget = zTkt;
> 135 zTargetType = mprintf("Ticket <a href=\"%s/tktview?name=%.10s\">%.10s</a>",
> 136 g.zTop, zTkt, zTkt);
> 137 }
> 138 if( P("ok") && szContent>0 ){
> 139 Blob content;
> 140 Blob manifest;
> 141 Blob cksum;
> 142 char *zUUID;
> 143 const char *zComment;
> 144 char *zDate;
> 145 int rid;
> 146 int i, n;
> 147
> 148 db_begin_transaction();
> 149 blob_init(&content, aContent, szContent);
> 150 rid = content_put(&content, 0, 0);
> 151 zUUID = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
> 152 blob_zero(&manifest);
> 153 for(i=n=0; zName[i]; i++){
> 154 if( zName[i]=='/' || zName[i]=='\\' ) n = i;
> 155 }
> 156 zName += n;
> 157 if( zName[0]==0 ) zName = "unknown";
> 158 blob_appendf(&manifest, "A %F %F %s\n", zName, zTarget, zUUID);
> 159 zComment = PD("comment", "");
> 160 while( isspace(zComment[0]) ) zComment++;
> 161 n = strlen(zComment);
> 162 while( n>0 && isspace(zComment[n-1]) ){ n--; }
> 163 if( n>0 ){
> 164 blob_appendf(&manifest, "C %F\n", zComment);
> 165 }
> 166 zDate = db_text(0, "SELECT datetime('now')");
> 167 zDate[10] = 'T';
> 168 blob_appendf(&manifest, "D %s\n", zDate);
> 169 blob_appendf(&manifest, "U %F\n", g.zLogin ? g.zLogin : "nobody");
> 170 md5sum_blob(&manifest, &cksum);
> 171 blob_appendf(&manifest, "Z %b\n", &cksum);
> 172 rid = content_put(&manifest, 0, 0);
> 173 manifest_crosslink(rid, &manifest);
> 174 db_end_transaction(0);
> 175 cgi_redirect(zFrom);
> 176 }
> 177 style_header("Add Attachment");
> 178 @ <h1>Add Attachment To %s(zTargetType)</h1>
> 179 @ <form action="%s(g.zBaseURL)/attachadd" method="POST"
> 180 @ enctype="multipart/form-data">
> 181 @ File to Attach:
> 182 @ <input type="file" name="f" size="60"><br>
> 183 @ Description:<br>
> 184 @ <textarea name="comment" cols=80 rows=5 wrap="virtual"></textarea><br>
> 185 if( zTkt ){
> 186 @ <input type="hidden" name="tkt" value="%h(zTkt)">
> 187 }else{
> 188 @ <input type="hidden" name="page" value="%h(zPage)">
> 189 }
> 190 @ <input type="hidden" name="from" value="%h(zFrom)">
> 191 @ <input type="submit" name="ok" value="Add Attachment">
> 192 @ <input type="submit" name="can" value="Cancel">
> 193 @ </form>
> 194 style_footer();
88 } 195 }
Changes to src/manifest.c
194 && !wiki_name_is_wellformed((const unsigned char *)zTarget) ){ 194 && !wiki_name_is_wellformed((const unsigned char *)zTarget) ){
195 goto manifest_syntax_error; 195 goto manifest_syntax_error;
196 } 196 }
197 if( blob_size(&a3)>0 197 if( blob_size(&a3)>0
198 && (blob_size(&a3)!=UUID_SIZE || !validate16(zSrc, UUID_SIZE)) ){ 198 && (blob_size(&a3)!=UUID_SIZE || !validate16(zSrc, UUID_SIZE)) ){
199 goto manifest_syntax_error; 199 goto manifest_syntax_error;
200 } 200 }
201 p->zAttachName = zName; | 201 p->zAttachName = file_tail(zName);
202 p->zAttachSrc = zSrc; 202 p->zAttachSrc = zSrc;
203 p->zAttachTarget = zTarget; 203 p->zAttachTarget = zTarget;
204 break; 204 break;
205 } 205 }
206 206
207 /* 207 /*
208 ** C <comment> 208 ** C <comment>
................................................................................................................................................................................
1117 tag_insert(zTag, 1, 0, rid, m.rDate, rid); 1117 tag_insert(zTag, 1, 0, rid, m.rDate, rid);
1118 free(zTag); 1118 free(zTag);
1119 db_multi_exec("INSERT OR IGNORE INTO pending_tkt VALUES(%Q)", 1119 db_multi_exec("INSERT OR IGNORE INTO pending_tkt VALUES(%Q)",
1120 m.zTicketUuid); 1120 m.zTicketUuid);
1121 } 1121 }
1122 if( m.type==CFTYPE_ATTACHMENT ){ 1122 if( m.type==CFTYPE_ATTACHMENT ){
1123 db_multi_exec( 1123 db_multi_exec(
1124 "INSERT OR IGNORE INTO attachment(mtime, target, filename)" | 1124 "INSERT INTO attachment(attachid, mtime, src, target,"
1125 "VALUES(0.0,%Q,%Q)", | 1125 "filename, comment, user)"
1126 m.zAttachTarget, m.zAttachName | 1126 "VALUES(%d,%.17g,%Q,%Q,%Q,%Q,%Q);",
> 1127 rid, m.rDate, m.zAttachSrc, m.zAttachTarget, m.zAttachName,
> 1128 (m.zComment ? m.zComment : ""), m.zUser
1127 ); 1129 );
1128 db_multi_exec( 1130 db_multi_exec(
1129 "UPDATE attachment SET mtime=%.17g, src=%Q, comment=%Q, user=%Q" | 1131 "UPDATE attachment SET isLatest = (mtime=="
1130 " WHERE mtime<%.17g AND target=%Q AND filename=%Q", | 1132 "(SELECT max(mtime) FROM attachment"
1131 m.rDate, m.zAttachSrc, m.zComment, m.zUser, | 1133 " WHERE target=%Q AND filename=%Q))"
1132 m.rDate, m.zAttachTarget, m.zAttachName | 1134 " WHERE target=%Q AND filename=%Q",
> 1135 m.zAttachTarget, m.zAttachName,
> 1136 m.zAttachTarget, m.zAttachName
1133 ); 1137 );
1134 } 1138 }
1135 db_end_transaction(0); 1139 db_end_transaction(0);
1136 manifest_clear(&m); 1140 manifest_clear(&m);
1137 return 1; 1141 return 1;
1138 } 1142 }
Changes to src/schema.c
325 @ ); 325 @ );
326 @ CREATE INDEX backlink_src ON backlink(srcid, srctype); 326 @ CREATE INDEX backlink_src ON backlink(srcid, srctype);
327 @ 327 @
328 @ -- Each attachment is an entry in the following table. Only 328 @ -- Each attachment is an entry in the following table. Only
329 @ -- the most recent attachment (identified by the D card) is saved. 329 @ -- the most recent attachment (identified by the D card) is saved.
330 @ -- 330 @ --
331 @ CREATE TABLE attachment( 331 @ CREATE TABLE attachment(
> 332 @ attachid INTEGER PRIMARY KEY, -- Local id for this attachment
> 333 @ isLatest BOOLEAN DEFAULT 0, -- True if this is the one to use
332 @ mtime TIMESTAMP, -- Time when attachment last changed 334 @ mtime TIMESTAMP, -- Time when attachment last changed
333 @ src TEXT, -- UUID of the attachment. NULL to delete 335 @ src TEXT, -- UUID of the attachment. NULL to delete
334 @ target TEXT, -- Object attached to | 336 @ target TEXT, -- Object attached to. Wikiname or Tkt UUID
335 @ filename TEXT, -- Filename for the attachment 337 @ filename TEXT, -- Filename for the attachment
336 @ comment TEXT, -- Comment associated with this attachment 338 @ comment TEXT, -- Comment associated with this attachment
337 @ user TEXT, -- Name of user adding attachment | 339 @ user TEXT -- Name of user adding attachment
338 @ PRIMARY KEY(target, filename) <
339 @ ); 340 @ );
> 341 @ CREATE INDEX attachment_idx1 ON attachment(target, filename, mtime);
> 342 @ CREATE INDEX attachment_idx2 ON attachment(src);
340 @ 343 @
341 @ -- Template for the TICKET table 344 @ -- Template for the TICKET table
342 @ -- 345 @ --
343 @ -- NB: when changing the schema of the TICKET table here, also make the 346 @ -- NB: when changing the schema of the TICKET table here, also make the
344 @ -- same change in tktsetup.c. 347 @ -- same change in tktsetup.c.
345 @ -- 348 @ --
346 @ CREATE TABLE ticket( 349 @ CREATE TABLE ticket(