merge of '5616899c7c44519d7ea52d68cc931f9f056b9584'

and '6c9151f261ad9f73f6614808f73d4ca224c2cb8e'

Monotone-Parent: 5616899c7c44519d7ea52d68cc931f9f056b9584
Monotone-Parent: 6c9151f261ad9f73f6614808f73d4ca224c2cb8e
Monotone-Revision: 06d643c3c015e84728100fb5624bf4bac033748f

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2010-11-08T19:12:46
Monotone-Branch: ca.inverse.sogo
This commit is contained in:
Wolfgang Sourdeau
2010-11-08 19:12:46 +00:00
17 changed files with 182 additions and 74 deletions

View File

@@ -1,3 +1,24 @@
2010-11-08 Ludovic Marcotte <lmarcotte@inverse.ca>
* SOPE/GDLContentStore/GCSAlarmsFolder.m
We now check for non-nil values before calling
-timeInterval...
* SoObjects/Mailer/SOGoMailAccount.m
We try to fallback to the imap server prior falling
back to localhost
2010-11-08 Francis Lachapelle <flachapelle@inverse.ca>
* UI/WebServerResources/SOGoDragHandles.js (adjust): for vertical
drag handles, prioritize the top limit rather than the bottom one.
* UI/WebServerResources/UIxContactEditor.js (onComboButtonClick):
return false so the form is not submitted when the button is clicked.
* UI/WebServerResources/ContactsUI.js
(onCategoriesMenuPrepareVisibility): don't verify the selection if
the list doesn't exist (happens in the contact editor).
2010-11-05 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* OpenChange/MAPIStoreSOGo.m: added debugging witnesses call to
@@ -27,6 +48,33 @@
(-getBody): invoked setupValues if values is nil to ensure that
the timezone has been set properly.
2010-11-05 Francis Lachapelle <flachapelle@inverse.ca>
* UI/MailerUI/UIxMailListActions.m (-getSortedUIDsAction): now
accepts the form parameter "no_headers" so only the UIDs are
returned, without the prefetched headers.
* UI/WebServerResources/SOGoMailDataSource.js (init): made the
headers argument optional.
(_loadCallback): handled the case when the server doesn't send the
prefetched headers.
* UI/WebServerResources/SOGoDataTable.js (_refresh): new method to
force the refresh of the data table with the data of the data source.
(remove): don't update the internal variables (index and count) if
the UID was not found in the data source.
* UI/WebServerResources/MailerUI.js (openMailbox): when reloading
a mailbox, only fetch the messages UIDs (without the headers).
(loadMessageCallback): only reload the headers if the seen state
has changed.
2010-11-04 Ludovic Marcotte <lmarcotte@inverse.ca>
SoObjects/SOGo/SOGoMailer.m
We stop when we see an invalid recipient and we inform the
client back with what are the invalid recipients
2010-11-04 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Tools/SOGoSockDOperation.m (_getFolderWithId:forUser:): invoke

View File

@@ -326,8 +326,10 @@ static NSString *alarmsFolderURLString = nil;
{
NSNumber *tRecId, *tADate;
tRecId = [NSNumber numberWithInt: (int) [recId timeIntervalSince1970]];
tADate = [NSNumber numberWithInt: (int) [alarmDate timeIntervalSince1970]];
// We check if recId and alarmDate are nil prior calling -timeIntervalSince1970
// Weird gcc optimizations can cause issue here.
tRecId = [NSNumber numberWithInt: (recId ? (int)[recId timeIntervalSince1970] : 0)];
tADate = [NSNumber numberWithInt: (alarmDate ? (int)[alarmDate timeIntervalSince1970] : 0)];
return [NSDictionary dictionaryWithObjectsAndKeys: cname, @"c_name",
path, @"c_path",

View File

@@ -1,3 +1,9 @@
2010-11-08 Francis Lachapelle <flachapelle@inverse.ca>
* NSString+NGCards.m (-vCardSubvaluesWithSeparator:): now returns
an empty array when the string is empty, instead of an array with
an empty string.
2010-10-28 Francis Lachapelle <flachapelle@inverse.ca>
* iCalRecurrenceRule.m (-isInfinite): a repeat count set to 0 is

View File

@@ -322,11 +322,14 @@ static NSString *commaSeparator = nil;
}
}
substring = [[NSString alloc] initWithCharactersNoCopy: substringBuffer
length: substringLength
freeWhenDone: YES];
[components addObject: substring];
[substring release];
if (substringLength > 0)
{
substring = [[NSString alloc] initWithCharactersNoCopy: substringBuffer
length: substringLength
freeWhenDone: YES];
[components addObject: substring];
[substring release];
}
NSZoneFree (NULL, stringBuffer);

View File

@@ -353,7 +353,22 @@ static NSString *sieveScriptName = @"sogo";
if (!sieveServer)
{
NSString *s;
sieveServer = @"localhost";
s = [dd imapServer];
if (s)
{
NSURL *url;
url = [NSURL URLWithString: s];
if ([url host])
sieveServer = [url host];
else
sieveServer = s;
}
}
else
{

View File

@@ -1,6 +1,6 @@
/* SOGoMailer.m - this file is part of SOGo
*
* Copyright (C) 2007-2009 Inverse inc.
* Copyright (C) 2007-2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
@@ -96,12 +96,9 @@
- (NSException *) _sendMailData: (NSData *) mailData
withClient: (NGSmtpClient *) client
andRejections: (unsigned int) toErrors
{
NSException *result;
if (toErrors > 0)
[self logWithFormat: @"sending email despite address rejections"];
if ([client sendData: mailData])
result = nil;
else
@@ -118,12 +115,13 @@
{
NGInternetSocketAddress *addr;
NSString *currentTo, *host;
NSMutableArray *toErrors;
NSEnumerator *addresses;
NGSmtpClient *client;
NSException *result;
NSRange r;
unsigned int toErrors, port;
unsigned int port;
client = [NGSmtpClient smtpClient];
host = smtpServer;
@@ -145,7 +143,7 @@
{
if ([client mailFrom: sender])
{
toErrors = 0;
toErrors = [NSMutableArray array];
addresses = [recipients objectEnumerator];
currentTo = [addresses nextObject];
while (currentTo)
@@ -153,17 +151,21 @@
if (![client recipientTo: [currentTo pureEMailAddress]])
{
[self logWithFormat: @"error with recipient '%@'", currentTo];
toErrors++;
[toErrors addObject: [currentTo pureEMailAddress]];
}
currentTo = [addresses nextObject];
}
if (toErrors == [recipients count])
if ([toErrors count] == [recipients count])
result = [NSException exceptionWithHTTPStatus: 500
reason: @"cannot send message:"
@" (smtp) all recipients discarded"];
else if ([toErrors count] > 0)
result = [NSException exceptionWithHTTPStatus: 500
reason: [NSString stringWithFormat:
@"cannot send message (smtp) - recipients discarded:\n%@",
[toErrors componentsJoinedByString: @", "]]];
else
result = [self _sendMailData: mailData withClient: client
andRejections: toErrors];
result = [self _sendMailData: mailData withClient: client];
}
else
result = [NSException exceptionWithHTTPStatus: 500

View File

@@ -558,17 +558,25 @@
- (id <WOActionResults>) getSortedUIDsAction
{
NSDictionary *data;
id data;
NSString *noHeaders;
SOGoMailFolder *folder;
WORequest *request;
WOResponse *response;
request = [context request];
response = [context response];
folder = [self clientObject];
data = [self getUIDsAndHeadersInFolder: folder];
[response setHeader: @"text/plain; charset=utf-8"
forKey: @"content-type"];
folder = [self clientObject];
noHeaders = [request formValueForKey: @"no_headers"];
if ([noHeaders length])
data = [self getSortedUIDsInFolder: folder];
else
data = [self getUIDsAndHeadersInFolder: folder];
[response appendContentString: [data jsonRepresentation]];
return response;
}

View File

@@ -79,17 +79,17 @@
methods = {
getMail = {
protectedBy = "View";
actionClass = "UIxMailListActions";
actionClass = "UIxMailListActions";
actionName = "getMail";
};
uids = {
protectedBy = "<public>";
actionClass = "UIxMailListActions";
actionClass = "UIxMailListActions";
actionName = "getSortedUIDs";
};
headers = {
protectedBy = "<public>";
actionClass = "UIxMailListActions";
actionClass = "UIxMailListActions";
actionName = "getHeaders";
};
subscribe = {

View File

@@ -21,7 +21,7 @@
"contacts_category_labels" = "Ami, Client, Collègue, Concurrent, Famille, Fournisseur, Partenaire d'affaire, Presse, VIP";
/* vacation (auto-reply) */
"Enable vacation auto reply" = "Activer message d'absense prolongée";
"Enable vacation auto reply" = "Activer message d'absence prolongée";
"Auto reply message :" = "Message de réponse automatique :";
"Email addresses (separated by commas) :" = "Adresses courriels (séparées par des virgules) :";
"Add default email addresses" = "Ajouter les adresses par défaut";

View File

@@ -8,6 +8,7 @@
xmlns:label="OGo:label"
className="UIxPageFrame"
title="name"
const:userDefaultsKeys="SOGoContactsCategories"
const:popup="YES"
>
<div class="menu" id="categoriesMenu">

View File

@@ -1302,30 +1302,34 @@ function resetCategoriesMenu() {
}
function onCategoriesMenuPrepareVisibility() {
var rows = contactsList.getSelectedRows();
if (rows.length > 0) {
var catList = rows[0].getAttribute("categories");
var catsArray;
if (catList && catList.length > 0) {
catsArray = catList.split(",");
}
else {
catsArray = [];
}
var menu = $("categoriesMenu");
var ul = menu.down("ul");
var listElements = ul.select("li");
for (var i = 0; i < listElements.length; i++) {
var li = listElements[i];
if (catsArray.indexOf(li.category) > -1) {
li.addClassName("_chosen");
var contactsList = $("contactsList");
if (contactsList) {
var rows = contactsList.getSelectedRows();
if (rows.length > 0) {
var catList = rows[0].getAttribute("categories"); log ("cats = " + catList);
var catsArray;
if (catList && catList.length > 0) {
catsArray = catList.split(",");
}
else {
li.removeClassName("_chosen");
catsArray = [];
}
var menu = $("categoriesMenu");
var ul = menu.down("ul");
var listElements = ul.select("li");
for (var i = 0; i < listElements.length; i++) {
var li = listElements[i];
if (catsArray.indexOf(li.category) > -1) {
li.addClassName("_chosen");
}
else {
li.removeClassName("_chosen");
}
}
}
}
return true;
}
function onCategoriesMenuItemClick() {

View File

@@ -425,7 +425,7 @@ function deleteSelectedMessages(sender) {
triggerAjaxRequest(url, deleteSelectedMessagesCallback, data, parameters,
{ "Content-type": "application/x-www-form-urlencoded" });
}
else
if (uids.length == 0)
showAlertDialog(_("Please select a message."));
return false;
@@ -440,7 +440,7 @@ function deleteSelectedMessagesCallback(http) {
if (Mailer.currentMailbox == data["mailbox"]) {
var div = $('messageContent');
if (Mailer.currentMessages[Mailer.currentMailbox] == data["id"][i]) {
div.update();
div.innerHTML = '';
Mailer.currentMessages[Mailer.currentMailbox] = null;
}
if (deleteMessageRequestCount == 0) {
@@ -457,7 +457,7 @@ function deleteSelectedMessagesCallback(http) {
}
}
else {
div.update();
div.innerHTML = '';
}
Mailer.dataTable.remove(data["id"][i]);
Mailer.dataTable.refresh();
@@ -731,7 +731,7 @@ function openMailbox(mailbox, reload) {
}
var dataSource = Mailer.dataSources.get(key);
if (!dataSource || reload) {
if (!dataSource) {
dataSource = new SOGoMailDataSource(Mailer.dataTable, url);
if (inboxData) {
dataSource.init(inboxData['uids'], inboxData['headers']);
@@ -742,9 +742,16 @@ function openMailbox(mailbox, reload) {
Mailer.dataSources.set(key, dataSource);
getUnseenCountForFolder(mailbox);
}
messageList.deselectAll();
Mailer.dataTable.setSource(dataSource);
Mailer.dataTable.render();
else if (reload) {
urlParams.set("no_headers", "1");
dataSource.load(urlParams);
}
if (reload)
Mailer.dataTable.refresh();
else {
Mailer.dataTable.setSource(dataSource);
Mailer.dataTable.render();
}
configureDraggables();
Mailer.currentMailbox = mailbox;
@@ -767,7 +774,6 @@ function openMailbox(mailbox, reload) {
*/
function messageListCallback(row, data, isNew) {
var currentMessage = Mailer.currentMessages[Mailer.currentMailbox];
row.id = data['rowID'];
row.writeAttribute('labels', (data['labels']?data['labels']:""));
row.className = data['rowClasses'];
@@ -1511,7 +1517,8 @@ function loadMessageCallback(http) {
var msguid = http.callbackData.msguid;
// Warning: If the user can't set the read/unread flag, it won't
// be reflected in the view unless we force the refresh.
//Mailer.dataTable.invalidate(msguid, true);
if (http.callbackData.seenStateHasChanged)
Mailer.dataTable.invalidate(msguid, true);
cachedMessage['idx'] = Mailer.currentMailbox + '/' + msguid;
cachedMessage['time'] = (new Date()).getTime();
cachedMessage['text'] = http.responseText;

View File

@@ -159,6 +159,7 @@ var SOGoDataTableInterface = {
count = end - start;
this.currentRenderID = index + "-" + count;
// Query the data source only if at least one row is not loaded
if (refresh === true ||
this.renderedIndex < 0 ||
@@ -168,12 +169,16 @@ var SOGoDataTableInterface = {
this.dataSource.getData(this.currentRenderID,
index,
count,
this._render.bind(this),
(refresh === true)?this._refresh.bind(this):this._render.bind(this),
this.renderDelay);
}
},
_render: function(renderID, start, max, data) {
_refresh: function(renderID, start, max, data) {
this._render(renderID, start, max, data, true);
},
_render: function(renderID, start, max, data, refresh) {
if (this.currentRenderID != renderID) {
// log ("DataTable._render() ignore render for " + renderID + " (current is " + this.currentRenderID + ")");
return;
@@ -201,17 +206,16 @@ var SOGoDataTableInterface = {
this.renderedCount = 0;
}
if (start > (this.renderedIndex + this.renderedCount) ||
if (refresh === true ||
start > (this.renderedIndex + this.renderedCount) ||
start + data.length < this.renderedIndex) {
// No reusable row in the viewport;
// refresh the complete view port
for (i = 0, j = start;
i < this.renderedCount && i < data.length;
i++, j++) {
// Render all existing rows with new data
var row = rows[i+1]; // must skip the first row (this.rowTop)
row.removeClassName('_selected');
this.rowRenderCallback(row, data[i], false);
}
@@ -314,11 +318,12 @@ var SOGoDataTableInterface = {
}
var index = this.dataSource.remove(uid);
// log ("DataTable.remove(" + uid + ") at index " + index);
if (this.renderedIndex > index)
this.renderedIndex--;
else if ((this.renderedIndex + this.renderedCount) > index)
this.renderedCount--;
if (index >= 0) {
if (this.renderedIndex > index)
this.renderedIndex--;
else if ((this.renderedIndex + this.renderedCount) > index)
this.renderedCount--;
}
return index;
},

View File

@@ -39,8 +39,10 @@ var SOGoDragHandlesInterface = {
}
}
else if (this.dhType == 'vertical') {
this.dhLimit = window.height() - 20 - this.upperBlock.cumulativeOffset()[1] + this.upperBlock.offsetTop;
if (parseInt(this.getStyle("top")) > this.dhLimit) {
var windowHeight = window.height();
this.dhLimit = windowHeight - 20 - this.upperBlock.cumulativeOffset().top + this.upperBlock.offsetTop;
if (parseInt(this.getStyle("top")) > this.dhLimit &&
windowHeight > this.topMargin) {
this.setStyle({ top: this.dhLimit + 'px' });
this.lowerBlock.setStyle({ top: this.dhLimit + 'px' });
this.upperBlock.setStyle({ height: (this.dhLimit - this.upperBlock.offsetTop) + 'px' });

View File

@@ -45,12 +45,14 @@ SOGoMailDataSource = Class.create({
init: function(uids, headers) {
this.uids = uids;
var keys = headers[0];
for (var i = 1; i < headers.length; i++) {
var header = [];
for (var j = 0; j < keys.length; j++)
header[keys[j]] = headers[i][j];
this.cache.set(header["uid"], header);
if (headers) {
var keys = headers[0];
for (var i = 1; i < headers.length; i++) {
var header = [];
for (var j = 0; j < keys.length; j++)
header[keys[j]] = headers[i][j];
this.cache.set(header["uid"], header);
}
}
this.loaded = true;
@@ -78,7 +80,10 @@ SOGoMailDataSource = Class.create({
if (http.status == 200) {
if (http.responseText.length > 0) {
var data = http.responseText.evalJSON(true);
this.init(data.uids, data.headers);
if (data.uids)
this.init(data.uids, data.headers);
else
this.init(data);
this.loaded = true;
if (this.delayedGetData) {
this.delayedGetData();

View File

@@ -180,7 +180,7 @@ function performSearch(input) {
if (input.value.trim().length > 0) {
var urlstr = (UserFolderURL
+ "Contacts/allContactSearch?excludeGroups=1&search="
+ escape(input.value));
+ encodeURIComponent(input.value));
triggerAjaxRequest(urlstr, performSearchCallback, input);
}
input.searchTimeout = null;

View File

@@ -213,7 +213,7 @@ function onComboButtonClick(event) {
"left": menuLeft + "px",
"width": width + "px" });
event.preventDefault();
return false;
}
function onCategoryInputChange(event) {