View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0002096 | SOGo | Web Mail | public | 2012-11-09 13:34 | 2012-11-15 16:49 |
Reporter | cnaumer | Assigned To | |||
Priority | normal | Severity | minor | Reproducibility | random |
Status | closed | Resolution | fixed | ||
Product Version | 2.0.2 | ||||
Target Version | 2.0.2a | Fixed in Version | 2.0.2a | ||
Summary | 0002096: Corruppted JPG, PDF and DOC | ||||
Description | Sending an jpg as attachment can result in the jgp getting corrupted. | ||||
Tags | No tags attached. | ||||
2012-11-09 13:34
|
|
The attached email ist displayed correctly in TB with attachments. The same views in the webinterface looks like the attached jpg-File |
|
2012-11-09 13:36
|
|
The Files that are corrupted are 3 bytes larger in this case. |
|
2012-11-09 13:40
|
|
I'm not sure if this is relevant for this bug I had a corrupted ZIP-attachements issue as well. I've found out that the ZIP file, when downloaded from the SOGo Web interface could only be openned with 7Zip but not from the windows built-in ZIP archiver anymore. |
|
There is a potential fix in sope-mime which was commited a few days ago but which is already availbable in the nightly builds. Could you try with those packages? |
|
I've compiled both SOPE and SOGo from the latest Git repository as instructed on the FAQ. |
|
I've tested the provided JPG with the GIT master branch freshly compiled and get the same result as cnaumer |
|
Files are not corrupted when being sent - it's the reading/viewing portion of SOGo that is broken. |
|
I downgraded our 2.0.2-1 SOGo server to the 2.0.0-1 version (Debian packages) |
|
Can you apply this patch to SOPE? It removes a lot of premature optimizations that cause issues. |
|
2012-11-12 19:44
|
remove-premature-optimizations.diff (22,299 bytes)
diff --git a/sope-core/NGStreams/NGByteBuffer.m b/sope-core/NGStreams/NGByteBuffer.m index 014b857..842cdd0 100644 --- a/sope-core/NGStreams/NGByteBuffer.m +++ b/sope-core/NGStreams/NGByteBuffer.m @@ -19,12 +19,16 @@ 02111-1307, USA. */ -#include "NGStreamProtocols.h" #include "NGByteBuffer.h" #include "common.h" - #include <sys/time.h> +typedef struct NGByteBufferLA { + unsigned char byte; + char isEOF:1; + char isFetched:1; +} LA_NGByteBuffer; + @implementation NGByteBuffer static BOOL ProfileByteBuffer = NO; @@ -40,13 +44,17 @@ static Class DataStreamClass = Nil; DataStreamClass = NSClassFromString(@"NGDataStream"); } ++ (int)version { + return [super version] + 1; +} + + (id)byteBufferWithSource:(id<NGStream>)_source la:(unsigned)_la { if (_source == nil) return nil; if (*(Class *)_source == DataStreamClass) return _source; return [[[self alloc] initWithSource:_source la:_la] autorelease]; } -- (id)initWithSource:(NSObject <NGStream> *)_source la:(unsigned)_la { +- (id)initWithSource:(id<NGStream>)_source la:(unsigned)_la { if (_source == nil) { [self release]; return nil; @@ -66,21 +74,21 @@ static Class DataStreamClass = Nil; // Find first power of 2 >= to requested size for (size = 2; size < _la; size *=2); - self->laImpl = (int (*)(id, SEL, unsigned)) - [self methodForSelector: @selector (la:)]; - self->sourceReadByte = (int(*)(id, SEL)) - [_source methodForSelector: @selector (readByte)]; - self->sourceReadBytes = (int (*)(id, SEL, void *, unsigned)) - [_source methodForSelector: @selector (readBytes:count:)]; - - self->la = malloc(size * sizeof(unsigned char)); + self->la = malloc(sizeof(LA_NGByteBuffer) * size + 4); + memset(self->la, 0, sizeof(LA_NGByteBuffer) * size); self->bufLen = size; self->sizeLessOne = self->bufLen - 1; self->headIdx = 0; - self->freeIdx = 0; - self->EOFIdx = 0; self->wasEOF = NO; + if ([self->source respondsToSelector:@selector(methodForSelector:)]) { + self->readByte = (int(*)(id, SEL)) + [(NSObject *)self->source methodForSelector:@selector(readByte)]; + } + if ([self respondsToSelector:@selector(methodForSelector:)]) { + self->laFunction = (int(*)(id, SEL, unsigned)) + [(NSObject *)self methodForSelector:@selector(la:)]; + } } return self; } @@ -116,210 +124,206 @@ static Class DataStreamClass = Nil; /* operations */ -/* this function reads bytes from self->la *without* increasing self->headIdx */ -static size_t readAllFromBuffer(NGByteBuffer *self, - unsigned char *dest, size_t len) { - size_t required, lastBytesCount; - unsigned localHeadIdx, localNextHeadIdx; - - required = self->freeIdx - self->headIdx; - if (required > 0) { - if (required > len) { - required = len; - } - - localHeadIdx = self->headIdx & self->sizeLessOne; - localNextHeadIdx = (self->headIdx + required) & self->sizeLessOne; - if (localHeadIdx < localNextHeadIdx) { - memcpy(dest, self->la + localHeadIdx, required); - } - else { - lastBytesCount = self->bufLen - localHeadIdx; - memcpy(dest, self->la + localHeadIdx, lastBytesCount); - memcpy(dest + lastBytesCount, self->la, required - lastBytesCount); - } - } - - return required; -} - -/* this function reads *all* bytes from source, unless an exception was - returned. In all case it does *not* increase self->headIdx nor - self->freeIdx. */ -static size_t readAllFromSource(NGByteBuffer *self, - unsigned char *dest, size_t len) { - register size_t totalReadCnt = 0; - register int readCnt; - - while (totalReadCnt < len) { - readCnt = self->sourceReadBytes(self->source, - @selector (readBytes:count:), - dest + totalReadCnt, - len - totalReadCnt); - if (readCnt == NGStreamError) { - NSException *exc = [self->source lastException]; - if ([exc isKindOfClass:[NGEndOfStreamException class]]) { - self->wasEOF = YES; - } - else { - [exc raise]; - } - break; - } - else { - totalReadCnt += readCnt; - } - } - - return totalReadCnt; -} - - (int)readByte { - int byte = self->laImpl(self, @selector (la:), 0); + int byte = (self->laFunction == NULL) + ? [self la:0] + : self->laFunction(self, @selector(la:), 0); [self consume]; return byte; } - (unsigned)readBytes:(void *)_buf count:(unsigned)_len { - size_t totalReadCnt, readCnt; - - if (self->wasEOF && self->headIdx == self->EOFIdx) - [NGEndOfStreamException raiseWithStream:self->source]; - - totalReadCnt = readAllFromBuffer(self, _buf, _len); - self->headIdx += totalReadCnt; - if (totalReadCnt < _len) { - readCnt = readAllFromSource(self, - _buf + totalReadCnt, _len - totalReadCnt); - totalReadCnt += readCnt; - /* if we are here, it means that readAllFromBuffer gave headIdx the same - value as freeIdx */ - self->headIdx += readCnt; - self->freeIdx = self->headIdx; - if (self->wasEOF) { - self->EOFIdx = self->headIdx; - } - } + if (_len == 0) + return 0; - return totalReadCnt; + if (!(self->la[(self->headIdx & self->sizeLessOne)].isFetched)) { + int byte = [self readByte]; + if (byte == -1) + [NGEndOfStreamException raiseWithStream:self->source]; + + ((char *)_buf)[0] = byte; + return 1; + } + else { + unsigned cnt = 0; + int idxCnt = self->headIdx & sizeLessOne; + unsigned char buffer[self->bufLen]; + + while (self->la[idxCnt].isFetched && cnt < _len && cnt < bufLen) { + buffer[cnt] = self->la[idxCnt].byte; + cnt++; + idxCnt = (cnt + self->headIdx) & sizeLessOne; + } + memcpy(_buf, buffer, cnt); + [self consume:cnt]; + return cnt; + } + return 0; } - (int)la:(unsigned)_la { // TODO: huge method, should be split up - int result; - register unsigned idx; + volatile unsigned result, idx; + unsigned i = 0; + + result = -1; + *(&idx) = (_la + self->headIdx) & self->sizeLessOne; if (_la > self->sizeLessOne) { [NSException raise:NSRangeException format:@"tried to look ahead too far (la=%d, max=%d)", _la, self->bufLen]; } - - idx = self->headIdx + _la; - - /* a safeguard against infinite loops in parsers */ - if (self->lastLaIdx == idx) { - self->lastLaIdxCount++; - if (self->lastLaIdxCount > 53) - [NSException raise: NSInternalInconsistencyException - format: @"invoked %s an unreasonable amount of times (%d)", - __PRETTY_FUNCTION__, self->lastLaIdxCount]; - } - else { - self->lastLaIdx = idx; - self->lastLaIdxCount = 0; - } - - if (idx < self->freeIdx) { - result = self->la[idx & self->sizeLessOne]; + + if (self->wasEOF) { + result = (!self->la[idx].isFetched || self->la[idx].isEOF) + ? -1 : self->la[idx].byte; + return result; } - else if (self->wasEOF) { - result = -1; + + if (self->la[idx].isFetched) { + result = (self->la[idx].isEOF) ? -1 : self->la[idx].byte; + return result; } - else { - unsigned max, localFreeIdx; - register unsigned len, readCnt; + *(&i) = 0; + for (i = 0; + i < _la && + self->la[(self->headIdx + i) & self->sizeLessOne].isFetched; + i++); + + /* + If we should read more than 5 bytes, we take the time costs of an + exception handler + */ + if ((_la - i + 1) <= 5) { + while (i <= _la) { #if DEBUG - struct timeval tv; - double ti = 0.0; + struct timeval tv; + double ti = 0.0; #endif + int byte = 0; + #if DEBUG - if (ProfileByteBuffer) { - gettimeofday(&tv, NULL); - ti = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0); - } + if (ProfileByteBuffer) { + gettimeofday(&tv, NULL); + ti = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0); + } #endif + byte = (self->readByte == NULL) + ? [self->source readByte] + : (int)self->readByte(self->source, @selector(readByte)); - max = idx - self->freeIdx + 1; - - localFreeIdx = self->freeIdx & self->sizeLessOne; - len = self->bufLen - localFreeIdx; - if (len > max) { - len = max; - } - - /* fill last bytes of buffer, from the position pointed at by freeIdx */ - readCnt = readAllFromSource(self, self->la + localFreeIdx, len); - self->freeIdx += readCnt; - if (self->wasEOF) { - self->EOFIdx = self->freeIdx; - } - else if (readCnt < max) { - /* if needed fill first bytes of buffer */ - len = max - readCnt; - readCnt = readAllFromSource(self, self->la, len); - self->freeIdx += readCnt; - if (self->wasEOF) { - self->EOFIdx = self->freeIdx; +#if DEBUG + if (ProfileByteBuffer) { + gettimeofday(&tv, NULL); + ti = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0) - ti; + if (ti > 0.01) { + fprintf(stderr, "[%s] <read bytes from stream> : time " + "needed: %4.4fs\n", + __PRETTY_FUNCTION__, ti < 0.0 ? -1.0 : ti); + } + } +#endif + + if (byte == -1) { // EOF was reached + self->wasEOF = YES; + break; } + else { + int ix = (self->headIdx + i) & self->sizeLessOne; + self->la[ix].byte = byte; + self->la[ix].isFetched = 1; + } + i++; } - -#if DEBUG - if (ProfileByteBuffer) { - gettimeofday(&tv, NULL); - ti = (double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0) - ti; - if (ti > 0.01) { - fprintf(stderr, "[%s] <read bytes from stream> : time " - "needed: %4.4fs\n", - __PRETTY_FUNCTION__, ti < 0.0 ? -1.0 : ti); + } + else { + BOOL readStream = YES; + NSException *exc = nil; + + while (readStream) { + int cntReadBytes = 0; + int cnt = 0; + int desiredBytes = _la - i+1; + char *tmpBuffer; + + // TODO: check whether malloc is used for sufficiently large blocks! + tmpBuffer = malloc(desiredBytes + 2); + + cntReadBytes = (self->readBytes == NULL) + ? [self->source readBytes:tmpBuffer count:desiredBytes] + : self->readBytes(self->source, @selector(readBytes:count:), + tmpBuffer, desiredBytes); + + if (cntReadBytes == NGStreamError) { + exc = [[self->source lastException] retain]; + break; } + else { + if (cntReadBytes == desiredBytes) + readStream = NO; + + cnt = 0; + while (cntReadBytes > 0) { + int ix = (self->headIdx + i) & self->sizeLessOne; + self->la[ix].byte = tmpBuffer[cnt]; + self->la[ix].isFetched = 1; + i++; + cnt++; + cntReadBytes--; + } + } + + if (tmpBuffer) free(tmpBuffer); } -#endif - - if (idx < self->freeIdx) { - result = self->la[idx & self->sizeLessOne]; + if (exc) { + if (![exc isKindOfClass:[NGEndOfStreamException class]]) { + [self setLastException:exc]; + return NGStreamError; + } + self->wasEOF = YES; } - else { - result = -1; + } + + if (self->wasEOF) { + while (i <= _la) { + self->la[(self->headIdx + i) & self->sizeLessOne].isEOF = YES; + i++; } } - + + result = (self->la[idx].isEOF) ? -1 : self->la[idx].byte; return result; } - (void)consume { - if (self->headIdx == self->freeIdx) { - self->laImpl(self, @selector (la:), 0); - } - else if (self->headIdx > self->freeIdx) { - [NSException raise: NSRangeException - format: @"a buffer inconsistency was detected"]; + int idx = self->headIdx & sizeLessOne; + + if (!(self->la[idx].isFetched)) { + (self->laFunction == NULL) + ? [self la:0] + : self->laFunction(self, @selector(la:), 0); } + self->la[idx].isFetched = 0; self->headIdx++; } - (void)consume:(unsigned)_cnt { - unsigned nextHead, needed; - - nextHead = self->headIdx + _cnt; - if (nextHead >= self->freeIdx) { - needed = nextHead - self->freeIdx + 1; - self->laImpl(self, @selector (la:), needed); + while (_cnt > 0) { + int idx = self->headIdx & sizeLessOne; + + if (!(self->la[idx].isFetched)) + (self->laFunction == NULL) + ? [self la:0] + : self->laFunction(self, @selector(la:), 0); + + self->la[idx].isFetched = 0; + self->headIdx++; + _cnt--; } - self->headIdx = nextHead; } /* description */ diff --git a/sope-core/NGStreams/NGStreams/NGByteBuffer.h b/sope-core/NGStreams/NGStreams/NGByteBuffer.h index 7c69c04..b4f6603 100644 --- a/sope-core/NGStreams/NGStreams/NGByteBuffer.h +++ b/sope-core/NGStreams/NGStreams/NGByteBuffer.h @@ -43,28 +43,22 @@ struct NGByteBufferLA; @interface NGByteBuffer : NGFilterStream { @protected - unsigned char *la; + struct NGByteBufferLA *la; unsigned bufLen; BOOL wasEOF; unsigned headIdx; - unsigned freeIdx; /* first byte index that has not been fetched */ - unsigned EOFIdx; /* max byte index ever + 1 */ unsigned sizeLessOne; - unsigned lastLaIdx; - unsigned lastLaIdxCount; - - int (*laImpl)(id, SEL, unsigned); - int (*sourceReadByte)(id, SEL); - int (*sourceReadBytes)(id, SEL, void *, unsigned); + int (*readByte)(id, SEL); + int (*laFunction)(id, SEL, unsigned); } /* Initialize a byte buffer with a lookahead depth of _la bytes. */ + (id)byteBufferWithSource:(id<NGStream>)_stream la:(unsigned)_la; -- (id)initWithSource:(NSObject <NGStream> *)_stream la:(unsigned)_la; +- (id)initWithSource:(id<NGStream>)_stream la:(unsigned)_la; // LA - (int)la:(unsigned)_lookaheadPosition; diff --git a/sope-mime/NGImap4/NGImap4ResponseParser.m b/sope-mime/NGImap4/NGImap4ResponseParser.m index 8d45650..aaeac0a 100644 --- a/sope-mime/NGImap4/NGImap4ResponseParser.m +++ b/sope-mime/NGImap4/NGImap4ResponseParser.m @@ -57,16 +57,17 @@ @implementation NGImap4ResponseParser -static __inline__ int _la(NGImap4ResponseParser *self, unsigned _laCnt) { - register unsigned char c; - register unsigned pos = _laCnt; - - while ((c = self->la(self->buffer, @selector(la:), pos)) == '\r') - pos++; +#define __la(__SELF__, __PEEKPOS) \ + ((__SELF__->la == NULL) \ + ? [__SELF__->buffer la:__PEEKPOS]\ + : __SELF__->la(__SELF__->buffer, @selector(la:), __PEEKPOS)) - return c; +static __inline__ int _la(NGImap4ResponseParser *self, unsigned _laCnt) { + register unsigned char c = __la(self, _laCnt); + return (c == '\r') + ? _la(self, _laCnt + 1) + : c; } - static __inline__ BOOL _matchesString(NGImap4ResponseParser *self, const char *s) { @@ -166,7 +167,7 @@ static NSNull *null = nil; if (Imap4MMDataBoundary < 10) /* Note: this should be larger than a usual header size! */ - Imap4MMDataBoundary = 1 << 20; + Imap4MMDataBoundary = 2 * LaSize; StrClass = [NSString class]; NumClass = [NSNumber class]; @@ -194,11 +195,13 @@ static NSNull *null = nil; id s; s = [(NGBufferedStream *)[NGBufferedStream alloc] initWithSource:_stream]; - self->buffer = [[NGByteBuffer alloc] initWithSource:s la:LaSize]; + self->buffer = [NGByteBuffer alloc]; + self->buffer = [self->buffer initWithSource:s la:LaSize]; [s release]; - self->la = (int(*)(id, SEL, unsigned)) - [self->buffer methodForSelector:@selector(la:)]; + if ([self->buffer respondsToSelector:@selector(methodForSelector:)]) + self->la = (int(*)(id, SEL, unsigned)) + [self->buffer methodForSelector:@selector(la:)]; self->debug = debugOn; } @@ -270,7 +273,6 @@ static NSNull *null = nil; l0 = _la(self, 0); if (l0 == '*') { /* those starting with '* ' */ - _consume(self, 1); _parseUntaggedResponse(self, result); if ([result objectForKey:@"bye"]) { endOfCommand = YES; @@ -334,45 +336,17 @@ static void _parseSieveRespone(NGImap4ResponseParser *self, return; } -static NSUInteger _removeCRLF(unsigned char *buffer, size_t len) { - NSUInteger offset; - register size_t new_pos, last_pos = 0; - unsigned char *chr_ptr, *src_ptr; - - new_pos = 0; - offset = 0; - chr_ptr = memchr(buffer, '\r', len); - while (chr_ptr) { - last_pos = new_pos + 1; - new_pos = (chr_ptr - buffer); - if (last_pos > 1) { - offset++; - src_ptr = buffer + last_pos; - memmove(src_ptr - offset, src_ptr, (new_pos - last_pos)); - } - chr_ptr = memchr(chr_ptr + 1, '\r', len - new_pos - 1); - } - if (last_pos > 0) { - last_pos = new_pos + 1; - if (last_pos < len) { - offset++; - src_ptr = buffer + last_pos; - memmove(src_ptr - offset, src_ptr, len - last_pos); - } - } - - return offset; -} - - (NSData *)_parseDataToFile:(unsigned)_size { // TODO: move to own method // TODO: do not use NGFileStream but just fopen/fwrite static NSProcessInfo *Pi = nil; NGFileStream *stream; NSData *result; - unsigned char buf[LaSize + 1]; - unsigned remaining; + unsigned char buf[LaSize + 2]; + unsigned char tmpBuf[LaSize + 2]; + unsigned wasRead = 0; NSString *path; + signed char lastChar; // must be signed if (debugDataOn) [self logWithFormat:@" using memory mapped data ..."]; @@ -391,19 +365,44 @@ static NSUInteger _removeCRLF(unsigned char *buffer, size_t len) { [self setLastException:[e autorelease]]; return nil; } + + lastChar = -1; + while (wasRead < _size) { + unsigned readCnt, bufCnt, tmpSize, cnt, tmpBufCnt; - remaining = _size; - buf[LaSize] = '\0'; - while (remaining > 0) { - unsigned readCnt; - NSUInteger offset; + bufCnt = 0; + + if (lastChar != -1) { + buf[bufCnt++] = lastChar; + lastChar = -1; + } + + [self->buffer la:(_size - wasRead < LaSize) + ? (_size - wasRead) + : LaSize]; + + readCnt = [self->buffer readBytes:buf+bufCnt count:_size - wasRead]; + + wasRead+=readCnt; + bufCnt +=readCnt; - readCnt = [self->buffer readBytes:buf count:(remaining < LaSize) ? remaining : LaSize]; - offset = _removeCRLF(buf, readCnt); - remaining -= readCnt; - - [stream writeBytes:buf count:readCnt-offset]; + tmpSize = bufCnt - 1; + cnt = 0; + tmpBufCnt = 0; + + while (cnt < tmpSize) { + if ((buf[cnt] == '\r') && (buf[cnt+1] == '\n')) { + cnt++; + } + tmpBuf[tmpBufCnt++] = buf[cnt++]; + } + if (cnt < bufCnt) { + lastChar = buf[cnt]; + } + [stream writeBytes:tmpBuf count:tmpBufCnt]; } + if (lastChar != -1) + [stream writeBytes:&lastChar count:1]; [stream close]; [stream release]; stream = nil; @@ -414,27 +413,43 @@ static NSUInteger _removeCRLF(unsigned char *buffer, size_t len) { } - (NSData *)_parseDataIntoRAM:(unsigned)_size { /* parses data into a RAM buffer (NSData) */ - register unsigned char *buf; - // register unsigned char firstChar, nextChar; - NSUInteger wasRead, offset; - NSData *result; - - buf = malloc((_size + 1) * sizeof(char)); - - wasRead = 0; + unsigned char *buf = NULL; + unsigned char *tmpBuf; + unsigned wasRead = 0; + unsigned cnt, tmpBufCnt, tmpSize; + NSData *result; + + buf = calloc(_size + 10, sizeof(char)); + while (wasRead < _size) { - self->la(self->buffer, @selector (la:), (_size - wasRead < LaSize) ? (_size - wasRead) : LaSize); + [self->buffer la:(_size - wasRead < LaSize) ? (_size - wasRead) : LaSize]; + wasRead += [self->buffer readBytes:(buf + wasRead) count:(_size-wasRead)]; } - *(buf + _size) = '\0'; - + /* normalize response \r\n -> \n */ - - offset = _removeCRLF(buf, wasRead); - result = [DataClass dataWithBytesNoCopy:buf - length:wasRead-offset - freeWhenDone:YES]; - + + tmpBuf = calloc(_size + 10, sizeof(char)); + cnt = 0; + tmpBufCnt = 0; + 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++; + } + + result = [DataClass dataWithBytesNoCopy:tmpBuf length:tmpBufCnt]; + + if (buf != NULL) free(buf); buf = NULL; return result; } - (NSData *)_parseData { @@ -584,13 +599,10 @@ static void _parseUntaggedResponse(NGImap4ResponseParser *self, // TODO: is it really required by IMAP4 that responses are uppercase? // TODO: apparently this code *breaks* with lowercase detection on! unsigned char l0, l1 = 0; - - l0 = _la(self, 0); - if (l0 == ' ') { - _consume(self, 1); - l0 = _la(self, 0); - } + _consumeIfMatch(self, '*'); + _consumeIfMatch(self, ' '); + l0 = _la(self, 0); switch (l0) { case 'A': if ([self _parseACLResponseIntoHashMap:result_]) @@ -2496,10 +2508,9 @@ static BOOL _parseNoUntaggedResponse(NGImap4ResponseParser *self, } static BOOL _parseOkUntaggedResponse(NGImap4ResponseParser *self, - NGMutableHashMap *result_) + NGMutableHashMap *result_) { - /* we know the first element is 'O', since the caller has tested it */ - if (!((_la(self, 1)=='K') && (_la(self, 2)==' '))) + if (!((_la(self, 0)=='O') && (_la(self, 1)=='K') && (_la(self, 2)==' '))) return NO; _consume(self, 3); @@ -2676,11 +2687,9 @@ static __inline__ void _consume(NGImap4ResponseParser *self, unsigned _cnt) { if (_cnt == 0) return; - - if (self->la(self->buffer, @selector(la:), _cnt - 1) == '\r') { - _cnt++; - } - + + _cnt += (__la(self, _cnt - 1) == '\r') ? 1 : 0; + if (self->debug) { unsigned cnt; |
I'll give it a try today and will report back. |
|
I can't apply your patch to the master Git branch. root@sogodevel:/home/sogod/sope# patch -p0 --dry-run < patch.txt |
|
Get the latest revision of SOPE from git and simply apply the patch with "patch -p1 < the file". |
|
Oups.. now I'm feeling completely stupid by not having been able to modify my '-p' option ;-) Anyway, you patch fixes the ZIP issue I've reported, as well as the JPG issue reported in this ticket. I've not been able to test with a pdf file causing an issue because I don't have one. |
|
Fix pushed: https://github.com/inverse-inc/sope/commit/a18bb288f890db5747911bf2c74382e59583fde4 |
|
Date Modified | Username | Field | Change |
---|---|---|---|
2012-11-09 13:34 | cnaumer | New Issue | |
2012-11-09 13:34 | cnaumer | File Added: email.txt | |
2012-11-09 13:36 | cnaumer | Note Added: 0004811 | |
2012-11-09 13:36 | cnaumer | File Added: 121108_Trafos_MC2_SkimMilk_2.jpg | |
2012-11-09 13:38 | cnaumer | Note Added: 0004812 | |
2012-11-09 13:40 | cnaumer | File Added: 121108_Trafos_MC2_SkimMilk_2_ok.jpg | |
2012-11-09 15:39 | lemeurt | Note Added: 0004814 | |
2012-11-09 15:47 |
|
Note Added: 0004815 | |
2012-11-09 16:50 | lemeurt | Note Added: 0004817 | |
2012-11-09 16:57 | lemeurt | Note Added: 0004818 | |
2012-11-12 17:01 | ludovic | Note Added: 0004822 | |
2012-11-12 18:09 | flevee | Note Added: 0004824 | |
2012-11-12 19:44 | ludovic | Note Added: 0004827 | |
2012-11-12 19:44 | ludovic | File Added: remove-premature-optimizations.diff | |
2012-11-12 20:04 | ludovic | Target Version | => 2.0.3 |
2012-11-13 08:41 | lemeurt | Note Added: 0004833 | |
2012-11-13 08:53 | lemeurt | Note Added: 0004834 | |
2012-11-13 09:17 | lemeurt | Note Edited: 0004834 | |
2012-11-13 12:04 | ludovic | Note Added: 0004835 | |
2012-11-13 13:00 | lemeurt | Note Added: 0004836 | |
2012-11-13 13:37 | ludovic | Note Added: 0004837 | |
2012-11-13 13:37 | ludovic | Status | new => closed |
2012-11-13 13:37 | ludovic | Resolution | open => fixed |
2012-11-13 13:37 | ludovic | Fixed in Version | => 2.0.3 |
2012-11-15 16:49 | francis | Fixed in Version | 2.0.3 => 2.0.2a |
2012-11-15 16:49 | francis | Target Version | 2.0.3 => 2.0.2a |