Monthly Archives: March 2013

Hymn World 0.3 release

Published March 27, 2013 2:20 pm

This release contains some new additions of hymns.

  1. Rejoice, O Pilgrim Throng
  2. Were You There?
  3. Within the Father’s House
  4. The Lord’s My Shepherd and
  5. a second translation of A Mighty Fortress Is Our God, using the isorhythmic version of the tune.

Uploading image to azure blob from windows store app

Published March 22, 2013 11:11 am


msdn gives quick start to upload image file using background transfer.  but I was looking for way to upload image file using WinJS.xhr() in the javascript app.

Windows.Storage.Pickers.FileOpenPicker.pickSingleFileAsync() returns StorageFille object  whereas WinJS.xhr.send() expects a File DOM object. Essentially, what we need is way to get a w3c File DOM object out of StorageFile object. I found finally the method MsApp.createFileFromStorageFile() to do that.

// url needs to be SAS (shared access signature) url for the blob when the container is protected
// otherwise - it requires putting authorization code in the request. I have talked about in previous post.
// but if the javascript is in the client side - you wont like to put your client secret in the app.
// hence, you need to have some mechanism (your service) to return the sas url for your azure container/blob. 

    var url = '';
    var date = new Date().toGMTString().replace('UTC', 'GMT');
    var data = MSApp.createFileFromStorageFile(storageFile);
    var xhrOptions = {
        type: 'PUT',
        url: blobSasUrl,
        headers: {
            'Content-Type': 'image/jpeg',
            'Content-Length': data.size,
            'x-ms-date': date,
            'x-ms-version': '2009-09-19',
            'x-ms-blob-type': 'BlockBlob',
        },
        data: data,
    };
    WinJS.xhr(options).then(null, function onerror(error)
    {
        // handle error
    });

I see that many of us need to upload images to azure blob containers. If you are one of us, it will help to know little bit more to help you better.

Putting a blob in azure from windows store app in javascript

Published March 21, 2013 6:18 pm


I need to put a blob into azure from my windows store app that is being coded in javascript. I did not find azure javascript client lib. Azure does have nodejs sdk but did not find azure javascript client lib. Hence, I coded up my first put blob rest api call. The most tricky part in the code is to generate the authorization shared key. Rest is simply adding properties into XHR call options parameters.

Refer the code below.

var url = 'http://mystorageaccount.blob.core.windows.net/mycontainer/myblob';
                var date = new Date().toGMTString().replace('UTC', 'GMT');
                var xhrOptions = {
                    type: 'PUT', url: url,
                    headers: {
                        'Content-Type': 'application/octet-stream',
                        'Content-Length': contentLength,
                        'x-ms-date': date,
                        'x-ms-version': '2009-09-19',
                        'x-ms-blob-type': 'BlockBlob',
                        data: data
                    }
                };
                var options = { storageAccount: 'mystorageaccount', resourcePath: 'mycontainer/myblob', primaryKey: 'myprimarykey' };
                var authorizationHeaderValue = authorizationHeader.compute(options, xhrOptions);
                xhrOptions.headers.Authorization = authorizationHeaderValue;
                WinJS.xhr(xhrOptions).done(function oncomplete(req)
                {

                }, function onerror(error)
                {
                });
var authorizationHeader = 
{
        /*
        options - refer call to this method
        xhrOptions - parameter for the WinJS.xhr call. computed Authorization header will be used this xhr request only.
        */
        compute: function compute(options, xhrOptions)
        {
            var sig = this._computeSignature(options, xhrOptions);
            var result = 'SharedKey ' + options.storageAccount + ':' + sig;
            return result;
        },
        _computeSignature: function computeSignature(options, xhrOptions)
        {
            var sigString = this._getSignatureString(options, xhrOptions);
            var key = CryptoJS.enc.Base64.parse(options.primaryKey);
            var hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key);
            hmac.update(sigString);
            var hash = hmac.finalize();
            var result = hash.toString(CryptoJS.enc.Base64);
            return result;
        },
        _getHeaderOrDefault: function getHeaderOrDefault(headers, headerName)
        {
            var result = headers[headerName];
            result = result ? result : '';
            return result;
        },
        _getSignatureString: function createSignatureString(options, xhrOptions)
        {
            var headers = xhrOptions.headers;
            var httpVerb = xhrOptions.type.toUpperCase();
            var sigItems = [];
            sigItems.push(httpVerb);
            var contentEncoding = this._getHeaderOrDefault(headers, 'Content-Encoding');
            sigItems.push(contentEncoding);
            var contentLanguage = this._getHeaderOrDefault(headers, 'Content-Language');
            sigItems.push(contentLanguage);
            var contentLength = this._getHeaderOrDefault(headers, 'Content-Length');
            sigItems.push(contentLength);
            var contentMD5 = this._getHeaderOrDefault(headers, 'Content-MD5');
            sigItems.push(contentMD5);
            var contentType = this._getHeaderOrDefault(headers, 'Content-Type');
            sigItems.push(contentType);
            var date = this._getHeaderOrDefault(headers, 'Date');
            sigItems.push(date);
            var ifModifiedSince = this._getHeaderOrDefault(headers, 'If-Modified-Since');
            sigItems.push(ifModifiedSince);
            var ifMatch = this._getHeaderOrDefault(headers, 'If-Match');
            sigItems.push(ifMatch);
            var ifNoneMatch = this._getHeaderOrDefault(headers, 'If-None-Match');
            sigItems.push(ifNoneMatch);
            var ifUnmodifiedSince = this._getHeaderOrDefault(headers, 'If-Unmodified-Since');
            sigItems.push(ifUnmodifiedSince);
            var range = this._getHeaderOrDefault(headers, 'Range');
            sigItems.push(range);
            var canonicalizedHeadersString = this._getCanonicalizedHeadersString(xhrOptions);
            sigItems.push(canonicalizedHeadersString);
            var canonicalizedResource = this._getCanonicalizedResource(options);
            sigItems.push(canonicalizedResource);

            var result = sigItems.join('\n');
            return result;
        },
        _getCanonicalizedHeadersString: function getCanonicalizedHeadersString(xhrOptions)
        {
            var headers = xhrOptions.headers;
            var headerNames = Object.keys(headers);
            var lowercaseHeaderNames = headerNames.map(function tolower(name)
            {
                return name.toLowerCase();
            });
            var msHeaderNames = lowercaseHeaderNames.filter(function isMsHeader(name)
            {
                if (name.indexOf('x-ms-') == 0)
                    return true;
                else
                    return false;
            });
            msHeaderNames.sort();
            var strItems = [];
            for (var i = 0; i < msHeaderNames.length; i++)
            {
                var key = msHeaderNames[i];
                var value = headers[key] || '';
                value = value.trim();
                var item = key + ':' + value;
                strItems.push(item);
            }

            var result = strItems.join('\n');
            return result;
        },
        _getCanonicalizedResource: function getCanonicalizedResource(options)
        {
            var items = [];
            var path = "/" + options.storageAccount;
            path += "/" + decodeURIComponent(options.resourcePath);
            items.push(path);
            // TODO: handle storage rest api query parameters. 
            // need to add them to options and items 
            // as described here - http://msdn.microsoft.com/en-us/library/windowsazure/dd179428.aspx#Constructing_Element
            var result = items.join('\n');
            return result;
        }
    }

Notes

  1. Code uses the google code crypto lib –  – need to download the zip, extract and use rollups\hmac-sha256.js and components\enc-base64-min.js from the zip file.
  2. CryptoJS.algo.HMAC.create expects the key to be in utf8 or wordskey. Hence, the azure base64key needs to be decoded prior to passing to the call. Thanks to iug to give lead in this.
  3. hmac.update(message) call encodes the message string using utf8. hence, we are good there.

Weekly shopping things

Published March 17, 2013 10:49 pm

I am next looking into building something to help people with weekly shopping things. During my visit to a mega market for grocery shopping, I was just watching people doing shopping. Here is what I observed:

  1. Young-girls were busy with deodorant testing to choose the right fragrance. They did not plan for it. They just decided to get one, and were not in hurry. They talked about many of them and then, picked one.
  2. Two brothers with wives in a discussion; they consume 2 kg of daal and no harm in taking one more packet of daal, and whether the rice quality is good.
  3. 40 something friends with store coupons in hand – surfing the store.
  4. On a busy Sunday evening in the market, it was interesting to see that only few of them cared to carry a list of items they wanted to purchase. I was at one time thinking shopping list to be key element for such app; still I found couple of them carrying yellow sticky note, small notebook paper portion with items listed there which they referred quite often. Interesting point here was      that some of them had it written in their native language (likely Telugu), not English.
  5. One 45-50 something person – he was so organized to have full list of items written so legibly hand written with number bullets that I was awed.
  6. Two 20 something friends busy finding a product with image displaying on their Samsung galaxy; finding it hard to find it in the huge store. If there was someone who told whether the product existed in the store and where – I guess they would have happy!
  7. Family with teenagers – all of them enjoying the grocery shopping together.
  8. 20 something software engineer with mom – mom telling what she wants, and son looking around and getting it.
  9. Boyfriend with Samsung galaxy tab, and girlfriend with also with likely a smart phone, hand in hand, one shopping basket – busy discussing something other than shopping – nothing in the basket!
  10. House wife – busy finding product with the most recent manufactured date.
  11. I guess I found 1-2 people referring something on their smartphones that looked something to do with what they wanted to shop – one was WP8 yes! And one was likely Samsung note.
  12. Many of them simply moving from one ally to next ally in the store to pick what the need to – window shopping. Not in hurry!
  13. Seen few of the foreigners buying mostly soft drinks at the store.
  14. Alphonso Mangoes new in the store – many checked the price and moved.
  15. Crowd stood in front of the TV section when the Michael Jackson song (It’s dangerous) played on all the screen. Everyone watched it likely national anthem – no one moved until the song completed!

While one visit is hard to conclude behaviors, but few things stand out for this visit:

  1. Not many people shop with goal to ‘get it done’. They are just there for many other reasons that range from – surf, explore, hangout together or simply time pass. Shopping is likely secondary or side activity for this set.
  2. ‘get it done’ shopper is likely 30-45 range. Less than 30 are just there to hangout; greater than 45 are also likely there to kill time in the store.

More after next visit.

Hymn World feedback

Published March 7, 2013 11:02 am

3/3/2013 2:25 AM

Missing many good hymns  Jeremy 3-start-rating

Such as Victory in Jesus, The Solid Rock, The Lily of the Valley, I Have Decided to Follow Jesus, Were You There, Sweet Hour of Prayer, etc. Also A Mighty Fortress uses an unpopular translation. There are also duplicates of Christ the Lord is Risen Today. On the other hand, the ability to print scores is very nice.

Jeremy – thanks for taking time to write feedback. We do take feedback seriously. Regards the missing hymns – we are only able to bring the hymns which are in public domain; they are analyzed, formatted & published by our hymn expert. Also note that he is a volunteer. So – after new hymn request it may take some time.

Victory in Jesus –  there are multiple hymns titled “Victory in Jesus”, but the most popular one (and I’m guessing the requested one) was written in 1939 and is still under copyright protection.

The Solid Rock – is already present. The actual title of the hymn is “My Hope is Built”.

Christ the Lord is Risen Today (Lyra) –  you’re correct that there have same lyrics. But they have different tunes used for the same lyrics.  There are actually multiple hymns in the same situation, including “Blest Be the Tie that Binds”, “Dear Christians One and All Rejoice”, “Happy the Man Who Feareth God”, and numerous others.  Most of them are old hymns whose usage grew up in different places with different tunes. We will see if we can add the tune name in the title to bring more clarity.

A Mighty Fortress – This is a difficult question.  There are many translations and composites out there. Translations continue to be tweaked and reworked in modern days, and the translation that is mostly used in the USA today might be that in the ecumenical “Lutheran Book of Worship”, which is copyright 1978.  It is such a “core” hymn that everyone likes their own.  The more common one is the revision of that tune by Bach.  In this case, we will see if we can add second translation using the Bach version of the tune.

Amortization Schedule Calculator

Published March 6, 2013 4:15 pm

amor-calc-promo-414x180

Amortization schedule calculator is a must have calculator to calculate EMI and manage payments for your home mortgage, auto loan or any other kind of loans. Whether you are computing amortization schedules to decide on a loan, managing existing loans payments or considering to do extra principal payments to get debt free early – this application will help you.

Given the loan amount, term, interest rate, additional principal payments (if any) and the start date, it gives you the monthly payment schedule for the term of the loan. Each monthly payment has the interest and principal component breakup. It lets you share the schedule by mail or save to a csv file.

Last 5 computations are saved for your reference. They will be available for future reference on all your windows 8 devices.

It will help you get visibility into your loan interest and principal payments month by month. It can help you see how extra principal payments impact future payments, and reduce the term of the loan. You can track multiple loan schedules by referring your last computations.

Hymn World

Published March 6, 2013 10:26 am

StorePromo-414x180

Welcome to the world of hymns. Imagine yourself browsing through your favorite hymns – reading the lyrics, watching the score and playing their music. You can also print it for your reference. If you love hymns, Hymn world is for you!

Hymn world lets you explore the world of hymns. It lets you refer the lyrics and scores; play music of hundreds of hymns in public domain. You can search using part of the title of the hymn.

Stay tuned for more!