IPhone - Apple's completion vaguely "VerificationController.m"

I am trying to implement the new VerificationController.m class that Apple has released to fix an in-app purchase fraud problem.

Like everything released by Apple, this is another vague, incomplete and poorly explained document with a lot of voids and unknowns that cannot be circumvented / understood by everyone.

I am trying to implement this, but at the end of the code we see these four methods:

- (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; } 

You can see that Apple was lazy to implement the C functions at the end of the code. Since my C / C ++ features stink, I see that I need to implement these two functions in C / C ++ and that they should return char and void (???). Other people have placed routines to do this on SO, but they are either in Objective-C or they don't return characters and void (??).

NOTE. This is another problem: how does the method return void if it is used by Apple in this form?

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

should uint8_t be returned?

NOTE 2. Another problem is that the apple says base64_encode is required, but it is not used in the code provided by them. I think they smoke bad things, or my knowledge of C / C ++ really stinks.

So, back to my first question. Can someone send / specify a method that can perform a task that follows the requirements of the declared base64_encode and base64_decode methods? Please refrain from publishing Objective-C methods that are incompatible with these requirements set by Apple.

Thanks.

+6
source share
3 answers

This solution should be fairly simple, including all methods for filling in the missing information. Tested and functioning in the sandbox.

 // 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; } 
+8
source

Here is the base encoding function 64 for NSString - 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; } 

and here is the basic 64 decoding function for NSString to 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; } 

They were compiled from examples that I found in various places on the Internet when I looked for them some time ago. It may be easier for them to implement. I just created the Base64 class and put these methods into it.

+3
source

Here are the C wrappers around Justin:

 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]; } 

Where Class is the class containing Justin functions.

+2
source

Source: https://habr.com/ru/post/921218/


All Articles