Wednesday, 25 September 2013

jQuery offset() not working properly in Internet Explorer

Strictly speaking, maybe it works in Internet Explorer and not Chrome but the effect looks wrong in IE 10 so I'll assume that's the case.

Scenario? I have some transparent windows that are used to frame images so that the user can click on the transparent window and see the image full-screen. In order to do this, I iterate the images, create a new frame for each one and set its position using offset() to match that of the parent image. position: absolute and everything is fine in Chrome.

Same page in IE and the frames are not positioned above the images but are below them, causing the parent div to stretch and basically it's all rubbish. A quick check and in IE, these frames have position: relative which they don't in Chrome (since my CSS specifies absolute).

A dig through the jQuery source and the offending (and slightly odd) line of code is:

// set position first, in-case top/left are set even on static elem
        if ( position === "static" ) {
            elem.style.position = "relative";
        }

Which is presumably true in IE by default but not in Chrome (despite my CSS specifying absolute!). Anyway, I found a bug filed on jQuery here which describes it in more technical detail. The bug seems undecided even though it is clearly inconsistent behaviour but more importantly, Kelly Selden has proposed a workaround (which does work!) using css() instead of offset:

targetElement.css('left', source.offset().left).css('top', source.offset().top);

Thanks Kelly!

Why we should all be fighting SPAM with the SPF setting

At the moment, we are basically stuck with RFC 5322 which describes email format. Email is used by virtually every computer user, often each with multiple accounts (personal, business etc) and despite recent concerns about privacy, for some reason, the world has made lamentable progress on replacing the system with something much more secure and harder to spoof.

With SPAM, there are a couple of issues. The first is not really anything to do with the weaknesses of email and would occur if someone simply sent you an unsolicited email, either offering things for sale or perhaps offering malware or phishing. There are perhaps measures that could be taken in a future email protocol to help combat this but ultimately that would involve trust, verification, signing and a whole load of things that never sit terribly well on the web.

The second however is a very simple weakness with email and something that is perhaps more dubious from a SPAM point of view. This is when somebody sends you an email from any server in the world (which may or may not even stay alive for any period of time - it is untraceable) but in which the user has set the "from" address to something that looks genuine, e.g. admin@paypal.com and which then would probably contain information that looks like it comes from paypal. Many users would easily be fooled and could end up being fished/infected with a computer virus or whatever. RFC5322 does not provide a mechanism to ensure that the address of the user in the "from" field matches the ownership of the server that sent the email and in one sense, it would not be easy anyway. There are many reasons why a company might send emails from one server or another. Perhaps you outsource your marketing to another company and the mail is sent from their servers, perhaps you had to hire some servers while you were performing an upgrade on your own systems and perhaps the "from" address relates to someone who you want your customers to contact who doesn't work for your company.

Recently I received an email reporting to be from someone@red.com red.com sell film cameras but clearly, by not using a system called SPF, the email didn't raise any flags when it arrived in my in box - it should have.

SPF is a simple system that relies on DNS records and although not foolproof, is a good first step towards identifying SPAM. The idea is simple, if my mail client receives an email with a "from" address that contains e.g. somedomain.com, it makes a DNS request to somedomain.com and queries its SPF record (the same information should also be contained in the TXT record). This SPF record simply lists the server(s) that are permitted to send mail for somedomain.com and then provide an option to tell the client how harshly it should treat mail received from any other server. Theoretically, you can tell it to "hard fail" which means the client should instantly mark it as SPAM, you can also "soft fail" which says, "it probably is SPAM but I'm too scared to hard fail it in case genuine mail gets lost into SPAM folders".

If you use a single (private) mail server to relay your mail, this actually works really well because presumably no-one else can send mail from your server. It gets slightly more complex if you use shared mail servers (e.g. gmail or your hosting company) because naturally other people can send mail from the same servers that your SPF records authorise. This is a low risk for most people. In our case, we use GMail to relay mail and although they have lots of mail servers and many other customers sharing these, it would be fairly straight-forward to identify SPAM comping from a Gmail account and have it closed by Google.

So what are you waiting for? Update your SPF records or get your hosting provider to do it (if they manage the DNS for you) and start seeing more junk go straight into your SPAM folder and less of it in your inbox!

Friday, 20 September 2013

How to animate an HTML image to make it "glow"

We have a system where people click on an image in certain places and our designer wanted these "click points" to glow as they are clicked in order to make them both look good but also to make them look more obvious, otherwise it is hard choosing colours for images that work on top all kinds of coloured images without making them too obvious.

Anyway, she had designed them in Photoshop using an animation effect on the layer so my question was how to mimic this in HTML using (probably) jQuery animate() and some set of CSS values to make it glow.

A bit of searching and I found this article that shows how to make a very basic but very effective glow: http://www.onlywebpro.com/2010/09/19/

So this was easy enough to use as a starting point but there was more. By default, jQuery cannot animate the box shadow used in this "glow" so I needed an extension in the form of the box shadow animation plugin found here: http://www.bitstorm.org/jquery/shadow-animation/

Then it was a case of trial and error. Note that my images are circular but the default box shape is obviously square so I also had to add 50% border radius to make sure the box shadow was circular and not square. Also note that I am creating my images in Javascript but the same thing could be applied to an existing image(s).

CSS:

.fingerprint
{
    border-radius: 50%;
    -moz-box-shadow: 0px 0px 0px 0px #ffffff;
    -webkit-box-shadow: 0px 0px 0px 0px #ffffff;
    box-shadow: 0px 0px 0px 0px #ffffff;
}

JavaScript:

$("<img src='../Images/orange1.png' class='fingerprint' />")
    .appendTo("#clickTarget")
    .show()
    .animate({ boxShadow: "0px 0px 10px 7px rgb(255,255,255)" }, 300, function ()
    {
       $(this).animate({ boxShadow: "0px 0px 0px 0px rgb(255,255,255)" }, 300);
    });

Using the animation plugin, I can simply animate the box shadow from the default css to the values in the first animate call in 300 milliseconds and then when this is finished, it will call the inner function which will call animate again to take the values back to their defaults. Naturally you can modify the way these work and the timings. Also, you could use a Javascript timer if you want to keep triggering the animation. You must have a value in your CSS by default in order to animate it, you cannot animate from "null" to some value!

Have a play and see what you can do with it, it's pretty straightforward thanks to jQuery!

Monday, 9 September 2013

Developers: Beware 401 response codes on IIS!

This problem was causing me to use very naughty words: A PHP Yii app using the built-in CHttpException class and every time I tried to return a 401 (unauthorised) exception, the request for the page would lock up. Change it to pretty much any other code and it was fine.

Lots of other weirdness ensued, at one point, just echoing "hello" to the output was enough to make it work but remove this line and it locks up again.

What was happening (looking in Fiddler) was that the response headers came through OK but the body never did. Looking at the content-length, it was correct as per the information I was sending back to the user.

Long story short, it appears that IIS is deciding, on your behalf to remove the body on any 401 responses. I say IIS not because I know but I can't see it being anything else! This means when you write to the response, the content-length is set correctly so the client is waiting for it - but it never comes!

Anyway, needless to say, I had to remove the error messages I was sending back with the 401 and just include the correct challenge header instead.

Thursday, 5 September 2013

SPF not working on Google - "Received-SPF: neutral" - "is neither permitted nor denied by best guess record for domain of"

Sender Policy Framework is a minor attempt to help identify SPAM in email by using a DNS record(s) to say which mail servers are allowed to send email on behalf of the domain. In my case, I forward all mail via one of our GMail accounts from web servers and although I had an SPF entry in my DNS, I noticed that GMail was reporting the email as:

Received-SPF: neutral (google.com: 209.85.215.178 is neither permitted nor denied by best guess record for domain of user@mydomain.co.uk) client-ip=209.85.215.178;
 
I was slightly surprised because I had just assumed this worked and didn't really understand how SPF was supposed to work, especially the weird Google code I had to add to the DNS entry. It took a while initially to learn what exactly is going on but it is pretty simple. On receiving an email from a user@domain, the receiving email server checks to see if the DNS for that domain has an SPF record. This record contains one or more IP addresses that are permitted to relay mail for that domain, this results in one of several things happening: 1) If the IP of the sending mail server is in the record, it passes and the message changes to:
 
Received-SPF: pass (google.com: domain of user@mydomain.co.uk designates 209.85.212.179 as permitted sender) client-ip=209.85.212.179;
 
2) If the address is NOT in the SPF record then depending on the flag at the end of the SPF record, one of two things will happen. If the record contains ~all, then the system will produce a soft fail, an indication that there might be something wrong with the email but maybe it's OK. Google have sometimes suggested this because otherwise any temporary problems with the DNS system might otherwise flag good emails as SPAM. If the flag is -all, then a hard fail will be produced which in many email programs will immediately flag the message as SPAM.
3) If the receiving mail server cannot find an SPF record, the result will be neutral as per the first message above and the receiving client basically won't have any way to mark the message as SPAM other than the usual weird rules they might apply to content and style of the email.

Anyway, none of this was working as expected, despite using Google's standard entry of "v=spf1 include:_spf.google.com ~all" in my DNS SPF record. Fortunately, I eventually found the answer in this blog post: http://aahank.com/2013/google-apps-with-amazon-route-53/

The piece I was missing was that I needed a TXT record as well as the SPF record. SPF sounds more correct and perhaps some servers look-up the SPF record but obviously GMail uses the TXT one. By adding the TXT record (with the same content as the SPF record), in no time, GMail was correctly identifying my emails as genuine. Hopefully this will help in any SPAM problems in the future!