The following code will deselect the index of an NSArrayController leaving the controller without a selected index. This works well when observing key value “selectedIndex” of NSArrayController when the user is selecting in two different arrays and a reset of the indexes is required to get an observation notice.

-(IBAction)resetArraySelection:(id)sender
{
NSIndexSet *indexEmptySet= [NSIndexSet indexSet];
NSLog(@”manual switching”);
if (manual) {

//NSArrayController 1
[boxList setSelectionIndexes: indexEmptySet];

}else{
//NSArrayController 2

[DeviceArrayController setSelectionIndexes: indexEmptySet];

}
}

In order for AsyncSocket to get notification of a disconnect it needs to have an outstanding read. [socket readDataWithTimeout:-1 tag:0] is only good for 1 read. To have an outstanding read put [socket readDataWithTimeout:-1 tag:0] -didWriteData delegate. When remote disconnects a message is sent through the asynchSocket delegate -willDisconnectWithError. At which point the appropriate code can be used here to deal with disconnect.

Brother printers have a bad low toner count mechanism which prematurely tells the end user that the toners are low when they are not.  The following steps will rest the toner count.

1. Open the front cover that gives you access to the toners.
2. Press and hold “Secure Print” and “Cancel” at the same time. You will see “K-TNR-STD” display on the screen.
3. Using the “+” and “-” buttons select the toner you want to reset.
4. Press the “Ok” button.
5. It will display “Ok?” and hit the “Ok” button again to reset the toner.
6. Close the lid.

Mac OS X 10.7 Lion hides the /user/Library folder from the user by default.

Accessing this folder can be done by going to the Finder Go–>Go to Folder and tying it in there.  Holding down the Option key while clicking on the Go menu will show as a menu option there as well.  For a more permanent solution the following Terminal commands will unhide and hide the folder.

Unhide:

chflags nohidden ~/Library/

Hide:

chflags hidden ~/Library/

Pages templates are keep in a templates folder.  Templates placed in this folder will show up in the list of templates in the “New From Template Chooser” window in Pages. This folder is located in your home directory under the Applications support iWork directory (/Users/yourname/Library/Application Support/iWork/Pages/templates/My Templates).  This directory may not be there under iWork and you will have to create it.  Place your templates here and they will show up when you need them.

 

Recently got an “Drum Life End Soon” message. The printer still worked, but the message keeps popping up.

This is tied to a counter The message can be cleared by:

Need to get to the Rest Parts Life menu.  This can be done by one of two ways depending on the drum status.

If you are getting the Drum Life End Soon Message

Press the + or – button to choose “Machine Info”.
Press OK to proceed to the next menu level, and then press the + or – button to choose
“Reset Parts Life”.
Press OK, and then press the + button to choose “Drum Unit”.
Press OK two times.

*******************OR****************************

If you need to reset the counter without the message appearing.

With the front door open.

1.  Press the GO and + buttons at the SAME time.  The “Reset Parts Life” will appear on the LCD. 
2.  Select Drum Unit.
3.  Press OK

 


Objective C Frameworks for providing licensing in your Applications

1. AquaticPrime http://www.aquaticmac.com/ . Strong encryption, easy to use and provides php scripts to link with paypal to automate the licensing process. However, it does have it’s weaknesses.   Unfortunately the function call that tests whether the license is valid provides a single point of failure.  Hack this function to return true and all is lost. There has been some work done as of late that may prove to be more secure.The updated Version can be found here https://github.com/bdrister/AquaticPrime

2. CocoaFob https://github.com/glebd/cocoafob/

3. Elliptic https://github.com/dchest/ellipticlicense

 

To find a cursor’s position on the screen. All return and NSPoint

-[NSCursor hotSpot]. The hotSpot is the location inside the cursor image of the tip of the arrow.

If you need the mouse position at the time of some event, use -[NSEvent locationInWindow]. 
If you need the mouse position “now” inside some window, use -[NSWindow mouseLocationOutsideOfEventStream].
If you need the mouse position “now” with neither an event nor a window, use +[NSEvent mouseLocation].

This was taken from the Cocoa dev forms.

A few days ago I had to change some file permissions on my freenas server to allow ssh to work. In doing so I could no longer login to the AFP share from my desktop. The strange thing was I could not login from bonjour ‘Shared’ panel on the left of the Finder window but I could connect through Finder in the Go–>Connect. After some investigation I deleted the following files from the root of the share folder on the Freenas.

  1. .AppleDB
  2. .AppleDesktop
  3. .AppleDouble
  4. .TemporaryItems
  5. Network Trash Folder
  6. Temporary Items
  7. .DS_Store

Restarting the AFP service on the Freenas restored the files and everything was back to normal.

After further investigation I realized by looking at the logs that Error Code -5014 refers to a corrupt .AppleDB file. I only needed to delete the .AppleDB file and resart the AFP service to rebuild the database.

While working on a mp4 meta data tagger application, I wanted to use the Amazon Web service API to get the meta data info for the video files.  I remember seeing an example of this in one of my readings.  I found it as one of the chapters in Aaron Hillgass book Cocoa(R) Programming for Mac(R) OS X (3rd Edition).  However, the info was somewhat outdated as Amazon has changed the Restful request requirements.  What follows below is how I accomplished this.  While I would like to claim most of this work my own, that would not be true.  The vast majority of the info was garnered from this post on the bignerd ranch forum.  I simply clarified, adapted and expanded the info to present in this page. The following is the AmaZone project from the book adapted to grab video information.  I would highly suggest reading the chapter to get an idea of what needs to be accomplished.

Creating a Cocoa application that accesses Amazon’s web service requires a quite of bit of coding and time.  Below is a list of requirements to get this going.

1.  Sign up for Amazon Web Service (AWS).

2.  Your Access Key and Secret Key from the AWS service. These can be found under the Account tab Security Credentials.

AWS can be accessed through SOAP or Restful request.  The Restful services is the newer of the two services ad is probably the simplest route to go.  To access the service you will use your Access Key, which any one can see, and your secret key, which is used as part of a Base64 encoding scheme to produce a signature.  Through this process, AWS can assure that you are who you claim to be and no one is tampering with your request.

Open the project in Xcode.

To make this process simpler, start by using the existing code from the book found here on the download examples button.  Once the download is complete, navigate to the AmaZone directory and open the project file.

amazonepict.jpg

Adding the OpenSSL libcrypto.dylib to the AmaZone project.

Libcrypto.dylib is part of the OpenSSL Cryptography and SSL/TLS ToolKit and is included in the Xcode developer Frameworks. We will use this framework to pass the html request to for encoding into a Base64 string. This will create the signature necessary for the Restful request to be successful.  To add it, simply right click on Frameworks in the Groups & Files pane in Xcode and Select Add –> Existing Frameworks.  In the frameworks search window it may be helpful to filter the search to “Dylibs” in the drop down menu.  This should bring up libcrypto.dylib and selecting it should add it to the projects frameworks.

framworkssearch.jpg

Making Changes to the AppController file.

In the AppController.m file add the following #includes.

#import <openssl/ssl.h>//for BIO, etc

#import <CommonCrypto/CommonHMAC.h>//for kCCHmacAlgSHA256

#import <CommonCrypto/CommonDigest.h>//for CC_SHA256_DIGEST_LENGTH

 

Also add your Access Key and Secret Key.

#define AWS_ID @“AKXAJDX2BXQWOKM47XXX”

#define SECRET_KEY @“v111+11111u1i11111hhxVYvzPC1111111111111″

Now we need two things to happen

1.  encode the string into a Base64String.

2.  Make an NSString from the Base64String.

To accomplish this create two categories.

While still in AppController.m we add a method to NSData to accomplish the encoding.  This is done this by creating a Category for NSData .

Insert this before the implementation statement for AppController.

@interface NSData (Base64)

- (NSString *)encodeBase64;

- (NSString *)encodeBase64WithNewlines: (BOOL) encodeWithNewlines;

@end

@implementation NSData (Base64)

- (NSString *)encodeBase64

{

return [selfencodeBase64WithNewlines: NO];

}

- (NSString *)encodeBase64WithNewlines: (BOOL) encodeWithNewlines

{

// Create a memory buffer which will contain the Base64 encoded string

BIO * mem = BIO_new(BIO_s_mem());

// Push on a Base64 filter so that writing to the buffer encodes the data

BIO * b64 = BIO_new(BIO_f_base64());

if (!encodeWithNewlines)

BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);

mem = BIO_push(b64, mem);

// Encode all the data

BIO_write(mem, [selfbytes], [selflength]);

BIO_flush(mem);

// Create a new string from the data in the memory buffer

char * base64Pointer;

BIO_get_mem_data(mem, &base64Pointer);

// deprecated

// long base64Length = BIO_get_mem_data(mem, &base64Pointer);

// NSString * base64String = [NSString stringWithCString: base64Pointer

// length: base64Length];

BIO_get_mem_data(mem, &base64Pointer);

NSString * base64String = [NSString stringWithUTF8String: base64Pointer];

// Clean up and go home

BIO_free_all(mem);

return base64String;

}

@end

Now we need to add a method to NSString so we can take the encoded base64String and form a proper URL. Again this is added before the @implementation statement in the AppController.m file.

@interface NSString (ForURL)

- (NSString*)reallyEncodeURL;

@end

@implementation NSString (ForURL)

- (NSString*)reallyEncodeURL

{

return (NSString*)CFURLCreateStringByAddingPercentEscapes(

NULL,

(CFStringRef)self,

NULL,

(CFStringRef)@”!*’();:@&=+$,/?%#[]”,

kCFStringEncodingUTF8 );

}

@end

Now we need to direct the old fetchBooks method to use the encoding.  Here I also varied from the original AmaZone.  The original AmaZone was a book search while this is a video search.  If you notice in the response_group I included the cover image as well as the Editorial review (summary).

Replace the old fetchBooks method with this one.

- (void)fetchBooks:(id)sender

{

// Show the user that something is going on

[progressstartAnimation:nil];

// Put together the request

// See http://www.amazon.com/gp/aws/landing.html

// Get the string and percent-escape for insertion into URL

NSString *searchString = [[searchFieldstringValue] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

NSLog(@”searchString = %@”, searchString);

// Create the URL

//Timestamp format : needs to be yyyy-mm-ddThh:mm+/-timediff , it’s also set to tomorrow to avoid Request Expired error.

NSDate *now = [[NSDatealloc] initWithTimeIntervalSinceNow:24 * 60 * 60];

NSDateFormatter *dateFormatter = [[NSDateFormatteralloc] init];

[dateFormatter setDateFormat:@”yyyy-MM-dd’T'hh:mm:ssZ”];

NSString *timestamp = [dateFormatter stringFromDate:now];

NSString * encoded_timestamp = [timestamp reallyEncodeURL];

NSLog(@”Date formatted %@ => %@”, timestamp, encoded_timestamp);

// parameters have to be binary sorted

NSString *service_URL = @”ecs.amazonaws.com”;

NSString *service_path = @”/onca/xml”;

NSString *access_ID = [NSString stringWithFormat:@”AWSAccessKeyId=%@&”,AWS_ID];

NSString *keywords = [NSString stringWithFormat:@”Keywords=%@&”,searchString];

NSString *operation = @”Operation=ItemSearch&”;

NSString *response_group = @”ResponseGroup=ItemAttributes%2CImages%2CEditorialReview&”;

NSString *search_index = @”SearchIndex=Video&”;

NSString *service = @”Service=AWSEcommerceService&”;

NSString *signature_method = @”SignatureMethod=HmacSHA256&”;

NSString *signature_version = @”SignatureVersion=2&”;

NSString *ts = [NSString stringWithFormat:@”Timestamp=%@&”, encoded_timestamp];

NSString *version = @”Version=2010-01-01″;

//Signature

NSString *string_to_sign = [NSStringstringWithFormat:@”GETn%@n%@n%@%@%@%@%@%@%@%@%@%@”,

service_URL, service_path, access_ID, keywords, operation, response_group,

search_index, service, signature_method, signature_version, ts, version];

NSLog(@”String to sign = %@”, string_to_sign);

NSString *key = SECRET_KEY;

NSString *data = string_to_sign;

constchar *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding];

constchar *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];

unsignedchar 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 encodeBase64];

NSString *encoded_hash = [hash reallyEncodeURL];

NSLog(@”hash = %@- => %@”, hash, encoded_hash);

// Create the URL

NSString *urlString = [NSStringstringWithFormat:@”http://%@%@?%@%@%@%@%@%@%@%@%@%@&Signature=%@”,

service_URL, service_path, access_ID, keywords, operation, response_group,

search_index, service, signature_method, signature_version, ts, version, encoded_hash];

NSLog(@”urlString = %@”, urlString); // you can paste this in your web browser to see the XML returned

NSURL *url = [NSURL URLWithString:urlString];

NSURLRequest *urlRequest = [NSURLRequestrequestWithURL:url

cachePolicy:NSURLRequestReturnCacheDataElseLoad

timeoutInterval:30];

// Fetch the XML response

NSData *urlData;

NSURLResponse *response;

NSError *error;

urlData = [NSURLConnection sendSynchronousRequest:urlRequest

returningResponse:&response

error:&error];

if (!urlData) {

NSRunAlertPanel(@”Error loading”, @”%@”, nil, nil, nil, [error localizedDescription]);

return;

}

// Parse the XML response

[docrelease];

doc = [[NSXMLDocument alloc] initWithData:urlData

options:0

error:&error];

NSLog(@”doc = %@”, doc);

//ShowTree(doc, 0);

if (!doc) {

NSAlert *alert = [NSAlert alertWithError:error];

[alert runModal];

return;

}

[itemNodesrelease];

itemNodes = [[docnodesForXPath:@”ItemSearchResponse/Items/Item”error:&error] retain];

if (!itemNodes) {

NSAlert *alert = [NSAlert alertWithError:error];

[alert runModal];

return;

}

// Update the interface

[tableViewreloadData];

[progressstopAnimation:nil];

}

We also need to change the tableview data source methods.

- (id)tableView:(NSTableView *)tv objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row

{

NSXMLNode *node = [itemNodes objectAtIndex:row];

NSString *xPath = [tableColumn identifier];

NSLog(@”XPATH = %@”, xPath);

if ([[tableColumn identifier] isEqual:@”Image”])

{

NSString *imageXPath = @”SmallImage/URL”;

NSString *urlString = [self stringForPath:imageXPath ofNode:node];

if (urlString) {

NSURL *url = [NSURL URLWithString:urlString];

NSImage *image = [[NSImagealloc] initWithContentsOfURL:url];

return image;

} else {

returnnil;

}

}

return [selfstringForPath:xPath ofNode:node];

}

@end

Since we have changed the content to video and added images as well as Editorial reviews we need to add two columns in the Tableview.

AmazoneUI.jpg

Add 2 columns.  One with header titled images the other titled Description.  Drag an image cell from the UI library to the Image column. Now run the application and you should get results for your video.