Archive for August, 2008

AdobePDFViewer crashes my Leopard Safari party, gets booted!

I love viewing PDFs on a Mac. The built-in Preview app is lightweight and good for 99% of what I need to do (if you need to digitally sign stuff, created PDFs, etc., then by all means get the official Acrobat reader/writer from Adobe.) I have the latest Acrobat installed (all 1GB or so of it) but I still want to use Preview and Safari's built-in PDF viewer for my daily browsing because it's fast, lightweight, and Just Works.

Until upgrading to Leopard and reinstalling my software, I hadn't had an issue with this at all. But since the upgrade, I started getting the following message when trying to open a PDF with Safari: AdobePDFViewer cannot find a compatible Adobe Acrobat or Adobe Reader to view this PDF. Please select one.

Bummer.

And the dialog that pops up doesn't let me select the Preview app.

A quick Google search later, I find a forum post with the solution.

The thing to do is to delete the AdobePDFViewer.plugin file in the /Library/Internet Plug-Ins/ folder.

I have no idea when Adobe managed to sneak that plugin in there but it was a very naughty thing to do!

Deleting the plugin and restarting Safari has returned things to normal and PDFs now pop up quickly in the built-in previewer.

Dr. Woohoo, Generating Artwork, and some Python code to massage user submitted content (specifically, images).

Cotton Candy Corral ReefThe cool thing about user submitted content is that you can't always predict what you're going to get. Our speakers at the Singularity Web Conference, for example, submit and update their own bios and session descriptions on the site. Yesterday, I noticed that Dr. Woohoo had put up an image of one of his awesome generative artworks in his session description.

Of course, since I hadn't considered images in session descriptions, this had the side-effect of breaking the layout of the sessions page.

(In case you're wondering, yes, this is the way I like to work. Instead of over-engineering things, I like to see how people actually use stuff and then evolve them to meet their needs.)

So tonight I wrote a bit of code to massage and tame how images in session descriptions are displayed and I thought I'd share it with you in case it helps anyone else. (Another, more complicated way to go about things would have been to grab the images using urlfetch, store them in the datastore, and resize them via the image API -- but that would have been overkill for my needs.)

# Copyright (c) 2008 Aral Balkan, Singularity Web Conference
# http://www.singularity08.com
# Released under the open source MIT license.
 
from markdown import Markdown
 
image_tag_width_re = r'(?P<img><img.*?width=")(?P<width>\d*?)"'
image_tag_height_re = r'(?P<img><img.*?height=")(?P<height>\d*?)"'
image_tag_re = r'(<img)(.*?)>'
image_tag_src_re = r'<img.*?src="(.*?)"'
image_tag_alt_re = r'<img.*?alt="(.*?)"'
 
image_tag_width_rc = re.compile(image_tag_width_re)
image_tag_height_rc = re.compile(image_tag_height_re)
image_tag_rc = re.compile(image_tag_re)
image_tag_src_rc = re.compile(image_tag_src_re)
image_tag_alt_rc = re.compile(image_tag_alt_re)
 
IMAGE_SAFE_WIDTH = 160.0
 
def massage_images(html):
	"""Helper: Alters dimensions of any images in the passed HTML to make them safe for the site's design."""
	image_tag_widths = image_tag_width_rc.findall(html)
	image_tag_heights = image_tag_height_rc.findall(html)
	image_tag_srcs = image_tag_src_rc.findall(html)
	image_tag_alts = image_tag_alt_rc.findall(html)
 
	for i in range(len(image_tag_widths)):
		# Reduce the width of any found images to 160px so as not to break the layout
		original_width = int(image_tag_widths[i][1])
 
		maintain_aspect_ratio = True
		try:
			original_height = int(image_tag_heights[i][1])
		except IndexError:
			# Mismatched width/height pairs on image tags. We won't be
			# able to maintain aspect ratio.
			maintain_aspect_ratio = False
 
		if maintain_aspect_ratio:
 
			aspect_ratio = float(original_width)/float(original_height)
			new_height = int(IMAGE_SAFE_WIDTH/aspect_ratio)
 
			# Substitute the new height
			html = image_tag_height_rc.sub(r'\g<img>'+repr(new_height)+r'"', html)
			logging.info(html)
 
		# Substitute the new width
		html = image_tag_width_rc.sub(r'\g<img>'+str(int(IMAGE_SAFE_WIDTH))+'"', html)
 
		# Add float:left and slight margin so that text flows around the image
		html = image_tag_rc.sub(r'\1 style="float:left; margin-right:.5em;" \2>', html)
 
		# Finally, add a link to the original image if people want to see it larger
		html = image_tag_rc.sub(r'<a href="'+ image_tag_srcs[i] + '" title="'+image_tag_alts[i]+r'">\1\2></a>', html)
 
	return html
 

There are a couple of basic but helpful regular expressions in there and you might find the snippet useful if you want to manipulate image tags generated from user submitted content.

Oh, and before I forget, Dr. Woohoo is going to be talking about Generating Artwork at the Singularity Web Conference. Check out his bio and session and the other sessions at the conference.

(You can find out more about Dr.Woohoo on his web site and take a look at his latest book, Color Visualizations: Exploring the Circle, vol 02.)

If you haven't booked your ticket for Singularity yet, hurry, as the $99 early bird discount ends at the end of this month.

Google Groups to Google App Engine: you seem a little shifty to me!

It seems that Google Groups has some seriously strict spam filters in place as they're currently blocking urlfetch requests for RSS feeds from Google App Engine applications.

This morning, I started what I hoped would be a quick Flash widget to display the latest RSS headlines from our new Singularity Local Conference Hubs Google Group on the new local conference hubs page on the Singularity web site.

Since Google Groups does not support consumption of its feeds by Flash and Flex applications (they don't have a crossdomain policy file on their servers), I set up simple server-side proxy and wrote some quick E4X in Flash to parse the Atom feed.

Hit publish, test locally, everything works! Ah, cool, let's deploy and move on.

Not so fast, young man! Have you met Murphy? He sells ceiling fans for lavatories.

I deployed and got an error. Weird.

So I checked the proxy URL directly in the browser and saw the following message:

Google Groups to Google App Engine - you smell spammy

OK, so Google Groups has some paranoid spam filter that's blocking Google App Engine urlfetch requests (quite understandable as Google Groups must have to deal with every type of spam known to humans.)

I opened an issue and posted on both the Google App Engine and Google Groups Help forums so the issue should hopefully be on their radar. Not being one to give up, however, I decided to try another route.

Yahoo! Pipes to the rescue

I need a proxy but I can't use my own app on Google App Engine... wait a minute, Yahoo! Pipes should fit the bill :)

So I set up a very simple pipe that does nothing more than grab the RSS 2.0 feed from Google Groups and re-publish it. Since Yahoo! does have a cross domain policy on Pipes, we can load the RSS feed in directly from Flash.

That's exactly what I did and, instead of parsing the XML by hand, I decided to use the generic FeedFactory parser in as3syndicationlib. So I downloaded that and its dependency, corelib, and refactored my code.

Unfortunately, as3syndicationlib is Flex-only at the moment. It has two simple bugs that have been fixed but have not been included into the library, barring entry to Flash CS3 developers.

The first bug is in ParsingTools.as and produces the following error: ReferenceError: Error #1065: Variable mx.utils::StringUtil is not defined..

The other error is that it uses the Flex-only DateBase class.

Thankfully, Steve Jones ran across the same errors earlier, fixed them, and shared his solution on Mike's blog.

I do hope that Mike finds the time to commit Steve's version into the repository at some point so that Flash CS3 developers can also make use of the excellent AS3 Syndication Library without jumping through these hurdles.

The final hurdle was that Yahoo!'s crossdomain policy is on pipes.yahooapis.com not pipes.yahoo.com. By default, when you copy the RSS feed URL from Yahoo! Pipes, you will get a feed URL that references pipes.yahoo.com. You have to change this to use pipes.yahooapis.com to take advantage of the crossdomain policy file.

Check out the new local conference hubs page to see the simple widget in action.

Photo: Flickr

Make some history: organize a Singularity Web Conference local conference hub!

Singularity Web Conference Local Hubs Google Group

The Singularity Web Conference is breaking new ground: we're creating a new type of web conference that is at once global and local, social, and green. Instead of flying half-way around the world, we're going to be meeting up in our own local communities and using those gorgeous pipes on The Internets to take part in this seminal global event.

Do you want to be instrumental in making this historic effort a success?

Local conference hubs are an essential -- core -- part of the Singularity experience. As community organizers and leaders, your support and participation is invaluable.

Sign up on the Singularity Web Conference Local Hubs Google Group to get involved.

Let's make some history!

Photo: Flickr

New session announcements at the Singularity Web Conference

I just added a sessions list to the Singularity Web Conference site so you can easily skim the announced sessions in one place.

The topics are eclectic and range from First "Principles of Web Accessibility" by Mike Davies from Yahoo! to "The best way to predict the future is to invent it" by Carlos Ulloa of Papervision3D.

Just some of the highlights:

Let All Things Be Connected by Rafi Haladjian, father of the Nabaztag bunny:

Since the end of the 70's we consider that computers (and mobile phones) are the only way to interact with information. Now the time has come to go to the next step.

Web Hooks: Real pipes for the web by Jeff Lindsay:

The web hooks pattern is a simple and pragmatic solution that will change the dynamics of the web as much as the adoption of web APIs. By complementing web APIs and RSS, web hooks will give us empowering infrastructure similar to Unix command pipelining, but on a grander scale. Pipes for the web have not yet been fully realized, but web hooks can change this. They also come with the added potential for allowing users to customize and extend web applications.

In this talk, Jeff Lindsay will describe the pattern in theory and by example, and explain the implications and importance of mass adoption.

Big Spaceship: Digital Creative Agency by Joshua Hirsch, Minister of Technology at Big Spaceship:

Get a glimpse behind the scenes and learn about the approach, philosophy, structure, process, techniques and culture of award winning creative agency Big Spaceship.

The Essential Elements of Great Web Applications by Robert Hoekman, Jr., author of designing the obvious and designing the moment:

Most great web applications have a few key things in common. But can you name them? Better yet—can you achieve them consistently in your own projects?

In this session, Robert Hoekman, Jr., author of Designing the Moment (New Riders) and the Amazon bestseller Designing the Obvious (New Riders), describes the qualities of great web-based software and how to achieve them. See why it’s important to build only what’s absolutely essential, apply instructive design, create error-proof interactions, surface commonly-used features, and more in this informative session that will change the way you work and enable your users to walk away from your software feeling productive, respected, and smart.

Education in the Internet Age by Lynda Weinman, author, teacher, and founder of Lynda.com:

We live in a game-changing age that's both disruptive and democratic, and requires that we challenge our past assumptions and play by new rules. It's clear to us industry insiders life as usual has forever been altered, but our formal educational systems trail behind and aren't keeping pace. What are the challenges to education in this age – where is the correct balance between real and virtual? Lynda Weinman, founder of lynda.com (one of the largest online education subscription sites in the world) discusses her views on this and related topics such as assessment, mentorship, authenticity, advertising, subscriber support, information, inspiration, and much more. Defining the role between the computer and the teacher, what is left best to technology and left best to live human interaction, is going define the future of education.

See the full list of sessions on the Singularity Web Conference web site.

Tickets for the Singularity Web Conference are just $99 until the end of August.

New sessions are being added every day, so check back for updates!

HOWTO Install PIL on OS X Leopard

OS X Leopard comes with Python 2.5.1 and lacks the PIL package for image manipulation. Google App Engine's local SDK uses PIL to emulate its image manipulation features.

The instructions on Google's installation page for PIL are incorrect.

To install PIL, follow these instructions by Matt Kangas instead. (Thanks, Matt!) :)

The only thing I'd add to that is that the instructions won't work unless you've got your .bash_profile file set up to read your .bashrc file.

So, make sure you have the following code in the .bash_profile file in your home folder (cd ~):

if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi

Downloadable documentation for Google App Engine

Finally! :) Go get 'em!

Back on Leopard

Plagued with random Bus Errors in Python on my Tiger install, and wanting to upgrade to Python 2.5.1 (as Python 2.5 is not supported by Google App Engine and the SDK has errors in it that won't be fixed), I decided to upgrade to Leopard again.

I had initially upgraded right after Leopard was released, at the end of last year, only to experience a myriad of problems like keyboard freezes (and here). I was so disenchanted that I wrote posts with titles like Leopard is tarnishing the reputation of OS X and Leopard: Great eye candy, pity the keyboard doesn’t always work before giving up and downgrading to Tiger.

This time around, I decided to backup my drive and do a clean install. I initially tried the backup with Carbon Copy Cloner (CCC) but it failed with errors. I then tried Super Duper, which worked out of the box. I did see that Super Duper had the option to repair permissions before backing up and I actually ran Disk Utility and repaired permissions manually before doing the Super Duper backup so it may be that CCC would have worked also had I'd tried it after repairing permissions.

I also downloaded the 10.5.4 combo update so that I could update to the latest release easily after upgrading.

With a sparse diskimage on my lovely new Lacie rugged drive in hand, I proceeded to install Leopard using the clean install option.

And I'm happy to report that everything went smashingly.

After completing the system install and the 10.5.4 upgrade, I ran a system upgrade that added a few more items (a security patch, the latest iTunes, etc.)

Instead of using migration assistant to pull stuff in, I decided to install only what I need at the moment and go from there. So, initially, I installed Zooom (which I can't live without; the new Zooom 2 rocks even harder than the earlier version for Tiger), Visor (which installed without issues, unlike my previous attempt a year ago), TextMate, iPython (sudo easy_install ipython followed by sudo easy_install -f http://ipython.scipy.org/dist/ readline), and several other apps. I used MobileMe to sync by contacts, etc., back to the new machine and it looks like I'm back up an running.

And, everything appears to be running smoothly. I don't have that weird feeling that something is just not quite right with the OS that I had a year ago. The four upgrades since must have hit the spot.

Leopard, I think we can kiss and make up now. Come 'ere you silly big cat! Awwww! :)

China blocking Google App Engine?

According to this thread on the Google App Engine forums, it appears that Google App Engine has become unreachable for some Chinese developers as of two days ago, with more developers reporting that their apps have become affected today.

Damien Hou, author of three Google App Engine apps stated that one of his apps has 360,000 users and that as of this morning his apps were unreachable.

This is a total disaster to me!!!! I can't believe this is happening! I feel
totally terrified how long this will last.

Damien goes on to theorize about the possible reasons behind such a move, if indeed the Chinese government is blocking parts of Google App Engine:

I don't even want to know why since I know under such cencorship you don't even know who's in charge of such stuff. They simply block anything without a blink of the eyes. I'd guess it's related to some local internet company's plan to enter the cloud computing market. Same thing with facebook's blocking recently.

Currently there are only a handful of reports on the thread but it will be interesting to watch how this develops.

I sincerely hope that this is merely a technical glitch and nothing more sinister. In the meanwhile, my thoughts are with the Chinese developers who are currently unable to reach their applications, regardless of the reason. I can't even begin to imagine how angry (and helpless) I would feel if this was to happen to me and to our application.

As of 2pm GMT on August 14th, there wasn't a response from Google on the thread. I can only assume that they are looking into it and will be updating the forum once they know what's going on.

Hang in there guys, I hope this gets resolved as soon as possible!

Going solo in the UK? Don’t miss Going Solo Leeds!

Going Solo Leeds Badge.Going Solo Leeds is a one day educational conference for freelancers and small businesses on September 12th in Leeds, UK.

This is just the conference I wish was around when I was starting my business six years ago with lots of wide-eyed optimism and nary a clue.

Check out the topics list:

  • setting rates
  • negotiating contracts
  • finding clients
  • balancing work and life
  • being productive without getting all stressed out

What a minute, what am I saying, after reading that list, Going Solo Leeds is the conference I wish my crazy schedule would allow me to attend six years on from setting up my own business.

I don't do client work anymore but balancing work and life and being productive without getting stressed out are two things I grapple with all the time. And, chances are, if you're a freelancer or thinking of becoming one, the topics above will have crossed your mind at least (if not kept you up at night).

("Going solo" by freelancing or setting up your own business can be hugely rewarding -- I personally couldn't do it any other way -- but it's not always a walk in the park.)

When I first arrived in London to set up my do-it-all-digital-agency (hint: focus is an important thing, I only learned later), I surrounded myself with every business book I could find. Truth is, what I really should have done was talk to people. And talk to other freelancers. That's why this conference is so cool. Six years later, I know I'd still benefit from attending (am I talking myself in to attending as I write this post, I wonder?)

Stephanie Booth, who is organizing the conference, is an avid professional blogger, entrepreneur, and someone I'm honored to call my friend. If you've ever met her in real life you'll find that she's beaming with energy and I know first hand from our conversations that she's been channelling every bit of that energy into Going Solo Leeds to make it even better than the hugely successful first Going Solo conference in Lausanne.

Stephanie's given me two special codes that you guys can use to register for the event.

The first is the mega-special-omg-its-awesome-wow-wow-wow code (hey, I'm just the messenger here, I don't make up these names, honest!) With that code, you'll get a whopping 30% off the price of a ticket.

The catch is that I only have two of those codes to give away. So the first two people to email me will get that. The other catch is that you must promise me that you're going to sign up (geeks honor and all that!) Fire me an email at aral {at} aralbalkan(.)com and I'll send you the code.

Once those two are gone, don't despair, as I have another code for you: Use the code singularity to register and you will get 10% off the price.

If you're freelancing or thinking about freelancing or setting up your own business, don't miss Going Solo Leeds.






Bad Behavior has blocked 0 access attempts in the last 7 days.