code prettify

Friday, 12 February 2016

Associating git hooks with js syntax check

This is a followup article from my previous post.


Here we will be using git pre-commit to check for syntax error while committing in JavaScript files.

We will need nodejs in our system. Please check https://nodejs.org/en/ for downloading and install steps.

Note: I am using ubuntu 14.04 for this setup.

Steps to add pre-commit JavaScript syntax check with git:

1. Use npm to install jslint package globally in your system.

https://www.npmjs.com/package/jslint

$ npm install -g jslint

This should globally install jslint in your system and can be referenced as below to check syntax error for any js file.

$ jslint sample.js

for (i = 0; i < 10; i++)
{
        sum += i;
}

Sample output from above command:
sample.js
 #1 'i' was used before it was defined.
    for (i = 0; i < 10; i++) // Line 1, Pos 6
 #2 'i' was used before it was defined.
    for (i = 0; i < 10; i++) // Line 1, Pos 13
 #3 'i' was used before it was defined.
    for (i = 0; i < 10; i++) // Line 1, Pos 21
 #4 Unexpected '++'.
    for (i = 0; i < 10; i++) // Line 1, Pos 22
 #5 Expected exactly one space between ')' and '{'.
    { // Line 2, Pos 1
 #6 Use spaces, not tabs.
    sum += i; // Line 3, Pos 1
 #7 Expected 'sum' at column 9, not column 2.
    sum += i; // Line 3, Pos 2
 #8 'i' was used before it was defined.
    sum += i; // Line 3, Pos 9
 #9 Expected '}' at column 5, not column 1.
    } // Line 4, Pos 1

Above info is quite informative and helpful to fix basic syntax errors, missing semi-colons, indentation etc.

Correcting the above errors to below code and running jslint again:

var i, sum = 0;

for (i = 0; i < 10; i = i + 1) {
    sum += i;
}

Output from jslint:

sample.js is OK.

Note: Please also refer rules and standards being followed by jslint for checking here. Makes a nice read. :)

2. Now that jslint is globally available, let us use it and create a pre-commit file.
I found below links which highlight the use of it in a script:

http://stackoverflow.com/questions/15703065/setup-pre-commit-hook-jshint
http://dev.venntro.com/2012/11/maintaining-consistent-javascript-with-jslint/

The only disadvantage I see in the script is that it only highlights passed and failed JavaScript files with names and does not specify the error in each.

So, I made a few changes to the script as below (highlighted in blue):

#!/bin/sh

files=$(git diff --cached --name-only --diff-filter=ACM | grep "\.js$")
if [ "$files" = "" ]; then
    exit 0
fi

pass=true

ERRORS_BUFFER=""

echo -e "\nValidating JavaScript:\n"

for file in ${files}; do
    result=$(jslint ${file} | grep "${file} is OK")
    if [ "$result" != "" ]; then
        echo -e "\t\033[32mJSLint Passed: ${file}\033[0m"
    else
        ERRORS=$(jslint ${file})
        ERRORS_BUFFER="$ERRORS_BUFFER\n$ERRORS"
        echo -e "\t\033[31mJSLint Failed: ${file}\033[0m"
        pass=false
    fi
done

echo -e "\nJavaScript validation complete\n"

if ! $pass; then
    echo -e "\033[41mCOMMIT FAILED:\033[0m Your commit contains files that should pass JSLint but do not. Please fix the JSLint errors and try again."
    echo -e $ERRORS_BUFFER
    echo 
    exit 1
else
    echo -e "\033[42mCOMMIT SUCCEEDED\033[0m\n"
fi

3. Save the above script in your git pre-commit file as below:

$ cd /project/directory/
$ vim .git/hooks/pre-commit

Paste the above content and save it. Then give execute permission to it.

$ chmod +x .git/hooks/pre-commit

And we are done and ready :)

Trying a sample case:

I have two js files named sample.js and another.js with below content:

sample.js:

var i = j;

for (key in names) {
    echo names[key];

}

another.js:

var i = []

Lets try to commit them:

$ git commit -m 'Error Commit' sample.js another.js

Below is the pre-commit check output:

Validating JavaScript:

JSLint Failed: sample.js
JSLint Failed: true.js

JavaScript validation complete

COMMIT FAILED: Your commit contains files that should pass JSLint but do not. Please fix the JSLint errors and try again.

 sample.js #1 'j' was used before it was defined. var i = j; // Line 1, Pos 9 #2 'key' was used before it was defined. for (key in names) { // Line 3, Pos 6 #3 Cannot read property 'kind' of undefined // Line 3, Pos 10

 true.js #1 Expected ';' and instead saw '(end)'. var i = [] // Line 1, Pos 11

The output can be formatted a little bit better to place each line error in a new line of its own. But this simple tool is pretty handy for checking js errors while committing :)

Sunday, 7 February 2016

How to generate text representation of an image using PHP?

We will learn how to convert an image to its text representation using PHP that can be used in an html page (if any such requirement arises in your application or just for fun sake :) ).


The steps followed to convert the image to text representation are:

1. Get the width and height of the image to be converted.
2. Loop through every pixel value in the image.
3. At every pixel value, find the color at that position.
4. Apply that color to a # symbol we use to represent that pixel.
5. Finally we get the text representation of the image represented by # (hashes).

Code:

<html>
    <body style="background-color: #000000;">
        <tt>
<?php

$img = imagecreatefromjpeg('red_leaf.jpg');
$dx = imagesx($img);
$dy = imagesy($img);

// Loop through each pixel in the image and check the color
// Then do something with that color data like display the # character
// at the appropriate color for each pixel.
for ($y = 0; $y < $dy; $y++) 
{
     for ($x = 0; $x < $dx; $x++) 
    {
         $col = imagecolorat($im, $x, $y);
         $rgb = imagecolorsforindex($im, $col);
         printf('<font color=#%02x%02x%02x>#</font>',
             $rgb['red'], $rgb['green'], $rgb['blue']);
    }

     echo "<br>\n";
}

imagedestroy($im);

?>
        </tt>
    </body>
</html>

Image used in the program:

Sample output can be seen here.

Cool isn't it :)

Friday, 5 February 2016

Associating git hooks with php syntax check

Many a times we have faced this problem that when we commit something and it breaks something on the server due to some syntax error.
I know that these can be caught by IDEs and good editors, but sometimes there might be an syntax error introduced after a code merge conflict resolution and commit.

To address this, we can use git pre-commit hooks to check for any syntax errors in the to be committed files.

There is a good script I found which does this at https://github.com/ReekenX/phpcheck-git

Steps to add pre-commit php syntax check with git:

(Issue below commands in your console)

1. $ cd /project/directory/

2. $ cd .git/hooks/

3. Get the pre-commit script file from above github page or from direct link: https://raw.githubusercontent.com/ReekenX/phpcheck-git/master/pre-commit

$ wget https://raw.githubusercontent.com/ReekenX/phpcheck-git/master/pre-commit

4. Give execute permission to it.

$ chmod +x pre-commit

This should be it :)

Now if you try to commit any php file, it will display message about any syntax error. If there are, then it will specify the file, error and line number where the error took place and will abort the commit.

This small tool will help us in better checking our code before being committed :)

Thursday, 4 February 2016

MVVM pattern as applied to Javascript


MVVM stands for Model, View and ViewModel pattern.

Application: Used in knockout.js library.

Role of each part:

Model - Handles the application's persisted data that is the data which the view page receives through an ajax request from the server(GET or POST). It can also be used to store the data which is passed to the page when the page is loaded for the first time with some data content, to be used later on client(browser) side.

View - It simply represents the html content. Each View is associated with a ViewModel. View changes according to changes in ViewModel(It's next in list).

ViewModel - It is basically a model for the view. It is a code representation of the data and the supported operations on it. The ViewModel is not usually used as a persisted storage medium but is meant to hold dynamic data and handle related operations. It basically holds the unsaved changes the user is working with. The data can be saved by posting it back to server.

                     ViewModels in knockout.js are implemented by POJOs(Plain Old Javascript Objects). For instance, if you are dispaying a list of todo notes(View), then your ViewModel might hold a list of such note objects and expose several functions to modify/add notes. Display of notes changes according to changes made to notes ViewModel.

Wednesday, 3 February 2016

Getting started with Redis

As per redis home page,

"Redis is an open source (BSD licensed), in-memory data structure store, used as database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs and geospatial indexes with radius queries."

Redis Installation Steps:

I am trying the below steps in an ubuntu 14.04 system. Open the terminal and issue the below commands:

1. Get the latest tar zip for redis (http://redis.io/download)

$ cd /path/to/download/directory/
$ wget http://download.redis.io/releases/redis-3.0.7.tar.gz

2. Untar it and issue below commands:

$ tar xf redis-3.0.7.tar.gz
$ cd redis-3.0.7
$ make
$ sudo make install

Getting started with Redis:

1. Run redis server in one console:

$ redis-server

or as a background process:

$ redis-server &

2. You can interact with redis now using the built-in client in console:

$ redis-cli
redis> set name Satej
OK
redis> get name
"Satej"

If you are a newbie at Redis like me, give a try at the online interactive tutorial: http://try.redis.io/. It's real fun and easy.

I learnt some basic data types and their related operations from the tutorial:
- integer
- string
- list
- set
- sorted sets
- hashes

What is scrolljacking?

Excerpt from http://paper-leaf.com/alton-jquery-scroll-jacking-plugin/
"Scrolljacking basically means we replace native scrolling (what you’re used to) with targeted scrolling: when the user initiates a scroll, either with their mouse or keyboard, scrolljacking takes them to an exact vertical point on the screen (for example, the top of the next content container). When done properly, scrolljacking can be a part of a unique, enjoyable online experience."
The above definition makes it quite clear what scrolljacking is.

Excerpt from http://www.sitepoint.com/scrolljacking-accessibility/
"Recently, Apple came up with the new concept of ‘scrolljacking’ in their product pages. This is method that ‘re-wires’ the behavior your browser’s scrollbar to display the content as a set of slides — instead of its traditionally vertical movement."
Note: There can be accessibility issues with scrolljacking as has been mentioned in the link above.

A jQuery plugin I came across that helps in achieving this: http://paper-leaf.com/alton-jquery-scroll-jacking-plugin/

Sunday, 6 September 2015

Session logout fix with CodeIgniter framework when dealing with ajax requests and iframes in SPA applications

Recently, we had an issue in our application which is a single page application(SPA). We have all the functionality in a single page and most of the data and view changes happen through ajax requests and iframe page displays.
We are using CodeIgniter framework for this application. So sometimes what happened was the user was logged out while accessing the application and this occurred once a while for 1 or 2 users, not a reproducible case one would say.
Before starting on the case, I would like to specify the steps which CodeIgniter takes for checking session for any request.
Steps:
1. Read session cookie sent from browser.
2. Read session cookie process proceeds with below step checks (If any one step fails below, it results in create one session cookie)
2a. Checks if session cookie is present
2b. Checks if it is a valid session cookie by using it's decryption algorithm check
2c. If  valid session, then check if it is expired
2d. Check for config related options if enabled like check ip, check useragent etc.
2e. If database enabled then check session is present in database
3. If a valid cookie is found, then check if it needs update since its last activity update which is determined by below condition, update database if enabled with updated cookie and send the updated cookie (even if not updated in database) to browser.
($this->userdata['last_activity'] + $this->sess_time_to_update) < $this->now
The problem which occurs is related to step 3 when update of session cookie happens.
There are two versions of CodeIgniter I would like to discuss here for step 3:
1. CodeIgniter Version 2.2.0: Session update happens for all requests that is page reloads and ajax requests.
2. CodeIgniter Version 2.2.1 and above: Session update happens only for page reload requests and not for ajax requests.
So for case 1, if the issue would occur if there are many ajax requests happening from browser at same time and for case 2, it would occur if you are making multiple iframe requests at same time from SPA application.
Note this issue happens only if there are simultaneous requests happening related to respective versions as described above and the server detects a session cookie update case. Given that these are the two conditions which need to be satisfied for the issue to occur, it happens sometimes(very rarely).
Request flow and session cookie setting process flow
Explanation:
Let me explain the issue. I will be using the term requests instead of the respective detailed requests for respective CodeIgniter versions.
So lets say in our SPA application, "A" is the session cookie value stored in the browser and two requests R1 and R2 happen at same time (both will have cookie request value "A") and reach the CodeIgniter server at same time.
Note the session value in database is "A" which must match browser cookie one.
Lets say R1 is first processed by the server. So server checks it is a valid cookie and detects that it needs an update. So it generates a random cookie "B" and updates database session where old session is A. So in database, new value is now "B" and then sends updated cookie value to browser. So now the cookie value in browser is updated from "A" to "B".
After that R2 is then being processed by the server. The request still contains the old cookie session value "A" and same old last updated time. So server detects that it needs an update and generates a random session value "C" and tries to update the value in database where old_value is "A", which is not present any where. So the update does not occur, but it nevertheless sends the update cookie data with "C" to the browser. So now the cookie value in browser is updated from "B" to "C".
So now when you make any new request from the SPA application, it will use cookie session value "C" and while trying to read the session from database, it won't find the value in database(since the update had not been done to "C" and the current value in database is "B") and will destroy your session.
Solution:
The main issue here is with the second request R2, which could not update the value in database but sent an updated cookie value to browser which it should not. So this can be solved by checking if any rows were affected in database and then only sent updated cookie session data to browser. So in this case generated random value "C" would not be sent to browser and new requests would use "B" value which is still present in the browser.
Original code in sess_update() function in Session library:

// Update the session ID and last_activity field in the DB if needed
if ($this->sess_use_database === TRUE)
{
    // set cookie explicitly to only have our session data
    $cookie_data = array();
    foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
    {
        $cookie_data[$val] = $this->userdata[$val];
    }

    $this->CI->db->query($this->CI->db->update_string($this->sess_table_name, array('last_activity' => $this->now, 'session_id' => $new_sessid), array('session_id' => $old_sessid)));
}

// Write the cookie
$this->_set_cookie($cookie_data);
Modified fixed code:

// Update the session ID and last_activity field in the DB if needed
if ($this->sess_use_database === TRUE)
{
    // set cookie explicitly to only have our session data
    $cookie_data = array();
    foreach (array('session_id','ip_address','user_agent','last_activity') as $val)
    {
        $cookie_data[$val] = $this->userdata[$val];
    }

    $this->CI->db->query($this->CI->db->update_string($this->sess_table_name, array('last_activity' => $this->now, 'session_id' => $new_sessid), array('session_id' => $old_sessid)));

    if ($this->CI->db->affected_rows())
    {
        // Write the cookie
        $this->_set_cookie($cookie_data);
    }
}
else
{
    // Write the cookie
    $this->_set_cookie($cookie_data);
}
This finally fixed the issue. Hope it helps :)