hasenj blog

Doing away with captcha

Posted in webdev by hasenj on 19/09/2009

I don’t include any form of captcha in anything I develop, mainly because I never took the time to invest into figuring out how to do it. But also because I really *hate* captchas. Also, my audience is largely composed of non-geeks and a captcha would be too confusing. So for me, putting captcha is a no-no.

So what do I do? How do I get away with it? Some people have described methods that revolve around a combination of css/javascript:
Honeypot Captha, Javascript Captcha

The way I do it, is simpler in a sense; it doesn’t even have a concept of captcha. I simply do everything in javascript. There’s no submit button, so there’s nothing for bots to do anyway.

I use a regular button with an onclick event that’s attached to a javascript function.


function submit_form()
{
    jQuery.ajax({
            "type": "POST", // or GET, or even PUT or DELETE
            "url": 'action_url', // The url you wish to send the data to, the url you'd put in the "action" attribute on the form tag
            "data": jQuery("form#the-form").serialize(), // The data you'll send. You need to get the form somehow. Easiest way is to give it an id.
            "dataType": "json", // Only put this if the server sends the response in json format
            "success": function(data, textStatus) // server responded with http status 200
            { 
                // do success stuff, this is the happy case
            },
            "error": function(req, textStatus, errorThrown) // maybe HTTP 404 or HTTP 500
            {
                // something went wrong. let the user know, or something
            },
            "complete": function(req, textStatus) // This one always gets called anyway
            {
                // cleanup after yourself
            }  // careful: if you put a comma here, IE6 will fail
        });
}

At first glance this might not seem so simple, but if you’re doing everything as ajax, then this is just a natural part of it.

You can add action="javascript:return false;" inside the `form` tag, just in case.

The reason why spambots can’t get through is simple: they don’t know what to do. There’s no url in the “action” attribute on the form tag. There’s no submit button. Most importantly, most spambots don’t have javascript.

While it’s possible that some spambots will have javascript, they still won’t know what to do since there’s no submit button. They might try to guess what button to click, or maybe they’ll just click all of them, but that would still be easy to circumvent. You can add a hidden button (that regular users won’t see) that disabled the real send button, so if a spambot tries to click every button it finds, it would likely hit the wrong button and then never be able to send the form.

Though unfortunately, if someone is targeting your site specifically, this kind of thing won’t work.

Best way to get round edges in IE

Posted in webdev by hasenj on 12/09/2009

I’m sure we’ve all struggled with it too much with this issue. IE just doesn’t support any css property to render round edges.

The best solution, ultimate best solution, it to just give up and let IE users see sharp edges. Of course, add the border-radius property to the css style sheet, maybe a future version of IE will support that property.

But yeah, save yourself and your audience all the trouble.

Any method to support round corners in IE6 will either result in a mentanence nightmare or a sub-optimal user experience. You’ll either create too much boilerplate code (nested divs, extra css, tables, etc) and/or the user will have to download extra data (javascript, background image, etc). You’ll possibly slow down the page too, if you have a script that injects the boilerplate code after the page loads.

Possibly related link:
http://giveupandusetables.com/

## EDIT

Actually, as it turned out, This is the best way to round cross-browser round corners: http://www.malsup.com/jquery/corner/

IE6 doesn’t run onclick events in “option” tags

Posted in webdev by hasenj on 05/09/2009

You have an ajax drop-down menu, something like this:

 
  <select>
    <option onclick="do_fancy_stuff();">Fancy Stuff</option>
    <option onclick="do_cool_stuff();">Cool Stuff</option>
    <option onclick="remove_ugliness();">Remove Ugliness</option>
  </select>

Because you’re a sane human being, you don’t use IE6 as your browser, you only have it running inside a virtual machine called “winxp”, or something like that. When you want to test your page on IE6 you type “vboxmanage startvm winxp” on the command line.

Anyway, so you check your site on IE6 and you discover that selecting an item from the menu doesn’t do anything! You wonder why and you google it, and (you get here? naa) in my case I came across this: http://www.ozzu.com/website-design-forum/option-onclick-internet-explorer-t55560.html

It provides a good explanation but I don’t think the solution is the best out there. It pretty much requires re-writing everything and re-arranging your events so that what function to call depends on the index of the option.

Oh wait, did I mention what the problem is? IE6 doesn’t care if the option tag has an onclick event. The only way to make something happen when you select something from the list is to put an onchange event on the *select* tag. and you’ll have to use `this.selectedIndex`, or `this[this.selectedIndex]` to get the option that was selected. The suggested solution over there is to use a function that gets the index passed to it as an integer and then decide what to do based on the value of that integer. But that’s not really a good idea IMHO.

For me, the solution is quite simple:


  <select onchange="this[this.selectedIndex].onclick()"> {# gotta hate IE6 #}

This will force IE6 to activate the onclick event handler on the options (assuming they all have an onclick handler). The problem of course is that in Firefox this will run onclick twice. So, we have to put this inside some sort of a conditional structure that checks if we’re in IE6. My solution is basically this:


<script type="text/javascript">IE6 = false;</script>
<!--[if IE 6]> <script type="text/javascript"> IE6 = true; </script> <![endif]-->
<select onchange="if(IE6) this[this.selectedIndex].onclick()"> {# gotta hate IE6 .. even more now #}
    <option onclick="do_fancy_stuff();">Fancy Stuff</option>
    <option onclick="do_cool_stuff();">Cool Stuff</option>
    <option onclick="remove_ugliness();">Remove Ugliness</option>
 </select>

Of course, it’s best to put this snippet

<script type="text/javascript">IE6 = false;</script>
<!--[if IE 6]> <script type="text/javascript"> IE6 = true; </script> <![endif]-->

somewhere (in your setup) so that it’s included in every single page.

UPDATE:

Actually, it turns out this applies to all version of IE, not just IE6.

The problem with Django

Posted in webdev by hasenj on 11/04/2009

Frameworks speed your development time at first, but then you often hit a wall. The framework doesn’t do what you want and you have to dig into its internals to figure out how to do what you want, which is often more difficult than writing your own framework from the ground up. — Cal Henderson, Flickr’s Engineering Manager, at a django conference

In many ways Django reminds me a bit of unpacking cool stuff. You download it and are instantly blown away how cool it is. Database just works, templating is awesome, URL routing gives you these incredible neat looking URLs and much more. It’s so cool that many are trying to suddenly do everything with it. And that’s kinda where the problem lays. You are forcing Django to do things it’s not designed for. — Armin Ronacher, in a blog post

I’ve been using Django for about, almost two years, and I came to the same conclusion. Django is amazingly awesome at first, but not so awesome in the long run.

The reason Django is so amazing at first is that it relieves you from having to do the stupid repetitive tasks involved in writing a typical php app: writing an admin interface, writing a class that maps to your db table, and doing all the mappings manually. I’ve had little experience writing a mini-blog like website using php, and it was an exciting experience to build my first web-app ever (it was a school project). However, even though it was exciting, I also didn’t like the thought of having to repeat all that redundant work all the time, so in that regard finding Django was a big relief.

However this awesomeness doesn’t last so long. Soon enough the requirement get complicated, and Django doesn’t wanna do what you want it to do anymore. You’re forced to either wrestle with it, or implement the requirments completely outside django, which kinda defeats the point.

It’s a Framework!

See, one of Django’s problems is that it tries to do everything for you, forcing you in the meantime to adapt to its way of doing things, instead of it adapting itself to you.

Django has an (awesome, btw) automatically generated admin site, and as awesome and incridible as it is, it’s suitable only for data entry. It relieves you from the initial effort of writing the admin interface. You can get started with a simple application by just specifying the models and writing a couple of simple templates, without ever worrying about SQL or writing (an) Admin page(s) for entering you data. But is that really so great? I mean, it gives you a relief in that you don’t have to do it, but at the same time, it’s so simplistic, it’s not the kind of thing that’s suitable for all situations; infact it’s quiet unsuitable for most situations.

I’m writing this blog post right now in wordpress. Have you seen the admin interface? It’s so great, but .. it’s all written in php! Django’s admin interface can never ever come close to this. No matter how much you try to customize it (and there isn’t that much to customize anyway). Of course you can build one from scratch, (in python), but then what’s the point of doing this inside a Django framework? See, when you start doing things outside Django, you realize that you don’t even need django. Not only that, but Django will get in your way because you can’t just do what yo want, you have to do it in a way that pleases Django.

Remember the first quote above from Flicker’s manager? It speeds you up at first, but then you hit a wall and you have to start from scratch again.

I’ve done an ajax admin interface to some application (that shall remain anonymous), and I didn’t use one bit of Django’s forms framework. Why? Because I don’t need to. It’s much easier to write my own forms in html, and my own validation functions, than to constrain my self to the framework.

I kinda forgot t mention this but (as you might have guessed already): Django has a forms framework. I’ve never looked deeply into it, but I can tell it suffers the same issues as the admin interface: it make so many assumptions about your workflaw, and forces you to adapt to /its/ workflow, instead of it adapting itself to yours. Plus, forms are relatively simple to write in plain html (and much easier to customize when you write them that way), why should I spend time to learn a complicated Forms framework? Is it worth it? I doubt that.

The same thing can be said about the template system, and the crazy idea that you have to write a costum tag (read: lexer and parser) for every extra little thing you need. Thank God there’s Jinja!

Anyway I don’t think I need to talk about the pitfalls of Django’s template system much, it’s kinda obvious for anyone who’ve used it. I will just mention that I had *so much pollution* in my python code to cover up for the shortcoming of the template system, and even after I switched to jinja, some of that poison is still lurking somewhere, in some deep dark rusty corners of my code.

Of course, the auth and session middlewares suffer from the same thing: they’re awesome, but not really extensible. At least in the sense that it’d be much easier to roll your own solution from scratch than wrestling with the framework and digging into its internals.

Fragmentation

After a while of working on a website with several “apps”, you come to realize what a mess everything is. Everythign is torn apart. You can view the application as being composed of 3 basic parts:

  • python code
  • template files
  • media files

The media files can be broken down further into: images, javascript, and css; but let’s not get into that, as it’s outside the realm of Django.

The problem is that each of these components lives in a completely different planet. You have a directory for code, a directory for templates, a directory for media. Each directory is in a completely different place from the rest. When you need to make changes to an application, *you have to remember quite a lot of things*, if you *only* remember where each directory was, you’re already using 3 slots in your short term memory. It might not seem like much, but it does get daunting after a while. It becomes a wall that makes you go “oh no, I have to go through that again?”, pushing you to procrastinate, thus making you less productive.

Furthermore, the python code has to be further fragmented according to the specifications and expectations of the framework. You need a urls.py file, models.py, admin.py, views.py (and maybe you tag along with this idiom and create a forms.py, and maybe utils.py, or biznis_logic.py, or whatever)

So if your app has four components (in terms of models), then different pieces that deal with different aspects of each component are fragmented across these files.

Many kinds of changes to the code will require “shotgun surgery”; lots of little changes to lots of files.

This fragmentation is caused by the framework; because it *forces you* to layout all of your files in a certain way; it forces you to adapt to *its* work-flow.

What’s left?

So, so far I’ve dismissed the template engine, the forms framework, the admin interface, and the file layout.

What’s still remaining? The url-mapping, and the ORM.

Well, I recently learned about Werkzeug, so I don’t have to use Django for url-mapping. As for the ORM, there’s SQLAlchemy.

The thing that’s attracting me to Werkzeug is that it (by design) is anti-framework. I haven’t used it for real yet, but that’s the kind of impression it’s giving me.

As for the ORM, I think Django’s ORM is great, but if SQLAlchemy also solves the same problem, then I don’t have to stick to Django just for the ORM. Plus, SQLAlchemy is dedicated to being an ORM, while Django’s ORM is a part of a larger project, therefor I would assume that SQLAlchemy has a better chance of doing things right.

Things I’d like to keep from Django: the pagination module, and the email module; as python’s smtplib just sucks!

Tagged with: , ,

modifying plink to work with unison

Posted in hacking, webdev by hasenj on 19/12/2008

Last time I talked about how to make unison work on windows with ssh.

Well, there was still one problem that remained unsolved, that is, password input.

I thought about the issue and figured I could hack plink’s source code to make the modifications necessary to make it work like unison expects it to.

The changes are simple:

  • make it accept -e none
  • make it print the password prompt to stderr instead of stdout

in winsoncs.h change hin and hout, around line 325:

    hin = CreateFile("CONIN$",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
    hout = GetStdHandle(STD_ERROR_HANDLE);

and in cmdline.c around line 438:

    //ignore "-e" option! (for unison compatibility)
    if( !strcmp(p,"-e") )
    {
        RETURN(2);       
    }

It’s not heavy tested, and frankly it’s a hack in a sense, I didn’t study plink’s source code in any kind of depth! Who knows, maybe my changes break the behavior in some (at least subtle) ways, but it works for me!

here is the result

This is not a wrapper; it’s a modified plink, and we call it ssh.exe so that it integrates with unison.

Integrating Jinja2 with django

Posted in webdev by hasenj on 12/11/2008

(I have this posted on django snippets: http://www.djangosnippets.org/snippets/1112/ and it’s where you can view the code and download it)

Jinja2 is an alternative template system that can be plugged into django. It offers greator flexibility in presentation logic; if you find the django template system too restrictive, you should have a look at Jinja2 (The syntax is very similar).

In Jinja, you don’t need costum tags (most of the time), because you can call functions and pass them parameters too! The only problem is that you cannot “load” functions from the template, this “loading” must be done by the code that renders the template. Same goes for filters and tests.

If you need only two or three functions/filters, no problem, you can manually add them to the Environment object; but this method doesn’t really scale with real-life webapps.

This module/snippet offers a solution by allowing the user to define application-specific functions and filters and load them into the jinja2 environment automatically.
It also sets auto_escaping on (Jinja2 has it off by default).
It searches for templates in TEMPLATE_DIRS and also in the “templates” subfolder (if it exists) of each application folder.

The approach I’ve taken to specify functions and filters is like this:

To add test functions, put them in a file called “jtests.py” and let each function start with “is_test_name”; it will be available as “test_name” in your jinja2 environment, so you can test {% if var is test_name %}

The same idea applies for filters, put them in a file called “jfilters.py” and let each one start with “filter_name”, and it will be available as “name” in the environment, so you can say “{{var|name}}”

For functions, it’s a little different; you add them a file called “jtemp.py” (temp is my wacky abbreviation of template global functions), but they are put in a name space that’s named after the application. so if your application is called “app”, then any function you put in jtemp.py will be avaiable in the template environment as {{ app.function_name() }}

Here’s how to use this:

  1. Install Jinja2 (for a quick & dirty installation, you can just put the jinja2 folder in a folder that’s in PYTHONPATH)
  2. Save this python module somewhere and call it something meaningful (I have it as jinja.py in my project directory)
  3. Whenever you need to respond (an HttpResponse) with a template that’s rendered by jinja, import this module and call return jrespond( template_name, context )
  4. Any filters or functions you define in any of your applications will be readily available inside the template (see the documentation in code)
Tagged with: ,

unison on windows (ssh on windows)

Posted in webdev by hasenj on 12/11/2008

[Update: this post discusses some outdated techniques, please see this newer post for a better technique to use ssh with unison on windows]

I’m running windows vista on a laptop, and need to synchronize files with a linux server (for a web development project). After googling for a while, I found two options: rsync and unison. rsync requires cygwin, and it’s for (uni-directional) mirroring. unison on the other hand does not require cygwin, and is designed for (bi-directional) synchronization. so I chose unison.

Unison seems easy enough to use, check out the tutorial on its manual page.

but I quickly discovered that it doesn’t really work on windows out of the box: it needs “ssh”, or an ssh-like tool to be present on the machine, and guess what, ssh requires cygwin!

Now, there’s “plink” which behaves pretty much like ssh, except for some subtle differences, but these “subtle” differences render it unusable with unison. The problem is that unison sends some command-line options to ssh that plink can’t understand.

I found this discussion page on google, and a solution is offered in the form of a bat file that removes the extra command-line arguments before passing the rest to plink

http://twiki.org/p/pub/Codev/UnisonKeySetup/ssh2plink.bat

So you can save this file somewhere and use the -sshcmd option to make unison use this file as if it was “ssh”.

A problem arises when you connect to the server and you are prompted to enter your password: unison chocks and says “the ssh server is responding with something that I don’t understand, so I’ll quit”!! You’d expect a program that’s designed to connect to ssh servers and sync files with them to be smart enough to handle the password prompt; but then again, we’re using plink, where as unison expects “ssh”, and I guess this is also one of the “subtle” differences between ssh and plink.

so as a way around that we could pass the password on the command line using -sshargs option.
see, plink has this option “-pw password” which has the nice effect of allowing you to bypass the “password prompt”, and we can use it for this purpose. pass this to unison:

-sshargs “-pw password”

and it should do the trick (you need the quotes ..)
of course when you automate this, it raises the issue of having your password stored somewhere in a text file on your laptop; so you have to watch out and make sure no unauthorized person can read this file.

Now, if you actually google “window unison ssh”, you will see this page http://www.wischik.com/lu/programmer/unison-ssh.html

which provides a nice tool (conveniently named “ssh.exe”) that you can copy to a folder that’s included in your PATH environment variable, but it still suffers from a problem with the password prompt: the prmopt is broken; it doesn’t work (at least on my vista laptop), as soon as you type the first character, it presses enter for you and prompts you to enter the password again because the password that you just entered is incorrect :) (maybe this only happens in vista, but it happens for me, and that’s what matters).

Now, there’s another dependency that you will probably need: diff, as unison uses it (optionally) to show the differences between files. So you might consider downloading it if you don’t already have it.

Tagged with: , , , ,
Follow

Get every new post delivered to your Inbox.