Conflict between Google Translate widget and Firefox Flashblock extension

The Google Translate widget allows webmasters to add on-demand translation of a website page. Very easy to configure and deploy.

The rendered widget appears in the browser as a simple select dropdown with options for all thelanguage supported by Google Translate. When the user selects his desired target language, the widget is supposed to contact the Google Translate mother ship, translate the text on the page, and then add an fixed iframe panel at the top of the browser viewport, followed by the translation of the page. The translated page even implements onmouseover handlers for text-based elements that display the original source text. Sweet.

It has worked great for me in the past. But I recently did a new deployment and I was unable to get the widget to work. When I (as the user) selected my target language, I got the following:

Error: The server could not complete your request. Try again later.

A bit more poking showed that it was only happening in Firefox. All my other browsers were ok. Eventually, I narrowed it down to a conflict with the Flashblock extension. Disabling the extension solved the problem.

Now, the tough choice is to run without the Flashblock or without the Google Translate. But at least I can deploy for the customer.

InfusionSoft API Support via Helpstream

Man, InfusionSoft sure is not making things easy.

One of my customers recently moved to InfusionSoft for their CRM platform. They have a mailing that gets sent every morning to a list of opt-in subscribers. Prior to their move to InfusionSoft, we maintained our own database of subscribers. Now, we need to pull the recipients from the InfusionSoft database.

Fortunately, Infusionsoft offers an API to their data. It’s not the best API (as noted in Jon Gales scathing blog post), but it appears adequate, at least for this task. It’s an XML-RPC API, so the calls don’t technically require a dedicated client library, but InfusionSoft has helpfully developed one.

But it was a bit of a muddle trying to determine the current version of their released library and where to actually download it.

So I sent them a support request. And here’s the tricky part. Logged-in to the InfusionSoft admin interface, I see the following:

infusionsoft1

I click a link for “Help > View My Support Cases” and get sent to the “Fusebox”, whatever that is, where I am still logged in:

infusionsoft2

I click on the “Question” link and enter my question, complete with all detail that would probably be required by the Customer Support rep: account name, email, even a complete email signature, containing email address, snail-mail address, tel, etc.

I get my answer back pretty quickly. The answer itself is quite satisfactory, complete with the code I need to perform my little task. My application development proceeds in a straightforward manner, the API works as advertised. Kind of a pain to get there, but, for the most part, all cool in the end.

Or so I thought.

A few days later, I get an email message from the InfusionSoft system, the content of which is a comment from some random stranger, noting that he has the same problem as I have.

WTF? How did this totally random guy get access to my support request?

A bit of poking around and the truth begins to emerge from the fog: A Question is not the same as a Case. The latter is a customer support ticket, a confidential communication to the Customer Service folks at InfusionSoft. In contrast, a Question is apparently nothing more than an initial post on a forum thread. As such, a Question is completely public, exposed to essentially anyone (well, to anyone in the InfusionSoft community). Email, name, tel, InfusionSoft account name. Man, it’s just sheer luck that I hadn’t included my freakin’ password in my post.

Yikes!

So, I am now chasing InfusionSoft to get my post removed, or at least edited. We’ll see how that goes.

In hindsight, I can see that there is a link to “Cases” back on the main Fusebox page - it’s there in the screenshot above - which is undoubtedly what I should have used. And had I been more familiar with the Fusebox, I might have realized its dual nature, as a Forum/Community/KnowledgeBase (the Questions) on the one hand, combined with a confidential Ticket/Case system on the other, all built on the Helpstream platform.

But at the time, I totally missed it. It just never occurred to me that the Customer Support pathway I was pursuing, especially from a logged-in interface, would lead to posting in a public forum.

Would you have seen it? Let me know in the comments.

Cheers. And, let’s be careful out there.

2009-12-28, 22:00 - Update: Got a reply from the community manager, informing me that he has removed my post, per my request. He even sent along the text of my request, in case I did not have a copy of it. Very prompt, very satisfactory. All cool.

Oracle to control MySQL? Very bad idea.

“We are using MySQL, help save it”

The blog post above from Monty Widenius, the creator of MySQL, starts out this way:

I, Michael “Monty” Widenius, the creator of MySQL, is asking you urgently to help save MySQL from Oracle’s clutches. Without your immediate help Oracle might get to own MySQL any day now. By writing to the European Commission (EC) you can support this cause and help secure the future development of the product MySQL as an Open Source project.

And continues to explain the fairly obvious: that Oracle benefits more from killing MySQL than it does from helping it.

Anyone who uses MySQL should read Monty’s post and take at least some of the actions he suggests.

“I am a forum spammer”

One of my customers gets this email today from his online forum system:

From: Idiot Russian Spammer [mailto:daniella.stolz@gmail.com]
Sent: Tuesday, October 27, 2009 12:08 AM
To: theforum@example.com
Subject: I am a forum spammer! Delete my account immediately!! Re: Welcome
to MyForum!

This email address was created solely to register automatically at
thousands of forums for the purposes of spamming forums like yours.
Remove my account and any other account registered with my email
address, and strongly consider strengthening your forum’s password
requirements.

Sincerely,

A Random Digilante Who Is Sick Of Forum Spammers

Gotta admire the guy’s honesty, eh?

It appears that the bot posts a registration request to the forum, then waits for a verify-email-address message sent from the forum. Then an auto-responder on the email address he provided (in this case, daniella.stolz@gmail.com) sends the message above.

The bot seems to be active and from China.

Despite the fact that the message chastises the forum for its weak security, it’s not as bad as it seems.

Sure, a CAPTCHA or some other token-based system or even a call to the Akismet service would probably have prevented this. But at least in my example, the bot had not yet verified its email address by visiting the verification link we provide, which is required before the user can post.

Still, it sounds like it would be a pretty modest modification to make to the bot - rather than a mere auto-responder: he simply pipes the incoming message to a processing script that looks for links to “click”. But that would not be available on a gmail address; he’d probably have to host someplace. But that location would then represent a decent hook on which forums could ban access.

So it seems to be a cute novelty, an annoyance. Still, the advice it gives is worthwhile. Never hurts to employ better spambot detection.

Firefox Error: ssl_error_bad_cert_domain

Working on a customer’s hosting account today and had to login at the hosting admin panel, something like the following:

https://www.mycustomer.com:2222/

Turns out that the host uses a shared SSL certificate, tied to the hosting company’s domain, not to the domains hosted by the hosting company. Whew, that’s a mouthful of pebbles. Got all that?

OK, so who cares?

Well, my version of Firefox (3.5.3) has default settings that require the domain on the certificate to match the domain name on the request. Firefox then spits out the error:

https://www.mycustomer.com:2222/ uses an invalid security certificate.

The certificate is only valid for <a id=”cert_domain_link” title=”thehostingcompany.com”>thehostingcompany.com</a>

ssl_error_bad_cert_domain

In this case, I was pretty certain that the domain I was visiting was the one I wanted, so I was prepared to push through the issue, provided Firefox would let me. The technique for this is to create an Exception to Firefox’s security policy.

In Firefox 3.5, do the following:

Tools -> Options -> Advanced -> Encryption -> View Certificates -> Servers -> Add exception.

Then enter the url you were trying to accesss. In my example above it was “https://www.mycustomer.com:2222/”

The new page should now be accessible.

Hope it helps!

Picking Dates

On one of my ongoing web projects, we have forms that require users to specify a date. The input field is a single text field with an expected format (as opposed to a trio of selectors corresponding to day, month, and year). On form submit, we perform server-side validation. all straightforward stuff.

In the spirit of progressive enhancement - or graceful degradation, depending upon whether you see your glasses as half-full or half-empty - we add some client-side enhancements.

The first bit of client-side enhancement is just validation on the expected format. Nothing special here. The second bit is a date picker with which to easily select dates.

Better, stronger, faster

In the first round of development, we used a popup window containing a server-generated HTML page, as is done in phpMyAdmin. It worked fine for a while but there were several downsides to our particular implementation:

  • As a popup, it was subject to possible blocking
  • As server-generated content, it was a bit slow, especially on our internet connections here in Thailand
  • The javascript was inline, not unobtrusive. Not a capital offense, but one that still irked me.

Also, it was more than a bit old-fashioned. I mean, it’s like wearing your grandpa’s sweater: it may keep you warm, but it sure as heck ain’t gonna impress Mary Lou the cheerleader down at the soda shop.

With all the new javascript libraries, especially jQuery, it seemed high time to move into - or at least closer to - the modern era. So we deployed the Datepicker plugin from the jQuery UI package, enabled a little animation effect, and it’s pretty nice. Fast, clean, unobtrusive. Steve Austin would be proud.

The best part of it is ease of use: For any fields to which we want to bind a datepicker, we simply give that field a particular CSS class. So we could have HTML markup of the form:

<input type="text" name="mydate" id="mydate" class="dp">

and then we bind a datepicker to it with javascript code as follows:

(function($){
    $(document).ready(function(){
        $('.dp').datepicker();
    });
})(jQuery);

Very sweet.

Companions: Checking-in and Checking-out together

But like all things web-related, that’s not the end of the story. Turns out that there are places on the site where two date input fields are related, paired as companions, typically in a check-in / check-out scenario, as in a hotel room or for a flight.

Certainly it is possible for these fields and their datepickers to function in a fully independent manner. If the user tries to check-put before he checks in, both the client-side and the server-side validation kick in to ensure data integrity.

But it is somewhat sub-optimal to even allow the user to select such a situation in the first place.

Even better, don’t you love it when you go to a site and after you select the check-in date, the check-out date automatically sets itself to the day after check-in?

Or, on the other side, don’t you hate when: you are booking a room or a flight way in the future, like next year; you select the first date, perhaps by navigating through a sequence of months, and then are forced to do the same thing on the second datepicker?

[Actually, it's probably the case that the user shouldn't even have to do this on the first datepicker, that in addition to prev-month and next-month navigation, the datepicker control should have its own selectors that allow the user to jump to a desired year and month. Good, full-featured, datepickers actually have this as well.]

The selection of the first date (the preceder) inherently puts a lower bound on the acceptable values for the second date (the succeeder). So why not bake that into the operation of the form?

And, this thinking works in the other direction, too. Suppose I chance the check-out date to sometime before the current check-in date? It seems reasonable that I should change the check-in date to be something before the check-out date, and the most reasonable choice is the day before check-out. If the user wants to push forward further than that, then he his certainly free to do so, but at least we put him in a reasonable ballpark.

Of course, all date changes do not warrant changing the companion. If I already have a reasonable check-in that precedes a check-out, and then I push back my check-out to a later date, there is certainly no need to change my check-in. Symmetrically, if I move my check-in forward to an earlier date, I certainly have no basis for concluding that the check-out should change.

So what I need is a way to pair these two input fields to each other so that a change in one can automatically create a change in the other, but only when it is appropriate to do so. And I’d like to handle it all with a single set of DRY handlers. And I’d like it to be valid HTML markup. And I’d like it to be completely unobtrusive.

Es posible? Si!

My Companion Approach

The jQuery Datepicker UI plugin has the option to set an onSelect callback option. That is, when a date is actually selected by the user in the datepicker, this function will be executed by the plugin. This is the key to the handling.

But we need some way to identify pairs, and especially which one is the preceder and which one is the succeeder.

I created a class naming scheme as follows.

Consider paired fields representing check-in and check-out:

<input type="text" name="mycheckin" id="mycheckin">
<input type="text" name="mycheckout" id="mycheckout">

As before, we want them to be bound to their own datepickers, so we add the class “dp” yielding:

<input type="text" name="mycheckin" id="mycheckin" class="dp">
<input type="text" name="mycheckout" id="mycheckout" class="dp">

Now, we want to specify that mycheckin is a preceder, bound to the succeeder mycheckout. And vice versa. So, I add classes as follows:

<input type="text" name="mycheckin" id="mycheckin" class="dp dp_1_mycheckout">
<input type="text" name="mycheckout" id="mycheckout" class="dp dp_2_mycheckin">

The 1 and the 2 represent flags to help determine which is a preceder and which is a succeeder.

The part trailing the numeric preceder/succeeder flags is the object id of the companion.

Then I define a bunch of helper functions to:

  • parse the class names to extract this information
  • detect when a change in one actually warrants a change in the other
  • add/subtract a day from a user selected date
  • output dates in the desired format

and then use all these helpers in the single DRY datepicker onSelect handler.

Aaaah, sweet success.

If I get a chance - or an overwhelming deluge of requests - I’ll post some sample code in more detail.

HTML email templates from CampaignMonitor: Fail?

Clients love HTML email.

Done correctly, it looks slick as all get-out; it prompts users to action; it drives traffic for a special promotion; presents an exciting, professional image; lifts you aloft and floats you to heaven. All with higher response/action rates than plain-text email messages.

However, as every web developer knows, doing it well is a nightmare. Design/layout is the easy part; the sticky parts are numerous. Different email clients render HTML email with, shall we say, somewhat uneven support for web standards that are increasingly respected in modern browsers. Further, many email clients come configured with default settings to that disable images, adding another factor to consider. Finally - well, not finally, but the list of issues feels effectively endless - HTML email is often used by spammers, so there are more complicated considerations associated to ensuring that your messages do not get incorrectly tagged as spam.

There is a growing body of best-practices that has slowly developed for HTML email. These practices are not “best” in the sense that they represent elegant, flexible coding philosophies (like DRY, OO, for example) or minimal load times or optimized development practices. Rather, these ideas are considered best-practices, IMHO, merely in the sense that they “work”: they offer the best chance that your message will be received by the intended recipient and be reasonably well-rendered when he views it.

These best-practices include foregoing all the techniques we learned for creating semantic markup that cleanly separates content from presentation using CSS; instead, we are told to use tables for layout. We should no longer refer to styles in an external style sheet since most email clients - especially web-based ones like Hotmail, Yahoo, and Gmail - will strip them out; rather, we should use inline styling, repeating style information on nearly every element that needs it, inducing bloat and making modifications a tedious search-and-replace activity rather than a simple change in a single style declaration.

Other best-practice resources often conclude by pointing to Campaign Monitor or MailChimp and advising readers to download their free templates and use them as directly or as a starting point for editing or even as a guide to these best-practices. Both sites claim that their templates have been tested to render fine in all major clients.

Now, Campaign Monitor is great. These guys are founders of the Email Standards Project. I totally support the idea that someone should be pushing email clients towards better support of web standards, especially CSS support. The first step in that direction is measuring and evaluating the current support. And their chart of CSS support in major mail clients is a tremendous resource.

But the first template I downloaded from CampaignMonitor violates a bunch of these best practices right off the bat and fails to render correctly in Gmail. The template has nearly all of its styling inside a <style> tag inside the page’s <head> section. CampaignMonitor’s own CSS support guide referenced above notes that such an approach will not work with Gmail, yet their template includes it and claims to render fine.

Gotta tell ya, I’m a bit disappointed.

Refactoring Video Renderers with Design Patterns and Autoloaders

On the face of it, it’s a very simple request from a customer.

We have a page listing our YouTube-hosted videos. Each video has a thumb and some descriptive information, all linked to a page that renders the descriptive info and the YouTube embed codes so the visitor can view the video in our site wrap. Customer wants to add a new video to the list.

Simple. Should be nothing. Piece of cake.

But it turns out that existing rendering/embedding code was set up to expect videos with only a YouTube embedding. The new video is hosted at another site which does their embeds in slightly different way. And there is every reason to think that the next video that comes up will be different still.

Further, the supporting code for summary and detail renderings (summary rendering: display a thumb, some video metadata, and links to play, download, etc; detail rendering: display the actual embed from the video provider, some video metadata, links to download, etc) was not as well structured as I would have liked. Although there was a summary rendering class and a detail rendering class and both descended from a common base class to share some common functionality, the commonality was all based on the YouTube embedding. Also, the caller instantiated the renderers directly using the new operator, rather than using a factory design pattern.

So, what it seems was needed is something that puts all the commonality (title, speaker, place, date, thumbnail, general layout of the summary pages and the detail page) in a single place; allows enough flexibility to deal with embeddings from various sources; and uses established design patterns for easy use and maintenance.

So, I refactored all our code into a more modern approach that uses a factory pattern to create renderers that are capable of dealing with the type of video embed required. Start with a parent class for renderers Customer_Video_Renderer containing much of the functionality that would be common across various renderers and video embedding types. In particular, it defines the primary interface for using the renderers:


class Customer_Video_Renderer
{

	public function renderSummary()
	{
		// to implement
	}

	public function renderDetail()
	{
		// to implement
	}

	// other supporting code common to renderers
}

A generalized renderer for an embedded video now uses dependency injection as follows:


class Customer_Video_Renderer_Embed extends Customer_Video_Renderer
{
	protected $_embedClassName;

	public function __construct($video, $embedClassName = '')
	{
		parent::__construct($video);
		$this->_embedClassName = $embedClassName;
	}
}

The variable $embedClassName variable contains the name of a class that must support the static function getEmbedCode($video). So for example:


class Customer_Video_Renderer_Embed_YouTube
{
	public static function getEmbedCode($video)
	{

		$w = $video['speech_video_width'];
		$h = $video['speech_video_height'];
		$u = self::_getEmbedUrl($video);

		return <<< EOT

		<object width="$w" height="$h">
			<param name="movie" value="$u"></param>
			<param name="allowFullScreen" value="true"></param>
			<param name="allowscriptaccess" value="always"></param>
			<embed
				src="$u"
				type="application/x-shockwave-flash"
				allowscriptaccess="always"
				allowfullscreen="true"
				width="$w"
				height="$h">
			</embed>
		</object>
EOT;

	}

	protected static function _getEmbedUrl($video)
	{
		return 'http://www.youtube.com/v/'.$video['speech_embed_code'].'&hl=en&fs=1';
	}
}

Then we use a factory to create renderers:


class Customer_Video_Renderer_Factory
{

	public function create(array $video)
	{

		if (!isset($video['vType'])){
			throw new Customer_Video_Renderer_Exception('Video does not specify video type');
		}

		switch ($video['vType']) {
		    case 'youtube':
		        $renderer = new Customer_Video_Renderer_Embed($video, 'Customer_Video_Renderer_Embed_YouTube');
		        break;
		    case 'moneywatch':
		        $renderer = new Customer_Video_Renderer_Embed($video, 'Customer_Video_Renderer_Embed_MoneyWatch');
		        break;
		    case 'inline':
		        $renderer = new Customer_Video_Renderer_Embed($video, 'Customer_Video_Renderer_Embed_Inline');
		        break;
		    default:
				throw new Customer_Video_Renderer_Exception('Video specifies unsupported video type: '.$video['vType']);
		        break;
		}

		return $renderer;
	}
}

So the caller simply renders a video as follows:


// given a $video
echo Customer_Video_Renderer_Factory::create($video)->renderDetail();

And I am - finally! - using a standard __autoload function so all those irritating requires statements are no longer, well, required:


function __autoload($className){
    include_once str_replace('_', '/', $className) . '.php';
}

Can’t believe how smoothly it all went, how beautiful the code is now structured (though I see that there could be different ways of approaching it), and how easy it will be to add new video providers. Might even add unit-tests if I can find the time.

So pleased.

Update 2009-11-07: I realize now that the use of static methods was kind of a n00bish idea, that considerations of unit testing and loose-coupling should have dictated a more compositional approach, perhaps invoking one of the standard design patterns that applies. All I can say is that I’m moving that way, slowly but surely. Onward!

Zend Framework - Here I Come

Time to elevate my game.

After years of developing and tuning my own PHP-based web development framework which I have used on countless projects, I have decided to move into one of the more established PHP-based web frameworks.

My own framework is a loose collection of classes and methodologies that have worked pretty well so far. I can usually figure out how to do anything that has come up. Although it is a huge step up from so much of the the script-kiddie crap that is still fairly common - among even some successful commercial houses here in Phuket - I must confess that it never felt quite tight enough for me. It never lent itself to the kind of controlled development process I would ultimately like to be doing: source control, automated unit-testing, automated builds, and automated deployments.

There is no shortage of discussion out there about web frameworks: which ones are essentially CMS’s or mere libraries rather than full frameworks; which ones are tightly/loosely coupled; which ones are sufficiently true to established design patterns, to object-oriented principles, to MVC principles, etc; which ones are performance dogs, etc. I’ve read through much of it.

Upshot: I’m sticking with PHP, going with Zend Framework.

I’ve got nothing against the other PHP frameworks. CodeIgniter seems very approachable and has a decent community. CakePHP seems to have a lot of advocates and supportive community. Kohana, too, seems nice. Of course, there are many others.

And if I were really going to go wild, I would leap in Ruby on Rails about which I have never heard a single bad thing. But a leap into a new framework is enough without having to bite off the syntax of another language to boot.

Perhaps some other time I’ll get into all the reasons and do a comparative analysis, though it is just as likely that it will never happen since there are already tons of such resources out there and doing my own comparative analysis at a level that would be satisfactory to me would require becoming expert at all the others.

First step is to use a few of the Zend Framework classes here and there in a few projects, availing myself of the “loosely-coupled, use-at-will” nature of the library. Mostly to familiarize myself with some of the design patterns and to learn what supportive functionality is available outside the context of the full framework stack.

Eventually, I will commit to using the full MVC stack on a green-field project, either a brand new site or a redesign of an existing site. I already have one in mind. Both excited and terrified at the same time.

Go, go, go, …

Facebook connecting the dots?

An NY Times Op-Ed piece by Eduardo Porter about web privacy finishes with the following:

But with more and more information about people’s credit cards, browsing histories and identities sloshing around online, I wonder whether this will do. A few months ago, I nervously created my first Facebook page with the minimum necessary information to view pictures posted by old friends.

I returned to the page a few days later to discover that somehow it had found out both the name of my college and my graduation class, displaying them under my name. I have not returned since. In the back of my mind, I fear a 28-year-old hacker and a couple of Russians have gathered two more facts about me that I would rather they didn’t have. And it’s way too late to take my life offline.

Really? Facebook is connecting the dots this way?

Hard to make a true determination of what he means. His Facebook profile is obviously accessible to friends only. It could be that Facebook connected the dots and presented them to him for confirmation. That would certainly be less insidious than making the connections and imposing them upon his account. For example, he could easily wish to keep his Facebook profile clear of various episodes of his past life, like college, previous employers, etc.

But it surely shows that every little bit of ourselves that we leak out into the cyberspace represents another potential hook that a data miner could use to link vast data repositories.

One has to wonder if there is really any privacy left at all. We get by on obscurity, the (blind!) hope that no one will look too closely. But I wonder how most of us, with modest connections to to electronic world - an email address, some credit cards, a few online purchases, perhaps even a Facebook account - would fare if someone with access to those data mines turned their attention on them. In fact, it’s probably the case that the data miners do this themselves via automated searches on their data stores.

As Mr. Porter said, way too late to pull our lives offline.