diff --git a/ChangeLog b/ChangeLog index 37230ebde..9145147ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,133 @@ +commit 321675ba99288b036677242ada3bfb0cb945970c +Author: Francis Lachapelle +Date: Wed Jan 30 08:51:10 2013 -0500 + + Bump version to 2.0.4a + +M Version + +commit 9eb1418e36f075a60bce249fe321e32196a3d9ab +Author: Francis Lachapelle +Date: Wed Jan 30 08:49:16 2013 -0500 + + Update French translation + +M UI/Contacts/French.lproj/Localizable.strings + +commit d8804c699dd784be7e7840e6ff4b19eee72c5b65 +Author: Francis Lachapelle +Date: Wed Jan 30 08:40:27 2013 -0500 + + Format birthday on contact card + +M NEWS +M UI/Contacts/UIxContactView.m + +commit 4e9db74e290dd828a84759e25a9bc06018eddabc +Author: Francis Lachapelle +Date: Tue Jan 29 15:04:57 2013 -0500 + + Update NEWS file + +M NEWS + +commit 7150ebde6be2d64458f9c30fb70bbfa72b2e4a6e +Author: Francis Lachapelle +Date: Tue Jan 29 15:03:37 2013 -0500 + + Update updates.php + +M Scripts/updates.php + +commit 6fbd975e001b6fb5dd0855f0c5a6a4a1a54e64b0 +Author: Francis Lachapelle +Date: Tue Jan 29 15:02:51 2013 -0500 + + Update NEWS file + +M NEWS + +commit e0a1a47953a78a16429e803b2ac1af832a032815 +Author: Francis Lachapelle +Date: Tue Jan 29 14:53:57 2013 -0500 + + Code cleanup in UIxAppointmentEditor.m + +M UI/Scheduler/UIxAppointmentEditor.m + +commit da757a19c65c286c2a4de2d0fcfe0a347b8ffeec +Author: Francis Lachapelle +Date: Mon Jan 28 22:05:54 2013 -0500 + + Fix handling of decoding contacts UID + + A problem occurs when the contact UID contains a special character that + was HTML encoded (ex: space, &, "). + +M UI/Templates/UIxAclEditor.wox +M UI/WebServerResources/UIxAclEditor.js +M UI/WebServerResources/UIxContactsUserFolders.js +M UI/WebServerResources/dtree.js + +commit ea13fd14c97ac3c58e1c50d3b82d0657715f1016 +Author: Jean Raby +Date: Tue Jan 29 10:31:16 2013 -0500 + + Use older NSPropertyListSerialization methods + + dataWithPropertyList and propertyListWithData didn't exist in gnustep 1.20 + which is shipped with debian-squeeze. + +M Tools/SOGoToolDumpDefaults.m + +commit 902a5d8f708f2a22f96634dc7fb5f299d3fedee6 +Author: Francis Lachapelle +Date: Mon Jan 28 18:43:45 2013 -0500 + + Fix saving all-day event in appointment editor + +M UI/Scheduler/UIxAppointmentEditor.m + +commit be0090be0654929c865ac2e89ab3b17794127912 +Author: Francis Lachapelle +Date: Mon Jan 28 16:44:14 2013 -0500 + + Fix until date in component editor + +M UI/Scheduler/UIxComponentEditor.m + +commit 2d455bf0ca94cd19874a0d9cb1b81c7271cd134e +Author: Francis Lachapelle +Date: Mon Jan 28 09:51:42 2013 -0500 + + Fix possible infinite loop in repeataable object + +M SOPE/NGCards/iCalRepeatableEntityObject.m + +commit 1d8e72646c2f585473fad8baf4b244b45243b7fe +Author: Francis Lachapelle +Date: Mon Jan 28 08:43:58 2013 -0500 + + Update Czech translation + +M UI/PreferencesUI/Czech.lproj/Localizable.strings + +commit c066136a06dc0cb63deb3001c4c8db5cdda41f9d +Author: Ludovic Marcotte +Date: Mon Jan 28 08:34:40 2013 -0500 + + Reverted code that was causing issues with groups (#2090) + +M SoObjects/SOGo/SOGoUserManager.m + +commit 40facab9a711e719b5533eb868dd50e6e8eb9497 +Author: Francis Lachapelle +Date: Fri Jan 25 13:59:52 2013 -0500 + + Update ChangeLog + +M ChangeLog + commit 94eec4678ef7f0e0ab0b53e22444a0992d5030b7 Author: Francis Lachapelle Date: Fri Jan 25 13:58:17 2013 -0500 diff --git a/NEWS b/NEWS index d94ed80cd..20a6ba973 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,19 @@ -2.0.4 (2013-01-DD) +2.0.4a (2013-01-30) +------------------ + +Enhancements + - updated Czech translation + - birthday is now properly formatted in addressbook module + +Bug fixes + - fixed handling of groups with spaces in their UID + - fixed possible infinite loop in repeatable object + - fixed until date in component editor + - fixed saving all-day event in appointment editor + - fixed handling of decoding contacts UID + - fixed support of GNUstep 1.20 / Debian Squeeze + +2.0.4 (2013-01-25) ------------------ New features @@ -18,6 +33,7 @@ Enhancements - updated translations - recurrence-id of all-day events is now set as a proper date with no time - 'show completed tasks' is now persistent + - fixed memory usage consumption for remote ICS subscriptions Bug fixes - fixed usage of browser's language for the login page diff --git a/SOPE/NGCards/iCalRepeatableEntityObject.m b/SOPE/NGCards/iCalRepeatableEntityObject.m index 4cc9437a3..5a7dee12c 100644 --- a/SOPE/NGCards/iCalRepeatableEntityObject.m +++ b/SOPE/NGCards/iCalRepeatableEntityObject.m @@ -330,14 +330,15 @@ lastPossibleRecurrenceStartDateUsingFirstInstanceCalendarDateRange: (NGCalendarD rRules = [[self recurrenceRules] objectEnumerator]; rule = [rRules nextObject]; - while (rule && ![rule isInfinite] & !date) + while (rule && ![rule isInfinite] && !date) { calc = [iCalRecurrenceCalculator recurrenceCalculatorForRecurrenceRule: rule - withFirstInstanceCalendarDateRange: _r]; + withFirstInstanceCalendarDateRange: _r]; rdate = [[calc lastInstanceCalendarDateRange] startDate]; - if (!date - || ([date compare: rdate] == NSOrderedAscending)) + if (!rdate) + date = [_r startDate]; + else if (!date || ([date compare: rdate] == NSOrderedAscending)) date = rdate; else rule = [rRules nextObject]; diff --git a/Scripts/updates.php b/Scripts/updates.php index e1b8bcb49..b49910cff 100755 --- a/Scripts/updates.php +++ b/Scripts/updates.php @@ -1,7 +1,7 @@ * Francis Lachapelle @@ -28,12 +28,12 @@ $plugins = array( "sogo-connector@inverse.ca" => array( "application" => "thunderbird", - "version" => "17.0.2", - "filename" => "sogo-connector-17.0.2.xpi" ), + "version" => "17.0.3", + "filename" => "sogo-connector-17.0.3.xpi" ), "sogo-integrator@inverse.ca" => array( "application" => "thunderbird", - "version" => "17.0.2", - "filename" => "sogo-integrator-17.0.2.xpi" ), + "version" => "17.0.3", + "filename" => "sogo-integrator-17.0.3.xpi" ), "{e2fda1a4-762b-4020-b5ad-a41df1933103}" => array( "application" => "thunderbird", "version" => "1.9", diff --git a/SoObjects/SOGo/SOGoUserManager.m b/SoObjects/SOGo/SOGoUserManager.m index a583164f4..28fec2a21 100644 --- a/SoObjects/SOGo/SOGoUserManager.m +++ b/SoObjects/SOGo/SOGoUserManager.m @@ -790,12 +790,9 @@ static Class NSNullK; NSString *aUID, *cacheUid, *jsonUser; BOOL newUser; - /* TODO: we need to perform a better validity check on "uid" */ - if ([uid isEqualToString: @"anonymous"]) currentUser = [self _contactInfosForAnonymous]; - else if ([uid length] > 0 - && [uid rangeOfString: @" "].location == NSNotFound) + else if ([uid length] > 0) { // Remove the "@" prefix used to identified groups in the ACL tables. aUID = [uid hasPrefix: @"@"] ? [uid substringFromIndex: 1] : uid; diff --git a/Tools/SOGoToolDumpDefaults.m b/Tools/SOGoToolDumpDefaults.m index 8f5770804..2344c3a3c 100644 --- a/Tools/SOGoToolDumpDefaults.m +++ b/Tools/SOGoToolDumpDefaults.m @@ -83,10 +83,9 @@ defaultsDict = [ud persistentDomainForName: @"sogod"]; } - plistData = [NSPropertyListSerialization dataWithPropertyList: (id) defaultsDict + plistData = [NSPropertyListSerialization dataFromPropertyList: (id) defaultsDict format: NSPropertyListOpenStepFormat - options: 0 - error: 0 ]; + errorDescription: 0 ]; return [[[NSString alloc] initWithData:plistData encoding:NSUTF8StringEncoding] autorelease]; } @@ -94,7 +93,7 @@ - (NSString *) defaultsFromFilename: (NSString *)filename { NSData *rawData, *plistRawData, *plistDataOpenStep; - NSError *err; + NSString *errstr; rawData = [NSData dataWithContentsOfFile: filename]; if (rawData == nil) @@ -104,23 +103,22 @@ return @""; } - plistRawData = [NSPropertyListSerialization propertyListWithData: rawData - options: 0 + plistRawData = [NSPropertyListSerialization propertyListFromData: rawData + mutabilityOption: 0 format: 0 - error: &err]; + errorDescription: &errstr]; if (plistRawData == nil) { - NSLog(@"Error converting '%s' to plist: %@", [filename UTF8String], err); + NSLog(@"Error converting '%s' to plist: %@", [filename UTF8String], errstr); return @""; } - plistDataOpenStep = [NSPropertyListSerialization dataWithPropertyList: (id) plistRawData + plistDataOpenStep = [NSPropertyListSerialization dataFromPropertyList: (id) plistRawData format: NSPropertyListOpenStepFormat - options: 0 - error: &err ]; + errorDescription: &errstr ]; if (!plistDataOpenStep) { - NSLog(@"Error converting plist to OpenStep format: %@", err); + NSLog(@"Error converting plist to OpenStep format: %@", errstr); return @""; } diff --git a/UI/Contacts/French.lproj/Localizable.strings b/UI/Contacts/French.lproj/Localizable.strings index bde6dc24d..31a269473 100644 --- a/UI/Contacts/French.lproj/Localizable.strings +++ b/UI/Contacts/French.lproj/Localizable.strings @@ -197,7 +197,7 @@ "Export Address Book..." = "Exporter le carnet d'adresses..."; "View Raw Source" = "Afficher le contenu original"; "Import Cards" = "Importer des contacts"; -"Select a vCard or LDIF file." = "Sélectionner un fichier. LDIF ou vCard."; +"Select a vCard or LDIF file." = "Sélectionner un fichier LDIF ou vCard."; "Upload" = "Ajouter"; "Uploading" = "Téléversement en cours"; "Done" = "Terminer"; diff --git a/UI/Contacts/UIxContactView.m b/UI/Contacts/UIxContactView.m index 1c0e55dd6..392aabdaf 100644 --- a/UI/Contacts/UIxContactView.m +++ b/UI/Contacts/UIxContactView.m @@ -30,6 +30,9 @@ #import #import +#import +#import +#import #import #import "UIxContactView.h" @@ -612,7 +615,23 @@ - (NSString *) bday { - return [self _cardStringWithLabel: @"Birthday:" value: [card bday]]; + NSString *bday, *value; + NSCalendarDate *date; + SOGoDateFormatter *dateFormatter; + + bday = [card bday]; + if (bday) + { + // Expected format of BDAY is YYYY[-]MM[-]DD + value = [bday stringByReplacingString: @"-" withString: @""]; + date = [NSCalendarDate dateFromShortDateString: value + andShortTimeString: nil + inTimeZone: nil]; + dateFormatter = [[[self context] activeUser] dateFormatterInContext: context]; + bday = [dateFormatter formattedDate: date]; + } + + return [self _cardStringWithLabel: @"Birthday:" value: bday]; } - (NSString *) tz diff --git a/UI/PreferencesUI/Czech.lproj/Localizable.strings b/UI/PreferencesUI/Czech.lproj/Localizable.strings index 01063b409..2616f662d 100644 --- a/UI/PreferencesUI/Czech.lproj/Localizable.strings +++ b/UI/PreferencesUI/Czech.lproj/Localizable.strings @@ -141,6 +141,7 @@ "messageforward_inline" = "Do řady"; "messageforward_attached" = "Jako přílohu"; +"When replying to a message:" = "Při odpovědi na zprávu:"; "replyplacement_above" = "Začít mojí odpověď nad citací"; "replyplacement_below" = "Začít mojí odpověď pod citací"; "And place my signature" = "A umístit můj podpis"; @@ -149,12 +150,17 @@ "Compose messages in" = "Vytvářet zprávy ve formátu"; "composemessagestype_html" = "HTML"; "composemessagestype_text" = "Prostý text"; +"Display remote inline images" = "Zobrazit vzdálené inline obrázky"; +"displayremoteinlineimages_never" = "Nikdy"; +"displayremoteinlineimages_always" = "Vždy"; /* IMAP Accounts */ "New Mail Account" = "Nový poštovní účet"; "Server Name:" = "Adresa serveru:"; "Port:" = "Port:"; +"Encryption:" = "Zabezpečení spojení:"; +"None" = "Žádné"; "User Name:" = "Uživatelské jméno:"; "Password:" = "Heslo:"; @@ -167,6 +173,9 @@ "Signature" = "Podpis"; "Please enter your signature below:" = "Text podpisu:"; +"Please specify a valid sender address." = "Prosím zadejte správnou adresu odesílatele."; +"Please specify a valid reply-to address." = "Prosím zadejte správnou adresu pro odpověď."; + /* Additional Parameters */ "Additional Parameters" = "Dodatečné parametry"; @@ -243,6 +252,7 @@ "match any of the following rules:" = "match any of the following rules:"; "match all messages" = "match all messages"; "Perform these actions:" = "Perform these actions:"; +"Untitled Filter" = "Nepojmenovaný filtr"; "Subject" = "Subject"; "From" = "From"; @@ -283,6 +293,7 @@ "Label 4" = "Label 4"; "Label 5" = "Label 5"; +"The password was changed successfully." = "Heslo bylo úspěšně změněno."; "Password must not be empty." = "Heslo nesmí být prázdné."; "The passwords do not match. Please try again." = "Hesla se neshodují. Prosím zadejte je znovu."; "Password change failed" = "Změna hesla selhala"; diff --git a/UI/Scheduler/UIxAppointmentEditor.m b/UI/Scheduler/UIxAppointmentEditor.m index 2437cbdb0..98609a034 100644 --- a/UI/Scheduler/UIxAppointmentEditor.m +++ b/UI/Scheduler/UIxAppointmentEditor.m @@ -1,6 +1,6 @@ /* UIxAppointmentEditor.m - this file is part of SOGo * - * Copyright (C) 2007-2011 Inverse inc. + * Copyright (C) 2007-2013 Inverse inc. * * Author: Wolfgang Sourdeau * Francis Lachapelle @@ -253,7 +253,6 @@ signed int offset; SOGoObject *co; SOGoUserDefaults *ud; - iCalTimeZone *eventTimeZone; [self event]; co = [self clientObject]; @@ -290,17 +289,12 @@ { endDate = [endDate dateByAddingYears: 0 months: 0 days: -1]; - // Verify if the start date is "floating" (no timezone). In this case, convert it - // to the user's timezone. - eventTimeZone = [(iCalDateTime*)[event uniqueChildWithTag: @"dtstart"] timeZone]; - if (eventTimeZone == nil) - { - offset = [timeZone secondsFromGMTForDate: startDate]; - startDate = [startDate dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 - seconds:-offset]; - endDate = [endDate dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 + // Convert the dates to the user's timezone + offset = [timeZone secondsFromGMTForDate: startDate]; + startDate = [startDate dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 seconds:-offset]; - } + endDate = [endDate dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 + seconds:-offset]; } isTransparent = ![event isOpaque]; } @@ -543,7 +537,10 @@ int nbrDays; iCalDateTime *startDate; iCalTimeZone *tz; + NSCalendarDate *allDayStartDate; + NSTimeZone *timeZone; SOGoUserDefaults *ud; + signed int offset; [self event]; [super takeValuesFromRequest: _rq inContext: _ctx]; @@ -552,7 +549,13 @@ { nbrDays = ((float) abs ([aptEndDate timeIntervalSinceDate: aptStartDate]) / 86400) + 1; - [event setAllDayWithStartDate: aptStartDate + // Convert all-day start date to GMT (floating date) + ud = [[context activeUser] userDefaults]; + timeZone = [ud timeZone]; + offset = [timeZone secondsFromGMTForDate: aptStartDate]; + allDayStartDate = [aptStartDate dateByAddingYears:0 months:0 days:0 hours:0 minutes:0 + seconds:offset]; + [event setAllDayWithStartDate: allDayStartDate duration: nbrDays]; } else diff --git a/UI/Scheduler/UIxComponentEditor.m b/UI/Scheduler/UIxComponentEditor.m index ced89c05e..07728523c 100644 --- a/UI/Scheduler/UIxComponentEditor.m +++ b/UI/Scheduler/UIxComponentEditor.m @@ -1927,7 +1927,7 @@ RANGE(2); ud = [[context activeUser] userDefaults]; date = [NSCalendarDate dateWithYear: [date yearOfCommonEra] month: [date monthOfYear] - day: [date dayOfYear] + day: [date dayOfMonth] hour: 0 minute: 0 second: 0 timeZone: [ud timeZone]]; diff --git a/UI/Templates/UIxAclEditor.wox b/UI/Templates/UIxAclEditor.wox index d567d39d7..4435b6914 100644 --- a/UI/Templates/UIxAclEditor.wox +++ b/UI/Templates/UIxAclEditor.wox @@ -38,7 +38,7 @@
  • + >
  • diff --git a/UI/WebServerResources/UIxAclEditor.js b/UI/WebServerResources/UIxAclEditor.js index 66b4b6837..035e6ecee 100644 --- a/UI/WebServerResources/UIxAclEditor.js +++ b/UI/WebServerResources/UIxAclEditor.js @@ -41,7 +41,7 @@ function addUser(userName, userID, type) { var url = window.location.href; var elements = url.split("/"); elements[elements.length-1] = ("addUserInAcls?uid=" - + encodeURIComponent(userID)); + + encodeURIComponent(userID.unescapeHTML())); triggerAjaxRequest(elements.join("/"), addUserCallback, newNode); result = true; } @@ -91,7 +91,7 @@ function nodeForUser(userName, userId, canSubscribe) { var span = createElement("span"); span.addClassName("userFullName"); - span.appendChild(document.createTextNode(" " + userName)); + span.appendChild(document.createTextNode(" " + userName.unescapeHTML())); node.appendChild(span); if (canSubscribe) { @@ -135,9 +135,9 @@ function onUserRemove(event) { var baseURL = elements.join("/"); for (var i = 0; i < nodes.length; i++) { - var userId = nodes[i].id; + var userId = nodes[i].id.unescapeHTML(); if (userId != defaultUserID && userId != "anonymous") { - triggerAjaxRequest(baseURL + userId, removeUserCallback, + triggerAjaxRequest(baseURL + encodeURIComponent(userId), removeUserCallback, nodes[i]); } } @@ -159,7 +159,7 @@ function subscribeToFolder(refreshCallback, refreshCallbackData) { function openRightsForUserID(userID) { var url = window.location.href; var elements = url.split("/"); - elements[elements.length-1] = "userRights?uid=" + userID; + elements[elements.length-1] = "userRights?uid=" + encodeURIComponent(userID); var height = AclEditor.userRightsHeight; if (userID == "anonymous") { @@ -178,7 +178,7 @@ function openRightsForUserID(userID) { function openRightsForUser(button) { var nodes = $("userList").getSelectedRows(); if (nodes.length > 0) - openRightsForUserID(nodes[0].getAttribute("id")); + openRightsForUserID(nodes[0].getAttribute("id").unescapeHTML()); return false; } diff --git a/UI/WebServerResources/UIxContactsUserFolders.js b/UI/WebServerResources/UIxContactsUserFolders.js index 49689e2f5..3a8eb238b 100644 --- a/UI/WebServerResources/UIxContactsUserFolders.js +++ b/UI/WebServerResources/UIxContactsUserFolders.js @@ -117,7 +117,7 @@ function buildUsersTree(treeDiv, response) { function onUserNodeToggle(event) { this.stopObserving("click", onUserNodeToggle); - var person = this.parentNode.getAttribute("dataname"); + var person = this.parentNode.getAttribute("dataname").unescapeHTML(); var url = (UserFolderURLForUser(person) + "foldersSearch" + "?type=" + window.opener.userFolderType); diff --git a/UI/WebServerResources/dtree.js b/UI/WebServerResources/dtree.js index 958c033a5..0a874b67a 100644 --- a/UI/WebServerResources/dtree.js +++ b/UI/WebServerResources/dtree.js @@ -12,11 +12,7 @@ /* The content of attribute values should be quoted properly by using the equivalent entities. */ function dTreeQuote(str) { - return (str - .replace(/&/g, "&") - .replace(/