Forgot to disable auto-post from the NotObvious blog.
Catch the original over there
A while back I wrote something for Dropbox users on OS X called Dropbox Cache Cleaner. It was early in the life of the now infamous file sharing/syncing service and they had an effective but rudimentary method of caching deleted items in the event you really needed them back. The trouble was that it could consume large amounts of disk space without you even knowing it.
While it is easy to use Activity Monitor to see whether a running app is 32-bit or 64-bit (sample), it would be even more useful to see this information from the command-line. This post shows you how to combine a bit of rudimentary Python code and correct ps command-line options to see the "bitness" of your running apps.
Executing ps in Terminal.app will show you processes that you own and adding some command-line options: ps -Al, you can get tons of information about each process. In this case, I've asked the ps command to show me all processes and include a decent number of output fields, including one we now really care about, the "flags" field (sample output). "Flags" will end in a "4" (sample Terminal output) if the app is 64-bit, otherwise it ends with a zero.
By saving this script:
as something like "psbit.py" and executing it from the command line with either "32" or "64" as a parameter (it defaults to 64), you will see a list of apps with path names that meet the opted criteria.
When I run it, my system shows 24 active 32-bit processes out of 81 total processes. Good progress, but I shall not rest until I see it be all 64-bit!
UPDATE: A few folks have written (see the comments for the kind contributors) to indicate the path has changed:
file:///Users/USERNAME/Library/Application Support/Feedly/feedly/safari.htm
This post will demonstrate how to make a Fluid app for Feedly (for Safari) and includes a handy application that will make getting Feedly and keeping up with Feedly updates much easier for the average Mac user. Everything has been tested on OS X 10.6 (Snow Leopard) but it all should work on OS X 10.5 (Leopard) (I did not deliberately build anything 64-bit only).
If you are not familiar with Feedly, it is a clever bit of HTML, Javascript and graphic design that turns your Google Reader & Twitter browsing activities into more of a magazine-reading experience. Their site does a great job explaining and presenting the experience, so head there first if you aren't familiar with it. If you agree that makes those two services much easier on the eyes, read on to make it easier on the workflow.
1Password.html which is located on your home system in your ~/Library/Application Support/1Password/1Password.agilekeychain directory).rsync files to a web host under your control, then read on to see what I've cooked up.
When passing data to a web site, especially via "GET" requests (e.g. calling + stringWithContentsOfURL:encoding:error:) it's important to ensure content is properly escaped. This is also true on the iPhone when you are attempting to use a "mailto:" URL to invoke the native e-mail client from your app.
One obvious way to do this is by calling NSString's "- (NSString *)stringByAddingPercentEscapesUsingEncoding:(NSStringEncoding)encoding" method. While this does a good job, it is not perfect and will miss things like "/", which may make some web services cry. The best way to do this encoding is to use:
CFStringRef CFURLCreateStringByAddingPercentEscapes (
CFAllocatorRef allocator,
CFStringRef originalString,
CFStringRef charactersToLeaveUnescaped,
CFStringRef legalURLCharactersToBeEscaped,
CFStringEncoding encoding
);This method lets you specify what you want encoded and what you want left raw. I threw together a really quick sample command line tool to show you the difference. Here are the salient lies:
NSString *url = @"<b>some HTML content</b> <a href=\"http://theresurgence.com/search/node/bible\">study materials</a>" ;
NSLog(@"Original text: [%@]", url) ;
NSLog(@"NSString percent escapes: [%@]",
[ url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]) ;
NSLog(@"CFURL percent escapes: [%@]",
CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)url, NULL, CFSTR("!*'();:@&=+$,/?%#[]"), kCFStringEncodingUTF8));
And, here is the output:
Original text: [<b>some HTML content</b> <a href="http://theresurgence.com/search/node/bible">study materials</a>] NSString percent escapes: [%3Cb%3Esome%20HTML%20content%3C/b%3E%20%3Ca%20href=%22http://theresurgence.com/search/node/bible%22%3Estudy%20materials%3C/a%3E] CFURL percent escapes: [%3Cb%3Esome%20HTML%20content%3C%2Fb%3E%20%3Ca%20href%3D%22http%3A%2F%2Ftheresurgence.com%2Fsearch%2Fnode%2Fbible%22%3Estudy%20materials%3C%2Fa%3E]
Big difference without tons of additional code. Plus, you can use CFURLCreateStringByReplacingPercentEscapesUsingEncoding just as easily to unescape any string.
UITableViewCells with just three UILabels and the second has static-height UITableViewCells three UILabels and one UIImageView. For those two, the following settings are pretty important (translate Interface Builder settings to iPhone SDK calls if you are working – as I am – purely in code):

tableView:cellForRowAtIndexPath:. When I was prototyping, I had a good portion of the transformation code in that method and have since moved it to the XML parsing routines. Since I was not able to set my cells to be opaque, limiting the number of "inner" UIViews was also high on the priority list. I did not need to background load the images in the cells, so I did not have to resort to using a subclass of UITableViewCell but I *did* implement a very rudimentary caching system which helped to speed things up a bit:
NSMutableDictionary called "heights" (the key is the row number) which caches the row heights of each cell since one of the UILabels can drastically vary in height. You need to do something like the following in tableView:heightForRowAtIndexPath::
UILabel's frame size each time in tableView:cellForRowAtIndexPath: and also retrieve said hight and calculate the number of rows in tableView:cellForRowAtIndexPath::
Python on the Mac is a mixed blessing. On one hand, it makes app development much easier. On the other hand, it limits the deployment to OX X 10.5 (Leopard) unless you do some wrangling.
I made an Objective-C version of the "desktop widget" which is available for download now. Most likely, I will not update this version and I have not tested on Tiger yet. If you do test it and it does work (or fails miserably), please drop a note in the comments.
Cocoa is cool and Objective-C is a great language, but I like/prefer Python and the PyObjC bridge makes my life easier and programming actually interesting/fun for me.
This Xcode project is an example of how easy it is to create useful custom views in PyObjC with an example of a graph view that displays a circular queue/buffer. Everything is done starting with an Xcode project which is available for download (76KB compressed archive) and modification. Here is a preview of what you can use out of the box:


The easiest and smallest part of the project is the RingBuffer class that implements a very simple circular queue/buffer and provides direct access to the list that stores the information:
# # RingBuffer.py class RingBuffer: def __init__(self, size): """ init with # of elements in the queue """ self.data = [ None for i in xrange(size) ] def append(self, x): """ take away one and put one in """ self.data.pop(0) self.data.append(x) def get(self): """ return the list so we can manipulate it """ return self.data
There's not a lot of rocket science there, but it's amazing how much code you can eliminate by taking advantage of Python's inherent capabilities. In this case, list initialization is a breeze and removal/insertion of new elements could not be easier.
Next up is the CBGraphView class itself:
There was a bug in the threading in version 1.1 (apologies for not posting an RDN-update for 1.1) which is now fixed in version 1.2 (188KB compressed archive). No other functionality changes, just a bug fix.

In response to a comment, I am also releasing a desktop version, conveniently called DBCC Desktop (272KB compressed archive, OS X 10.5 ONLY). It runs dock-less and menu-less, effectively making it a widget for your desktop. Just click the "Clear Cache" button and you'll get your space back. The info button takes you to the DBCC portion of this site. I did not put Sparkle updates in this app, so check back here for updates. NOTE: there is a discrepancy between the sizes reported between the widget and desktop app. I use "du" for the widget and Python modules for the app. I'm working on tracking down why there is such a difference.
As you can see, I take feedback and problem reports pretty seriously, so drop me a note if you have any issues, complaints or feature requests.
It seems that 2009 is starting off with a Twitter phishing problem. Users are being "tricked" into clicking on links that then do all sorts of bad things.
While these attacks can come via "regular" URLs, we will eventually see phishers use sites like TinyURL to mask their destination, making it that much harder on desktop and in-stream protection mechanisms.

If you run OS X 10.5 (Leopard), I offer you Throw Them Back (592K compressed archive) as a way to stay a step ahead of the bad guys. This version (0.9) has two modes. The most useful one is where you start the app up, then copy a URL to the clipboard and invoke the global shortcut key (Command-Control-J :: this will be a configurable option in the next release) which will take the URL, expand it (if necessary) and run it through the PhishTank screening service to see if it is a "bad" site. PhishTank is run by OpenDNS and is a great service, but it is not comprehensive (no service would be). While you can pretty much trust the items tagged as phishing (indicated by a fish icon that will pop up in the window), you should not assume that a lack of notification equals an OK site.
If you are determined to press on even if you do not recognize an expanded URL (or are unsure about a standard URL), use the arrows next to the URL fields to bring up a drawer that will render the site filtered through Google Mobile. That should take care of any malicious code and let you see if this is a site you really want to visit.
The URL you pasted is put back on the clipboard, so you can use it anywhere you like and you can copy the short or expanded URL from the displayed fields.

The second mode is where you just enter or paste a URL right into the field in the window. While that is useful, it is not nearly as speedy.
I have a bunch of items on the TO DO list, including:
I welcome feedback and suggestions in the comments or on Twitter (@hrbrmstr).
| If you do like the software, please consider clicking the button on the right. I'm seriously contemplating making version 1.0 (this is version 0.9) something you have to pay for to get all the additional features. If you act now, you will receive free upgrades forever for just $3.99USD. Version 1.0 pricing will be $4.99USD. |
If you are interested in purchasing Base to aid your development projects (it is a front-end for SQLite3 database design), you must remove the ".xml" extension on the license file (Base_License.baselicense.xml) Menial sends to you in order for the app to recognize it.
I realize this applies to a very small subset of folks out there (most of whom probably figured this out as quickly as I did), but if this post helps out even one person, it was worth the entry time.
Dropbox is a great way to share items between team or project members and can also help you keep your data synchronized across multiple systems (and web-accessible). It is very fast, especially if files are deleted inadvertently and restored due the use of a cache.
Hidden in your home directory (/Users/username/) is a directory named .dropbox where the application keeps a database of your account configuration (encrypted) and what should be synchronized to your local Dropbox folder. There is also a ~/.dropbox/cache directory which can get huge. Since Dropbox has yet to add cache management to the agent application, you will need to manually clear this out if you want to free up space on your hard drive.
Enter: Dropbox Cache Cleaner. This simple Dashboard Widget lets you see how big your Dropbox cache is and then gives you the option to clear it all away.

While this has worked very well for me, your mileage may vary. If it fries your local Dropbox or interferes with future Dropbox functionality, I take no responsibility.
Drop a note in the comments if you found it useful or if you have suggestions for how to improve the widget. Once Dropbox adds proper cache management tools to their app, I will cease updates.
I've got a decent number of folks on Twitter who are also in my OS X Address Book and I wanted an easier way to keep their Twitter avatars in sync than just manually downloading and updating the images. Enter Taabu [297K DMG], my Twitter Avatar to OS X Address Book Updater.
As long as your OS X Address Book contacts have one URL field with their http://twitter.com/twitterid account in it (and you are following them), you will be able to use Taabu to update their OS X Address Book pictures with their Twitter images.
This currently works for up to ~98 contacts (all depends on your current Twitter API rate limit status, which you can use the widget in the previous post to keep track of) and is fine for me since I have far fewer than that I need to sync. Post a comment if you need that functionality as it will mean some coding to allow processing of your local contacts in batches (due to the rate limit situation). There's a "README" in the DMG download that gives a bit more info and some additional screenshots.
Requests, bug reports, complaints, accolades, etc are all welcome. (And, yes, there is a spelling error in "Downloadig" - will fix when I post the next release which will also contain the full, ugly Objective-C source code :-)

For those who are developing anything that uses the Twitter API or even if you just like to experiment with Twitter standalone or alternate web-clients there is a hard limit (currently 100) on the number of calls per hour. This, however, is not made obvious since it requires grabbing an XML file from an http Basic Auth protected URL.
Enter the "Twitter Rate Limit" Dashboard Widget:

With it, you will know how many API calls you have left and when the counter gets reset.
This is version 1.1. Version 1.0 was inspired by @aadom who was also the UI designer of 1.1.
Version 1.2 will be out in a bit as I really need to fix the gauge colors.
Drop a note in the comments with your suggestions/gripes/accolades.