Google Analytics not reporting Windows 7 users

It seems that Google Analytics is not reporting Windows 7 users properly. According to the stats for my blog I’m getting an increasing number of people browsing my blog from Windows NT.

Google Analytics for Windows NT Users on my Blog

I would guess that the operating system is self identifying as Windows NT 7.0 which is why Google Analytics is putting the visits in the NT bucket, but Windows hasn’t been called NT (at least in a marketing sense) since Windows NT 4.0. After that it became Windows 2000* (which Google Analytics is identifying), then XP, Vista and now Windows 7.

* Admittedly with the tag line “Built on NT Technology”

Interpreting promotional codes

The application I’m working on these days has a thing in it called a booking code. Now a booking code can be many things. It can tell you which discount code to use, which third party was being used to make the order, which business customer is making the order and so on. It is really just a convenience on the user interface so we didn’t have a large selection of text boxes asking for a discount code, merchant code or corporate customer ID, etc.

The application can determine what the code is based on which prefix has been used. “D” for a discount, “ME” for a merchant, “CC” for a corporate customer and so on.

So far all this seems fairly simple and straight forward. It is very simple to perform some conditional based on, for example,

string.StartsWith("ME")

However, it does mean that the code is soon cluttered up with lots of conditional statements testing the start of a string with magic values.

Of the two issues here the easiest to address is the magic values. It is easy enough to set up a series of const values representing the various prefixes. For example:

public const string MerchantPrefix = "ME";
public const string DiscountPrefix = "D";
public const string CorporateCustomerPrefix = "CC";

Then when a condition has to be met then the constant value can be used. This reduces the potential number of errors in the code because if the name of the constant is mistyped the compiler will catch it. If the magic value is mistyped then bugs can be introduced. Also, by using a constant value you can provide more meaningful names than the prefix alone can.

However, this is not the end of the story.

Because these prefixes are artificial there was also lots of code to strip off the prefix and check that the right number of characters was being stripped off, or have none stripped off (because in one case that type of code genuinely did always have that prefix in the back-end system). It seemed a lot easier to me to refactor the code and create a BookingCode class that encapsulated that functionality.

The new class takes in its constructor the code as the user would have typed it in. It has a property that exposes the type of booking code as a enum so it can be easily be used in switch statements. It also has a number of properties along the line of IsMerchantIdentifier, IsDiscountCode or IsCorporateCustomer for use where a single departure from the normal processing was required (i.e. an if statement).

Finally, the BookingCode class has a string property that exposes the actual code that the back end system needs. That way all the code that was stripping off the prefixes can be removed. The possibility of introducing intermittent errors is also reduced because there is now only one place where the code the user typed in is deconstructed into its component parts.

All in all this is a much more robust solution to the way the code used to work.

NOTE: The details in the example code above serve as an example only and do not represent the actual system in production.

Tip of the Day #15: Loop Performance

When you look at the code it will probably seem somewhat obvious, but it is interesting how the same thought process isn?t necessarily there when actually developing the code, especially when under the pressure of a looming deadline.

Take for example this snippet of code (from a fictitious hotel management system) that may have been run by a receptionist to print out the check in forms that customers of the hotel will fill in on their arrival.

List bookings = GetTodaysBookings();foreach (Booking booking in bookings)
{
    PrintService service = GetLocalPrintService();
    service.PrintCheckInForm(booking);
}

The method GetLocalPrintService() could be doing a multitude of things. It may simply be creating a new instance of the PrintService object, or it could be resolving a number of dependencies in order to set itself up to communicate with the local printer. But what ever it is doing, we don’t actually need a new instance of the service on each loop. The code will work just as well if we have just one instance that is re-used on each iteration of the loop.

That being the case, the creation of the PrintService can be moved outside the loop so it is created only once, thus removing unnecessary work from the loop. The new code then looks like this:

List bookings = GetTodaysBookings();
PrintService service = GetLocalPrintService();
foreach (Booking booking in bookings)
{
    service.PrintCheckInForm(booking);
}

As I said at the top, this is obvious. Isn’t it?

Tip of the Day #14: A Step to PCI Compliance

If you have a public facing website that accepts credit card payments from customers they you?ll be looking to become PCI compliant. This means you need to improve the security of your website to prevent attack and to prevent data being intercepted by third parties.

SSL 2.0 is now seen as weak and insecure, yet IIS will by default accept connections from older browsers that want to use this. It can be turned off, but it isn?t obvious how to do that. Here?s how to turn off SSL 2.0 on IIS or Microsoft Support has a reference on How to disable PCT 1.0, SSL 2.0, SSL 3.0 or TLS 1.0 in IIS (Internet Information Services).

While many PCI auditing companies will tell you if you are using SSL 2.0 or any other weak techniques, the quick test to ensure the server is not serving pages using SSL 2.0 is to change the Advanced Options in Internet Explorer to only support SSL 2.0.

Internet Options 1 (SSL)

After that I went to a secure page in the site and got the following error message:

Internet Explorer cannot display the webpage

Most likely causes:
  • You are not connected to the Internet.
  • The website is encountering problems.
  • There might be a typing error in the address.

What you can try:

Diagnose Connection Problems
More information

This problem can be caused by a variety of issues, including:

  • Internet connectivity has been lost.
  • The website is temporarily unavailable.
  • The Domain Name Server (DNS) is not reachable.
  • The Domain Name Server (DNS) does not have a listing for the website’s domain.
  • If this is an HTTPS (secure) address, click Tools, click Internet Options, click Advanced, and check to be sure the SSL and TLS protocols are enabled under the security section.

For offline users

You can still view subscribed feeds and some recently viewed webpages.
To view subscribed feeds

  1. Click the Favorites Center button , click Feeds, and then click the feed you want to view.

To view recently visited webpages (might not work on all pages)

  1. Click Tools , and then click Work Offline.
  2. Click the Favorites Center button , click History, and then click the page you want to view.

To ensure the site was working normally, I reset the settings to allow only support SSL 3.0 and TLS 1.0 and tried again.

Internet Options 2 (SSL)

This time I got the page I was expecting.

Note: You cannot use FireFox to perform this quick test as it does not support SSL 2.0.

Internet Options 3 (SSL/FF)

How I'm reducing my debt

I recently came across some notes I’d made some years ago about how I planned to reduce my debt and increase my savings. It is something that has worked (and is working) for me and it might be useful to others so I thought I’d share it. This comes with the caveat that you need to look at your own personal situation and apply this only if you are comfortable with it.

Reducing Credit Card debts

If you do not have the option of replacing high interest credit cards with a lower interest loan there are some things you can do with your existing cards.

If you have multiple cards, pay off the card with the highest interest payments first.

Say you have three cards each wanting a minimum payment of £50 each. The interest rate on each card is different and you have a budget of £200 for repaying credit cards. The card with the highest interest rate is costing you more than the others. Pay £100 per month to that and leave the others paying the minimum.

Assuming you are not still spending on the cards the two cards you have left on minimum payments only will also start to slowly reduce meaning their minimum payments also go down. This means more money for paying off the expensive card so its debt reduces more quickly thus getting rid of the expensive debt. Once that card is paid off choose the next most expensive card and repeat the process.

I once worked out that if I just left all my cards on the minimum payment only it would take 27 years to pay off the debt I had and cost three times the the original debt.

Increasing Savings

Extended warrantees and consumer insurance

Some time ago it occurred to me that I’ve rarely needed to use extended warrantees that shops offer on consumer goods. The same goes with mobile phone and laptop insurance. In fact in the last decade I’ve had one mobile stolen and one microwave break in what would have been the extended period. The total cost of that was £250. However, compare that to the cost of the insurances and extended warrantees that I was offered for the same period.

What I did instead was set up a savings account that I’d put money into every time I was offered an extended warrantee or a (in my opinion) pointless insurance policy. The last time I was offered mobile phone insurance they wanted £5 per month. So £5 per month goes into that account. PC world wanted £15 per month for insuring my laptop with some “support” services I didn’t need*, so that goes in too.

Incidentally, I have my laptop (among other specified items) covered on my home contents insurance and it costs me an extra £50 per year, so that (£4 per month) gets deducted from the money PC world wanted. So I now have £16 per month going into a savings account just from those two things. If either my laptop or mobile needs to be unexpectedly replaced I have some funds to draw on. In the case of the laptop I’d be able to put the funds back when my home contents policy paid out too.

Be careful what you consider to be a pointless insurance policy. I would never class home contents or buildings insurance as pointless even although I’ve paid thousands of pounds over the years into such things and only received back about £200 so far. The simple reason is that I don’t have nearly £200K to replace my home, nor do I have the resources to suddenly replace large quantities of my belongings either if the need arises.

Also, some people I’ve spoken to do seem to regularly have accidents with their laptops or mobiles so the dedicated insurance policy may be good for them.

Over the years I’ve built up a savings account with about £3000 in it.

* I almost walked out the shop, I tried to explain I was a software developer and all the issues he was telling me the support would cover me for I could deal with perfectly capably on my own.

Paying things monthly

Some things like insurance policies can be paid monthly instead of annually. At first this may seem an excellent way of spreading the cost, but beware that the insurance company will often charge quite a hefty interest rate for that. If you can pay up front you can save quite a bit of money.

When I first started doing this I couldn’t afford to pay all the things I wanted upfront, so I had to take the hit of the interest payments the first few years. What I did instead was set up another savings account to save up for each item so that when the renewal date came around I had enough money to pay it up front the next year.

As I couldn’t afford to start doing this for everything I chose one thing that I could afford to pay twice over (once to the insurance company AND the same amount into the savings account). At the start of the next year I could afford to pay that insurance policy up front, for much less than it had cost the previous year, so I had money left over in the savings account too. I then moved on to starting to pay the second policy twice over (once to the insurance company and once into my savings account).

Over time, I also added car tax (an annual payment if you want it cheap), an estimate of the servicing charges for my car (MOT, servicing costs, tyre replacement costs*, etc) and so on. I worked out what those costs are on a monthly basis and add it to the savings account. When my car tax is due the money is already there.

Other things which I buy on a longer cycle (a new PC, a new car**, etc.) I do the same thing with. It all starts to add up, and I much prefer having the money in my account than in someone else’s account.

* If you are curious, I actually calculated that based on my driving style I need to replace a tyre on average once every 6500 miles. Knowing that and my average annual mileage I can annualise the cost.

** Although with the amount going in to my savings account for a new car, I’ll be two or three cars down the line before I can walk into the showroom with all the money up front.

Offset Mortgages

In my opinion these are one of the best inventions in the mortgage market. There were a lot of really duff ideas in that area over the last few years like endowment mortgages and sub-prime mortgages, but offset mortgages are one of the ideas that really works well, I think.

How they work is that they money in your savings account offsets the capital that is to be repaid on your mortgage. What that means is that, say you have a £100K mortgage and £10K in your savings account you pay interest on only £90K of the mortgage. Since mortgage interest is typically* higher than a savings rate you might be offered on a savings account the saving in interest on the mortgage is better than the interest you would have received on the savings account. Added to that is the bonus that since you are not receiving any interest payments on the savings the tax is zero, so it works out even better.

Depending on the mortgage lender there are a variety of ways to calculate how the offset works. My particular lender gives me three options and I can change those whenever I want.

1. Offsetting reduces the interest payments you pay each month. The term of the mortgage remains the same as the capital is being repaid at the same rate, however the monthly mortgage payments are reduced.

2. Offsetting increases the capital repayments each month. Instead of reducing the monthly bill, it stays the same as if there was no offsetting, the savings you would have made are used to pay off some more of the capital. Your capital reduces faster which means each month you are paying off more capital than you would have been otherwise. The term of your mortgage reduces as the capital is paid off more quickly.

3. A hybrid of the above two options. Essentially option 2 is in effect until the interest rate changes. The mortgage is then recalculated to maintain the original end date, the overall monthly bill will reduce at this point if you had something to offset.

When I did my calculations I estimated that over the course of my mortgage I’d be £15K better off than a regular tracker mortgage + a high interest savings account.

* Although I have seen a number of savings accounts these days with interest rates at 4% above the Bank of England base rate, so it may be that right now one of those savings accounts may be the better option.

Other things

Other things I did to cut my debt and increase my savings were mostly to do with cutting out the subscriptions to things I didn’t need, or reduce my outgoings in other ways.

For example, I worked out that I was only really watching Sky for one show. It was much cheaper just to buy the DVDs. So that’s what I did. And I can watch my favourite TV show any time I like now.

I was buying a weekly rail pass, so I changed to a monthly pass. And if I planned my holidays far enough in advance I could match them up with the renewal date of the pass, or go back to weekly passes briefly, so that I wasn’t wasting additional money.

Also, I didn’t need to go and buy a sandwich at lunch time. I could just bring a packed lunch. Although I have to admit that didn’t last long as I’m not a morning person and making my lunch the evening before just meant it wasn’t very nice when I came to actually eating it.

Shop around for deals. If you have gas and electricity there are often deals where you get money off if you go with the same supplier.

Do you desperately need that new TV or will the old bulky CRT behemoth you have still do? Seriously! My parents have a really nice HD TV and quite frankly I can’t see the difference unless I’m really close up staring directly into the pixels.

Finally

I’d like to say that these are things that have worked for me.I present them as mere options. Whether they will work for you depend on your circumstances. I’m not a debt councillor nor do I want to be. You take this advice at your own risk.

Follow up on what not to develop

Back in May I wrote about a substandard website I attempted to use in an article entitled “What not to Develop”. I also sent the hotel an email at the same time telling them of the failing of their website, however, I never got a response.

When the post went live initially, I got asked on twitter to name and shame the company in question. I suppose publically decrying a company has the effect that if people start doing that then companies will be pressurised in to providing a better service or product. These days I do not to put in a blog post the name of the company in question until I’ve given them a chance to respond to any email I might have sent. I sent the email on 16 May 2009 at 17:21 (BST), I think that’s quite enough time for a response.

I’ve decided to publish some more details so that people can at least learn from the mistake and not repeat them elsewhere. Essentially, this is an extract of the email (slightly reformatted to fit this blog)

Hello,

I tried to book on your website last night and it didn’t work – it advertised a rate to me then refused to book it. I then tried to use your Contact Us page to send you a message and that also broke and said “The web site you are accessing has experienced an unexpected error. Please contact the website administrator. ”

I don’t know who the web site administrator is, but I can guess it is someone employed by TIG Global given this news story: http://www.hospitalitynet.org/news/4036652.search. Personally, if that is the quality they are delivering I wouldn’t use them again as they are not very good and are at best turning away potential customers and at worst exposing you to needless risk.

In order to [help you to] track down the errors I’ve gone back and replicated the initial problem annotating the pages as I go. You will find a number of graphics files attached.

Southwark Rose Hotel Step 1

In [the above image] I show the initial details of my availability search. Check in Friday 31st July, check out Sunday 2nd Aug. 1 adult, 0 children.

Southwark Rose Hotel Step 2

In [the above image] I show the next page. This was a pop-up, so opened a new window. The details at the top are correct and match what I’d previously entered. The description of the “Weekend Advanced Purchase” sounds perfect “Valid Friday-Sunday throughout 2009”. I see that it is £150 for the “Total price of the stay”. I press the book button.

Southwark Rose Hotel Step 3

In [the above image] I show the next page. This was another pop-up, so opened a second window. I now have 3 windows open just for your hotel. (Is this really necessary?). I spot that the number of nights has increased to 3, so I go to change it back to two. I then get an unhelpfully terse error message that says “Minimum stay: 3” [See the next image]

Southwark Rose Hotel Step 3 error

At this point I’m some what irritated by the experience so go hunting for your contact us page. I see that it is a form only without an email address. I fill in the form and when I’m ready I press the “Submit” button. At this point I get an error page back that includes the message “The following information is meant for the website developer for debugging purposes.” You might want to tell those developers that this information is also useful for attackers and they shouldn’t be displaying it to the public. If the developers were any good what they would have done is get the website to log the information internally and display a general message to the user. If they wanted to tie up a user’s experiences with what is in the log then they might also include a randomly generated (say a GUID – globally unique identifier) identifier that is put in the log and displayed so a user can refer to when explaining what problems they were having at the time.

The error message that should have never been displayed is [as follows].

Vomiting SQL for no good reason

The details in the error page also contain my original complaint. I think I now understand where the American formatting of culture specific information (e.g. dates) is coming from.The company that produced your website was American and in their arrogance just assumed everyone else was just as comfortable using MONTH/DAY/year. I suspect that same arrogance was also responsible for the other failings I’ve pointed out here.

Regards,

Colin.

So, there you are. The hotel is the Southwark Rose Hotel, and their website was produced by TIG Global. (I’ve recently noticed it actually says that at the bottom of the web pages and I need not have searched for relevant press releases!). Incidentally, you can click on any of the graphics to be taken to my Flickr account to see the full sized version.

BBC repeating mindless nonsense

I’ve just read a report from the BBC that simply repeats some mindless drivel about SQL Injection Attacks from a spokesman for the US Department of Justice. According to the BBC:

Edward Wilding, a fraud investigator, told the BBC that this method was “a pretty standard way” for fraudsters to try to access personal data.

It “exploits any vulnerability in a firewall and inserts a code to gather information,” he explained.

It, however, does not point out that Mr Wilding is incorrect. It simply regurgitates the standard patter about firewalls without question. SQL Injection attacks have absolutely nothing to do with firewalls. They are all to do with leveraging mistakes in the way the application communicates with the database. An application which already has valid rights to communicate with the database. Firewalls may be in place to stop direct access to the database, but a SQL Injection attack takes a secondary route to get there.

In short, SQL Injection Attacks are the result of poor software development practices. Something, the prevalence of which, I’ve blogged about previously. I’ve also blogged about how to reduce the attack surface of the application with respect to SQL Injection attacks. In fact, it is so mind-numbingly easy to reduce the ability for someone to launch a SQL Injection Attack on an application I’m surprised developers are still allowed to get away with it.

But back to the article:

Mr Wilding said that chip-and-pin did provide some protection against SQL attacks, but there was little consumers could do to protect themselves against this kind of fraud.

You have to be kidding me! Chip-and-pin also has nothing to do with a SQL Injection attack. It cannot protect you from one. A SQL Injection Attack is an attack on a database, not the actual physical card. All chip-and-pin can do is ensure that a person using a credit or debit card knows the pin. Chip and pin is not used in online transactions. It is not used in telephone transactions.

“The real vulnerability, I suspect, is internet and telephone transactions. But this is a failure in the configuration of [corporate] firewalls,” he said.

Back to the firewall nonsense again. I repeat that firewalls cannot protect against SQL Injection Attacks because the route to the database is a valid one via a third process. (My machine runs the first process, the database is the second process the application being attacked is the third process) However, the BBC is still blithely repeating this misattribution of blame.

If blame is to be placed anywhere then it must surely be at the door of the developers who wrote the payment system that could so easily be hacked in order to gain sufficient access to the database to get all this data. This, of course, is if you believe that it was a SQL Injection Attack. The BBC could have got that bit wrong too!

UPDATE (@ 19:30)

I’ve just noticed that the BBC have reworked the article and it was last updated an hour ago. It does now contain a side box that I didn’t see before that at least, in some small way, explains that a SQL Injection Attack are “weaknesses in companies’ programming which allows them to get behind firewalls”. The main article now contains the paragraph:

The method is believed to involve exploiting errors in programming to get behind compnay [sic]  frewall’s [sic] and accessing [sic] data.

As you can see by the spelling and grammatical mistakes it must have been rather hastily put together. One quote from Mr Wilding has also changed from being reported as:

“The real vulnerability, I suspect, is internet and telephone transactions. But this is a failure in the configuration of [corporate] firewalls,” he said.

to:

“The real vulnerability [for cardholders], I suspect, is Internet and telephone transactions using credit cards were most vulnerable, he said, though added it was a failure of corporations, not customers.

Yet again, this looks like it was hastily put together because of the poor punctuation.

Come on, BBC, this is not journalism but reactive rubbish! Do you even understand what you are actually reporting?

Recruitment Agents, eh?

Today I received an email from a recruitment agent that seems more than a little mixed up in terms of the skills required.

Dear Colin,

Are you a C#.net developer? Are you fluent in Italian? If so then I have a client that would be really interested in hearing from you.

Due to the new venture, any potential candidate would need to be an Spanish speaker ideally bilingual in Spanish. Please note the role is based in Manchester but would involve some travel to Spain.

[Emphasis mine]

In order to spare the recruiter’s blushes, I’ve removed any identifying information. Incidentally, if you are curious the pay was absolutely rubbish!

Links from ALT.NET UK Open Spaces Coding Sessions

This is a small follow up to my previous post giving an overview of the ALT.NET Conference, including Coding day and ALTNET Beers. This post is just a set of links and resources from the coding day.

Inversion of Control

“The nice thing about IoC containers is that the framework is almost not there”- @mikehadlow

Web Frameworks

“If you don’t look at code you wrote six months ago and think ‘God! That’s awful’ then you are not really progressing” – @mikehadlow