From: wolfgang Date: Wed, 12 Dec 2007 16:33:27 +0000 (+0000) Subject: git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1297 d1b88da0-ebda-0310... X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b39d78a6c7c1a0e1ebe914b8c2f1ef3560077eea;p=scalable-opengroupware.org git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1297 d1b88da0-ebda-0310-925b-ed51d893ca5b --- diff --git a/ChangeLog b/ChangeLog index 9d9c6ca6..b1885e35 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2007-12-12 Wolfgang Sourdeau + + * SoObjects/SOGo/SOGoContentObject.m ([SOGoContentObject + -davCreationDate]) + ([SOGoContentObject -davLastModified]) + ([SOGoContentObject -davContentLength]): implemented dav methods. + +2007-12-10 Francis Lachapelle + + * SoObjects/Mailer/SOGoMailBodyPart.m ([SOGoMailBodyPart + -GETAction:]): when asAttachment is set to true, the header + "content-disposition" is set to "attachment" so browsers like IE + and Safari properly asks the user to save the file. + +2007-12-10 Wolfgang Sourdeau + + * UI/MailPartViewers/UIxMailPartHTMLViewer.m + ([UIxMailPartHTMLViewer -flatContentAsString]): when in + UIxMailPartAlternative, scan the filenames of potential cid at the + same level as our parent. + 2007-12-07 Wolfgang Sourdeau * Main/SOGo.m ([SOGo -run]): the table creation script now have a diff --git a/SOPE/GDLContentStore/ChangeLog b/SOPE/GDLContentStore/ChangeLog index 058a7edb..af7d8047 100644 --- a/SOPE/GDLContentStore/ChangeLog +++ b/SOPE/GDLContentStore/ChangeLog @@ -1,3 +1,10 @@ +2007-12-12 Wolfgang Sourdeau + + * GCSFolder.m ([GCSFolder -creationDateOfEntryWithName:]): new + method that returns the creation date of the specified entry. + ([GCSFolder -lastModificationOfEntryWithName:]): same as above for + the last modification time. + 2007-11-27 Wolfgang Sourdeau * GCSFolder.m ([GCSFolder -versionOfContentWithName:], [GCSFolder diff --git a/SOPE/GDLContentStore/GCSFolder.h b/SOPE/GDLContentStore/GCSFolder.h index 7209517e..73b608cc 100644 --- a/SOPE/GDLContentStore/GCSFolder.h +++ b/SOPE/GDLContentStore/GCSFolder.h @@ -105,6 +105,8 @@ - (NSArray *)allSubFolderNames; - (NSNumber *)versionOfContentWithName:(NSString *)_name; +- (NSCalendarDate *)creationDateOfEntryWithName:(NSString *)_name; +- (NSCalendarDate *)lastModificationOfEntryWithName:(NSString *)_name; - (NSString *)fetchContentWithName:(NSString *)_name; - (NSException *)writeContent:(NSString *)_content toName:(NSString *)_name diff --git a/SOPE/GDLContentStore/GCSFolder.m b/SOPE/GDLContentStore/GCSFolder.m index e6ec63c7..23cbbdec 100644 --- a/SOPE/GDLContentStore/GCSFolder.m +++ b/SOPE/GDLContentStore/GCSFolder.m @@ -305,6 +305,24 @@ static GCSStringFormatter *stringFormatter = nil; ignoreDeleted: YES]; } +- (NSCalendarDate *)creationDateOfEntryWithName:(NSString *)_name { + int seconds; + + seconds = [[self _fetchValueOfColumn:@"c_creationdate" inContentWithName:_name + ignoreDeleted: YES] intValue]; + + return [NSCalendarDate dateWithTimeIntervalSince1970: seconds]; +} + +- (NSCalendarDate *)lastModificationOfEntryWithName:(NSString *)_name { + int seconds; + + seconds = [[self _fetchValueOfColumn:@"c_lastmodified" inContentWithName:_name + ignoreDeleted: YES] intValue]; + + return [NSCalendarDate dateWithTimeIntervalSince1970: seconds]; +} + - (NSNumber *)deletionOfContentWithName:(NSString *)_name { return [self _fetchValueOfColumn:@"c_deleted" inContentWithName:_name ignoreDeleted: NO]; diff --git a/SOPE/NGCards/ChangeLog b/SOPE/NGCards/ChangeLog index 3ddc7293..5e6348e4 100644 --- a/SOPE/NGCards/ChangeLog +++ b/SOPE/NGCards/ChangeLog @@ -1,3 +1,9 @@ +2007-12-12 Wolfgang Sourdeau + + * iCalTimeZone.m ([iCalTimeZone -periodForDate:date]): at least + one timezone period is needed so we might need to fallback on the + only one present if the other does not exist. + 2007-11-29 Wolfgang Sourdeau * iCalDateTime.m ([iCalDateTime -timeZone]): log a message if the diff --git a/SOPE/NGCards/iCalTimeZone.m b/SOPE/NGCards/iCalTimeZone.m index 0e2e56be..cd7afbe9 100644 --- a/SOPE/NGCards/iCalTimeZone.m +++ b/SOPE/NGCards/iCalTimeZone.m @@ -89,13 +89,18 @@ forDate: date]; standardOccurence = [self _occurenceForPeriodNamed: @"standard" forDate: date]; - if ([date earlierDate: daylightOccurence] == date - || [date earlierDate: standardOccurence] == standardOccurence) + + if (!standardOccurence) + period = (iCalTimeZonePeriod *) [self uniqueChildWithTag: @"daylight"]; + else if (!daylightOccurence) + period = (iCalTimeZonePeriod *) [self uniqueChildWithTag: @"standard"]; + else if ([date earlierDate: daylightOccurence] == date + || [date earlierDate: standardOccurence] == standardOccurence) period = (iCalTimeZonePeriod *) [self uniqueChildWithTag: @"standard"]; else period = (iCalTimeZonePeriod *) [self uniqueChildWithTag: @"daylight"]; - NSLog (@"chosen period: '%@'", [period tag]); +// NSLog (@"chosen period: '%@'", [period tag]); return period; } diff --git a/SoObjects/Mailer/SOGoMailBodyPart.h b/SoObjects/Mailer/SOGoMailBodyPart.h index c3d6509d..0effd14c 100644 --- a/SoObjects/Mailer/SOGoMailBodyPart.h +++ b/SoObjects/Mailer/SOGoMailBodyPart.h @@ -41,6 +41,7 @@ NSArray *pathToPart; NSString *identifier; id partInfo; + BOOL asAttachment; } /* hierarchy */ @@ -57,6 +58,8 @@ - (id) partInfo; - (NSData *) fetchBLOB; +- (void) setAsAttachment; +- (BOOL) asAttachment; /* factory */ diff --git a/SoObjects/Mailer/SOGoMailBodyPart.m b/SoObjects/Mailer/SOGoMailBodyPart.m index 0ce0fcd7..6fac084d 100644 --- a/SoObjects/Mailer/SOGoMailBodyPart.m +++ b/SoObjects/Mailer/SOGoMailBodyPart.m @@ -63,13 +63,28 @@ static BOOL debugOn = NO; NSLog(@"Note(SOGoMailBodyPart): etag caching disabled!"); } -- (void)dealloc { +- (id) init +{ + if ((self = [super init])) + asAttachment = NO; + + return self; +} + +- (void) dealloc +{ [self->partInfo release]; [self->identifier release]; [self->pathToPart release]; [super dealloc]; } +- (void) setAsAttachment +{ + asAttachment = YES; +} + + /* hierarchy */ - (SOGoMailObject *)mailObject { @@ -178,6 +193,8 @@ static BOOL debugOn = NO; /* lookup body part */ if ([self isBodyPartKey:_key inContext:_ctx]) obj = [self lookupImap4BodyPartKey:_key inContext:_ctx]; + else if ([_key isEqualToString: @"asAttachment"]) + [self setAsAttachment]; /* should check whether such a filename exist in the attached names */ if (!obj) obj = self; @@ -283,14 +300,18 @@ static BOOL debugOn = NO; /* try type from body structure info */ - parts = [self contentTypeForBodyPartInfo: [self partInfo]]; - contentType = [[parts componentsSeparatedByString: @";"] objectAtIndex: 0]; - - if (![contentType length]) - { - extension = [[self nameInContainer] pathExtension]; - contentType = [self contentTypeForPathExtension: extension]; - } + if (asAttachment) + contentType = @"application/octet-stream"; + else { + parts = [self contentTypeForBodyPartInfo: [self partInfo]]; + contentType = [[parts componentsSeparatedByString: @";"] objectAtIndex: 0]; + + if (![contentType length]) + { + extension = [[self nameInContainer] pathExtension]; + contentType = [self contentTypeForPathExtension: extension]; + } + } return contentType; } @@ -301,7 +322,7 @@ static BOOL debugOn = NO; NSException *error; WOResponse *r; NSData *data; - NSString *etag, *mimeType; + NSString *etag, *mimeType, *fileName; if ((error = [self matchesRequestConditionInContext:_ctx]) != nil) { // TODO: currently we fetch the body structure to get here - check this! @@ -333,6 +354,17 @@ static BOOL debugOn = NO; [r setHeader: mimeType forKey:@"content-type"]; [r setHeader: [NSString stringWithFormat:@"%d", [data length]] forKey: @"content-length"]; + + if (asAttachment) { + fileName = [[[self partInfo] objectForKey: @"parameterList"] objectForKey: @"name"]; + if (!fileName) + fileName = [[[[self partInfo] objectForKey: @"disposition"] + objectForKey: @"parameterList"] + objectForKey: @"filename"]; + if ([fileName length]) + [r setHeader: [NSString stringWithFormat: @"attachment; filename=%@", fileName] + forKey: @"content-disposition"]; + } if ((etag = [self davEntityTag]) != nil) [r setHeader:etag forKey:@"etag"]; diff --git a/SoObjects/SOGo/SOGoContentObject.m b/SoObjects/SOGo/SOGoContentObject.m index c82fc589..73cc1401 100644 --- a/SoObjects/SOGo/SOGoContentObject.m +++ b/SoObjects/SOGo/SOGoContentObject.m @@ -29,6 +29,7 @@ #import #import +#import "NSCalendarDate+SOGo.h" #import "SOGoGCSFolder.h" #import "SOGoUser.h" #import "SOGoPermissions.h" @@ -320,6 +321,30 @@ } /* WebDAV */ +- (NSString *) davCreationDate +{ + NSCalendarDate *date; + + date = [[self ocsFolder] creationDateOfEntryWithName: nameInContainer]; + + return [date rfc822DateString]; +} + +- (NSString *) davLastModified +{ + NSCalendarDate *date; + + date = [[self ocsFolder] lastModificationOfEntryWithName: nameInContainer]; + + return [date rfc822DateString]; +} + +- (NSString *) davContentLength +{ + return [NSString stringWithFormat: @"%u", + [content + lengthOfBytesUsingEncoding: NSISOLatin1StringEncoding]]; +} - (NSException *) davMoveToTargetObject: (id) _target newName: (NSString *) _name diff --git a/UI/MailPartViewers/UIxMailPartHTMLViewer.m b/UI/MailPartViewers/UIxMailPartHTMLViewer.m index 835de070..50f79391 100644 --- a/UI/MailPartViewers/UIxMailPartHTMLViewer.m +++ b/UI/MailPartViewers/UIxMailPartHTMLViewer.m @@ -432,17 +432,26 @@ andBaseURL: (NSString *) url intoDictionary: (NSMutableDictionary *) attachmentIds { - NSString *bodyId; + NSString *bodyId, *filename; + NSMutableString *attachmentURL; bodyId = [part objectForKey: @"bodyId"]; if ([bodyId length] > 0) { + filename = [[part objectForKey: @"parameterList"] objectForKey: @"name"]; + if (!filename) + filename = [[[part objectForKey: @"disposition"] + objectForKey: @"parameterList"] + objectForKey: @"filename"]; if ([bodyId hasPrefix: @"<"]) bodyId = [bodyId substringFromIndex: 1]; if ([bodyId hasSuffix: @">"]) bodyId = [bodyId substringToIndex: [bodyId length] - 1]; - [attachmentIds setObject: [url stringByAppendingFormat: @"/%d", count] - forKey: bodyId]; + attachmentURL = [NSMutableString stringWithString: url]; + [attachmentURL appendFormat: @"/%d", count]; + if ([filename length]) + [attachmentURL appendFormat: @"/%@", filename]; + [attachmentIds setObject: attachmentURL forKey: bodyId]; } } @@ -451,7 +460,7 @@ NSMutableDictionary *attachmentIds; UIxMailPartViewer *parent; unsigned int count, max; - NSMutableString *url; +// NSMutableString *url; NSString *baseURL; NSArray *parts; @@ -463,18 +472,18 @@ isEqualToString: @"UIxMailPartAlternativeViewer"]) { baseURL = [[self clientObject] baseURLInContext: context]; - url = [NSMutableString new]; - [url appendString: baseURL]; - [url appendFormat: @"/%@", [partPath componentsJoinedByString: @"/"]]; - [url deleteCharactersInRange: NSMakeRange([url length] - 2, 2)]; - parts = [[parent bodyInfo] objectForKey: @"parts"]; +// url = [NSMutableString new]; +// [url appendString: baseURL]; +// [url appendFormat: @"/%@", [partPath componentsJoinedByString: @"/"]]; +// [url deleteCharactersInRange: NSMakeRange([url length] - 4, 4)]; + parts = [[[parent parent] bodyInfo] objectForKey: @"parts"]; max = [parts count]; for (count = 0; count < max; count++) [self _convertReferencesForPart: [parts objectAtIndex: count] withCount: count + 1 - andBaseURL: url + andBaseURL: baseURL intoDictionary: attachmentIds]; - [url release]; +// [url release]; } return attachmentIds; diff --git a/UI/MailerUI/English.lproj/Localizable.strings b/UI/MailerUI/English.lproj/Localizable.strings index d745a638..5e348b6a 100644 --- a/UI/MailerUI/English.lproj/Localizable.strings +++ b/UI/MailerUI/English.lproj/Localizable.strings @@ -148,7 +148,7 @@ "Create Filter From Message..." = "Create Filter From Message..."; /* Image Popup menu */ -"View Image" = "View Image"; +"Save Image" = "Save Image"; /* Mailbox popup menus */ "Open in New Mail Window" = "Open in New Mail Window"; diff --git a/UI/MailerUI/French.lproj/Localizable.strings b/UI/MailerUI/French.lproj/Localizable.strings index 46d1e916..f2c4d679 100644 --- a/UI/MailerUI/French.lproj/Localizable.strings +++ b/UI/MailerUI/French.lproj/Localizable.strings @@ -149,7 +149,7 @@ "Create Filter From Message..." = "Créer un filtre à partir du message..."; /* Image Popup menu */ -"View Image" = "Voir l'image"; +"Save Image" = "Enregistrer l'image"; /* Mailbox popup menus */ "Open in New Mail Window" = "Ouvrir dans une nouvelle fenétre"; diff --git a/UI/MailerUI/German.lproj/Localizable.strings b/UI/MailerUI/German.lproj/Localizable.strings index 21748193..b0b8dcef 100644 --- a/UI/MailerUI/German.lproj/Localizable.strings +++ b/UI/MailerUI/German.lproj/Localizable.strings @@ -132,7 +132,7 @@ "Create Filter From Message..." = "Filter aus Nachricht erstellen..."; /* Image Popup menu */ -"View Image" = "View Image"; +"Save Image" = "Save Image"; /* Mailbox popup menus */ "Open in New Mail Window" = "In neuem Fenster öffnen"; diff --git a/UI/Templates/MailerUI/UIxMailMainFrame.wox b/UI/Templates/MailerUI/UIxMailMainFrame.wox index 2e555aed..355c8999 100644 --- a/UI/Templates/MailerUI/UIxMailMainFrame.wox +++ b/UI/Templates/MailerUI/UIxMailMainFrame.wox @@ -173,7 +173,7 @@ diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index 894df77c..97a2a289 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -213,24 +213,24 @@ function ml_lowlight(sender) { /* bulk delete of messages */ function deleteSelectedMessages(sender) { - var messageList = $("messageList"); - var rowIds = messageList.getSelectedRowsId(); - - if (rowIds.length > 0) { - for (var i = 0; i < rowIds.length; i++) { - var url; - var rowId = rowIds[i].substr(4); - var messageId = Mailer.currentMailbox + "/" + rowId; - url = ApplicationBaseURL + messageId + "/trash"; - deleteMessageRequestCount++; - var data = { "id": rowId, "mailbox": Mailer.currentMailbox, "messageId": messageId }; - triggerAjaxRequest(url, deleteSelectedMessagesCallback, data); - } - } else { - window.alert(labels["Please select a message."]); - } - - return false; + var messageList = $("messageList"); + var rowIds = messageList.getSelectedRowsId(); + + if (rowIds.length > 0) { + for (var i = 0; i < rowIds.length; i++) { + var url; + var rowId = rowIds[i].substr(4); + var messageId = Mailer.currentMailbox + "/" + rowId; + url = ApplicationBaseURL + messageId + "/trash"; + deleteMessageRequestCount++; + var data = { "id": rowId, "mailbox": Mailer.currentMailbox, "messageId": messageId }; + triggerAjaxRequest(url, deleteSelectedMessagesCallback, data); + } + } + else + window.alert(labels["Please select a message."]); + + return false; } function deleteSelectedMessagesCallback(http) { @@ -240,7 +240,6 @@ function deleteSelectedMessagesCallback(http) { deleteCachedMessage(data["messageId"]); deleteMessageRequestCount--; if (Mailer.currentMailbox == data["mailbox"]) { - var div = $('messageContent'); if (Mailer.currentMessages[Mailer.currentMailbox] == data["id"]) { div.update(); @@ -273,8 +272,7 @@ function deleteDraft(url) { new Ajax.Request(url, { method: 'post', onFailure: function(transport) { - if (!isHttpStatus204) - log("draftDeleteCallback: problem during ajax request: " + transport.status); + log("draftDeleteCallback: problem during ajax request: " + transport.status); } }); } @@ -318,8 +316,24 @@ function moveMessages(rowIds, folder) { } function onMenuDeleteMessage(event) { - deleteSelectedMessages(); - preventDefault(event); + deleteSelectedMessages(); + preventDefault(event); +} + +function deleteMessage(url, id, mailbox, messageId) { + var data = { "id": id, "mailbox": mailbox, "messageId": messageId }; + deleteMessageRequestCount++; + triggerAjaxRequest(url, deleteSelectedMessagesCallback, data); +} + +function deleteMessageWithDelay(url, id, mailbox, messageId) { + /* this is called by UIxMailPopupView with window.opener */ + setTimeout("deleteMessage('" + + url + "', '" + + id + "', '" + + mailbox + "', '" + + messageId + "')", + 50); } function onPrintCurrentMessage(event) { @@ -435,12 +449,15 @@ function openMailbox(mailbox, reload, idx) { if (mailbox != Mailer.currentMailbox || reload) { Mailer.currentMailbox = mailbox; var url = ApplicationBaseURL + encodeURI(mailbox) + "/view?noframe=1"; - var messageContent = $("messageContent"); - messageContent.update(); - lastClickedRow = -1; // from generic.js - + + if (!reload) { + var messageContent = $("messageContent"); + messageContent.update(); + lastClickedRow = -1; // from generic.js + } + var currentMessage; - if (!idx) { + if (!idx && !reload) { currentMessage = Mailer.currentMessages[mailbox]; if (currentMessage) { loadMessage(currentMessage); @@ -968,9 +985,12 @@ function onMenuViewMessageSource(event) { preventDefault(event); } -function viewImage(event) { +function saveImage(event) { var img = document.menuTarget; - window.open(img.getAttribute("src"),'_blank','resizable=1'); + var url = img.getAttribute("src"); + var urlAsAttachment = url.replace(/(\/[^\/]*)$/,"/asAttachment$1"); + + window.location.href = urlAsAttachment; } /* contacts */ @@ -1725,7 +1745,7 @@ function getMenus() { "mark-menu", "-", null, null, onMenuDeleteMessage); - menus["imageMenu"] = new Array(viewImage); + menus["imageMenu"] = new Array(saveImage); menus["messageContentMenu"] = new Array(onMenuReplyToSender, onMenuReplyToAll, onMenuForwardMessage, diff --git a/UI/WebServerResources/UIxMailPopupView.js b/UI/WebServerResources/UIxMailPopupView.js index dd197486..9c406496 100644 --- a/UI/WebServerResources/UIxMailPopupView.js +++ b/UI/WebServerResources/UIxMailPopupView.js @@ -9,4 +9,21 @@ function initPopupMailer(event) { resizeMailContent(); } +function onMenuDeleteMessage(event) { + + if (window.opener && window.opener.open && !window.opener.closed) { + var rowId = window.name.substr(9); + var messageId = window.opener.Mailer.currentMailbox + "/" + rowId; + var url = ApplicationBaseURL + messageId + "/trash"; + + window.opener.deleteMessageWithDelay(url, + rowId, + window.opener.Mailer.currentMailbox, + messageId); + } + + window.close(); + return false; +} + FastInit.addOnLoad(initPopupMailer);