3

OS X または iOS は、MIME Encoded-Wordを解析するための API を提供していますか? これらの素敵な文字列:

=?iso-8859-1?Q?=A1Hola,_se=F1or!?=

あるいは、これを行う既知のオープンソース ライブラリはありますか?

4

2 に答える 2

2

@NickolayO. の回答を受け取り、 QSStringsでbase-64 サポートを追加し、 componentsSeparatedByString:andを使用してコードを短縮しましたstringByReplacingOccurrencesOfString:withString:

コードをGitHubで利用できるようにしました。便宜上、スニペットを次に示します。

@implementation NSString (MimeEncodedWord)

- (BOOL) isMimeEncodedWord
{
    return [self hasPrefix:@"=?"]  && [self hasSuffix:@"?="];
}

+ (NSString*) stringWithMimeEncodedWord:(NSString*)word
{ // Example: =?iso-8859-1?Q?=A1Hola,_se=F1or!?=
    NSArray *components = [word componentsSeparatedByString:@"?"];
    if (components.count < 5) return nil;

    NSString *charset = [components objectAtIndex:1];
    NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)charset)); // TODO: What happens if the encoding is invalid?

    NSString *encodingType = [components objectAtIndex:2];
    NSString *encodedText = [components objectAtIndex:3];
    if ([encodingType isEqualToString:@"Q"])
    { // quoted-printable
        encodedText = [encodedText stringByReplacingOccurrencesOfString:@"_" withString:@" "];
        encodedText = [encodedText stringByReplacingOccurrencesOfString:@"=" withString:@"%"];
        NSString *decoded = [encodedText stringByReplacingPercentEscapesUsingEncoding:encoding];
        return decoded;
    } else if ([encodingType isEqualToString:@"B"])
    { // base64
        NSData *data = [QSStrings decodeBase64WithString:encodedText];
        NSString *decoded = [[NSString alloc] initWithData:data encoding:encoding];
        return decoded;
    } else {
        NSLog(@"%@ is not a valid encoding (must be Q or B)", encodingType);
        return nil;
    }    
}

@end
于 2012-12-24T02:25:42.383 に答える
1

これは引用された印刷可能なバージョンのコードです (Mime Encoded-word は引用された印刷可能なバージョンまたは base-64 でエンコードされたものにすることができます)。base64 エンコードの場合は、引用された印刷可能なデコードを base64 デコードに置き換えて、同様に行う必要があります。おそらく、このコードにはいくつかのテストが必要です。また、NSString のエンコーディングのみをサポートします。

- (NSString*) decodeMimeEncodedWord:(NSString*)word
{
    if (![word hasPrefix:@"=?"] || ![word hasSuffix:@"?="])
        return nil;

    int i = 2;
    while ((i < word.length) && ([word characterAtIndex:i] != (unichar)'?'))
        i++;

    if (i >= word.length - 4)
        return nil;

    NSString *encodingName = [word substringWithRange:NSMakeRange(2, i - 2)];
    NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)encodingName));
    // warning! can return 'undefined something' if encodingName is invalid or unknown

    NSString *encodedString;

    if ([[word substringWithRange:NSMakeRange(i + 1, 2)] isEqualToString:@"Q?"])
    {
        // quoted-printable
        encodedString = [word substringWithRange:NSMakeRange(i + 3, word.length - i - 5)];
        NSMutableData *binaryString = [[[NSMutableData alloc] initWithLength:encodedString.length] autorelease];
        unsigned char *binaryBytes = (unsigned char*)[binaryString mutableBytes];
        int j = 0;
        char h;     

        for (i = 0; i < encodedString.length; i++)
        {
            unichar ch = [encodedString characterAtIndex:i];
            if (ch == (unichar)'_')
                binaryBytes[j++] = ' ';
            else if (ch == (unichar)'=')
            {
                if (i >= encodedString.length - 2)
                    return nil;

                unsigned char val = 0;

                // high-order hex char
                h = [encodedString characterAtIndex:++i];
                if ((h >= '0') && (h <= '9'))
                    val += ((int)(h - '0')) << 4;
                else if ((h >= 'A') && (h <= 'F'))
                    val += ((int)(h + 10 - 'A')) << 4;
                else
                    return nil;
                // low-order hex char
                h = [encodedString characterAtIndex:++i];
                if ((h >= '0') && (h <= '9'))
                    val += (int)(h - '0');
                else if ((h >= 'A') && (h <= 'F'))
                    val += (int)(h + 10 - 'A');
                else
                    return nil;

                binaryBytes[j++] = val;             
            }
            else if (ch < 256)
                binaryBytes[j++] = ch;
            else
                return nil;
        }

        binaryBytes[++j] = 0;
        [binaryString setLength:j];

        NSString *result = [[NSString alloc] initWithCString:[binaryString mutableBytes] encoding:encoding];        
        // warning! can return 'undefined something' if encoding is invalid or unknown

        return result;
    }
    else if ([[word substringWithRange:NSMakeRange(i + 1, 2)] isEqualToString:@"B?"])
    {
        // base64-encoded       
        return nil;
    }
    else
        return nil;
}
于 2012-12-23T21:28:33.143 に答える