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 *zTarget = db_column_text(&q, 2); 69 const char *zFilename = db_column_text(&q, 2); | 70 const char *zFilename = db_column_text(&q, 3); 70 const char *zComment = db_column_text(&q, 3); | 71 const char *zComment = db_column_text(&q, 4); 71 const char *zUser = 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 } > 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 } 79 @ <p><b>%h(zFilename)</b> | 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; 88 } 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(); > 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 "VALUES(%d,%.17g,%Q,%Q,%Q,%Q,%Q);", 1126 m.zAttachTarget, m.zAttachName | 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==" > 1132 "(SELECT max(mtime) FROM attachment" > 1133 " WHERE target=%Q AND filename=%Q))" 1130 " WHERE mtime<%.17g AND target=%Q AND filename=%Q", | 1134 " WHERE target=%Q AND filename=%Q", 1131 m.rDate, m.zAttachSrc, m.zComment, m.zUser, < > 1135 m.zAttachTarget, m.zAttachName, 1132 m.rDate, 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(