/* Copyright (C) 2000-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #import #include #include "imCommon.h" @implementation NSString(Imap4) static unsigned int _encodeToModifiedUTF7(unichar *_char, unsigned char *result_, unsigned int *cntRes_); static unsigned int _decodeOfModifiedUTF7(unsigned char *_source, unichar *result_, unsigned int *cntRes_ ); - (NSString *)stringByEncodingImap4FolderName { unichar *buf = NULL; unsigned char *res = NULL; unsigned int len = 0; unsigned int cnt = 0; unsigned int cntRes = 0; NSString *result = nil; len = [self length]; buf = NSZoneMalloc(NULL, (len + 1) * sizeof(unichar)); [self getCharacters: buf]; buf[len] = 0; /* 1 * '&', 3 for the max bytes / char, 1 * '-' */ res = NSZoneMalloc(NULL, ((len * 5) + 1) * sizeof(char)); while (cnt < len) { unichar c = buf[cnt]; if (((c > 31) && (c < 38)) || ((c > 38) && (c < 127))) { res[cntRes++] = c; } else { if (c == '&') { res[cntRes++] = '&'; res[cntRes++] = '-'; } else { res[cntRes++] = '&'; cnt += _encodeToModifiedUTF7(buf + cnt, res + cntRes, &cntRes); res[cntRes++] = '-'; } } cnt++; } if (buf != NULL) NSZoneFree(NULL, buf); res[cntRes] = 0; result = [NSString stringWithCString: (char *) res encoding: NSISOLatin1StringEncoding]; return result; } - (NSString *)stringByDecodingImap4FolderName { unsigned char *buf; unichar *res; unsigned int len; unsigned int cnt = 0; unsigned int cntRes = 0; NSString *result = nil; // NSData *data; if ((len = [self lengthOfBytesUsingEncoding: NSISOLatin1StringEncoding]) == 0) return @""; buf = NSZoneMalloc(NULL, (len + 1) * sizeof(unsigned char)); if ([self getCString:(char *)buf maxLength: len + 1 encoding: NSISOLatin1StringEncoding] == NO) { NSZoneFree(NULL, buf); return @""; } buf[len] = '\0'; res = NSZoneMalloc(NULL, (len + 1) * sizeof(unichar)); while (cnt < len) { /* &- */ unsigned char c; c = buf[cnt]; if (c == '&') { if (buf[cnt + 1] == '-') { res[cntRes++] = '&'; cnt += 2; } else { cnt += _decodeOfModifiedUTF7(buf + cnt + 1, res + cntRes, &cntRes) + 1; } } else { res[cntRes++] = c; cnt++; } } if (buf != NULL) NSZoneFree(NULL, buf); res[cntRes] = 0; result = [NSString stringWithCharacters: res length: cntRes]; return result; } /* check metamail output for correctness */ static unsigned char basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static char index_64[128] = { -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 }; #define char64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) static unsigned int _encodeToModifiedUTF7(unichar *_char, unsigned char *result_, unsigned int *cntRes_) { unsigned int processedSrc, processedDest, cycle; unichar c; char leftover; BOOL hasLeftOver; hasLeftOver = NO; processedSrc = 0; processedDest = 0; cycle = 0; leftover = 0; c = *_char; while (c > 126 || (c > 0 && c < 32)) { if (cycle == 0) { *(result_ + processedDest) = basis_64[(c >> 10) & 0x3f]; *(result_ + processedDest + 1) = basis_64[(c >> 4) & 0x3f]; leftover = (c << 2); hasLeftOver = YES; processedDest += 2; cycle = 1; } else if (cycle == 1) { *(result_ + processedDest) = basis_64[(leftover | (c >> 14)) & 0x3f]; *(result_ + processedDest + 1) = basis_64[(c >> 8) & 0x3f]; *(result_ + processedDest + 2) = basis_64[(c >> 2) & 0x3f]; leftover = (c << 4); hasLeftOver = YES; processedDest += 3; cycle = 2; } else if (cycle == 2) { *(result_ + processedDest) = basis_64[(leftover | (c >> 12)) & 0x3f]; *(result_ + processedDest + 1) = basis_64[(c >> 6) & 0x3f]; *(result_ + processedDest + 2) = basis_64[c & 0x3f]; leftover = 0; hasLeftOver = NO; processedDest += 3; cycle = 0; } processedSrc++; c = *(_char + processedSrc); } if (hasLeftOver) { *(result_ + processedDest) = basis_64[leftover & 0x3f]; processedDest++; } processedSrc--; *cntRes_ += processedDest; return processedSrc; } static unsigned int _decodeOfModifiedUTF7(unsigned char *_source, unichar *result_, unsigned int *cntRes_) { unsigned int processedSrc, processedDest; unsigned char c, decoded; unichar currentRes; int shift; processedSrc = 0; processedDest = 0; shift = 10; currentRes = 0; c = *_source; while (c != 0 && c != '-') { decoded = index_64[c]; if (shift < 0) { currentRes |= (decoded >> (shift * -1)); *(result_ + processedDest) = currentRes; processedDest++; shift += 16; currentRes = (decoded << shift); } else { currentRes |= (decoded << shift); if (shift == 0) { *(result_ + processedDest) = currentRes; processedDest++; currentRes = 0; shift = 16; } } shift -= 6; processedSrc++; c = *(_source + processedSrc); } if (shift != 10) { *(result_ + processedDest) = currentRes; } if (c == '-') processedSrc++; *cntRes_ += processedDest; return processedSrc; } - (NSString *)stringByEscapingImap4Password { // TODO: perf unichar *buffer; unichar *chars; unsigned len, i, j; NSString *s; len = [self length]; chars = NSZoneCalloc(NULL, len + 2, sizeof(unichar)); [self getCharacters:chars]; buffer = NSZoneCalloc(NULL, len * 2 + 2, sizeof(unichar)); buffer[len * 2] = '\0'; for (i = 0, j = 0; i < len; i++, j++) { BOOL conv = NO; if (chars[i] <= 0x1F || chars[i] > 0x7F) { conv = YES; } else switch (chars[i]) { case '(': case ')': case '{': case ' ': case '%': case '*': case '"': case '\\': conv = YES; break; } if (conv) { buffer[j] = '\\'; j++; } buffer[j] = chars[i]; } if (chars != NULL) NSZoneFree(NULL, chars); s = [NSString stringWithCharacters:buffer length:j]; return s; } @end /* NSString(Imap4) */