Tuesday, April 28, 2009

WordPress: Disable Canonical URL Redirection Plugin

If you've got WordPress redirecting the browser to a URL, only to cause Apache (or whatever you are running as a web server) to redirect back to the original URL, you've got to disable the canonical URL redirection in WordPress. You can do this by saving the following to a PHP file in the plugins directory and activating it via WordPress.

Plugin Name: Disable Canonical URL Redirection
Description: Disables the "Canonical URL Redirect" features of WordPress 2.3 and above.
Version: 1.0
Author: Mark Jaquith
Author URI: http://markjaquith.com/

remove_filter('template_redirect', 'redirect_canonical');

Changing my WordPress blog domain

The WordPress guys and my co-worker who made some mods on it made it difficult to move our blog from the staging environment to the production environment. As the domain name is different, I had to fix up the post GUID links using string replacement in the PHP file, as I didn't want to change the database on the live site (our PHP files are version controlled, but the data on the DB server is not). I did have to change the URL in the options table in the DB for 2 rows 'cos WordPress would always redirect me to the staging environment's domain name.

After getting the blog all patched up, I finally did a Google search to figure out how other WordPress bloggers moved their blogs, which brought me to this article:

CSS: Center Aligning Text Vertically - Method 3

Another approach to vertically centering text is to change the display property of the container to table-cell and add the vertical-align property with the value middle. This method does not work with MS Internet Explorer.


div#header {
vertical-align: middle;
display: table-cell;
height: 200px;
background-color: yellow;

My text

CSS: Center Aligning Text Vertically - Method 2

You can center text vertically by using absolute positioning on the child element and setting the top property to 50%. You might have to adjust the margin-top attribute to get the text exactly in the center.


div#header {
position: relative;
height: 200px;

div#header span {
position: absolute;
top: 50%;
margin-top: -10px;

<div id="header">
<span>My text</span>

CSS: Center Aligning Text Vertically

The easiest way to center text vertically using CSS is to set the line-height to the same size as the container's height.


//Add this to your STYLE tag or external CSS file
div#header {

height: 100px;
line-height: 100px;

<div id="header">
My text

UPDATE: Also see

Saturday, April 25, 2009

Multi-lingual Email Address

Multi-lingual email addresses, or Email Address Internationalization (EAI) as it is more commonly known, has been around for a while. Netaka, a Canadian firm, has been providing an email service for the Chinese community that supports the use of Chinese characters in the email address.

The Internet Engineering Task Force (IETF) has also assigned a committee to oversee the internationalized email effort and the result has been the RFC4952, which in combination with RFC3490 for Internationalizing Domain Names in Applications (IDNA) defines a standard for supporting email addresses with international character sets.

The effort for internationalizing email addresses has been fairly recent, so it will be a while before email servers start supporting other charactersets.

Yahoo! Geocities Pulling Down Shutters

Yahoo! will stop providing the Geocities free web hosting service later this year. What started off in 1994, providing free web hosting communities, was started off by Beverly Hills Internet. In it's original form, Geocities consisted of several virtual 'cities' that represented a category (Eg. Cape Canaveral was for Science & Silicon Valley was for Technology (?) ).

It was acquired by Yahoo in 1999. After a change in the Terms of Service, indicating that all content would be owned by Yahoo!, Geocities grew fairly unpopular and this caused Yahoo! to reverse it's decision on content ownership. Geocities also sold information about it's users to marketing firms which led to a litigation.

Judge of The Pirate Bay case

A recent blog article reveals that the judge who presided over The Pirate Bay hearing was, in fact, a part of two intellectual property protection organizations. As if that wasn't bad enough, he was also a part of the organization acting as the plaintiff i.e. the guys suing The Pirate Bay. If that isn't a mis-trial, I don't know what is. Get more of the juicy details here.

Tuesday, April 21, 2009

Torrent Sites Shut down After Pirate Bay Verdict

Following the court verdict against The Pirate Bay, several other torrent search and tracking sites have shut down to avoid becoming the target of legal lawsuits. Among them are: Nordicbits, Powerbits, Piratebits, MP3nerds, and Wolfbits. Nordicbits has a page here indicating the shutdown, while the others simply disappeared into thin air.

Monday, April 20, 2009

Why Are Software Development Estimates In-accurate?

I came across an article on CodeOfDoom.com about why estimations are inaccurate. The article starts with the question - Who made the estimate? If it's the new guy, he hadn't a clue of the team's efficiency, the skeletons in the closet (flaws in the existing system), and the requirements. If it's the upper management, the estimates made are either based on a dissimilar project or to please a higher-up guy. If it's marketing, they are in the business of selling the client an estimate and that's what makes it worse - you can't change your estimate, based on what you learn the further down the path you go, because what was sold to the client was the original estimate!

Often, we spend time doing things we didn't originally estimate for, such as lack of documentation, inadequate hardware and things we normally tend to overlook. Then, there's something that can be described as an act of God - illnesses, family emergencies and stuff of the sort.

Having put all of the above aside, dealing with the problem involves padding estimates, keeping management informed about resource and information requirements, and limiting changes to the scope or time frame and avoiding unrealistic time frames.

Finally, what you can do to keep work moving at the intended pace is to follow a couple of simple scrum practices (daily sprints, daily standup meets) and dealing with difficult people.

Google Torrent Search

In another protest against the court ruling against The Pirate Bay, a supporter used Google's Custom Search to provide a torrent search. This is simply another voice that says, "Is assisting users to find torrents any different from a search engine?"

Oracle buys Sun Microsystems

Oracle acquired Sun Microsystems for $9.50 per share, which works out to about $7.4 billion. There is a lot of speculation over how Oracle's acquisition affects Java and MySQL. This also puts the Solaris & Sparc brands under the Oracle umbrella.

Replicating data from MS SQL Server to MySQL

I managed to replicate data from MS SQL Server to MySQL using an SQL Server Agent job.

I tried to use a trigger to directly insert data into MySQL via a trigger, but that just didn't work. For more info, see my earlier post.

My approach was to create another table, which was exactly the same as the original table on MS SQL Server, except for the identity property which I left disabled. I then created a trigger that would copy rows from the original table to the copy like this:
CREATE TRIGGER [dbo].[trgMyTable]
ON [dbo].[mytable]
INSERT INTO mytable_repli (qid, qname) SELECT qid, qname FROM inserted;

I tested it by inserting a row into mytable, and sure enough, it appeared in mytable_repli.

I then installed the MySQL ODBC driver 5.1.5 from the MySQL website.

I then configured a System DSN by going to Administrative Tools - Data Sources - Add. Select the MySQL ODBC 5.1 Driver and click Finish. In the dialog box that pops up, enter a data source name (you will need to remember this for later; I'm calling this Nitin), server name (localhost for me, as I'm running XAMPP on the same computer), user name, password, and database name.

The next step was to add a Linked Server using the Wizard in Server Management Studio: Server Objects - Linked Servers... right-click and select New Linked Server. I selected the Microsoft OLE DB Provider for ODBC Drivers, entered the Data source from the System DSN setup earlier (mine is called Nitin). I entered Nitin for the Linked server and Product name, and clicked Ok.

An optional step is to go to Server Objects - Linked Servers - Providers and go to properties for MSDASQL to check the "Nested queries", "Level zero only", "Allow inprocess", and "Supports Like operator" option.

Finally, I created an SQL Server Agent Job. You have to start the SQL Server Agent if it is not running (right-click and select Start), and create a new Job (right-click on SQL Server Agent - Jobs, and select New Job). Enter a name for the job, and click on the Steps page (left of the dialog box). Click the New button, type in a Step name, select the Database in which the SQL Server table is located and write a T-SQL script to copy the values across to the MySQL table like this:
declare @maxid int;

select @maxid = max(qid) from mytable_repli;

insert into Nitin...qtable(qname)
select qname from mytable_repli
where qid <= @maxid;

delete from mytable_repli
where qid <= @maxid;

In the above T-SQL, note that qtable is the name of my database table on the MySQL server and I'm accessing it with the name Nitin defined earlier in the Linked Server setup.

Click Ok for the Job Step Properties dialog box and go to the Schedules page of the Job Properties dialog box. Click New and define how frequently you want the replication to occur (about once every 15 minutes should seem reasonable, unless you need it to occur more frequently).

If you do not configure a schedule, you need to run the job manually (do this by right-clicking on the job and selecting Start Job At Step). You might also want to do this via the trigger created earlier using sp_start_job - this will cause the row to appear immediately in MySQL. To do this, add the following line below the insert statement in your trigger (replace 'mytable_repli_job' with the name you've specified when creating the SQL Server Agent job):
EXEC msdb.dbo.sp_start_job @job_name='mytable_repli_job';

Attempt: Replicating data from MS SQL Server to MySQL

I took my first stab at getting MS SQL Server to push some data to MySQL. My approach I tried was to use an INSERT trigger that inserts data into a MySQL table using the Linked Server feature in MS SQL Server.

I did some reading on Linked Servers and read that it only supports OLE DB drivers and since the only OLE DB drivers I could find were either old or commercial, I decided to use the MySQL ODBC driver and use the OLE DB to ODBC Linked Server option. Everything went well for the most part - I was able to create the linked server, I could select and insert data into the MySQL table from within SQL Server. The part that did not work is when I created a trigger on MS SQL Server and tried to insert the data into MySQL from within the trigger. The problem is that the ODBC driver for MySQL doesn't support distributed transactions (via MS DTC).

I'm thinking perhaps I might have to perform the publisher-subscriber replication instead.

Sunday, April 19, 2009

Comic: Spammers Are A Lower Life Form

Spammers are low life form, particularly the ones who sneak links into blog comment posts. Spam bots can be stopped by the Captcha, but not human spammers :-(

Ubuntu 9.04 Releasing On Thursday

Ubuntu 9.04 (Jaunty Jackalope) is releasing on Thursday. The availability of the Release Candidate last Thursday was a taste of things to come.

Jaunty Jackalope features out-of-the-box support for Wacom digital tablets, reduced bootup time, the 2.6.28 kernel featuring stable Ext4 filesystem support and updated packages of all included software.

MockupScreens Sent Me A Free License

MockupScreens just sent me a free license to try out their software. You can use it to create mockups for your software before you begin development. If you would like to order a license, it costs under $90 for a single user license.

MockupScreens is Vista-compatible and you can find screenshots of it here:

Protest Against Sentence To The Pirate Bay

Hundreds of youngsters protested the sentence by the Stockholm court to the founders of The Pirate Bay.

Bezeq Intl Seeds Torrents Locally

Bezeq International, an Israeli Internet Service Provider, is finding ways to both satisfy customers' torrent needs and improve network performance while proving both aren't necessarily exclusive. Their approach is to seed torrents on their own network by modifying torrent files downloaded by subscribers, adding a tracker containing the seeds to it.

With the recent turn of events in the Pirate Bay case, this could become controversial.

Pirate Bay founders sentenced in copyright case

Earlier this month, in the case of The Pirate Bay versus Universal, MGM, Sony et al, the Stockholm court convicted Peter Sunde, Carl Lundstrom, Frederik Neij and Gottfrid Svartholm Ward of acting as an accessory to breaching copyright laws.

The Pirate Bay founders are optimistic and have appealed the decision. In either case, I'd go grab all the torrents off The Pirate Bay while I still can.

WordPress Mod: Authenticate via ASP.NET

I hooked up a WordPress blog to authenticate via ASP.NET. It's wicked, I tell you! After hacking through the WordPress source code, the integration was quick and easy from both the PHP and ASP.NET sides. The purpose of the integration was to deal with differences in hash algorithms, so we wouldn't have to create user accounts with completely different passwords.

We still would have to build a component on the ASP.NET side to push profile changes and new user accounts into WordPress. I'm wondering if MS SQL Server can connect to MySQL and update the data from within a trigger.

Monday, April 13, 2009

Virus Sweeper

You shouldn't believe everything you read on the Internet. Most people simply just ignore that advice and that's how Virus Sweeper gets into computers. Virus Sweeper is advertised as a warning indicating that you should use it to disinfect your computer. When users do download and run it, that's when Virus Sweeper takes over.

They even have a very convincing user interface that makes Virus Sweeper seem like an actual anti-malware program:

You can find removal instructions and a utility here.

Source: 2-spyware.com

HttpResponse.Close instead of HttpResponse.End

When profiling my application, I noticed that Response.End takes more time to execute than Response.Close. I'm guessing this is because Response.End causes a ThreadAbortException and .NET's handling of the exception causes the overhead.

Twitter Worm

A worm has been running amok on Twitter. It changes profile info, posts tweets, and resets the password. You can get the source code of the worm at:

All it requires is an active Twitter session to take effect.

Saturday, April 11, 2009

Bury The DiggBar

If you've been using Digg for finding websites to visit or bookmarking, you've no doubt come across the DiggBar. It is an annoying bit that takes up screen space. Having to close the DiggBar each time is a pain.

Digg, bury the DiggBar. Make a browser toolbar instead.

Wednesday, April 8, 2009

A Start In Joomla

I've been trying out Joomla, the free and open-source CMS developed in PHP. I set it up on XAMPP and the first thing I can tell is that it's not very intuitive. The features provided on Joomla make it worth the effort to learn it all though - advertising banner management, contact lists, news feeds, polls, search and more.

Twitter Hands Over Registration Details of "Skype"

Twitter handed over the registration details of the user "Skype" to Skype Inc. It definitely raises privacy concerns, but what makes this extreme is that they do not notify the user when they do reveal private data.

Monday, April 6, 2009

Manual Sliding Expiration

When using ASP.NET Forms Authentication, ASP.NET sets a timeout of 30 minutes by default for which a user is logged in. If the user does make a request within the 30 minutes, the authentication ticket is renewed for a another period. This normally happens behind the scenes and the developer is often not aware of this process, known as sliding expiration.

However, if you've got some pages on your web application that should be viewable by the user without the authentication ticket being renewed (such as a ticker to display new messages within an IFrame), you can disable slidingExpiration by making the following change in the web.config file:

<authentication mode="Forms">
<forms slidingExpiration="false"></forms>

You then have to programatically perform sliding expiration within your code, which can be done with the following code snippet posted at:

// Acquire Auth Ticket from the FormsIdentity object
FormsAuthenticationTicket objOrigTicket = ((FormsIdentity)Context.User.Identity).Ticket;

if (!Request.Url.AbsolutePath.ToLower().EndsWith(".ashx"))
// Manually slide the expiration
FormsAuthenticationTicket objNewTicket = FormsAuthentication.RenewTicketIfOld(objOrigTicket);

if (objNewTicket.Expiration > objOrigTicket.Expiration)
// Create the (encrypted) cookie.
HttpCookie objCookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(objNewTicket));
// Add the cookie to the list for outbound response.
// Update original
objOrigTicket = objNewTicket;

In the code snippet above, you would have to change the condition within the IF statement that checks Request.Url to exclude the pages for which you do not want slidingExpiration to occur. The example above excludes all requests to ASP.NET Generic Handlers (files ending in .ashx).

Sunday, April 5, 2009

Aspose Library for Creating Excel and Word Files

If you want to generate Excel and Word files using .NET or Java code, then the Aspose.Cells and Aspose.Words libraries are just what you are looking for. The Aspose.Cells library costs roughly $600 while the Aspose.Words library costs about $900, but you can get a discount of about $200 for purchasing both libraries in a single transaction. You might want to buy Aspose.Total, which is a package containing both Aspose.Cells and Aspose.Words along with several other useful libraries.

How to use Aspose.Cells for creating Excel files in .NET

Using Aspose.Cells is quite simple. You need to add a reference to the Aspose.Cells.dll, create an instance of the Workbook class, get a Worksheet instance (either use the existing sheet or create a new one) and use the Cells indexer to access a cell. Set the value of cells using the PutValue method. Finally, generate the Excel file using the Save method of the Workbook class. Here's an example:

//using Aspose.Cells; //add this to the top of your file
Workbook wb = new Workbook();
Worksheet ws = wb.Worksheets[0];
wb.Save("File1.xls", FileFormatType.Excel2003);

If you are using Aspose.Cells in an ASP.NET application, you can simply save the document for the user to download by replacing the above wb.save statement with the one below:
wb.Save("File1.xls", FileFormatType.Excel2003, SaveType.OpenInExcel, Response);

You can also use Aspose.Cells to directly save a DataTable (System.Data.DataTable) to an Excel file by inserting values into the worksheet like this:
ws.Cells.ImportDataTable(myDataTable, true, "B2");
The "true" value indicates that the column names of the data table will also be written to the worksheet and the "B2" indicates the cell from which the copy will begin.

How to use Aspose.Words for creating Word files in .NET

Using Aspose.Words was a little challenging for me to get started as the demos provided on the Aspose website do not provide examples of creating MS Word files from scratch, but rather focus on demonstrating the ability to load an existing Word file as a template and building upon it. As is the case with the Workbook object in Aspose.Cells, you have to begin by creating a Document object and creating a DocumentBuilder. You can then use the Write, Writeln, and InsertHtml methods of the DocumentBuilder class to create the document and the Save method of the Document class to write to a file or a Respose stream.

Here's an example:
//using Aspose.Words; //add this to the top of your file
Document doc = new Document();
DocumentBuilder bld = new DocumentBuilder(doc);
bld.Writeln("Nitin Reddy");
bld.InsertHtml("<b>Location:</b> Dubai<br />");
doc.Save("File1.doc", SaveFormat.Doc);

When using this in an ASP.NET application to serve files to client browsers, simply replace the above doc.Save method call with the following:
doc.Save("File1.doc", SaveFormat.Doc, SaveType.OpenInWord, Respose);

W3C Geolocation API

ASP.NET MVC 1.0 Source Code

For those of you who are still in the dark, the ASP.NET MVC 1.0 source code is available for download at:

Twitter Comic Strips

Saturday, April 4, 2009

Windows 7 To Minimize OEM Software Performance Hit

Microsoft aims to deliver a better user experience for Windows 7 users by going as far as keeping a check on the performance hit and impact on startup time due to pre-installed OEM software. After the failure of Windows Vista, Microsoft is taking every measure to ensure that it doesn't repeat the same mistakes with Windows 7. A lot of effort goes into improving UI elements that we use everyday, such as the Start button and the taskbar.

Friday, April 3, 2009

New Path For .NET 4 Certification

It's quite likely that the certification path for .NET 4 may be significantly different from the ones for .NET 2.0 and .NET 3.5. The certification path for .NET 2/3.5 requires test-takers to take a foundation exam that covers various topics.

The change would be welcomed by many professionals. After all, how many ASP.NET and Silverlight developers want to spend time learning COM interop instead of focusing on their core competencies?

Tiobe Index For Programming Languages

The Tiobe Programming Community Index, indicative of a programming language's popularity, can be found here .

According to the index, Java, C, C++, PHP and BASIC are the top 5 languages, with Python, C# and JavaScript following closely behind. Over the last year, there's been a sharp decline in the popularity of BASIC and Perl, and a moderate decline in the popularity of Java. On the other hand, C, C++ and JavaScript have been gaining popularity.

You can also look at a long-term trend chart for the top 10 languages here.

Thursday, April 2, 2009

Cross-Domain Policy Files

A Cross-domain policy file or crossdomain.xml is used by Adobe Flash in determining whether it is allowed to access resources from a domain other than that of the currently running Flash object.

The master cross domain policy file has to be located at the root of the server Eg. http://api.flickr.com/crossdomain.xml .

The root element of the crossdomain.xml file is the cross-domain-policy tag which can contain one of the following:

The allow-access-from element allows other domains to access resources. Attributes used with this element are domain (to specify a domain name; wildcards are supported), to-ports (to specify a comma-separated list or hyphenated-range of ports), secure (set to false for an HTTPS policy file to be used for allowing an HTTP request).

The site-control element is valid only within the master policy file (policy file located at the domain root). It is used to determine if other policy files other than the master policy file are permitted. The permitted-cross-domain-policies attribute is used in this tag with a value of: none, master-only, by-content-type, by-ftp-filename, and all. Using none prevents the user of any cross domain policy files for this domain, master-only specifies that only the policy file located at the root is permitted, by-content-type indicates that any file served via HTTP or HTTPS with a content type of text/x-cross-domain-policy is permitted, by-ftp-filename indicates that any file with the name crossdomain.xml is permitted, and all indicates that any policy file on the domain is allowed.

The allow-http-request-headers-from element allows a request from another domain to include custom headers. Attributes used within this element are domain (to specify a domain name), headers (to specify list of comma-separated headers, an asterisk or a header with a wildcard suffix), and secure (set to false for an HTTPS policy file to be used for allowing an HTTP request).

The following is an example of a cross domain policy file:
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<allow-access-from domain="www.company.com" />

The cross domain policy file should be served with the MIME type of text/*, application/xml, or application/xhtml+xml, but the preferred content type is text/x-cross-domain-policy.

Wednesday, April 1, 2009

On A Pentium-II

I'm making this blog post from my old IBM Thinkpad 600E, which is powered by a Pentium-II 366MHz processor and 64MB RAM. It runs Opera 9.64 on Windows 98 and can send/receive email and post to my blog without breaking a sweat. It makes you wonder how newer machines have lots and lots of processing power but you only need so much to get the job done.

I must admit though that for the amount of processing power I get, I do spend an awful lot of electricity. With the same number of electrons it takes to power an old computer, I can run a brand new shiny Thinkpad. My newer Thinkpad T60 also generates lesser heat, so I'm guessing the cooling fan uses lesser electricity and I'm less likely to turn on the air conditioning.

Anyway, I do my part by shutting down the 600E when it's not in use so let's all just take pride in knowing that an old Thinkpad 600E is still alive and in service on the frontlines.

PS: I would install Linux on it but I can't find a driver for the USB interface of my SpeedStream ADSL modem.

Flash Game: Darts

Check out this really cool game of darts:

It's fun to play - you use the mouse to aim left/right and hold the mouse button down to set the force at which you throw the dart. It's pretty much impossible to beat the computer-opponent at the game though.