calling a C function using cocoa - cocoa

I have a C function with the following method signature.
NSString* md5( NSString *str )
How do I call this function, pass in a string, and save the returned string?
I tried the following, but it did not work:
NSString *temp= [[NSString alloc]initWithString:md5(password)];
thanks for your help

You're making it too hard. The stuff in []'s is effectively smalltalk. What you want is to just call the function in C:
NSString * temp = md5(password);

What is password? Is password a common "char *" pointer? Is the md5 signature you put correct?
If that's the case, you could:
NSString *temp = [[NSString alloc] initWithCString:password encoding:NSASCIIStringEncoding];
If your md5 signature is: char *md5(char *password), and you have you password stored in a NSString, you could:
NSString password = #"mypass";
char buff[128];
NSString *temp = [[NSString alloc] initWithString:password];
[temp getCString:buff maxLength:128 encoding:NSASCIIStringEncoding];
char *md5 = md5(buff);
// then you could do whatever you want with md5 var

Related

Sort by Double Value and not String Value

I'm currently pulling info from an sql DB where the 'cachedDist' column is set as a double. However when I pull it into my app and create my array I turn it into an String and the sort will obviously be off, 18.15 will come before 2.15. How do I fix that in my code so it will sort distance as a Double and not a String?
In Bar object.
NSString *cachedDist
#property(nonatomic,copy) NSString *cachedDist;
#synthesize cachedDist;
My while loop in the View Controller.
while (sqlite3_step(sqlStatement)==SQLITE_ROW) {
Bar * bar = [[Bar alloc] init];
bar.barName = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,1)];
bar.barAddress = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,2)];
bar.barCity = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 3)];
bar.barState = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 4)];
bar.barZip = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 5)];
bar.barLat = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 8)];
bar.barLong = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 9)];
if (currentLoc == nil) {
NSLog(#"current location is nil %#", currentLoc);
}else{
CLLocation *barLocation = [[CLLocation alloc] initWithLatitude:[bar.barLat doubleValue] longitude:[bar.barLong doubleValue]];
bar.cachedDist = [NSNumber numberWithDouble:[currentLoc distanceFromLocation: barLocation]/1000];
[thebars addObject:bar];
}
My sorting
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"cachedDist" ascending:YES];
sortedArray = [thebars sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];
return sortedArray;
NSString has a method doubleValue to make this quite simple:
double cachedDistance = [cachedDistanceString doubleValue];
which you can use in a custom comparator for your sorting, or else make the property an NSNumber or double to make sorting that much easier. (I'm not sure how you are sorting...)
edit:
I re-evaluated your code, and now it looks like we are going from a double to a string to a double... we can cut out the middle-man, so to speak.
In your #prototype section, change the #property:
// #property(nonatomic,copy) NSString *cachedDist; // old way
#property(nonatomic) double cachedDist;
then assign it like this:
bar.cachedDistance = [currentLoc distanceFromLocation: barLocation]/1000;
and remove the lines which create a string from the distance (which is actually just a double).
Alternatively, if you want to be more object oriented, you can (should?) use NSNumber objects:
#property(nonatomic,copy) NSNumber *cachedDist;
...
bar.cachedDistance = [NSNumber numberWithDouble:[currentLoc distanceFromLocation: barLocation]/1000];

How to predefine Apple Script constants or variables

Is it possible to predefine constant or variable for an AppleScript in cocoa application?
in other words is the function "addConstantToAppleScript" (used in the following code) definable?
addConstantToAppleScript("myText", "Hello!");
char *src = "display dialog myText";
NSString *scriptSource = [NSString stringWithCString:src];
NSAppleScript *appleScript = [[NSAppleScript alloc] initWithSource:scriptSource];
NSDictionary *scriptError = [[NSDictionary alloc] init];
[appleScript executeAndReturnError:scriptError];
thanks.
If you want to prepend an NSDictionary of key/value pairs to the beginning of an NSString containing AppleScript you could use something like the following function. Personally I would do this as a category on NSString but you have asked for a function.
NSString *addConstantsToAppleScript(NSString *script, NSDictionary *constants) {
NSMutableString *constantsScript = [NSMutableString string];
for(NSString *name in constants) {
[constantsScript appendFormat:#"set %# to \"%#\"\n", name, [constants objectForKey:name]];
}
return [NSString stringWithFormat:#"%#%#", constantsScript, script];
}
This function converts the key/value pairs to AppleScript statements of the form set <key> to "<value>". These statements are then added to the front of the supplied script string. The resulting script string is then returned.
You would use the above function as follows:
// Create a dictionary with two entries:
// myText = Hello\rWorld!
// Foo = Bar
NSDictionary *constants = [[NSDictionary alloc ] initWithObjectsAndKeys:#"Hello\rWorld!", #"myText", #"Bar", #"Foo", nil];
// The AppleScript to have the constants prepended to
NSString *script = #"tell application \"Finder\" to display dialog myText";
// Add the constants to the beginning of the script
NSString *sourceScript = addConstantsToAppleScript(script, constants);
// sourceScript now equals
// set Foo to "Bar"
// set myText to "Hello\rWorld!"
// tell application "Finder" to display dialog myText
NSAppleScript *appleScript = [[NSAppleScript alloc] initWithSource:sourceScript];

Implementing a file format to be used with Encryption - Cocoa

I need to implement salts in my encryption, but to do so, I need to store it in a file format that I need to create so I can later retrieve it to decrypt. I'm a noob when it comes to encryption. The specifications of the file format should be as so:
Ciphertext: length of ciphertext ;
Salt: length of salt ;
Then the ciphertext and salt written out. This is where xcode really confuses me, as in creating a new file, etc.
How can I do this? And then retrieve the salt for decryption?
Thank you, your help is greatly appreciated.
You might consider using NSMutableDictionary and NSKeyedUnarchiver like this:
// Example ciphertext and salt
NSString *ciphertext = #"the ciphertext";
NSString *salt = #"the salt";
// File destination
NSString *path = #"/Users/Anne/Desktop/Archive.dat";
// Create dictionary with ciphertext and salt
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
[dictionary setObject:ciphertext forKey:#"ciphertext"];
[dictionary setObject:salt forKey:#"salt"];
// Archive dictionary and write to file
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dictionary];
[data writeToFile:path options:NSDataWritingAtomic error:nil];
// Read file and unarchive
NSMutableDictionary *theDictionary = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
// Get ciphertext and salt
NSString *theCiphertext = [theDictionary objectForKey:#"ciphertext"];
NSString *theSalt = [theDictionary objectForKey:#"salt"];
// Show Result
NSLog(#"Extracted ciphertext: %#",theCiphertext);
NSLog(#"Extracted salt: %#",theSalt);
Output:
Extracted ciphertext: the ciphertext
Extracted salt: the salt
EDIT
Response to comment: Both NSData and NSString feature length.
Quick example:
NSString *theString = #"Example String";
NSData *theData = [theString dataUsingEncoding:NSUTF8StringEncoding];
NSUInteger stringLength = [theString length];
NSUInteger dataLength = [theData length];
NSLog(#"String length: %ld",stringLength);
NSLog(#"Data length: %ld",dataLength);
Output:
String length: 14
Data length: 14

Cocoa AES Encryption NSData and Bytearrays

I'm using the following code to encrypt files in cocoa:
- (NSData *)AES256EncryptWithKey:(NSString *)key
{
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES256 + 1]; // room for terminator (unused)
bzero( keyPtr, sizeof( keyPtr ) ); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof( keyPtr ) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc( bufferSize );
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt( kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted );
if( cryptStatus == kCCSuccess )
{
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free( buffer ); //free the buffer
return nil;
}
And wrote this for the connection to the file:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"foo" ofType:#"rtf"];
NSData *data = [NSData dataWithContentsOfFile:filePath];
NSString *key = [withFileKey stringValue];
NSString *newStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSString *encrypted = [newStr AES256EncryptWithKey:key];
NSLog(#"File encryption:%#", encrypted);
[filePathName setStringValue:filePath];
if (!data) {
NSLog(#"Unable to read file");
}
Basically what I did was first of all get the filepath of the file the user wants. Then convert the data in the file to a string. Then encrypt that string with the AES256EncryptWithKey: method. However, when I decrypt a plain text file for example, it returns a bunch of garbage like fonts and all that stuff, then the few lines I wrote. Something like this:
\ansicpg1252\cocoartf1138\cocoasubrtf100
{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset0 Menlo-Bold;}
{\colortbl;\red255\green255\blue255;}
\margl1440\margr1440\vieww10800\viewh8400\viewkind0
\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural
\f0\fs24 \cf0 Hello my name is bobby bob\
\
\pard\tx560\pardeftab560\pardirnatural
\f1\b\fs22 \cf0 \CocoaLigature0 YAY!\
and I am awesome!!}
Shouldn't I be taking the data and then encrypting that (conversion to bytes), then convert the encrypted data and convert it to a string to display? I tried something like that but it didn't work. :(
Something like:
NSData *encryptedData = [data AES256EncryptWithKey:yourkey];
And then:
NSString *convertData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
?
Your help is greatly appreciated. Thanks!
Your code appears hard-coded to load foo.rtf. This looks like an RTF file. Where is the "plain text file" you're talking about?
EDIT We had a lot of discussion on this, so I wrote up a blog post about how to correctly use CCCrypt().

Cocoa - Trim all leading whitespace from NSString

(have searched, but not been able to find a simple solution to this one either here, or in Cocoa docs)
Q. How can I trim all leading whitespace only from an NSString? (i.e. leaving any other whitespace intact.)
Unfortunately, for my purposes, NSString's stringByTrimmingCharactersInSet method works on both leading and trailing.
Mac OS X 10.4 compatibility needed, manual GC.
This creates an NSString category to do what you need. With this, you can call NSString *newString = [mystring stringByTrimmingLeadingWhitespace]; to get a copy minus leading whitespace. (Code is untested, may require some minor debugging.)
#interface NSString (trimLeadingWhitespace)
-(NSString*)stringByTrimmingLeadingWhitespace;
#end
#implementation NSString (trimLeadingWhitespace)
-(NSString*)stringByTrimmingLeadingWhitespace {
NSInteger i = 0;
while ((i < [self length])
&& [[NSCharacterSet whitespaceCharacterSet] characterIsMember:[self characterAtIndex:i]]) {
i++;
}
return [self substringFromIndex:i];
}
#end
This is another solution using Regular Expressions (requires iOS 3.2):
NSRange range = [string rangeOfString:#"^\\s*" options:NSRegularExpressionSearch];
NSString *result = [string stringByReplacingCharactersInRange:range withString:#""];
And if you want to trim the trailing whitespaces only you can use #"\\s*$" instead.
This code is taking blanks.
NSString *trimmedText = [strResult stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(#"%#",trimmedText);
Here is a very efficient (uses CoreFoundation) way of doing it (Taken from kissxml):
- (NSString *)trimWhitespace {
NSMutableString *mStr = [self mutableCopy];
CFStringTrimWhitespace((CFMutableStringRef)mStr);
NSString *result = [mStr copy];
[mStr release];
return [result autorelease];
}
NSString *myText = #" foo ";
NSString *trimmedText = [myText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSLog(#"old = [%#], trimmed = [%#]", myText, trimmedText);
Here's what I would do, and it doesn't involve categories!
NSString* outputString = inputString;
NSRange range = [inputString rangeOfCharacterFromSet: [NSCharacterSet whitespaceCharacterSet]
options:0];
if (range.location == 0)
outputString = [inputString substringFromIndex: range.location + range.length];
This is much less code.
I didn't really have much time to test this, and I'm not sure if 10.4 contains the UTF8String method for NSString, but here's how I'd do it:
NSString+Trimming.h
#import <Foundation/Foundation.h>
#interface NSString (Trimming)
-(NSString *) stringByTrimmingWhitespaceFromFront;
#end
NSString+Trimming.m
#import "NSString+Trimming.h"
#implementation NSString (Trimming)
-(NSString *) stringByTrimmingWhitespaceFromFront
{
const char *cStringValue = [self UTF8String];
int i;
for (i = 0; cStringValue[i] != '\0' && isspace(cStringValue[i]); i++);
return [self substringFromIndex:i];
}
#end
It may not be the most efficient way of doing this but it should work.
str = [str stringByReplacingOccurrencesOfString:#" " withString:#""];

Resources