A Better IE 5.5 and 6 PNG Fix

I should have posted this here prior to now, but as you can probably tell … .. I don’t post to this blog very often. During the implementation of the new flixn.com site we decided to use PNG alpha transparency to some extent. During the course of implementation existing IE5.5/6 PNG hacks were deemed to be wholly inadequate for our needs. So, I took some time to reimplement the core PNG hack as an .htc (IE CSS Behavior) and layer in some additional hacks on top to support css repeat and positioning.

Get the code: [HERE]

Original post follows:

So there I was in the wake of an unexpected and tragic steamroller accident involving the entirety of the production design staff… “Wait, you mean I have to cut and implement all the new Flixn.com designs? Me? Well, ok, this shouldn’t be too hard. I’ll just slice each element out with alpha transparency preserved in PNG’s, then layer them using CSS just like they are in Photoshop.”

“Wait, wait. What do you mean that won’t work?”

Back in reality, the lack of true support for PNG alpha transparency in Internet Explorer 5.5 and 6 has been nipping at us and many others for at least 4 or 5 years now. Given that browsers that are fully supporting are in the 70%+ market share range, we decided that it was time to come up with a proper “fix” that would allow our alpha transparent PNG’s to degrade gracefully on now effectively “legacy” versions of IE.

Many web developers out there will be familiar with the prevalent “.htc” file behavior fix targeted at this problem. There are certainly other ways to approach a solution, but we tend to like this one for a number of reasons, perhaps the biggest being: It will invalidate otherwise valid CSS. This may seem a bit crazy, but a fix (hack) is a fix (hack) and as a boundary pushing web developer, one probably shouldn’t be left to forget that.

The IE behavior/.htc fix that has been around for a number of years has some pretty staggering limitations when used on anything resembling a complex layout – so staggering, in fact, that it’s easier to just say what it gets right: images in img tags, and non-repeating (non-tiled) background images aligned to the top left of their container. Perhaps this isn’t a problem if you design the page with this in mind, but it certainly won’t suffice in making a crazy-alpha-png’d-layout degrade gracefully on IE 5.5/6.

For our from-scratch implementation, we started with a page cut and structured as we desired and validated the presentation in IE7, Firefox2+ and Safari 3+, then implemented our own behavior/htc hack to correct all the regressions that we could find in earlier versions of IE. What we ended up with was something that was capable of not only preserving the status-quo in IE PNG hacks. We also bring to the table full support for the CSS properties background-position (for labeled, pixel and percentage offsets) and background-repeat (for values of repeat, no-repeat, repeat-x and repeat-y). The only thing we don’t do is support the use of these two properties together. We’ll leave that for someone else… or maybe a future weekend hacking session.

The Barack Obama Call Center


I’m an Obama supporter, but I’m also that guy who wants to put a knife in someone’s eye when he receives an unsolicited political call. Especially, ESPECIALLY, when it is an unsolicited unprofessional political call. So, now…. … I’m really not sure what to say about this. Introducing, the Barack Obama call center! They are inviting me and you and any other would-be supporter to go ahead and start calling to voice our support. Who would you be calling? Your friends? Oh no, they will supply you with scripts to read to the complete strangers whose names and numbers are being provided! … Great …

PowerDNS / PostgreSQL & Web Interfaces 2

After a bit of eat and drink, as well as a half hour of zOMG why is this not werking!?!?! (iptables), Supermaster/Superslave is operating famously. It seems to “just work”. No complaints thus far, which is, well… highly unusual for me to put it lightly.


Feb 03 05:35:55 Received NOTIFY for flixn.com from 72.232.239.130 for which we are not authoritative
Feb 03 05:35:55 Created new slave zone 'flixn.com' from supermaster 72.232.239.130, queued axfr
Feb 03 05:35:55 gpgsql Connection succesful
Feb 03 05:35:55 No serial for 'flixn.com' found - zone is missing?
Feb 03 05:35:55 AXFR started for 'flixn.com', transaction started
Feb 03 05:35:55 AXFR done for 'flixn.com', zone committed

PowerDNS / PostgreSQL & Web Interfaces

http://evilcode.net/sjg/infernal/PowerDNS/SCHEMA/

I have been looking at PowerDNS for a while now, and after regular confirmation that it is in fact performing extremely admirably over at DreamHost I decided that it was time to deploy it.

While PowerDNS is the least braindead DNS server I have ever come across, there were a couple of things that I was not 100% happy with, at least in terms of coupling it to a web frontend.

  • SOA records are stored space-delimited. This would hardly be a problem except that our serial is stored here. In its defense, PowerDNS has an alternate method of handling serials that is probably better in most circumstances. Hardly, but we would still have to break it apart and put it back together again to edit the minimum (default in practice) TTL, etc.
  • Record types are stored textually. Even when implemented as an enumerated value this still violates DRY, as you must re-state these values in your frontend code.
  • Everything must be represented fully qualified. This = FAIL from a normalization perspective.

Here I have come up with a somewhat optimal schema from the point of view of my web interface, and I have tied it to PowerDNS’s preferred table structure via domain logic. This could have been handled in other ways of course, but I tend to like this one for a number of reasons.

  • First, the alternative is to add custom queries to the PowerDNS configuration file to make it understand whatever schema we might have in place, PowerDNS actually makes this very easy.
  • Another alternative would be to use dynamic (normal) views.

On to the benefits, some being quite minor.

  • Querying against serialized views will have performance benefits versus the above two options, this of course has to be weighed against the cost of maintaining the views.
  • As mentioned, PowerDNS has two methods of handling serials, either in the SOA record, which we are keeping up to date with our domain logic. Alternatively PowerDNS will scan each record for you to find the most recently updated (if you maintain change_date). The former should logically be more performant, so we have implemented that option. This could have been handled either way in the domain logic, but most importantly we aren’t relying on our web frontend to keep our serials up to date.
  • Most importantly, namely for debuggability, data on master’s and slave’s “looks the same”.

To get you rolling your PowerDNS configuration file need not be any more complicated than this:


launch=gpgsql
gpgsql-host=hostname
gpgsql-user=powerdns
gpgsql-password=password
gpgsql-dbname=pdnstest
daemon=yes

I haven’t tried slaving yet, but I suspect it will work without a hitch. Will update here when I do and when this rolls out.

Senator Tim Johnson

I had neglected to shower that day. What was the point? I wasn’t looking to impress anyone, so far as I knew we were to spend yet another day in D.C. perusing the vastness of the Smithsonian. Who in their right mind wants to waste time on a shower when their locomotive of a fourteen year old mind thinks it may be spending another dozen hours in the Air and Space Museum?

Visiting the halls of the capitol building and congressional offices was awe inspiring. So much so that said mind, once so focused on all things scientific, was derailed into a spiral of tumult over the state of affairs within our nation and without. Ten years and seven seasons of The West Wing later…

While the scope of the most pressing issues facing our nation is often daunting, events of the last year seem to have forced a new clarity of perception. Yet without this picture following from one locale to the next. Occasionally surfacing as some odd component or gizmo was fished from some box or another, politics would have in all likelihood been less than an afterthought throughout my life. Full well knowing that this very phrase has likely been emblazoned on hundreds or thousands of other pictures signed by this very same man, it has somehow emboldened me every time I have come across it. It has forced me to choke back the bile I taste when presented with a viewpoint on health care, education or any other swelteringly hot topic when significantly divergent from my own point of view.

Whether our chosen representatives realize or not, it is the little things they do that really change lives, not just the votes they cast. Thank you Tim, from the bottom of my heart, for even though we have never met, you have helped to expand my horizons.

ActionScript

This week I decided to toy with ActionScript/Flash a bit (for the first time, really). I’m using the FlashDevelop IDE, so it’s all free goodness, no shelling out $500 to Adobe. Anyway, I wrote an MP3 player that is devoid of any sort of flash user interface, completely controllable through JavaScript. It’s a mere 162 lines of ActionScript and weighs in at 2071 bytes as an swf. It supports a wide range of operations, load, play, pause, stop, setvolume, getvolume, ispaused, getpauseoffset, getcurrentfile, getduration, getposition, getbytesloaded, getbytestotal, getid3, as well as a number of asynchronous JavaScript callbacks (notifications) on various events, loadcomplete, playcomplete and id3found. You can see it in action with possibly the simplest UI possible here: http://evilcode.net/sjg/player/.

The real question that I am trying to answer for myself is, does eliminating the flash user interface somehow make it [flash] more palatable?

JavaScript/File-based HTTP request logging

http://httpd.apache.org/docs/2.0/mod/mod_log_config.html

I just had the thought that it should be pretty feasible (if not trivial) to tie JavaScript-based request logging (like Mint and Analytics) to traditional file-based request logging using cookies and/or headers and CustomLog in Apache or similar in other httpd’s.

The question being… Is this somehow useful? I think it potentially could be, I’m just not 100% on how as yet.

Introspecting PostgreSQL and MySQL, starting out

Starting at the top, PostgreSQL and MySQL have wildly different concepts of what constitutes a schemata. In MySQL information_schema is a database that can be used directly or via cross-database queries. Whereas in PostgreSQL, you cannot perform cross-database queries because you connect to a single database. Here, the information_schema is contained within what PostgreSQL calls a schema, or a seperate namespace within a database.


Common Fields (schemata):
catalog_name
PostgreSQL: Always the name of the parent database
MySQL: Always NULL
schema_name
PostgreSQL: Name of the schema
MySQL: Name of a database
default_character_set_name
PostgreSQL: Feature not available
MySQL: Default character set (utf8, latin1, etc.)

PostgreSQL:
schema_owner
User (role) that owns the schema

MySQL:
default_collation_name
Default character set collation (utf8_general_ci ...)

So, what we get out of all this is that for PostgreSQL, we connect to a database and schemata tells us what schema’s exist. In the case of MySQL, it tells us what databases exist. Of course application dependant, but in many cases you can treat these as the same thing.

Once we know all about our databases, or whether we wanted to know about them at all, the next thing we will probably want to dig into are tables.


Common Fields (tables):
table_catalog
PostgreSQL: Always the name of the parent database
MySQL: Always NULL
table_schema
PostgreSQL: Name of the schema that contains the table
MySQL: Name of the database
table_name
Name of the table
table_type
'BASE TABLE' for a regular persistent table
'VIEW' for a view
PostgreSQL: 'LOCAL TEMPORARY' for a temporary table
MySQL: 'TEMPORARY' for a temporary table

MySQL:
table_comment
Comment

To set comments on PostgreSQL tables:
COMMENT ON TABLE table_name IS 'This is a table comment';
To retrieve comments we must dig into the system information schema:
SELECT obj_description(
(SELECT c.oid FROM pg_catalog.pg_class c
WHERE c.relname='table_name'), 'pg_class')
AS comment;

Next, we’ll want to dig into information about the columns of those tables


Common Fields (tables):
table_catalog
PostgreSQL: Always the name of the parent database
MySQL: Always NULL
table_schema
PostgreSQL: Name of the schema that contains the table
MySQL: Name of the database
table_name
Name of the table
column_name
Name of the column
ordinal_position
Position of the column within the table, the ordering of the columns
column_default
Default (expression) for the column
is_nullable
Whether or not the column can be null, 'YES' or 'NO'
data_type
Name of the built-in type
PostgreSQL:
'ARRAY' - see the element_types view
'USER-DEFINED' - identified in udt_name+
If domain-based, refers to the underlying
type and the domain is identified in domain_name+
character_maximum_length
Maximum length of character data if defined, otherwise NULL
character_set_name+collation_name
MySQL: NULL if not defined

PostgreSQL:
udt_schema
Schema the user-defined type is defined in
udt_name
Name of the user-defined type

domain_schema
Schema the domain is defined in
domain_name
Name of the domain

MySQL:
column_type
More specific column type than data_type (varchar(255)
column_key
'PRI' or blank ?
column_comment
Comment

To set comments on PostgreSQL columns:
COMMENT ON COLUMN table_name.column_name IS 'This is a column comment';
To retrieve comments we must dig into the system information schema:
SELECT col_description(
(SELECT c.oid FROM pg_catalog.pg_class c
WHERE c.relname='table_name'),
(SELECT a.attnum
FROM pg_catalog.pg_class c,
pg_catalog.pg_attribute a
WHERE a.attrelid=c.oid
AND c.relname='table_name'
AND a.attname='column_name'));

PHP/AJAX file upload with progress bar, part 3

Part 1, Part 2

I pulled this back out over the weekend and did a little work on it. The backend code is now totally functional, however I would consider it to be alpha quality. It just needs to be wrapped in a UI now, check it out and let me know what you think. Try the demo with JavaScript enabled first, once the upload completes you will see the result is a mash-up that looks like PHP’s $_REQUEST/$_FILES. Hit the resulting url again within 60 seconds and you will see the status side of things (Using a GET request, you don’t want to re-post the form data). Total bytes, bytes received, percent complete. Try it again with JavaScript disabled and behold the standard php handler.

Source
Demo