Tomcat, Solr And Special Characters

If Solr does not return any results when looking for words with special characters, this post could explain why.

Solr's example schema.xml comes with the charFilter element to map special chars to their ASCII equivalents. Look for the following in the "index" and "query" section of the solr.TextField class:

<charFilter class="solr.MappingCharFilterFactory" mapping="mapping-ISOLatin1Accent.txt"/>

You can open the mapping-ISOLatin1Accent.txt file to see what gets mapped to what.

What often gets overlooked is that Tomcat, which takes the search request URI, also has to properly encode those special characters or they'll end up like gibberish when it reaches Solr. This is simple to do. The URIEncoding="UTF-8" attribute needs to be added to the Connector element in Tomcat's conf/server.xml

It is not part of a standard Tomcat installation, which is what most people use when setting up Solr.

This is what the Connector should look like:

<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" />

Now, when looking for "bacteriën" (bacteria) or "financiën" (finance) Tomcat won't mess up the 'ë', Solr will properly map them and look for "bacterien" and "financien".

At the time of this writing, a patch for this issue just got applied to Solr 4.1 which will take care of the encoding for us. It will ask the HTTPRequest for its character encoding and convert it correctly.

Ten Things I Wish Apple Does In 2013

2012 seems to have been all about the hardware at Apple. Retina displays on 2 new 10" iPads, iPad mini (magnificent device), retina displays on newly designed 13" and 15" MacBook Pros, complete overhaul of the range of iPods, a superb iPhone 5 and a drastically less voluminous iMac.

Apple knows the hardware department is top-notch, they're doing great things, nothing needs to change. They don't need to redesign anything and 4 years down the line their devices will still look the best. The problem lies with the software side of things. Things don't "just work" anymore.

Things don't just work anymore and that's understandable. Today's software-world is many times more complex than it was in 2004. Computing has changed. The era of the single desktop computer in a family's home, without any cloud integration, has passed.

Nowadays we have multiple devices each. Kids have their own notebooks for schoolwork, they are given iPads as entertainment devices, as they get older they get smartphones and their parents could very well be reading books on their own iPads once the kids are put to bed.

Together with the shift to multiple devices Apple has also pushed the digital consumption to all of those devices. We expect all our content to be available everywhere, all the time. In a world where not all devices are constantly online this creates technical problems. Apple's trying its hardest to get its iCloud infrastructure to keep it all in sync but there's work left to be done.

As 2012 was the year of hardware, I hope Apple does nothing but improve its software in 2013. Here is what I feel really needs to be addressed:

  1. Unify Apple IDs and iCloud IDs.
    Provide a way to merge the two IDs and stop the dichotomy between the two. There are people backing up things on their iPhones to iCloud with a different login than the one they buy content with on the Apple Store. It is a mess and it needs to be fixed.

  2. Gives us back our @mac.com / @me.com / @icloud.com e-mail address.
    Long-time Apple users will feel the same. Those who've had @mac.com e-mail addresses but refused to pay for Apple's abysmal service during the .Mac and MobileMe years never got their @mac.com e-mail addresses back once iCloud rolled around the corner. Moreover, they can't opt to have iCloud e-mail because the <first part>@icloud.com is already taken by their own <first part>@mac.com Apple ID of old.

  3. Make iMessage work.
    In the previous blog post I've written about it in great length: iMessage does not work well enough. It fails to deliver messages to iPhone when the user you are addressing has an iPad within Wi-Fi range, but he himself is currently somewhere without a data connection. iMessage does not fall back to sending a text message once 1 device has been found. When iMessaging, you primarily target someone's phone. It should arrive at the phone at all times.

  4. Make iMessage more sentient.
    Currently when I'm chatting to someone via iMessage from the computer my iPhone is going berserk. Do the way Google does it and don't make the phone buzz when iCloud knows you're chatting from the computer. Set a 5 or 10 minute timeout after the last-received message before an iPhone can buzz again.

  5. Update Maps POIs.
    Apple Maps is great. It is beautiful, it's easy to use, it works on the home-screen, it gives good directions. It gives them to the wrong destination. Apple's Maps app is great, there's not a wrong street on it, but it's their (Yelp's) POI data which is incredibly inaccurate. It is so bad it becomes unusable. Get rid of Yelp or do a major effort to update it, world-wide. Because I see gas stations where there aren't any at all, I see hotels 3 blocks from where they actually are, I see shops on the wrong side of the road... Nothing is accurate. I'd say that's OK for the POIs around where you live, because you know better... But you use POIs when you're somewhere you've never been before. People fully rely on this information when it is all they have. I've been updating POIs in my neighbourhood for 6 months, not one has changed.

  6. Sync "Do Not Disturb" via iCloud.
    When someone doesn't want to be disturbed, one could assume he doesn't want to be disturbed on any of his devices. Sync this switching on and off of the "Do Not Disturb" setting between all devices registered with the same iCloud ID. No-one feels like switching to "Do Not Disturb" mode on three seperate devices every night before going to bed. The same goes for "Airplane Mode".

  7. Make iCloud work for movies outside USA. (Update: Apple added this on 2013-02-27)
    This one's easy. When you're not in the USA, deleting a purchased movie from iTunes will delete it forever. It does not work the way music does outside of the United States. If it doesn't, then why does iTunes tells us: "Your movie purchases in iCloud will also appear whenever you're signed into the iTunes Store." Clearly it doesn't. Your movie purchase will not appear once you've deleted it. There is no re-downloading movies.

  8. Update iWork. (Update: Apple released iWork '13 on 2013-10-22)
    iWork dates back to January 2009. That's 4 years. That's older than most people's computers. It's seriously lagging behind in functionality. You only need one example: it still has a separate window for Search & Replace. Enough said.

  9. Remove excessive skeuomorphism. (Update: Apple released iOS 7 on 2013-09-18)
    Skeuomorphism is a good thing. Windows 8 looks too stark. But in iOS and OS X it has been overdone. iBooks is ridiculous, and it's telling that in an update Apple added the option to remove the book artefacts around pages. The calendar is ridiculous as well and we don't need shredding animations when deleting a Passbook ticket. Skeuomorph icons are a good idea because we do need to quickly recognize objects as address books and calendars, but the applications don't have to function like their physical instantiations.

  10. Update some OS X behaviour.
    When cmd+tabbing to Finder and no Finder window is open, or if it is minimised, show it anyway. I know it might not adhere to OS X's window-model but it's been an annoyance for years, especially for people switching away from Windows. Do not make us stare like fools at our desktop where seemingly nothing happened other than then menubar changing to "Finder". Just open a new Finder window, OK?
    On the same topic, get rid of the buttons to minimise and zoom windows. Zooming has not been doing what people have been expecting it to be doing for years. The people who "get" the zoom button are so few that they won't mourn its removal. Declutter the UI and get rid of zoom. You either drag the window out to your preferred dimensions or you go full-screen. No "zooming".
    Get rid of the minimise button as well, or find a way to make it "just work". Why introduce a preference to minimise windows in their Dock icons when it's almost impossible to get them back? It is very unintuitive. People need to hit F3 for Mission Control and see their windows. If there are any minimised, show them below the line like it was in previous OS X versions.

There you have it, my wish list of things Apple needs to address in order to reinstate the confidence its customers should have when using their products. I could have added more but ten things is enough. Let's hope they find their way to this page. Let's make things just work.

"Delivered" — iMessage's Problem

An iMessage, sent to someone who owns an iPhone, that can not be delivered to that iPhone, can never be "Delivered".

My wife inherited my old iPhone 3GS when I got the iPhone 5. She wasn't with a sanctioned iPhone operator in Belgium so she didn't get the APN settings OTA. I didn't think of checking them and setting them manually. So, she did not have an active data connection to her phone when she was out of the house.

We set up Messages at home when she was on Wi-Fi and Apple recognised her number as being linked to her Apple ID. Or is it iCloud ID? That dichotomy's another story... Now, when I started sending her texts they never reached her because during the day she is not at home, and Apple's servers couldn't connect to her phone.

Yet, whenever I text her Messages.app said the message was "Delivered". It got delivered alright, to her iPad that was lying at home, connected to our Wi-Fi network.

The reason must be that Apple's servers check for any device registered for receiving iMessages with the receiver's Apple ID. When it can reach one device it sends the message through and responds success to the sender. The sender has no idea to which devices the message arrived, all he gets to see is "Delivered".

Usually, when people send texts they mean to reach someone's phone. That's their primary target. If iCloud can sync it to iPads, iPods and Macs that's great but the phone remains most important.

With the above in mind (someone who has an unreachable phone but another device which can be reached) three situations can occur, one of which can be easily remedied, one is a bit harder and one where nothing can be done.

  1. Sending from iPhone. Apple should check the devices registered with the recipient's Apple ID, if it can reach the iPad but it can not reach the iPhone it should send the iPad message as per usual but also fall back to sending an SMS to the unreachable iPhone. Currently it does not fallback to SMS as soon as another non-iPhone device can be reached.
  2. Not sending from iPhone, but the sender has an iPhone. Apple should check the devices registered with the recipient's Apple ID, if one of them is a non-reachable iPhone it should then check whether the sender has a (reachable-via-data-connection) iPhone registered to his Apple ID. If so, then Apple can contact the iPhone and have it send an SMS to the recipient's phone to make sure the text gets delivered. Only if the sender has the fallback-to-SMS setting turned on of course.
  3. Not sending from iPhone and the sender has no iPhone. There is no way the message can be delivered to the non-reachable iPhone. I assume Apple does not have SMS servers in every country to make this happen on their behalf instead of using the sender's iPhone. But then it should not say "Delivered". It could say "Delivery failed." and show a popup with more info.

Solving situation 1 and 2 would help Apple get back on track with their "It just works" meme. It's a technical challenge, trying to get texts delivered any way they can. It's a interesting problem to solve. And when solved it would be magic. The user does not need to know how. It should just work.

Situation 3 would occur less frequently I think. People who don't have iPhones are less inclined to use iMessage.

With all of Apple's new services and software in the past couple of years... it has come to a point where a lot does not "It just works" anymore. More articles like this one will get written until they start fixing their software. Apple's hardware is drastically improving, their software department has been lacking.

I hope Apple will devote 2013 to doing nothing else but making things just work again.
Like it used to be.

Mastering MAMP's Metadata-Munching MySQL

Since this post ran a bit long I've included a TL;DR section.

The Problem

MAMP's MysQL uses a shared InnoDB file "ibdata1" which grows over time and never shrinks. Not even when dropping databases. All the metadata and indices for all databases stay in there forever.

The Solution

Tell MySQL to store medata and indices in separate files per database.

  1. Dump all databases in files and drop the databases.
  2. Delete ibdata1, ib_logfile0 and ib_logfile1.
  3. Add innodb_file_per_table to the [mysqld] section of /etc/my.cnf
  4. Restart MySQL and reimport the dumped databases.

The Article

Recently I had to import a MySQL dump of 9GB resulting in a database of 21GB. I didn't have enough space on my hard drive and after continuously deleting applications and music as the import went on I realised I wouldn't make it. I aborted the process and dropped the partial database. Funnily enough I noticed I didn't get all my space back. After a little scooting around on the file system I understood something I had been suspecting for a while already. MAMP's default MySQL settings suck.

jeroen@liver:/Applications/MAMP/db/mysql$ ls -hl | grep ibdata1
-rw-rw---- 1 jeroen admin 14G Nov 4 16:25 ibdata1

I've always been slightly opposed to using MAMP for serious work but the company I work for uses it and their setup scripts expect folder layouts the way MAMP sets them up. Now, after a year of using MAMP on a 128GB MacBook Air I saw the shared InnoDB file MySQL uses had grown to 14GB. That is a lot of wasted space.

Why is it wasted space you might ask? Surely MySQL needs it for something. Yes, MySQL needs it. It stores the _current_ database-indices in there as well as the metadata for them, you can even restore whole databases, after having dropped them, from this InnoDB data file. But, it also stores all that information for databases you have already dropped. See, MySQL's ibdata1 file never shrinks, it only grows.

As a web developer working with Drupal for about a year now, one of the things I do a lot is importing databases of ongoing projects, dropping them when I screw up and reimporting a backup to try again. Therefore I bet not too many web-developers know about MAMP's hungry MySQL or I would've heard about it earlier.

There is a solution and it is called innodb_file_per_table. When you put this in the MySQL configuration file it tells MySQL to store the metadata and indices for each database in a separate file within that database's folder. Then, when you drop a database and MySQL deletes the folder it will also remove the metadata files.

If you're wondering where you can find the MySQL config file your best guess is /etc/my.cnf unless of course you're using MAMP because it just starts MySQL with any meaningful parameters, neither does it install a my.cnf anywhere MySQL looks for one. (More info here: http://bensch.be/mysql-config-with-mamp) You can copy one of MAMP's default MySQL config files to /etc/my.cnf. Look for them under /Applications/MAMP/Library/support-files/

None of MAMP's MySQL config files however include the innodb_file_per_table setting so make sure to add this to the [mysqld] section of the file you chose to copy to the /etc/my.cnf:

innodb_file_per_table

When you restart your MySQL server it will start putting the medatadata in the database folders that will be created from then on, unfortunately this does not get rid of the huge ibdata1 file. All current databases must be dumped and dropped first, then the ibdata1, ib_logfile0 and ib_logfile1 fils can be deleted. MySQL can be restarted with the innodb_file_per_table setting in place and the dumped databases can be reimported.

You'll be saving gigabytes of disk space in your day-to-day development.

While I was writing this post I came across this Stack Overflow answer: http://stackoverflow.com/a/4056261 It tells the same story but with a bit more detail about what's in the ibdata1 file.

Have Vim Recognise Drupal's .module Files As PHP

OS X's Vim doesn't by default recognise file-types when opening files.
You can turn it on by adding following lines to the .vimrc file in your home directory.

$ echo -e "filetype indent on\nsyntax on" >> ~/.vimrc

This will add "filetype indent on" and "syntax on" to the file, or create it if it doesn't already exist. The "syntax on" is needed or Vim won't recognise the filetypes.

Now Vim will recognise file-types, indent them and colour the syntax of the recognised files.
Drupal however puts a lot of PHP code in .module files. These .module files aren't recognised by Vim as being PHP files.

We can tell Vim to interpret .module files as PHP by modifying the "Virata" piece of code in Vim's filetype file at /usr/share/vim/vim73/filetype.vim from:

" Virata Config Script File
au BufRead,BufNewFile *.hw,*.module,*.pkg setf virata

to:

" Virata Config Script File or Drupal module
au BufRead,BufNewFile *.hw,*.module,*.pkg,
  \ if getline(1) =~ '<?php' |
  \   setf php |
  \ else |
  \   setf virata |
  \ endif

If you don't have access to the global filetype.vim file you can also put these lines in your own home directory's .vimrc.

Next time you want to edit a .module file in Vim it'll detect it as a PHP file. Some of you might say, no-one uses Vim, but when you quickly need to check/hack something on a server, chances are you'll be connecting through SSH using Vim to make the changes, so this might come in handy. Do set up your server-accounts' vim in such a way that viewing PHP in Vim becomes a bit more bearable.

Other settings you can put in your ~/.vimrc that might help you live with Vim are these:

set ruler             " Show a ruler on the bottom
set expandtab         " Expand tabs as spaces
set tabstop=2         " A tab is 2 spaces
set softtabstop=2     " Typing a tab in insert mode is 2 spaces
set shiftwidth=2      " Indent 2 spaces
set smartindent       " Be smart when indenting
set title
set cindent
set hlsearch          " Highlight searches
set incsearch         " Search incrementally

Apple's Single-Threaded Mail.app.

Last weekend we bought a new computer for my mother. Until then she had a 5 year old hand-me-down white MacBook whose battery was dead, still had a physical trackpad-button, the power-cable near the connector was completely ripped and the palmrest-edges weren't just cracked, they were gone.

Time for a new one we thought, so we got her Apple's entry-level notebook, the MacBook Air. A notebook no other computer manufacturer seems capable of matching in terms of price, build-quality or industrial-design finesse.

Whatever.

The problem was with setting the thing up. Apparently we got a model of MacBook Air which had been sitting on the shelf for a while as it did not come with OS X Mountain Lion and when running Software Update it had to pull in so much data, both software and firmware updates, that it choked when it tried to install them and just reported an error.

Running Software Update again triggered a re-download of the whole 1.6GB before failing again with the same error. Third time's a charm I thought but I went about it less... intuitive. I thought it'd be a good idea to download the firmware updates first (one by one) and apply those before trying the rest of the software updates. That eventually worked. So Apple, you have a problem when applying these two types of updates in one go.

This is not something "normal" people would be able to pull off. It was quite upsetting. Imagine having to take it back the next day because on day 1 something as simple as a software update kept failing, after having downloaded a huge amount of data, repeatedly.

After downloading 1.6GB of updates, three times, we got an up-to-date OS X Lion. It was getting late already and I didn't even dare mention anymore that another 4.3GB Mountain Lion download was in tow.

Anyway, the title of this post has to do with a single-threaded Mail.app. When we got to setting up her mail account, we found Mail.app beach-balling all the time. Whatever got clicked it beach-balled a minute or two before we could click again. I had enough and said I'd take the MacBook Air home and bring it back the next day because I had had enough. (Why does Apple gear only ever works flawless with me, I don't know.)

That same evening I found out that a MobileMe account got pre-installed, probably after entering her iCloud credentials. OS X Lion's Mail.app pre-populated itself with a MobileMe account. MobileMe, as we know, does not exist anymore. Mail.app was constantly trying to reach MobileMe's mail server, couldn't find it and started timing out, taking the whole Mail application with it. I patiently beach-balled my way through Mail.app's settings until I could hit the button that deleted the MobileMe account.

How could anyone ship a Mail application that completely hangs as soon as one mail account has problems connecting to the server? It's beyond me.

Getting MySQL, PHP and Apache To Work (Again) On OS X Mountain Lion

Apple's gone and done it again, messing up our local Web Server setup. In Lion you used to be able to put a website in ~/Sites and it'd work when browsing to http://127.0.0.1/~username.

What they've done:

  • Took out the GUI option of starting/stopping Apache in System Preferences' Sharing section.
  • Updated Apache, which comes with a new httpd.conf that disables the PHP module.
  • Removed username.conf from /etc/apache/users, thereby throwing out our local user's DocumentRoot.
  • Updated PHP from 5.2 to 5.3, moving our /etc/php.ini to /etc/php.ini-5.2-previous.

How to fix it:

PHP

Enable PHP by opening /etc/apache2/httpd.conf and uncomment the following line:
LoadModule php5_module libexec/apache2/libphp5.so

MySQL

When installing MySQL on Mac it will put the mysql.sock file in the "tmp" folder. This is not the place where the version of PHP that ships with OS X will look for it. We need to tell PHP where to find the mysql.sock file.
Copy /etc/php.ini.default to /etc/php.ini, open /etc/php.ini and change all occurrences of "/var/mysql/mysql.sock" to "/tmp/mysql.sock" (without the quotes)

Apache

Make Apache recognize /Users/<username>/Sites as a valid DocumentRoot again.
Create a text file /etc/apache2/users/<username>.conf and add, swapping out username with your actual username:
<Directory "/Users/username/Sites/">
Options Indexes MultiViews
AllowOverride All
Order allow,deny
Allow from all
</Directory>

Starting Apache

Now that our settings are back to normal we can start Apache, but with the item missing from System Preferences' Sharing menu we'll need to do it from the command line. Open up Terminal and type: sudo apachectl start
This controls Apache and tells it to start, you obviously need to be administrator so "sudo" is needed here as well. It will ask you for the password and then, when you browse to:

http://127.0.0.1/~username

You should see your old website again.

Apache can be started, restarted and stopped with the following commands:
sudo apachectl start
sudo apachectl restart
sudo apachectl stop

How To Always Sort By Date With Apache Solr In Drupal 7

Recently I had a case where Solr search results had to always be sorted by the end-date of a date field in Drupal 7.

The website had two content types, activities and courses, both with start and end-dates in a date field. On a Solr search page I wanted to do two things: only show the courses that haven't finished or started yet (those in the future) and sort them chronologically by date. Eventually, with the help of Kristof De Jaeger and Nick Veenhof I found out how to do it.

The problem is this: Solr will detect the field date, and extract the start and end dates as dm_field_date_start and dm_field_date_end. When you look at the Solr schema browser you can see those fields are being listed. Unfortunately Solr cannot sort on them because it indexed them as dm_* which means they are "date multiple" fields. Solr can only sort on single fields. The solution is to add the "date single" field (ds_end_date) to the index and use that in a sort.

There are a couple of things that need to happen in order for it to work:

  1. Add the end-date field to the Solr index so it can be returned in the results and sorted upon.
  2. Create the sort on the date field when running the query.
  3. Add a filter to exclude the past courses.
  4. Add the end-date field to the query results.
  5. Run the sort.

1. Adding A Date Field To The Solr Index

The content/entity types for courses and activities are nodes and Drupal's Solr API exposes functions for every entity type there is. There is hook_apachesolr_index_document_build() in which you can write a switch-case statement to see whether the $entity parameter is a node but it's easier to use hook_apachesolr_index_document_build_node() which is only called for nodes and it saves you a switch.
The date field on the activity and course content types was named "field_date". So in case the entity type that is being indexed is an activity or a course, add the end-date value of field_date to the document in Apache Solr's date format.
The name of the field in the Solr index is free to choose, but make sure it starts with ds_ or Solr will not be able to to sort on it. "ds" stands for "date single", which means it can only have value and which makes sorting possible.

function mymodule_apachesolr_index_document_build_node(ApacheSolrDocument $document, $entity, $entity_type, $env_id) {
  if ($entity->type == 'activity' || $entity->type == 'course') {
    $entity_date = field_get_items('node', $entity, 'field_date');
    // Add the end date of the entity_date field as a sort field to the solr index
    if (!empty($entity_date)) {
      $document->addField('ds_end_date', apachesolr_date_iso(strtotime($entity_date[0]['value2'])));
    }
  }
}



When you reindex your content you'll see in the Solr schema browser for your Solr core that the field "ds_end_date" will be added.



2. Making The Date Sort Available


Before we can sort we need to "add" the sort to the query we are executing, making sure it exists, telling it on which field to sort and how. In hook_apachesolr_query_prepare() you will want to have some logic to know when to modify the query as you do not want to modify each and every query that is performed. hook_apachesolr_query_prepare() is run for every Solr search.
In this case I check to see whether we're on the "courses" or "activities" page, and only then I add the sort. It will sort ascending.

function mymodule_apachesolr_query_prepare($query) {
 // Add a sort on date.
 if (arg(0) == 'courses' || arg(0) == 'activities') {
   $query->setAvailableSort('ds_end_date', array(
     'title' => t('End date'),
     'default' => 'asc',
   ));
 }
}



3. Filter Out The Past Courses And Activities


One other thing I wanted to do was hide the past courses and activities, they serve no more purpose anyway. This can be done by adding a query filter to the hook_apachesolr_query_alter(). We want to filter the date field and filter on a range. Anything between today and forever is OK. Date ranges are noted like [start_date TO end_date]. The start_date will be apachesolr_iso_date of the timestamp of TODAY and the end_date can be substituted with the asterisk wildcard.


Again, we only want to filter if we're on the courses or activities Solr search pages.

function hook_apachesolr_query_alter($query) {
  if (arg(0) == 'courses' || arg(0) == 'activities') {
    $query->addFilter('dm_field_date_end', '['. apachesolr_date_iso(strtotime('TODAY')) .' TO *]');
  }
}



4. Add The End-Date To The Query Results


In step 1 we added the ds_end_date to the Solr index for courses and activities... but unless we tell the query to add this field to the results it will not be there, and we will not be able to sort on it. So again, in hook_apachesolr_query_alter() we add the line and the function will look like this:

function mymodule_apachesolr_query_alter($query) {
  if (arg(0) == 'courses' || arg(0) == 'activities') {
    $query->addFilter('dm_field_date_end', '['. apachesolr_date_iso(strtotime('TODAY')) .' TO *]');
    $query->addParam('fl', 'ds_end_date');
  }
}


5. Actually Run The Date Sort


Finally we need to run the sort on the query after having added the field to the Solr search index, and made the sort available on the query.

function mymodule_apachesolr_query_alter($query) {
  if (arg(0) == 'courses' || arg(0) == 'activities') {
    $query->addFilter('dm_field_date_end', '['. apachesolr_date_iso(strtotime('TODAY')) .' TO *]');
    $query->addParam('fl', 'ds_end_date');
    $query->setSolrsort('ds_end_date', 'asc');
  }
}


And that's it.

Fortis Fail

Recently Fortis started offering their "Easy Banking" application on iOS, which lets you do bank-transfers from your iPhone or iPad.

Before you can use "Easy Banking" you need to enable it on Fortis' website first where you have to choose a password. The problem I ran into was with their input validation on the password fields.

The default way of choosing a password is to type it twice, in separate input fields. One part of the validation is checking whether the two inputs are the same. Often it will also check the minimum length of the password. Or even the max-length, although I advise against that. You can't argue against longer passwords... Worse is when companies start checking your input and only allow certain character-sets. There's no point in this at all... People make their passwords more complex by adding in non-alphanumeric characters, they type them correctly, twice... and then the company says they have to simplify the password they're used to, or they won't take it. That is just ridiculous.

But with Fortis it's even worse. The problem is two-fold.

First, on the Fortis website where you choose your "Easy Banking" password, it does not allow non-alphanumeric characters in your password. That is silly in itself but the bigger problem is that they skip over input in their fields when a non-alphanumeric character is typed. Try to imagine... when you are hitting a '%' or '(' or '@' or any other non-alphanumeric character it just does not _type_ it in the field. This is so bad I can't even start describing it.

Thus, suppose your password has a '#' in it... let's say "p#ssword", without the quotes. If you type that in Fortis' input fields you will see this: ••••••• You tab to the next input field and repeat your password, again you see, without error: •••••••

You click OK and everything goes well. Fortis accepts the password because the passwords in both fields match. Cool, you think. I've got my password set up. Now let's get my iPhone and try out "Easy Banking"...

This is where we see the 2nd part to the problem.

In their iOS app's password field... unlike on their website, it does _not_ skip over non-alphanumeric characters. So when you type the above password in the app as you try to log in it will show: ••••••••

You hit "Login" and the application will fail to log you in because you provided wrong credentials. You then need to wait 2 minutes before trying again... With the same result, you can not log in. If you go back you'll see that on the website you only really typed 7 characters, Fortis took out the '#'... The iOS app takes 8 chars, as it should. No app should ever alter the password data you input in the field.

A user will not understand this… He did everything right, saw no error, but he cannot sign in.

I do not understand how BNP Paribas Fortis, a major bank, can be this outright ridiculous in the way they create their applications. Who do they think they're doing a favor by not allowing non-alphanumeric chars _and_ not telling their customers about it when they're just skipping over those characters. People effectively think they typed something twice but the password that is accepted by the website will be different from what you typed... You actually have to start counting the dots in the input fields to know if they match the amount of characters you have in your password.

Hopefully this will soon be fixed, but I'm afraid they don't even know about it themselves. This is a typical case of UX fail when companies try to validate too early and auto-correct input, definitely when dealing with people's passwords, on a banking website.

Location Of my.cnf With MAMP

"How on earth do I tell MAMP to use my own MySQL configuration?"

Chances are you've heard this question one too many times if you're a web-developer... It's also been driving me crazy for about an hour.

Turns out MAMP isn't that bad after all, good thing I refrained from tweeting angry things about them. Granted, they do still suck (their little UI that never disappears is horrid, as well as the incapability of restarting one service, and, they should put their stuff in System Preferences as a PreferencePane, just like the official MySQL has)

In any case, here's what to do if you can't figure out where to put your my.cnf when working with MAMP. To have MySQL print out its help, listing the different paths in which it will look for a my.cnf configuration file, sorted by order of preference, type the following on the command line:

mysql --help | grep cnf

Part of the output should be the following line:

/etc/my.cnf /etc/mysql/my.cnf /Applications/MAMP/conf/my.cnf ~/.my.cnf

Perfect, a couple of locations MAMP's MySQL will look for the my.cnf for and /etc/my.cnf is the first location it will try.

If you were like me you didn't even consider putting it in /etc and tried figuring out where to put it under MAMP's folder. Turns out it's not necessary as /etc/my.cnf will do. But, as an added bonus, it tells you where to put it should you want the my.cnf file under MAMP's folder anyway.

Another tip: in case you've got multiple MySQLs installed make sure you're using MAMP's MySQL by entering the following command: which mysql

Pages

Subscribe to Jeroen Bensch RSS