NSData *fileData2;
NSData *fileData3;
NSString *attachmentName;
+
+ NSArray *attachmentNames;
}
@end
@implementation UIxMailEditorAttach
- (void)dealloc {
+ [self->attachmentNames release];
[self->attachmentName release];
[self->filePath1 release];
[self->filePath2 release];
return self->fileData3;
}
+- (NSArray *)attachmentNames {
+ NSArray *a;
+
+ if (self->attachmentNames != nil)
+ return self->attachmentNames;
+
+ a = [[self clientObject] fetchAttachmentNames];
+ a = [a sortedArrayUsingSelector:@selector(compare:)];
+ self->attachmentNames = [a copy];
+ return self->attachmentNames;
+}
+- (BOOL)hasAttachments {
+ return [[self attachmentNames] count] > 0 ? YES : NO;
+}
+
/* requests */
- (BOOL)shouldTakeValuesFromRequest:(WORequest *)_rq inContext:(WOContext*)_c{
/* operations */
+- (NSString *)defaultPathExtension {
+ return @"txt";
+}
+
+- (NSString *)newAttachmentName {
+ NSArray *usedNames;
+ unsigned i;
+
+ usedNames = [[self clientObject] fetchAttachmentNames];
+ for (i = [usedNames count]; i < 100; i++) {
+ NSString *name;
+
+ name = [NSString stringWithFormat:@"attachment%d", i];
+ if (![usedNames containsObject:name])
+ return name;
+ }
+ [self logWithFormat:@"ERROR: too many attachments?!"];
+ return nil;
+}
+
+- (NSString *)fixupAttachmentName:(NSString *)_name {
+ NSString *pe;
+ NSRange r;
+
+ if (_name == nil)
+ return nil;
+
+ pe = [_name pathExtension];
+ if ([pe length] == 0)
+ /* would be better to check the content-type, but well */
+ pe = [self defaultPathExtension];
+
+ r = [_name rangeOfString:@"/"];
+ if (r.length > 0) _name = [_name lastPathComponent];
+
+ r = [_name rangeOfString:@" "];
+ if (r.length > 0)
+ _name = [_name stringByReplacingString:@" " withString:@"_"];
+
+ if ([_name hasPrefix:@"."]) {
+ _name = [@"dotfile-" stringByAppendingString:
+ [_name substringFromIndex:1]];
+ }
+
+ // TODO: should we need to check for umlauts?
+
+ if ([_name length] == 0)
+ return [[self newAttachmentName] stringByAppendingPathExtension:pe];
+
+ return _name;
+}
+
- (BOOL)saveFileData:(NSData *)_data name:(NSString *)_name {
- [self logWithFormat:@"TODO: save attachment %@, length %d",
- _name, [_data length]];
- return NO;
+ if (_data == nil)
+ return NO;
+ if ([_name length] == 0) {
+ _name = [self newAttachmentName];
+ _name = [_name stringByAppendingPathExtension:[self defaultPathExtension]];
+ }
+
+ if ((_name = [self fixupAttachmentName:_name]) == nil)
+ return nil;
+
+ // TODO: add size limit?
+ return [[self clientObject] saveAttachment:_data withName:_name];
}
/* actions */
- (id)viewAttachmentsAction {
- [self logWithFormat:@"view attachments ..."];
+ [self debugWithFormat:@"view attachments ..."];
return self;
}
- (id)attachAction {
- [self logWithFormat:@"should save ..."];
-
- // TODO: error handling!
+ BOOL ok;
+ ok = YES;
if ([self->fileData1 length] > 0)
- [self saveFileData:self->fileData1 name:[self filePath1]];
- if ([self->fileData2 length] > 0)
- [self saveFileData:self->fileData2 name:[self filePath2]];
- if ([self->fileData3 length] > 0)
+ ok = [self saveFileData:self->fileData1 name:[self filePath1]];
+ if (ok && [self->fileData2 length] > 0)
+ ok = [self saveFileData:self->fileData2 name:[self filePath2]];
+ if (ok && [self->fileData3 length] > 0)
[self saveFileData:self->fileData3 name:[self filePath3]];
- return self;
+ if (!ok) {
+ // TODO: improve error handling
+ return [NSException exceptionWithHTTPStatus:500 /* server error */
+ reason:@"failed to save attachment ..."];
+ }
+
+ return [self redirectToLocation:@"viewAttachments"];
}
- (id)deleteAttachmentAction {
- [self logWithFormat:@"delete attachment: %@", [self attachmentName]];
- return self;
+ if (![[self clientObject] deleteAttachmentWithName:[self attachmentName]]) {
+ // TODO: improve error handling
+ return [NSException exceptionWithHTTPStatus:500 /* server error */
+ reason:@"failed to delete attachment ..."];
+ }
+
+ return [self redirectToLocation:@"viewAttachments"];
}
@end /* UIxMailEditorAttach */
</div>
<div id="attachment_list">
- <div style="padding: 4px;">
-
- <div class="embedwhite_out">
- <div class="embedwhite_in">
- <table border="0" width="100%" cellspacing="0" cellpadding="1">
- <tr class="tableview">
- <td class="tbtv_headercell">
- Attachments
- </td>
- <td class="tbtv_headercell" width="10%">
- <entity name="nbsp" />
- </td>
- </tr>
-
- <var:foreach list="clientObject.fetchAttachmentNames"
- item="attachmentName">
- <tr class="tableview">
- <td><var:string value="attachmentName" /></td>
- <td>
- <a href="deleteAttachment"
- var:_attachmentName="attachmentName"
- >delete</a>
- </td>
- </tr>
- </var:foreach>
- </table>
- </div>
+ <div style="padding: 4px;">
+ <var:if condition="hasAttachments">
+ <div class="embedwhite_out">
+ <div class="embedwhite_in">
+ <table border="0" width="100%" cellspacing="0" cellpadding="1">
+ <tr class="tableview">
+ <td class="tbtv_headercell">
+ Attachments
+ </td>
+ <td class="tbtv_headercell" width="10%">
+ <entity name="nbsp" />
+ </td>
+ </tr>
+
+ <var:foreach list="attachmentNames" item="attachmentName">
+ <tr class="tableview">
+ <td><var:string value="attachmentName" /></td>
+ <td>
+ <a href="deleteAttachment"
+ var:_attachmentName="attachmentName"
+ >delete</a>
+ </td>
+ </tr>
+ </var:foreach>
+ </table>
+ </div>
+ </div>
+ </var:if>
</div>
- </div>
</div>
</form>
</body>