Category Archives: Rants

The Sorry State of the Web in 2016

When I republished my article “Bypassing a Login Form using SQL Injection“, it received a mixed reception. While some applauded the effort to raise awareness on bad coding practices leading to serious security vulnerabilities (which was the intent), others were shocked. Comments on the articles and on Reddit were basically variants of “That code sucks” (of course it sucks, that’s exactly what the article is trying to show) and “No one does these things any more”.

If you’ve had the luxury of believing that everybody writes proper code, then here are a few things (limited to my own personal experience) that I ran into during 2016, and in these first few days of 2017.

SQL Injection

I was filling in a form on the website of a local financial institution a few days ago, when I ran into this:

It was caused by the apostrophe in my surname which caused a syntax error in the SQL INSERT statement. The amateur who developed this website didn’t even bother to do basic validation, let alone parameterised queries which would also have safeguarded against SQL injection.

Airlines and Apostrophes

My experience with airlines is that they tend to go to the other extreme. In order to keep their websites safe, they simply ban apostrophes altogether. This is a pain in the ass when your surname actually has an apostrophe in it, and airlines stress the importance of entering your name and surname exactly as they show on your passport.

United Airlines, for instance, believe that the surname I was born with isn’t valid:

Virgin America, similarly, takes issue with my whole full name:

We’re in 2017. Even shitty Air Malta accepts apostrophes. All you need to do is use parameterised queries or a proper ORM. Using silly and generic error messages doesn’t help avoid customer frustration.

Plagiarism

Speaking of Air Malta, here’s a classic which they ripped off from some other US airline:

US Federal law? In Malta? Go home, Air Malta. You’re drunk.

Don’t Piss People Off

I’ve had a really terrible experience with booking domestic flights with US airlines. There is always some problem when it comes to paying online with a VISA.

United Airlines, for instance, only accepts payments from a specific set of countries. Malta is not on that list, and there is no “Other” option:

Delta gives a variety of billing-address-related errors depending on what you enter.

Southwest provides fields to cater for payments coming from outside the US:

And yet, you need to provide a US State, Zip Code and Billing Phone Number.

The worst offender, though, is Virgin America. While the overall experience of their AngularJS website is quite pleasant, paying online is a hair-ripping experience. If you choose a country where the State field does not apply (such as Malta, or the UK), a validation error fires in JavaScript (it doesn’t appear in the UI) and does not let you proceed:

It’s almost like the developers of this website didn’t quite test their form. Because developers normally do test their code, right? Right?

Well, when I reported the error to Virgin, and offered to provide a screenshot and steps to reproduce, the support representative gave me this canned bullshit:

“So sorry for the web error. Can recommend using one of our compatible browsers chrome or safari. Clearing your cookies and cache.  If no resolve please give reservations a ring [redacted] or international [redacted] you’ll hear a beep then silence while it transfers you to an available agent.  Thanks for reaching out.~”

I had to escalate the issue just so that I could send in the screenshot to forward to their IT department. Similarly, I was advised to complete the booking over the phone.

Over a month later, the issue is still there. It’s no wonder they want people to book via telephone. Aside from the international call rate, they charge a whooping $20 for a sales rep to book you over the phone.

Use SSL for Credit Card And Personal Details

In July 2016, I wanted to book a course from the local Lifelong Learning unit. I found that they were accepting credit card details via insecure HTTP. Ironically, free courses (not needing a credit card) could be booked over an HTTPS channel. When I told them about this, the response excuse was:

“This is the system any Maltese Government Department have been using for the past years.”

It is NOT okay (and it’s probably illegal) to transmit personal information, let alone credit card details, over an insecure channel. That information can be intercepted by unauthorised parties and leaked for the world to see, as has happened many times before thanks to large companies that didn’t take this stuff seriously.

To make matters worse, Lifelong Learning don’t accept cheques by post, so if you’re not comfortable booking online, you have to go medieval and bring yourself to their department to give them a cheque in person.

I couldn’t verify if this problem persists today, as the booking form was completely broken when I tried filling it a few days ago – I couldn’t even get to the payment screen.

Update 8th January 2017: I have now been able to reproduce this issue. The following screenshots are proof, using the Photo Editing course as an example. I nudged the form a little to the right so that it doesn’t get covered by the security popup.

Update 9th January 2017: Someone pointed out that the credit card form is actually an iframe served over HTTPS. That’s a little better, but:

  • From a security standpoint, it’s still not secure.
  • From a user experience perspective, a user has no way of knowing whether the page is secure, because the iframe’s URL is hidden and the browser does not show a padlock.
  • The other personal details (e.g. address, telephone, etc) are still transmitted unencrypted.

Do Server Side Validation

When Times of Malta launched their fancy new CMS-powered website a few years ago, they were the object of much derision. Many “premium” articles which were behind a paywall could be accessed simply by turning off JavaScript.

Nowadays, you can still access premium articles simply by opening an incognito window in your browser.

Let’s take a simple example. Here’s a letter I wrote to The Times a few years ago, which is protected by the paywall:


Back in 2014, I used to be able to access this article simply by opening it in an Incognito window. Let’s see if that still works in 2017:

Whoops, that’s the full text of the article, without paying anything!

Like those critics of my SQL injection article, you’d think that people today know that client-side validation is not enough, and that it is easy to bypass, and that its role is merely to provide better user experience and reduce unnecessary roundtrips to the server. The real validation still needs to be server-side.

Conclusion

Many people think we’re living in a golden age of technology. Web technology in particular is progressing at a breathtaking pace, and we have many more tools nowadays than we could possibly cope with.

And yet, we’re actually living in an age of terrible coding practices and ghastly user experience. With all that we’ve learned in over two decades of web development, we keep making the same silly mistakes over and over again.

I hope that those who bashed my SQL injection article will excuse me if I keep on writing beginner-level articles to raise awareness.

On Akka .NET Actor Creation

Abstract: this article is a bit of a rant about how actors are created in Akka .NET, and suggests a way of making it just a little bit more manageable. This is written based on my limited knowledge of Akka .NET, and I will be more than happy to stand corrected on the matters I write about.

Actors Need Props

Creating an ActorSystem and actors in Akka .NET is one of the most basic necessities, and it is something you’ll be doing all the time. Once you have an ActorSystem, you can create actors using an IActorRefFactory implementation (i.e. the ActorSystem itself, or an actor’s Context). This requires you to use Props.

            using (var actorSystem = ActorSystem.Create("MyActorSystem"))
            {
                var props = Props.Create<MyActor>();
                var actor = actorSystem.ActorOf(props);

                Console.ReadLine();
            }

What the hell are Props?

This is explained by Unit 1 Lesson 3 of the Petabridge Akka .NET Bootcamp. Basically, the answer is something like: it’s a recipe for creating actors, but don’t worry about it for now; we’ll use it later.

As a matter of fact, it’s needed mainly for advanced scenarios such as remote deployment and clustering. Most of the time as you’re learning to use Akka .NET, you don’t really care about them.

Creating Props

There are three ways to create Props, all involving some manner of a call to Props.Create().

The first way is to give it a Type.

var props = Props.Create(typeof(MyActor));

This is discouraged by Akka .NET, because it has no type safety and in fact lets you do stupid things like this:

akka-actorcreaton-typeof

The second way is to use a generic form:

var props = Props.Create<MyActor>();

While this is encouraged in the bootcamp, I personally discourage this. This is because while it gives you type safety over the actor type, it doesn’t give you any guarantees with the parameters:

akkanet-props-generic-2

The third way is to pass in a factory method. This is a great way to create Props because it’s the only one that lets you pass dependencies into the actor’s constructor in a type-safe manner (particularly important to use constructor injection if you’re thinking of writing tests against your actors).

var props = Props.Create(() => new MyActor());

Making It Better

In reality, most of the time I don’t care about Props. So why do I have to constantly bother about them? Actually, if we take a closer look at the third way of creating Props, we can wrap them into oblivion:

akkanet-props-expression

See that generic Expression over there? That’s what we need to avoid all this madness. Based on that, we can create a generic method to take care of everything:

    public static class IActorRefFactoryExtensionscs
    {
        /// <summary>
        /// Creates an actor, creating props based on the provided
        /// actor factory method.
        /// </summary>
        /// <typeparam name="T">The actor type.</typeparam>
        /// <param name="actorRefFactory">ActorSystem or actor Context.</param>
        /// <param name="actorFactory">Actor factory method.</param>
        public static IActorRef CreateActor<T>(this IActorRefFactory actorRefFactory,
            Expression<Func<T>> actorFactory) where T : ActorBase
        {
            var props = Props.Create(actorFactory);
            var actor = actorRefFactory.ActorOf(props);
            return actor;
        }
    }

To create an actor directly from the ActorSystem, we now only need to do this:

var actor = actorSystem.CreateActor(() => new MyActor());

…and to do it from inside an actor, it’s just as easy:

var actor = Context.CreateActor(() => new MyActor());

Weird Conventions

This is where the rant begins.

Apart from all the weirdness associated with having to deal with Props in the first place, Unit 1 Lesson 3 of the Petabridge Akka .NET Bootcamp has this little gem that makes my day brighter every time I read it:

How do I make Props?

“Before we tell you how to make Props, let me tell you what NOT to do.

DO NOT TRY TO MAKE PROPS BY CALLING new Props(...). Similar to trying to make an actor by calling new MyActorClass(), this is fighting the framework and not letting Akka’s ActorSystem do its work under the hood to provide safe guarantees about actor restarts and lifecycle management.”

Here’s a similar gem from Unit 1 Lesson 1:

NOTE: When creating Props, ActorSystem, or ActorRef you will very rarely see the new keyword. These objects must be created through the factory methods built into Akka.NET. If you’re using new you might be making a mistake.”

Wait, what? These guys are telling us to call static Create() methods rather than using constructors. These are the same people who told us that using async/await in actors is bad (which has since been corrected). I don’t know, but I bet if you ask anyone who has done OOP before, they’ll tell you that if there’s a mistake, it’s in Akka .NET’s design.

But to really top it all, check out the following comment from Aaron Standard (Petabridge CTO and Akka .NET co-founder) on the Reddit thread about one of his articles (emphasis mine):

Orleans is a piss-poor implementation of the Actor model and breaks a lot of the conventions that make it powerful, aside from having an overall hideous set of programming conventions. But because MSFT released it, people will flock to it like lemmings.

“We’re going to keep working on Akka.NET because there’s a community supporting it now and because we believe in TypeSafe’s vision for actor systems.”

A case of the pot calling the kettle black? Or quoting Confucius, “Don’t complain about the snow on your neighbor’s roof when your own doorstep is unclean.”

In any case, my goal is not to start a flame war but to understand why the Akka .NET API (and codebase) is such a mess. If you look at the source code for ActorSystem, for instance, it does not do anything so particularly complicated that would justify banning constructor calls. In fact, the call to ActorSystem.Create() ends up here:

        private static ActorSystem CreateAndStartSystem(string name, Config withFallback)
        {
            var system = new ActorSystemImpl(name, withFallback);
            system.Start();
            return system;
        }

In fact, although you shouldn’t do this, this code works just as well as what we had before:

            using (var actorSystem = new ActorSystemImpl("MyActorSystem"))
            {
                actorSystem.Start();

                var actor = actorSystem.CreateActor(() => new MyActor());

                Console.ReadLine();
            }

Why is this even public such that I can call it?

Conclusion

The API provided by Akka .NET, particular in ActorSystem and actor creation, is very strange indeed. We are discouraged to do something as trivial a calling a constructor, and have to deal with Props even though we won’t need them most of the time. It is hard to speculate on why this API was written this way without having the developers provide insight on it.

At the very least, aside from pointing out these obvious flaws, this article aims to suggest best practices on how to go about creating Props, and to provide an extension method to hide the existence of Props for the majority of cases where using them directly isn’t really necessary.

Lessons Learned from the Patreon Security Breach

Patreon is a popular crowdfunding platform, providing “recurring funding for artists and creators”. I was considering using it myself. I’m glad I didn’t.

Almost two months ago, Patreon suffered a security breach, and several gigabytes of data including a copy of their production database and their source code were leaked on the internet. An article at Ars Technica covers some of the details of the breach.

As I read the press release from Patreon about this incident, my feeling was of utter disbelief, particularly when reading these two points (emphasis mine):

  • “The unauthorized access was confirmed to have taken place on September 28th via a debug version of our website that was visible to the public. Once we identified this, we shut down the server and moved all of our non-production servers behind our firewall.
  • “There was no unauthorized access of our production servers. The development server included a snapshot of our production database, which included encrypted data.”

I’m not sure whether I need to explain why having your development environment publicly accessible, and why using production data in your development environment, are both very stupid things to do. Either way, now I don’t need to explain that. What happened to Patreon shows exactly why no one in his right state of mind would do this.

Further down, Jack Conte, CEO/Co-founder of Patreon, writes:

“I take our creators’ and patrons’ privacy very seriously.”

Sorry, but given what happened here, I find that very hard to believe. It doesn’t matter what steps are being taken to increase security. It’s already too late. People’s private data are now on the internet, and there’s no going back.

So if you want to spare your company a lot of embarrassment, here’s what you need to take away from this incident:

  • Keep your development environment isolated from your production environment.
  • Use dummy data, not production data, in your development environment.

An Overview of Air Malta’s Customer Service

Introduction

Just a few days ago, Air Malta was voted 6th Best Regional Airline in Europe, measured based on customer satisfaction. And as an irate former customer of Air Malta who has experienced a terrible customer experience just a few weeks ago, this really makes me wonder under which rock people are living. Just the day before, another story appeared in which a cellist lost her cello’s seat because of an overbooking.

This article deals with my own bad customer experience with Air Malta, due to being stranded in Budapest towards the end of June 2015. However, it also mentions other incidents which give a deeper illustration of Air Malta’s customer service.

Summary

  • We were meant to fly from Budapest to Malta on 29th June 2015.
  • Due to a technical fault, a smaller plane was used, leaving many passengers stranded in Budapest.
  • We spent 7 hours at the airport.
  • Air Malta never communicated with us directly.
  • We missed all replacement flights for the day since Air Malta took ages to confirm our seats.
  • Budapest airport staff claimed that Air Malta was uncooperative and refused to pay for the overnight accommodation.
  • When we claimed compensation (due by EU law), Air Malta agreed only on condition that we sign an agreement which, among other things, forces us to keep the settlement confidential.
  • Other past incidents show how Air Malta knows nothing about customer service.

Seven Hours at the Airport

On 29th June 2015, I went to Budapest airport with my friends to catch the Air Malta flight back to Malta. Shortly after arriving, we learned from the flight schedule board at the terminal that the flight was being delayed by two hours. We thought nothing of it at the time, as there was still plenty of time to get back to Malta in the evening.

However, things looked a lot more grim as we joined the checkin queue. This queue was at a standstill for quite a long time, with passengers and airport staff alike shuffling back and forth. We eventually learned that the aeroplane suffered some kind of technical fault, and that a smaller one was being sent as a replacement, which meant that not everybody would fit. Some people were rerouted via other flights.

Over the span of the next few hours, airport staff struggled to deal with Air Malta in order to get a replacement flight. Time after time, they brought up our hopes, saying there was another flight we could take – only to bring those hopes back down when we realised that Air Malta had failed to confirm our places on those flights in time.

Once we missed the last flight, via Brussels, we resigned ourselves to the fate of spending an extra night in Budapest. Budapest is a lovely place, but many of us had to go to work the next day, and others would miss a day from their holiday in Malta. At that point, we told the airport staff that we understood there was nothing more that could be done, and that we’d appreciate being settled in a hotel as soon as possible. Spending seven hours in an airport is not fun.

The airport staff apparently tried to get hold of Air Malta to get the accommodation, dinner and transfer booked, but more time went by and we remained at the airport. In the end, the airport pretty much gave up on Air Malta and arranged for everything on their own initiative. In all this time, we never heard anything from Air Malta directly.

On Compensation

During our seven-hour ordeal at Budapest airport, we had already educated ourselves – using intermittent WiFi access that didn’t work most of the time – about our rights under the circumstances. EU law [PDF] entitled us to at least EUR250 plus food expenses. We didn’t count the dinner and accommodation of course, because the airport covered those. But we did incur additional expenses due to this mess, including:

  • Mobile expenses. This is difficult to quantify since Vodafone charge EUR3, and Go want EUR12 and an affidavit, in order to provide a breakdown of charges.
  • Lost day of work. The cost of this varies from person to person.

The EUR250 worth of compensation is not a very fair deal, to be honest. The value of compensation depends mainly on distance, and not on duration (as long as it’s more than 3 hours). So technically, if you’re delayed for 3 hours, 1 day, or a week, you get the same compensation. That can’t possibly make up for a lost day of work.

Also, having such a low compensation fee makes it worthwhile for unscrupulous airlines such as Air Malta to exploit the practice of overbookings (more on this later).

Clarifications and Settlement

One of my friends and fellow passengers wrote to Air Malta on behalf of 8 of the people who spent the extra night at Budapest, requesting compensation. Aside from requesting compensation for the 8 people, the email also asked for clarifications on why we were neglected as described earlier in this article.

Air Malta replied as follows (emphasis mine):

“First of all, we would like to apologise for all the inconvenience caused with reference to the flight you had with us. Although Air Malta tries to offer the best possible service, there are instances that the service given is not in accordance to the passengers’ expectation. In this case, the flight was overbooked and we had to reroute several passengers from the direct flight to other connections available.

We had problems with communicating with the handling agents in Budapest, and we tried to accomodate all the passengers to fly the same day. In fact, some of the passengers who were denied boarding flew via Munich or Athens, and we tried to reroute the others via Brussels. We already had made the necessary changes, however, due to several reasons, the check-in for the flight from Budapest to Brussels closed soon before the passengers could arrive to board.

“Air Malta made it clear that any hotel accomodation, transport and meals required for the passengers, can be refunded, and we never delayed or declined to offer such convenience, as stated in your email. However, as we said beforehand, we had an ongoing miscommunication with our handlers in Budapest, and this caused a lot of confusion and misinformation to the passengers.”

However, they agreed to pay the EUR250 plus food expenses, if we provide our bank details (necessary to transfer the refund) and sign a form (emphasis mine):

“In light of the above, to cover any inconvenience this mishap has caused all of the passengers that were denied boarding, we are offering the amount of €250 each, as per EU Law. Moreover, passengers that were denied boarding can send us the receipts of any meals that they had to buy for their extra stay by mail on the address in the signatory, in order to give the refund of such. Kindly fill in individually the Release and the ex-Gratia Form in order to provide you the amount stated (Reference and PNR listed above), and send them back as a reply to his email by not later than the 17th July 2015.”

The Release form, among other things, included the following (emphasis mine):

“1. The Releasor accepts the sum of EUR TWO HUNDRED AND FIFTY (€250.00) from the Releasees without admission of liability in full and final settlement of all claims for damages, interest, costs or expenses whether past, present or future and whether ascertained or unascertained, which the Releasor may have against the Releasees howsoever arising out of the matters recited above.

2. In consideration or receipt of the said sum Releasor:-

[…]

“(e) undertakes and warrants that he/she (as applicable) will keep this Release and Discharge and settlement recorded in it confidential, and will not disclose such information to any other person or entity (unless required by law to do so or for purposes of taking legal advice).”

So basically they were telling us that, in order to provide us compensation required by EU law, we would have to keep the settlement secret, accept it as final settlement, and sign it within a specified deadline. But more on that later.

My friend, who initiated the communication with Air Malta, followed up, asking for clarification about the use of the word “overbooked” in Air Malta’s email, and highlighting the fact that the airline should have made contact with us (as it is required to do by EU law), especially in the context of “miscommunication” with the airport.

In their subsequent reply, Air Malta explained their interpretation of their earlier use of the word “overbooking”:

“The reason why there was an overbooking is because there was a technical problem, and the aircraft had to be changed in order to avoid any further delays. In fact, instead of the A320, as previously scheduled, the A319 was used for the flight Budapest to Malta, leaving some passengers stranded.”

Conditions for Settlement

The settlement (EUR250 + food) offered was the least Air Malta could offer us. It was required by law, and at the same time did not cover other expenses (e.g. lost day of work) that resulted from this undesirable experience. Nonetheless, I sent Air Malta my bank details for the refund. However, I did not sign the Release Form, which required me among other things to keep the settlement confidential. You see, after being abandoned in Budapest airport like that, imposing conditions and deadlines to give me the least required by EU law felt like a kick in the nuts. It’s a bit like saying “I’ll give you what I owe you, but only if you get down on your knees.” So I wrote as follows:

“Please note that I am not including the Release Form. Under EU law, you are bound to compensate us for the denied boarding, and you have no right to place additional obligations or deadlines.”

They insisted that I sign the Release Form, and made it clear that they would only provide compensation if I complied.

I refused to sign the agreement given the conditions, and threatened to sue them.

Following that, they refused to provide the compensation unless I sign the form, with the excuse that it is a company requirement in order to process refunds.

I replied that their company requirements are irrelevant, because they are obliged by EU law to provide the compensation. That is where I decided to take the matter to the authorities.

The Air Passenger Rights section within the Malta Competition and Consumer Affairs Authority, which is the national authority that deals with consumer complaints, received my complaint. They made it clear that the airline have no right to impose conditions or deadlines to give compensation due by law. Quite the opposite: this compensation does not preclude further action to secure additional compensation – something that I would have renounced, had I signed the Release Form.

Facebook Denial

A few days ago, seeing the introduction of Air Malta’s “Sky Spa” free in-flight massage treatment, I wrote on their Facebook page:

air-malta-facebook-reply

It’s funny how “overbooking” appears again in this context – presumably because it’s so common that it’s one of the primary causes of customer complaints that the airline’s customer service department (if you can call it that) is well-experienced at handling.

But it’s also worrying that in this comment, Air Malta seem to not know anything about the incident. They may either be lying, or else their IT system is in such a complete mess that they are unable to retrieve historical flight data from it.

While I obviously cannot know which of these is actually the case, the latter is not too far-fetched. In fact, a friend of mine recently told me about a problem he had with Air Malta’s customer service. Although he uses their services regularly, the flights he took did not appear under his account on their website. When he reported the problem, instead of retrieving the data from their database, they asked him to produce evidence that he had taken those flights.

As if this wasn’t enough, another friend of mine reported similar conditions when reactivating his Flypass. Quoting Air Malta’s Flypass Terms and Conditions:

“Any closed Flypass account cannot be reactivated unless passenger proves that he/ she has flown at least four scheduled flights within the six months` period preceding his/ her request. The four boarding passes need to be forwarded to Flypass Unit and KMiles for these four flights only will be credited retroactively.”

On Overbookings

We’ve seen earlier how Air Malta used the word “overbooking” quite freely (even though overbooking had nothing to do with the Budapest incident). This is pretty ironic, because it is easy to find evidence of actual overbookings that Air Malta has been responsible for in the past, such as this one in Athens in 2013, and this one in Verona in 2010.

If these incidents sound like they happened a long time ago, check out the recent incident with the cello’s seat, clearly due to an overbooking according to Air Malta’s own words:

cellist-overbooking-fb

This is actually not very different from how Air Malta explained and justified the overbookings in the Athens 2013 article:

“”Overbooking is a normal occurrence in the airline industry and not particular to Air Malta. The reason why airlines overbook flights is due to ‘no-shows’ when people book on a flight and fail to show up at the check-in desks. Unfortunately seats blocked for booked passengers who fail to show up remain empty when the flight departs,” an airline spokesman said.

“These unutilised seats may be required by other travellers. In fact, flights which are not overbooked may result in many prospective passengers being denied an opportunity to fly on seats which would otherwise be unused, the airline said. Air Malta has a very low rate of denied boarding compared to the industry as a whole.”

So what they’re saying here is that they allow extra seats to be purchased, because if someone doesn’t show up, they can sell his seat to someone else. But if the person who doesn’t show up paid for the seat, what gives the airline the right to sell it to someone else, making double the money from a single seat? How is this even legal?

Also, the ridiculous compensation schemes we have make this practice very viable. At best, the airline would have sold two seats for the cost of one, and at worst, it would have sold that seat and compensated the person who was denied boarding, leaving that passenger more or less where he started financially, but with a great inconvenience.

If overbooking is a standard practice in the airline industry, it doesn’t mean all airlines do it. Ryanair, the low-cost airline frowned upon for many other reasons, “does not overbook its flights” [PDF], something that has been confirmed by a Which? investigation.

Similar Incident in 2008

After I explained my ordeal in Budapest, a friend of mine reached out and recounted a similar experience he had in Milan in 2008. He was informed in the morning that his 3pm flight was to be delayed by 3 hours. Despite this, he spent until 3am at the airport; no one communicated with him at the time, there was no Air Malta representative, and the airport staff knew nothing about the flight. Although he asked for compensation, he was never granted any.

Conclusion

Air Malta’s customer service is simply terrible, and the authorities will decide whether it is also illegal. My advice is thus: don’t fly with Air Malta, even if the ticket is free.

Even when flying with other airlines, know your rights. If your airline refuses compensation or imposes conditions, you have other means at your disposal to claim what is yours by right. It might take a little longer, but we can’t let the airlines keep treating us like dirt because they think we’re too afraid or apathetic to pursue them legally.

Bluehost Ripping Off Customers

I’ve been running websites for almost 13 years (since 2002). For the past 8 years (since 2007), I’ve hosted my websites at Bluehost. Last month, I decided to switch to a different provider. Here’s why.

Different pricing for renewals

Bluehost lure their customers with seemingly low rates for hosting and domains, making full use of the elusive asterisk.

bluehost-asterisk

If you follow that asterisk to the bottom of the page, you’ll find some fine print saying that this fancy price applies for the first year only:

bluehost-asterisk-2

To see how much you’d really pay, check out the hosting prices and the domain prices.

At the time of writing, you can expect to pay the following rates after your first year:

bluehost-hosting-prices

At the time of writing, the domain prices are the following (excerpt):

bluehost-domain-pricing

So a renewal for a .com domain, including privacy, is going to set you back $27.87. And you’ll be paying $4 more than you did when you bought it the first time.

Sudden price increases (domains)

Bluehost tend to increase their prices without informing their customers. With domains, I saw this happen over a number of years.

  • From 2007 – 2010, a domain cost $10.
  • In 2010, I was charged $4.95 extra for domain privacy. I opted out of it and didn’t pay for privacy again.
  • Around mid-2011, I was charged an extra $1.80 in taxes. Fine.
  • By end-2011, I was paying $14.10 ($11.95 for the domain and $2.15 in taxes). The tax thing eventually got resolved, and I continued paying $11.95 for my domains until around mid-2012.
  • In August 2012, I was charged $13.99 for a renewal, and in November 2012, I was charged $11.99 for a new domain.
  • From August 2013 until today, I’ve been paying $14.99 for domain renewals.
  • In October 2014, adding domain privacy cost me $9.99.

Noticing this fishy business a few years back, I wrote to Bluehost support on 10th February 2013:

Hi,

Since when are domains being charged at $13.99? Over the past couple of years I’ve been charged different prices for domains including $10.00, $11.95, $11.99, and $13.99.

What is going on?

They replied:

Hello,
To purchase a domain it is $11.99. To renew it is $13.99. That is why you are being charged different prices for purchase and renewal.

Sudden price increases (hosting)

That was just for domains. Let’s see how hosting evolved over the years.

  • In 2007, I paid $166.80 for hosting – that’s $6.95 per month for 24 months.
  • In 2009, I paid another $250.20 – that’s $6.95 per month for 36 months. It might seem to be the same price, but I actually had to pay for an extra year to remain within the same price. If I remember correctly, buying a 2-year term would have cost $7.95 per month.
  • In 2012, I had another renewal. I don’t have any email records for this one, so presumably it remained the same.
  • On 14th May 2015, I received an email which was a bit of a shock:

bluehost-hosting-ripoff

So these guys suddenly decided to increase my fee from $6.95 to $9.99 per month, and actually had the nerve to tell me that I was saving money. I only learned about this because my next renewal was drawing near – Bluehost don’t bother to inform their customers about these changes.

Furious, I wrote to their support department:

Hi,

I just got an email saying that my web hosting will be renewing soon, and that I’ll be paying $9.99/mo. What is this about? I thought I was paying something like $6.99.
And you even have the nerve to say I’m saving $180?
I’m feeling cheated, and I expect an immediate explanation.

Their reply was thus:

Hello,
Our hosting renewal rates increased recently due to significant upgrades that have been made to our servers and the services we provide. This price increase will also allow us to continue investing in the best technology to make our hosting services even better.

Because of this price increase, apart from better performance and reliability of your account, the Plus hosting package which you are currently on now offers spam experts and cloudflare at no charge for one domain name.

Spam experts is an email filtering addon that helps to block and remove unwanted spam and dangerous emails that may cause problems with your webmail accounts.

cloudflare is a content distribution network that, when activated for your domain, distributes your website’s static information across servers around the globe, thus increasing download speed, performance, and security of your website.

I would also love to look over your account and see if you are a fit for our starter package to save you some money.
Please respond with Domain name and last four of the main account password so we can further assist you.

Sick of this bullshit, I wrote just what I thought at the time:

Hi,

Your “significant upgrades” are insignificant to me. The new features mean nothing to me, as does your marketing attitude, because I never agreed to pay extra for these new features (not to mention the ever-increasing renewal costs for domains). And the least you could have done was to inform me in advance of the price increase.
Guess what: there exist companies that thrive by NOT ripping off their customers. And I’m moving on to one of those.

Their next reply seemed to ignore the fact that I was done with them, and involved a proposal of sorts:

Hello,

Thank you for your email and apology for the inconvenience caused.

In starter package you can host one main domain and five parked domain. You have one addon domain in your account. In order to downgrade your account to starter package please unassign or park your addon domain. Once the domain is unassigned please get back to us. So that we will downgrade the package to starter plan .

Renewal rates for Starter plan:

1 month  $7.99/mo
> 3 months $7.99/mo (billed at $23.97)
> 6 months $7.99/mo (billed at $47.94)
> 1 year   $7.49/mo   (billed at $89.88)
> 2 years  $6.99/mo (billed at $167.76)
> 3 years  $5.99/mo (billed at $215.64)

We will be happy to assist you with a term-change if another term-length or hosting plan better fits your needs. Please get back to us with following:

The plan and term length you would like to change to.
The last four case-sensitive characters of the main login password.
The last four digits of the credit card used for the most recent hosting payment.

Please let us know if you have any question.

So it came to this: either pay a lot more for the same service, or pay roughly the same and get downgraded.

Conclusion

I moved away from Bluehost because their costs are ridiculous, and they increase substantially almost every year without warning. For instance, my current web hosting provider charges just $9.95 for a domain (whether it’s a new one or a renewal) and privacy is included.

They quite clearly run their business by ripping off their customers, and provide only lame excuses.

3 Stupid Article Title Patterns

If you use social media (e.g. Facebook) a lot, you’ll notice that your friends probably share a lot of crap, ranging from Farmville invitations to ‘inspirational’ (*cough*) articles. Over the years, you probably noticed that a lot of the articles they share seem to follow a small set of clichéd patterns. Here are three particular ones I’ve come across.

1. n Things

stupidtitles-nthings

Look at the image above. The article itself and the majority of the ones linked on the side follow the same pattern: “6 Reasons…”, “5 Things”, etc. In fact, I deliberately used such a pattern even for this article, to help get the message across.

An “n Things” article is typically little more than a random list of items, often based on the author’s limited experience and viewpoint rather than on any relevant sources. There is no particular structure in such articles. In fact, even the numbering itself is misleading: these articles often list items in no particular order. This is in stark contrast with factual news articles which use the inverted pyramid as a model to present information progressively in descending order of importance.

stupidtitles-topn

A variant of this is the “Top n” article, such as “Top 10 places to visit in Dublin”. In this case there really is an ordering. However, it’s not always quite reliable. If it’s some top 10 list on someone’s blog, then that’s just the (only?) 10 places he happened to visit. Some more reputable sites might refer to some actual statistics, but the criteria used to evaluate the items and come up with a ranking are usually quite debatable.

2. Questions

stupidtitles-question

I’m not the first person to feel uneasy whenever I see a title that ends in a question mark. In fact, Betteridge’s Law of Headlines states that:

“Any headline which ends in a question mark can be answered by the word no.”

Again quoting the above-linked Wikipedia article, Betteridge was quoted thusly about a particular article:

“This story is a great demonstration of my maxim that any headline which ends in a question mark can be answered by the word “no.” The reason why journalists use that style of headline is that they know the story is probably bullshit, and don’t actually have the sources and facts to back it up, but still want to run it.”

I don’t think this requires further elaboration.

3. Future Predictors

stupidtitles-predictors

Articles that contain the word “Will” are usually one of two types. If they end in a question mark, then refer to Betteridge’s Law above. If they don’t, then they’re making some kind of grand statement about how things will be in the future.

You might think that people writing such articles have been blessed with the gift of prophecy. More often than not, however, they have no idea what they are talking about. Such articles tend to make grand claims about the future, either depicting some sort of utopia or scaremongering on the bleakness that is to come. But in reality, nobody knows what will happen in the future, and the people who write these kinds of articles are usually not among the few who might be able to make educated guesses about what will happen.

Not convinced? Check out the comments for the above Slashdot article.