Tuesday, December 21, 2010

11 Free Productivity Tools for the office

Here's a list of 11 Free Tools to increase productivity at Work:
  1. 7-Zip:
    Category: Compression/Decompression
    Details: Compression utility that can handle almost all possible formats
    URL: http://www.7-zip.org
  2. Eclipse:
    Category: IDE
    Details: Very popular IDE that supports a vast array of languages and configurations
    URL: http://www.eclipse.org
  3. FileZilla:
    Category: FTP Client (& Server)
    Details: FTP Client and server with lots of options
    URL: http://filezilla-project.org
  4. PuTTY:
    Category: Telnet/SSH
    Details: Very simple but powerful Telnet/SSH client
    URL: http://www.chiark.greenend.org.uk/~sgtatham/putty/
  5. PuTTy Connection Manager:
    Category: Telnet/SSH
    Details: Allows docking of multiple PuTTY session windows as Tabs and allows user to create a database of connections that includes user names, passwords, script to run after login, etc.
    URL: http://puttycm.free.fr
  6. Notepad++:
    Category: Editor
    Details: Very simple, but powerful and full featured editor that supports syntax highlighting, plug-ins, macros, regexes, etc.
    URL: http://notepad-plus-plus.org
  7. OpenOffice:
    Category: Office Software
    Details: Full featured replacement for the cos$tly M$ Office Suite of products. Includes software for word processing, spreadsheets, presentations, graphics, databases and more.
    URL: http://www.openoffice.org
  8. PDFCreator:
    Category: Office Software
    Details: Create PDF files from any application.
    URL: http://www.pdfforge.org/pdfcreator/
  9. VirtualDimension:
    Category: Desktop Manager
    Details: Fast and full-featured virtual desktop manager that allows you to create virtual desktops on Windows just like X-Win.
    URL: http://virt-dimension.sourceforge.net
  10. VistaSwitcher:
    Category: Task Manager
    Details: Replaces the default Windows Alt-Tab dialog with a nice box that shows a list of all running tasks, with their names and preview snapshots, and enables the user to take actions on them using the mouse and keyboard shortcuts.
    URL: http://www.ntwind.com/software/vistaswitcher/
  11. WinMerge:
    Category: Development
    Details: Visual diff and merge tool for Windows that can compare both folders and files
    URL: http://winmerge.org

Other good free softwares that I also considered were:
  1. PSPad:
    Category: Editor
    Details: Another powerful and full featured editor that supports syntax highlighting, plug-ins, macros, regexes, etc.
    URL: http://www.pspad.com
  2. PDFReDirect:
    Category: Office Software
    Details: Another simple software to create PDF files.
    URL: http://www.exp-systems.com
  3. DiffMerge:
    Category: Development
    Details: Visual diff and merge tool for Windows, Mac OS X and Linux that can compare both folders and files
    URL: http://www.sourcegear.com/diffmerge/
  4. Toad Free:
    Category: Database Access
    Details: Free version of the powerful Toad for Oracle with a few features disabled.
    URL: http://www.toadworld.com/Freeware/tabid/680/Default.aspx
  5. SQLDeveloper for Oracle:
    Category: Database Access
    Details: Oracle client provided by Oracle
    URL: http://www.oracle.com/technetwork/developer-tools/sql-developer/overview/index.html

Please let me know if you see other good free software worthy of including in the above list!

Friday, October 8, 2010

S/W Update for T-Mobile Samsung Vibrant Galaxy S

This morning, T-Mobile pushed a software update to my Samsung Vibrant Galaxy S - however, the phone would not install it as the battery level was lower than 75%!

After the install, here are the major changes that I noticed:
  1. HD Camcorder is now available in the list of applications
  2. Media Hub now works but the previews work only on Wi-Fi :(  This should have been allowed on 3G - I would sure like to watch the preview while traveling on the bus/train!
  3. Task Manager app is provided, however, I did not find it very useful as it did not show many of the running applications which the Advanced Task Killer free app shows.
Here are the current version numbers:
  • Firmware version: 2.1-update1
  • Baseband version: T959UVJI6
  • Kernel version: 2.6.29
  • Build number: ECLAIR.UVJI6
Now let's see when Froyo gets pushed - waiting for Android 2.2 for a lot of kool features to be enabled!

Tuesday, October 5, 2010

Created a simple TTS app with App Inventor

With my Samsung Vibrant phone, even though I am still struggling with connectivity to Ubuntu 9.04, I was able to connect very smoothly to Windows7!!!

So to test it out, I created a simple app that has a text box and a button. On pressing the button, the text that was entered in the text box is spoken out aloud by the app. If there is no text in the box, then a default message is read out.

To create this first app, it took only 2 minutes!!!
This shows that the App Inventor is pretty good and quite promising.

However, there are a few cons as well - the created software when installed on the phone, takes a huge amount of space; 3.55Mb to be precise for this simple app! Also, I cannot share this app with others or upload it to the Android Marketplace - it can only be shared with others who have an App Inventor account. Well, you can't have your cake and eat it too!

Monday, October 4, 2010

Unable to connect Samsung Vibrant to App Inventor on Ubuntu9.04

The good news is that almost 2.5 months after I applied for access to Google Android App Inventor, I got the access on 1st October.

Now the bad news is that I am unable to connect my Samsung Galaxy S Vibrant to App Inventor on my machine running Ubuntu 9.04. Here is what I have tried till now after installing App Inventor Extras software for Linux:

I ensured the below settings were done before connecting the phone:
  1. Settings > Applications > Unknown sources is checked
  2. Settings > Applications > Development > USB debugging is checked
  3. Settings > Applications > Development > Stay awake is checked
  4. Settings > Sound and display > Orientation is un-checked

On connecting the phone, I see the USB Icon which mentions that USB is connected and also a Red exclamation alert icon mentioning that USB debugging is connected. I also ensured that OpenJDK is also not installed on my machine as that is known to cause clashes with Android SDK.

Then I opened a shell, logged in as root (using sudo -s) and then did the following:

# lsusb | grep 'Sam'
Bus 001 Device 003: ID 04e8:681c Samsung Electronics Co., Ltd 
# vi /etc/udev/rules.d/51-android.rules
SUBSYSTEMS=="usb", ATTRS{idVendor}=="04e8", ATTRS{idProduct}=="681c", MODE="0666"

Now rebooted the machine and again with sudo -s, ran the following commands:

# /etc/init.d/udev restart
 * Stopping kernel event manager...                                      [ OK ]
 * Starting kernel event manager...                                      [ OK ]
# cd /usr/google/appinventor-extras/commands-for-Appinventor
# ./adb kill-server
# ./adb devices
* daemon not running. starting it now *
* daemon started successfully *
List of devices attached

# ./adb usb
error: device not found


I tried the above sequence of steps with these versions of UDEV rules as well, but to no avail:
# vi /etc/udev/rules.d/51-android.rules
SUBSYSTEMS=="usb", SYSFS{idVendor}=="04e8", MODE="0666"

and

# vi /etc/udev/rules.d/51-android.rules
SUBSYSTEMS=="usb_device", SYSFS{idVendor}=="04e8", MODE="0666"


Here is the log from the Java console:

Creating the REPL controller
Changing the REPL communication button text to Communicating...
Disabling REPL communication button.
********* Actually invoking CreateAndSend
Restarting repl controller (true)
ReplController sending (begin (require com.google.youngandroid.runtime)  (setup-repl-environment "<<" ":" "@@" "Success" "Failure" "=="">>" '((">>""&2")("<<""&1")("&""&0"))))
**** devicesPluggedIn: 0 isPluggedIn: false connectionHappy: false
************************** commIndicator was unexpectedly
connected!!!! COMMUNICATING
Changing REPL communication button to Connect.
Re-enabling REPL communication button.
Communication with REPL failed: java.io.IOException: App Inventor
cannot find any phones.
Please plug in a phone and try again.

I am at a loss as to what else to check as all these steps are a compilation of the knowledge in the google groups as well as other blogs on the topic. If anyone has any ideas/pointers/suggestions, please let me know - Thanks.

Wednesday, September 22, 2010

How to use Syntax Highlighter 3 in Blogger

Syntax Highlighter version 3.0.83 has been released and there are quite a few changes in the way things work now. I realized this when the rendering on this site broke after I modified it to use the latest release. So, here is the steps required to setup the "hosted" version of the latest Syntax Highlighter (version 3.0.83) and integrate with your Blogger/Blogspot blog.

Installation

  1. Navigate to Dashboard > Design > Edit HTML
  2. Backup the current template by clicking on the link Download Full Template
  3. In the textarea, press CTRL+F to find the code </head>
  4. Copy the below code and paste it just above
    <!-- Syntax Highlighter Additions START -->
    <link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/>
    <link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'/>
    
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushBash.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPerl.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPhp.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushVb.js' type='text/javascript'/>
    <script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js' type='text/javascript'/>
    
    <script language='javascript' type='text/javascript'>
    SyntaxHighlighter.config.bloggerMode = true;
    SyntaxHighlighter.all();
    </script>
    <!-- Syntax Highlighter Additions END -->
    
  5. Preview your changes and make modifications as required
  6. Save the template

In the above code, I have put in brushes for the languages that I use frequently. Modify the brushes according to your needs - check the full list of supported brushes here and use whichever you need.

Configuration

Apart from choosing the brushes that you need, there are other configuration parameters that you can setup as well. Check out the details here. More useful ones are the ones that allow you to change the starting line number, highlight specific lines, disable auto-linking of URLs and html-script option to highlight mixture of HTML/XML code.

Apart from these configuration changes, you can change the theme as well. SyntaxHighlighter comes bundled with 7 themes and I personally like the default one. However, you can choose the theme that you fancy the most by simply replacing the name of the theme in this line:
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/>

So you can replace shThemeDefault in the above line with any one of the following themes:
  1. Django - shThemeDjango
  2. Eclipse - shThemeEclipse
  3. Emacs - shThemeEmacs
  4. Fade to Grey - shThemeFadeToGrey
  5. Midnight - shThemeMidnight
  6. RDark - shThemeRDark

Usage

To use it in your blog post, there are a couple of things that need to be done.
  1. Escape all code by replacing any occurrences of:
    1. < with &lt;
    2. > with &gt;
  2. Enclose the escaped code between <pre class="brush:[brush_name];[optional_params]"> and </pre>
  3. Setup the proper brush name (based on the code being highlighted) in the opening pre tag. Using the correct brush will ensure proper highlighting of the code

New Features in 3.0.83

The new version brings with it quite a few new features - here's an overview:
  • Auto-Loading of Brushes

    Now all the brushes need not be pre-loaded on every page. You can load only the required brushes on the pages that need those brushes. Use the shAutoloader.js and then load the brushes as required
    For more details on using this feature, check out the instructions here. Note that this might not be so useful for a blogger account as we do not modify the javascript for each page/post.
  • No usage of Flash

    Earlier, Flash was being used to copy the code to clipboard. This has now been removed and a simpler & better way to do this has been implemented. Also, the user can now simply double-click anywhere in the code to select it and then use the standard CTRL+C to copy it.
  • Code copy without line numbers

    Now the copied code excludes line numbers and the extra leading tabs/spaces to make it usable directly - very convenient!
  • Add Title

    Now you can add a title to the code block by title="[title_name]"
parameter to the pre tag.

  • More under the hood

    More improvements and changes under the hood like better CSS support, easier integration with CommonJS & node.js, etc.
  • Monday, September 20, 2010

    Search & replace text in multiple files in Unix

    To search a particular string in multiple files and replace all occurrences with a new string, you can use the following handy Perl one-liner:

    perl -pi -e 's#search_string#replace_string#g' *.php
    

    Here, the -p switch wraps the script inside a loop, executing once for each input file which is denoted by the last arguement *.php.

    The -i switch allows inline modification of the file; you can optionally save a backup of the original file by providing the backup file name template after this switch as -i *.bak.

    The -e switch executes the following piece of code.

    The string of code 's#search_string#replace_string#g' searches for search_string and replaces it with replace_string globally. You can use any other character like "/" to delimit the search & replace strings. Remember to replace the place-holder text with the actual text and also escape it properly.

    Friday, September 17, 2010

    Extend battery life on Samsung Vibrant

    Here are a few tips / tricks to extend the battery life on Samsung Vibrant and any Android based phones. Of course, cutting down on many of these aspects may reduce the quality of experience that you have with the phone, so there's always a give-and-take involved. However you can definitely turn-off those features that you don't use so that you can have the full-fledged experience of the phone as well as a better battery life!

    1. Switch off GPS
    If you are not using any location aware services, maps or navigation, then turn off the GPS radio. GPS radios generally use a lot of juice and if you are not using the feature, no point in letting it consume battery.

    2. Switch off Wi-Fi
    If you are on the move and not using Wi-Fi, then turn it off as Wi-Fi radios can eat up a lot of power as well.

    3. Switch off Bluetooth
    If you are not using Bluetooth, then turn it off. Switched on Bluetooth transciever that is not being used is another major culprit for draining the battery in all phones that have bluetooth, not just the Samsung Vibrant.

    4. Adjust & Optimize Display Setting
    Reduce the brightness of the screen and decrease the screen time-out (the amount of time the phone waits to turn the display off if there is no activity). Display is the major consumer of battery resources hence using it in a controlled manner will provide astonishing results.

    5. Increase Synchronization intervals
    Increase the gap between synchronization intervals or set them to synchronize on demand instead of a time interval. Apps for social networks, emails that use "polling" instead of "push", weather, news, etc. are major culprits for such unwarranted usage of battery.

    6. Install Apps to Kill unwanted tasks
    Note: this may be risky / complicated depending on which app(s) are installed and how they are used.
    For Android 2.1, you can install JuiceDefender to intelligently manage & control how apps use battery.
    You can also install & use Advanced Task Killer to kill apps that don't close after you have exited from them. Apps that keep running in the background even after you have exited from them can also drain the battery.

    7. Remove Dynamic Wall Papers
    Dynamic / Live Wall Papers and similar apps can also eat into the battery very fast - disable such apps to increase available battery.

    8. Turn off Vibrate / Haptic Feedback
    A small motor spins at a high speed to create the Vibration / Haptic Feedback buzz. This obviously takes a lot of power, so switching it off can save quite a bit.

    9. Switch to Flight mode in areas of no cell coverage
    Switch to Flight mode in areas where there is no cell coverage to conserve battery. When there is no cell coverage, generally the signal strength is boosted to see if any towers can be reached and the polling interval also increases. Switching to Flight mode switches off the radios saving the battery from drain out.


    Note: These are also generally applicable for all other (smart) phones too based on whether they have the below mentioned features.

    Friday, July 16, 2010

    Interview Tips

    Came across a few good articles on how to prepare for interviews especially aimed at Google. These make very good reads even if you are not planning on attending any interviews any time soon!

    Upgrade Drupal

    Drupal core could get updates due to security / bug fixes / patches and it is very important that your installation of Drupal be kept updated in this regard. Here are the steps needed to updgrade a Drupal installation:
    1. Backup current data
    2. Download & unzip update file
    3. Disable all contributed modules
    4. Revert theme to a core theme
    5. Delete all old files
    6. Upload new files
    7. Copy over the backed up folders
    8. Re-enable contributed modules
    9. Run update.php script
    10. Re-apply custom theme

    Now lets discuss each of the above steps in a bit of detail:

    1. Backup current data
    Backup your installation database using phpMyAdmin or any other suitable tool.
    Backup the files and sites folders

    2. Download & unzip update file
    Download files for the upgrade and extract the contents to a temporary folder. On Ubuntu, I just double-click on the file to do this. On WinX platforms, this cannot be done directly - you will need to download & install the free & open source tool 7-Zip to do this. Now you should have the full install files extracted into your chosen temporary folder.

    3. Disable all contributed modules
    Log in to the Drupal admin and go to Administer > Site building > Modules or the Drupal path admin/build/modules. Disable all the contributed modules.

    4. Revert custom theme to a core theme
    If you have a custom theme, revert it back to one of the core themes. Log in to the Drupal admin and go to Administer > Site building > Themes or the Drupal path admin/build/themes to do this.

    5. Delete all old files
    Delete all the files in your installation main directory - this ensures that there are no clashes between existing files and new files.

    6. Upload new files
    Now upload the files extracted in step 2 above folder to the main installation folder on the server.

    7. Copy over the backed up folders
    Copy back the files and sites folders backed up in step 1 above back to their respective folders.

    8. Re-enable contributed modules
    Log in to the Drupal admin and go to Administer > Site building > Modules or the Drupal path admin/build/modules. Enable all the contributed modules that you disabled in step 3 above.

    9. Run update.php script
    Drupal provides a special update script located in the root folder of the install for maintaining the database after upgrades. Log in to the admin section with your admin id(usually having id of 1 and is the first account to be creaed). Then point your browser to http:///update.php and click on the Update button. The modules requiring database updates will have their appropriate DB update number selected in their drop-downs. For most cases, the defaults should be fine. The database update may take some time depending on the number of updates to apply.

    10. Re-apply custom theme
    If you had a custom theme, re-apply it now. Log in to the Drupal admin and go to Administer > Site building > Themes or the Drupal path admin/build/themes to do this.

    Updating Drupal Module

    With changes to the core modules or due to security / bug fixes / patches, installed modules may require to be updated. Updating (contributed) modules is very simple as the process has been kept very rudimentary. Here are the steps needed to update a module:
    1. Find modules requiring updates
    2. Disable the module
    3. Delete all files of the module
    4. Reinstall the updated module
    5. Run update.php script

    Now lets delve into each of the above steps in a bit of detail:

    1. Find modules requiring updates
    If you do not already have the Update Status module installed & enabled, get it from the drupal site http://drupal.org/project/update_status & install it. This module tracks which of the installed modules have updates available and provides handy links to download the updates directly. Once this is installed & enabled, go to Administer > Reports > Available updates or the Drupal path admin/reports/updates. This page shows which modules require updates to be installed.

    2. Dsiable the module
    Once the list of modules to be updated is known, go to Administer > Site building > Modules or the Drupal path admin/build/modules and disable those modules.

    3. Delete all files of the module
    Now delete all the files for these modules by deleting their corresponding folder in sites/all/modules folder in your Drupal install.

    4. Reinstall the updated module
    Now upload & install the files for the updated module just as if it were a new module. For details on how to install a new module, check out my blog post on Installing Drupal Module.

    5. Run update.php script
    Drupal provides a special update script located in the root folder of the install for maintaining the database after upgrades. Log in to the admin section with your admin id(usually having id of 1 and is the first account to be creaed). Then point your browser to http:///update.php and click on the Update button. The modules requiring database updates will have their appropriate DB update number selected in their drop-downs. For most cases, the defaults should be fine. The database update may take some time depending on the number of updates to apply - once this is done, the modules are all updated!

    Installing a Drupal Module

    Drupal is a very powerful CMS platform and has many modules to enhance it's functionality. Installing (contributed) modules is very simple as the process has been kept very rudimentary. Here are the steps needed to install a module:
    1. Find & download compatible module
    2. Unzip it locally
    3. Upload files to your server
    4. Read & follow special instructions (if any)
    5. Enable the new module
    6. Setup permissions (if required)
    7. Adjust Settings (if required)

    Now lets delve into each of the above steps in a bit of detail:

    1. Find & Download compatible Module
    Search for the module on the drupal site http://drupal.org/project/modules/. This page has a big list of available modules and you can search for required modules as well. Once you find the module that is compatible with the version of the installed Drupal core, download the compressed "tar.gz" file locally.

    2. Unzip it locally
    Once the file is available locally, extract the contents to a temporary folder. On Ubuntu, I just double-click on the file to do this. On WinX platforms, this cannot be done directly - you will need to download & install the free & open source tool 7-Zip to do this. Now you should have a folder by the name of the module in your chosen temporary folder.

    3. Upload files to your server
    Now upload this extracted folder to sites/all/modules folder in your Drupal install. This is the folder that holds all the contributed modules.

    4. Read & follow special instructions (if any)
    Check the module folder for "README.txt" or "INSTALL.txt" or similarly named files to see if this module requires any special steps for installation. If so, follow those steps to a "T".

    5. Enable the new module
    Log in to the Drupal admin and go to Administer > Site building > Modules or the Drupal path admin/build/modules. Look for the new module and enable it.

    For most cases, you should be good by now. If not, then follow the below steps.

    6. Setup permissions (if required)
    Some modules need extra permissions to be setup for them to work properly. Grant the permissions as appropriate & required for the module to function properly.

    7. Adjust Settings (if required)
    Tweak the settings provided by the module (if any) to make it function as per your requirements. Mostly the provided defaults work good, but there could be cases where you need to change the settings to suit your needs.

    Monday, July 12, 2010

    Google launches Android App Inventor Beta

    Ever wanted to create an app for your (or for that matter, someone else's) Android phone? But were lost in the sea of code & APIs that is required to be mastered?

    Worry no more - for Google Labs has launched (but of course) a Beta version of the App Inventor for Android.

    This looks like a glorified equivalent of the Visual Basic interface that was used to make many a (good & bad) programs. However the good part here is that you can make an entire program without even a single line of coding! To quote from the App Inventor site:

    To use App Inventor, you do not need to be a developer. App Inventor requires NO programming knowledge. This is because instead of writing code, you visually design the way the app looks and use blocks to specify the app's behavior.

    The App Inventor team has created blocks for just about everything you can do with an Android phone, as well as blocks for doing "programming-like" stuff-- blocks to store information, blocks for repeating actions, and blocks to perform actions under certain conditions. There are even blocks to talk to services like Twitter.

    Here's to Google to open up it's platform for the young and the old alike for whoever may have the appetite and energy to create their own Android apps. Only time will tell whether this approach will yield better apps or not!

    Fee jQuery eBook - 7/12 Only

    Sitepoint is offering free download of the eBook jQuery: Novice to Ninja by Earle Castledine and Craig Sharkie here.

    Amazon reviews are pretty good and the paper edition is priced at $35.60.

    Tuesday, June 29, 2010

    Magento - Change Price Labels

    Magento by default labels the prices as "Regular Price" and "Special Price". I could not find any simple or straightforward method of changing these labels in the back-end admin.

    It turns out that this is driven from the template's Price PHP file app/code/design/frontend/MYTHEME/template/catalog/product/price.phtml which reads the label values from the locale files and displays it.

    So the simple solution is to change the label values in app/locale/en_US/Mage_catalog.cvs:
    "Special Price:","Special Price:" 
    
    to
    "Special Price:","Our Special Price:" 
    

    and

    "Regular Price:","Regular Price:" 
    
    to
    "Regular Price:","Suggested Retail Price:" 
    

    However, the recommended upgrade-proof method would be to create a new locale specific translation file containing only the above desired changes and save it as: app/design/frontend/MYTHEME/locale/en_US/translate.csv.

    And don't forget to clear the cache after doing any of the above changes or they may not be visible on the front-end!

    Similarly you can change any labels that you desire. Note that this is case-sensitive and needs to be done very carefully.

    Magento - Ampersand in Category name not showing properly

    Quite a few Categories added to a test install of Magento shopping cart had the ampersand character in the name. The Category page was displaying the ampersand in the name as & a m p ; which is the special HTML entity for the ampersand character.

    I fiddled around with the settings in the back-end admin but there was no solution like the one I had stumbled upon for a similar problem in Product names here.

    After a lot of fiddling, it turned out that this was happening because the category view PHP file for the theme I was using had compatibility issues with the instaleld cart version. The solution was to modify the app/design/frontend/MYTHEME/template/catalog/category/view.phtml as follows:

    Search for occurrences the line:
    <h2><?php echo $_helper->categoryAttribute($_category, $this->htmlEscape($_category->getName()), 'name') ?></h2> 
    

    Replace with this line:
    <h2><?php echo $_helper->categoryAttribute($_category, $_category->getName(), 'name') ?></h2> 
    


    Explanation:
    We are changing the theme view code to not translate any characters in the name that may have a HTML Special Entity representation. So these will remain as they are and you will not see the names going haywire!

    Note that this may need to be done in a different file depending on which of the files are causing this problem. The errant file could be an incompatible older version of a plug-in as well.

    Magento - Ampersand in Product name not showing properly

    Some of the products added to a test Magento cart had ampersand & character in the name. When viewing the product page for such products, the ampersand in the name was being shown as & a m p ; which is the special HTML entity for the ampersand character.

    I was at a loss and almost on the verge of advising that Product name should not contain and special characters. However, while fiddling with the settings, I stumbled upon the setting in the attribute that allows HTML code in the name.

    In the back-end admin, go to Catalog >> Attributes >> Manage Attributes menu and then click on the name attribute. Set the Allow HTML-tags on Front-end to Yes and you are all set to show ampersand and other special characters properly in the product name!

    In fact, this same approach can be used for any field that is displaying such a similar behavior.

    Magento - Invalid argument supplied for foreach in toolbar.phtml

    After adding a new theme and uploading a big number of records to a fresh Magento install, I see the following error in the log files:

    Invalid argument supplied for foreach() in /home/content/07/6268407/html/app/design/frontend/MYTHEME/template/catalog/product/list/toolbar.phtml on line 63

    After much digging around, I realized that this error is due to change in Magento on how the pagination works now in 1.4 as compared to earlier versions. The theme I used was clearly not compatible with Magento1.4 and hence this issue. To resolve this problem, here are the steps I took:

    1. Create Template file for Pagination
    Create a new file for handling pagination according to the new way. Create a new file called pager.phtml in the /template/catalog/product/list/ folder inside your theme folder. Now write the below code into this new file:
    <?php if($this->getCollection()->getSize()): ?>
            <?php if($this->getLastPageNum()>1): ?>
            <td class="pages">
                <strong><?php echo $this->__('Page:') ?></strong>
                <ol>
                <?php if (!$this->isFirstPage()): ?>
                    <li><a href="<?php echo $this->getPreviousPageUrl() ?>"><img src="<?php echo $this->getSkinUrl('images/pager_arrow_left.gif') ?>" alt="<?php echo $this->__('Previous Page'); ?>" /></a></li>
                <?php endif ?>
                <?php foreach ($this->getPages() as $_page): ?>
                    <?php if ($this->isPageCurrent($_page)): ?>
                        <li><span class="on"><?php echo $_page ?></span></li>
                    <?php else: ?>
                        <li><a href="<?php echo $this->getPageUrl($_page) ?>"><?php echo $_page ?></a></li>
                    <?php endif ?>
                <?php endforeach;; ?>
                <?php if (!$this->isLastPage()): ?>
                    <li><a href="<?php echo $this->getNextPageUrl() ?>"><img src="<?php echo $this->getSkinUrl('images/pager_arrow_right.gif') ?>" alt="<?php echo $this->__('Next Page'); ?>" /></a></li>
                <?php endif ?>
                </ol>
            </td>
            <?php endif; ?>
    <?php endif ?>
    

    2. Call this Pagination code in Layout
    Edit the catalog layout xml file to include this new pagination code. Open the file catalog.xml in the /layout/ folder inside your theme folder. Now search for this line of code:
    <block type="catalog/product_list_toolbar" name="product_list_toolbar" template="catalog/product/list/toolbar.phtml">
    

    Below this line, add the following new line to call the pager file that you created in step 1 above:
    <block type="page/html_pager" name="product_list_toolbar_pager" template="catalog/product/list/pager.phtml" />
    

    3. Call this Pagination code in Toolbar
    Edit the toolbar html file to include this new pagination code. Open the file toolbar.phtml in the /template/catalog/product/list/ folder inside your theme folder. Now search for the below block of code approximately around lines 42 - 63:
    <?php if($this->getLastPageNum()>1 && is_array($this->getPages())): ?>
    ...
    ...
    ...
    <?php endif; ?>
    

    Now replace this block of code with the following single line of code:
    <?php echo $this->getPagerHtml(); ?>
    


    If you follow these 3 steps to the 'T' it should definitely resolve your problem!

    To find out details of errors, please go through this post on Debugging Magento.

    Monday, June 21, 2010

    Logitech QuickCam Deluxe Webcam on Ubuntu 9.04

    I suddenly realized that I had not used my Logitech QuickCam for Notebooks Deluxe Webcam on Ubuntu 9.04 till now! So I plugged it in and fired up Skype to do a Video Chat. To my pleasant surprise, it just worked right out of the box without requiring any tweaking, extra configuration or driver installation. The only thing that I had to do was to choose the Logitech devices as my Mic-In and Video-In devices.


    Check out the specs & reviews of Logitech QuickCam for Notebooks Deluxe on Amazon:

    Sony DSLR A230L Kit Refurb for 288 on SonyStyle

    SonyStyle has a Refurbished Sony DSLR A230L for $288 with Free Shipping. The kit consists of Body having 10.2 Megapixel resolution & in-body image stabilization and 18-55 Standard Zoom Lens.

    PROs:
    1. SteadyShot™ Image Stabilization in body
    2. HDMI Output
    3. Eye-Start™ Autofocus System
    4. Anti-Dust Technology helps keep the CCD imager clean
    5. Small & light body
    6. Accepts Memory Stick PRO Duo™, Memory Stick PRO-HG Duo™ and SD/SDHC media
    7. Very good for beginners
    8. Can shoot in RAW mode


    CONs:
    1. Grip has been a major crib across the forums
    2. Included Lens is just about average
    3. Limited functionality for "PRO" users
    4. Average battery life
    5. Pop-up flash is front facing which may be disadvantageous
    6. Custom hot-shoe for external flash
    7. Average low-light performance

    Verdict:

    A good deal for the price especially for beginners, more so as it contains the lens as well.



    For convenience, here's the direct link to DSLR-A230L on SonyStyle.



    Check out the reviews and tech specs on Amazon:

    Friday, June 18, 2010

    Dell Outlet Laptops on Sale

    Dell Outlet has a lot of good laptops & desktops with i3, i5 and i7 processors on sale right now.

    Go to Dell Outlet and click on Home & Home Office link at the bottom right.
    In the left menu, Check Availability & Prices section, select the product that you are interested in (laptop/desktop).
    Select the Processor i3/i5/i7 with desired speed, uncheck Certified Refurbished (if not interested in Refurbished items) in the top center and click Filter Results. To sort by price low to high, click the Price column header.

    Add desired item to your cart and then to make this deal sweeter, use coupon code
    ?C73C85JCXMXMG
    for an extra 15% off - this coupon expires today. You will also get free 3-5 day ground shipping automatically for Dell Laptops from outlet store.

    Check out the specs & reviews on Amazon:

    Wednesday, June 16, 2010

    Make your Blog Post Title SEO Friendly

    By default, the Blog Post Title that Blogger creates has the Blog Name followed by the Post title. This is not so SEO Friendly and it determines how you your blog title is displayed in search results. Making it more relevant increases the chances of people clicking through your link and besides, doing this is really very simple!

    Change Blog Post Title
    1. Go to Design > Edit HTML in your Dashboard
    2. Search for:
      <title><data:blog.pageTitle/></title>
    3. Replace it with:
      <b:if cond='data:blog.pageType == "index"'> 
        <title><data:blog.title/></title>
      <b:else/> 
        <title><data:blog.pageName/> | <data:blog.title/></title> 
      </b:if>
      
    4. Save the Template

    Note: The changes on your Blog will be immediate, but the results to show up on the search engines may take up time depending on how they spider and change their databases.

    Jamba Juice for a Dollar - 16 June 2010

    Today Jamba Juice is offering three of its new super-fruit smoothie flavors for only a dollar! These include Pomegranate, Yumberry or Acai 16 oz smoothies - they are just awesome!
    Yumberry fruit is a Chinese / Japanese Bayberry which looks like litchi except that the outer skin is also edible.
    Acai fruit or Acai berry has been long touted as a very good anti-oxidant but not clinically proven as yet.

    So go ahead and have a healthy fruit smoothie today for a buck, courtesy of Jamba Juice!

    Summer is here (almost)!

    Good to see that warmth is returning to the air and its summer time again!
    And along with the arrival of summer, it is good see new, fresh and very good templates/themes being made available from blogger!
    My previous blog template was good but was breaking and it was time to change it - what a timing from blogger in releasing the new templates!
    So to reflect the joy in the air, I have changed the template on my blog to be more cheerful!
    If you have a blogger/blogspot blog, do check out the new templates!

    With the new template, the Tag Cloud widget stopped working so I had to re-install it. If you face a similar problem, then check out the creator phydeaux3 blog page on this here. Only thing that I did not like about this widget is that it shows the current post also in the list of related posts. I feel filtering it should not be such a big task - I hope the creator can take note of this and implement it at the earliest.

    The code was not showing up properly after installing new template - this indicated that the Syntax Highlighter was not working. To re-install it, I referred to the detailed post here.

    Apparently, adding the new template broke the Related Posts widget as well, so I had to re-install that as well. Check out the instructions at the the creators' site here.

    Note: Please backup your current template locally before doing any such changes. Also you may need to re-install 3rd party widgets as they may not be cleanly supported by these new templates!

    Monday, June 14, 2010

    Fix Magento Error Message “Exception printing is disabled by default for security reasons”

    Sometimes when Magento exceptions out, it gives the message:
    “Exception printing is disabled by default for security reasons”
    To remove this message, follow the steps below:

    Step 1:
    Copy the file errors/local.xml.sample and name it as errors/local.xml

    Step 2:
    Modify the configuration to suit your needs - the xml is very well commented and self-explanatory. For leaving the error log files on the server for future reference as well as email it to the store admin, the config should be setup as below:

    <config>
        <skin>default</skin>
        <report>
            <!--
                "action" can be set to "print" to show exception on screen and "email"
                to send exception on specified email
            -->
            <action>email</action>
            <!--
                in "subject" you can set subject of email
            -->
            <subject>Store Debug Information</subject>
            <!--
                "email_address" admin email address
            -->
            <email_address>storeadmin@mystore.com</email_address>
            <!--
                "trash" is handle about trace info
                value "leave" is for store on disk
                value "delete" is for cleaning
            -->
            <trash>leave</trash>
        </report>
    </config>
    

    For more Magento debugging tips, check out my article Debugging Magento.

    Debugging Magento

    Magento some times errors out with the below message which gives no clue as to what might have gone wrong:

    There has been an error processing your request
    Exception printing is disabled by default for security reasons.
    Error log record number: XXXXXXXXXX
    

    If you have access to the files on the server, then go to the folder /var/report/ and look for the file named with the above number and open it up - you will see a "stack trace" of the error!

    In case you do not have access to these files, fear not! You can enable the printing of the logs on the front-end. Open the file index.php and uncomment line 71 to display the errors:

    ini_set('display_errors', 1);
    

    But remember - do not keep this on for a long time as the error messages will be visible to the world.

    Monday, June 7, 2010

    Rip Audio CDs in Ubuntu

    I had an old music audio CD that I wanted to convert/rip to MP3 and then upload to my RockBox-ed Sansa e260. This is quite a simple task if you have the right set of tools with you. Here's how I did it on Ubuntu 9.04.

    Here are the steps to get this done:
    1. Install SoundJuicer
    2. Install MP3 Encoder
    3. Setup Sound Juicer to convert to MP3
    4. Convert the Audio CD

    Install SoundConverter
    You need to install soundjuicer application from the Synaptic package manager. This program does the work of converting between formats and supports WAV, FLAC and OGG Vorbis natively. So for converting to MP3 and other formats, it requires the appropriate encoders.

    Install MP3 Encoder
    You need to install GStreamer MP3 Encoder (gstreamer-0.10-plugins-ugly) from Multi-Verse link apt:gstreamer0.10-plugins-ugly-multiverse?section=multiverse as mentioned on the SoundConverter website since it is not directly supported by Ubuntu and so may not available from the Synaptic package manager.

    Setup SoundJuicer to convert to MP3
    Now that our installation is complete, fire-up the Sound Juicer application Applications > Sound & Video > Audio CD Extractor and go to Edit > Preferences menu. Change the Format > Output Format to ".MP3"; Bitrate Mode to "Variable (VBR) - Best Quality; and Quality to High.

    Convert the required files
    This completes our setup and now we are ready to convert files. Just load the audio CD you want to convert and press the Extract button!

    Note: Sometimes if the tracks in the Audio CD do not have any tag info, then Sound Juicer simply crashes. In that case, copy the files from the CD onto a local folder and then follow the steps to convert WAV to MP3 in my post here

    Convert WAV files to MP3 in Ubuntu

    I had old music files in WAV format that I wanted to convert to MP3 and then upload to my RockBox-ed Sansa e260. This is quite a simple task if you have the right set of tools with you. Here's how I did it on Ubuntu 9.04.

    Here are the steps to get this done:
    1. Install SoundConverter
    2. Install MP3 Encoder
    3. Setup Sound Converter to convert to MP3
    4. Convert the required files

    Install SoundConverter
    You need to install soundconverter application from the Synaptic package manager. This program does the work of converting between formats and supports WAV, FLAC and OGG Vorbis natively. So for converting to MP3 and other formats, it requires the appropriate encoders.

    Install MP3 Encoder
    You need to install GStreamer MP3 Encoder (gstreamer-0.10-plugins-ugly) from Multi-Verse link apt:gstreamer0.10-plugins-ugly-multiverse?section=multiverse as mentioned on the SoundConverter website since it is not directly supported by Ubuntu and so may not available from the Synaptic package manager.

    Setup SoundConverter to convert to MP3
    Now that our installation is complete, fire-up the Sound Converter application and go to Edit > Preferences menu. Change the Type of result? > Format to ".MP3"; Bitrate Mode to "Variable (VBR) - Best Quality; and Quality to High.

    Convert the required files
    This completes our setup and now we are ready to convert files. Just add the files you want to convert and press the Convert button!

    Note: that you will need to copy files from the Audio CD onto your HDD before starting the conversion otherwise SoundConverter complains and does not do anything.

    Note: If you sinply want to rip an Audio CD, then follow the steps to rip an Audio CD to MP3 in my post here

    Full featured hosting for $1.99 per month

    For those on the lookout for a good Web Hosting Deal, WebHostingPad.com is now offering full featured unlimited hosting for $1.99/month when prepaid for 4 or 5 years!

    For those looking for affordable Linux + Java/JSP Web Hosting, DailyRazor is providing a full featured unlimited hosting including Shared Tomcat for $4.60/month when prepaid for 3 years!
    If looking for a regular hosting, DailyRazor is offering a full featured unlimited web hosting for only $2.95/month when prepaid for 3 years.
    Use coupon code 15PD for another 15% discount at DailyRazor!

    Checking for NaNs

    In Sybase 12.5.4, checking for NaN is very simple - just convert the number to a string and check for the string!
    select * from mydata where STR(numcol) like '%NaN%'
    

    From Oracle 10g onwards, this is very simple as a special NaN value is made available for checking against:
    select * from mydata where numcol is NaN
    

    Tuesday, June 1, 2010

    Bagel and Coffee for a Buck plus more food deals

    Its always good to see cheap food deals, especially in NYC! So this week Mustang Cafe on 22 W 38th Street between 5th and 6th Avenues has the following deals:
    Breakfast
    Toasted Bagel with Butter and small Coffee or Tea for $1.
    Lunch
    Tossed or Chopped Salad with 1 Main ingredient and Unlimited Toppings with Free Small Soup. Small Salad for $6.99 and Large Salad for $7.99.

    Enjoy it while it lasts!

    Update: As of the week of June 21, these deals are still valid!

    Friday, May 21, 2010

    Import Products and Categories into Magento

    Of the few shopping carts that I was playing around with, I found Zen Cart and Magento to be the best. Simplicity of the Zen Cart was very alluring and Magento was attractive for its features based on the solid framework.

    However, for a new store, importing all the products and categories for the initial setup is a major area for complaint. I wonder, how such a simple and important features gets left out of such a thought out & planned product?!

    The developer community has provided plug-ins for Zen Cart and Magento Extensions to solve this problem to some extent. However I still feel that the ones available for free are not so well integrated and do not provide a very clean solution. A better integrated & cleaner solution should come in pre-packaged with the cart.

    The solution should take care of and provide the following features:
    • Import Category hierarchies
    • Import Product Images & gallery if required
    • Associating of Related, Cross Sell & Up Sell products

    *** Sighhh **** well, so much for wishes - for now, use what you get to be as close to the end goal as possible and mash-up the required functionality with it.

    Useful jQuery Tips

    Recently I have started playing around a bit with jQuery and find it quite amazing. To Quote straight from the jQuery site: jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript


    In essence, what this means is that if you are not so good at understanding & writing complex JavaScript, use this wrapper/framework to simplify your coding life! This also implies that using jQuery could be slower than rolling your own library if your needs are limited and you can afford to dirty your hands with JavaScript.


    But, since I had decided to play with and use jQuery anyways, I started to look around for good articles and found this very useful article by Jon Hobbs-Smith of TVI Design UK.


    Here are a few useful cheat sheets:
    The visually best one I felt is (a rather big one at 6 pages) JQuery 1.3 Cheat Sheet by Woorkup.
    Another good one with nice details is jQuery Cheat Sheet by Matt Kruse - its available in various formats and for different versions as well!


    Be sure to check the comments on these posts for other people's observations and also ensure that you use the cheat sheet appropriate for the version of jQuery you are using!

    Wednesday, April 28, 2010

    Adding Google Custom Search to your Blog

    Adding Custom Search to your Blogspot Blog enhances its value and allows visitors to sift through your posts with ease. Adding Google Custom Search is not simple or for the fain at heart. It requires tons of patience, a keen eye and a good comfort level at playing with code. For a live demo, I have added the same to my blog as well, so feel free to try it out! Adding Google Custom Search is not simple, here are the steps that are required:
    1. Create a static page on Blogger for displaying Search Results
    2. Sign Up for Google AdSense - if you want to earn money
    3. Sign Up for Google Custom Search
    4. Update the static page with Google Custom Search Code
    5. Remove side bar & meta-data displayed on the static page
    6. Add search box on side bar
    So here goes, get ready to get down & dirty with the details ...

    1. Create a static page on Blogger

    Create a static page on Blogger for displaying Search Results. Go to Posting > Edit Pages and click on the New Page button to create a new static page. Set the title as Search Results or anything appropriate and for now, enter placeholder text Search Results in the page. View this page and note down the URL of this page - this will be used in the later steps when configuring Google Custom Search.

    2. Sign Up for Google AdSense

    If you want to earn some money through the searches that are done on your site, you will need to sign-up for an adsense account. Here I am assuming that you already have one - if not, then just go ahead and sign up for one.

    3. Sign Up for Google Custom Search

    From inside the AdSense account, click on the link AdSense for Search and then follow the steps below:

    • Click on Single Page link at the top to view all the options in one page
    • Search Type: Select Only sites I select
    • Selected sites: If you have more than one site, enter one site per line for each of the websites you want to include in the search.
    • Optional Keywords: Enter keywords separated by space if you want to give hints to the search engine.
    • Opening of search results page: Select Open results within my own site and in the box below for Enter URL where search results will be displayed, enter the URL of the static page created in Step 1 above.
    • Ad Location: You can choose whichever option you like, but I personally prefer to go for Top and Bottom
    • Name Your Search Engine: give a name for your custom search engine
    • Fill in all the other remaining fields as per your requirement
    • Press the Submit and Get Code button to get the Javascript code that you need to put into the static page

    4. Update static page on Blogger

    Go to Posting > Edit Pages and click on the Edit link for the static page created above. Then:

    1. Copy code from Search box code and paste it here
    2. Enter a break tag <br>
    3. Copy code from Search results code and paste it here

    5. Remove side bar & meta-data displayed on the static page

    Now this is the tricky part which requires you to change the template. You can skip this step if you are OK with having the widgets display on the right column. Note: take a backup of your template before proceeding!
    Go to Layout > Edit HTML and check the box Expand Widget Templates. Then add the line: to the following 3 places:
    To remove the Post Metadata (Author, Tags, Time) from Static page
    Lines 1 and 19 in this code snippet

           <b:if cond="data:blog.pageType != "static_page"">
       <div class="postmeta">
       <b:if cond="data:top.showAuthor">
          Posted by
          <span class="fn"><data:post.author/></span>
          </b:if> |
       <b:if cond="data:post.labels">
       Posted in
            <b:loop values="data:post.labels" var="label">
              <a expr:href="data:label.url" rel="tag"><data:label.name/></a><b:if cond="data:label.isLast != "true"">,</b:if>
            </b:loop>
          </b:if> |
       <b:if cond="data:top.showTimestamp">
          <b:if cond="data:post.url">
          Posted on <data:post.timestamp/> 
          </b:if>
          </b:if>
       </div>
          </b:if>
     </div>
    

    To remove the "Continue Reading" or similar link from Static page
    Lines 2 and 7 in this code snippet
     <b:if cond="data:blog.pageType != "item"">
            <b:if cond="data:blog.pageType != "static_page""><br/>
     <div class="postmetadata">
        <p><a expr:href="data:post.url">Continue Reading</a></p>
     </div>
        </b:if>
        </b:if>
    

    To remove the right Column widgets from Static page
    Lines 2 and 14 in this code snippet
     <!-- Body_right -->
    <b:if cond="data:blog.pageType != "static_page"">
        <div id="body_right">
       <!-- Sidebar Ads -->
    ...
    ...
       <!-- /Sidebar Ads -->
       
       <!-- Sidebar -->
       <div id="sidebars">
    ...
    ...
          </div>
    </b:if>
       <!-- /Body_right -->
    

    6. Add search box on side bar

    To add search box on side bar, go to Layout > Page Elements and click on the Add a Gadget link on the bottom right. Add a HTML/JavaScript widget and in the window that opens up, enter the following:

    • Title: Search or something similar
    • Content: Here paste the code from Google Custom Search / AdSense for Content from the box Search box code
    And after these long & complicated steps, you should have your Google Custom Search with AdSense on your Blogger Blog ready!!!

    Thursday, April 15, 2010

    Implement reCAPTCHA with Classic ASP and Validate with AJAX

    A friend asked me to help implementing reCAPTCHA with classic ASP which I successfully managed to implement even though I have not dabbled much with ASP - read the implementation here.
    So now the expectations rise and he asks me to validate reCaptcha using AJAX - I do not have any experience of AJAX combined with ASP either.

    Going through the resources section of the recaptcha.net site did not help much in this regard. So here are the steps that I did to achieve this. Note that most parts of the solution here have been taken from various pages on the net which are listed at the bottom of this post in the References section.


    There are 6 parts of the code as follows:
    1. JavaScript to create reCaptcha on the page that has the input form
    2. Insert the created reCaptcha in the desired location
    3. Generic JavaScript to make AJAX call
    4. Make AJAX call to Server-side component to validate reCaptcha
    5. Handle AJAX validation response from server-side component
    6. Server side component to validate the reCaptcha

    1. JavaScript to create reCaptcha on the page that has the input form
    Here is the code that needs to be placed in the ASP file to generate the JavaScript which when called, generates the code for reCaptcha. The generated string needs to be placed in your form where you want the reCaptcha to be displayed.

    <%
    recaptcha_public_key = "XXXXXXXXXXXXXXXX"
    function recaptcha_challenge_writer(publickey) 
      recaptcha_challenge_writer = "<script type=""text/javascript"">" & _ 
     "var RecaptchaOptions = {" & _ 
     " theme : 'red'," & _ 
     " tabindex : 0" & _ 
     "};" & _ 
     "</script>" & _ 
     "<script type=""text/javascript"" src=""http://api.recaptcha.net/challenge?k=" & publickey & """></script>" & _ 
     "<noscript>" & _ 
     "<iframe src=""http://api.recaptcha.net/noscript?k=" & publickey & """ frameborder=""1""></iframe>
     " & _ 
     "<textarea name=""recaptcha_challenge_field"" id=""recaptcha_challenge_field"" rows=""3"" cols=""40""></textarea>" & _ 
     "<input type=""hidden"" name=""recaptcha_response_field"" id=""recaptcha_response_field"" value=""manual_challenge"">" & _ 
     "</noscript>" 
    end function 
    %>
    

    2. Insert the created reCaptcha in the desired location
    Here is how you need to place the code in your form where you want the reCaptcha to be displayed.

    <%=recaptcha_challenge_writer(recaptcha_public_key)%>

    3. Generic JavaScript to make AJAX call
    Here is a generic JavaScript function to make an AJAX call
    
    

    4. Make AJAX call to Server-side component to validate reCaptcha
    Here is the JavaScript "onClick" function that will make the specific call to the server-side component to validate the reCaptcha input.

    
    

    5. Handle AJAX validation response from server-side component
    Here code that needs to be put in the asp file that processes the submitted form.

    // The function for handling the response from the server
    var showMessageResponse = function (oXML) { 
        
        // get the response text, into a variable
     var response = oXML.responseText;
        
        // act on the result from the server
     if (response == "PASS") {
      //alert("Captcha Passed ...");
      document.getElementById("Form1").action = "process_form.asp";
      document.getElementById("Form1").submit();
     }  else {
            // Reload the captcha image if the validation failed & alert the user
     alert("Captcha Failed. Please try again ...");
     Recaptcha.reload();
     }
    };
    

    6. Server side component to validate the reCaptcha
    Here code that needs to be put in the asp file that processes the submitted form.

    'Define some variables to be used on page
    dim pubkey, privkey, challenge, form_response, test_captcha, recaptcha_confirm
    
    'Customize your public and private keys and other variables
    pubkey = "XXXXXXXXXXXXXXXX"
    privkey = "XXXXXXXXXXXXXXXX"
    
    ' Get the user input
    challenge = Request.Form("recaptcha_challenge_field")
    form_response = Request.Form("recaptcha_response_field")
    
    ' Generate the POST string for reCaptcha
    Dim VarString
    VarString = _
    "privatekey=" & privkey & _
    "&remoteip=" & Request.ServerVariables("REMOTE_ADDR") & _
    "&challenge=" & challenge & _
    "&response=" & form_response
    
    ' Make an AJAX call to validate input reCaptcha
    Dim objXmlHttp
    Set objXmlHttp = Server.CreateObject("Msxml2.ServerXMLHTTP")
    if isNull(objXmlHttp) then
    Set objXmlHttp = Server.CreateObject("Microsoft.XMLHTTP")
    end if
    objXmlHttp.open "POST", "http://api-verify.recaptcha.net/verify", False
    objXmlHttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
    objXmlHttp.send VarString
    
    ' Receive response from reCaptcha server
    Dim ResponseString
    ResponseString = split(objXmlHttp.responseText, vblf)
    Set objXmlHttp = Nothing
    
    if ResponseString(0) = "true" then
    'They answered captcha correctly
        response.write("PASS")
    else
    'They answered captcha incorrectly
        response.write("FAIL")
    end if
    


    Note:
    1. Of course, you need to sign-up for a free reCaptcha account at reCaptcha.net.
    2. The above steps 1, 3, 4 & 5 can be put in the same script block.
    3. The above step 2 needs to be put in the place in the form where reCaptcha is to be shown.
    4. Remember to substitute the public & private keys with the ones that you get when you sign up for a free reCaptcha account.
    5. This is a very basic, no-frills version. You can modularize, clean-up, optimize and add more error-handling. But this should be good enough to get you started!

    References:
    1. This Google Groups post
    2. reCaptcha resources page
    3. This post on Jeff Niblack's Blog
    4. This post on World of Code Blog
    5. This blog post on Dark Side of Carton.

    Syntax Highlighter now available for Blogger

    I had been putting off using Syntax Highlighter for quite some time as it required me to host the files somewhere and then use them. Also, using it for a Blogger Blog did not seem to be so straight-forward and did not produce clean results. This was the status when I had last checked it out quite some time back.

    So when reviewed a post I wrote with a lot of code in it, I was saddened that I had not add Syntax Highlighter to my blog. So I decided to take a second look and was pleasantly surprised to see both my issues resolved! Now there was an option for using the hosted version of the files and also there was a very neat blogger mode!

    So now finally, you don't need to look around for someone to host the Syntax Highlighter files for you - you can use the hosted version of the Syntax Highlighter files. And there is a very good bloggerMode! which helps to integrates very cleanly with Blogger.

    Implementing reCaptcha in Classic ASP

    A friend of mine was very impressed with reCaptcha and wanted me to help him implement on his website that uses classic ASP! Going through the posts mentioned in the reference below gave me a bit of an idea but the solution was not very clear. Here's how I finally implemented it...

    There are 3 parts of the code as follows:
    1. JavaScript to create reCaptcha on the page that has the input form
    2. Insert the created reCaptcha in the desired location
    3. Server side component to validate the reCaptcha

    1. JavaScript to create reCaptcha on the page that has the input form
    Here is the code that needs to be placed in the ASP file to generate the JavaScript which when called, generates the code for reCaptcha. The generated string needs to be placed in your form where you want the reCaptcha to be displayed.

    <%
    recaptcha_public_key = "XXXXXXXXXXXXXXXX"
    function recaptcha_challenge_writer(publickey) 
      recaptcha_challenge_writer = "<script type=""text/javascript"">" & _ 
     "var RecaptchaOptions = {" & _ 
     " theme : 'red'," & _ 
     " tabindex : 0" & _ 
     "};" & _ 
     "</script>" & _ 
     "<script type=""text/javascript"" src=""http://api.recaptcha.net/challenge?k=" & publickey & """></script>" & _ 
     "<noscript>" & _ 
     "<iframe src=""http://api.recaptcha.net/noscript?k=" & publickey & """ frameborder=""1""></iframe>
     " & _ 
     "<textarea name=""recaptcha_challenge_field"" id=""recaptcha_challenge_field"" rows=""3"" cols=""40""></textarea>" & _ 
     "<input type=""hidden"" name=""recaptcha_response_field"" id=""recaptcha_response_field"" value=""manual_challenge"">" & _ 
     "</noscript>" 
    end function 
    %>
    

    2. Insert the created reCaptcha in the desired location
    Here is how you need to place the code in your form where you want the reCaptcha to be displayed.

    <%=recaptcha_challenge_writer(recaptcha_public_key)%>

    3. Server side component to validate the reCaptcha
    Here code that needs to be put in the asp file that processes the submitted form.

    'Define some variables to be used on page
    dim pubkey, privkey, challenge, form_response, test_captcha, recaptcha_confirm
    
    'Customize your public and private keys and other variables
    pubkey = "XXXXXXXXXXXXXXXX"
    privkey = "XXXXXXXXXXXXXXXX"
    
    ' Get the user input
    challenge = Request.Form("recaptcha_challenge_field")
    form_response = Request.Form("recaptcha_response_field")
    
    ' Generate the POST string for reCaptcha
    Dim VarString
    VarString = _
    "privatekey=" & privkey & _
    "&remoteip=" & Request.ServerVariables("REMOTE_ADDR") & _
    "&challenge=" & challenge & _
    "&response=" & form_response
    
    ' Make an AJAX call to validate input reCaptcha
    Dim objXmlHttp
    Set objXmlHttp = Server.CreateObject("Msxml2.ServerXMLHTTP")
    if isNull(objXmlHttp) then
    Set objXmlHttp = Server.CreateObject("Microsoft.XMLHTTP")
    end if
    objXmlHttp.open "POST", "http://api-verify.recaptcha.net/verify", False
    objXmlHttp.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
    objXmlHttp.send VarString
    
    ' Receive response from reCaptcha server
    Dim ResponseString
    ResponseString = split(objXmlHttp.responseText, vblf)
    Set objXmlHttp = Nothing
    
    if ResponseString(0) = "true" then
    'They answered captcha correctly
    ''' Handle Success scenario
    else
    'They answered captcha incorrectly
    ''' Handle Failure scenario
    end if
    


    Note:
    1. Of course, you need to sign-up for a free reCaptcha account at reCaptcha.net.
    2. The code in step 3 above needs to be put in the top of the file which processes your submitted form - the asp file that is mentioned in the action of this particular form. The above code needs to be executed before anything else in that file.
    3. It's regular processing steps should be put in the if block (line 37) that has the comment that the user answered the captcha correctly.
    4. Error message display logic should go into the else block (line 40) that has the comment that the user answered the captcha incorrectly.
    5. Remember to substitute the public & private keys with the ones that you get when you sign up for a free reCaptcha account.
    6. This is a very basic, no-frills version. You can modularize, clean-up, optimize and add more error-handling. But this should be good enough to get you started!

    References:
    1. This Google Groups post
    2. reCaptcha resources page
    3. This post on Jeff Niblack's Blog
    4. This post on World of Code Blog

    Are campaigns like "Big Picture" really effective?

    I sure got my travel mug today and got free coffee from Starbucks. Starbucks is offering free coffee today (April 15th) to encourage people to reduce usage of paper cups - read my post about that here. This opens up the debate that whether these kind of programs really work? Here's my take ...

    First hand experience - lugging around the travel mug is a pain which I am not ready to do everyday. The coffee was good, but cleaning the travel mug that has a narrow bottom was real pain as well. And God save you in case you got caught up in work / meeting and the leftover coffee in the travel mug dries up - cleaning it will require way more effort than you can imagine. These are the non-material negatives to using the travel mug.

    Now coming to the material aspect - buying a travel mug costs some dough and if you go in for a "cool" one, get ready to be set back by at least 10 bucks. But that's only one time for however long you can manage to hold onto the mug. However, washing the travel mug with (running) hot water and soap after every use will require investing in soap & scrubber, add to the bill for heating water and use up your time {Remember - Time = Money!}. Also, producing the energy to heat the water may not be exactly soft on the planet either - but we may not know or notice that exactly.

    Now for the psychological aspect of this issue. Most people will take this campaign as an opportunity to get *FREE* coffee. Many people may even drive extra miles just for this and in the process end up spending the cost of the coffee on gas instead! And from the very next day - most people will revert to their normal routine and use (and throw away) paper cups, tissues, plastic cutlery left and right as usual. Very very very few people would actually have a change of heart and
    change their habits in a single attempt of such a one day campaign.

    Even if I had not got the chance to get the free coffee, I would have sub-consciously noted that this is a good company which I should patronize the next time I am going to buy a product that they offer. This gives the company huge advantage over the competition. So in the end, what is gained is that people got free coffee and the company scores brownie points for being & encouraging people to go green as well as get a lot of cheap, effective & useful advertisement.

    So, what do you think? And what would you do?!

    Wednesday, April 14, 2010

    Starbucks to Make a Difference with the Big Picture

    Starbucks is trying to make a difference through its The Big Picture Green Project. Starbucks is asking general public to join the movement and on April 15th, it is encouraging people to reduce their usage of paper cups by giving free brewed coffee to those who bring in a reusable travel mug into their local Starbucks store. Their quote: One person can save trees, together we can save forests. is really worth working towards!

    It is good to such big corporations like Starbucks sharing their responsibilities towards our communities and the planet and trying to make a difference. I wish more corporations follow the lead and do such campaigns to make this planet a better place to live in!

    Thursday, April 8, 2010

    URL Rewrite very slow on IIS7

    My friend has an ASP shopping cart running on Windows 2008 Server + IIS7 + SQL Server. This cart does not support SEO / user friendly URLs and apparently due to that, his site was getting very low rankings on the search engines. He called me in to help him out implement URL Rewriting to resolve this. Here is my experience with this problem and finally how I went about resolving this.

    So the first step was to install the URL Rewrite Module 2.0 for IIS. Next was to configure the rewriting of the URLs - the cart produced URLs of the form store/listItems.asp?cat=123&item=456. The item id number and the corresponding category id number changed for different items so putting in a generic regular expression would not work. So we would need to create static rewrite maps to achieve our goal.

    So I created a rewrite map with entries like /store/listItems.asp?cat=123&item=456 mapped to /Item1 and /store/listItems.asp?cat=123&item=457 mapped to /Item2 and so on. This worked but the page did not come up properly. Investigation revealed that this was due to the HTML having relative URLs for CSS, Image & JavaScript files. I changed paths to absolute paths and lo-behold it was working fine! However, when using the user-friendly URL, the pages would come up quite slow compared to the page display using the old URLs.

    In fact the pages came up so slow that we had to scrap this idea and look for other alternatives. Finally, after a lot of investigation, we fixed on the ages-old method of creating static HTML index files in folders named by each category. The header, footer & navigation menus would be common and kept in common folder. I know that this is not such a good idea and will result in creation of hundreds of folders with only an index file. But what the heck - it is simple, it works and it gets the job done!

    Friday, April 2, 2010

    Cheap Webhosting Deals

    It seems that April is the month for Cheap Web Hosting Deals!!!
    Here is a round-up of the cheapest (but not necessarily the best) web hosting deals I found out.

    However, my personal favorite is always BlueHost for their excellent support & fast servers. Check out my post on the same here.

    NOTE: No guarantees on the validity of the offers or the quality of the services. I am in no way connected to any of these hosting companies and the links provided are direct links (no affiliate tracking code). I do not gain in any way from you clicking on any of these links and/or signing up for any of these offers!!!


    Lifetime Webhosting for $79
    HostSure is offering a full featured lifetime web hosting for only $79 where most companies offer that for $60-$100/year.

    Facade Host
    Facade Host is offering shared web hosting packages for as low as only only $0.85/month where most companies offer that for $2-$5/month. Use coupon code april for a further 20% discount!

    Cookie Host
    Cookie Host is offering shared web hosting packages for as low as only only $5/year where most companies offer that for $60-$100/year. Note that the promotion starts on April 7th 2010 and is valid only for new hosting accounts. The good thing is that they do not automatically rebill you at the end of the first year and you will be given the option to renew at the then prevailing regular price.

    Just Host
    Just Host is offering a full featured unlimited web hosting with free domain for the life of hosting for only $3.45/month when prepaying for 2 years. Use coupon code 50OFF for a further discount to bring down the price to $2.95/month when prepaying for 2 years!

    Fat Cow
    Fat Cow is offering a full featured unlimited "green" web hosting with free domain for the life of hosting for only $66/year!

    Dream Host
    Dream Host is offering a full featured unlimited "green" web hosting with free domain for the life of hosting for only $9.24/year with coupon code 777!

    Daily Razor
    Daily Razor is offering a full featured unlimited web hosting for only $2.95/month. Use coupon code 15PD for another 15% discount!

    NOTE: Not all of these plans may suit your needs

    Wednesday, March 31, 2010

    Deleting duplicate rows in Sybase

    I had to delete a set of duplicate rows in Sybase and that had me in a quandry. I had done that many-a-times in Oracle using the ROWID psuedo-column but nothing similar is available in Sybase or for that matter in SQL Server. Here's how to go about this daunting task in Sybase!


    The deletion of duplicate rows cannot be done in a single SQL query like it can be done in Oracle. Hence it needs to be done in 3 steps:
    1. Create temporary table with one instance of each distinct row
    2. Delete all rows having multiple instances
    3. Move back the unique data from temporary table to actual table

    Step 1:
    Create temporary table with one instance of each distinct row with the below query.
    select distinct t.* into temp_table_name
    from data_table_name t
    group by keycol1, keycol2, keycol3 
    having count(0) > 1
    
    Note: that this step creates the temp_table_name table so it will fail if a table by that name already exists.

    This step puts one instance of each distinct row into the temporary table. However, some of the rows may contain identical values in the key columns but different data in the remaining columns. At this point you need to check the data in the temp_table_name and reconcile which of the rows you wish to keep for a given duplicate key value. You may even need to do these three steps on the temporary table to achieve a set of unique records in the temporary table.

    Step 2:
    Delete all rows having multiple instances with the below query.
    delete data_table_name from temp_table_name 
    where data_table_name.keycol1 = temp_table_name.keycol1 
    and data_table_name.keycol2 = temp_table_name.keycol2 
    and data_table_name.keycol3 = temp_table_name.keycol3
    

    Step 3:
    Move back the unique data from temporary table to actual table with the below query.
    insert into data_table_name 
    select * from temp_table_name
    

    Remember to change the table & column names in the above queries.
    Replace data_table_name with your actual table name,
    temp_table_name with your choice of name for temporary table and
    keycol1..n with the actual table column names!

    Check out my previous post here for doing this same thing in Oracle.

    Deleting duplicate rows in Oracle

    Deleting duplicate rows in Oracle seems to be the simplest to me (may be because I have used it more or may be its quite simple really!). Lets get down straight to the code and do a recap of how to delete duplicate rows in Oracle.

    Simple Solution
    Note that this simple solution assumes that there are no primary or unique keys on the table but the combination of data in a set of columns defines the duplicates. The example shows three key columns, but you can use more or less columns to identify unique rows based on your actual data.

    DELETE FROM data_table
    WHERE rowid not in
    (SELECT MIN(rowid)
    FROM data_table
    GROUP BY keycol1, keycol2, keycol3
    

    However, there could be cases where the table has a sequence / auto-generated column as the primary key. In such cases too, you can use the above query after substituting rowid with the id column name.

    Advanced Solution
    If you are looking for an advanced and faster solution with more features & flexibility, you can use the following solution that I found on devx. This solution uses RANK() function's capabilities to provide the extra features.

    DELETE
    FROM data_table
    WHERE ROWID IN
    (SELECT tmp_key
    FROM
    (SELECT tmp_key, keycol1, keycol2,
    RANK() OVER (PARTITION BY keycol1, keycol2 ORDER BY tmp_key) AS seq_num
    FROM
    (SELECT rowid as tmp_key, keycol1, keycol2
    FROM data_table
    WHERE (keycol1, keycol2) IN
    (SELECT keycol1, keycol2
    FROM data_table
    GROUP BY keycol1, keycol2
    HAVING COUNT(0) > 1)))
    WHERE seq_num > 1)
    

    Let me break up this complicated query into parts and explain in detail.
    1. The innermost sub-query (lines 12 - 15) finds those records that have duplicates. This gives us the sub-set of data that are only duplicate rows.
    2. The next outer sub-query (lines 9 - 11) uses ROWD psuedo-column to create a single key column. This adds a key column to the set of data rows we are interested in.
    3. The next outer sub-query (lines 6 - 8) uses RANK() function to dynamically assign sequence numbers to rows in the set of duplicate rows and orders them. Note that there are a set of sequence numbers each for each set of duplicate rows. This assigns a sequence number to and orders the rows inside each set of duplicates.
    4. The next outer sub-query (lines 4, 5 & 16) selects the duplicate rows based on the sequence number assigned by the RANK function is above step.
    5. The outer-most query (lines 1 - 3) deletes the duplicate rows.

    Note: In case the table has a unique / primary key, substitute that instead of the ROWID psuedo-column in the above solution to get the same results.

    Now, the extra features that using RANK provides are that you can choose the number of rows you want to keep. For example, you want to keep only the top 10 rows, you can change the numbers in lines 15 & 16 of the above query from 1 to 10 and add a proper ORDER BY to line 7 to get the data sorted in the required manner to determine the "top 10 rows".

    Similarly, if you want to keep only the latest row, you can add a proper ORDER BY clause to line 7 to get the data sorted in the required manner to determine the latest row.

    Remember to change the table & column names in the above queries.
    Replace data_table with your actual table name and
    keycol1..n with the actual table column names!

    Check out my next post here for doing this same thing in Sybase.

    LinkWithin

    Related Posts Plugin for WordPress, Blogger...