Tuesday, October 20, 2009
Windows - the Seventh
The number 'Seven' has a lot of significance. There are seven days in a week and it was on the seventh day that the world was completed. 'Seven' symbolizes completeness or perfection. Perfection is only divine. At an earthly level, I would attribute seven to refinement. In that respect, Microsoft has achieved elegance with W7. A few things I like about W7 are:
1. The annoying UAC has become much more placid. Introduced in Vista, as a security measure, it turned out to irritate the users with its frequent pop-ups.
2. The boot performance is significantly faster. Windows 7 should have achieved a 15-sec boot up by the time it is up for final release.
3. W7 lets the users connect to wireless networks instantly with fewer clicks which will prove to be of lot of help, for users without much technical know-how.
4. The footprint of the OS is much lighter compared to Vista. It installs faster and occupies lesser space on the hard disk. Some of additional software like Windows Mail have been made optional downloads instead of default installations.
5. The new OS uses lesser battery power and is known to save energy by 20%. That is a very good news for netbook makers as, Windows 7 will prove to be the OS for netbooks, too.
6. There are some cool mouse gestures included: Aero Peek and Aero Shake. Aero Peek makes all the open windows transparent and lets the users peek through their desktop revealing hidden gadgets and icons while, Aero Shake lets the users minimize unnecessary windows from the desktop by shaking the required window.
7. The OS supports backward compatibility. Legacy applications can run in a Windows XP mode, inside of Window 7.
And, something I don't like about W7:
1. Microsoft failed to come up with a suitable strategy for integrating the cloud. With computing being the talk of the town, and Microsoft itself working on Azure, the Software as a Service(Saas) integration seems to have been lost in translation. Microsoft could have amalgamated its Live Mesh with Windows 7 for data backup.
2. W7 still lives on to the concept of one partition OS. I would have liked this to change. The data like Documents, Music, Pictures and other user settings should reside on a different partition than the OS itself. This would be of great value in case of a system crash or an OS reinstall.
Overall, W7 is a nice compact mixture of niceties and removes some of the nuisances of Vista.
Friday, July 3, 2009
Opera innovations
1. Appearance: The Opera browser has a very polished look. It is very much a Windows 7 product. Firefox looks too XPed, IE never excited me and I have never used an Apple.
2. Mouse Gestures: One of the first things I tried to experiment was mouse gestures. Hold your right mouse in the tab and flick it to left, it performs the "Back" functionality of the browser.
4. Closed tabs: If you close any of your tabs accidentally, Opera lets you open them instantly. More important is the accessibility of this button. It is right there where I would want it to be.
5. Unite: This is something which has a potential to change the way the web works. It allows you to share files from your system rather than some third party service. By giving the user, control of his information, Opera makes the user, the master of his information. But I feel it is little too early for something like this to become an instant hit. Poor Internet speeds, limited hardware resources would be some key limitations for Unite's success. Nevertheless the idea deserves credit.
6. Widgets: These are web applications which run in the browser but without showing the browser controls. They are very easy to use and also very easy to build using client side programming languages. I have been playing around with them and will write more about how to create your own widgets, but that is later.
7. Anti Cloud: Yes Opera is anti-cloud. The world has been focusing on centralizing services across the Internet for quite some time now. With a few big names in the fray, the race has heated up. But, Opera has different plans. By providing an individual to host his own web server inside a browser, Opera has de-centralized information.
Tuesday, June 23, 2009
Cross domain calls
The XMLHTTPRequest object is used to make an http request directly to a web server and load the server response data back into the scripting language. But this techniques works only when you are making a request to the same web server with in the same domain. Here is how to make a call from www.site1.com/user.html to www.site2.com/usercheck.aspx :
1. Create a web page on www.site1.com which would make a call to another server www.site2.com. Documentation available inline.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<head>
<title>Check username availability</title>
</head>
<body>
<form id="form1" runat="server">
<div>
Enter Username:
<!-- Check if username exists already or not -->
<input type="text" name="user" onchange="createScriptTag(this); return false;"/>
<span id="outputmessage"></span>
<input id='submit_button' name='submit_button' type='submit' value='submit' />
</div>
</form>
<script language="javascript" type="text/javascript">
//Create a script tag which loads javascript from a remote source
function createScriptTag(e){
var headElement;
var scriptTag;
var inputValue = e.value;
var url = 'http://www.site2.com/usercheck.aspx?username=' + inputValue + '&rnd=' + new Date().getTime();
headElement = document.getElementsByTagName("head").item(0);
scriptTag = document.createElement("script");
scriptTag.setAttribute("id", "user_script");
scriptTag.setAttribute("type", "text/javascript");
scriptTag.setAttribute("src", url);
headElement.appendChild(scriptTag);
// Creates issue with IE so remove the script tag later at an appropriate place
//headElement.removeChild(scriptTag);
}
//function to be executed on callback from the above request. The callback returns a response similar to "isAvailable({'status':1})"
function isAvailable(response){
if (response.status == 1){
document.getElementById("outputmessage").innerHTML = "Username is still available";
}
else {
document.getElementById("outputmessage").innerHTML = "Username already exists";
}
}
</script>
</body>
</html>
2. The www.site2.com/usercheck.aspx page accepts querystring parameters,
implements a business logic and returns the function to be executed on client side as response.
using System.Collections;
using System.Configuration;
using System.Data;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
public partial class keygenerator : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.ContentType = "text/plain";
if (Request.QueryString.Count > 0)
{
string username = Request.QueryString[0];
//array of names to check against
ArrayList arlExistingUsernames = new ArrayList();
arlExistingUsernames.Add("harpreet");
arlExistingUsernames.Add("singh");
if (!arlExistingUsernames.Contains(username))
{
Response.Write("isAvailable({'status':1})");
}
else
{
Response.Write("isAvailable({'status':0})");
}
}
else
{
Response.Write("isAvailable({'status':0})");
}
Response.End();
}
}
For more cross domain calling options check out:
http://snook.ca/archives/javascript/cross_domain_aj/
http://ox.no/posts/ajast-cross-domain-rest-calls-using-json-injection
http://developer.yahoo.com/javascript/howto-proxy.html
Saturday, June 20, 2009
Turbogears debugging in Eclipse
Setting up debug enabled environment for a Turbogears application in Eclipse is not really straightforward. I struggled a lot before I could set it up. Initially I wasnt even sure if I could set up break points and debug the application like in microsoft visual studio. It is very much possible although some of the things are not very obvious. Here is a list of things to check up, if you are facing problems.
1. You can install Pydev by following the instructions mentioned on pydev website. You can also have a look at this ibm site which helps you make the necessary settings in Eclipse.
2. You can patch the Decorators file from pydev blog. If you are facing any problems drop your email id I will send you the patched file.
>easy_install -U turbojson==1.1.4
>easy_install -U DecoratorTools==1.4
4. Remember, you will still see the following error when you start the debug session.
PYDEV DEBUGGER WARNING:
sys.settrace() should not be used when the debugger is being used.
This may cause the debugger to stop working correctly.
If this is needed, please check:
http://pydev.blogspot.com/2007/06/why-cant-pydev-debugger-work-with.html
to see how to restore the debug tracing back correctly.
Call Location:
File "C:\Python24\lib\site-packages\decoratortools-1.4-py2.4.egg\peak\util\decorators.py", line 562, in uninstall
But, wait for a few seconds and eclipse will start the debug session after the error message.
Tuesday, June 16, 2009
Asp.Net and Python-cgi communication
I recently had my first shot at writing cgi scripts in python. It was an altogether different experience having come from a .Net and Turbogears background. I also got my hands on a Linux server. Infact, it was the first time I got to use vi, ls, cat, cp etc, since college. It is really amazing how much you can do with just the shell commands on Linux.
The Linux machine had an apache server which ran some cgi scripts to do some basic tasks like creating a new user record in the database, deleting, editing etc. I think that was the reason they did not go beyond cgi. These tasks were manually done by an admin after logging into the application. Now, these scripts were required to be made callable from an asp.net web application.
ASP.NET application <===========> Python cgi scripts
CreateDemo.aspx _____________ create_demo.cgi
(collects user info
for demo record) _____________ (requires authentication)
So, we decided to create another script, let us say 'authenticate.cgi', in which we used urllib python library to by pass the authentication on create_demo.cgi and then CreateDemo.aspx would call authenticate.cgi. Here is the new flow-
CreateDemo.aspx --> authenticate.cgi --> create_demo.cgi
This write-up addresses two key areas:
1. How to communicate with a python cgi script from an asp.net web page?
//Request url and request method
HttpWebRequest httpRequest = HttpWebRequest)WebRequest.Create("http://192.1.1.1/no_auth/authenticate.cgi?name=harpreet”);
httpRequest.KeepAlive = false;
httpRequest.Method = "GET";
//Read the web response from the URI
string strResponse = string.Empty;
using (WebResponse webResponse = (WebResponse)httpRequest.GetResponse())
{
System.Text.Encoding enc = System.Text.Encoding.GetEncoding(1252);
using (StreamReader srResponseStream = new StreamReader(webResponse.GetResponseStream(), enc))
{
//Read the response into a string or you could use XML also
strResponse = srResponseStream.ReadToEnd();
}
}
2. How to by pass basic authentication on cgi script using urllib?
#!/usr/bin/env /usr/local/bin/python
import urllib2,urllib
import sys,os,cgi,cgitb
import re,datetime
import base64
from urlparse import urlparse
def handler():
form = cgi.FieldStorage()
if form.list:
data = {}
for field in flds:
data[field]=form.getvalue(field,'')
theurl = 'http://localhost/admin/create_demo.cgi’
# you'll need to supply a protected page with your username and password
username = 'scott'
password = 'tiger' # a very bad password
req = urllib2.Request(theurl)
try:
handle = urllib2.urlopen(req, urllib.urlencode(data))
except IOError, e:
# do whatever you want to handle the exception here, 'pass' in this example
pass
else:
# If we don't fail then the page isn't protected
print "This page is not protected by any authentication."
sys.exit(1)
if not hasattr(e, 'code') or e.code != 401:
# we got an error - but not a 401 error
print "This page is not protected by any authentication."
print 'Some other reason for failure'
sys.exit(1)
authheader = e.headers['www-authenticate']
# this gets the www-authenticate line from the headers
# which would contain the authentication scheme and realm
authobj = re.compile(r'''(?:\s*www-authenticate\s*:)?\s*(\w*)\s+realm=['"]([^'"]+)['"]''',re.IGNORECASE)
# this RE is used to extract scheme and realm
matchobj = authobj.match(authheader)
# if the authheader isn't matched by the regular expression
# then there is probably some error in the header
if not matchobj:
print 'The authentication header is badly formed.'
sys.exit(1)
scheme = matchobj.group(1)
realm = matchobj.group(2)
# check schem (this example works for basic authorization only
if scheme.lower() != 'basic':
print 'This example only works for BASIC Authorization.'
sys.exit(1)
base64string = base64.encodestring('%s:%s' % (username, password))[:-1]
authheader = "Basic %s" % base64string
req.add_header("Authorization", authheader)
try:
handle = urllib2.urlopen(req,urllib.urlencode(data))
except IOError, e:
print "The username or password is not valid."
sys.exit(1)
thepage = handle.read()
print "Content-type: text/html; charset=utf-8"
print thepage
handler()
Security was not really a major concern for this cgi, but an IP based security was added to limit unwanted access.
* The code snippets are not really tested but, will hopefully work :-)
Friday, May 1, 2009
Will the history repeat itself, with Grabbler?
Saturday, March 7, 2009
How I set up my Turbogears based development environment...
1. Installed Python 2.4.4.
2. I was working on a windows platform and required support for it so I installed extensions for windows. PyWin32 is a collection of modules for advanced windows-specific support. These include utilities for COM, Win32 API calls, Registry, Event Log and MFC user interfaces.
3. Installed setuptools, so as to be able to build and distribute packages. It includes a utility easy_install, which lets you automatically download, build, install, and manage Python packages and their dependencies.
4. Installed the Turbogears web application framework by running the command:
>easy_install-2.4 -f http://files.turbogears.org/ "TurboGears==1.0.4.4"
5. Installed win-psycopg, a windows port of the psycopg python-postgresql database interface.
6. Installed SQLObject, an Object Relational Manager which provides an object interface to your database, with tables as classes, rows as instances, and columns as attributes. Used the following command to install it:
>easy_install-2.4 "SQLObject==0.10.2"
7. Installed other packages like PyPDF 1.9, ElementTree 1.2.6, ElementTidy and PyLucene for my text based application.
8. Installed TinyMCE 1.0.6, a JavaScript HTML WYSIWYG editor control, using the following command:
>easy_install-2.4 "TurboTinyMCE==1.0.6"
9. Downloaded the ExtJS 2.2 Library. It has some excellent built-in components ready to use.
10. Installed Eclipse 3.2 IDE and added the PyDev plugin using the manual and configured it accordingly.
There I was, ready to play!
Friday, March 6, 2009
Remote access to PostgreSQL Server
The resolution is a five step process : -
1. Firstly, check if your firewall allows the port (default is 5432) to establish a connection.
2. By default, PostgreSQL does not allow remote incoming connections. This has been implemented in this way, because of security concerns. You need to enable incoming TCP/IP connection requests from the client. This can be done by adding
#
listen_addresses = '*'
#
in the configuration file postgresql.conf. This configuration is valid for postgresql 8.x.
3. You will have to inform Postgresql who can connect to the server. This has to be done by modifying the configuration file pg_hba.conf
host all all 127.0.0.1/32 trust
host all all 192.168.0.0/16 trust
This would allow any user on the local network to access all the databases on the server in "trust" mode.
4. After you have saved the configuration files you will have to restart the server. Remember, these configuration files are read on server startup.
5. Test your config. Go to the command prompt and run the following command.
>psql -h serverIP -U postgresUser -d postgresdb
And, you should be set for remote access to postgresql server.
Thursday, March 5, 2009
JSON
A sample JSON:-
{"continents": {
"asia":[{"country": "india",
"code": "101"
},
{"country": "japan",
"code": "102"
}],
"europe":[{"country": "france",
"code": "401"
}]
}
}
The most notable features of JSON are:-
1. It is basically a collection of name-value pairs ("key": "value") separated by a colon.
2. It is not only easy to read for humans but also easy to parse by the machines.
3. Values can be a string, an integer, an object or an array.
Standard literals like True, False, null are also acceptable.
4. Each object is placed between {...}.
5. Arrays are place between [...] and are comma separated.
6. It can be passed using httpWebRequest.
7. Reserved keywords from JavaScript are not allowed in JSON.
8. JSON can be parsed using the eval() method in JavaScript.
9. It uses Unicode.
Common errors like the "missing } after property list" can be corrected
using a JSON validator like www.jsonlint.com
Tuesday, March 3, 2009
Existing database tables and SQLObject
class Bookmark(SQLObject):
_fromDatabase = True # the table structure will be loaded from the database
BookmarkName = StringCol (dbName="bookmark_name")
# dbName is the name of the column in the database, BookmarkName is the name reference in code.
ProjectId = IntCol(dbName="project_id")
(Make sure the indentation is correct)
Connecting to an existing database using TurboGears framework
scheme://[user[:password]@]host[:port]/database[?parameters]
For instance:
postgres://user:pwd@localhost:5432/db
SQLObject provides a debug mechanism, which can be turned on easily by appending ?debug=True to the end of your database URI in the dev.cfg file.
postgres://user:pwd@localhost:5432/db?debug=True
This would publish the query generated onto the console.
..........
Define the existing table Bookmark as a class in model.py:-
class Bookmark(SQLObject):
_fromDatabase = True # the table schema be loaded from the database
BookmarkName = StringCol (dbName="bookmark_name")
ProjectId = IntCol(dbName="project_id")
# dbName is the name of the column in the database, BookmarkName is the name reference in code.
..........
Using the following code in controller.py you should be able to retrieve the second record from the Bookmark table
b=Bookmark.select()
print ": %s " % b[2].BookmarkName