How to generate vcard in iPhone using the address book contact details? - iphone

I have an application where I want to import the address book details into vcard format. This is the code that I have done but the problem my email address, photo, organisation name, etc is not getting saved in vcard.
-(NSString*)vcardrepresentation
{
NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
[mutableArray addObject:#"BEGIN:VCARD"];
[mutableArray addObject:#"VERSION:3.0"];
[mutableArray addObject:[NSString stringWithFormat:#"FN:%# %#", self.contactlist.objContact.firstname,self.contactlist.objContact.lastname]];
[mutableArray addObject:[NSString stringWithFormat:#"ORG:%#",self.contactlist.objContact.companyname]];
[mutableArray addObject:[NSString stringWithFormat:#"ADR:%#",self.contactlist.objContact.City]];
if ([phoneArray count]!=0)
[mutableArray addObject:[NSString stringWithFormat:#"TEL:%#", phoneemail.phoneNumber]];
if ([emailArray count]!=0)
{
[mutableArray addObject:[NSString stringWithFormat:#"EMAIL:%#",phoneemail.phoneNumber]];
}
if ([contactlist.objContact.Photo length]==0)
{
[mutableArray addObject:[NSString stringWithFormat:#"PHOTO:%#",[UIImage imageNamed:#"man.png"]]];
}
else
{
[mutableArray addObject:[NSString stringWithFormat:#"PHOTO:%#",[UIImage imageWithData:contactlist.objContact.Photo]]];
}
[mutableArray addObject:#"END:VCARD"];
NSString *string = [mutableArray componentsJoinedByString:#"\n"];
return string;
}
How can I save all the contact data in vcard format?

Rani, I suggest the following pseudocode:
Get contact photograph as NSData (contactlist.objContact.Photo)
Convert NSData bytes to BASE 64 encoding scheme (NSData to base64, base64EncodedString)
Add encoded data and properties to vCard:
[mutableArray addObject:[NSString stringWithFormat:#"PHOTO;ENCODING=BASE64;TYPE=JPEG:%#", data]];
For your information vCard photographs are images encoded with Base 64 scheme. There are 16 supported file formats including GIF and JPEG. Here's an example:
PHOTO;ENCODING=BASE64;TYPE=GIF:
R0lGODdhfgA4AOYAAAAAAK+vr62trVIxa6WlpZ+fnzEpCEpzlAha/0Kc74+PjyGM
SuecKRhrtX9/fzExORBSjCEYCGtra2NjYyF7nDGE50JrhAg51qWtOTl7vee1MWu1
50o5e3PO/3sxcwAx/4R7GBgQOcDAwFoAQt61hJyMGHuUSpRKIf8A/wAY54yMjHtz
...

(1) It looks like you are setting the value of the EMAIL property to the phone number.
(2) The format of the ADR property is incorrect. The correct format is to separate the address into its individual components, delimited by semicolons. The format is:
ADR:post-office-box;extended-address;street-address;city;state;zip-code;country
If an address is missing a component (for example, it doesn't have a post office box), then an empty string should be used. Therefore, an ADR value should always contain 6 semicolons.
(3) Semicolons, commas, backslashes, and especially newlines should be escaped in all vCard property values. Semicolon and comma characters have a special meanings inside some properties (such as ADR and ORG), so it is especially important that these characters be escaped for these properties. The characters are escaped with backslashes like so: \;, \,, \\, \n.
(4) Beware of folding. The specs recommended that no line should exceed 75 characters (excluding newline). If a line exceeds this limit, then it can be "folded" by inserting a newline and adding at least one tab or space character at the beginning of the line (as shown in #rjobidon's answer).
(5) The correct newline sequence for a vCard is \r\n not \n.

Related

How to "normalize" an URL replacing any special characters with new ones

In any URL, you can have special characters like *? & ~ : / *
and soon if not already, accentuated characters
What I'd like is to convert ANY url into it's nearest equivalent in pure ASCII character
THEN replacing any remaining spécial charaters by a _
I've tried this looking and inspiring myslef with many examples over the net, but it do not work (for example, using this code, the character "é" is not converted to "e" in #"http://www.mélange.fr/~fermer.php?aa=10&ee=13")
NSMutableCharacterSet *charactersToKeep = [NSMutableCharacterSet alphanumericCharacterSet];
[charactersToKeep addCharactersInString:#"://&=~?"];
NSCharacterSet* charactersToRemove = [charactersToKeep invertedSet];
myNSString = [[[myNSString decomposedStringWithCanonicalMapping] componentsSeparatedByCharactersInSet:charactersToRemove] componentsJoinedByString:#""];
to start, after I will have to convert remaining special characters with _
How may I achieve this ?
As an example (and only for example), I'd like to convert :
http://www.mélange.fr/~fermer.php?aa=10&ee=13
to
http___www.melange.fr__fermer_php_aa_10_ee_13
of course without having to check one by one each possible special or accentued character.
Two thoughts:
To replace accented characters with unaccented ones, there are a couple of candidates:
You can use CFStringTransform:
NSMutableString *mutableString = [string mutableCopy];
CFStringTransform((__bridge CFMutableStringRef)mutableString, NULL, kCFStringTransformStripCombiningMarks, NO);
You could use dataUsingEncoding:allowLossyConversion:
NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
Characters it doesn't know what to do with become ? and but this sometimes replaces one character with multiple characters (e.g. © with (C)), which you may or may not want.
Once you do this international character conversion, it looks like you want replace any non-alphanumeric character (or period) with an underscore, which you could do with a stringByReplacingOccurrencesOfString with a regular expression:
NSString *result = [string stringByReplacingOccurrencesOfString:#"[^a-z0-9\\.]"
withString:#"_"
options:NSRegularExpressionSearch | NSCaseInsensitiveSearch
range:NSMakeRange(0, [string length])];
There are lots of permutations of this regular expression that will accomplish the same thing, but hopefully you get the idea.

get ascii code from string in xcode for iphone app

hey just a couple quick noob questions about writing my first ios app. Ive been searching through the questions here but they all seem to address questions more advanced than mine so im getting confused.
(1) All I want to do is turn a string into an array of integers representing the ASCII code. In other words, I want to convert:
"This is some string. It has spaces, punctuation, AND capitals."
into an array with 62 integers.
(2) How do I get back from the NSArray to a string?
(3) Also, are these expensive operations in terms of memory or computation time? It seems like it might be if we have to create a new variable at every iteration or something.
I know how to declare all the variables and im assuming I run a loop through the length of the string and at each iteration I somehow get the character and convert it into a number with some call to a built in command.
Thanks for any help you can offer or links to posts that might help!
if you want to store the ascii values in an nsarray it is going to be expensive. NSArray can only hold objects so you're going to have to create an NSNumber for each ASCII value:
unsigned len = [string length];
NSMutableArray arr = [NSMutableArray arrayWithCapacity:len];
for (unsigned i = 0; i < len; ++i) {
[arr addObject:[NSNumber numberWithUnsignedShort:[string characterAtIndex:i]]];
}
2) to go back to an NSString you'll need to use an MSMutableString and append each byte to the NSMutableString.
After saying that I'd suggest you don't use this method if you can avoid it.
A better approach would be to use #EmilioPelaez's answer. To go back from a memory buffer to an NSString is simple and inexpensive compared to iterating and concatting strings.
NSString * stringFromMemory = [[NSString alloc] initWithBytes:buffer length:len encoding: NSASCIIStringEncoding];
I ended up using the syntax I found here. Thanks for the help
How to convert ASCII value to a character in Objective-C?
NSString has a method to get the characters in an array:
NSString *string = "This is some string. It has spaces, punctuation, AND capitals.";
unichar *buffer = malloc(sizeof(unichar) * [string lenght]);
[string getCharacters:buffer range:NSMakeRange(0, [string length])];
If you check the definition of unichar, it's an unsigned short.

HmacSHA256 objective-c encryptation

I wanna encpryt a string with a key, using HmacSHA256. The code everyone use is the one below, but there is one thing that doesn´t make sense.
Why would we use base64 at the end if all we want is the HmacSHA256 hash?
I tried seeing the hash generated after the method CCHmac is called with
NSString *str = [[NSString alloc] initWithData:HMAC encoding:NSASCIIStringEncoding];
NSLog(#"%#", str);
But i don´t get the hash generated, i get null, or garbage, like this:
2011-10-11 09:38:05.082 Hash_HmacSHA256[368:207] (null)
2011-10-11 09:38:05.085 Hash_HmacSHA256[368:207] Rwªb7iså{yyþ§Ù(&oá÷ÛËÚ¥M`f
import < CommonCrypto/CommonHMAC.h>
NSString *key;
NSString *data;
const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC
length:sizeof(cHMAC)];
NSString *hash = [HMAC base64Encoding]; //This line doesn´t make sense
[key release];
[data release];
First of all, for those wondering, this is in reference to my answer to this question: Objective-C sample code for HMAC-SHA1
The HMAC you generate is a 256-bit binary value that may or may not start with a 0 byte.
To be able to print it, you need a string representation (binary, hex, decimal, base64, etc.). Base64 is one of the most efficient among these, that's why I used a Base64 encoding there.
The reason you get garbage is that most (if not all) of the octets in the HMAC value are outside the range of printable ASCII characters. If the first octet is 0 (0x00), you get nil. This is why you need an encoding that supports arbitrary values. ASCII doesn't.
Of course, if you don't want to print the HMAC value, then may not need such an encoding, and can keep the HMAC as is (binary NSData).
I spend a whole day, trying to convert the generated hash (bytes) into readable data. I used the base64 encoded you said and it didn´t work at all for me .
So what i did was this:
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
// Now convert to NSData structure to make it usable again
NSData *out = [NSData dataWithBytes:cHMAC length:CC_SHA256_DIGEST_LENGTH];
// description converts to hex but puts <> around it and spaces every 4 bytes
NSString *hash = [out description];
hash = [hash stringByReplacingOccurrencesOfString:#" " withString:#""];
hash = [hash stringByReplacingOccurrencesOfString:#"<" withString:#""];
hash = [hash stringByReplacingOccurrencesOfString:#">" withString:#""];
// hash is now a string with just the 40char hash value in it
NSLog(#"%#",hash);
Don't do "[out description]" to get the hash as a string.
Do [hash base64Encoding] to get the base64 encoding of it. Use http://cybersam.com/ios-dev/http-basic-access-authentication-with-objective-c-and-ios/attachment/nsdataadditions to get the base64Encoding function. The additions class is a category that will add the function base64Encoding to NSData's implementation.
Or you can do [[NSString alloc]initWithData:out encoding:NSUTF8StringEncoding].

Find words with regEx and then add whitespaces inbetween with Objective-c

I was wondering how to add whitespaces inbetween letters/numbers in a string with Objective-C.
I have the sample code kinda working at the moment. Basically I want to turn "West4thStreet" into "West 4th Street".
NSString *myText2 = #"West4thStreet";
NSString *regexString2 = #"([a-z.-][^a-z .-])";
for(NSString *match2 in [myText2 componentsMatchedByRegex:regexString2 capture:1L]) {
NSString *myString = [myText2 stringByReplacingOccurrencesOfString:match2 withString:#" "];
NSLog(#"Prints out: %#",myString); // Prints out: Wes thStreet // Prints out: West4t treet
}
So in this example, it's replacing what I found in regEx (the "t4" and "hS") with spaces. But I just want to add a space inbetween the letters to separate out the words.
Thanks!
If you wrap parts of your regex patterns in parentheses, you can refer to them as $1, $2, etc in your replacement string (patterns are numbered from left to right, by the order of their opening parenthesis).
NSString *origString = #"West4thStreet";
NSString *newString = [origString stringByReplacingOccurrencesOfRegex:#"(4th)" withString:#" $1 "];
Not sure I understand your broader use case, but that should at least get you going...

Detect Unicode characters in NSString on iPhone

I am working on an SMS application for the iPhone. I need to detect if the user has entered any unicode characters inside the NSString they wish to send.
I need to do this is because unicode characters take up more space in the message, and also because I need to convert them into their hexadecimal equivalents.
So my question is how do I detect the presence of a unicode character in an NSString (which I read from a UITextView). Also, how do I then convert those characters into their UCS‐2 hexadecimal equivalents?
E.g 繁 = 7E41, 体 = 4F53, 中 = 4E2D, 文 = 6587
To check for only ascii characters (or another encoding of your choice) use:
[myString canBeConvertedToEncoding:NSASCIIStringEncoding];
It will return NO if the string contains non-ascii characters. You can then convert the string to UCS-2 data with:
[myString dataUsingEncoding:NSUTF16BigEndianStringEncoding];
or NSUTF16LittleEndianStringEncoding depending on your platform. There are slight differences between UCS-2 and UTF-16. UTF-16 has superseded UCS-2. You can read about the differences here:
http://en.wikipedia.org/wiki/UTF-16/UCS-2
I couldn't get this to work.
I has a html string with NON BREAKING SPACE
</div>Great Guildford St/SouthwarkSt & nbsp;Stop:& nbsp; BM<br>Walk to SE1 0HL<br>
"Great Guildford St/SouthwarkSt \U00a0Stop:\U00a0 BM",
I tried 3 types of encode/decode
// NSData *asciiData = [instruction dataUsingEncoding:NSUTF16BigEndianStringEncoding];
// NSString *asciiString = [[NSString alloc] initWithData:asciiData
// encoding:NSUTF16BigEndianStringEncoding];
// NSData *asciiData = [instruction dataUsingEncoding:NSASCIIStringEncoding];
// NSString *asciiString = [[NSString alloc] initWithData:asciiData
// encoding:NSASCIIStringEncoding];
//little endian
NSData *asciiData = [instruction dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
NSString *asciiString = [[NSString alloc] initWithData:asciiData
encoding:NSUTF16LittleEndianStringEncoding];
none of these worked.
They seemed to work as if I NSLog the string it looks ok
NSLog(#"HAS UNICODE :%#", instruction);
..do encode/decode
NSLog(#"UNICODE AFTER:%#", asciiString);
Which output
HAS UNICODE: St/SouthwarkSt  Stop:  BM
UNICODE AFTER: St/SouthwarkSt  Stop:  BM
but I happened to store these in an NSArray and I happened to call [stringArray description] and all the unicode was still in there
instructionsArrayString: (
"Great Guildford St/SouthwarkSt \U00a0Stop:\U00a0 BM",
"Walk to SE1 0HL"
)
So something in NSLog hides but it shows up in NSArray description so you may think youve removed the Unicode when you haven't.
Will try another method that replace the characters.