}
- (NSURL *)applicationURL {
- if (self->appURL == nil) {
- NSString *s;
+ NSString *s;
+
+ if (self->appURL != nil)
+ return self->appURL;
- s = [self->request adaptorPrefix];
- if ([s length] > 0) {
- s = [NSString stringWithFormat:@"%@/%@/",
- s, [self->request applicationName]];
- }
- else
- s = [[self->request applicationName] stringByAppendingString:@"/"];
-
- self->appURL =
- [[NSURL URLWithString:s relativeToURL:[self serverURL]] retain];
+ // TODO: we should ensure that the suffix (.woa) is in the URL
+
+ s = [self->request adaptorPrefix];
+ if ([s length] > 0) {
+ s = [[[s stringByAppendingString:@"/"]
+ stringByAppendingString:[self->request applicationName]]
+ stringByAppendingString:@"/"];
}
+ else
+ s = [[self->request applicationName] stringByAppendingString:@"/"];
+
+ self->appURL =
+ [[NSURL URLWithString:s relativeToURL:[self serverURL]] retain];
return self->appURL;
}
- (NSURL *)urlForKey:(NSString *)_key {
// TODO(hh): code is now prepared for last-exception, but currently it just
// raises and may leak the exception object
+@interface NGImap4ResponseParser(ParsingPrivates)
+- (BOOL)_parseNumberUntaggedResponse:(NGMutableHashMap *)result_;
+- (NSDictionary *)_parseBodyContent;
+@end
+
@implementation NGImap4ResponseParser
#define __la(__SELF__, __LACNT) \
}
static NSDictionary *_parseBody(NGImap4ResponseParser *self);
-static NSDictionary *_parseBodyContent(NGImap4ResponseParser *self);
static NSString *_parseBodyString(NGImap4ResponseParser *self,
BOOL _convertString);
static NSString *_parseBodyDecodeString(NGImap4ResponseParser *self,
NGMutableHashMap *result_);
static BOOL _parseByeUntaggedResponse(NGImap4ResponseParser *self,
NGMutableHashMap *result_);
-static BOOL _parseNumberUntaggedResponse(NGImap4ResponseParser *self,
- NGMutableHashMap *result_);
static NSArray *_parseFlagArray(NGImap4ResponseParser *self);
static BOOL _parseFlagsUntaggedResponse(NGImap4ResponseParser *self,
NGMutableHashMap *result_);
}
static NSData *_parseData(NGImap4ResponseParser *self) {
+ // TODO: split up method
NSData *result;
unsigned size;
NSNumber *n;
}
[stream writeBytes:tmpBuf count:tmpBufCnt];
}
- if (lastChar != -1) {
+ if (lastChar != -1)
[stream writeBytes:&lastChar count:1];
- }
+
[stream close];
[stream release]; stream = nil;
result = [NSData dataWithContentsOfMappedFile:path];
return result;
}
- {
+ if (size == 0) {
+ [self logWithFormat:@"ERROR(%s): got content size '0'!",
+ __PRETTY_FUNCTION__];
+ return nil;
+ }
+ else {
unsigned char *buf = NULL;
- unsigned wasRead = 0;
- char *tmpBuf;
- unsigned cnt, tmpBufCnt, tmpSize;
+ unsigned wasRead = 0;
+ unsigned char *tmpBuf;
+ unsigned cnt, tmpBufCnt, tmpSize;
- buf = malloc(sizeof(char) * size + 10);
-
+ buf = calloc(size + 10, sizeof(char));
+
while (wasRead < size) {
[self->buffer la:(size - wasRead < LaSize) ? (size - wasRead) : LaSize];
/* normalize response \r\n -> \n */
- tmpBuf = malloc(sizeof(char) * size + 10);
+ tmpBuf = calloc(size + 10, sizeof(char));
cnt = 0;
tmpBufCnt = 0;
- tmpSize = size - 1;
- while (cnt < tmpSize) {
- if ((buf[cnt] == '\r') && (buf[cnt+1] == '\n')) {
- cnt++;
- }
- tmpBuf[tmpBufCnt++] = buf[cnt++];
+ tmpSize = size == 0 ? 0 : size - 1;
+ while (tmpBufCnt < tmpSize && cnt < size) {
+ if ((buf[cnt] == '\r') && (buf[cnt + 1] == '\n'))
+ cnt++; /* skip \r */
+
+ tmpBuf[tmpBufCnt] = buf[cnt];
+ tmpBufCnt++;
+ cnt++;
+ }
+ if (cnt < size) {
+ tmpBuf[tmpBufCnt] = buf[cnt];
+ tmpBufCnt++;
+ cnt++;
}
- if (cnt < size)
- tmpBuf[tmpBufCnt++] = buf[cnt++];
result = [NSData dataWithBytesNoCopy:tmpBuf length:tmpBufCnt];
- if (buf) free(buf); buf = NULL;
+ if (buf != NULL) free(buf); buf = NULL;
return result;
}
}
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- if (_parseNumberUntaggedResponse(self, result_)) // la: 5
+ if ([self _parseNumberUntaggedResponse:result_]) // la: 5
/* eg "* 928 FETCH ..." */
return;
break;
return NO;
}
-static BOOL _parseNumberUntaggedResponse(NGImap4ResponseParser *self,
- NGMutableHashMap *result_) {
+- (BOOL)_parseNumberUntaggedResponse:(NGMutableHashMap *)result_ {
NSNumber *number = nil;
NSString *key = nil;
key = [_parseUntil(self, ' ') lowercaseString];
if ([key hasPrefix:@"body["]) {
- [fetch setObject:_parseBodyContent(self) forKey:key];
+ NSDictionary *content;
+
+ if ((content = [self _parseBodyContent]) != nil)
+ [fetch setObject:content forKey:key];
+ else
+ [self logWithFormat:@"ERROR: got no body content for key: '%@'",key];
}
else if ([key isEqualToString:@"body"]) {
[fetch setObject:_parseBody(self) forKey:key];
else
data = _parseData(self);
- if (data)
- [fetch setObject:data forKey:key];
+ if (data != nil) [fetch setObject:data forKey:key];
}
else {
NSException *e;
return result;
}
-static NSDictionary *_parseBodyContent(NGImap4ResponseParser *self) {
+- (NSDictionary *)_parseBodyContent {
NSData *data;
-
+
if (_la(self, 0) == '"') {
NSString *str;
_consume(self,1);
else
data = _parseData(self);
+ if (data == nil) {
+ [self logWithFormat:@"ERROR(%s): got no data.", __PRETTY_FUNCTION__];
+ return nil;
+ }
return [NSDictionary dictionaryWithObject:data forKey:@"data"];
}