Author Archives: Guru

Good UX is All About Confidence

Fast food self-ordering kiosks are here to stay. Who knew there could be so many ways to get a McDouble?

Those kiosks have been tried before, you know. Decades ago, one fast food spot in my town built cabinets to house old boxy touch-screen computer monitors for the customer’s use. Yeah, it didn’t really catch on. But just like virtual reality, it kept coming back, making an appearance now and then to see whether the world was ready. Efficiency demands it. Getting more people to use the kiosk means cheaper food for us, and a bigger market share for the company. And the batch that McDonald’s rolled out in 2015 seems to have stuck for good.

But even now, not everybody will use it. As we come through the door, our first choice is whether to interface with a computer or the teen behind the counter. A whole lot of us still choose to line up to meet the human, even if it means waiting a little longer to eat. 

So why is it so hard to get a tech-savvy populace to use a simple touch-screen to order lunch?

It’s a matter of confidence.

It’s not that we don’t trust that the kiosk software works properly (though that may be part of it.) It’s that we lack confidence in ourselves—we don’t trust that we will know how to use the software well enough to get our own order right.

Crisis of Confidence

Whether dining or shopping, we like getting help from a human. They are the experts at their store. They know their inventory and are experienced in answering the kinds of questions that you might ask. They might have helpful suggestions you hadn’t thought of. There are verbal cues, facial expressions, and body language that help you know when you’re on the same page, and validation that your order makes sense.

These are things that software can’t easily provide (yet). Even the best clean and modern user interfaces can still be confusing. A vaguely-worded button makes a user hesitate. An unexpected choice of colors from their phone screen makes them wonder whether they had done the right thing. Without the utmost care to UX detail, your users’ confidence level can quickly drop. And it doesn’t have to drop far to turn into a frustrating experience.

It’s not enough anymore to make it reasonably clear what the software is doing. Plan on your users second-guessing themselves, your software, and you—because they will. “I’m pretty sure I’ve entered this the way that I’m supposed to, but you could also read it this other way. Maybe that’s what the software wants me to do.”

It must be so incredibly obvious what the software is doing, that it’s also clear that it is not doing everything else.

The trend these days is to aim to create software that “delights”. I like to think of it another way. Picture your users as opening your software only because they have to in order to get something done. They want to get that thing done quickly and with minimal frustration, and then move on to the next thing on their to-do list.

Pretty isn’t as important as solid. And no matter how stable and bug-free your software actually is, it won’t feel solid to them without a confidence-building UX.

Your Confidence-building Toolbox

If this crisis of confidence is ringing true for your app, don’t let this get you down. Most software needs improvement in this area. And even if you don’t have easy access to a professional designer, there is a lot you can do.

Let’s examine your UX toolbox, filled with double-edged swords that you have already been using, for good or ill. Used properly, each of these tools can assure your users that they are using your software properly, even upon first use! They can also be used for ill, unintentionally plaguing your users (and customer support representatives) with anxiety and frustration.

Colors

Color can be a powerful way to communicate status, importance, and validation. By default, consider giving your app only one or two colors outside of the greyscale spectrum. Then, when you smartly use color to communicate status, importance, or validation, it will stand out and be meaningful to the user. For example, if you’re going to make a button stand out with color, make sure it’s the main, primary action on that screen.

Be sure to follow your intuition and conventions here. For instance, red messages usually mean that there is an abnormal problem (e.g. the server is down) or is used to scold the user for trying something invalid. (By the way, try to craft your software so that it’s difficult to get into a situation where a user would need to be scolded.)

Wording

Take time with your verbiage. Whittle it down to something very clear and brief. Your users don’t want to read long messages explaining software functionality.

Think of different ways that something can be read. Oftentimes, something that is obvious to you might confuse a colleague. Run it by them and ask what they think. Discover how to craft it in a way that it can’t be interpreted any differently than you mean it.

Animation

Sometimes thought of as unnecessary fluff, subtle animation can add vital clarity to what is going on. For instance, when the user takes an action to filter a list and a few items disappear, it can be visually disorienting for the screen to change in an instant, as the user needs to get her bearings again. Instead, consider having an animation have them fade or slide out from view.

Another fine example is when you navigate from one week to the next in Google Calendar. A subtle motion of the calendar content tells your brain which direction you’re moving.

After the Fact

It’s important to give users confidence that the button they are about to click will do the thing they want to do. Additionally, after the action has been taken they will look for similar reassurance. “No news is good news” does not apply here.

It can be quite helpful to display a message showing a few words confirming what happened, and that it was successful. Be sure to remove all doubt that they may have done the wrong thing.

For instance, if a user just submitted a popup form (i.e. modal) providing feedback, it is nice to indicate that it was successfully received. This is sometimes done with another modal where the user needs to click OK.

However, a small, out-of-the-way message is usually even better, commonly called a “toast”. (Think of a toaster at the bottom of your screen, popping up little informational messages that don’t need to be acknowledged and that don’t get in the way of the user.) Have it say “Feedback received” with a little ‘x’ to allow the user to close it, but have it also disappear on its own after a few seconds. The user smiles at the encouragement that all went as expected, but isn’t interrupted. Gmail is great at this, by the way.

Undo

Once your user sees that actions can be undone, she will take actions quicker and be more at ease knowing that it will be harder for her to permanently mess things up. Consider having this “undo” action be a part of your non intrusive toast that appears after an action has been taken. Again, Gmail does this flawlessly.

Follow Conventions

Sometimes we like to buck the trend and be a little different. I admire your creativity, but with UX conventions, this is often the wrong move. Users grow accustomed to things that they find common among other apps and have already done the work to learn their meaning. Following conventions is a way that you can tap into what they already know. Don’t be afraid to ride the river of convention as far as you can, and have them walk on shore only as far as they need to in order to learn the truly unique parts of your app.

For instance, you may want to be cute and use “Forget about it” instead of the boring “Cancel”. Even if the meaning seems obvious to you, your user will pause and think, “Wait a minute. If this button was going to cancel, then they would have just said ‘cancel’. This must do something slightly different. Instead of canceling my changes, is it going to delete the order from the system?” Little things like this unnecessarily detract from their confidence in your app.

Study the big, well-established apps. Don’t plagiarize, but make sure you’re not far out of line with them.

Cater to the Brand New User

The software manuals are in the landfills where they belong, and your software experience has to be incredibly intuitive. Forget what you know and look at your app with fresh eyes. Test your UX with coworkers and family and watch their reactions.

You’ve got great software that works. Now, just put some extra time into your UX and raise the average user confidence level from 85% to 95%. Believe me, it will pay off.


P.S. If you need any help with your app—whether it’s just advice, help with coding, or building the whole thing from scratch—Guru Technologies is always ready, and at a reasonable hourly rate.

Web browser text search

So I am working on a project where I have to search some HTML documents for a possible text string. This lead me to an interesting find in how browsers do searching on text.

 

Let’s look at the following HTML.

<div>
<div style="background-color: #00ff00;">Hello ther</div>
<div style="background-color: #ff0000;">e,
<span style="background-color: #f0ff00;">bob</span> how are</div>
<div style="background-color: #00ff00;">you?</div>
</div>

The text displays as the following: Text displayed in a browser

The yellow represents the inner span. The divs are different colors to show their distinction.

If you search for the text “Hello there” no results will be found as the browser does not search across div elements.

If you search for the text “e, bob how are” the text will be found as the browser will search across span elements.

It’s interesting to note that the browser’s search works only across defaulted inline elements but not elements set inline by the html.

Html5 Audio restart playback in iOS Safari

When using html5 audio and Apple’s safari browser on iOS there is a problem that occurs when you try to set the audio’s time.

Html5 audio DOM object has an attribute called currentTime. This unfortunately isn’t available in iOS safari. This makes it difficult if you want to start the audio from the beginning.

An example code like this:

if($('#audio_' + id)[0].currentTime != undefined)
{
	$('#audio_' + id)[0].currentTime = 0;
}

will throw an exception.

There is an easy way around this problem and that is by removing the audio element from the DOM and then re-adding it.

Here is my code:

var audio = $('#audio_' + id).clone();
var parent = $('#audio_' + id).parent();
$('#audio_' + id).remove();

Post in the comments below if this has helped you in developing html5 audio in safari. Any questions are also welcome.

Javascript Object Switcheroo

So I found out something interesting with javascript and objects. Let’s say you have a cube object in javascript that is defined by this function.

function Cube(x, y, z);

Now lets say we had set the z value to be zero. Why would we want a cube object when it is really just a plane?

function Cube(x, y, z)
{
	this.x = x;
	this.y = y;
	this.z = z;
	this.type = 'Cube';
	if(z == 0)
	{
		return new Plane(x, y);
	}
}

function Plane(x, y)
{
	this.x = x;
	this.y = y;
	this.type = 'Plane';
}

If we do this code here:

var shape = new Cube(4, 2, 0);

If we were to inspect shape what type of object will it be?

If we did something like document.write(shape.type) the answer will be Plane.

Better jquery each loop for coffeescript

When writing object-oriented code in coffeescript, I’ve found that the jquery each method is insufficient, due to its use of “this”.  I am forced to use the following syntax:

$('.thing').each (index, thing) =>
  $(thing).css
    width: @width()

I’ve created an alternative which works better for this use case.  It passes the object as both “this” and as the first argument, and wraps them both in a jquery object automatically:

$('.thing').loop (thing) =>
  thing.css
    width: @width()

In cases where you don’t want access to the original “this”, it is also useful.  Here is an example with “each”:

$('.photo').each ->
  $(@).hide()

With “loop”, there’s no need to wrap “this” with a jquery object:

$('.photo').loop ->
  @hide()

Here is the source code for $.loop:

# Better each() for use with coffeescript
# 1. Wraps child in jquery object
# 2. Sets child first argument, so that fat-binding can be used.
# 3. Sets @ as well, for normal binds
jQuery.fn.loop = (block) ->
  for i in @
    element = jQuery(i)
    res = block.call element, element
    break if res == false

OS X Server Lion Profile Manager

Working on one of the projects that I am on we have an iOS app that needed to be distributed via the enterprise distribution. Finding information about this though was very difficult as apple doesn’t have any information on the enterprise accounts without signing up first.

It is also hard to get any information on how to distribute these apps effectively across multiple devices while allowing app updates as well.

There is good news though. You don’t have to pay for a MDM (mobile device management) server unlike what Apple requests. If you buy OS X Lion Server in the app store there is a MDM server built into it. The cost is $49.99.

So here is what the software looks like.

Honestly if you ask me OS X Lion Server is a waste of $50 if you do not need this MDM server. Everything it includes is either built into the OS or is already available free on the web. Apple just rolled it into one application.

So what is the MDM server?

The MDM server is also known as the profile manager. This is a ruby application to manage iOS devices. If you have bought the actual application it can be found here /usr/shared/devicemgr/. There are two parts to this application. Backend/ and frontend/. Backend/ is the ruby application where as frontend is just a static html javascript page which calls upon the backend code to pull data.

I will go more in depth into these later. For now let’s see what it actually looks like. After browsing to your Mac’s address via https on a url like “https://localmacaddr/profilemanager” you will be redirected to a login screen. This login is the same as the login for Users under the OS X Lion Server software.

As you can see Apple didn’t leave out their eye candy designs in this application. One of the things you will learn about apple from this is that appearance is everything. Usability is second place. A good example of this is that you can only upload iOS applications with safari.

Once you are authenticated there really isn’t many options to the profile manager. Although you don’t really need much. If you look on the left hand menu you see Devices, Device Groups, Users, Groups, Active Tasks, Completed Tasks.

Devices are the Apple hardware connected to your MDM service. As you can see in the picture above the current type of devices we have are the iPod/iPhones and iPads. There is also support for OS X computers as well. The devices are shown with their name given to them by iTunes along with the user that they were enrolled under. For example Volunteer Enrollment is the user that enrolled Guru’s iPad.

By having a device enrolled in your profile manager you can set up pass codes on the device, network information, vpn information, manage certificates, restrict what services the device can use such as camera use, app purchasing, application use like safari, media ratings, and many more options. This is mostly for iPhone/iPad/iPod restrictions. There are different restrictions for OS X.

You can also get basic information about the device such as the installed apps (with their versions), Device UDIDs, serial numbers, MAC addresses, total space available, space remaining, battery life, and software version.

There are also features which allows you to remote wipe an app, clear the pass code, and lock the device.

Locking the device is basically the same as pressing the lock button on the top. If you have a pass code set locking the device requires you to re-enter the pass code.

Clear passcode removes the passcode on the device which prevents unlocking.

Wiping the device takes the device back to its out-of-the-box state.

The profile manager also allows you to set up device groups which allows you to push the same settings, restrictions, and apps to multiple devices instead of each individual device. In the picture above you can see we have 3 groups for our alpha, beta, and production version of the app.

There is also the same functionality for devices that a specific user enrolled. You can also set up user groups to allow for devices enrolled by multiple users.

These users and user groups are the same as the ones managed by OS X Server Lion.

If you go to a device, device group, users, user groups page at the bottom you see a cog for options. The bottom option says “edit apps”

This is where probably the most useful feature of this app takes place in terms of enterprise development.

If you click on edit apps you see a dialog pop down which shows a list of apps uploaded to the profile manager.

As you can see we have two apps in our MDM server. The apps are distinct by their bundle identifier. They also have a version as well.

You can upload apps which just asks you to select the .ipa file from your computer.

If you upload an app that has the same bundle identifier it will only overwrite the existing app if its version is higher than the one in the profile manager. Otherwise it will ignore the upload. You cannot have any spaces in the name of the .ipa that is uploaded to the server.

Clicking remove will instantly delete the app and the apps data from the device/device group/user’s devices/user group’s devices.

If you click add it will add the app to the device/device group/user’s devices/user group’s devices. Note: it will prompt the device upon app updates and application adding on the device to see if they wish to install it. Unlike removing it doesn’t happen automatically.

Lastly probably the most major downside is that this MDM application doesn’t allow you to update one specific device with a device version. If you update the app it updates all the devices who use that app. Not the specific device you are viewing. Apps are only unique by their bundle identifier and not their version as well.

That being said this application is just a simple ruby application. If you wish to change something about it you can easily do so. By default the application can be found in /usr/share/devicemgr/

There are two main sections of the app. The backend, and frontend sections. The backend is the rails application where as the frontend is a javascript/html interface to query the backend for information.

The application is served via apache and uses a postgres database.

If any web routes match {HOST}/profilemanager by default the frontend code is used.

If any web routes match {HOST}/devicemanagement/ the backend is used.

The backend can be hit via the url as stated {HOST}/devicemanagement/api/{controller}/{action}

There is a apache rewrite to rewrite {HOST}/mydevices to {HOST}/devicemanagement/api/device/start_ota

If you wish to do any database changes you can connect to the postgres database via command line by using this command.

sudo -u _devicemgr psql device_management

If you know Ruby on Rails and PSQL changing the profile manager should be easy.

AES CTR Encryption in C

Encryption is one of the best tools at protecting data when it comes to computer security. There are many forms of encryption as well. One of the forms that I encountered recently in my work is AES CTR encryption. I am sure you have heard of AES encryption, but what exactly is AES CTR?

AES CTR

CTR is a counter mode for AES encryption. It is also known as ICM and SIC.

In AES encryption you have what is called an Initializing Vector, or IV for short. This is a 128-bit input that is usually randomized. In CTR mode the IV has two parts. The first 8 bytes is the regular randomized IV. The last 8 bytes is a counter. This counter is a 0 index of the number of 128-bit blocks you are inside the encrypted information. For example. If you are encrypting 512 bits of information (64 bytes), the start position of 0 bytes into the information would have a counter of 0. 16 bytes in, you would have a counter of 1. 32 bytes in your counter would be up to 2. So on an so on until you are at the end if your information. Unlike normal AES encryption this encryption can be seek-able through the information. You don’t have to decrypt all of the bytes to get some information in the middle.

The way encryption works in AES CTR mode is that we generate some random bits with the encryption key provided and the IV. With these random bits we then XOR them with our string. This creates a randomized text. To decrypt them we just simply XOR the text with the same exact random bits that we generated with the encryption key and the IV.

Let’s look at this example. There is two people, person A and person B. They both share a random string of text that no one else has. Let’s have this random text be 10100011011011011. If person A wants to send person B a message all they have to do is to XOR their message with their random text.

Let’s have person A’s message be 10011010101010100.

If we XOR the message with the random text we get the following string. 00111001110001111

We then send this string to person B. If person B XORs the string with his random string he will get the original message from person A of 10011010101010100.

Encrypting a file and decrypting a file are the same steps. The only differences in our code example would be during decryption we set the IV from the file. During encryption we generate the IV randomly.

So everyone wants a code example right? What’s the point of knowing about the method without being able to implement it.

For this example we will be using OpenSSL’s AES implementation in their cryptography library.

Download the library:

Windows

For windows you can find the OpenSSL download link here: https://www.openssl.org/related/binaries.html

Linux

If you’re using a debain based version of linux you can download the library with this command: “sudo apt-get install libssl-dev”

OS X.

You already have this library installed. It can be found in /usr/include/openss/ and /usr/bin/openssl/

The language that we will be using will be C. The code is not platform specific. We will be writing the code in Linux using a text editor and the GCC compiler.

Demo: Encrypt/Decrypt files with OpenSSL AES CTR mode.

  • Note: Code example uses partial code from: https://stackoverflow.com/questions/3141860/aes-ctr-256-encryption-mode-of-operation-on-openssl

Let’s start with our includes.

We will need to include 4 files for this example.

#include <openssl/aes.h>
#include <openssl/rand.h>
#include <stdio.h>
#include <string.h>

We will also need a structure to maintain our ivector, ecount, and num.

struct ctr_state
{
    unsigned char ivec[AES_BLOCK_SIZE];
    unsigned int num;
    unsigned char ecount[AES_BLOCK_SIZE];
};

The Ivector is the only piece of information used by our program that we care about. Num and ecount are variables that we have to pass into our encryption function that we don’t ever need to care about.

*Note AES_BLOCK_SIZE is defined to be the integer value of 16. This is the number of bytes in the 128-bit block for AES.

We will also need two file types declared for encrypting and decrypting.

FILE *readFile;
FILE *writeFile;

We will also need to set our encryption key.

AES_KEY key;

Some other inforation that we will need is to know how many bytes we read/wrote, the data that we read/wrote to the file, the IV that we read from the file, and our state for the encryption of a ctr_state struct.

int bytes_read, bytes_written;
unsigned char indata[AES_BLOCK_SIZE];
unsigned char outdata[AES_BLOCK_SIZE];
unsigned char iv[AES_BLOCK_SIZE];
struct ctr_state state;

It is helpful to have a function which initializes the IV setting all the values to be 0 except the first 8 which will be the random input.

int init_ctr(struct ctr_state *state, const unsigned char iv[16])
{
    /* aes_ctr128_encrypt requires 'num' and 'ecount' set to zero on the
    * first call. */
    state->num = 0;
    memset(state->ecount, 0, AES_BLOCK_SIZE);

    /* Initialise counter in 'ivec' to 0 */
    memset(state->ivec + 8, 0, 8);

    /* Copy IV into 'ivec' */
    memcpy(state->ivec, iv, 8);
}

Let’s work on our encryption function.

Our function can be described as this

void fencrypt(char* read, char* write, const unsigned char* enc_key)
{

Read is the file name plus location that we are reading from to encrypt.

Write is the file name plus location that we are writing the encrypted information to.

enc_key is the encryption key used to encrypt the file. *Note, this must be 16 bytes long. This is the “password” to the file.

The first thing we need to do is to create an IV with random bytes. OpenSSL library has a function to generate random bytes into an array. It is found in rand.h.

    if(!RAND_bytes(iv, AES_BLOCK_SIZE))
    {
        fprintf(stderr, "Could not create random bytes.");
        exit(1);
    }

Now we need to open our reading/writing files and make sure that they can be used.

    readFile = fopen(read,"rb"); // The b is required in windows.
    writeFile = fopen(write,"wb");
    if(readFile==NULL)
    {
        fprintf(stderr, "Read file is null.");
        exit(1);
    }

    if(writeFile==NULL)
    {
        fprintf(stderr, "Write file is null.");
        exit(1);
    }

Now that we have our file in place we need to write out our IV to the file. The IV is not suppose to be secure. Remember that only the first 8 bytes of the IV are even used in this mode of AES encryption.

    fwrite(iv, 1, 8, writeFile); // IV bytes 1 - 8
    fwrite("", 1, 8, writeFile); // Fill the last 8 with null bytes 9 - 16

The next step is to set our encryption key.

    //Initializing the encryption KEY
    if (AES_set_encrypt_key(enc_key, 128, &key) < 0)
    {
        fprintf(stderr, "Could not set encryption key.");
        exit(1);
    }

After we set our encryption key we need to initialize our state structure which holds our IV.

    init_ctr(&state, iv); //Counter call

Now the fun part. We will go into a continuous loop reading from the file encrypting all the data and writing it out.

    while(1)
    {

We then need to read 16 bytes from the file into our indata array.

        bytes_read = fread(indata, 1, AES_BLOCK_SIZE, readFile);

After we read the bytes we then encrypt them using our AES_ctr128_encrypt function. This is the 128-bit encryption function found in aes.h. Indata is the data we read from the file. Outdata is our array to which the encrypted bytes will be placed. bytes_read is the number of bytes in the indata array to be encrypted. Key is the encryption key that was set using our 16 byte password. State.ivec is the IV used for encryption. The last two variables are not used by us so we don’t need to know about them at all.

        AES_ctr128_encrypt(indata, outdata, bytes_read, &key, state.ivec, state.ecount, &state.num);

Now that we encrypted our data into outdata it’s time to write them to a file.

        bytes_written = fwrite(outdata, 1, bytes_read, writeFile);

If we read less than our block size it probably means we are at the end of the file. We can stop encrypting now.

        if (bytes_read < AES_BLOCK_SIZE)
        {
            break;
        }
    }

We now need to close our files to as they are no longer needed.

    fclose(writeFile);
    fclose(readFile);
}

So what changes in the decrypting function?

Basically nothing. The only changes that we do is we set our IV to be the first 16 bytes in the input file. The rest of the code is the exact same.

If you want a further example the code can be found here: https://www.gurutechnologies.net/uploads/martyj/aes_ctr_example.zip

Compile via command line with the following command. “gcc main.c -lm -lcrypto -lssl”