Search: 

Machine translation:
MBBSoftware
Creating software for businesses, professionals, and the home
our sites: MBBSoftware - Custom Image Presenter - Authenticate Testimonial
MBBSoftware Blog - Complete .Net to JavaScript Encoding Hi guest
Sign up
Login

Complete .Net to JavaScript Encoding


By Miroslav B. Bonchev
There are times when one wants to insert data to be used by JavaScript functions on the webpage from the code behind. This is quite straightforward if the data is plain text without escape characters, but slightly more complex if there are escape sequences and special symbols in the text. The difficulty comes from the fact that there is no bijective conversion between the encoding and decoding functions provided by JavaScript and the .Net environments. The escape()/unsecape() functions of JavaScript have no .Net equivalent at all and the other JavaScript encoding functions such as encodeURI()/decodeURI() and encodeURIComponent()/decodeURIComponent() cannot be coupled with the .Net System.Text.Encode functions since they behave equivalently on only a limited subset of the typically used escape or special characters, and thus I could not use these functions either.

The solution was to create my own encoding. In the particular case when the problem came to me, I needed to embed text parameter to a JavaScript function call which would be called when a link was pressed. The text parameter was in fact YouTube video embedding string which contains ", <, > and other escape and special characters requiring attention. Armed with some old assembly language skills, I created a simple and coherent encoding and resolved the problem as shown below.

On the server side I used typical C# code to format the link text in a dynamically created page and table in it. In other cases one might have used the Register-Script API or another more suitable approach to embed the JavaScript invoking code into the webpage. In this piece of code the string EncodeA2P( string ) is the encoding function which we will explain shortly. EncodeA2P takes the escape and special symbols containing string and returns it as an encoded string with no escape or special characters in it, and thus it will not interfere with the page and JavaScript processing on the client side.


              tcVideo.Text = string.Format( "<a href='#' onclick='javascript:SetVideo( \"{0}\" );'>{1}</a>", 
                                        EncodeA2P( strYouTubeEmbedString_FromDatabase ), 
                                        strVideoTitle_FromDatabase);
    
public static string EncodeA2P( string strToEncode ) { return( EncodeA2P( System.Text.Encoding.UTF8.GetBytes( strToEncode ) ) ); }
public static string EncodeA2P( byte[] strDataToEncode ) { int Length = strDataToEncode.GetLength( 0 ); char[] Destination = new char[2*Length]; for( int Index = 0; Index < Length; Index++ ) { byte b1Byte = strDataToEncode[Index]; char b1MSHB = (char)( b1Byte >> 0x04 ); char b1LSHB = (char)( b1Byte & 0x0F ); Destination[2 * Index] = (char)('A' + b1MSHB); Destination[2 * Index + 1] = (char)('A' + b1LSHB); } return( new string( Destination ) ); }


The string EncodeA2P( string ) function takes a string with any possible character in it and returns an ASCII-A2P encoded string. To the best of my knowledge, there is no such well known definition so I will define it now. The name ASCII-A2P stands for American Standard Code for Information Interchange - A to P or ASCII from A to P.

Definition: ASCII-A2P is encoding in which every half byte from the encoded string is represented as an ASCII character, in a hexadecimal base counting system, where the zero is represented by 'A' and 15 by 'P'.

I could have used the ASCII characters of the respective hexadecimal numbers in the encoded string but that would make the conversion slightly more complicated absolutely unnecessary. The string EncodeA2P( string ) function takes the data of the string passed to it as a byte array, and passes it to its override string EncodeA2P( byte[] ) which does the actual conversion. This embedding of calls is done for design considerations, explained at the end of the article. The string EncodeA2P( byte[] ) takes the byte array holding the data to be encoded, in my case the data of YouTube video embedding strings and returns ASCII-A2P encoded string. For those who are not familiar with binary arithmetic, I will explain the function in more detail. A byte in hexadecimal base counting system looks like this: 0xYY where Y is a number from 0 to 9, A (=ten), B (=eleven), C, D, E or F (=fifteen), thus a byte covers all numbers from 0x00 to 0xFF (0 to 255 in decimal). The way in which the string EncodeA2P( byte[] ) function works is that it takes each byte from the array passed to it and splits it into two halves: left (more significant) and right (less significant). Each of these half bytes is actually a number on its own with value from 0 to 0x0F (0 to 15 decimal). Then each of these numbers are converted to ASCII symbols by adding 'A' to them. Thus every 0 becomes 'A', 1 becomes 'B', ... 0x0E (14 decimal) becomes 'O' and 0x0F (15 decimal) becomes 'P'. Then the function concatenates these characters in a straight order to produce the new string which is returned as the encoded representation of the byte array passed to the function.



On the client side, I created the inverse function to decode the ASCII-A2P encoded data into the original string, which is placed in the script section of the head of the page. Note that the SetVideo( string ) function which calls the DecodeA2P( ASCII-A2P ) function is the one referenced in the dynamic link building which we mentioned in the beginning.
              function DecodeA2P( strEncodedText ) 
              { 
                if( 1 == (1 & strEncodedText.length) )
                { 
                  throw "Not an ASCII-A2P encoding 1."; 
                } 

                var arrayResult = new Array(); 
                strEncodedText = strEncodedText.toUpperCase(); 

                for( var Index = 0; Index < strEncodedText.length; Index += 2 )
                { 
                  var sb1MSB = strEncodedText.charCodeAt( Index ) - 65;
                  var sb1LSB = strEncodedText.charCodeAt( Index + 1 ) - 65;

                  if( (15 < sb1LSB) || (15 < sb1MSB) )
                  { 
                    throw "Not an ASCII-A2P encoding 2."; 
                  } 

                  arrayResult[Index/2] = (sb1MSB << 4) | sb1LSB;
                } 

                return( arrayResult ); 
              } 

              function DecodeA2PAsString( strEncodedText ) 
              { 
                var strResult = ""; 
                var arrDecoded = DecodeA2P( strEncodedText ); 

                for( var Index = 0; Index < arrDecoded.length; Index++ ) 
                { 
                  strResult = strResult + String.fromCharCode( arrDecoded[Index] ); 
                } 

                return( strResult ); 
              } 

              function SetVideo( varURL ) 
              { 
                parent.document.getElementById( "cellTV" ).innerHTML = DecodeA2PAsString( varURL ); 
              }


The SetVideo( string ) function gets called when the link in which its reference is embedded is clicked, and the encoded video embedding string is passed to it. SetVideo( string ) calls DecodeA2PAsString( ASCII-A2P ) to decode the video embedding code (in my particular task) and injects the decoded YouTube embedding code into the target cell of a table where the YouTube video player will be displayed. DecodeA2PAsString( ASCII-A2P ) in turn calls the DecodeA2P( ASCII-A2P ) which actually does the work.

The DecodeA2P( ASCII-A2P ) function works as follows: first it tests that the passed string has an even length. Then it sets the string to upper case, just in case someone/something changed the case of the ASCII-A2P encoded data. It then takes every two characters from the encoded data in sequences of pairs and subtracts 65 ('A') from each number. Thus any 'A' becomes zero, 'B' becomes 1, ... 'O' becomes 0x0E (14 decimal) and 'P' becomes 0x0F (15 decimal). Then the left symbol, which was the most important half of the original number, is shifted 4 bits to the left and merged with the less significant part using a bitwise OR. Thus DecodeA2P( ASCII-A2P ) returns an array of decoded bytes which is the same as the array passed to string EncodeA2P( byte[] ) on the server side. DecodeA2PAsString( ASCII-A2P ) converts that array of bytes to a string concatenated in a straight order to result in the original string (passed to string EncodeA2P( string ) on the server side), which is finally returned to the SetVideo( string ) function to be inserted into the table cell.


In conclusion I will make a brief analysis of the results and the ASCII-A2P encoding. The method solves the problem beautifully as I am now able to encode any string and pass it with no fear of character being incorrectly decoded. The ASCII-A2P encoding has some advantages and some drawbacks. ASCII-A2P is always twice the size of the original string. This is good from a predictability point of view, but in most cases would probably yield in a larger encoded string than EncodeURL; however in cases where there are many escape/special characters ASCII-A2P may even produce smaller encoded data than EncodeUrl. A disadvantage of ASCII-A2P encoding is that generally it is unreadable by humans while the EncodeURL can be read by the developer "AS IS", for example, for debugging purposes. Another advantage of ASCII-A2P is that unlike EncodeURL, it encodes the data homogenously: all characters are handled in a consistent way. Yet another advantage is that ASCII-A2P is error aware, as the encoded symbols are in a range, thus any symbol outside of that range is an indication of an error. Further, since ASCII-A2P encoded data always has even length, if an encoded data has odd length then it necessarily contains an error.

The string EncodeA2P( string ) and its inverse DecodeA2P( ASCII-A2P ) are the functions that I needed to solve my problem. However, notice that the ASCII-A2P encoding actually works on binary data, which is much more generic and powerful than working on strings only. For this reason I created the binary overrides of the ASCII-A2P encoding and decoding (string EncodeA2P( byte[] ) and byte-array DecodeA2P( ASCII-A2P )) as the central functions, which I wrapped with string interfacing overrides which I needed for this particular solution. In this manner I achieve optimal design and reuse of the code.
Miroslav B. Bonchev
24-th July 2012
London, England
We would love to know your thoughts and opinions on this article. Please leave any comments or questions you may have about it in the box below, and create a free account or subscribe to our newsletter if you wish to be notified when we publish new articles.
Community Content
(To enter your comments you must be signed in. Log in or create FREE account.)
MemberComments
Be the first to comment.
Products
Act On File
Audio Control
Custom Image Presenter
Photo Window
Vat # Validator
Custom Image Presenter
Homepage
for Galleries and Museums
for Hotels, Resorts and Cruises
for Parks of any kind
for Any Business
Learning
Encryption and Authentication
Safe Online Communication
Authenticable Website Testimonials
Learn how to store private keys
Make The Most From Your Files
Convenient Volume Control
Photo Window - an Awesome Gift
Support
My Account
FAQ - Forum
 
Community
Blog
Email this page
Newsletter
MBBSoftware
About
Contact
Buy Now
Download
Public Authentication Key
Public Encryption Key

Sitemap
Disclaimer
Privacy
Antispam
© Copyright 2017 MBBSoftware. All Rights Reserved.

Email this page
To:
use semicolon to separate emails eg: joe@abc.com; lea@abc.com
Subject:
Message:
a link to this page will be automatically added to your message
From:
Please type the anti-bot text below.
Type text:
Thank you for subscribing to the MBBSoftware newsletter.
Enter your email address:
Please type the anti-bot text below.
Type text: