Lessons learnt today: Double quotes, redirection and rubbish routers

I haven’t posted here in a long while, and no doubt that will continue unfortunately. However, tonight I’ve learnt (or in some cases re-learnt) a few, albeit simple, lessons and it felt sensible to note it down so I can remember in the future.

Double Quotes vs. Single Quotes in PHP

This was a massive rookie error and a sign that I haven’t worked in PHP much over the past year.

While tightening my database security, I ended up patching up some dodgy db related code in PHP in a particularly old project. I spent nearly half an hour trying to work out why my passworded database user was being denied access to the database.

After a bit of debugging, I noticed the password was being cut off in the middle, and after further debugging and tracing the string back, I noticed that my randomly generated, double quoted password string happened to have a ‘$’ character in it.

PHP (among other languages) tries to resolve variables within double quoted strings, meaning “abc123$efg456” is resolved to “abc123”, if the variable $efg456 doesn’t exist in your script. The solution was to simply exchange the double quotes for single quotes.

Lesson: If you’re working in a language which treats double and single quoted strings differently, check you’re using the right ones!

.htaccess redirection

.htaccess always ends up leeching away my time. This time I was trying to set up some redirects to treat a sub-directory as the root directoy, but only if the file or directory didn’t exist in the root directory and did exist in the sub-directory.

This is simple enough if you know what the .htaccess variables mean, but in using examples and making assumptions I tripped myself up. So here’s the bit I learnt:

%{REQUEST_FILENAME} – This isn’t just the filename that was requested, but the absolute path from the root of the server.
%{REQUEST_URI} – This is the filename on its own.
%{DOCUMENT_ROOT} – This is usually the path up to the root directory of your site (though I’m quite sure this is not always the case).

So given the path “/a/file/path/to/a/website/index.html”:

%{REQUEST_FILENAME} = /a/file/path/to/a/website/index.html
%{REQUEST_URI} = index.html
%{DOCUMENT_ROOT} = /a/file/path/to/a/website

Simple when you know, but confusing otherwise! In any case, here’s the resulting rule I cobbled together:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/other%{REQUEST_URI} -f
RewriteRule ^(.*)$ /other/$1 [L,QSA]

That won’t suffice if you need directories to work as expected, and it will only apply to files, but it’s as much as I need for now.

Lesson: Don’t assume things, especially when dealing with something as powerful as .htaccess files. The more you know and use it, the less of a pain it will be.

NAT Loopback and remote IPs not working locally

Having acquired a new domain name today, I decided to put it to work as a domain for my home server (with help from no-ip). Having set it all up, I came across a peculiar scenario where I was able to access the machine remotely with the domain (the outward facing IP), I was able to access the machine locally with the local IP address, but I was unable to access the machine locally with the public IP or domain name.

In a few minutes I realised that this was not so peculiar at all. The Network Address Translation (NAT) rules decide where inbound requests should go when it hits the router, I have my router set up to allow certain connections to forward through to my server. However, these rules don’t apply to requests which pass through the router on the way out. I’d only be guessing, but I’d imagine this is because responses to requests across the Internet would otherwise have these rules applied to them as well, completely breaking the network.

To solve this issue, NAT loopback, a feature or further rule which resolves requests to the router’s public IP from inside the network correctly, is available in many routers. It is commonly turned off due to security concerns, or simply may not be available in some routers.

Unfortunately, my Huawei HG533 router falls into the latter group, with no obvious plans of an upgrade which would fix this.

Lesson: If you want to use one address to access a machine locally and remotely, ensure NAT Loopback is set up.

All simple stuff, but it’s been interesting learning about it all. Hopefully I can continue documenting the small things like this over the next year, my final year of university should be a steep learning curve!

Javascript: addEventListener and element.event

A quick post on the differences between addEventListener and element.event.

addEventListener and element.event, on first appearances, do the same thing. They allow a custom function or action to be linked to a javascript event, which are usually triggered by user-input.

But in more detail they do in fact have differences and for this reason, they should be used and treated differently. Each case where either is required should be assessed to make sure that it’s the best option of the two.

Using both methods

To use an addEventListener for the mousedown event, for example, we would do this.

var mouseInput = function(e) {
//filter the mouse inputs you're looking for
//do something based on the mouse input
}

document.addEventListener('mousedown', mouseInput, true);

The alternative element.event method would look like this.

var mouseInput = function(e) {
//filter the mouse inputs you're looking for
//do something based on the mouse input
}

document.onmousedown = mouseInput;

That’s it, and in most cases, both those will do the same thing…

The Exception to Explain the Difference

However, the methods are actually doing different things behind the things.

addEventListener

addEventListener assigns an additional function or action to carry out when the event happens. The clue is in the name really, addEventListener suggests that it won’t overwrite or override any other actions. This is generally a good thing, scripts, extensions and the browser itself will have assigned things to certain events and it may make the User Experience (UX) poorer if those normal functions and actions don’t happen when those specific events happen.

However, it also means that if you are purposely trying to change default actions to in fact improve the UX, this method won’t work “out-of-the-box”. An example of this is if you’re writing a web app and you want to force your own right click context menu*. You won’t surpress the context menu by default.

*A note on this idea: This is something you should carefully think about, it can certainly be useful, but many core browser operations can be found in the default right-click menu, and many extensions place a menu item to enable them to work effectively. It’s best to only use it on certain parts of the web page/app if you really are going to do this. It is very inadvisable to use this technique to stop people copying your content, there are other ways to take your content and it will often detriment genuine, non-malicious users.

element.event

element.event is an absolute assignment, it scraps and effectively destroys anything that was meant to happen when that event occurred and instead replaces it with yours. When put like that, it’s a pretty selfish way of coding as, again, it is likely to detriment the overal UX. Posts about making element.event assignments less problematic were commonly seen around a decade ago. But as addEventListener has become more supported over the years (it has been in the w3 spec for years and had support in Netscape 6(!), but only gained full support across the browsers when IE9 came in), and full featured libraries such as jQuery it has been less of an issue.

However, element.event has it’s place. It has much wider support. It’s likely that you’ll be able to support browser versions you’ve not even considered because this method of registering event listeners has been around since the beginning of Javascript (it’s fully supported in Netscape 2 as part of DOM 0…). So if compatibility is a real issue further than it is for most projects, and you can’t use a library (which will more than likely have this support built in), then this is your method to go for.

It also is quicker, and in some respects, a little easier to read, so if you’re writing a proof of concept or a quick script, where you know you won’t be interfering with anything unintentionally. Then this is also the method to choose.

The Best of Both

It is now accepted that using addEventListener over element.event is generally a better way to do things. You won’t be mucking about with the pre-assigned functions and actions for that event, which means that you’ll provide a better, more consistent UX overall.

However, if you actually are looking to surpress default actions using addEventListener, it is possible. This final example demonstrates how.

var mouseInput = function(e) {
e.preventDefault();
//filter the mouse inputs you're looking for
//do something based on the mouse input
}

document.addEventListener('mousedown', mouseInput, true);

It should be noted that this example is actually a very bad idea if implemented, as it will stop any pre-assigned click functions. If you were trying to prevent the default context menu from appearing on right click, you should replace mousedown with contextmenu to do this correctly. See my (*) about this above.

Further Reading

 StackOverflow thread that brought these differences to my attention
 Further information on element.event registration
 Article from 2004 on making a cross-browser addEventListener (for the onload event) function for full browser support
 Article from 2001 about how difficult it was to code cross-browser event handlers (not much has changed sadly…)
 Mozilla Developer Network page on both event registration methods
 QuirksMode article on DOM Level 0 (the first version of DOM, used in the first iterations of Javascript)