mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-04-17 19:28:50 +00:00
merge of '24faa1b3ee3108a8faa323c456c74d517b4e233d'
and 'ce654c24f2f00574570b6f4719cccc588905dc0e' Monotone-Parent: 24faa1b3ee3108a8faa323c456c74d517b4e233d Monotone-Parent: ce654c24f2f00574570b6f4719cccc588905dc0e Monotone-Revision: 9091f162c671a0d32c003aa063bff71fb1e68a10 Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2009-10-05T22:10:12 Monotone-Branch: ca.inverse.sogo
This commit is contained in:
36
ChangeLog
36
ChangeLog
@@ -1,3 +1,39 @@
|
||||
2009-10-05 Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
|
||||
* Tests/test-maildav.py (DAVMailCollectionTest._testFilter): fixed
|
||||
to use the "test-dav-mail" folder name as collection during the
|
||||
tests.
|
||||
|
||||
* SoObjects/Mailer/SOGoMailFolder.m (-davMailQuery): new method
|
||||
implementing the "mail-query" REPORT for Inverse's maildav
|
||||
protocol.
|
||||
(-parseDAVRequestedProperties:): new method making use of the
|
||||
"davIMAPFieldsTable" method below for parsing fields in the
|
||||
mail-query request.
|
||||
(-_mailSortingFromSortElement:): new method to parse the "sort"
|
||||
element of mail-query requests.
|
||||
(-_fetchMessageProperties:matchingQualifier:andSorting:): new
|
||||
stub for a method that will fetch the IMAP messages based on the
|
||||
criteria found above.
|
||||
(-_appendProperties:fromMessages:toResponse:) new stub for a
|
||||
method that will add the content of the resulting set of message
|
||||
properties to the DAV response.
|
||||
|
||||
2009-10-05 Cyril Robert <crobert@inverse.ca>
|
||||
|
||||
* SoObjects/Mailer/SOGoMailFolder.m (-davIMAPFieldsTable): new
|
||||
method designed to match maildav properties on mail objects with
|
||||
IMAP fields, for PROPFIND and REPORT methods.
|
||||
|
||||
* Tests/test-webdavlib.py: Added new tests for the URL parser / regexp.
|
||||
|
||||
* Tests/webdavlib.py: Fixed errors in the URL regexp.
|
||||
|
||||
* SoObjects/Mailer/EOQualifier+MailDAV.m: New category to generate IMAP
|
||||
qualifiers from DAV filters. (REPORT)
|
||||
Formatted dates using ([NSCalendarDate rfc822DateString]). Added
|
||||
NOT and extra fields.
|
||||
|
||||
2009-10-04 Ludovic Marcotte <lmarcotte@inverse.ca>
|
||||
|
||||
* Adjusted the Welsh and Dutch templates for
|
||||
|
||||
37
SoObjects/Mailer/EOQualifier+MailDAV.h
Normal file
37
SoObjects/Mailer/EOQualifier+MailDAV.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* EOQualifier+MailDAV.h - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2009 Inverse inc.
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef EOQUALIFIER_MAILDAV_H
|
||||
#define EOQUALIFIER_MAILDAV_H
|
||||
|
||||
#import <EOControl/EOQualifier.h>
|
||||
#define XMLNS_INVERSEDAV @"urn:inverse:params:xml:ns:inverse-dav"
|
||||
|
||||
@class DOMElement;
|
||||
|
||||
@interface EOQualifier (SOGoMailDAVExtension)
|
||||
|
||||
+ (id) qualifierFromMailDAVMailFilters: (DOMElement *) mailFilters;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* EOQUALIFIER_MAILDAV_H */
|
||||
233
SoObjects/Mailer/EOQualifier+MailDAV.m
Normal file
233
SoObjects/Mailer/EOQualifier+MailDAV.m
Normal file
@@ -0,0 +1,233 @@
|
||||
/* EOQualifier+MailDAV.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2009 Inverse inc.
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSSet.h>
|
||||
|
||||
#import <DOM/DOMElement.h>
|
||||
#import <DOM/DOMProtocols.h>
|
||||
#import <SaxObjC/XMLNamespaces.h>
|
||||
#import <SOGo/DOMNode+SOGo.h>
|
||||
|
||||
#import <NGCards/NSString+NGCards.h>
|
||||
#import <SoObjects/SOGo/NSCalendarDate+SOGo.h>
|
||||
|
||||
#import "EOQualifier+MailDAV.h"
|
||||
|
||||
@implementation EOQualifier (SOGoMailDAVExtension)
|
||||
|
||||
+ (NSString *) buildQualifierFromFilters: (DOMElement *) mailFilters
|
||||
{
|
||||
NSMutableArray *qualifiers;
|
||||
NSString *qual, *buffer;
|
||||
id <DOMNodeList> list;
|
||||
DOMElement *current;
|
||||
NSCalendarDate *startDate, *endDate;
|
||||
int count, max, intValue;
|
||||
NSString *negate;
|
||||
|
||||
qualifiers = [NSMutableArray array];
|
||||
qual = nil;
|
||||
|
||||
#warning Qualifiers may be invalid, need to be tested
|
||||
|
||||
list = [mailFilters childNodes];
|
||||
if (list)
|
||||
{
|
||||
max = [list length];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
current = [list objectAtIndex: count];
|
||||
if ([current nodeType] == DOM_ELEMENT_NODE)
|
||||
{
|
||||
// Negate condition
|
||||
if ([current attribute: @"not"])
|
||||
negate = @"NOT ";
|
||||
else
|
||||
negate = @"";
|
||||
|
||||
// Received date
|
||||
if ([[current tagName] isEqualToString: @"receive-date"])
|
||||
{
|
||||
startDate = [[current attribute: @"from"] asCalendarDate];
|
||||
endDate = [[current attribute: @"to"] asCalendarDate];
|
||||
if (startDate && [startDate isEqual: endDate])
|
||||
[qualifiers addObject:
|
||||
[NSString stringWithFormat: @"%@(on = '%@')",
|
||||
negate, [startDate rfc822DateString]]];
|
||||
else if (startDate)
|
||||
[qualifiers addObject:
|
||||
[NSString stringWithFormat: @"%@(since > '%@')",
|
||||
negate, [startDate rfc822DateString]]];
|
||||
if (endDate)
|
||||
[qualifiers addObject:
|
||||
[NSString stringWithFormat: @"%@(before < '%@')",
|
||||
negate, [endDate rfc822DateString]]];
|
||||
}
|
||||
// Sent date
|
||||
else if ([[current tagName] isEqualToString: @"date"])
|
||||
{
|
||||
startDate = [[current attribute: @"from"] asCalendarDate];
|
||||
endDate = [[current attribute: @"to"] asCalendarDate];
|
||||
if (startDate && [startDate isEqual: endDate])
|
||||
[qualifiers addObject:
|
||||
[NSString stringWithFormat: @"%@(senton = '%@')",
|
||||
negate, [startDate rfc822DateString]]];
|
||||
else if (startDate)
|
||||
[qualifiers addObject:
|
||||
[NSString stringWithFormat: @"%@(sentsince > '%@')",
|
||||
negate, [startDate rfc822DateString]]];
|
||||
if (endDate)
|
||||
[qualifiers addObject:
|
||||
[NSString stringWithFormat: @"%@(sentbefore < '%@')",
|
||||
negate, [endDate rfc822DateString]]];
|
||||
}
|
||||
// Sequence
|
||||
else if ([[current tagName] isEqualToString: @"sequence"])
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
// UID
|
||||
else if ([[current tagName] isEqualToString: @"uid"])
|
||||
{
|
||||
buffer = [current attribute: @"uid"];
|
||||
if (buffer)
|
||||
[qualifiers addObject:
|
||||
[NSString stringWithFormat: @"%@(uid = '%@')",
|
||||
negate, buffer]];
|
||||
}
|
||||
// From
|
||||
else if ([[current tagName] isEqualToString: @"from"])
|
||||
{
|
||||
buffer = [current attribute: @"from"];
|
||||
if (buffer)
|
||||
[qualifiers addObject:
|
||||
[NSString stringWithFormat: @"%@(from doesContain: '%@')",
|
||||
negate, buffer]];
|
||||
}
|
||||
// To
|
||||
else if ([[current tagName] isEqualToString: @"to"])
|
||||
{
|
||||
buffer = [current attribute: @"to"];
|
||||
if (buffer)
|
||||
[qualifiers addObject:
|
||||
[NSString stringWithFormat: @"%@(to doesContain: '%@')",
|
||||
negate, buffer]];
|
||||
}
|
||||
// Size
|
||||
else if ([[current tagName] isEqualToString: @"size"])
|
||||
{
|
||||
intValue = [[current attribute: @"min"] intValue];
|
||||
[qualifiers addObject:
|
||||
[NSString stringWithFormat: @"%@(larger > '%d')",
|
||||
negate, intValue]];
|
||||
intValue = [[current attribute: @"max"] intValue];
|
||||
if (intValue)
|
||||
[qualifiers addObject:
|
||||
[NSString stringWithFormat: @"%@(smaller < '%d')",
|
||||
negate, intValue]];
|
||||
}
|
||||
// Answered
|
||||
else if ([[current tagName] isEqualToString: @"answered"])
|
||||
{
|
||||
intValue = [[current attribute: @"answered"] intValue];
|
||||
if (intValue)
|
||||
[qualifiers addObject: [NSString stringWithFormat:
|
||||
@"%@(answered)", negate]];
|
||||
intValue = [[current attribute: @"unanswered"] intValue];
|
||||
if (intValue)
|
||||
[qualifiers addObject: [NSString stringWithFormat:
|
||||
@"%@(unanswered)", negate]];
|
||||
}
|
||||
// Draft
|
||||
else if ([[current tagName] isEqualToString: @"draft"])
|
||||
{
|
||||
intValue = [[current attribute: @"draft"] intValue];
|
||||
if (intValue)
|
||||
[qualifiers addObject: [NSString stringWithFormat:
|
||||
@"%@(draft)", negate]];
|
||||
}
|
||||
// Flagged
|
||||
else if ([[current tagName] isEqualToString: @"flagged"])
|
||||
{
|
||||
intValue = [[current attribute: @"flagged"] intValue];
|
||||
if (intValue)
|
||||
[qualifiers addObject: [NSString stringWithFormat:
|
||||
@"%@(flagged)", negate]];
|
||||
}
|
||||
// Recent
|
||||
else if ([[current tagName] isEqualToString: @"recent"])
|
||||
{
|
||||
intValue = [[current attribute: @"recent"] intValue];
|
||||
if (intValue)
|
||||
[qualifiers addObject: [NSString stringWithFormat:
|
||||
@"%@(recent)", negate]];
|
||||
}
|
||||
// Seen
|
||||
else if ([[current tagName] isEqualToString: @"seen"])
|
||||
{
|
||||
intValue = [[current attribute: @"seen"] intValue];
|
||||
if (intValue)
|
||||
[qualifiers addObject: [NSString stringWithFormat:
|
||||
@"%@(seen)", negate]];
|
||||
}
|
||||
// Deleted
|
||||
else if ([[current tagName] isEqualToString: @"deleted"])
|
||||
{
|
||||
intValue = [[current attribute: @"deleted"] intValue];
|
||||
if (intValue)
|
||||
[qualifiers addObject: [NSString stringWithFormat:
|
||||
@"%@(deleted)", negate]];
|
||||
}
|
||||
// Keywords
|
||||
else if ([[current tagName] isEqualToString: @"keywords"])
|
||||
{
|
||||
buffer = [current attribute: @"keywords"];
|
||||
if (buffer)
|
||||
[qualifiers addObject:
|
||||
[NSString stringWithFormat: @"%@(keywords doesContain: '%@')",
|
||||
negate, buffer]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ([qualifiers count])
|
||||
qual = [qualifiers componentsJoinedByString: @" AND "];
|
||||
|
||||
return qual;
|
||||
}
|
||||
|
||||
|
||||
+ (id) qualifierFromMailDAVMailFilters: (DOMElement *) mailFilters
|
||||
{
|
||||
EOQualifier *newQualifier;
|
||||
NSString *qual;
|
||||
|
||||
qual = [EOQualifier buildQualifierFromFilters: mailFilters];
|
||||
|
||||
newQualifier = [EOQualifier qualifierWithQualifierFormat: qual];
|
||||
|
||||
return newQualifier;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -32,6 +32,7 @@ Mailer_OBJC_FILES += \
|
||||
SOGoMailForward.m \
|
||||
SOGoMailReply.m \
|
||||
\
|
||||
EOQualifier+MailDAV.m \
|
||||
NSData+Mail.m \
|
||||
NSString+Mail.m
|
||||
|
||||
|
||||
@@ -34,18 +34,26 @@
|
||||
#import <NGExtensions/NSString+misc.h>
|
||||
#import <NGExtensions/NSFileManager+Extensions.h>
|
||||
|
||||
#import <DOM/DOMElement.h>
|
||||
#import <DOM/DOMProtocols.h>
|
||||
#import <SaxObjC/XMLNamespaces.h>
|
||||
|
||||
#import <NGImap4/NGImap4Connection.h>
|
||||
#import <NGImap4/NGImap4Client.h>
|
||||
|
||||
#import <SoObjects/SOGo/SOGoPermissions.h>
|
||||
#import <SoObjects/SOGo/SOGoUser.h>
|
||||
#import <SoObjects/SOGo/NSArray+Utilities.h>
|
||||
#import <SOGo/DOMNode+SOGo.h>
|
||||
#import <SOGo/NSArray+Utilities.h>
|
||||
#import <SOGo/SOGoPermissions.h>
|
||||
#import <SOGo/SOGoUser.h>
|
||||
|
||||
#import "EOQualifier+MailDAV.h"
|
||||
#import "SOGoMailObject.h"
|
||||
#import "SOGoMailAccount.h"
|
||||
#import "SOGoMailManager.h"
|
||||
#import "SOGoMailFolder.h"
|
||||
|
||||
#define XMLNS_INVERSEDAV @"urn:inverse:params:xml:ns:inverse-dav"
|
||||
|
||||
static NSString *defaultUserID = @"anyone";
|
||||
|
||||
#warning this could be detected from the capabilities
|
||||
@@ -1102,7 +1110,159 @@ static NSString *spoolFolder = nil;
|
||||
return [self nameInContainer];
|
||||
}
|
||||
|
||||
// For DAV PUT
|
||||
- (NSDictionary *) davIMAPFieldsTable
|
||||
{
|
||||
static NSMutableDictionary *davIMAPFieldsTable = nil;
|
||||
|
||||
if (!davIMAPFieldsTable)
|
||||
{
|
||||
davIMAPFieldsTable = [NSMutableDictionary new];
|
||||
[davIMAPFieldsTable setObject: @"BODY[HEADER.FIELDS (DATE)]"
|
||||
forKey: @"{urn:schemas:httpmail:}date"];
|
||||
[davIMAPFieldsTable setObject: @""
|
||||
forKey: @"{urn:schemas:httpmail:}hasattachment"];
|
||||
[davIMAPFieldsTable setObject: @""
|
||||
forKey: @"{urn:schemas:httpmail:}read"];
|
||||
[davIMAPFieldsTable setObject: @"BODY"
|
||||
forKey: @"{urn:schemas:httpmail:}textdescription"];
|
||||
[davIMAPFieldsTable setObject: @"BODY[HEADER.FIELDS (CC)]"
|
||||
forKey: @"{urn:schemas:mailheader:}cc"];
|
||||
[davIMAPFieldsTable setObject: @"BODY[HEADER.FIELDS (DATE)]"
|
||||
forKey: @"{urn:schemas:mailheader:}date"];
|
||||
[davIMAPFieldsTable setObject: @"BODY[HEADER.FIELDS (FROM)]"
|
||||
forKey: @"{urn:schemas:mailheader:}from"];
|
||||
[davIMAPFieldsTable setObject: @"BODY[HEADER.FIELDS (INREPLYTO)]"
|
||||
forKey: @"{urn:schemas:mailheader:}in-reply-to"];
|
||||
[davIMAPFieldsTable setObject: @"BODY[HEADER.FIELDS (MESSAGEID)]"
|
||||
forKey: @"{urn:schemas:mailheader:}message-id"];
|
||||
[davIMAPFieldsTable setObject: @"BODY[HEADER.FIELDS (RECEIVED)]"
|
||||
forKey: @"{urn:schemas:mailheader:}received"];
|
||||
[davIMAPFieldsTable setObject: @"BODY[HEADER.FIELDS (REFERENCES)]"
|
||||
forKey: @"{urn:schemas:mailheader:}references"];
|
||||
[davIMAPFieldsTable setObject: @"BODY[HEADER.FIELDS (SUBJECT)]"
|
||||
forKey: @"{urn:schemas:mailheader:}displayname"];
|
||||
[davIMAPFieldsTable setObject: @"BODY[HEADER.FIELDS (TO)]"
|
||||
forKey: @"{urn:schemas:mailheader:}to"];
|
||||
}
|
||||
|
||||
return davIMAPFieldsTable;
|
||||
}
|
||||
|
||||
- (NSDictionary *) _davIMAPFieldsForProperties: (NSArray *) properties
|
||||
{
|
||||
NSMutableDictionary *davIMAPFields;
|
||||
NSDictionary *davIMAPFieldsTable;
|
||||
NSString *imapField, *property;
|
||||
unsigned int count, max;
|
||||
|
||||
davIMAPFieldsTable = [self davIMAPFieldsTable];
|
||||
|
||||
max = [properties count];
|
||||
davIMAPFields = [NSMutableDictionary dictionaryWithCapacity: max];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
property = [properties objectAtIndex: count];
|
||||
imapField = [davIMAPFieldsTable objectForKey: property];
|
||||
if (imapField)
|
||||
[davIMAPFields setObject: imapField forKey: property];
|
||||
else
|
||||
[self errorWithFormat: @"DAV property '%@' has no matching IMAP field,"
|
||||
@" response could be incomplete", property];
|
||||
}
|
||||
|
||||
return davIMAPFields;
|
||||
}
|
||||
|
||||
- (NSDictionary *) parseDAVRequestedProperties: (DOMElement *) propElement
|
||||
{
|
||||
NSArray *properties;
|
||||
NSDictionary *imapFieldsTable;
|
||||
|
||||
properties = [propElement flatPropertyNameOfSubElements];
|
||||
imapFieldsTable = [self _davIMAPFieldsForProperties: properties];
|
||||
|
||||
return imapFieldsTable;
|
||||
}
|
||||
|
||||
- (NSString *) _mailSortingFromSortElement: (DOMElement *) sortElement
|
||||
{
|
||||
NSArray *imapFields;
|
||||
NSString *davReverseAttr;
|
||||
NSMutableString *imapSortCriteria;
|
||||
|
||||
imapSortCriteria = [NSMutableString string];
|
||||
|
||||
imapFields = [[self parseDAVRequestedProperties: sortElement] allValues];
|
||||
davReverseAttr = [[sortElement attribute: @"order"] uppercaseString];
|
||||
if ([davReverseAttr isEqualToString: @"descending"])
|
||||
[imapSortCriteria appendString: @"REVERSE "];
|
||||
else if ([davReverseAttr length]
|
||||
&& ![davReverseAttr isEqualToString: @"ascending"])
|
||||
[self errorWithFormat: @"unrecognized sort order: '%@'",
|
||||
davReverseAttr];
|
||||
[imapSortCriteria
|
||||
appendString: [imapFields componentsJoinedByString: @" "]];
|
||||
|
||||
return imapSortCriteria;
|
||||
}
|
||||
|
||||
- (NSArray *) _fetchMessageProperties: (NSDictionary *) properties
|
||||
matchingQualifier: (EOQualifier *) searchQualifier
|
||||
andSorting: (NSString *) sorting
|
||||
{
|
||||
#warning not implemented
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void) _appendProperties: (NSArray *) keys
|
||||
fromMessages: (NSArray *) messages
|
||||
toResponse: (WOResponse *) response
|
||||
{
|
||||
#warning not implemented
|
||||
}
|
||||
|
||||
- (id) davMailQuery: (id) queryContext
|
||||
{
|
||||
WOResponse *r;
|
||||
id <DOMDocument> document;
|
||||
DOMElement *documentElement, *propElement, *filterElement, *sortElement;
|
||||
NSDictionary *properties;
|
||||
NSArray *messages;
|
||||
EOQualifier *searchQualifier;
|
||||
NSString *sorting;
|
||||
|
||||
r = [context response];
|
||||
[r setContentEncoding: NSUTF8StringEncoding];
|
||||
[r setHeader: @"text/xml; charset=\"utf-8\"" forKey: @"content-type"];
|
||||
[r setHeader: @"no-cache" forKey: @"pragma"];
|
||||
[r setHeader: @"no-cache" forKey: @"cache-control"];
|
||||
|
||||
document = [[context request] contentAsDOMDocument];
|
||||
documentElement = (DOMElement *) [document documentElement];
|
||||
|
||||
propElement = [documentElement firstElementWithTag: @"prop"
|
||||
inNamespace: XMLNS_WEBDAV];
|
||||
properties = [self parseDAVRequestedProperties: propElement];
|
||||
filterElement = [documentElement firstElementWithTag: @"mail-filters"
|
||||
inNamespace: XMLNS_INVERSEDAV];
|
||||
searchQualifier = [EOQualifier
|
||||
qualifierFromMailDAVMailFilters: filterElement];
|
||||
sortElement = [documentElement firstElementWithTag: @"sort"
|
||||
inNamespace: XMLNS_INVERSEDAV];
|
||||
sorting = [self _mailSortingFromSortElement: sortElement];
|
||||
|
||||
messages = [self _fetchMessageProperties: properties
|
||||
matchingQualifier: searchQualifier
|
||||
andSorting: sorting];
|
||||
[r setStatus: 207];
|
||||
[r appendContentString: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"];
|
||||
[self _appendProperties: [properties allKeys]
|
||||
fromMessages: messages
|
||||
toResponse: r];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
- (NSException *) _appendMessageData: (NSData *) data
|
||||
usingId: (int *) imap4id;
|
||||
{
|
||||
|
||||
@@ -22,4 +22,7 @@
|
||||
= davCollectionQuery;
|
||||
"{urn:inverse:params:xml:ns:inverse-dav}acl-query" = davAclQuery;
|
||||
"{urn:inverse:params:xml:ns:inverse-dav}user-query" = davUserQuery;
|
||||
|
||||
/* Inverse MailDAV */
|
||||
"{urn:inverse:params:xml:ns:inverse-dav}mail-query" = davMailQuery;
|
||||
}
|
||||
|
||||
@@ -310,8 +310,8 @@ class DAVMailCollectionTest(unittest.TestCase):
|
||||
expected_hrefs[href] = True
|
||||
|
||||
received_count = 0
|
||||
query = webdavlib.MailDAVMailQuery(self.resource, ["displayname"],
|
||||
filter[0])
|
||||
url = "%sfolder%s" % (self.resource, "test-dav-mail")
|
||||
query = webdavlib.MailDAVMailQuery(url, ["displayname"], filter[0])
|
||||
self.client.execute(query)
|
||||
self.assertEquals(query.response["status"], 207,
|
||||
"filter %s:\n\tunexpected status: %d"
|
||||
|
||||
@@ -28,5 +28,23 @@ class HTTPUnparsedURLTest(unittest.TestCase):
|
||||
self.assertEquals(testURL.port, None)
|
||||
self.assertEquals(testURL.path, "/folder/folder/simplereference")
|
||||
|
||||
pathURL = "http://user:secret@bla.com/hooray"
|
||||
testURL = HTTPUnparsedURL(pathURL)
|
||||
self.assertEquals(testURL.protocol, "http")
|
||||
self.assertEquals(testURL.username, "user")
|
||||
self.assertEquals(testURL.password, "secret")
|
||||
self.assertEquals(testURL.hostname, "bla.com")
|
||||
self.assertEquals(testURL.port, None)
|
||||
self.assertEquals(testURL.path, "/hooray")
|
||||
|
||||
pathURL = "http://user@bla.com:80/hooray"
|
||||
testURL = HTTPUnparsedURL(pathURL)
|
||||
self.assertEquals(testURL.protocol, "http")
|
||||
self.assertEquals(testURL.username, "user")
|
||||
self.assertEquals(testURL.password, None)
|
||||
self.assertEquals(testURL.hostname, "bla.com")
|
||||
self.assertEquals(testURL.port, "80")
|
||||
self.assertEquals(testURL.path, "/hooray")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -24,7 +24,7 @@ class HTTPUnparsedURL:
|
||||
url_parts = url.split("?")
|
||||
alpha_match = "[a-zA-Z0-9%\._-]+"
|
||||
num_match = "[0-9]+"
|
||||
pattern = ("((%s)://(((%s)(:(%s)?)@)?(%s)(:(%s))))?(/.*)"
|
||||
pattern = ("((%s)://(((%s)(:(%s))?@)?(%s)(:(%s))?))?(/.*)"
|
||||
% (alpha_match, alpha_match, alpha_match,
|
||||
alpha_match, num_match))
|
||||
url_re = re.compile(pattern)
|
||||
|
||||
Reference in New Issue
Block a user