This question already has answers here:
Objective-c iPhone percent encode a string?
(8 answers)
Closed 8 years ago.
I'm trying to encode url string using Objective-c
// 1. Get string
char res = ((char)(400));
NSString *unencodedString = [NSString stringWithFormat:#"%c",res];
// 2. Encode string
static NSString *escape = #":/?&=;+!##$()',*[]";
NSString *result = (__bridge_transfer NSString *)
CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef)unencodedString,
NULL,
(__bridge CFStringRef)escape,
kCFStringEncodingUTF8);
// result = %C2%90
But result is not that I expect. Because I get %C6%90 using other programming languages.
As you see Objective-C result is %C2%90, but I expect %C6%90.
Where is my error? Am I do something wrong?
The problem is NSString *unencodedString = [NSString stringWithFormat:#"%c",res] doesn't do what you think it does. char res cannot hold a value larger than 128 (256 for unsigned char).
char res = ((char)(400));
NSString *unencodedString = [NSString stringWithFormat:#"%c",res];
XCTAssertEqualObjects(unencodedString, #"\xc2\x90", #"");
static NSString *escape = #":/?&=;+!##$()',*[]";
NSString *result = (__bridge_transfer NSString *)
CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef)unencodedString,
NULL,
(__bridge CFStringRef)escape,
kCFStringEncodingUTF8);
XCTAssertEqualObjects(result, #"%C2%90", #"");
Here is an example which works.
NSString *unencodedString = #"Ɛ";
static NSString *escape = #":/?&=;+!##$()',*[]";
NSString *result = (__bridge_transfer NSString *)
CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef)unencodedString,
NULL,
(__bridge CFStringRef)escape,
kCFStringEncodingUTF8);
XCTAssertEqualObjects(result, #"%C6%90", #"");
UPDATE
If you want a sample like this to work, use unichar and -stringWithCharacters:length:.
unichar res = ((unichar)(400));
NSString *unencodedString = [NSString stringWithCharacters:&res length:1];
XCTAssertEqualObjects(unencodedString, #"Ɛ", #"");
static NSString *escape = #":/?&=;+!##$()',*[]";
NSString *result = (__bridge_transfer NSString *)
CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef)unencodedString,
NULL,
(__bridge CFStringRef)escape,
kCFStringEncodingUTF8);
XCTAssertEqualObjects(result, #"%C6%90", #"");
Related
We are facing problem while creating compressed file at iOS Device Document Directory, .tgz file is in Hex string transferring from pin-pad device to iPad iOS App at TCP socket layer. We used below HexToString function to convert that hex string and make file with .tgz. but at the end file is corrupted.
Can anyone please help us here, how to create compress file at iOS level with below hex string ? Please suggest us any code changes.
Note :- we had tried multiple NSStringEncoding technique, like ASCII, Unicode, Utf8, etc.
HEX String:-
1F8B08003058A8620203EDCA3B0A80301045D1594A5660265FB7E036065422A8453282CB57B4B2B112419CD3DCE2BD6966DD8F54925E4A975B62D22551EE741A2A5E199E80BBE8F1681DFDA5270BC6DB60D1398735A0092E0650082F580A53566A6F36F7BFFBFDA39A01841042FCD0062C8057FA00080000
we are using Xcode Version:13.1 and IOS Version 15.1 and above.
//Below function we used for creating .tgz file
//fileName here is abc.tgz which is compress file type
//content here is hex string mention aboved
+ (void)writeToLogFile:(NSString*)content fileName:(NSString*)fileNameString{
content = [NSString stringWithFormat:#"%#",content];
NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSString *fileName = [documentsDirectory stringByAppendingPathComponent:fileNameString];
NSData *fileOriginalString = [self HextoString:content];
NSData *fileData = [fileOriginalString dataUsingEncoding:NSASCIIStringEncoding];
***//In alternative we also tried direct hex string to NSData type by calling below commentented method but it still failing
//NSData *fileData = [self dataFromHexString:content];***
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSError *error = nil;
[fileData writeToFile:fileName options:NSDataWritingAtomic error:&error];
NSLog(#"Write returned error: %#", [error localizedDescription]);
});
}
//Below function we used for Hex to String conversion
+(NSString*)HextoString:(NSString*)string{
#try{
NSMutableString * StrResult = [[NSMutableString alloc] init];
int i = 0;
while (i < [string length]){
NSString * hexChar = [string substringWithRange: NSMakeRange(i, 2)];
int value = 0;
sscanf([hexChar cStringUsingEncoding:NSASCIIStringEncoding], "%x", &value);
[StrResult appendFormat:#"%c", (char)value];
i+=2;
}
return StrResult;
}
#catch (NSException *exception){
[AELoggerManager info:[NSString stringWithFormat:#" %s EXCEPTION ::%#",__FUNCTION__,exception]];
}
}
+ (NSData *)dataFromHexString:(NSString *) string {
if([string length] % 2 == 1){
string = [#"0"stringByAppendingString:string];
}
const char *chars = [string UTF8String];
int i = 0, len = (int)[string length];
NSMutableData *data = [NSMutableData dataWithCapacity:len / 2];
char byteChars[3] = {'\0','\0','\0'};
unsigned long wholeByte;
while (i < len) {
byteChars[0] = chars[i++];
byteChars[1] = chars[i++];
wholeByte = strtoul(byteChars, NULL, 16);
[data appendBytes:&wholeByte length:2];
}
return data;
}
I have to remove an NSString (containing some confidential data) from memory but not only by setting it to nil, but by nullifying it's bytes. What I've tried so far is:
NSString *str = #"test";
NSLog(#"original string:%#", str);
CFStringRef ref = (__bridge CFStringRef)str;
const char * strPtr = CFStringGetCStringPtr(ref, kCFStringEncodingUTF8);
memset(strPtr, 0, [str lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
NSLog(#"cleared string:%#", str);
but the function CFStringGetCStringPtr is returning NULL so it crashes at the line with the memset. Apple says here that in some cases it is normal for that function to return NULL, but then I don't know how to solve this.
Thanks in advance
Don't store confident data as strings. You can't remove them from memory easily.
If possible, use NSMutableData to store confident data, instead.
Try This:
NSMutableString *str = [NSMutableString stringWithString:#"test"];
NSLog(#"original string:%#", str);
CFStringRef ref = ( CFStringRef)str;
CFIndex stringLength = CFStringGetLength(ref), usedBytes = 0L;
const char * strPtr = NULL;
strPtr = CFStringGetCStringPtr(ref, kCFStringEncodingUTF8);
char *freeUTF8StringPtr = NULL;
for(CFIndex idx = 0L; (strPtr != NULL) && (strPtr[idx] != 0); idx++)
{
if(strPtr[idx] >= 128) { strPtr = NULL; }
}
if((strPtr == NULL) && ((freeUTF8StringPtr = malloc(stringLength + 1L)) != NULL))
{
CFStringGetBytes(ref, CFRangeMake(0L, stringLength), kCFStringEncodingUTF8, '?', false, (UInt8*)freeUTF8StringPtr, stringLength, &usedBytes);
freeUTF8StringPtr[usedBytes] = 0;
strPtr = (const char *)freeUTF8StringPtr;
}
NSUInteger memorySize=[str lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSLog(#"cleared string:%#", str);
I have tried something like this below:-
NSMutableString *str = #"test";
NSLog(#"original string:%#", str);
CFStringRef ref = (__bridge CFStringRef)str;//kCFStringEncodingUTF16
const char * strPtr = CFStringGetCStringPtr(ref, kCFStringEncodingUTF16);
NSUInteger memorySize=[str lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSLog(#"cleared string:%d", memorySize);
Output := 4
I have a requirement to integrate with a web service that serves as a login. The hash needs to be generated on the client. I am able to produce the correct hash as NSMutableData, but then I need to convert it to a string, without the spaces or brackets produced when the NSMutableData object is rendered as a string in the output console. I have read several posts, all seeming to say the same thing:
NSString *newstring = [[NSString alloc] initWithDSata:dataToConvert encoding:NSUTF8StringEncoding];
Unfortunately, this doesnt work for me. Using NSUTF8StringEncoding returns null. NSASCIIStringEncoding is even worse.
Here is my code:
NSString *password = [NSString stringWithFormat:#"%#%#", kPrefix, [self.txtPassword text]];
NSLog(#"PLAIN: %#", password);
NSData *data = [password dataUsingEncoding:NSASCIIStringEncoding];
NSMutableData *sha256Out = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
CC_SHA256(data.bytes, data.length, sha256Out.mutableBytes);
NSString *preppedPassword = [[NSString alloc] initWithData:sha256Out encoding:NSASCIIStringEncoding];
NSLog(#"HASH: %#\n", preppedPassword);
How can I convert the NSMutableData to string?
My problem is that I need to from this
<7e8df5b3 17c99263 e4fe6220 bb75b798 4a41de45 44464ba8 06266397 f165742e>
to this
7e8df5b317c99263e4fe6220bb75b7984a41de4544464ba806266397f165742e
See How to convert an NSData into an NSString Hex string?
I use a slightly modified version myself:
#implementation NSData (Hex)
- (NSString *)hexRepresentationWithSpaces:(BOOL)spaces uppercase:(BOOL)uppercase {
const unsigned char *bytes = (const unsigned char *)[self bytes];
NSUInteger nbBytes = [self length];
// If spaces is true, insert a space every this many input bytes (twice this many output characters).
static const NSUInteger spaceEveryThisManyBytes = 4UL;
// If spaces is true, insert a line-break instead of a space every this many spaces.
static const NSUInteger lineBreakEveryThisManySpaces = 4UL;
const NSUInteger lineBreakEveryThisManyBytes = spaceEveryThisManyBytes * lineBreakEveryThisManySpaces;
NSUInteger strLen = 2 * nbBytes + (spaces ? nbBytes / spaceEveryThisManyBytes : 0);
NSMutableString *hex = [[NSMutableString alloc] initWithCapacity:strLen];
for (NSUInteger i = 0; i < nbBytes; ) {
if (uppercase) {
[hex appendFormat:#"%02X", bytes[i]];
} else {
[hex appendFormat:#"%02x", bytes[i]];
}
// We need to increment here so that the every-n-bytes computations are right.
++i;
if (spaces) {
if (i % lineBreakEveryThisManyBytes == 0) {
[hex appendString:#"\n"];
} else if (i % spaceEveryThisManyBytes == 0) {
[hex appendString:#" "];
}
}
}
return hex;
}
#end
Now i ve got this code:
-(void)getContacts{
ABAddressBookRef currentAddressBook = ABAddressBookCreate();
if (currentAddressBook) {
CFArrayRef allBook = ABAddressBookCopyArrayOfAllPeople(currentAddressBook);
if (allBook) {
for (int index=0; index < CFArrayGetCount(allBook); index++){
ABRecordRef currentPerson = CFArrayGetValueAtIndex(allBook, index);
NSString *firstName = (__bridge NSString *)ABRecordCopyValue(currentPerson, kABPersonFirstNameProperty);
NSString *lastName = (__bridge NSString *)ABRecordCopyValue(currentPerson, kABPersonLastNameProperty);
NSData *imageData = (__bridge NSData*)ABPersonCopyImageDataWithFormat(currentPerson, kABPersonImageFormatThumbnail);
NSMutableArray *tempArrayForPhones = [[NSMutableArray alloc] init];
ABMultiValueRef phoneNumbersMultiValue = ABRecordCopyValue(currentPerson, kABPersonPhoneProperty);
for(CFIndex counter = 0; counter < ABMultiValueGetCount(phoneNumbersMultiValue); counter++){
CFStringRef currentLabel = ABMultiValueCopyLabelAtIndex(phoneNumbersMultiValue, counter);
NSString *phoneLabel =(__bridge NSString*) ABAddressBookCopyLocalizedLabel(currentLabel);
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(phoneNumbersMultiValue, counter);
currentLabel = ABMultiValueCopyLabelAtIndex(phoneNumbersMultiValue, counter);
phoneLabel =(__bridge NSString*) ABAddressBookCopyLocalizedLabel(currentLabel);
NSString *phoneNumber = (__bridge NSString *)phoneNumberRef;
CFRelease(phoneNumberRef);
CFRelease(currentLabel);
NSDictionary *tempDictForPhonew = [NSDictionary dictionaryWithObjectsAndKeys:phoneNumber,#"number",
phoneLabel,#"label",
nil];
[tempArrayForPhones addObject:tempDictForPhonew];
}
NSDictionary *dictionaryWithAddressBook = [NSDictionary dictionaryWithObjectsAndKeys:firstName,#"firstName",
lastName,#"lastName",
imageData,#"image",
tempArrayForPhones,#"phones",
nil];
tempArrayForPhones = nil;
[dataArray addObject:dictionaryWithAddressBook];
CFRelease(phoneNumbersMultiValue);
}
CFRelease(allBook);
}
CFRelease(currentAddressBook);
}
}
all works fine on simulator, i get array with dictionary, which contains all fields i need. But when i run code on real device(iOS 5.1) dictionary got only first name and last name.
I tried to do some nslog around initializing dictionary, and temp dictionary with phones and image data existed, but not in final dataArray. Whats wrong?
Problem solved; It was a mistake in parsing address book; I forgot to handle contacts without first name.
I am trying to encrypt/decrypt one field of SQLite3 database stored in iPhone app.
I am using this category mentioned in this question.
While encrypting, I am using following code:
NSString *key = #"pass123";
NSString *secret = webNote.note;
NSData *plain = [secret dataUsingEncoding:NSUTF8StringEncoding];
NSData *cipher = [plain AES256EncryptWithKey:key];
sqlite3_bind_text(statement, 1, [[cipher description] UTF8String], -1, SQLITE_TRANSIENT);
It does save data into the field in 74657874 20746f20 656e6372 797074 format.
But while decrypting, I get blank field (tried everything I knew). I am using following code for decrypting:
char *noteDet = (char *)sqlite3_column_text(statement, 1);
NSString *key = #"pass123";
NSString *secret = [NSString stringWithUTF8String:noteDet];
NSData *secretData = [secret dataUsingEncoding:NSUTF8StringEncoding];
NSData *clean = [secretData AES256DecryptWithKey:key];
aNote.note = ([[NSString alloc] initWithData:clean encoding:NSUTF8StringEncoding])?[[NSString alloc] initWithData:clean encoding:NSUTF8StringEncoding]:#"";
I think, I am unable to convert types. Please guide!
Thanks!
The description of NSData returns something like "" => if you were to read that again you would get different overall data ( and of a higher length ), also you are right that you are not converting the data types correctly.
Try saving the NSData object directly, by saving the bytes themselves rather than the description of the NSData object.
void *bytes = [dataObject bytes];
size_t length = [dataObject length];