Wishful Coding

Didn't you ever wish your
computer understood you?

My thoughts on iPhone reception

In the press conference Apple gave on July 16 about the iPhone G4 reception issues, they basically said that the 4 or 5 bars you usually see where fake, and caused by a "bug" in the way signal strength is measured.

If I remember correctly, there was another "bug" with the reception prior to iOS 4, that was solved by a software update "improving" G3 reception.

I can't help thinking they just tweaked their formula to show high bars to save their asses, and this backfired on them with iOS 4.
Published on

Bring actual image data in sync with EXIF orientation

While sorting out all my holiday photographs, I turned them to the right orientation using F-Spot photo manager. When I came home I imported them into Adobe bridge, sorted them all out using all sorts of labels, tags and ratings.

Everything was fine so far, until I looked at them with a bad viewer, or uploaded them to Facebook. F-Spot and Bridge happily adjusted the orientation in the EXIF meta-date, but left the actual image untouched.
Not all viewers check the EXIF data before displaying an image, so they display it in the original orientation, corresponding to orientation 1 in EXIF.

Now I was stuck with over a thousand neatly sorted and rotated photos, that I could not publish without rotating them all again with another application.

Luckily I was saved by this page: http://sylvana.net/jpegcrop/exif_orientation.html

If you run Mac and probably Linux as well, jpegtran is already installed.

Just download the C app and the Bash script, but them in the same folder and run this command to compile:
gcc -o jpegexiforient jpegexiforient.c
Now run these commands to make the files executable:
chmod +x jpegexiforient
chmod +x exifautotran
I had to change exifautotran to read ./jpegexiforient in 2 places instead of just jpegexiforient. Otherwise it'd say "command not found".
Now you can run "./exifautotran file.jpg" to convert a single file, or "./exifautotran /dir/*.jpg" to convert a whole directory of jpg files.

Twitter xAuth in Python using Twisted and Twitty Twister

This is the first post in what will most likely be a series of posts related to Twitter, POP3, SMTP and Twisted. This post will be about asynchronous authentication with Twitter using xAuth.

xAuth is a simplified form of OAuth. Instead of doing the dance, you use credentials(like basic auth), but exchange them for an access token. You need to send a request to api@twitter.com to enable it.

This technique is also applicable to getting OAuth tokens, although that is more complicated.

We are going to use Twitty Twister, which is a Twitter lib for Twisted which supports signing OAuth requests. It does not, however, include code for obtaining an access token.

To obtain the token, it is suggested to use an external library. But since my app is 100% Twisted, and most OAuth libs blocking, I had a problem right there. We don’t want to have our nice reactor sit idle while we request our token, do we?

The solution is to use python-oauth to make the request, but just before we send it, you call request.to_postdata() and use twisted.web.client.getPage to send the request in an asynchronous manner.

My main resources where: http://dev.twitter.com/pages/xauth http://github.com/simplegeo/python-oauth2#readme http://twistedmatrix.com/documents/10.1.0/api/twisted.web.client.getPage.html

The resulting code(insert your key, secret, username and password):

from oauth import oauth
from twisted.web.client import getPage
from twisted.internet import reactor
from twittytwister import twitter
import cgi

url = "https://api.twitter.com/oauth/access_token"
consumer = oauth.OAuthConsumer("key", "secret")

def respond(tokens):
    params = cgi.parse_qs(tokens, keep_blank_values=False)
    key = params['oauth_token'][0]
    secret = params['oauth_token_secret'][0]
    print "got access"

    token = oauth.OAuthToken(key, secret)
    tweet = twitter.Twitter(consumer=consumer, token=token).update("Hello world! First tweet using xauth via #Twisted and #Python")
    tweet.addCallback(posted)

def posted(message):
    print "message:", message

request = oauth.OAuthRequest.from_consumer_and_token(oauth_consumer=consumer, http_method='POST', http_url=url,
    parameters = {
        'x_auth_mode': 'client_auth',
        'x_auth_username': 'username',
        'x_auth_password': 'password'
    }
)
request.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(), consumer, None)

page = getPage(url, method='POST', postdata=request.to_postdata())
page.addCallback(respond)

print "running..."
reactor.run()