This is a xml structure that I want to parse using libxml parsing.
How can i get the attribute value for "campaign" tag i.e ID and for the "image" tag i.e url and size.
If I use these values, i can extract the values of "code" tag and "name " tag.
static const char *kName_campaign = "campaign";
static const NSUInteger kLength_campaign = 9;
static const char *kName_code = "code";
static const NSUInteger kLength_code = 5;
static const char *kName_name = "name";
static const NSUInteger kLength_name = 5;
Then I get the code and name of current and upcoming campaign all together.
This is the code I use in the delegate which gets called when parsing is done.
static void endElementSAX(void *ctx, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI)
{
LibXMLParser *parser = (LibXMLParser *)ctx;
if (parser.parsingASong == NO) return;
if (prefix == NULL)
{
if (!strncmp((const char *)localname, kName_campaign, kLength_campaign))
{
[parser finishedCurrentSong];
parser.parsingASong = NO;
}
else if (!strncmp((const char *)localname, kName_code, kLength_code))
{
parser.currentSong.title = [parser currentString];
NSLog(#"Code :: %#",[parser currentString]);
}
else if (!strncmp((const char *)localname, kName_name, kLength_name))
{
parser.currentSong.category = [parser currentString];
NSLog(#"Name :: %#",[parser currentString]);
}
}
}
How can i get the attributes values from start to bottom of id from "campaign" tag. url and size from "image" tag?
static void startElementSAX(void *ctx, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI, int nb_namespaces, const xmlChar **namespaces, int nb_attributes,
int nb_defaulted, const xmlChar **attributes)
{
if (nb_attributes > 0)
{
NSMutableDictionary* attributeDict = [NSMutableDictionary dictionaryWithCapacity:(NSUInteger)[NSNumber numberWithInt:nb_attributes]];
for (int i=0; i<nb_attributes; i++)
{
NSString* key = [NSString stringWithCString:(const char*)attributes[0] encoding:NSUTF8StringEncoding];
NSString* val = [[NSString alloc] initWithBytes:(const void*)attributes[3] length:(attributes[4] - attributes[3]) encoding:NSUTF8StringEncoding];
attributes += 5;
[attributeDict setValue:val forKey:key];
}
}
}
Try this..
Related
I am trying to encrypt an xml string.After the encryption is done then the decrypt the encrypted d I am getting the string as ALIGNMENT.
I dont understand what is the reason
(NSString*) doCipher:(NSString*)plainText:(CCOperation)encryptOrDecrypt {
const void *vplainText;
size_t plainTextBufferSize;
if (encryptOrDecrypt == kCCDecrypt)
{
NSData *EncryptData = [NSData dataFromBase64String:plainText];
plainTextBufferSize = [EncryptData length];
vplainText = [EncryptData bytes];
}
else
{
plainTextBufferSize = [plainText length];
vplainText = (const void *) [plainText UTF8String];
}
CCCryptorStatus ccStatus;
uint8_t *bufferPtr = NULL;
size_t bufferPtrSize = 0;
size_t movedBytes = 0;
// uint8_t iv[kCCBlockSize3DES];
bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
memset((void *)bufferPtr, 0x0, bufferPtrSize);
// memset((void *) iv, 0x0, (size_t) sizeof(iv));
NSString *key = #"123456789012345678901234";
NSString *initVec = #"init Vec";
const void *vkey = (const void *) [key UTF8String];
const void *vinitVec = (const void *) [initVec UTF8String];
ccStatus = CCCrypt(encryptOrDecrypt,
kCCAlgorithm3DES,
kCCOptionPKCS7Padding,
vkey, //"123456789012345678901234", //key
kCCKeySize3DES,
vinitVec, //"init Vec", //iv,
vplainText, //"Your Name", //plainText,
plainTextBufferSize,
(void *)bufferPtr,
bufferPtrSize,
&movedBytes);
//if (ccStatus == kCCSuccess) NSLog(#"SUCCESS");
//else/
if (ccStatus == kCCParamError) return #"PARAM ERROR";
else if (ccStatus == kCCBufferTooSmall) return #"BUFFER TOO SMALL";
else if (ccStatus == kCCMemoryFailure) return #"MEMORY FAILURE";
else if (ccStatus == kCCAlignmentError) return #"ALIGNMENT";
else if (ccStatus == kCCDecodeError) return #"DECODE ERROR";
else if (ccStatus == kCCUnimplemented) return #"UNIMPLEMENTED";
NSString *result;
if (encryptOrDecrypt == kCCDecrypt)
{
result = [ [NSString alloc] initWithData: [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes] encoding:NSASCIIStringEncoding];
}
else
{
NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
result = [myData base64EncodedString];
}
return result;
}
kCCAlignmentError means that the data you are passing is not correctly padded (specifically that the entire data length including padding is not a multiple of the block size). The most likely cause is that you are truncating your encrypted data somewhere, possibly outside of this routine.
You should check your encrypted data at each step and make sure that it is always a multiple of the block size (8 bytes). You'll need to base64-decode before checking the length.
i am trying to encrypt my data using before sending it to server, is there any highly secure two way encryption algorithm ? which one is best for this purpose.
Check ths once
Here, key is string variable, declare as a global variable.
add sequrity framework for your code and import
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>
- (void)viewDidLoad
{
[super viewDidLoad];
key=#"Your own key";
// encoding
NSString *encodingString=[[self encrypt:[#"Your String"
dataUsingEncoding:NSUTF8StringEncoding]
base64EncodedString];;
//decoding
NSData *data=[self decrypt:[NSData dataFromBase64String:encryptString]];
NSString *decodingString = [[NSString alloc] initWithBytes:[data bytes] length:
[data length] encoding: NSASCIIStringEncoding];
}
- (NSData *) encrypt:(NSData *) plainText {
return [self transform:kCCEncrypt data:plainText];
}
- (NSData *) decrypt:(NSData *) cipherText {
return [self transform:kCCDecrypt data:cipherText];
}
- (NSData *) transform:(CCOperation) encryptOrDecrypt data:(NSData *) inputData {
// kCCKeySizeAES128 = 16 bytes
// CC_MD5_DIGEST_LENGTH = 16 bytes
NSData* secretKey = [ChipperObject md5:Key];
CCCryptorRef cryptor = NULL;
CCCryptorStatus status = kCCSuccess;
uint8_t iv[kCCBlockSizeAES128];
memset((void *) iv, 0x0, (size_t) sizeof(iv));
status = CCCryptorCreate(encryptOrDecrypt,
kCCAlgorithmAES128,kCCOptionPKCS7Padding,
[secretKey bytes], kCCKeySizeAES128, iv, &cryptor);
if (status != kCCSuccess) {
return nil;
}
size_t bufsize = CCCryptorGetOutputLength(cryptor, (size_t)[inputData length],
true);
void * buf = malloc(bufsize * sizeof(uint8_t));
memset(buf, 0x0, bufsize);
size_t bufused = 0;
size_t bytesTotal = 0;
status = CCCryptorUpdate(cryptor, [inputData bytes], (size_t)[inputData length],
buf, bufsize, &bufused);
if (status != kCCSuccess) {
free(buf);
CCCryptorRelease(cryptor);
return nil;
}
bytesTotal += bufused;
status = CCCryptorFinal(cryptor, buf + bufused, bufsize - bufused, &bufused);
if (status != kCCSuccess) {
free(buf);
CCCryptorRelease(cryptor);
return nil;
}
bytesTotal += bufused;
CCCryptorRelease(cryptor);
return [NSData dataWithBytesNoCopy:buf length:bytesTotal];
}
Here is my code using 3des CCCrypt Method,Find GTMBase64.h from googlecode, https://code.google.com/p/google-toolbox-for-mac/source/browse/trunk/Foundation/GTMBase64.h?r=87
#import <CommonCrypto/CommonCryptor.h>
#import "GTMBase64.h"
- (NSData*)TripleDES:(NSData*)plainData encryptOrDecrypt:(CCOperation)encryptOrDecrypt key:(NSString*)key {
const void *vplainText;
size_t plainTextBufferSize;
if (encryptOrDecrypt == kCCDecrypt)
{
NSData *EncryptData = [GTMBase64 decodeData:plainData];
plainTextBufferSize = [EncryptData length];
vplainText = [EncryptData bytes];
}
else
{
plainTextBufferSize = [plainData length];
vplainText = (const void *)[plainData bytes];
}
CCCryptorStatus ccStatus;
uint8_t *bufferPtr = NULL;
size_t bufferPtrSize = 0;
size_t movedBytes = 0;
// uint8_t ivkCCBlockSize3DES;
bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
memset((void *)bufferPtr, 0x0, bufferPtrSize);
// memset((void *) iv, 0x0, (size_t) sizeof(iv));
// NSString *key = #"123456789012345678901234";
NSString *initVec = #"init Vec";
const void *vkey = (const void *) [key UTF8String];
const void *vinitVec = (const void *) [initVec UTF8String];
ccStatus = CCCrypt(encryptOrDecrypt,
kCCAlgorithm3DES,
kCCOptionPKCS7Padding,
vkey, //"123456789012345678901234", //key
kCCKeySize3DES,
vinitVec, //"init Vec", //iv,
vplainText, //"Your Name", //plainText,
plainTextBufferSize,
(void *)bufferPtr,
bufferPtrSize,
&movedBytes);
//if (ccStatus == kCCSuccess) NSLog(#"SUCCESS");
/*else if (ccStatus == kCC ParamError) return #"PARAM ERROR";
else if (ccStatus == kCCBufferTooSmall) return #"BUFFER TOO SMALL";
else if (ccStatus == kCCMemoryFailure) return #"MEMORY FAILURE";
else if (ccStatus == kCCAlignmentError) return #"ALIGNMENT";
else if (ccStatus == kCCDecodeError) return #"DECODE ERROR";
else if (ccStatus == kCCUnimplemented) return #"UNIMPLEMENTED"; */
NSData *result;
if (encryptOrDecrypt == kCCDecrypt)
{
result = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
}
else
{
NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
result = [GTMBase64 encodeData:myData];
}
return result;
}
Usage
NSString *inputString = #"good";
//encode
NSData *inputData = [inputString dataUsingEncoding:NSUTF8StringEncoding];
NSData *encriptdata = [self TripleDES:inputData encryptOrDecrypt:kCCEncrypt key:#"ff68f8e82961489a8b14b345"];
NSString *encodeString = [GTMBase64 stringByEncodingData:encriptdata];
NSLog(#"encodeString : %#" ,encodeString);
//decode
NSData *encodeData = [GTMBase64 decodeString:encodeString];
NSData *decodeData = [self TripleDES:encodeData encryptOrDecrypt:kCCDecrypt key:#"ff68f8e82961489a8b14b345"];
NSString *decodeString = [[NSString alloc] initWithBytes:[decodeData bytes] length:[decodeData length] encoding:NSUTF8StringEncoding];
NSLog(#"decodeString : %#" ,decodeString);
Public Key Infrastructure (PKI) offers you a trustworthy way to encrypt data between 2 machines. You can give it a try.
You can use HTTPS, or you can also use RC6 to encrypt your data.
Im using the following method to convert text to MD5 format.
- (NSString*)MD5
{
const char *ptr = [txt_Password.text UTF8String];
unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
CC_MD5(ptr, strlen(ptr), md5Buffer);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x",md5Buffer[i]];
return output;
}
However, it returns me the MD5 string in 16 bytes. And i need it in 64 bytes. Any help is appreciated. Thank you!!!
For md5: (Add this on a cathegory over NSString as well)
+ (NSString *)hashForString:(NSString *)aString {
NSData *data = [aString dataUsingEncoding:NSUTF8StringEncoding];
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5([data bytes], [data length], digest);
NSString *md5String = [[NSString alloc] initWithBytes:digest length:CC_MD5_DIGEST_LENGTH encoding:NSUTF8StringEncoding];
return [md5String autorelease];
}
For encoding your hashed psw to 64bit format:
- (NSString*)base64MD5HashForString:(NSString *)string {
NSString *md5Hash = [[[NSString hashForString:string] dataUsingEncoding:NSUTF8StringEncoding] encodeBase64];
return md5Hash;
}
Method below is a cathegory over NSData;
static const char kBase64Alphabet[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
- (NSString*)encodeBase64 {
NSMutableString *encodedData = [NSMutableString string];
int i = 0, j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[5];
memset(char_array_3, 0, 3*sizeof(char));
memset(char_array_4, 0, 5*sizeof(char));
int length = [self length];
char *bytes = (char*)[self bytes];
while(length--) {
char_array_3[i++] = *(bytes++);
if (i == 3) {
char_array_4[0] = kBase64Alphabet[(char_array_3[0] & 0xfc)>>2];
char_array_4[1] = kBase64Alphabet[((char_array_3[0] & 0x03) <<4) + ((char_array_3[1] & 0xf0) >>4)];
char_array_4[2] = kBase64Alphabet[((char_array_3[1] & 0x0f) <<2) + ((char_array_3[2] & 0xc0) >>6)];
char_array_4[3] = kBase64Alphabet[char_array_3[2]&0x3f];
[encodedData appendString:[NSString stringWithUTF8String:(const char*)char_array_4]];
i = 0;
}
}
if (i) {
for(j=i; j<3; j++)
char_array_3[j] = '\0';
char_array_4[0] = kBase64Alphabet[(char_array_3[0] & 0xfc)>>2];
char_array_4[1] = kBase64Alphabet[((char_array_3[0] & 0x03) <<4) + ((char_array_3[1] & 0xf0) >>4)];
char_array_4[2] = kBase64Alphabet[((char_array_3[1] & 0x0f) <<2) + ((char_array_3[2] & 0xc0) >>6)];
char_array_4[3] = kBase64Alphabet[char_array_3[2]&0x3f];
char_array_4[i+1] = 0;
[encodedData appendString:[NSString stringWithUTF8String:(const char*)char_array_4]];
while((i++<3))
[encodedData appendString:[NSString stringWithUTF8String:"="]];
}
return encodedData;
}
What should happen.
User send encrypted message to the server. Other user retrieve message from the the server and then decript it. And vice versa.
I have some text in unicode encoding. Text should send to the server using RSA encription as a part of JSON (like {"message" : ""} )
To encript text I create function that have NSString as an input parametr and NSString as an output parametr. Decript function have the same format.
My problem: text that is a result of decode function not the same that was encoded.
-(NSString*) encryptText:(NSString*) text {
OSStatus status = noErr;
//text = #"ネイティブ英会話";
text = #"test text";
int length = [text lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
const char *cText = [text cStringUsingEncoding:NSUTF8StringEncoding];
size_t cipherBufferSize = BUFFER_SIZE;
if (cipherBufferSize < length) {
cipherBufferSize = length;
}
char *cipherBuffer = malloc(cipherBufferSize);
memset(cipherBuffer, 0, cipherBufferSize);
NSLog(#"BEFORE SIPHER TEXT = %s", cText);
status = SecKeyEncrypt(_publicKey,
kSecPaddingNone,
(unsigned char*) cText,
length,
(unsigned char*) cipherBuffer,
&cipherBufferSize
);
NSLog(#"CIPHER TEXT = %s", cipherBuffer);
NSString *result = nil;
if (status == 0) {
result = [NSString stringWithFormat:#"%s", cipherBuffer];
}
free(cipherBuffer);
return result;
}
-(NSString*) decriptText:(NSString*) encriptedText {
OSStatus status = noErr;
const char *cText = [encriptedText cStringUsingEncoding:NSUTF8StringEncoding];
int length = [encriptedText lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
size_t plainBufferSize = BUFFER_SIZE;
if (plainBufferSize < length) {
plainBufferSize = length;
}
char *plainBuffer = malloc(plainBufferSize);
memset(plainBuffer, 0, plainBufferSize);
NSLog(#"BEFORE DECIPHER TEXT = %s", cText);
status = SecKeyDecrypt(_privateKey,
kSecPaddingNone,
(unsigned char *) cText,
length,
(unsigned char *) plainBuffer,
&plainBufferSize
);
NSLog(#"AFTER DESIPHER BUFFER = %s status = %d", plainBuffer, status);
NSString *decriptedText = nil;
if (status == 0) {
decriptedText = [NSString stringWithUTF8String:plainBuffer];
}
free(plainBuffer);
return decriptedText;
}
I got stuck on trying to detect the pair of name and value of the attributes in some general xmls by using libxml2 for parsing the api on iPhone application. For my project, the parsing speed is really important, so I decided to use libxml2 itself instead of using NSXMLParser.
Now, as referring to XMLPerformance that is a sample of iPhone SDK for the parsing benchmark between NSXMLParser and libxml2, I tried to get the detail of attribute in one of XML parser handler as below, but I don't know exactly how to detect it.
/* for example, <element key="value" /> */
static void startElementSAX(void *ctx, const xmlChar *localname, const xmlChar *prefix,
const xmlChar *URI, int nb_namespaces, const xmlChar **namespaces, int nb_attributes,
int nb_defaulted, const xmlChar **attributes)
{
if (nb_attributes > 0)
{
NSMutableDictionary* attributeDict = [NSMutableDictionary dictionaryWithCapacity:(NSUInteger)[NSNumber numberWithInt:nb_attributes]];
for (int i=0; i<nb_attributes; i++)
{
NSString* key = #""; /* expected: key */
NSString* val = #""; /* expected: value */
[attributeDict setValue:val forKey:key];
}
}
}
I saw the libxml2 document, but I can't. Please help me if you are great hacker :)
From looking at the linked documentation I'd think something like this might work:
for (int i=0; i<nb_attributes; i++)
{
// if( *attributes[4] != '\0' ) // something needed here to null terminate the value
NSString* key = [NSString stringWithCString: attributes[0] encoding: xmlencoding];
NSString* val = [NSString stringWithCString: attributes[3] encoding: xmlencoding];
[attributeDict setValue:val forKey:key];
attributes += 5;
}
This assumes that there are always 5 string pointers for each attribute. As it is not otherwise noted I think it is safe to assume that the value string is null terminated and the end pointer is only given to allow easy length calculation. In case the end pointer does not point to a null char you would need to interpret only the chars from attributes[3] up to attributes[4] as value string (length = attributes[4]-attributes[3]).
xmlencoding probably needs to be the encoding of the xml document/entity except libxml2 does some conversion already although this seems unlikely as it typedefs xmlChar to unsigned char.
For Others, based on x4u answer and tksohishi comment:
static void startElementSAX(void *ctx, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI,
int nb_namespaces, const xmlChar **namespaces, int nb_attributes, int nb_defaulted, const xmlChar **attributes)
{
NSLog(#"localname = %s",localname);
if(nb_attributes>0)
{
NSMutableDictionary * attributeDict =[[NSMutableDictionary alloc] initWithCapacity:nb_attributes];
for (int i=0; i<nb_attributes; i++)
{
NSString* key = [NSString stringWithCString:(const char*)attributes[0] encoding:NSUTF8StringEncoding];
NSString* val = [[NSString alloc] initWithBytes:(const void*)attributes[3] length:(attributes[4] - attributes[3]) encoding:NSUTF8StringEncoding]; // it'll be required // [val release];
[attributeDict setValue:val forKey:key];
attributes += 5;
}
}
}