6

アプリ内購入詐欺の問題を修正するために Apple がリリースした新しいVerificationController.mクラスを実装しようとしています。

Apple によってリリースされたすべてのものと同様に、これはもう 1 つのあいまいで、不完全で、説明が不十分なドキュメントであり、誰もが回避/理解できない多くの空白と不明な点があります。

私はそれを実装しようとしていますが、コードの最後に次の 4 つのメソッドがあります。

- (NSString *)encodeBase64:(const uint8_t *)input length:(NSInteger)length
{
#warning Replace this method.
    return nil;
}

- (NSString *)decodeBase64:(NSString *)input length:(NSInteger *)length
{
#warning Replace this method.
    return nil;
}

#warning Implement this function.
char* base64_encode(const void* buf, size_t size)
{ return NULL; }

#warning Implement this function.
void * base64_decode(const char* s, size_t * data_len)
{ return NULL; }

Apple がコードの最後に C 関数を実装するのを怠っていたことがわかります。私の C/C++ 能力は悪臭を放つので、これら 2 つの関数を C/C++ で実装する必要があり、それらは char と void (???) を返さなければならないことがわかりました。他の人が SO でそれを行うルーチンを投稿しましたが、それらは Objective-C にあるか、char と void (??) を返していません。

注: これは私が抱えている別の問題です: Apple がこの形式で使用する場合、メソッドはどのように void を返すことができますか?

uint8_t *purchase_info_bytes = base64_decode([purchase_info_string cStringUsingEncoding:NSASCIIStringEncoding],                                                 &purchase_info_length);

uint8_t を返すべきではありませんか?

注2:私が抱えている別の問題は、Appleがbase64_encodeが必要であると言っていますが、提供されたコードでは使用されていないことです。彼らは悪いものを吸っていると思いますか、私の C/C++ の知識は本当に悪臭を放っています。

それでは、最初の質問に戻ります。宣言されたメソッドbase64_encodeおよびbase64_decodeの要件に従うジョブを実行できるメソッドを誰かが投稿/指摘できますか? Apple が課したこれらの要件に適合しない Objective-C メソッドの投稿は控えてください。

ありがとう。

4

3 に答える 3

8

このソリューションは、不足している情報を入力するためのすべてのメソッドを含む、非常に簡単なはずです。サンドボックス内でテストされ、機能します。

//  single base64 character conversion
static int POS(char c)
{
    if (c>='A' && c<='Z') return c - 'A';
    if (c>='a' && c<='z') return c - 'a' + 26;
    if (c>='0' && c<='9') return c - '0' + 52;
    if (c == '+') return 62;
    if (c == '/') return 63;
    if (c == '=') return -1;

    [NSException raise:@"invalid BASE64 encoding" format:@"Invalid BASE64 encoding"];
    return 0;
}

- (NSString *)encodeBase64:(const uint8_t *)input length:(NSInteger)length
{
    return [NSString stringWithUTF8String:base64_encode(input, (size_t)length)];
}

- (NSString *)decodeBase64:(NSString *)input length:(NSInteger *)length
{
    size_t retLen;
    uint8_t *retStr = base64_decode([input UTF8String], &retLen);
    if (length)
        *length = (NSInteger)retLen;
    NSString *st = [[[NSString alloc] initWithBytes:retStr
                                             length:retLen
                                           encoding:NSUTF8StringEncoding] autorelease];
    free(retStr);    // If base64_decode returns dynamically allocated memory
    return st;
}

char* base64_encode(const void* buf, size_t size)
{
    static const char base64[] =  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    char* str = (char*) malloc((size+3)*4/3 + 1);

    char* p = str;
    unsigned char* q = (unsigned char*) buf;
    size_t i = 0;

    while(i < size) {
        int c = q[i++];
        c *= 256;
        if (i < size) c += q[i];
        i++;

        c *= 256;
        if (i < size) c += q[i];
        i++;

        *p++ = base64[(c & 0x00fc0000) >> 18];
        *p++ = base64[(c & 0x0003f000) >> 12];

        if (i > size + 1)
            *p++ = '=';
        else
            *p++ = base64[(c & 0x00000fc0) >> 6];

        if (i > size)
            *p++ = '=';
        else
            *p++ = base64[c & 0x0000003f];
    }

    *p = 0;

    return str;
}

void* base64_decode(const char* s, size_t* data_len_ptr)
{
    size_t len = strlen(s);

    if (len % 4)
        [NSException raise:@"Invalid input in base64_decode" format:@"%d is an invalid length for an input string for BASE64 decoding", len];

    unsigned char* data = (unsigned char*) malloc(len/4*3);

    int n[4];
    unsigned char* q = (unsigned char*) data;

    for(const char*p=s; *p; )
    {
        n[0] = POS(*p++);
        n[1] = POS(*p++);
        n[2] = POS(*p++);
        n[3] = POS(*p++);

        if (n[0]==-1 || n[1]==-1)
            [NSException raise:@"Invalid input in base64_decode" format:@"Invalid BASE64 encoding"];

        if (n[2]==-1 && n[3]!=-1)
            [NSException raise:@"Invalid input in base64_decode" format:@"Invalid BASE64 encoding"];

        q[0] = (n[0] << 2) + (n[1] >> 4);
        if (n[2] != -1) q[1] = ((n[1] & 15) << 4) + (n[2] >> 2);
        if (n[3] != -1) q[2] = ((n[2] & 3) << 6) + n[3];
        q += 3;
    }

    // make sure that data_len_ptr is not null
    if (!data_len_ptr)
        [NSException raise:@"Invalid input in base64_decode" format:@"Invalid destination for output string length"];

    *data_len_ptr = q-data - (n[2]==-1) - (n[3]==-1);

    return data;
}
于 2012-07-25T04:32:38.957 に答える
3

NSStringtoの base 64 エンコード関数は次のNSStringとおりです。

+(NSString *) encodeString:(NSString *)inString
{
    NSData *data = [inString dataUsingEncoding:NSUTF8StringEncoding];
    //Point to start of the data and set buffer sizes
    int inLength = [data length];
    int outLength = ((((inLength * 4)/3)/4)*4) + (((inLength * 4)/3)%4 ? 4 : 0);
    const char *inputBuffer = [data bytes];
    char *outputBuffer = malloc(outLength);
    outputBuffer[outLength] = 0;

    //64 digit code
    static char Encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    //start the count
    int cycle = 0;
    int inpos = 0;
    int outpos = 0;
    char temp;

    outputBuffer[outLength-1] = '=';
    outputBuffer[outLength-2] = '=';

    while (inpos < inLength){
        switch (cycle) {
            case 0:
                outputBuffer[outpos++] = Encode[(inputBuffer[inpos]&0xFC)>>2];
                cycle = 1;
                break;
            case 1:
                temp = (inputBuffer[inpos++]&0x03)<<4;
                outputBuffer[outpos] = Encode[temp];
                cycle = 2;
                break;
            case 2:
                outputBuffer[outpos++] = Encode[temp|(inputBuffer[inpos]&0xF0)>> 4];
                temp = (inputBuffer[inpos++]&0x0F)<<2;
                outputBuffer[outpos] = Encode[temp];
                cycle = 3;                  
                break;
            case 3:
                outputBuffer[outpos++] = Encode[temp|(inputBuffer[inpos]&0xC0)>>6];
                cycle = 4;
                break;
            case 4:
                outputBuffer[outpos++] = Encode[inputBuffer[inpos++]&0x3f];
                cycle = 0;
                break;                          
            default:
                cycle = 0;
                break;
        }
    }

    NSString *pictemp = [NSString stringWithUTF8String:outputBuffer];
    free(outputBuffer); 

    return pictemp;
}

NSStringtoの base 64 デコード関数は次のNSStringとおりです。

+(NSString *) decodeString:(NSString *)inString
{
    const char* string = [inString cStringUsingEncoding:NSASCIIStringEncoding];

    NSInteger inputLength = inString.length;

    static char decodingTable[128];

    static char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    for (NSInteger i = 0; i < 128; i++) {
        decodingTable[encodingTable[i]] = i;
    }

    if ((string == NULL) || (inputLength % 4 != 0)) {
        return nil;
    }

    while (inputLength > 0 && string[inputLength - 1] == '=') {
        inputLength--;
    }

    NSInteger outputLength = inputLength * 3 / 4;
    NSMutableData* data = [NSMutableData dataWithLength:outputLength];
    uint8_t* output = data.mutableBytes;

    NSInteger inputPoint = 0;
    NSInteger outputPoint = 0;
    while (inputPoint < inputLength) {
        char i0 = string[inputPoint++];
        char i1 = string[inputPoint++];
        char i2 = inputPoint < inputLength ? string[inputPoint++] : 'A'; /* 'A' will decode to \0 */
        char i3 = inputPoint < inputLength ? string[inputPoint++] : 'A';

        output[outputPoint++] = (decodingTable[i0] << 2) | (decodingTable[i1] >> 4);
        if (outputPoint < outputLength) {
            output[outputPoint++] = ((decodingTable[i1] & 0xf) << 4) | (decodingTable[i2] >> 2);
        }
        if (outputPoint < outputLength) {
            output[outputPoint++] = ((decodingTable[i2] & 0x3) << 6) | decodingTable[i3];
        }
    }

    NSLog(@"%@",data);

    NSString *finalString = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];

    return finalString;
}

少し前にネットで探していた時に見つけた事例をまとめてみました。それらは、実装する方が簡単かもしれません。クラスを作成し、Base64これらのメソッドをその中に配置しました。

于 2012-07-24T16:12:57.503 に答える
2

Justinの回答のCラッパーは次のとおりです。

char* base64_encode(const void* buf, size_t size)
{ 
    NSData* data = [NSData dataWithBytesNoCopy:(void*)buf length:size];
    NSString* string = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
    return [[_Class_ encode:string] UTF8String];
}

void* base64_Decode (const char* s, size_t* data_len)
{
    NSString* result = [_Class_ decode:[NSString stringWithCString:s encoding:NSASCIIStringEncoding]];
    *data_len = result.length;
    return [result UTF8String];
}

Classは Justin の関数を含むクラスです

于 2012-07-24T17:25:07.950 に答える