Saturday, December 8, 2007

Corporate Intranet Blogging

One of my coworkers recently came up with what I thought was a really good idea. He suggested that the company allocate time for us to blog. From a marketing standpoint, this could be good public relations in terms of finding both customers and employees, but from a business standpoint, there is a danger of compromising corporate intellectual property.

A lot of other companies have been successful with this idea, but our management is against the idea because of the fact that company secrets could inadvertently find their way into the hands of a competitor.

Therefore, my solution is corporate intranet blogging. We take the idea and we push forward with it, but only internally. This won't buy us any PR points, but it will provide everyone in the company with a platform where they can keep everyone up to date on any cool technologies, advice, bugs, or projects that they've worked on.

This would be a great extension of documentation. If I spend a few days fixing a nasty bug that I think someone else in the company may encounter, the fix will be documented in my intranet blog. If I know that coworker A has really good suggestions for user interface design, I can periodically review the blog for new advice. Sure, this may not be necessary when everyone works in the same office during the same hours, but suppose most employees work in another office? This is a great way to find out what everyone is working on without having to necessarily ask.

Tuesday, November 27, 2007

A Quarterback's Operating System

"Perhaps this is what needs to happen. Every Linux seller from Novell to Dell (via Canonical) buys air time during the Super Bowl and co-ops a website and a call center phone number for people interested in getting more information."

- Matt Hartley at Mad Penguin dot org

At the beginning of 2007, I was saying the same thing! I was extremely disappointed during the last Super Bowl! Well, not really. The Colts defeated the Bears in an exciting game where the combined efforts of Peyton Manning, Adam Vinatieri, and the Colts offense and defense put enough points up on the scoreboard to defeat the Bears. As one of the only two undefeated teams in the NFL this year, the Colts could end up playing at another Super Bowl game once again.

Although I wrote this article before the Colts loss to the Patriots, the Colts are still in the running and could still defeat the Patriots if they play as aggressively as the Eagles did!

This time, I'd like to see Peyton Manning take his acting career a step further. Last season, Peyton was the spokesman for Verizon. Instead of gaining sponsorship from Verizon, this year I'd like to see Peyton Manning in a Linux commercial. Linux is touted as a geeks' operating system. However, Linux distributions such as Ubuntu are clearly targeting your average home users. So what better way to advertise than to do exactly what Matt Hartley has suggested?

As I mentioned, I didn't see a single Linux commercial during the last Super Bowl, but I totally expected to see one! I was so sure that Linux would make its debut into mainstream media. With Vista looming on the horizon, now is the perfect opportunity for Ubuntu, SUSE, and other Linux distributions to spread the word during the largest televised event during the year.

Novell, you are a corporation. Throw some of those corporate dollars to Peyton Manning! Dell, you already advertise. Help out the open source movement and promote Ubuntu on your laptops! This is what makes you stand out from the crowd! Capitalize on it!

No one ever said it was illegal to make sales from open source software!

Saturday, November 10, 2007

Google Releases New Version of Gmail

Google has released a new version of Gmail. The ui parameter that appeared in the URL recently, the one that broke the HTML Reply Signatures for Gmail Signatures Firefox Extension and Greasemonkey, was part of the plan for allowing users to switch between the newer version and the older version.

How to Go Back to Gmail's Older Version explains more of the details regarding the new version features as well as how to switch back to the older version.

I just bought a 1968 Ford Thunderbird! I bought it yesterday actually. It hasn't even been 24 hours! It has a 429 cubic inch big block V8, suicide doors, a nice, well-preserved leather interior, and driving this well-engineered machine is like stepping back in time! It also has enough power to propel you into tomorrow!

And just how does this relate to the Gmail Reply Signatures Extension you ask? Well, it will be awhile before I will be able to fix this newly created Gmail bug, so for now, I'm going to recommend that you use the older version of Gmail so you can still use your HTML Signatures. Fortunately, Google is good at allowing us to enjoy backwards compatibility for awhile.

I'll post pictures of the car soon!

Thursday, November 1, 2007

Rebooting Linux

Rebooting Linux. These are two words that are seldom said in the same sentence. Its something that most Linux users just never think about; but recently, rebooting Linux was the topic of conversation between myself, and a coworker with a Windows background.

"Why are we using Linux as a server?", she asked. This is a very good question that is likely to evoke a myriad of different responses.

"I think that Linux is used because of it's modular nature. Updates, configuration changes, and other maintenance can be done to the server without needing to reboot it.", I stated. Restart or reboot the computer

"Well, when does it need to be rebooted?", asked my coworker. Wow! I never really thought about it like that before. When does it need to be rebooted? Of course, I knew from experience that Linux could run for months without requiring a restart ever since Professor James Caldwell of the University of Wyoming stated that his office computer reported over 100 days of uptime since the last reboot. But I never really thought about why Linux would require a reboot.

With Windows, it's fairly obvious. Rebooting a Windows box is done in all of the following situations, yet none of these situations require a Linux reboot:

1 - When updating or patching the operating system.
2 - When installing new software of any kind.
3 - When it locks up or slows down.
4 - As the first step in any troubleshooting procedure.
5 - As a secondary, tertiary, intermediary, or final step in any troubleshooting procedure.
6 - Automatically, when you're not looking.
7 - As a troubleshooting step.
8 - When an application conflicts with the system.
9 - As a troubleshooting step.
10 - As a trou...

Anyway, I've had the opportunity to install some software on the servers at work, and not once have I had to reboot the server. Not once has the server locked up, acted sluggish, or thrown the blue screen of death. I've heard our IT department speak of worms on Windows Servers, but laughter ensues when someone asks what kind of virus software is installed on the Linux servers.

The conversation between my coworker and I continued: "When do we need to reboot a server?", she asked.Restart or reboot computer

"That's a good question. I'm not sure. I don't think it matters. But you've made me curious... Let's see how long it's been since svrXX was rebooted...". So at the SSH terminal, I type 'uptime' at the prompt, "162 days!", I exclaim.

"It has to be rebooted in 162 days?", she asks. Having primarily a Windows background, the concept of not having to reboot is a bit perplexing to her.

"No, that is how long it has been since it was last rebooted!", I explain. I try running 'uptime' on another server, "Check out this one, 315 days! This server was last rebooted almost a year ago! Now, there's no uptime command for Windows --", probably because hours are easier to remember than months, "but if you could type uptime at the prompt it would probably tell you that it had been running for only a few days."

"Oh! Can I try uptime?", she asks.

Another coworker overhears our conversation, "Actually,", he begins, "there is indeed a command you can use to view statistics from the DOS prompt. Type 'net statistics server'."

Upon discovering this information, my curious coworker types the command in her DOS window. "My computer has been running for eight(8) hours!", she said. "I just turned it on this morning."

I looked at my screen. "Mine shows a whopping six(6) days!", and it definitely showed. The PC was running slow. Clicking on an icon resulted in a delayed reaction, kind of like in cartoons where the character gets his foot stepped on and it takes a few minutes for the signal to reach his brain. There were 46 Firefox tabs open, 2 VMWare images running, a few Notepad windows, collaboration software, a database manager, a couple folders, and several Putty windows along with a mess of other open programs.

Like an old muscle car, I was pushing this thing to it's limit and it was still driving forward. It was definitely being taxed, so no wonder I have problems with my computers, but I wonder if I would have the same problems with Ubuntu or SUSE installed on my workstation PC? With SUSE or Ubuntu, I could "rip the process out of the wall" using 'kill -9', as another co-worker would say; but with Windows, eventually you come to a point where you have to just kill the motor and restart.

But why risk any downtime if you don't need to?

P.S. In all fairness to Windows, I did take note of the fact that Ubuntu 6.0.6 did require a restart after some updates. I was unpleasantly surprised by this and am not quite sure what to make of it. Of course, I think Ubuntu was designed more for home desktop users rather than for use as a server. More research will be needed in order to determine if Ubuntu Server suffers from this same requirement.

Saturday, October 27, 2007

Using VMWare as a Cross-Platform Virtualization Platform

As part of my Microsoft Windows XP Quit Date strategy, I have been looking into using VMWare as a replacement technology for my Microsoft Virtual PC images.

I started using Virtual PC as a replacement for my dual-boot setup. I still have a dual-boot (actually a tri-boot setup), but I rarely, if ever, use it. The problem is that everything that I do need is on my Windows XP, NTFS-formatted, C: drive. NTFS-formatted drives are not writable from Linux, so when I boot into SUSE or Ubuntu, I feel like I can't update the files that I need to update or use software that I need to use.

As a result, I set up a SUSE 10.1 Virtual PC image. I don't use the GUI. Although GNOME looks awesome when I boot directly into SUSE or Ubuntu instead of Windows, the GUI is somewhat restrictive in Virtual PC. Instead of 1280x1024 screen resolutions, I'm limited to 1024x768.

Since starting my new job back in February, I've become extremely comfortable working from a Linux command prompt. In fact, I'm so comfortable at the command prompt that I feel lost when I try to do something using the GUI. Come to think of it, I don't even think we have the GUIs installed on our servers at work!

The main advantage that this gives me is a powerful development environment. I run Apache on the Virtual PC image, and I use this configuration to locally host development environments for websites that I am working on.

The NavCalendar Application

For example, I'm working on a Calendar application for Edúcate Ya. I'm building it in PHP. I chose PHP because their website is already built using PHP, and by using this technology I can get this application to market quicker than I would using some other technology. I host the development environment at locally on my Virtual PC image, and I created an entry in my Windows host file that maps the local IP address of the Virtual PC image to that host name. (The host file is located at C:\WINDOWS\system32\drivers\etc, and if this is the first time opening the file, one entry will be present by default. The default entry maps the host name "localhost" to the loop back IP address

I configured Apache using Virtual Hosting. I created a configuration file mapping the IP address of the VMImage and port 80 to the hostname After restarting Apache in Linux, and flushing the Windows DNS cache by running "ifconfig /flushdns", I was able to view the development version of the website on my local network.

In addition, this configuration gives me the ability to view the website on any computer on my network as long as the host file is mapped with the IP address and host name. This means the Virtual PC image could run on a server instead of my local PC, which would free up some memory used by the Virtual PC image!

Migrating to another Operating System

I've strayed from my point. I have, however, provided some insight into how I use virtualization technology and why it would interfere with my productivity should I lose the ability to boot my SUSE image. Virtual PC only runs on Windows. It can run many operating systems. I've successfully run Windows 3.1, Windows XP Home, Windows XP Pro, Windows Server 2003, Ubuntu 6.0.6, SUSE 10.1, several Knoppix versions, and FreeDOS. Currently, I only depend on the SUSE image although I have used the other operating systems as test platforms on several occasions.

As I mentioned, Virtual PC can run several operating systems, but it can only run on Windows 2000, XP, and Vista. Since I want to move toward software that runs on multiple platforms, I've been looking at VMWare. I use VMWare Player at work to run a Linux environment on a Windows XP machine in much the same manner as I do at home, and it works great! One of my coworkers also ran a Linux VMWare image on his Ubuntu desktop. Therefore, I know firsthand that it's cross-compatible with both Windows and Linux, and I know how the software works.

But what I recently discovered this-morning was something that is quite common in many open source software packages. VMWare offers users the ability to convert Virtual PC images to VMWare images! This is awesome! I don't have to go through the time-consuming process of reinstalling SUSE 10.1 on a VMImage and configuring it the way I want! Using the VMWare Converter, Virtual PC users can convert an image to VMware format!

After getting more hard drive space, this will be the next step in preparing to quit using Microsoft Windows XP.

Running dual-boot setups concurrently

While writing this piece, I stumbled upon an article that describes how to Run an Existing Windows Installation on Ubuntu with VMware Player. The author does not describe why these steps work, but he does outline the steps required to configure VMWare Player and the Windows installation. Personally, I wouldn't try these steps on a production machine, as having a third-party tool control Windows is not supported by Microsoft. Of course, neither are dual-boot setups, but I've never had an issue with dual-boot setups. Also, with a dual-boot setup, the operating system is not controlled by a third-party process. However, by following these instructions, you'll be allowing a third-party tool to control the environment that Windows runs in.

The bottom line is that VMWare Player can run a non-virtual installation of Windows, according to the article. I'm not going to try this myself as I don't have a spare PC available, but if anyone has tried this I would love to hear your experiences!

In summary, I've included a list of cross-compatible open source software that I currently use:

Soon, I'll add VMWare to the list.

UPDATE - 7/5/2008: I have configured VMware Player on Ubuntu 8.04 to share a Windows XP VMWare image with Windows XP Pro as an enhancement to a dual-boot setup. Read more about it! It's easy to setup and configure, and you'll be glad you did!

Sunday, October 21, 2007

PHP Navigational Calendar

I'm working on a project for Edúcate Ya that involves placing a calendar on the home page. The idea is that the calendar will be used to display any public events, classes, guided trips, fund raiser events, and anything else of importance that an organization may want to advertise on a web page.

NavCalendar Application - Navigational Calendar

Each event listed on the calendar would be a hyper link to another page on the website that provides more details about the event. I ran a few Google searches to see if I could find something that would fit. There are of course plenty of HTML, JavaScript, and many other types of Calendars to choose from. However, everything I found either was way more than what I was looking for, cost money, or did not have the navigational feature I was looking for.

Many of the calendars were similar to a web-based Microsoft Outlook, which an organization could use to help employees manage group schedules. Not only did these calendars have way too many features, but also they weren't the features we were looking for.

So, I decided to build a Calendar using PHP. I chose PHP because the Edúcate Ya website was built with PHP, so the server is already configured to use PHP. I started working on this towards the end of August. Yesterday, I was able to generate -- using PHP -- a calendar with a list of events that were pulled from an XML data file.

I chose XML because the list of events for Edúcate Ya is small. However, my plan is to retrofit the application with an abstract class that will allow developers to add different data sources, such as a database. I also designed the system so that a front-end controller loads a "view" based on a parameter passed when calling the controller. Anyone who wishes to use this application could simply replace the view with their own by using the API.

The back end functionality is somewhat in place. The implementation doesn't yet fit the architecture, but I wanted to get this to market for Edúcate Ya as soon as possible. So, as many software development projects go, I took some shortcuts. The abstract class representing the data sources is still visible only on paper, and the APIs required to build the view are somewhat tightly coupled. It's not perfect, but it works for me right now.

The actual HTML and CSS need some major overhauling. That is the next step in this process. However, my hope is that the Navigational Calendar may turn out to be useful to others who wish to have a Navigational Calendar on their website. In order to realize this goal, the final step will involve making it easier to build a view. Currently, a developer would have to first build a static HTML calendar, and then integrate it with the HTML-generating PHP code so that the correct month is displayed with the correct data. This also means that I will need to throughly document everything, which is something that I haven't done much of outside of my full-time employment.

I plan to use the open source cross-platform software Gimp to apply the "chrome" for the calendar.

Tuesday, October 16, 2007

The Gmail Dependency

I knew it was going to happen one day, I just wasn't sure exactly when. I knew one day the script would suddenly stop working. Not because code rusts. Or because the code cracked like glass, but because the foundation that it depends on cracked.

Well, it didn't really crack. It's more like what happens when a house settles. It's just digging itself in. Gmail was digging itself in. The developers added a new parameter to the URL that opens the HTML Compose editor. ui=1. If they added it to the end of the URL, it wouldn't have made a difference. But regular expressions care about where certain things are placed. Order doesn't matter in a URL parameter list, so Google developers could put this parameter wherever they wanted.

However, the script stopped working. The regular expression logic asks if the URL matches a specific "include" pattern. For most URLs, nothing happens, the script does nothing. There's no need to use processor power unnecessarily if there is no Gmail HTML content window to paste HTML into. Plus, users may get annoyed if the HTML popped up somewhere unwelcome.

If the URL were to match the pattern, then the code is executed. The HTML is read from an XML data file, as is the Greasemonkey Script. At a specified location in the script, JavaScript variables are generated, which contain the HTML retrieved from the XML file. This re factored JavaScript is then evaluated and dynamically inserted into the HTML content window of Gmail, using a compiled Greasemonkey engine.

An asterisk is all it takes. One small character, just 2 bytes of data, is enough to break functionality.

HTML Multiple Reply Signatures for Gmail is dependent on the functionality of Google's Gmail interface. The URL change was an easy fix, but should Google decide to perform a major overhaul of the Gmail interface, the HTML Multiple reply Signatures for Gmail scripts and Firefox Extension would reach the end of their useful lives. Better Gmail, and many other Firefox extensions built around Gmail's interface, such as Gspace, may also be rendered useless.

Manage Email Signatures in HTML Multiple Reply Signatures For Gmail
- Click the "Edit" button.

HTML Multiple Reply Signatures for Gmail

- Add the asterisk where indicated by the highlighting.

For all of the do-it-yourselfers, I highlighted the area where I had to make the change. If you're using one of the Greasemonkey scripts, the Firefox Extension, or another type of HTML Signature injector script that recently broke, you can fix it by making sure that highlighted asterisk is added to the included URL or regular expression. That's right! Even if you're using another Gmail HTML injector script other than one that I created, you can fix it yourself by editing the include URL list and correcting any errors!

Of course, if you find that you would rather get a new, updated copy, all of the links in the menu on this website reflect the updated URL changes. Since installing or reinstalling the scripts should fix the problem, you could just download a new copy and reinstall it.

Thursday, October 11, 2007

Nested-Nested Quotes

Larry Wakeman of Memory Pharmaceuticals recently sent me a reminder about a follow-up article that I forgot to write. Back in April, I addressed the concept of quotes within quotes within quotes and how to handle this phenomenon.

Any programmer who has ever had to write Greasemonkey scripts, as well as to perform any type of server-side or client-side programming has or will encounter this particular problem. For example, a JavaScript function that generates HTML that contains attributes that refer to JavaScript functions that take strings as parameters, will require some cleverness on the part of the developer, especially if the parameter passed into the JavaScript function is determined at the time the HTML is generated:

         <script type="text/javascript">

    function alertParameter(stringParameter) {

    var topLevel = "test";

    function generateHTML(topLevel) {
         document.write("<a href=\"#\" onclick=\"alertParameter('"+topLevel+"')\">Click this link to see the result</a>");



Here is a breakdown of the above process: The text "document.write" is what I refer to as top level. This is the actual command that outputs the string of text included within the outer quotes. The outer quotes are the quotes that wrap the text inside the parenthesis of the document.write method.

document.write(" /* These quotes are the outer quotes */ ");

Note that there are two types of quotes: Single quotes and double quotes. We can use either to represent the outer quotes. For this example, I chose double quotes. The first set of inner quotes, like the outer quotes, can also be double or single quotes. However, if the inner quote is the same as the outer quote, then the inner quote must be escaped. Consider the following example:

Nested JavaScript Quotes Example 1

document.write("<div onclick=\"alert('ht')\">click me</div>");

The above example is the same as the following example:

Nested JavaScript Quotes Example 2

document.write("<div onclick='alert(\"ht\")'>click me</div>");

Also, to demonstrate that we can use single-quotes as the outer quotes, check out this example:

Nested JavaScript Quotes Example 3

document.write('<div onclick="alert(\'ht\')">click me<div>');

Take a careful look at the above three JavaScript nested quote examples. Understanding this concept is a prerequisite to understanding deeper JavaScript nested quotes.

As I mentioned, the outer quote can be either a double or single quote, and the first inner quote can be either a double or a single quote independent of the choice made for the outer quote. In Example 1, I used double quotes for both the outer and inner quote, whereas in Examples 2 and 3 I alternated between single and double quotes. For convenience, here is Example 1 again:

Nested JavaScript Quotes Example 1

document.write("<div onclick=\"alert('ht')\">click me</div>");

It may seem confusing at first as to how this is possible, until you see the output in the browser source (of the generated HTML, that is. I'll go into more detail on this later):

<div onclick="alert('hi')">click me</div>

The outer quotes don't appear in the generated HTML. Those were top level quotes. They served only to wrap what was being generated. As you can see, the escaped double-quotes render as actual quotes, and cause absolutely no conflict.

Nested JavaScript Quotes Example 4

document.write('<div onclick="alert(\'ht\')">click me</div>');

Example 4 produces the same output! Except in example 4 it is the single quotes that must be escaped, as this time single quotes represent the outer quotes.

JavaScript Inner, inner quotes

By this point, it should be quite apparent that there are several combinations of outer and inner quotes that can be combined without causing a non-terminated string literal error. However, after choosing an outer and an inner quote, choices become much more limited. Instead, from this point forward, nested quotes must alternate between single and double quotes. Below is an example:

         <script type="text/javascript">

    function alertParameter(stringParameter) {

    var topLevel = "test";

    function generateHTML(topLevel) {
         document.write("<a href=\"#\" onclick=\"alertParameter('Say \\'Hello World\\'')\">Click this link to see the result</a>");



You may have noticed that the previous paragraph contains a sentence with strikethrough styling. After trying the example I was going to try, I realized that the rule that the quotes must alternate is not necessarily true. I'll explain, but first, here is the output when clicking the link:

Say 'Hello World'

Definition of literal quote: This is a quote that represents a quote as text in a string. A quote that marks the beginning or end of a string is a non-literal quote, and it is not part of the actual text. A non-literal quote can be represented as a literal quote by escaping it with a backslash (\) character.

Since the outer quote is a double quote, the inner quotes are literal quotes in the string. If the outer quotes were single quotes, then double quotes would be literal. As a result, I can place as may single quotes in a row as I want without affecting the String. However, this will affect not what occurs with the output, but what occurs with the output of the output:

(" ... onclick=\"alertParameter('Say \\'Hello World\\'')\"> ... ")

Outer quote = " (This marks the beginning and end of the string)
Inner quote = \" (Escaped as to not flag "beginning/end of string")
Third-tier quote = ' (Literal quote)
Fourth-tier quote = \\' (Literal quote that will be generated as an escaped outer quote)

This is what really makes this JavaScript nesting quote process complicated. As I mentioned, the single quote is a literal quote. This means the string treats it as a normal character. However, in the HTML -- in the output that is -- the single quote becomes an outer quote. The single quotes around 'Hello World' are literal quotes in the JavaScript code, but in the HTML, these single quotes are inner quotes that must be escaped. However, using a single \' would simply result in a '. So the trick is to escape the slash. Thus, a document.write("\\'"); would produce a \' in the HTML, and this would be resolved to a ' if processed again.

Essentially, you must take two things into consideration when dealing with escaping a quote in JavaScript. If it needs to be escaped in the inner string, then you must think one level deep. It helps to move backwards. Write your desired output first, and then go through and "wrap it" with the tools that would generate it:

<script type="text/javascript">document.write("<a href=\"#\" onclick=\"alert('Say \\'Hello World\\'');\">click here</a>");</script>

I want to dynamically generate this embedded JavaScript from the server with PHP. So I'll first verify that this works in between the body HTML tags of a PHP document. It does indeed work. Next, I'll wrap it with a PHP echo statement:

<? echo "<script type=\"text/javascript\">document.write(\"<a href=\\\"#\\\" onclick=\\\"alert('Say \\\\'Hello World\\\\'');\\\">click here</a> \");</script>'"; ?>

Escaping JavaScript quotes is recursive. After wrapping the PHP echo around the JavaScript with double quotes as outer quotes, I then had to escape the previous outer quotes. I then had to escape the inner-inner double quotes not once, but twice. Once to escape the backslash used to escape the quote, and once to escape the quote so that PHP wouldn't treat it as the end of the string. What I found most interesting is that the single quote used as the outer wrapper of the alert text was ignored during the PHP wrapping process because it is a literal quote. However, the innermost single quote had to have two backslashes added -- once to add another backslash and once to escape that backslash! Each time a wrapper is added, an escaped special character must be escaped again because during each iteration, a backslash escapes a backslash!

In summary, I'm not sure if this little exercise will be of any practical use. Perhaps it would be a good problem solving exercise during an employment interview to see how good a programmer is at dealing with complex layers of abstraction. Perhaps a situation will arise where one actually needs to generate different JavaScript functions based on different criteria. I can't think of any examples other than the Multiple HTML Reply Signatures Embedder for Gmail Greasemonkey script that I wrote, and sometimes I think that there may have been an easier way to generate a dynamic-drop down list in Gmail without having to nest quotes in JavaScript. Bottom line -- I'm not sure. However, if this has proved helpful, please share your story with me!

Sunday, October 7, 2007

Update for HTML Multiple Reply Signatures for Gmail

10/09/07 UPDATE: Due to a change made to the Gmail URL structure, the HTML Multiple Reply Signatures Extension suddenly stopped working. I've updated the URL to reflect the newest, working version.

There have been some problems with the Firefox Extension that can make inserting HTML signatures in Gmail somewhat of a hassle. However, in spite of these issues, people have been downloading and using it. To my surprise and pleasure, I've received quite a bit of positive feedback. For those of you who have given me feedback, thank you! In order to address some of the issues that you've had and to accommodate some requests I've received, I've updated the extension, which can be downloaded by clicking on the following link:

Multiple HTML Reply Signatures Extension 1.0.2

Multiple HTML Reply Signatures Extension

Multiple HTML Reply Signatures Extension

I've added multi-line functionality to the editor, so you won't have to type the HTML all on one line. In addition, this should make it much easier to paste HTML directly into the editor. This was causing the script to not function when HTML was pasted, since HTML is typically not written all on one line.

HTML Multiple Reply Signatures for Gmail Email Signature Editor

I also added an update notification to the new version. Firefox Extensions support update notifications through RDF, but since my hosting provider doesn't respond to RDF requests with "text/rdf" like an Apache server would, I was forced to create a hack that uses a regular expression to check the version number against my server. The cool thing about my custom version of update notifications is that the HTML Multiple Reply Signatures for Gmail extension will simply insert a "Click here to update" button in the tool bar.

HTML Multiple Reply Signatures for Gmail Updates

It's not the most elegant way to notify users of an update, but I absolutely hate popup windows. This tool bar button is very unobtrusive. An image or a logo would be cool, but that's not my specialty so for now, it's plain text.

I started looking into the issue of why quotes won't work in the extension. This is turning out to be a lot more complicated and will take a lot more time to resolve. The problem is that the quotes have been escaped so many times that I think the strings aren't being parsed correctly. For now, you must enter your attributes without quotes like I've done below:

<a href= style=color:orange>Blog</a>

Oh, I recently discovered that ampersand codes weren't supported. That has also been fixed. You can now use &nbsp; in your HTML, if needed.

I'll continue to fix bugs in this extension. The quotes are a big one, but not easily fixed. As always, if you have any problems, questions, concerns, or suggestions, please email me and I'll respond as quickly as I can.

Friday, October 5, 2007

Gedit and Open Source Text Editors

I found this article on the GNOME default text editor, Gedit to be quite interesting. I was impressed by the functionality that it provided when I used it in both SUSE and Ubuntu while I was working on a Firefox Extension.

The editor is actually more powerful than I gave it credit for. Micah Carrick, the author of the article, uses the editor as an Integrated Development Environment! Apparently, there are plugins that come with Gedit by default that allow you to customize and extend the functionality of the editor. In just a few short steps, you can import a file tree, connect to an FTP site, or instantly insert XHTML, CSS, PHP, and other code simply by clicking on items in a tag list!

Is tab completion something that you find helpful or perhaps necessary? There is a plug in for that as well. Apparently, there is also an embedded terminal that supports ssh connections. Although I'm happy with Putty in Windows or the default terminal in Linux, this could be useful if you prefer to integrate your tools into one application.


Although Gedit is open source, I'm disappointed that it isn't available for Windows. One thing that really makes an application stand out is cross-platform compatibility. I'm not just a proponent for open source software; I'm a supporter of open source software that runs on multiple platforms because it promotes freedom of choice. This cross-compatibility is part of my Microsoft Quit Date strategy.

In terms of text editors, I prefer Vi. Not only does it come standard with every single Linux distribution out there, but also it's available for Windows! I use it both at work and at home, and it makes editing code much easier when I'm away from a Linux terminal. The most beautiful thing about Vi is that if I'm sitting in front of an open Linux terminal, I can edit any text file, anywhere I want. If I'm editing a file located on a computer in India, I can do so. While the terminal does respond a little slower, quickly editing a file would be difficult using an Integrated Development Environment.

The main problem with using an IDE is that you have to configure it. It doesn't work right out of the box. While tools like Vi have a very steep learning curve, I can move from one computer to another and pick up working right where I left off with nothing more than a Linux terminal and a VPN connection.

Of course, the main thing I like about Vi is that I can do so many things without ever having to take my hands away from the keyboard.

Although I like Gedit, the fact remains that it's not available in Windows. Since declaring my quit date, I haven't started using any new cross-platform tools. However, I realize that in terms of text-editors, I've already started this process by using Vi.

Tuesday, October 2, 2007

The Microsoft Quit Date

I think I need to set a quit date. I've been talking about doing it for some time now. Eventually, the time for talk will be over, and it will be time for action.

As I previously mentioned, I may be in the market for another computer in the near future. This could happen anytime between now and 2009. I want to set up a server. That may involve setting up a Linux box. It could involve using this PC as the server, which means I'll put Linux on this PC and who knows what on the new computer.

I currently use Windows XP Professional. Overall, I don't mind using Windows XP. First, I'm familiar with it, so my opinion of it is somewhat biased. Second, I recall how often Windows Millennium would crash, and I realize that in comparison, Windows XP is far superior.

What concerns me is DRM. It's a joke. I've read the articles and the arguments and how there is one group of people who use "freedom" as their argument against DRM, and I've read arguments from those who use the word "ownership" in their arguments in support of DRM.

I agree with the point that those who make investments in a creative work with their time, energy, sweat, blood, and tears should be able to receive compensation for their efforts. However, Microsoft doesn't care about that. They may claim they do, but that's just marketing. The reason for "caring" so much is for consumer lock in. Microsoft is not performing a selfless act when they implement encryption algorithms that force us to use Windows Media Player. I can see right through that. DRM is merely a smoke screen -- a cover -- for a technical monopoly.

There are other ways to ensure consumer freedoms while also ensuring that consumers are free to use whatever media they choose. Microsoft hires some of the smartest people in the world. Why didn't they invent a method for ensuring that encrypted music could be played on a variety of platforms?

I'll save the details of what they could have done for a later post, for now, let's stick to the topic: The Quit Date.

Eventually, Microsoft will stop supporting Windows XP. At this time, I will have two choices. (1) Upgrade to Windows Vista, or (2) upgrade to a Linux distribution. Both choices will involve learning a new operating system, both will involve dealing with issues of backward compatibility, and both will involve some form of trade-off.

I think the best thing to do to prepare for a Microsoft Windows XP quit date is to migrate to software that will run on all three operating systems. This will ensure that, when the time comes to make the decision, I will be able to make a decision that won't be based on the difficulty of switching from one operating system to another. I'll have the freedom to choose Linux, stick with XP, or if I happen to go temporarily insane -- I can choose Vista! Of course, I've heard a lot of positive remarks about the Mac book Pro, so I just might go that direction as well.

Below are just some of the things we can do to prepare for the time when this decision must be made:

- Use Firefox

Firefox is compatible with Linux, Windows, and the Mac. So any tools I've become comfortable with will be available no matter what operating system I use.

- Use OpenOffice

OpenOffice is not as good as the newest version of Microsoft Office 2007, but there is a trade off. Using MS Office, you effectively lock yourself in to their technology. If you can get by using OpenOffice, I would highly recommend it, as it works on Macs, Windows machines, and Linux.

- Use Mozilla Thunderbird

Currently, I still use Microsoft Outlook. Why? Because I used it in college with the Microsoft Exchange server that their IT department installed. I was "locked-in". Unlocking myself will involve moving all data in Outlook to another client. But with
some advance notice, I think I can move this data to Thunderbird by my quit date. Why use Thunderbird, you ask? Same reason I'm using Firefox. Cross-platform compatibility!

I could keep adding items to the list, but I'm not. Instead of being exhaustive, I'll reduce the list to two items that summarize simplifying the migration process:

- Use software that is compatible with multiple operating systems.
- Buy hardware that works on both Linux and Windows

With a desktop PC, I think this is an easier feat. I've never had problems with Ethernet and Linux; however, I have never been able to connect to my network through a wireless network card using Linux. I haven't tried in about 8 months so perhaps this isn't a problem anymore, but I'm sure there are other types of hardware the Linux community has not yet been able to reverse-engineer in order to develop a driver.

I'm thinking I'll give myself six months to switch everything over and become less dependent on my current operating system. So, by the first day of Spring, I'll be able to make my decision.

Sunday, September 23, 2007

Hardware Upgrades

In October, I will have owned my Dell Dimension 3000 for 2 years, and according to Moore's Law, it's time for me to update my hardware.

The Dell Dimension 3000 comes with a 3.0GHz hyper-threading processor. From what I understand, this is not a true multiprocessor system, but somehow it mimics a multiprocessor PC. From an environmental standpoint, this PC is the equivalent of a gas-guzzling SUV, so I try not to leave it on all the time. The computer is fast. With a 3.0GHz processor and 1 GB of RAM, I've had very little issues with this computer.

last time I researched upgrade costs, I calculated that it would cost about $240 to replace the two 512MB DIMM chips with two 1024MB DIMM chips. This would give me 2 full gigabytes of memory for all of my applications and -- based on previous experience -- would probably extend the usefulness of the PC for another one-and-a-half to two years.

The hard drive that came with this PC is a 150GB 7200 RPM internal unit, and it is filled to capacity. But that's okay. Storage is cheap. Besides, that's not what concerns me. I'll simply buy a 320 GB external hard drive for 38 cents per gigabyte.

What concerns me is something about the PC that didn't concern me two years ago. Now, I'm not a gamer, and I'm still not; therefore, I saw absolutely no need to spend money on a PC with an AGP (advanced graphics port) expansion bay. However, video cards are used for more than just gaming, as I'm now discovering.

A few weeks ago, my monitor lost the color red. The monitor is an old Gateway that I found sitting in the "free pile" in my apartment building. Since the Dell didn't come with a monitor, this solved quite a few problems back in the day. Because the red died, I want to invest in either a wide screen flat panel or two smaller flat screens.

I would prefer two monitors. Two monitors really help make me faster. I can drag an open putty window onto one monitor, maximize it, and watch it expand to fit neatly inside of only one screen. While looking at a log file on one screen, I can test an application in another screen, using a maximized Firefox browser that only fills the one screen and doesn't hide the contents of the other.

The Dell Dimension 3000 doesn't have an AGP slot. While there are graphics cards available that offer dual-monitor support and that fit into PCI slots, I've read that performance can suffer using PCI. It seems to me that between AGP and the newer PCI express, a PCI graphics card would become outdated in a very short time. Therefore, it may be best for me to invest in a flat panel monitor that is compatible with my current PC.

When I purchase my next PC, I'm going to make sure it will have support for dual-monitors. However, the question I struggle with now is this: Do I upgrade the memory and monitor on the Dell, or do I purchase another PC that can handle dual-monitors?

Friday, July 13, 2007

Friday the 13th

Well, my karma is good.

Friday morning I wrote down the directions to the courthouse from Google Maps. I headed out the door at about 8:15, worried that I would miss the 9am start time and be held in contempt of court.

I saw a huge line outside the Multnomah County Courthouse, so I parked in a garage a few blocks away and stood at the back of the line, which by now was wrapping around the side of the building.

There were all kinds of people in line, and I suspected that jurors would come from all walks of life. But just to be sure I was in the right place, I asked the guy behind me if this was indeed the correct line. "This is the line just to get in the place", he responded.

Wow, so this line included jurors, witnesses, defendants, plaintiffs, reckless drivers, embezzlers, and possibly lawyers and undercover police officers.

Multnomah County Courthouse in the Fall 2006
SW Portland near the Multnomah County Courthouse - Fall 2006
I looked around. I knew exactly where I was. I rode my brother's scooter down here one Sunday last fall. There is a small park right out front of the courthouse with tall trees and park benches. Perhaps one of the best photographs I had ever taken was taken at the end of the block.

Just then, an officer split the line into two, starting just three people ahead of me. The officer said something inaudible to the woman and she started walking. He directed us to follow her. She led us to another entrance that reminded me of airport security.

"Sir, you must step back through, take your belt off, and place it on the conveyor belt", I take off my belt and walk through. The alarm buzzes again. "Hold your arms straight out."

I make it through security and am not surprised to see what looked like a Starbucks in the lobby! These Portlanders really like their coffee! I skip the coffee and head to Jury Room 130, where there is another line with about five people in it. They are waiting to talk to an older woman who is sitting in front of a computer and processing potential jurors. She hands the guy in front of me a badge. He looks tired. So does the woman behind me. Neither one of them wants to be here, so perhaps I felt a little guilty when the old woman at the desk told me I had been excused!

Apparently, my employer sent a letter on my behalf requesting that I be excused! The pen is truly mightier than the sword. I left the courthouse, paid for parking, and headed to work just in time for our morning coffee run, which happened to include our CEO, who has never attended a coffee run, who bought everyone's coffee and bagels, who we were able to talk to outside the walls of the office!

They say Friday the 13th is a bad day? What’s the deal with that! I don't necessarily believe that hocus pocus, but I do think that it is a day of power. It is whatever you make of it. For me, it may have saved me thousands of dollars in late fees and missed work.

Sunday, July 8, 2007

Good Code is Like Glass

I've been thinking recently about what qualities an employer wants to see in a potential software developer. Although there are plenty of other resources that have addressed this topic, I want to add my two cents.

In a previous article, I talked about how important honesty was in marketing a product to consumers. I also believe that honesty is important in all aspects of life, including selling your technical skills to an employer.

Nobody is perfect, of course. I'm not suggesting that you must represent the pinnacle of perfection. It is true that employers are interested in what knowledge you have regarding technologies they use, but more importantly, they are interested in your willingness to learn new technologies.

Software development is not a field where you learn the ropes and then that's it, you're done learning. Instead, it is a continual, never-ending process, and if you can demonstrate to an employer that you understand this concept and that you embrace it, then you've increased your chances of being hired.

Here is a list of some of the techniques an employer will use to try to rate you as a potential employee:

Evaluate Technical Aptitude Using Puzzles

As software developers, employers know that we love to program. Employers assume that we will try our best on some interesting feature of a new product, but the fact is that there are some tasks that may not be the most interesting to us. I believe this is where the puzzles enter the picture. An employer will use these to try to determine not only your thought process in solving a problem, but they will also be able to gauge how much effort you put into your attempt to solve the problem.

In my interview, I was very nervous, so I drew pictures and talked out loud to myself. This helped me relay to the interviewer my thought process as well. The best thing you can do is keep trying. You don't necessarily have to solve the puzzle, but you definitely want to attack the problem like your job depends on it. Because it does!

Evaluate Skills Based on Technical Questions

I'm not going to cite statistics on how much money an employer will lose by hiring inept technical people. Instead, I'm going to tell you that it is very frustrating to work with people who don't know what they're doing. I'm sure everyone has had an experience in college or in another group situation where one group member wasn't able to produce. This is where it becomes really important to be honest.

I know firsthand that there are employers who value honesty, and these employers make hiring decisions based on this honesty. In my interview, I was asked to rate my skills in Java on a scale of 1 to 10. I rated myself as a 3. I didn't rate my skills as a 1 because I had done some programming in Java, and I didn't rate it as a 4 or 5 because I had no formal training in Java. I was a C++ programmer. But I believe what made the difference for me was that I was able to demonstrate that I knew there were differences, I knew that I had a lot to learn -- especially since I never took a Java course. I made this very clear in my interview.

To prepare for the Java questions, I read online Java tutorials that specifically focused on interview questions. An employer will think very highly of you if you say you don't know much about something and then confidently nail almost all of his or her questions. Contrast this approach with that of the candidate who claims to be an expert in the field but then can't answer any of the questions. People who think they know something but don't usually end up breaking things whereas the person who is more humble will likely proceed with extreme caution when tinkering with their delicate systems.

Good Code is like a Glass Fish BowlSomeone once said that code doesn't rust. I believe this is true. Good code can last forever, but good code is like glass; it can shatter into a million pieces if clumsy and inept programmers are allowed to handle it. Sure, version control software does exist, but is it really possible to rollback changes submitted by one bad developer on a project that involves multiple developers without losing the changes submitted by the other developers? I'm not that knowledgeable on how CVS rollbacks work, but even if it were possible to "uncommit" changes by one developer, there is a good chance that some of the code written by the good developers would break due to dependencies on the code written by the bad developer.

In addition to Java, interviewers will probably ask about HTML, CSS, and JavaScript. Since most applications are served in a Web browser, employers will be interested to know how knowledgeable you are on these topics. Again, be honest! An employer would rather hire someone who openly admits to not having a full understanding of HTML rather than someone who claims to be an expert but who has "divitis" or "tableitis". Unless you are being hired as a front-end designer, you can probably get away with not being a master of these topics, but claiming you know something you don't will only destroy your credibility.

Appearance in a Technical Job Interview

I was surprised to hear just how many people go to interviews without wearing a suit. Many candidates choose to not wear one, but I felt it would help differentiate me from other candidates. I was right, at least for myself. Although wearing a suit may not necessarily be the best approach for every candidate, you should definitely put some thought into looking your best and wearing something that will make you feel and look confident and competent.

Saturday, June 30, 2007

The Seven Virtues of Marketing

I am not merely a student of Computer Science. I also studied Business Administration for two years, and this curriculum included a few courses in Marketing. I took classes that approached Marketing in the context of the global environment, and I took classes that briefly introduced Marketing, along with Management, Accounting, Finance, and Human Resource Management.

Marketing the University of Wyoming CampusThe Introduction to Marketing class focused on Marketing only. In this course, I learned the Four P's of Marketing: Price, Product, Place, and Promotion. I also learned the difference between target marketing and mass marketing. To put it somewhat bluntly, mass marketing equates to quantity while target marketing equates to quality. Target marketing involves thought while mass marketing involves lack of thought.

The class also introduced the concepts of brand awareness and brand loyalty. Brand loyalty was earned. If you're product has loyal customers then you know that you have a superior product. Creating brand loyalty involves honesty and commitment to the customer. You can't have brand loyalty without brand awareness, but brand awareness alone won't create brand loyalty. Consumers may be aware of your product, but they may also think it sucks. The only thing they may be loyal about is not purchasing your product, or perhaps they may help you create awareness that your brand sucks by telling ten people they know that they had a bad experience with your product instead of telling three that they loved it.

Now, brand awareness can create brand loyalty, but it can also stagnate your product's growth, so you shouldn't focus on awareness alone. Creating brand loyalty involves patience, creativity, honesty, hard-work, selflessness, commitment to the customer, and strategic business planning. If you forget or neglect one of these components, you may not be able to create the brand loyalty that you are looking for.

Why be patient? Well, chances are you may be worrying about your bottom-line. My advice is this: Don't. Why, you ask? Because if you worry about your bottom-line you will neglect patience. You will rush your design and production departments into creating a sub-optimal product. This leads to a severe lack of committment to the customer, which is selfish on your part because you're worried more about your bottom line than your customer's satisfaction. You and your team can work 12 to 15 hour days, only to end up sitting in a meeting with your boss trying to explain why the numbers aren't as high as what was originally projected.

Creativity and honesty are like patience, selflessness, and committment to the customer in that they are directly proportional. If you are creative, you can market your product with honesty. If you are honest, you will need to find a creative solution to market your product successfully. If you're marketing department isn't utilizing their full creative potential, you will probably notice that some shady shortcuts are being made. Don't lie to your customers, you'll lose. Unless, of course, your customers are morons. But even if they are morons, don't be shady, it's just not cool.

Besides, it might be you that's the moron. I laugh every time I see the commercials advertising male enhancement: "If this was a gimmick, could we afford to do this?". Hahaha. I don't want to know that answer now, I want to know that answer in ten years, long after a chapter 11 bankruptcy, and long after the marketing team decided to start careers in building maintenance because they didn't like their fresh-out-of-college-with-a-marketing-degree jobs with Extenze. Don't get me wrong, there's nothing wrong with building maintenance, you can learn a lot about home repair, construction, and many other interesting and marketable -- no pun intended -- fields. I've talked to many people who found happiness and success in building maintenance or construction who earned degrees but just didn't like their fields. My point though is that absolutely no creativity went into marketing the product, and that makes me question how much honesty there is behind the product, and how much these so-called marketers actually learned from their marketing classes.

Basically, if you use trickery to manipulate your customers, chances are they -- like me -- won't trust you. So you must be ethical in your quest to create brand loyalty. "Don't be evil", as Google would say.

Photo of Leaves in the GrassAlthough I've mentioned honesty above, I feel that I need to mention it again because I feel it is very important. Now, honesty directly correlates with commitment to the customer, patience, hard-work, strategic planning, and selflessness. It is perhaps the most important of The Seven Virtues of Marketing. You can be as honest as you want with your customers and still fall flat on your face. At least you can sleep at night though. But, if you're product is subordinate, you're honesty won't sell your product. Now, this doesn't mean that you should be dishonest. No, because as I've mentioned previously, neglecting honesty wlll directly challenge and insult the intelligence of your customers. But if you plan, work hard, be creative, and commit to the customer's satisfaction, then it will be easy to be honest. Your product will practically sell itself. You're customers will ask your sales team questions, and they will give honest answers. You're customers will exclaim "Wow! You mean, if I am not satisfied with Copilot, you'll refund my $5 dollars! Just like that!". Not only will you and your staff feel good about yourselves; but also, your customers will feel good about you as well! They wouldn't think of asking for their money back. In fact, they will probably bring more business to your doorstep.

These traits, patience, hard-work, honesty, creativity, proper planning, customer committment, and selflessness are important in all aspects of life, including business. Apply this mission statement, methodology, ranting, mode of living, or whatever you want to call it, to your business, your life, and you will create not just brand awareness, but brand loyalty!

Saturday, June 23, 2007

Reasonable Accommodations

What would you do if you suddenly became deaf or blind? If you were to become the victim of either one of these unfortunate events, what would you do? How would you manage?

Abstract Photo Blurred image of swingNever mind the fact that many of your hobbies would be affected -- that your quality of life would suffer. How would your life be affected in financial terms? Suppose that you were struggling to pay off student loans and a mortgage, and your job paid you well enough to just barely keep up with these expenses. Would you be able to find an employer who would be understanding about your newfound disability and yet still pay you enough to maintain your standard of living? How about your current employer? Would you still be able to work?

Yes, there is health and disability insurance, but will the benefits that you receive from those plans be enough to last you the rest of your life? The answer -- unfortunately -- is that these benefits will most likely either expire after a specified amount of time, or they will simply not be enough to cover your daily living expenses.

Now, this isn't a sales pitch. I know absolutely nothing about insurance and have spent a minuscule amount of time studying the topic, but I do wonder how I would live and get by if I were to lose me sensory abilities.

Adapting to a disability

A few years ago, I had the opportunity to work with a person who is deaf. I was the manager of a series of summer camp stores, and Shawn was a clerk. One of the stores staffed four clerks. There were two cash registers, a crafts station, and a candy and ice cream station that required staffing. At first, I wasn't sure exactly where to place my deaf staff member.

Royal Alpha 580 Cash Register used by Deaf EmployeeI trained all of the clerks on the cash registers, which were Royal Alpha 580 programmable cash registers. I didn't plan on training Shawn on this aspect of the store simply because I did not think that he would be able to handle interacting with customers. The lines in the store would sometimes be so long that they would extend past the entrance, and I worried that he would have problems in terms of communication.

When the time came to conduct the training, I could clearly see that Shawn wanted in on the action. Against what I thought was my better judgment, I took some time to train him on the different aspects of the cash register. Since I did not know sign language, I wrote instructions down in a notepad that Shawn brought with him that he used so that he could communicate with the hearing world. I explained that the "Cash" button was to be used when the customer paid a transaction with cash and I emphasized -- as I did with all my clerks -- that the "Credit Card" button should be used for credit cards. Most transactions that came through the store were cash transactions, and it was very easy to get into the mindset of thinking of the big "Cash" button as the "I want to open the cash register now" button.

I put the cash register in "training mode", which meant that any transactions that my trainees entered into the register would not be recorded on the X or Z daily reports. I then proceeded to grab random items in the store for my trainees to ring up. Some clerks required a little more attention than others, and I think Shawn fell right in the middle. Since he was the last trainee, and since he had observed the other clerks during their training, he caught on very quickly.

I was amazed when I walked into the store on the busiest days and saw Shawn working on the main register. We would typically only open register number two when we got very busy. Shawn had everything under control. He even opened the store one evening and worked the first hour all by himself! The store was busy, everything was perfectly under control, and Shawn was calm as the eye of a hurricane.

The reason that Shawn was so calm is that -- being born deaf -- he had long ago adapted to what the hearing world views as a disability. It wasn't him who had a problem with being deaf.

No! It was us, the hearing world, who had the problem, who had to adapt. While it is true that we had to overcome his lack of auditory perception, he didn't meet us halfway. He met us about three-quarters of the way while we only met him one-quarter of the way. All of his tricks -- the notepad he carried, writing "I'm deaf" on his nametag, turning the display on the register so he could communicate the total amount due, without words, to his customers -- were designed to help others minimize the amount of adapting that they would have to do. His demands were small in terms of needing reasonable accommodations, in fact, none were necessary.

Adapting to our own limitations

Photo of Moonrise over waterI often wonder if I would be able to adapt if I were to become blind or deaf. As a systems programmer, I rely heavily on my ability to view and interpret text on a computer screen. Should this ability be compromised, I wonder what would happen.

But then I think about things that I've done to adapt as a programmer, just by using the senses that I do have. There is a small percentage of people in the world who have an eidetic memory. When you have this fascinating ability to remember everything that you're exposed to, you don't have to learn mnemonic devices or practice techniques for organizing large amounts of information. You probably wouldn't understand what it is like to have an average mental capacity, unless you're Orlando Serrell. Since I don't have an eidetic memory, I have to use diagrams and pictures when designing an application. In order to limit the number of distractions when I am programming, I create shortcuts for lengthy but often-used commands. This allows me to stay focused on my goal and limit the number of variables that I must keep in my head all at once. I've adapted to not having an eidetic memory, something that I've of course never had, but nonetheless I've adapted.

If you or I were to suddenly go blind or deaf, we would find some way to adapt. It would take us some time, but we would eventually learn new tricks to help us overcome our disability. Just ask Ted Hart of Microsoft, who is a deaf Software Engineer who uses instant messenger and email to communicate with his colleagues and staff.

In a way, being normal or just average -- as opposed to being a savant -- can be an asset, as we are able to understand that everybody is different and that just because one person may excel in one area doesn't mean that someone else doesn't have something to offer in another area. This is what humbles us and makes us able to work as a team.

P.S. I wrote this article in the context of living in the United States of America. I wonder if adapting to such a disability would be as easily accomplished in another country?

Saturday, June 9, 2007

Multiple HTML Reply Signatures Remotely Served?

Ronald Heft of made a comment here asking a question about how users could use their HTML signature when not at their own computer.

This question interests me because I believe that applications need to be accessible via the web. Many power users use more than one computer, and Firefox Extensions must correspond to a specific user profile.

Stream at Vedauwoo between Laramie and Cheyenne in WyomingThere are ways around that within corporate networks. A Firefox Extension installed in a roaming profile will function for a user no matter what computer he or she uses, but a computer in the library or a coffee shop will effectively leave the user signatureless.

For my dual-boot setup, I could install my profile at a location on my FAT32 partition that is accessible by both operating systems. Then I could use the same centrally-configured Firefox Extensions, bookmarks, browser history, and other Firefox functionality from both Linux and Windows.

But suppose I'm sending an email from a friend's computer who is running Firefox, but who doesn't have my signature extension configured? Is there a way to serve this extension remotely? Applications such as the Mozilla Amazon Browser have made me very curious, and anyone who could implement something like this would surely differentiate themselves from the competition, as I'm not the only developer with a fancy HTML Signature extension.

As I mentioned in a previous post, I tried to manipulate the Google Docs interface so that I could use shortcut keys. Would it be possible to serve a XUL application that provided an interface to Gmail? Can another server -- perhaps one with the Greasemonkey engine installed -- effectively act as a middleman between a user and another server? Would security restrictions prevent this? Suppose I installed Firefox and the Plain Old Webserver on a remote server? Could I then serve my Firefox Extension remotely?

We will have to think about this concept for awhile...

Thursday, June 7, 2007

HTML Multiple Reply Signatures for Gmail Firefox Extension

After spending the last three weekends working on the HTML Multiple Reply Signatures for Gmail Firefox Extension 1.0.1, I finally have a working prototype.

The Firefox Extension has all of the features and functionality of the HTML Multiple Reply Signatures for Gmail Greasemonkey script, except the extension doesn't require Greasemonkey. In addition, the extension provides a user interface for easy editing of signatures.

With Greasemonkey, users are required to edit the script manually in order to edit signatures. With the extension, this is no longer necessary.

For convenience, there is a real-time preview window so any HTML entered is immediately displayed for easy editing.

In fact, I'm thinking that the preview editor has some potential to be used in a number of applications, such as an HTML tutorial, HTML-area textbox for user comments, possibly a content-management system, and some other uses.

Since the user interface consists of XUL, these applications would all have a client-side feel to them, yet the potential exists to either serve them remotely or package them as Firefox Extensions.

The Firefox Extension

You should be able to install the extension in Firefox simply by clicking on the HTML Multiple Reply Signatures for Gmail 1.0.1 Firefox Extension link. If you are prompted to install, wonderful! Simply choose the "Install" option and restart Firefox. However, I noticed that -- when I tried to install by clicking on the link -- I was instead prompted to save the XPI file to disk.

If you experience this, follow these steps to save the XPI to disk and install it locally.

  • To install the XPI locally, open the Extensions/Add ons window from the "Tools" menu.
  • Next, drag and drop the XPI file from your desktop to the extensions window.
  • When prompted to install, click "Install".

  • Restart Firefox by closing all Firefox windows.

Using the HTML Multiple Reply Signatures for Gmail Firefox Extension

Creating a signature

  • In Firefox, click "Tools" -> "Gmail Multiple Reply Signatures".

  • Open HTML Gmail Multiple Reply Signatures Editor

  • Near the top of the window are two radio buttons. Use these to toggle between editing the signatures for initial compose emails or reply emails

  • Reply Signatures Initial Composes and Replies

  • In the "Initial Composes" section, select from four signatures to configure.

  • Select from four Gmail HTML signatures to edit for Composes and Replies

  • Enter HTML in the "Enter HTML Signature here" section. For attributes, do not use any quotes. Below is an example of a signature hyperlink where attributes are used, but without quotes:

  • <div>--</div><a href= style=font-family:tahoma;color:blue;>James Mortensen</a><div></div>

    Gmail HTML Signatures Editor

  • In the "Preview" section, you will see real-time HTML output based on your input in the "Enter HTML Signature here" section. You may fine-tune your signature until it appears the way you want.

  • Preview Signature using HTML Multiple Reply Signatures Editor

  • Once configured, click "Save".

Inserting the HTML Signature in Gmail

Inserting the signature is automatic. When you click "compose" or "reply", the first signature in the list will automatically appear in the editor. To change signatures, use the dropdown list at the bottom of the Gmail left navigation section. The signature will be changed automatically as soon as your selection is made.

View the demo here.

Known bugs

There are some bugs that I have come across so far, and I am sure that there will be more. If you discover a bug that is not in this list, please email me or post a comment to this post.

Sometimes it is best to release software instead of trying to correct every single bug. None of these are showstoppers, but here they are:

  • Quotes cannot be used around attributes

  • Simply leave out the quotes as they are not required.

  • Large sections of HTML may be corrupted when saving.

  • When you enter large sections of HTML and save, the next time you open the sgnature content editor, you will be reverted back to defaults. You can find your signatures in an xml file called htmlmultiplereplysignaturesforgmail.xml in your Mozilla Firefox profile directory. Save this information somewhere else, or copy and paste the non-corrupted signatures back into the editor. I plan to create some means of recovery for these types of errors.

  • The signature names can't be renamed

  • This functionality has not been completely implemented yet.

  • When pressing "Compose" in Gmail more than once, multiple drop-down lists appear

  • Just delete any unwanted signatures from the Gmail editor.

  • After entering email content, selecting a different signature will cause part or all of my email to be deleted.

  • Be careful not to type below the "--" characters. There are invisible markers around he signature that mark the dynamic section. (Actually, the signature is placed inside a span element. If you type below the "--", you are typing inside the span element).

  • Fixed in 1.0.1 on 6/9/07 - After entering a signature on multiple lines in the editor, the signatures would not appear in the Gmail compose or reply editors.

  • I enabled the multiline attribute of the textbox, which the script did not know how to handle. The temporary fix was to disable multiline support until I have time to fix the problem and test it thoroughly. Be aware that if you want line breaks in the signature, simply use a <br> or <div></div>


This is the first project I've done on my own that is outside the context of work or school. Please don't hesitate to give me advice about how to better track bugs, write better documentation, or make improvements to the application.

Also, if you have any trouble or need help, please contact me. I hope you find this Firefox extension useful!

Friday, May 11, 2007

Dynamic Remote XUL, Struts, and Java Server Pages

I've recently had the opportunity to use Mozilla's XML-based XUL user interface language for the frontend of an Apache Struts application. The idea consists of using Firefox tabs or XUL tabs to manage multiple windows in the application.

Is it a Browser or a Client-Side Application?

Essentially, the application will run in a Firefox browser; however, it will look like a client-side application. That is the beauty of XUL. Since the Firefox user interface was developed using XUL, applications written in XUL can "take over" the Firefox interface and integrate with it either partially or fully. Thus, the line between what components are Firefox and what components belong to the application is very thin.

The backend will be developed in Java and use Struts to help utilize a Model, View, Controller architectural pattern. We are breaking new ground here. Most Struts applications I've seen generate dynamic HTML, not XUL. The application will be served remotely, appear to be a client-side application, and use Struts Action classes as the controller.

Since Struts actions are called via url's, it's possible to have different parts of our application run in different Firefox tabs! Mozilla has an API that allows developers to interact with the browser. Using JavaScript, a developer can open a url in a new window, a new tab, or the current window. From a development perspective, this means we can force our different modules to run in different tabs. The application would essentially run not in one Firefox tab, but in multiple tabs.

XUL Tabbrowser

There's not a lot of information out there on Struts and XUL, but it appears to be a very scalable model in that the MVC framework means that even existing Struts applications could be retrofitted with XUL simply by modifying the view.

However, the lack of Mozilla documentation does present a challenge. I found information on the tabbrowser XUL element, but none of the information appeared to be correct. In addition, the Mozilla Developer Center API for tabbrowser was missing examples. After researching and testing a solution, I contributed the following example:
Mozilla Developer Center XUL Tabs

  <tabbox id="tabBrowser">
    <tab label="Tab1"/>
    <tab label="Tab2"/>
    <tab label="Tab3"/>
  <tabpanels width="500" height="500">
    <browser id="browserTab1" src=""/>
    <browser id="browserTab2"/>
    <browser id="browserTab3"/>
   <button id="btnLoadBrowserContent"
  label="Load URL"  oncommand="loadURL(document.getElementById('tab2'),'')"/>

The example above will display three tabs in a Firefox window. Each tab contains a browser object. Using XML DOM methods, the src attribute can be dynamically modified based on user or system events:

function loadURL(browserElem,pUrl) {
//modify the src attribute of the browser element

The JavaScript code above will modify the src attribute of the second browser object and cause a page to be loaded in that tab. By replacing the src attribute with different Struts action urls, this application will be extremely dynamic and scalable.