]> err.no Git - scalable-opengroupware.org/commitdiff
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1297 d1b88da0-ebda-0310...
authorwolfgang <wolfgang@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Wed, 12 Dec 2007 16:33:27 +0000 (16:33 +0000)
committerwolfgang <wolfgang@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Wed, 12 Dec 2007 16:33:27 +0000 (16:33 +0000)
16 files changed:
ChangeLog
SOPE/GDLContentStore/ChangeLog
SOPE/GDLContentStore/GCSFolder.h
SOPE/GDLContentStore/GCSFolder.m
SOPE/NGCards/ChangeLog
SOPE/NGCards/iCalTimeZone.m
SoObjects/Mailer/SOGoMailBodyPart.h
SoObjects/Mailer/SOGoMailBodyPart.m
SoObjects/SOGo/SOGoContentObject.m
UI/MailPartViewers/UIxMailPartHTMLViewer.m
UI/MailerUI/English.lproj/Localizable.strings
UI/MailerUI/French.lproj/Localizable.strings
UI/MailerUI/German.lproj/Localizable.strings
UI/Templates/MailerUI/UIxMailMainFrame.wox
UI/WebServerResources/MailerUI.js
UI/WebServerResources/UIxMailPopupView.js

index 9d9c6ca6fb63c6243080f1594278e3db3d1402ca..b1885e35573b66a1313a946d7f8e3ddea86ba8cb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,24 @@
+2007-12-12  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+       * SoObjects/SOGo/SOGoContentObject.m ([SOGoContentObject
+       -davCreationDate])
+       ([SOGoContentObject -davLastModified])
+       ([SOGoContentObject -davContentLength]): implemented dav methods.
+
+2007-12-10  Francis Lachapelle  <flachapelle@inverse.ca>
+
+       * 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  <wsourdeau@inverse.ca>
+
+       * 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  <wsourdeau@inverse.ca>
 
        * Main/SOGo.m ([SOGo -run]): the table creation script now have a
index 058a7edb5a55e17c9058ef8a1411e9e0b15495bb..af7d8047ce8ca98127d74fa67f1fce40f74558df 100644 (file)
@@ -1,3 +1,10 @@
+2007-12-12  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+       * 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  <wsourdeau@inverse.ca>
 
        * GCSFolder.m ([GCSFolder -versionOfContentWithName:], [GCSFolder
index 7209517ed860ebf34294ee98d1c365ea0c37b30b..73b608cc4abef211b9f005753a268a9393f78bc5 100644 (file)
 - (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
index e6ec63c7ce2ffe17d4753a5f245af2b9f3f20cb1..23cbbdec04d6af947ca21037f93e262cd9428fdb 100644 (file)
@@ -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];
index 3ddc72939f26b236b1479ffef1d715d8e75ac1d5..5e6348e4f8523e74bd05e1530a3a8bfd76336ace 100644 (file)
@@ -1,3 +1,9 @@
+2007-12-12  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+       * 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  <wsourdeau@inverse.ca>
 
        * iCalDateTime.m ([iCalDateTime -timeZone]): log a message if the
index 0e2e56be4b9eedf48fe3200090515b2e207aaf55..cd7afbe97b861011054feed2997ee9aacf664f7c 100644 (file)
                             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;
 }
index c3d6509dd1bb04512dd50a57a4bc70439426a308..0effd14cf429e9b8d0782c547da1b707366ab6d3 100644 (file)
@@ -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 */
 
index 0ce0fcd7f59f3f2f9b4229ada4e20c07f5eded30..6fac084d8f9db02d3d6d609029ee8a5a30b8ebb3 100644 (file)
@@ -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"];
index c82fc58992df9f6054504854ce0f9db7d0d968b4..73cc1401e1c322474d0dee8ebeb726663716419c 100644 (file)
@@ -29,6 +29,7 @@
 #import <NGExtensions/NSObject+Logs.h>
 #import <GDLContentStore/GCSFolder.h>
 
+#import "NSCalendarDate+SOGo.h"
 #import "SOGoGCSFolder.h"
 #import "SOGoUser.h"
 #import "SOGoPermissions.h"
 }
 
 /* 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
index 835de0700cd538d6534a589881fff7fb65794e97..50f79391d77dd51b4e2013aa1e1b164e3fe674ab 100644 (file)
                         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];
     }
 }
 
   NSMutableDictionary *attachmentIds;
   UIxMailPartViewer *parent;
   unsigned int count, max;
-  NSMutableString *url;
+//   NSMutableString *url;
   NSString *baseURL;
   NSArray *parts;
 
                          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;
index d745a63847d59b0fa33b1e8986e92a2d563bb2de..5e348b6a4b3a6a0ea4c95ac03b3fe602a8730a7d 100644 (file)
 "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";
index 46d1e91603fea685ffbdee97fd881ab690115b26..f2c4d6797c050890a3fa83a1ebdd33c8b92165b4 100644 (file)
 "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";
index 21748193257b071d4fad391da513bb1df03cfa45..b0b8dcef603820873f19beb75ac0b067dec27a75 100644 (file)
 "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";
index 2e555aed1dc2f1c7d2e305ac672d3aa997d74126..355c899984a3bbdd61a87ee8ca4527d2c9f540e5 100644 (file)
 
   <div class="menu" id="imageMenu">
     <ul>
-      <li id="view_image"><var:string label:value="View Image"/></li>
+      <li id="save_image"><var:string label:value="Save Image"/></li>
     </ul>
   </div>
 
index 894df77c578fb29764f561345109b3d6cf1aab68..97a2a289e3113e4ec9e700453215c34630e82883 100644 (file)
@@ -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,
index dd19748678335dbc0f832b1943f0e327f4e676b9..9c40649643a677dbb3cefbf0952ef35ed35c9b33 100644 (file)
@@ -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);