To Top

Our Blog

Guru Technologies

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 Manger

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.http://www.gurutechnologies.net/uploads/martyj/profile_manager/server_lion.png

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.

http://www.gurutechnologies.net/uploads/martyj/profile_manager/Mgink.png

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.

http://www.gurutechnologies.net/uploads/martyj/profile_manager/device_list.png

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.

http://www.gurutechnologies.net/uploads/martyj/profile_manager/app_restrictions.png

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.

http://www.gurutechnologies.net/uploads/martyj/profile_manager/device_info.png

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

http://www.gurutechnologies.net/uploads/martyj/profile_manager/device_options.png

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.

http://www.gurutechnologies.net/uploads/martyj/profile_manager/device_groups.png

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.

http://www.gurutechnologies.net/uploads/martyj/profile_manager/user_enrollment.png

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

http://www.gurutechnologies.net/uploads/martyj/profile_manager/os_x_lion_users.png

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”

http://www.gurutechnologies.net/uploads/martyj/profile_manager/options.png

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.

http://www.gurutechnologies.net/uploads/martyj/profile_manager/apps.png

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/

http://www.gurutechnologies.net/uploads/martyj/profile_manager/mdm_app.png

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.

http://www.gurutechnologies.net/uploads/martyj/profile_manager/httpconf.png

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: http://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: http://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: http://www.gurutechnologies.net/uploads/martyj/aes_ctr_example.zip

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

How to Prevent Scope Creep

When our company develops software, one of the more difficult problems we face is taking a customer vision of a project and focusing it.  Software developers are generally very good at implementing functional requirements.  A skill that they aren’t as naturally good at is cutting and limiting requirements.

Why would we want to cut and limit features when the customer is asking for them?

Our experience has shown that our customers, not being developers, don’t always have a good handle on what features they ask for might entail or how important it is to prioritize them.   An article on scope creep says:

“…we are here to lead our clients, not to take their order. That requires being critical. Not critical in the sense of making value judgements (e.g. “that’s a dumb idea”) but in the sense of deconstructing ideas in order to justify them. We’ve got to get comfortable with challenging our clients’ requests by asking: Why? What is it for? How will it work? Who does it benefit? What does it cost? We can do this gently and kindly, by the way. I’m certainly not suggesting that we assault our clients with some kind of 3rd degree treatment. Our job is to help them make decisions, keeping in mind that there are priorities to consider with every possible feature: the purpose of it, the user experience, the content management experience, and of course, the cost-not necessarily of that specific thing, though that can be an issue, but of all these little features in the aggregate. In the end, managing the little things is the most powerful means of avoiding scope creep we have.”

Customers usually have a great vision for their products, but most of the time the budget doesn’t match the full vision, and more importantly, it’s better to have something smaller than the full vision but functional and actually released than to shoot for the full vision initially and miss the mark because the project is over budget.

One important way our team tries to solve this problem is by delivering software in small iterations rather than via “Big Design Up Front”.  This allows the customer to gauge how long it takes to see their ideas turn into something real and let’s them make adjustments along the way.

At Guru Technologies, we try to hire developers that can guide a project as well as be strictly write software.  We try to deliver something every week or every other week for the customer to look at, even if it is rough, to let them review, give feedback, and direct the next week’s work.

Read more at: How to Prevent Scope Creep.

New Guru Technologies Website

We now have a new custom-designed website that we built in-house.  We hope to make our blog a great resource for technology best practices and useful articles on software development and IT Support.