Archive

Author Archive

2011 in review

Categories: Uncategorized

Lucene example, free text search on .NET DataSet

If you don’t have Free Text Search for your SQL server database, then you can use Lucene.NET to run free text searches on DataSets.

First you have to build up a Full text index (on disk), based on an SQL statement:

        var strIndexRoot = Server.MapPath("FT");
        if (System.IO.File.Exists(strIndexRoot + @"\write.lock"))
        {
            System.IO.File.Delete(strIndexRoot + @"\write.lock");
        }
        Directory directory = FSDirectory.GetDirectory(strIndexRoot);
        Analyzer analyzer = new StandardAnalyzer();
        IndexWriter writer = new IndexWriter(directory, analyzer);        
        var strSQL = "select id,text from yourTable";       
        System.Data.DataSet ds = ExecuteDataSet(strSQL);
        foreach (DataRow dr in ds.Tables["sql"].Rows)
        {
            Document doc = new Document();
            doc.Add(new Field("id", dr["id"].ToString() , Field.Store.YES, Field.Index.NO));
            doc.Add(new Field("postBody", dr["text"].ToString(), Field.Store.YES, Field.Index.ANALYZED));
            writer.AddDocument(doc);            
        }
        writer.Optimize();
        writer.Flush();
        writer.Close();

You need to have a folder called “FT” (Free text) as a subfolder of your ASP.NET root folder.
I’ve omitted the code for “ExecuteDataSet”, it’s just a call to the database with an SQL command.

The FT folder will have the files:
segments.gen
segments_2
_0.cfs

Once the Free Text Index is generated.

Then to Query the free Text Index, I used the code:

       var strIndexRoot = Server.MapPath("FT");        
        if (IO.File.Exists(strIndexRoot + @"\write.lock"))
        {
            IO.File.Delete(strIndexRoot + @"\write.lock");
        }
        Directory directory = FSDirectory.GetDirectory(strIndexRoot);
        Analyzer analyzer = new StandardAnalyzer();
        IndexWriter writer = new IndexWriter(directory, analyzer);
        QueryParser parser = new QueryParser("postBody", analyzer);
        Query query = parser.Parse("User Query goes here");
        //Setup searcher
        IndexSearcher searcher = new IndexSearcher(directory);
        //Do the search
        Hits hits = searcher.Search(query);
        int hitNumber = hits.Length();        
        for (int i = 0; i < hitNumber; i++)
        {
            Document doc = hits.Doc(i);
            var id = doc.Get("id");
            var text = doc.Get("postBody");
        }
        searcher.Close();
        directory.Close();
Categories: Uncategorized

Getting a numeric value for the similarity of two text values in SQL Server

If you don’t have the luxury of a full text index on your free SQL server express database, or can’t set it up, because someone else manages or hosts, it, then a work around is this function that returns a numeric value for the similarity of two text values (which can be used as an order-by clause later)

create function func_similarity
(@TextBody varchar(8000),
@SearchTerm varchar(4000))
returns int
as
BEGIN
if ( @SearchTerm = @TextBody ) return 2
if ( @Textbody like '%' + @SearchTerm + '%') return 1
if ( @SearchTerm like '%' + @Textbody + '%') return 1
return 0
END

In my case, I was looking for a ‘kind of’ free text lookup on a table of US zip codes:

create proc FindUSPostcode
@city varchar(100)
as
select top 10 * from postcodeus
order by
dbo.func_similarity(Town,@city)
+ dbo.func_similarity(City,@city)
+dbo.func_similarity(state,@city)
desc

This meant that a lookup for

FindUSPostcode('Detroit')

Returns a top result for Detroit, Maine (Somerset county). But ‘Detroit, MI’ returns a top result for Detroit Michigan.

An API will come soon! (postcodefinder.org.uk)

Categories: Uncategorized

Single Image from Flikr using API in AJAX

Here is a code example of how to get one single image out of Flikr, and place it into a html page using AJAX.

Just call getImageFromFlikr with the search text, and an output element. It works asynchronously, so it will return as soon as Flikr is contacted.

function getImageFromFlikr(searchText, output)
{
try
{
xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState!=4) return;
if (xmlhttp.status != 200)
{
output.innerHTML = “Error”;
}
if (xmlhttp.status == 200)
{
output.innerHTML = eval(xmlhttp.responseText); //retrieve result as an JavaScript object
}
}
var strUrl = “http://api.flickr.com/services/rest/?&#8221;;
strUrl += “method=flickr.photos.search”;
strUrl += “&api_key=cabbc1b68c18461ca0627991833d8f97”;
strUrl += “&text=” + encodeURIComponent(searchText);
strUrl += “&per_page=1”;
strUrl += “&format=json”;
strUrl += “&sort=relevance”;
xmlhttp.open(“GET”,strUrl,true);
xmlhttp.open(“GET”,strUrl,true);
xmlhttp.send();
}
catch (err)
{
output.innerHTML = err.message;
}
}

function jsonFlickrApi(flikrObj)
{
var fmt=”http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{secret}_m.jpg”;
fmt = fmt.replace(“{farm-id}”,flikrObj.photos.photo[0].farm);
fmt = fmt.replace(“{server-id}”,flikrObj.photos.photo[0].server);
fmt = fmt.replace(“{id}”,flikrObj.photos.photo[0].id);
fmt = fmt.replace(“{secret}”,flikrObj.photos.photo[0].secret);
var html = “<img src='” + fmt + “‘>”;
return html;
}

Categories: Uncategorized

Find Backlinks to a website using AJAX

 One of the most basic SEO tools is a backlink checker, and if you need to fine tune this, then automating the check will save you lots of time, so this is my experience with the SEOMOZ links API  using AJAX.

The basis of the API, is a call to the URL: http://lsapi.seomoz.com/linkscape/links/<URL>?Scope=page_to_page&Sort=page_authority where <URL>  is the site in question. This throws up the basic HTTP authentication challenge, so I’ve included the username and password:
Your Access ID: member-2dd03f462e
Your Secret Key: 018a47ae0940f6342577b24dfce80a5f

This code requires the Base64.js code library from www.webtoolkit.info, to base64 encode the HTTP authentication. Note that this code will only work when run locally from Internet Explorer, it won’t work hosted online due to cross-domain restrictions.

  <input type="text" name="input" id="input" value="www.xyz.com">
  <input type="button" onclick="BacklinkCheck()" value="Check">
  <br>
  <div id="output"></div>
  <script language="javascript">
   function BacklinkCheck()
   {
	    var auth = authenticate('member-2dd03f462e','018a47ae0940f6342577b24dfce80a5f');
		var input = document.getElementById("input");
		var output  = document.getElementById("output");
		output.innerHTML = "working...";
		var http=new XMLHttpRequest();
		var url = "http://lsapi.seomoz.com/linkscape/links/"
		url += input.value + "?Scope=page_to_page&Sort=page_authority";
		http.open("GET", url, true);
		http.setRequestHeader('Authorization', auth);
		http.setRequestHeader('Content-type', 'text/html; charset=unicode');
		http.onreadystatechange = function() {//Call a function when the state changes.
			if(http.readyState == 4 && http.status == 200) {
				 var html = "<table>"
				 var jsondata=eval("("+http.responseText+")");
				 jsondata = jsondata.sort(
					function(a, b){
					 if (a.upl < b.upl) //sort string ascending
					  return -1
					 if (a.upl > b.upl)
					  return 1
					 return 0 //default return value (no sorting)
				   });
				  for (i in jsondata )
				 {
					var backlink = jsondata[i];
					if (i % 2 == 0)
					{
						html += "<tr>"
					}
					else
					{
						html += "<tr>"
					}
html += "<td width=50%><a onclick=\"this.innerHTML='" + backlink.uu.replace('\'','') + "'\">"+ backlink.upl + "</a></td>";
html += "<td width=50%>" + backlink.ut + "</td>";
html += "</tr>";
}
html += "</table>";
output.innerHTML = html;
}
if(http.readyState == 4 && http.status != 200)
{
alert("Something went wrong");
}
}
http.send(null);
}

function authenticate(user, password) {
var tok = user + ':' + password;
var hash = Base64.encode(tok);
return "Basic " + hash;
}
</script>
Categories: Uncategorized

Convert text to a HTML table

 Here is a handy litte script that converts tabulated text into a HTML table. Apply a CSS stylesheet to it, and it’ll look nice too …

  <textarea id="input" cols=100 rows=10>
  </textarea><br>
  <input type="button" id="Tabelize" onclick="tabilize()" value="tabilize">
  <div id="output"></div>

<script language="javascript">
 function tabilize()
 {
	var input = document.getElementById("input");
	var output = document.getElementById("output");	
	var splitInput = input.value.split("\n");
	var html = "<table>";
	for(i in splitInput)
	{
	   if (i % 2 == 0)
	   {
			html += "<tr>";
	   }
	   else
	   {
	        html += "<tr>";
	   }
	   var splitRow = splitInput[i].split("\t");
	   for(j in splitRow)
	   {
	     html += "<td>" + splitRow[j] + "</td>";
	   }
       html += "</tr>";
	}
    html += "</table>";
	html = html.replace(/</g,"&lt;");
    html = html.replace(/>/g,"&gt;"); 
	output.innerHTML = html;
 }
</script>
Categories: Uncategorized

Open Source Pastebin in .NET

A pastebin is designed to be an easy way to quickly post some text online, so that others can see it. It also has applications in cross-firewall data traversal, where one peer can upload data to a pastebin, and the other peer can poll the pastebin for the message to arrive.  This was the kind of pastebin I was after.

I looked at pastebin.com and paste.kde.org, to see if they were suitable. Paste.kde.org seemed promising,  where you could paste easily, using a URL like this:

http://paste.kde.org/?paste_data=Hello+World&paste_lang=c&api_submit=true&mode=xml&paste_project=fiachspastebin

Which would return an ID, which you could retrieve using http://paste.kde.org/api/xml/117613, for example. The problem came, when I wanted to list all pastes by a particular user, or project, and I spotted that it wasn’t working as expected, like http://paste.kde.org/~fiachspastebin/api/xml/all/ seemed to return numerous pastes by other users.

So, I decided to write my own pastebin, which would store the messages in-memory. This meant that they would be deleted as the IIS worker process recycled, but, I didn’t need longevity.

Using two simple actions “action=update” which either created or updated a paste, and assigned it to a “user“, containing the text contained in the “text” querystring parameter. Then when “action=get” then the text associated with that “user” would be returned.

So, to store text with a user, you simply call:

http://url/pastebin.aspx?action=update&user=dananos&text=Hello+World

Then to retrieve that text you call

http://url/pastebin.aspx?action=get&user=dananos

And that’s it. The code I used is below:

  public static Hashtable data = new Hashtable();
    protected void Page_Load(object sender, EventArgs e)
    {
        string action = Request.QueryString["Action"];
        string user = Request.QueryString["User"];
        string text = Request.QueryString["Text"];
        if (string.IsNullOrEmpty(action) || string.IsNullOrEmpty(user))
        {
            Response.Write("Action and User is required");
            return;
        }
        if (action == "update")
        {
            PasteBin.data[user] = text;
            Response.Write("OK");
        }
        if (action == "get")
        {
            if (PasteBin.data.ContainsKey(user))
            {
                Response.Write(PasteBin.data[user]);
            }
            else
            {
                Response.Write("NO DATA");
            }
        }
    }

I’ve ported the same code to PHP, for Linux users. This code requires the $_APP library, which is posted at http://www.leosingleton.com/projects/code/phpapp/

This is hosted at http://pastebin.omadataobjects.com/bin.php

<?php
include("app.php");
application_start();
$action = $_REQUEST["action"];
$user = $_REQUEST["user"];
$text = $_REQUEST["text"];
if ($action == "" || $user == "")
{
   echo("action and user is required");
}
else
{
   if ($action=="update")
   {
	$_APP[$user] = $text;
	echo "OK";
   }
   if ($action=="get")
   {
	echo stripslashes($_APP[$user]);
   }
}
application_end();
?>
Categories: Uncategorized

Bluetooth on Android

Categories: Uncategorized

403.14 mvc

Categories: Uncategorized

Free App Hub account, without Dreamspark

In order to get a Microsoft App Hub account, you can either pay 100 USD or, if you are a student, use a Dreamspark account to get in for free. If you neither want to pay the 100 dollars, and are no longer a student, then we can offer you a free account.

If you would like to publish an app on the Windows Phone 7 App hub without an account, then simply send us the XAP file, along with the required graphics and a description, and we will publish it on your behalf. Email us at support@openmerchantaccount.com with your app.

Graphics required are:
Application icon included in package (62×62 PNG)
Application tile image included in package (173×173 PNG)
Small tile (99×99 PNG)
Medium tile (173×173 PNG – normally this would be the application tile image)
Large tile (200×200 PNG)
Background artwork (1000×800 PNG – this is optional)
Description Text
Keywords Text
One or more application screenshots (480×800 PNG)

We do not offer outpayments, but your app will be published as a paid app. If you want your app to be published as a free app, then contact us for a price. Updates to apps will be charged at a reasonable rate.

During the approval process, if your app fails, then you will be given one attempt to fix it. If you fail a second time, then a small charge will be requested before we submit subsequent times. A PDF will be sent to you describing the fault.

Categories: Uncategorized