<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4210075784363570204</id><updated>2010-06-21T22:58:26.304-07:00</updated><title type='text'>Open Source Opportunities</title><subtitle type='html'>A discussion of current trends and business opportunities available in the open source software development market.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default?start-index=26&amp;max-results=25'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>46</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-7434177628250881279</id><published>2010-05-22T14:45:00.000-07:00</published><updated>2010-05-22T21:47:40.865-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Business'/><category scheme='http://www.blogger.com/atom/ns#' term='Google'/><category scheme='http://www.blogger.com/atom/ns#' term='Pacman'/><title type='text'>Google, Pacman, and the Enemies of Fun</title><content type='html'>You might think Google dropped a bomb on some small country or fed small kittens to snakes.  Today, there is a lot of noise about &lt;a href="http://googleblog.blogspot.com/2010/05/celebrating-pac-mans-30th-birthday.html"&gt;Google's method of celebrating the anniversary of Namco's Pacman&lt;/a&gt;, which today turned 30.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-WAA3c7s8sQ/S_hG4LBMcxI/AAAAAAAAAkA/urSnwEvwyAw/s1600/pacman10-hp.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 107px;" src="http://3.bp.blogspot.com/_-WAA3c7s8sQ/S_hG4LBMcxI/AAAAAAAAAkA/urSnwEvwyAw/s320/pacman10-hp.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5474203277913256722" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I'm glad I don't work with all of the naysayers and complainers and whiners on the Internet who obstinately declare that they're now &lt;a href="http://www.telegraph.co.uk/technology/google/7750074/Pac-Man-30th-anniversary-marked-by-Google-Doodle.html?state=target#postacomment&amp;postingId=7754371"&gt;changing their search engine&lt;/a&gt; to &lt;a href="http://en.wikipedia.org/wiki/Bing_(search_engine)"&gt;Bing&lt;/a&gt;!  What's funny is that deep down inside in the depths of their subconscious, they've had this burning desire to do so all along.  &lt;br /&gt;&lt;br /&gt;Microsoft has really been beating Bing into our skulls.  Whenever I turn on the television, I see references to it in pop culture.  On Vampire Diaries, Supernatural, and other television programs on the CW, the main characters made several references to it and even used "Bing" as a verb.  This is what savvy marketing people refer to as "brand awareness" while in reality it's just brainwashing.&lt;br /&gt;&lt;br /&gt;You people that are complaining about Google putting up an interactive widget aren't really angry at Google.  You're angry at yourselves for being too stupid to understand how to use a computer, and as any psychologist will tell you, you're using &lt;a href="http://www.google.com/url?sa=t&amp;source=web&amp;ct=res&amp;cd=1&amp;ved=0CBgQFjAA&amp;url=http%3A%2F%2Fwww.rider.edu%2F~suler%2Fdefenses.html&amp;rct=j&amp;q=psychology+defense+mechanisms+redirection&amp;ei=9kf4S4LQB4zYMPPq4cAF&amp;usg=AFQjCNExhxZw35MHVEptQC6JAxF7-Q48hg"&gt;displacement&lt;/a&gt; to redirect your anger at yourself onto Google for actually thinking that something that was meant to bring joy was a virus.  You're using this moment as the excuse you've been looking for to run to Bing.  &lt;br /&gt;&lt;br /&gt;Brainwash successful!&lt;br /&gt;&lt;br /&gt;To the complainers out there, the world isn't going to wait for you.  It's moving on with or without you.  I'm warning you now, you'd better catch up or you'll be standing in the unemployment line in 10 to 20 years, complaining about how your job went to India or China or someone much younger and with more drive than you, and you'll be bitching about how both your life and the the government both suck.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://upload.wikimedia.org/wikipedia/commons/thumb/0/06/Pac_Man.svg/385px-Pac_Man.svg.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 192px; height: 225px;" src="http://upload.wikimedia.org/wikipedia/commons/thumb/0/06/Pac_Man.svg/385px-Pac_Man.svg.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;I am really exited to hear if the grass really is greener on the other side in Bingland.  As for me, I'm sticking with Google.  I'm staying on the cutting edge where life is more exciting.  Why, because you can't please all of the people all of the time.  If you want to be spoon fed and treated like the whiny infant that you sound like, then go to AOL or Bing.  Good riddens, I say!  Google's products and services will only get better if they market them to people with open minds who are willing to experiment.  They're better off without you.&lt;br /&gt;&lt;br /&gt;As for anyone coming out of college or anyone looking for a job, here is some unsolicited advice:  &lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;You can tell a lot about an employer by looking at the tools they use.  If they support Google and openness and get really excited about new technologies, chances are you're really going to enjoy the environment and the people you work with.  In that organization, you'll be important, and you'll make a difference in the world.  Most importantly, you'll have a lot of fun while you do it.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Now, if they support Microsoft or ban a specific technology because of some ridiculous moment of hypoglycemia, lack of sleep, and confusion, then I suggest you run the other way.  Well, unless you are the enemy of fun and like working with a bunch of stiffs who get hypertension because they spent money on virus software today instead of spending it on taking a computer class like they should have years ago.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;In summary, I really enjoyed the Friday break.  So did many of my coworkers.  I feel really sorry for all of the people who were offended by something so non-offensive.  Go back to your stone knives and bearskins.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-7434177628250881279?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/7434177628250881279/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=7434177628250881279' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/7434177628250881279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/7434177628250881279'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2010/05/google-pacman-and-enemies-of-fun.html' title='Google, Pacman, and the Enemies of Fun'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_-WAA3c7s8sQ/S_hG4LBMcxI/AAAAAAAAAkA/urSnwEvwyAw/s72-c/pacman10-hp.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-5721548471558024242</id><published>2008-12-17T20:54:00.000-08:00</published><updated>2008-12-17T21:34:55.113-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web 2.0'/><category scheme='http://www.blogger.com/atom/ns#' term='Craigslist'/><category scheme='http://www.blogger.com/atom/ns#' term='firewood'/><title type='text'>Break out the Country Crock</title><content type='html'>I read an &lt;A href="http://sumnershortcuts.com/craigslist-strangeness-seasoned-firewood/" target="_blank"&gt;intriguingly funny article&lt;/a&gt; tonight.  The reason it's so funny is that it's very applicable to me at the moment.  My brother and I have been burning firewood for heat this winter in Portland, Oregon.  We've actually obtained our fire wood from many different &lt;A href="http://portland.craigslist.org" target="_blank"&gt;Craigslist&lt;/a&gt; advertisements, such as the one featured in this article's screen shot, and we have made some extra income selling our surpluses to people who are either in need of heat or just want the ambiance provided by a nice warm fire.&lt;br /&gt;&lt;br /&gt;Seasoned wood does not in fact refer to seasoning the wood with pepper and salt and Italian spices although the idea does create some interesting mental pictures. For those who don't know, seasoned wood is wood that has been aged and naturally dried so that it will burn well.  In order to be seasoned, most firewood must be aged for at least 1 to 2 years.&lt;br /&gt;&lt;br /&gt;Although seasoned wood isn't seasoned in terms of teeming with lemon-pepper or garlic and oregano, burning the many different kinds of wood does indeed produce a plethora of different uniquely enticing and delicious smells.  Black walnut is perhaps my favorite.  Sit a piece in front of your fireplace just inches from the transfer of potential to kinetic energy.  Watch the blue flames emanating from a few well-seasoned, dry chunks of maple as the walnut slowly heats up.  After awhile, it smells like freshly baked bread and makes you want to go break out the Country Crock and dig in.  We did that one night and the wood smelled so good I felt I could almost take a bite out of it!&lt;br /&gt;&lt;br /&gt;With a fireplace, who needs Dish Network.  It's all the entertainment I need.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-5721548471558024242?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/5721548471558024242/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=5721548471558024242' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/5721548471558024242'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/5721548471558024242'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2008/12/break-out-country-crock.html' title='Break out the Country Crock'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-4257318801993530922</id><published>2008-09-21T15:39:00.000-07:00</published><updated>2008-09-21T18:02:54.316-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Startups'/><category scheme='http://www.blogger.com/atom/ns#' term='Business'/><category scheme='http://www.blogger.com/atom/ns#' term='Web Hosting'/><title type='text'>Dreamhost Hosting Special</title><content type='html'>I work with a client who uses Dreamhost as the hosting provider for a new web application.  My client works with several other contractors besides myself.  Some have been only temporary contracts while others have been more long-term.  For the initial phase of development, all development was done on local servers, and there was only one hostname for the website.&lt;br /&gt;&lt;br /&gt;One of the newest consultants spent just a small portion of his time in setting up some tools that would not only make development more efficient; but also, these tools will help prevent catastrophic mistakes that oftentimes can occur.  Manual, repeated tasks are prone to error, and it's not a matter of &lt;span style="font-style:italic;"&gt;if&lt;/span&gt; a failure occurs, but &lt;span style="font-style:italic;"&gt;when&lt;/span&gt; will the failure occur.&lt;br /&gt;&lt;br /&gt;The consultant set up several domain names for us to use in the deployment process.  Previously, the site was deployed to the server under the www subdomain.  While this is fine for code that has been tested on the hosting platform, it's not fine when deploying live.  We now have a "testing" subdomain and a "stage" subdomain where "testing" is where untested code can be tested using a separate build of the website.  "Stage", of course, mirrors whatever is deployed live and acts as a staging ground for final tests of changes to ensure that they are indeed production ready.&lt;br /&gt;&lt;br /&gt;The consultant also set up &lt;a href="http://trac.edgewall.org/" target="_blank"&gt;Trac&lt;/a&gt;, which is an open-source wiki, bug tracking package, and project management platform all rolled into one web application.  It integrates with the Subversion repository, which the consultant also setup and configured using Dreamhost's web panel.&lt;br /&gt;&lt;br /&gt;Dreamhost offers these features as part of the standard hosting package, all for the low cost of $5.95 per month, depending on the length of your committment.  Of all of the hosting providers that I've looked at, Dreamhost is the best for new startups looking to establish a web presence using PHP, Perl, Ruby, and some other popular programming languages.  You'll never have to worry about running out of databases, as Dreamhost will supply you with an endless supply of MySql databases!  &lt;br /&gt;&lt;br /&gt;Some of the things that really stood out to me were things like the Jabber Chat server, a full Unix shell, the Debian Linux operating system, and IMAP access so you can download your email to a mail client.  There is a one-click install feature for installing many popular packages, such as Wordpress, Moodle, and Joomla.  In addition, through the shell you can install other applications, such as Trac!  &lt;br /&gt;&lt;br /&gt;To make this deal even sweeter, you can get unlimited disk space and unlimited bandwidth if you sign up now by clicking on the link in the left section on my website!  This leaves lots of room for growth, and this perhaps may be the last hosting package you'll ever need!&lt;br /&gt;&lt;br /&gt;The only catch, there are only 1111 slots left open for unlimited disk space and bandwidth, so sign up today!&lt;br /&gt;&lt;br /&gt;&lt;span class="center"&gt;&lt;a style="text-align:center" onclick="javascript:urchinTrackerWrapper('/partners/dreamhostreferral');" target="_blank" href="http://www.dreamhost.com/r.cgi?407880"&gt;Click here to learn more&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-4257318801993530922?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/4257318801993530922/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=4257318801993530922' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/4257318801993530922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/4257318801993530922'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2008/09/dreamhost-hosting-special.html' title='Dreamhost Hosting Special'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-5823018868712967166</id><published>2008-09-01T22:09:00.001-07:00</published><updated>2008-09-01T22:24:35.133-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Marketing'/><category scheme='http://www.blogger.com/atom/ns#' term='Google'/><category scheme='http://www.blogger.com/atom/ns#' term='Web 2.0'/><title type='text'>Google Chrome Browser</title><content type='html'>While most of us spent our Labor Day weekend camping, barbecuing, or in my case, moving into a new home, the marketing team at Google was laboring away releasing marketing materials on what seems to be the next evolution of the web!&lt;br /&gt;&lt;br /&gt;Google Chrome, a fully open source multi-process web browser, addresses many of the woes that most web surfers encounter on a daily basis.  Instead of being concerned with browser lock ups and ensuring that we don't go over 35 to 40 tabs in Firefox for fear of the dreaded browser crash, we can rest assured knowing that the most we will ever have to worry about is a "tab crash".&lt;br /&gt;&lt;br /&gt;What is a tab crash?  According to the &lt;a href="http://books.google.com/books?id=8UsqHohwwVYC&amp;printsec=copyright&amp;source=gbs_summary_r&amp;cad=0#PPA9,M1"&gt;Google Chrome Comic book&lt;/a&gt;, each tab is launched as a separate process.  What this means is that if there are N tabs open, there will be N JavaScript threads running, N copies of the global data structures, and a significantly reduced chance that a rogue JavaScript function will bring a user's web experience to a grinding halt.&lt;br /&gt;&lt;br /&gt;Both Firefox and IE run as a single process.  While IE does tout the advantage of running each tab in a different thread, the memory is still shared; and all tabs are still susceptible to crashes.  In either case, the result is the same.  &lt;br /&gt;&lt;br /&gt;However, I am very interested to see this new browser in action.  How impervious to crashes is it going to be?  What is this going to mean for web development?  Will we need more CSS and HTML magicians to step forward and deal with yet another browser hack?  Or will Google Chrome follow web standards and allow the same ease of web application development as Firefox and Safari do?  &lt;br /&gt;&lt;br /&gt;One question that I have is in regards to add-ons.  Will this new browser be as extensible as Firefox?  Is there or will there eventually be a market for Google Chrome add-ons?  &lt;br /&gt;&lt;br /&gt;More importantly, is this the first step towards the Google Operating System?&lt;br /&gt;&lt;br /&gt;I guess tomorrow we will find out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-5823018868712967166?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/5823018868712967166/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=5823018868712967166' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/5823018868712967166'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/5823018868712967166'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2008/09/google-chrome-browser.html' title='Google Chrome Browser'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-1458916639279173694</id><published>2008-07-21T20:30:00.000-07:00</published><updated>2008-12-10T07:24:17.216-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>JavaScript and Java are Pass By Value</title><content type='html'>&lt;h3&gt;Proof that JavaScript and Java are Pass By Value&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Pass by value and pass by reference can be daunting at times, and I too have been confused and frustrated at all of the babbling about whether or not Java is one or the other, that is, until I saw an article featuring the Litmus test.  I've seen the Litmus test in college, but it didn't make sense completely until reading &lt;a href="http://javadude.com/articles/passbyvalue.htm" target="_blank"&gt;Scott Stanchfield's "Dammit"&lt;/a&gt; article.  &lt;br /&gt;&lt;br /&gt;Today I was reading Jeff Cogswell's article asserting that &lt;a href="http://blogs.devsource.com/msdev/content/ajax_and_clientside/javascript_pass_by_reference_or_value_1.html" target="_blank"&gt;JavaScript is pass by value&lt;/a&gt;.  The blog author is indeed correct in his assertions; however, there were many comments rebutting his arguments.  I thought it would be best to support his arguments by applying the Litmus test to JavaScript to prove once and for all whether or not JavaScript is pass by value or pass by reference.&lt;br /&gt;&lt;br /&gt;Java is clearly pass by value.  Scott Stanchfield's statement says it best:  &lt;a href="http://javadude.com/articles/passbyvalue.htm" target="_blank"&gt;"Objects are not passed by reference. A correct statement would be  Object references are passed by value."&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The JavaScript Litmus Test&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;I decided to apply the Litmus test to JavaScript and see what the results are.  Here is what I have so far:&lt;br /&gt;&lt;br /&gt;&lt;div style="border-style:solid;font-family:arial;"&gt;&lt;br /&gt;function doLitmusTest() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   var a1 = 5;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   var a2 = 7;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   swap(a1,a2);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   alert(a1 + ","+a2);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function swap(a,b) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var temp = a;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;a = b;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;b = temp;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;window.addEventListener("load",function() { doLitmusTest(); },true);&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The output is as follows:&lt;br /&gt;&lt;br /&gt;5,7&lt;br /&gt;&lt;br /&gt;The values were not swapped.  JavaScript fails the Litmus test, as Java did.  This means that JavaScript is also pass by value.&lt;br /&gt;&lt;br /&gt;In Java, there is a workaround to being able to implement the swap function, and it also works in JavaScript:&lt;br /&gt;&lt;br /&gt;&lt;div style="border-style:solid;font-family:arial;"&gt;&lt;br /&gt;function anotherTest() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   var obj1 = { value: 5 };  // JSON notation&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   var obj2 = { value: 7 };  // JSON notation&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   swapValue(obj1,obj2);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   alert(obj1.value + "," + obj2.value);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function swapValue(objA,objB) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  var temp = objA.value;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  objA.value = objB.value;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  objB.value = temp;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;window.addEventListener("load",function() { anotherTest(); },true);&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The output is:&lt;br /&gt;7,5&lt;br /&gt;&lt;br /&gt;In Java, data can be "wrapped" in an object to allow the value to be changed.  JavaScript behaves in the same manner.  All values, both primitives and object references are passed by value.  With primitives, changes we make to one copy of a variable do not affect changes to another copy.&lt;br /&gt;&lt;br /&gt;The rule is the same with Object references.  Objects are not passed in as parameters in Java or JavaScript, object &lt;span style="font-style:italic"&gt;references&lt;/span&gt; are passed as parameters.  References point to a specific location in memory.  Three references can all point to the same location, so if the data located at that spot in memory is changed, the change will be reflected for all of the references that point to that spot.&lt;br /&gt;&lt;br /&gt;However, changes to the reference itself are not reflected.  A rule of thumb to remember is that when implementing the swap method, you can only change data by calling setter and getter methods, or by accessing public properties.  However, making changes to the object reference instruct the object reference to point to a different location.  This is why swapValue worked as expected while swap did not.&lt;br /&gt;&lt;br /&gt;Below is a sequence of "visual art" to demonstrate the concepts visually:&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-bottom:160px"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_-WAA3c7s8sQ/SHAEF9uWArI/AAAAAAAAAE4/Pjau4u1Ymtk/s1600-h/swap1.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px;float:right; text-align:right;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_-WAA3c7s8sQ/SHAEF9uWArI/AAAAAAAAAE4/Pjau4u1Ymtk/s320/swap1.PNG" border="0" alt="new operator uses new memory space" id="BLOGGER_PHOTO_ID_5219676468637205170" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Object A and Object B are instantiated and new memory is allocated on the heap.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-bottom:160px;"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_-WAA3c7s8sQ/SHAEGAjZsKI/AAAAAAAAAFA/ip-yLLiLnG4/s1600-h/swap2.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;float:left;" src="http://4.bp.blogspot.com/_-WAA3c7s8sQ/SHAEGAjZsKI/AAAAAAAAAFA/ip-yLLiLnG4/s320/swap2.PNG" border="0" alt="using new on object A creates new space in memory" id="BLOGGER_PHOTO_ID_5219676469396615330" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Object A is assigned a reference to new memory space because the "new" keyword was used.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-bottom:0px"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-WAA3c7s8sQ/SHAEGcDfgSI/AAAAAAAAAFI/PRrOJbdT3Rg/s1600-h/swap3.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;float:right;" src="http://3.bp.blogspot.com/_-WAA3c7s8sQ/SHAEGcDfgSI/AAAAAAAAAFI/PRrOJbdT3Rg/s320/swap3.PNG" border="0" alt="using setter changes value in memory location" id="BLOGGER_PHOTO_ID_5219676476778971426" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The value of the object referenced by B is changed to a new value, but the object reference still points to the same location in memory.&lt;br /&gt;&lt;br /&gt;For A, the "new" operator created new space in memory and instantiates a new object.  The "12" is located in a different spot in memory.&lt;br /&gt;&lt;br /&gt;B, on the other hand, has a value that was set using a setter method.  Thus, the value has changed from "7" to "2" without destroying the original object.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-bottom:10px;"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-WAA3c7s8sQ/SHAEGSOJyxI/AAAAAAAAAFQ/GI6w6tTFruA/s1600-h/swap4.PNG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;float:left;" src="http://1.bp.blogspot.com/_-WAA3c7s8sQ/SHAEGSOJyxI/AAAAAAAAAFQ/GI6w6tTFruA/s320/swap4.PNG" border="0" alt="multiple objects reference the same memory space" id="BLOGGER_PHOTO_ID_5219676474139331346" /&gt;&lt;/a&gt;&lt;br /&gt;Objects A, C, and D all point to the same place in memory.  If a setter method is called on one of the object references, the value is changed in all 3 object references because they all point to the same location in memory.&lt;br /&gt;&lt;br /&gt;A good analogy to use to explain this concept is "nicknames".  For instance, my name is James, but people also refer to me by Jim.  Additionally, I've been called "Mort" before as well.  All three names point to the same object, me!  In the example I've shown you, A, C, and D are all names of the same object.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-1458916639279173694?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/1458916639279173694/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=1458916639279173694' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/1458916639279173694'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/1458916639279173694'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2008/07/javascript-and-java-are-pass-by-value.html' title='JavaScript and Java are Pass By Value'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_-WAA3c7s8sQ/SHAEF9uWArI/AAAAAAAAAE4/Pjau4u1Ymtk/s72-c/swap1.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-4095770090074812620</id><published>2008-07-13T16:40:00.000-07:00</published><updated>2008-07-13T23:36:31.584-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Namespaces'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><category scheme='http://www.blogger.com/atom/ns#' term='XSLT'/><title type='text'>XSLT Transformations with XML Namespaces</title><content type='html'>As of the date of this article, there are currently not a lot of resources on the Internet regarding how to transform XML that contains namespaces.  Yahoo's Weather Web Services API returns data in the form of RSS, and this data is formatted not only with elements and attributes, but also with namespaces.&lt;br /&gt;&lt;br /&gt;I'm experimenting with the Yahoo Weather API for a potential project I may work on.  Considering that there may be other Weather API's used, it makes more sense from an architectural design standpoint to tranform Yahoo's data into my own XML data structure.  This ensures that if the client decides that he/she likes Google's Weather API, or the Fox News API, all we need to do is create a new XSLT stylesheet to convert the data into the format recognized by our server.&lt;br /&gt;&lt;br /&gt;Here is part of the Yahoo Weather Data, taken from &lt;a href="http://weather.yahooapis.com/forecastrss?p=97206" target="_blank"&gt;here.&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div style="border-style:solid;font-family:arial;"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8" standalone="yes" ?&amp;gt;&lt;br /&gt;&amp;lt;rss version="2.0" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"&amp;gt;&lt;br /&gt;&amp;lt;channel&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;title&amp;gt;Yahoo! Weather - Portland, OR&amp;lt;/title&amp;gt;&lt;br /&gt;&amp;lt;link&amp;gt;http://us.rd.yahoo.com/dailynews/rss/weather/Portland__OR/*http://weather.yahoo.com/forecast/97206_f.html&amp;lt;/link&amp;gt;&lt;br /&gt;&amp;lt;description&amp;gt;Yahoo! Weather for Portland, OR&amp;lt;/description&amp;gt;&lt;br /&gt;&amp;lt;language&amp;gt;en-us&amp;lt;/language&amp;gt;&lt;br /&gt;&amp;lt;lastBuildDate&amp;gt;Sat, 28 Jun 2008 4:53 pm PDT&amp;lt;/lastBuildDate&amp;gt;&lt;br /&gt;&amp;lt;ttl&amp;gt;60&amp;lt;/ttl&amp;gt;&lt;br /&gt;&amp;lt;yweather:location city="Portland" region="OR"   country="US"/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;yweather:units temperature="F" distance="mi" pressure="in" speed="mph"/&amp;gt;&lt;br /&gt;&amp;lt;yweather:wind chill="101"   direction="300"   speed="10" /&amp;gt;&lt;br /&gt;&amp;lt;yweather:atmosphere humidity="22"  visibility="10"  pressure="29.82"  rising="2" /&amp;gt;&lt;br /&gt;&amp;lt;yweather:astronomy sunrise="5:24 am"   sunset="9:03 pm"/&amp;gt;&lt;br /&gt;&amp;lt;image&amp;gt;&lt;br /&gt;&amp;lt;title&amp;gt;Yahoo! Weather&amp;lt;/title&amp;gt;&lt;br /&gt;&amp;lt;width&amp;gt;142&amp;lt;/width&amp;gt;&lt;br /&gt;&amp;lt;height&amp;gt;18&amp;lt;/height&amp;gt;&lt;br /&gt;&amp;lt;link&amp;gt;http://weather.yahoo.com&amp;lt;/link&amp;gt;&lt;br /&gt;&amp;lt;url&amp;gt;http://l.yimg.com/us.yimg.com/i/us/nws/th/main_142b.gif&amp;lt;/url&amp;gt;&lt;br /&gt;&amp;lt;/image&amp;gt;&lt;br /&gt;&amp;lt;item&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;title&amp;gt;Conditions for Portland, OR at 4:53 pm PDT&amp;lt;/title&amp;gt;&lt;br /&gt;&amp;lt;geo:lat&amp;gt;45.52&amp;lt;/geo:lat&amp;gt;&lt;br /&gt;&amp;lt;geo:long&amp;gt;-122.68&amp;lt;/geo:long&amp;gt;&lt;br /&gt;&amp;lt;link&amp;gt;http://us.rd.yahoo.com/dailynews/rss/weather/Portland__OR/*http://weather.yahoo.com/forecast/97206_f.html&amp;lt;/link&amp;gt;&lt;br /&gt;&amp;lt;pubDate&amp;gt;Sat, 28 Jun 2008 4:53 pm PDT&amp;lt;/pubDate&amp;gt;&lt;br /&gt;&amp;lt;yweather:condition  text="Fair"  code="34"  temp="101"  date="Sat, 28 Jun 2008 4:53 pm PDT" /&amp;gt;&lt;br /&gt;&amp;lt;description&amp;gt;&amp;lt;![CDATA[&lt;br /&gt;&amp;lt;img src="http://l.yimg.com/us.yimg.com/i/us/we/52/34.gif"/&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;b&amp;gt;Current Conditions:&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;Fair, 101 F&amp;lt;BR /&amp;gt;&lt;br /&gt;&amp;lt;BR /&amp;gt;&amp;lt;b&amp;gt;Forecast:&amp;lt;/b&amp;gt;&amp;lt;BR /&amp;gt;&lt;br /&gt;Sat - Mostly Clear. High: 97 Low: 65&amp;lt;br /&amp;gt;&lt;br /&gt;Sun - Mostly Sunny. High: 91 Low: 66&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;a href="http://us.rd.yahoo.com/dailynews/rss/weather/Portland__OR/*http://weather.yahoo.com/forecast/USOR0275_f.html"&amp;gt;Full Forecast at Yahoo! Weather&amp;lt;/a&amp;gt;&amp;lt;BR/&amp;gt;&lt;br /&gt;(provided by The Weather Channel)&amp;lt;br/&amp;gt;&lt;br /&gt;]]&amp;gt;&amp;lt;/description&amp;gt;&lt;br /&gt;&amp;lt;yweather:forecast day="Sat" date="28 Jun 2008" low="65" high="97" text="Mostly Clear" code="33" /&amp;gt;&lt;br /&gt;&amp;lt;yweather:forecast day="Sun" date="29 Jun 2008" low="66" high="91" text="Mostly Sunny" code="34" /&amp;gt;&lt;br /&gt;&amp;lt;guid isPermaLink="false"&amp;gt;97206_2008_06_28_16_53_PDT&amp;lt;/guid&amp;gt;&lt;br /&gt;&amp;lt;/item&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/channel&amp;gt;&lt;br /&gt;&amp;lt;/rss&amp;gt;&amp;lt;!-- api1.weather.sp1.yahoo.com compressed/chunked Sat Jun 28 17:19:32 PDT 2008 --&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Note that the temperature and other weather data is stored within elements that are part of the yweather namespace.  The XSLT stylesheet below demonstrates how to obtain the temp attribute from the yweather:condition element:&lt;br /&gt;&lt;br /&gt;&lt;div style="border-style:solid;font-family:arial;"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="ISO-8859-1"?&amp;gt;&lt;br /&gt;&amp;lt;xsl:stylesheet version="1.0"&lt;br /&gt;xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&lt;br /&gt;xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;xsl:template match="/"&amp;gt;&lt;br /&gt;  &amp;lt;html&amp;gt;&lt;br /&gt;  &amp;lt;body&amp;gt;&lt;br /&gt;    &amp;lt;h2&amp;gt;Weather&amp;lt;/h2&amp;gt;&lt;br /&gt;    &amp;lt;table border="1"&amp;gt;&lt;br /&gt;      &amp;lt;xsl:for-each select="rss/channel"&amp;gt;&lt;br /&gt;        &amp;lt;tr&amp;gt;&lt;br /&gt;          &amp;lt;td&amp;gt;title&amp;lt;/td&amp;gt;&lt;br /&gt;          &amp;lt;td class="title"&amp;gt;&amp;lt;xsl:value-of select="title" /&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;/tr&amp;gt;&lt;br /&gt;        &amp;lt;tr&amp;gt;&lt;br /&gt;          &amp;lt;td&amp;gt;link&amp;lt;/td&amp;gt;&lt;br /&gt;          &amp;lt;td class="link"&amp;gt;&amp;lt;xsl:value-of select="link" /&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;/tr&amp;gt;&lt;br /&gt;        &amp;lt;tr&amp;gt;&lt;br /&gt;          &amp;lt;td&amp;gt;curCond&amp;lt;/td&amp;gt;&lt;br /&gt;          &amp;lt;td class="curCond"&amp;gt;&lt;br /&gt;            &amp;lt;xsl:value-of select="//yweather:condition/@text" /&amp;gt;&lt;br /&gt;          &amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;/tr&amp;gt;&lt;br /&gt;        &amp;lt;tr&amp;gt;&lt;br /&gt;          &amp;lt;td&amp;gt;curTemp&amp;lt;/td&amp;gt;&lt;br /&gt;          &amp;lt;td class="curTemp"&amp;gt;&lt;br /&gt;            &amp;lt;xsl:value-of select="//yweather:condition/@temp" /&amp;gt;&lt;br /&gt;          &amp;lt;/td&amp;gt;&lt;br /&gt;          &amp;lt;td id="curTemp"&amp;gt;&lt;br /&gt;            &amp;lt;xsl:value-of select="//yweather:condition/@temp" /&amp;gt;&lt;br /&gt;          &amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;/tr&amp;gt;&lt;br /&gt;        &amp;lt;xsl:for-each select="//yweather:forecast"&amp;gt;&lt;br /&gt;                &amp;lt;tr&amp;gt;&lt;br /&gt;                        &amp;lt;td&amp;gt;forecast&amp;lt;/td&amp;gt;&amp;lt;td class="day"&amp;gt;day: &amp;lt;xsl:value-of select="@day" /&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;                &amp;lt;/tr&amp;gt;&lt;br /&gt;                &amp;lt;tr&amp;gt;&lt;br /&gt;                        &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td class="date"&amp;gt;date: &amp;lt;xsl:value-of select="@date" /&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;                &amp;lt;/tr&amp;gt;&lt;br /&gt;                &amp;lt;tr&amp;gt;&lt;br /&gt;                        &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td class="low"&amp;gt;low: &amp;lt;xsl:value-of select="@low" /&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;                &amp;lt;/tr&amp;gt;&lt;br /&gt;                &amp;lt;tr&amp;gt;&lt;br /&gt;                        &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td class="high"&amp;gt;high: &amp;lt;xsl:value-of select="@high" /&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;On another note, I've done XML conversions before the hard way:  By parsing the XML with PHP or JSP and dynamically rebuilding the XML!  While this would also work to solve my problem, using XSLT will allow me to keep the transformation layer separate from the business logic.  &lt;br /&gt;&lt;br /&gt;Although this was somewhat time consuming getting started with XSLT and converting XML with namespaces, I can already feel the weight being lifted off my mind knowing that changing my data sources won't involve troubleshooting PHP errors!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-4095770090074812620?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/4095770090074812620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=4095770090074812620' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/4095770090074812620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/4095770090074812620'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2008/07/xslt-transformations-with-xml.html' title='XSLT Transformations with XML Namespaces'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-7705844846389717717</id><published>2008-07-05T14:19:00.000-07:00</published><updated>2008-12-10T07:24:17.816-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Operating systems'/><category scheme='http://www.blogger.com/atom/ns#' term='Cross-platform'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Share VMWare Image between Dual-Boot Operating Systems</title><content type='html'>&lt;br /&gt;&lt;h3&gt;How to Share a VMWare Image Between Windows XP and Ubuntu 8.04&lt;/h3&gt;&lt;br /&gt;Sharing a VMWare Image in a dual-boot setup involves the following prerequisites:&lt;br /&gt;&lt;br /&gt;- One ntfs partition with Windows XP Professional installed&lt;br /&gt;- One ext3 partition with Ubuntu 8.04 installed&lt;br /&gt;- One fat32 partition, shared between Ubuntu and Windows&lt;br /&gt;- At least 1GB of RAM&lt;br /&gt;- VMPlayer installed in both Windows XP and Ubuntu 8.04&lt;br /&gt;- VMImages, stored on the fat32 partition&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Stored on the fat32 partition is one Windows XP Home VMImage.  I don't have VMWare Workstation.  So you may be wondering how I was able to create my own Windows XP Home image.  I'll get to that later.&lt;br /&gt;&lt;br /&gt;I first boot into the Windows XP Home installation using the Windows XP Pro host.  I moved some files around, made some changes to some files.  Then shutdown the VMImage.  I reboot the computer into Ubuntu 8.04, started VMPlayer, and boot into the very same Windows XP Home image I was just working with on the XP host.  My changes were all there!  &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_-WAA3c7s8sQ/SDs8TfmbpaI/AAAAAAAAAEo/WhsilX66mik/s1600-h/vmware-Screenshot.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_-WAA3c7s8sQ/SDs8TfmbpaI/AAAAAAAAAEo/WhsilX66mik/s320/vmware-Screenshot.png" border="0" alt="Windows XP VMPlayer on Ubuntu select copied" id="BLOGGER_PHOTO_ID_5204820099954615714" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;When I first started up the VMImage in Ubuntu, the system asked me if I moved or copied the VMImage.  Well, I didn't move it, but I didn't copy it either.  Since I wasn't sure what option to pick, I selected the "copied" option recommended by VMPlayer if you don't know whether or not you moved or copied the image.  This will happen again when I switch back to the Windows host.  So far, selecting "copied" has not negatively affected performance.&lt;br /&gt;&lt;br /&gt;The first time booting the image in the new host, networking didn't immediately work.  Wait a few minutes and it may fix itself.  You can also go into VMWare tools, if it's installed, and make sure your Ethernet card is enabled.  So far, I've had no issues with networking.&lt;br /&gt;&lt;br /&gt;I'm very impressed with VMPlayer!  I can run Windows XP in a VMimage in both Windows and Linux.  It's stable, fast, and allows me to work on Windows projects on both Ubuntu and Windows hosts.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_-WAA3c7s8sQ/SDs8T_mbpbI/AAAAAAAAAEw/fE8ohfEUIqw/s1600-h/vm-win-Screenshot.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_-WAA3c7s8sQ/SDs8T_mbpbI/AAAAAAAAAEw/fE8ohfEUIqw/s320/vm-win-Screenshot.png" border="0" alt="Boot Windows XP in Ubuntu using VMPlayer" id="BLOGGER_PHOTO_ID_5204820108544550322" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Using Microsoft Virtual PC to Create Image and Convert with VMWare Converter&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Previously, I was using Microsoft Virtual PC 2007, which wasn't cross-compatible with Linux.  To answer the above unanswered question of how I created a Windows XP Home VMWare image without VMWare Workstation, I used VMWare Comverter to convert my Windows XP Home Virtual PC image to VMWare.  In Virtual PC, it took a long time to boot up.  Once booted, response was slow and unusable.  I quit using the Virtual PC image long ago because it was simply too slow.&lt;br /&gt;&lt;br /&gt;In VMPlayer, I feel that the Guest operating system runs smoother than the Windows XP host itself!  I'd recommend this setup for anyone who wants to run Windows from Linux and Windows from Windows.  Additionally, although Virtual PC is slow, it's a great tool to allow you to create a Virtual image and then convert it to VMWare using the VMWare Converter.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic"&gt;UPDATE:  I've been using this setup for over a month and I'm still happy with it!&lt;/span&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-7705844846389717717?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/7705844846389717717/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=7705844846389717717' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/7705844846389717717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/7705844846389717717'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2008/07/share-vmware-image-between-dual-boot.html' title='Share VMWare Image between Dual-Boot Operating Systems'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_-WAA3c7s8sQ/SDs8TfmbpaI/AAAAAAAAAEo/WhsilX66mik/s72-c/vmware-Screenshot.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-4467424071484129876</id><published>2008-06-28T16:43:00.000-07:00</published><updated>2008-06-28T17:48:38.404-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VPN'/><category scheme='http://www.blogger.com/atom/ns#' term='Problem Solving'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Collaboration'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Cisco VPN on Ubuntu 8.04</title><content type='html'>Deadlines approach fast!  In times like these, it's oh so helpful to be able to dig a tunnel from your office to your home so that you have access to the tools that you need!  Right now you have images of me under the ground with a shovel slowly scooping through layers of packed dirt.  I'm not using shovels.  I didn't break a sweat, and I didn't have to use a single gallon of gasoline!&lt;br /&gt;&lt;br /&gt;I installed Cisco VPN on Ubuntu 8.04.  Essentially, I did create a tunnel from my office to my home, expanding the bubble that is our corporate network to surround my makeshift home office.  It was both easier than I thought and harder than I thought.  It was easier thanks to the wonderful community of Ubuntu users, yet harder because it required kernel patches and Google searches and a little patience and persistence.  &lt;br /&gt;&lt;br /&gt;I found a link to fix the &lt;a href="http://www.blog.arun-prabha.com/2008/05/01/cisco-vpn-installation-issue-with-ubuntu-804-hardy-heron/" target="_blank"&gt;Cisco VPN Installation Issue with Ubuntu 8.04 Hardy Heron&lt;/a&gt;.  There are in fact several of them, which helps to confirm that the steps you follow won't cause your refrigerator to start leaking.  A poster in the forum also described my exact problem that I was facing.  He was using an older version of the VPN Client, as I was.  And according to another poster, it wasn't compatible with the new kernel.  He supplies the reader with a link to the patch, which can also be found all over the net.&lt;br /&gt;&lt;br /&gt;After pulling our friendly IT Specialist from his episode of Babylon 5, I was able to obtain the latest version of the VPN Client.  It was in fact the same version listed in the forum that the poster recommended.  After applying the patch to the new version, all was good.  Well, almost.  I couldn't get the VPN to start.  It was complaining that the profile couldn't be found.  What it should have done was laughed at me, called me an idiot, and told me to put the profile configuration file in the correct directory!  Then it should have shook it's head and told me to try reading the usage instructions more carefully and to omit using the .pcf file extension in the command I was using.&lt;br /&gt;&lt;br /&gt;After reading further in the forum, I found that the Ubuntu community was nice enough to remind me of this fact, without laughing at me, and without the shake of a head.&lt;br /&gt;&lt;br /&gt;Easy enough.  I started the VPN Client and am now on the way to meeting my deadline, all without leaving the house!  In addition, I can now login on nights and future weekends, workaholic that I am, and be able to get more work done!&lt;br /&gt;&lt;br /&gt;I must say I'm pretty impressed with Ubuntu 8.04!  I'm glad I tried it out.  I haven't boot into Windows XP Pro in over a month now!  And so far there hasn't been a need.  Of course, I do have VMPlayer installed on here with a Windows XP Home VMImage, and am kind of cheating, but that's another adventure!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-4467424071484129876?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/4467424071484129876/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=4467424071484129876' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/4467424071484129876'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/4467424071484129876'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2008/06/cisco-vpn-on-ubuntu-804.html' title='Cisco VPN on Ubuntu 8.04'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-4956926757564241858</id><published>2008-06-27T21:45:00.000-07:00</published><updated>2008-06-27T22:16:18.381-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox development'/><category scheme='http://www.blogger.com/atom/ns#' term='Greasemonkey'/><category scheme='http://www.blogger.com/atom/ns#' term='XUL'/><category scheme='http://www.blogger.com/atom/ns#' term='HTML Signatures'/><category scheme='http://www.blogger.com/atom/ns#' term='Collaboration'/><category scheme='http://www.blogger.com/atom/ns#' term='Gmail'/><title type='text'>HTML Multiple Reply Signatures for Gmail 1.0.2.3</title><content type='html'>Don't get too excited.  The &lt;a  href="http://www.opensourceopportunities.com/htmlmultiplereplysignaturesfo1.0.2.3.xpi" onclick="javascript:urchinTrackerWrapper('/downloads/htmlmultiplereplysignaturesfo1.0.2.3.xpi');"    &gt;Multiple HTML Reply Signatures Extension 1.0.2.3&lt;/a&gt; update doesn't include too many new features.  I got rid of the red update link that appears in the toolbar.  I don't think it was working correctly.  In addition, it took up valuable browser real estate.  Bad idea.  &lt;br /&gt;&lt;br /&gt;I did try to see what would happen in Firefox 3.  Sadly, the Firefox Extension doesn't work in Mozilla's newest and fastest browser.  The problem isn't the editor or even the signature injection.  It's the module that reads data from the XML file.  This was a hack anyway.  I could probably get by with using the Firefox RDF API or perhaps store the signatures using the preferences system.  &lt;br /&gt;&lt;br /&gt;The good news is, converting to Firefox 3 wouldn't be hard.  The bad news is that I don't have time to do it.  We just need to fix the mechanism that reads signatures from the XML data file!  That's it!  Everything else appeared to work when I tested it!  &lt;br /&gt;&lt;br /&gt;Anyone know any JavaScript who is bored?  HTML Multiple Reply Signatures for Gmail is licensed under the GPL!  You can crack open the XPI and try to fix this yourself!  I'll even tell you what files to modify if you email me!&lt;br /&gt;&lt;br /&gt;I did start working on a version for Gmail 2.  Interestingly enough, there aren't many solutions out there for Gmail 2, yet there was tons of competition for Gmail 1.  I have a prototype that &lt;a href="http://fourinarow.net" target="_blank"&gt;Susan Hemmersmeier&lt;/a&gt; has happily tested for me.  It's very buggy though.  Too buggy to put up on the blog, and too buggy for her to use.&lt;br /&gt;&lt;br /&gt;Susan asked me when this will be finished.  I hate to keep promising that "I'll eventually get to it.".  You see, thanks to this blog, I landed some contract work!  It's a lot of fun, but it takes up a lot of time.  As a result, it would appear that HTML Multiple Reply Signatures for Gmail may be a (sniff...) dying project...&lt;br /&gt;&lt;br /&gt;Do you have the skills to resurrect it from it's ashes?  Let me know!  I can definitely provide the moral support and answer technical questions, I just can't devote programming time to it at the moment.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;James&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-4956926757564241858?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/4956926757564241858/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=4956926757564241858' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/4956926757564241858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/4956926757564241858'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2008/06/html-multiple-reply-signatures-for.html' title='HTML Multiple Reply Signatures for Gmail 1.0.2.3'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-5905376279594824733</id><published>2008-06-10T21:54:00.000-07:00</published><updated>2008-07-05T17:45:44.176-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><title type='text'>getElementByAttribute</title><content type='html'>I don't use many JavaScript libraries, I prefer to write my own implementations of code that I need so that I don't have to import the entire library (although the example I am referring to in this post was not written by me).  With Java, the compiler weeds out things you don't use, but the browser doesn't.  There is really no mainstream mechanism for the browser to say "Only import method X".  &lt;br /&gt;&lt;br /&gt;I've used &lt;a href="http://taconite.sourceforge.net/" target="_blank"&gt;Taconite&lt;/a&gt; and &lt;a href="http://getahead.org" target="_blank"&gt;DWR&lt;/a&gt; for a current project, but as a general rule I've found that for what I do, most libraries are limited to just solving one part of the problem.  Taconite is great for AJAX support and being able to add XHTML to the DOM while still maintaining a readable XHTML file so you don't have to wrap everything in DOM methods.  However, it doesn't cut it with cross-domain issues.  Similarly, DWR is great for making AJAX calls by invoking a JavaScript wrapper with the same name as your Java class method, but it suffers from the same limitation.  &lt;br /&gt;&lt;br /&gt;I'll write more on this topic later, but the main purpose of this post is to identify the source of some code I found on &lt;a href="http://mahiways.spaces.live.com/blog/cns!6A1F270FEA8CDD8C!219.entry?action=post&amp;wa=wsignin1.0" target="_blank"&gt;Mahesh Lambe's blog&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Mahesh obviously paid attention in school!  The getElementByAttribute function that he wrote uses two inner functions and recursion to search for an element that contains the attribute you specify and the value you specify.  The search consist of making a recursive call by diving down through all of the child elements in one call while checking the sibling in another call.  This results in a thorough check down the DOM tree.  It reminds me vaguely of something I may  have done in Lisp with Fibonacci numbers in college.  &lt;br /&gt;&lt;br /&gt;This is one of the reasons that I love JavaScript.  I just don't come across code like this in Java.  With JavaScript, the code seems more true to the spirit of Computer Science, while still representing the language of interactive web applications.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-5905376279594824733?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://mahiways.spaces.live.com/blog/cns!6A1F270FEA8CDD8C!219.entry?action=post&amp;wa=wsignin1.0' title='getElementByAttribute'/><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/5905376279594824733/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=5905376279594824733' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/5905376279594824733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/5905376279594824733'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2008/06/getelementbyattribute.html' title='getElementByAttribute'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-5230974203145886614</id><published>2008-05-25T13:58:00.000-07:00</published><updated>2008-05-25T13:58:01.077-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Business'/><category scheme='http://www.blogger.com/atom/ns#' term='Collaboration'/><category scheme='http://www.blogger.com/atom/ns#' term='Open Source Licensing'/><title type='text'>Open Source Infections</title><content type='html'>This article is in response to a comment left on &lt;a href="http://www.michiknows.com/2007/02/05/programming-contract-work-tips-part-2/"&gt;this article&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Below is an excerpt of the GPL from http://www.gnu.org/licenses/gpl.html:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The GPL license states that the purpose is to give developers more freedom to use the source code; however, it's not truly free!  Here is another excerpt from the &lt;a href="http://www.gnu.org/licenses/gpl-faq.html"&gt;GNU FAQ&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;If I add a module to a GPL-covered program, do I have to use the GPL as the license for my module?&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;    The GPL says that the whole combined program has to be released under the GPL. So your module has to be available for use under the GPL.&lt;br /&gt;&lt;br /&gt;    But you can give additional permission for the use of your code. You can, if you wish, release your program under a license which is more lax than the GPL but compatible with the GPL. The license list page gives a partial list of GPL-compatible licenses. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;You have a GPL'ed program that I'd like to link with my code to build a proprietary program. Does the fact that I link with your program mean I have to GPL my program?&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;        Not exactly. It means you must release your program under a license compatible with the GPL (more precisely, compatible with one or more GPL versions accepted by all the rest of the code in the combination that you link). The combination itself is then available under those GPL versions. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;If so, is there any chance I could get a license of your program under the Lesser GPL?&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;        You can ask, but most authors will stand firm and say no. The idea of the GPL is that if you want to include our code in your program, your program must also be free software. It is supposed to put pressure on you to release your program in a way that makes it part of our community.&lt;br /&gt;&lt;br /&gt;    You always have the legal alternative of not using our code. &lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The term "infect" perfectly describes what some open source licenses can do to code.  Specifically, any code one writes that uses a GPL library can become "blanketed" by the GPL license.  The author of the comment claims that this is FUD.  It's not FUD, it's reality.  Sure, open source software is great, and I have even written open source software myself.  However, I can't use this code in a proprietary project because the license would make the proprietary project non-proprietary.  The analogy of an infection paints a perfect picture regarding how the license would spread from the open source library to the proprietary code.&lt;br /&gt;&lt;br /&gt;This isn't to say that all open source licenses are bad.  It's important to differentiate between the GPL, LGPL, Apache License, MIT License, and other public licenses.  To really label a license as giving developers the freedom to use the software however they want, one would need to look at the LGPL, Apache Commons, or another license that allows open source software to be integrated into a proprietary application.&lt;br /&gt;&lt;br /&gt;While there is nothing wrong with the GPL, it's important to understand that there is a time and a place to use this license, and that GPL-licensed code may not be good for every project.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-5230974203145886614?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/5230974203145886614/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=5230974203145886614' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/5230974203145886614'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/5230974203145886614'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2008/05/open-source-infections.html' title='Open Source Infections'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-8190784444738302455</id><published>2008-05-10T14:04:00.000-07:00</published><updated>2008-05-11T14:04:11.093-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='Compression'/><category scheme='http://www.blogger.com/atom/ns#' term='String parsing'/><category scheme='http://www.blogger.com/atom/ns#' term='Firefox development'/><category scheme='http://www.blogger.com/atom/ns#' term='Obfuscation'/><title type='text'>Open Source JavaScript Compressor</title><content type='html'>Are you concerned about having your Firefox Extension JavaScript code compromised?  XPI files can be extracted and code can be easily viewed.  One solution that works very well for many organizations that wish to keep their JavaScript code secret is to use a JavaScript obfuscator.  &lt;br /&gt;&lt;br /&gt;Also known as a script compiler or script compressor, an obfuscator takes human-readable JavaScript code and converts it into text that is virtually impossible for humans to process.  When you're ready to deploy your product live, your developers can "obfuscate" a version of the code for distribution and maintain the original human-readable version for continued maintenance and development.&lt;br /&gt;&lt;br /&gt;In addition to making it difficult to reverse-engineer, compressed JavaScript files are generally 40% to 60% smaller than their aesthetically pleasing human-readable counterparts, as a result of comment, whitespace, and line break removal.&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://www.javascript-source.com/"&gt;http://www.javascript-source.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Please see the above link for a quick example of the difference between a human-readable JavaScript function and an obfucscated function.  I wouldn't recommend purchasing this version though as there are open source versions out there that will accomplish the same goal.  &lt;br /&gt;&lt;br /&gt;&lt;a href="http://javascriptcompressor.com/"&gt;http://javascriptcompressor.com/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This version is Dean Edward's Packer.  The problem with this is that the website has a decoder.  This kind of defeats the purpose of obfuscation, and I would recommend it only for compression and not obfuscation.&lt;br /&gt;&lt;br /&gt;These tools appear to be a great way to keep proprietary JavaScript code from falling into the wrong hands.  Obfuscation is not prefect or foolproof, but consider this question:  Is a thief more likely to snoop around in a car with unlocked doors or one that is securely locked?&lt;br /&gt;&lt;br /&gt;Here are some links to free or open source obfuscators.  All three work from the command line:&lt;br /&gt;&lt;br /&gt;- &lt;a href="http://developer.yahoo.com/yui/compressor/"&gt;YUI Compressor&lt;/a&gt;&lt;br /&gt;- &lt;a href="http://tools.2vi.nl/"&gt;ObfuscateJS JavaScript Obfuscator&lt;/a&gt;&lt;br /&gt;- &lt;a href="http://shaneng.awardspace.com/#jso_description"&gt;JSO (JavaScript Obfuscator)&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-8190784444738302455?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/8190784444738302455/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=8190784444738302455' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/8190784444738302455'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/8190784444738302455'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2008/05/open-source-javascript-compressor.html' title='Open Source JavaScript Compressor'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-1687707039283516354</id><published>2008-04-05T15:30:00.000-07:00</published><updated>2008-12-10T07:24:17.983-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Problem Solving'/><category scheme='http://www.blogger.com/atom/ns#' term='MVC'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Struts'/><title type='text'>Model View Squared Controller</title><content type='html'>At my place of work, Model View Controller is a common architectural pattern used as the foundation for the applications that we develop and maintain.  MVC is a common pattern that can be seen in just about any software industry, from Agile development shops to those that follow the more traditional models of development.&lt;br /&gt;&lt;br /&gt;As Computer Scientists, we often look for ways to solve a problem not once, but for N cases.  Some really smart people at the &lt;a href="http://struts.apache.org/" target="_blank"&gt;Apache Foundation&lt;/a&gt; and &lt;a href="http://www.springsource.com/web/guest/home" target="_blank"&gt;SpringSource&lt;/a&gt; have designed and implemented solutions for Java that lay the foundation or "framework" for quickly and efficiently starting the development of an MVC application.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;MVC Framework Flow in Struts and Spring&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;With both Struts and Spring, a request is sent from a browser to a servlet container,  such as &lt;a href="http://tomcat.apache.org/" target="_blank"&gt;Tomcat&lt;/a&gt; or &lt;a href="http://www.mortbay.org/" target="_blank"&gt;Jetty&lt;/a&gt;.  The container hands off the request to a servlet declared in an XML configuration file.  The servlet processes the request and hands it off to a controller.  The controller, typically an Action subclass in Struts or a Controller subclass in Spring, makes calls to the model to retrieve data from the data source, manipulate that data, and pass it back to the controller.  Afterwards, the result is forwarded to the view.  In Struts, an ActionForward is returned by calling the mapping.findForward method and passing in a String that maps to a JSP page declared in the configuration file.  In Spring, a ModelAndView object is instantiated with the JSP filename as an argument.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Advantages and Disadvantages of Struts and Spring&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;This particular pattern is well-known for decoupling the business logic from the user interface, the user interface from the controller, and the controller from the business logic.  The advantage is that the view can be modified, maintained, or completely replaced, independent of the rest of the system.&lt;br /&gt;&lt;br /&gt;Well, almost....&lt;br /&gt;&lt;br /&gt;If you want to change the view, it's still a development issue.  You still have to deploy a new Web Application Archive, or WAR file for short.  You still have to test the application, as other developmental changes could affect the behavior of the system.&lt;br /&gt;&lt;br /&gt;Unless you break the application up into completely separate modules that all exist outside the application....&lt;br /&gt;&lt;br /&gt;Velocity, a templating language developed by the Apache Foundation, is very similar to Java Server Pages (JSP), except the Velocity files can be hosted outside the WAR file, on a completely different server, completely independent of the application.  &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The Velocity Advantage&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Picture an enterprise-level reporting tool designed to be hosted by an application service provider.  Imagine that there are thousands of clients who use this system and who regularly depend on the functionality.  If you're a project manager for this reporting tool and you want to allow all of your clients to customize and skin the user interface without needing to involve your developers, then you need the Velocity Advantage!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;The JSP Disadvantages&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;Even with MVC, you may have a few JSP pages that create a tightly coupled system where a change to the HTML structure for one client will affect thousands, perhaps with disastrous results.  While the number of pages is small, it may take a lot of work to make them all work together for each logical case.  &lt;br /&gt;&lt;br /&gt;On the other hand, you could have N JSP pages for N clients.  This means that deploying a new feature means that you will need to modify N JSP pages.&lt;br /&gt;&lt;br /&gt;No matter what solution you use, the fact remains that updating the user interface becomes a development issue that involves a complete development, testing, and deployment cycle, as well as the possibility of either introducing new bugs into the system or creating a situation where you require intense, time-consuming CVS management.  Being organized takes time.&lt;br /&gt;&lt;br /&gt;But using Velocity, these JSP page equivalents could be stored on the client's servers, or an external server that you maintain that is specifically dedicated to hosting these view components.  Suppose you then have a configuration file where you can store the location of the view for each client, kind of like struts-config but better; it exists outside the WAR file!  And suppose the client has control over which view they use!  &lt;br /&gt;&lt;br /&gt;Sure, with Struts and Spring, the configuration exists in an XML file outside of the codebase, but you still have to pack a new WAR file and possibly restart your servlet container when making changes to these files.  This, of course, equates to &lt;i&gt;downtime!&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Here is where those smart people at the Apache Foundation failed to completely solve this problem.  &lt;span style="font-weight:bold;"&gt;(For the record, the developers of Struts are extremely bright problem solvers who have made significant contributions to the development community.  These contributions have reduced the cost of development significantly in many J2EE environments, and without them, I would probably still be sorting through a mess of code trying to figure out how to write a controller!  Additionally, I've not seen a container/framework yet that solves this problem in the manner that I propose.)&lt;/span&gt;  What's the point of externalizing all of my configuration if changing it still requires me to disrupt my production systems?  Any changes made to web.xml, server.xml, struts-config.xml, tiles-defs.xml, or any other configuration file requires a servlet container restart, in most cases.&lt;br /&gt;&lt;br /&gt;And this is exactly the type of problem that would make the above scenario fail with a framework such as Struts, or Spring, or WebWork, or Struts 2.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Model View Squared Controller&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;The framework can of course still be used, just not with the struts-config.XML file.  To allow clients to modify their HTML or CSS or change the view that they see, they have to be able to access your own customized, instantly reloadable configuration schema, not the framework schema.  You can use an XML file on your server or even a database, as long as changes to the data are instantly recognizable.  &lt;br /&gt;&lt;br /&gt;This is the type of framework that I want to develop.  I'll call it Model View Squared Controller.  It's too long though.  I need a better name.  The concept is that your view would consist of a single JSP page, but all it would do is output data from a bean or even the HttpServletRequest object.  The bean would be populated in the controller with the view template retrieved from outside the application.  The view would be created as a Velocity object, processed in the controller, and then forwarded to the JSP page.  &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-WAA3c7s8sQ/R_mGl9V8z2I/AAAAAAAAAEg/-vNqVKAtkb8/s1600-h/mvcsquared-diagram.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_-WAA3c7s8sQ/R_mGl9V8z2I/AAAAAAAAAEg/-vNqVKAtkb8/s320/mvcsquared-diagram.JPG" border="0" alt="Model View Squared Control Flow diagram" id="BLOGGER_PHOTO_ID_5186324432573747042" /&gt;&lt;/a&gt;&lt;br /&gt;Essentially, there are two "views"; one is part of the application and the other plugs into this view.  The JSP page within the WAR file does nothing except render the data, while the other view -- the plugged-in view -- is actually retrieved from a remote data source and assembled in the controller.  It's almost as if your view becomes a piece of data.  It actually is data!  &lt;br /&gt;&lt;br /&gt;It's a tough concept to ponder.  "My view is data, you say?  I thought the model was the data?".  Well, it is.  But the view just happens to be something that we retrieve from an external data source, whether it be a remote server as a file, or as a template stored in a database.&lt;br /&gt;&lt;br /&gt;Forms can be data.  I don't mean the data that is entered in the forms, I mean the forms themselves!  In your reporting tool, clients want to be able to use different forms with different field names and values.  If your developers are smart, they can design a database schema that is abstract and extensible, one where field names aren't column names, but pieces of data themselves.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Fitness Tracker&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;This is also the answer to my Senior Design project!  I designed a system for allowing health club owners to add exercises to the system so that their members could record data for each exercise.  &lt;br /&gt;&lt;br /&gt;Since each exercise is different, there are different data fields for each type of exercise.  These things can't be hard-coded because they are data.  Not data that the member would see, but data that the client, the club owner or manager would see!  Once again, the form fields are data!&lt;br /&gt;&lt;br /&gt;Same with the reporting tool!  Each client will have their own idea of what data they want their employees or customers to be able to enter.  Therefore, you absolutely must solve the problem once and only once!  Otherwise, you'll be scrambling to reinvent the wheel for each new customer that knocks on the door.&lt;br /&gt;&lt;br /&gt;I'm going to continue to write more on this subject, as I feel that the concept of a model generated view, view view, or whatever I decide to call it, is oftentimes overlooked.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-1687707039283516354?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/1687707039283516354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=1687707039283516354' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/1687707039283516354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/1687707039283516354'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2008/03/model-view-squared-controller.html' title='Model View Squared Controller'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_-WAA3c7s8sQ/R_mGl9V8z2I/AAAAAAAAAEg/-vNqVKAtkb8/s72-c/mvcsquared-diagram.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-6927638400498717454</id><published>2008-03-19T21:05:00.000-07:00</published><updated>2008-03-19T21:02:46.204-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Problem Solving'/><category scheme='http://www.blogger.com/atom/ns#' term='Business'/><category scheme='http://www.blogger.com/atom/ns#' term='Employment'/><title type='text'>Technical Customer Service</title><content type='html'>Quoted from &lt;a href="" target="_blank"&gt;Joel On Software - Some interesting jobs&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic"&gt;&amp;quot;My pet theory is that if the person who takes the call when a customer is missing, say, the Pear Mail module, if this person is the same person who maintains the setup code, then they will eventually get sick of sshing into customers' servers and typing &amp;quot;pear install Mail&amp;quot; for them and they'll just fix it in the setup code once and for all. And I think a lot of people would find a job that combines problem solving with new software development is going to be pretty interesting,...&amp;quot;  - Joel Spolsky&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I agree 100% with Joel's theory on having the software developers also be the customer service department.  I don't deal directly with external clients, but I do have to fix problems when things break.  As a result, I like to fix them the first time so that I don't have to deal with it again.&lt;br /&gt;&lt;br /&gt;It's a beautiful feeling when you can solve a problem the first time for N cases where N -&gt; INFINITY!  &lt;br /&gt;&lt;br /&gt;As long as the business model empowers software developers to actually implement these solutions, this organizational style will be successful.  I feel that I have this level of freedom at my company, and I'm fairly certain that this level of freedom exists at Fog Creek.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-6927638400498717454?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/6927638400498717454/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=6927638400498717454' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/6927638400498717454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/6927638400498717454'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2008/03/quoted-from-joel-on-software-some.html' title='Technical Customer Service'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-439768447245971231</id><published>2008-03-13T20:46:00.000-07:00</published><updated>2008-03-13T20:48:50.852-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Firefox development'/><category scheme='http://www.blogger.com/atom/ns#' term='Business'/><category scheme='http://www.blogger.com/atom/ns#' term='Greasemonkey'/><category scheme='http://www.blogger.com/atom/ns#' term='HTML Signatures'/><category scheme='http://www.blogger.com/atom/ns#' term='Gmail'/><title type='text'>Multiple HTML Reply Signatures for Google Apps</title><content type='html'>&lt;h2&gt;Gmail HTML Reply Signatures Greasemonkey Script&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;The company I work for uses Gmail for email communications.  Specifically, the service the company uses is part of the &lt;a href="http://www.google.com/a/help/intl/en/index.html" target="_blank"&gt;Google Apps&lt;/a&gt; bundle of services, and it's the same service that I use for my blog email.   &lt;br /&gt;&lt;br /&gt;As many of you may know, custom signatures through Gmail can't contain HTML by default.  However, &lt;a href="http://blog.opensourceopportunities.com/2007/06/html-multiple-reply-signatures-for.html"&gt;HTML Multiple Reply Signatures for Gmail&lt;/a&gt; solves this by using the Greasemonkey engine to inject HTML into the page.  The HTML Multiple Reply Signatures Script (and Firefox Extension) injects a drop down list to the left of the Gmail editor where a user can select from up to four customized HTML signatures, which will be injected into the Gmail editor.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;History of Gmail HTML Multiple Reply Signatures&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;About a year ago, I integrated the &lt;a href="http://blog.opensourceopportunities.com/2007/02/gmail-html-reply-signatures.html" &gt;HTML Reply Signatures script&lt;/a&gt; into our company's global Windows profile.  Since the global profile was shared across most of the company workstations, I created a DOS batch script that took the user's Windows login details from a workstation PC and generated the Greasemonkey script using this information.  The generated script on each workstation is exactly the same, except for the filename of the signature image to use.  The constraint is that all of the images must use a standard naming convention and all be located on the same public server.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Reliable Gmail HTML Signatures Solution&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;This solution has worked out quite well.  It has been very stable and reliable in the last year and has required absolutely zero maintenance.  Now that we have a need for certain people to have more than one signature card, I suggested that one of our managers install the HTML Multiple Reply Signatures Greasemonkey script.  So far, he's pretty satisfied with it.  &lt;br /&gt;&lt;br /&gt;Not being on the global profile made this much easier; otherwise, I would need to write a new batch script that generates the HTML Multiple Reply signatures script instead of the HTML Reply Signatures script, which can only handle injecting one signature.  In addition, not being on the global profile means that he could essentially name the image files whatever he wants, as long as he modifies the signature HTML in the script to point to the correct filenames.&lt;br /&gt;&lt;br /&gt;I recommended the script instead of the Firefox Extension for three reasons:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;The script is actually more reliable and bug-free than the Firefox Extension.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;This particular manager is technically adept and fully capable of modifying the script himself to configure new signatures.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Google Apps Gmail is not using Gmail's &lt;a href="http://blog.opensourceopportunities.com/2007/11/google-releases-new-version-of-gmail.html"&gt;New Interface&lt;/a&gt;, so it has not been susceptible to the same bugs that standard Gmail users have faced.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h2&gt;New version of Gmail&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Once Gmail moves these customers to the new version, we're likely to see problems.  I wonder why they haven't done this yet.  The bigger question is, with my organization's growing use of this particular tool, should we prepare for the change by using a plug-in that supports the new interface?  &lt;br /&gt;&lt;br /&gt;At any rate, it was cool to see the script being used in my own organization!  It may be a good idea to seriously consider moving the script to &lt;a href="http://code.google.com/p/gmail-greasemonkey/wiki/GmailGreasemonkey10API" target="_blank"&gt;Gmail's Greasemonkey API&lt;/a&gt; to support the new interface.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-439768447245971231?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/439768447245971231/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=439768447245971231' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/439768447245971231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/439768447245971231'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2008/03/multiple-html-reply-signatures-for.html' title='Multiple HTML Reply Signatures for Google Apps'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-9101838722107026476</id><published>2008-03-05T22:28:00.000-08:00</published><updated>2008-07-05T15:11:30.405-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Operating systems'/><category scheme='http://www.blogger.com/atom/ns#' term='Cross-platform'/><category scheme='http://www.blogger.com/atom/ns#' term='Data Loss Prevention'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><title type='text'>500 Gigabytes of Relief</title><content type='html'>&lt;h2&gt;Backup Humor&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;I just bought a Seagate OneTouch 4 Maxtor 500GB external hard drive.  The hard drive is marketed for backup purposes and comes with the backup software installed on the hard drive.  Below is a note included in the instructions for step 2:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic"&gt;Note:  It is highly recommended that you copy the current contents of the OneTouch 4 to your computer before proceeding.  Reference Seagate Knowledge Base article 4169 for more information.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It doesn't inspire confidence to know that I have to backup the software on the backup drive in case something goes horribly wrong.  If the unthinkable does happen, the backup software is the least of my worries.  I'm not too concerned.  The really important things will be backed up on a CD or a DVD.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Solution to my Software Backup Problems&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;Having this hard drive will solve a big problem that I have.  Lack of space.  With two Linux installations, Windows XP, and several Virtual PC images, my 160GB internal hard drive has reached capacity.  &lt;br /&gt;&lt;br /&gt;This has led to many other problems that all stem from lack of space.  I want to try more distributions of Linux, but I have so much data spread out on different partitions that I was afraid I might lose something important if I tried to install the latest version of Ubuntu or SUSE.  Now I am free to proceed with an upgrade.&lt;br /&gt;&lt;br /&gt;I also wanted to be able to convert my Virtual PC images to VMWare as part of the &lt;a href="http://blog.opensourceopportunities.com/2007/10/microsoft-quit-date.html"&gt;Microsoft Quit Date&lt;/a&gt;.  This has not been going as well as I've planned, but it hasn't been going bad.&lt;br /&gt;&lt;br /&gt;I am using the Mozilla Thunderbird Extension Lightning for my Calendar application; however, I'm still using MS Outlook for email.  If I can get a solid Linux distribution running then this will help reduce my dependence.  At the moment, &lt;a href="http://www.pandora.com" target="_blank"&gt;Pandora&lt;/a&gt; is the only music that I have in Linux.  I had MP3 support briefly, but for some reason G-Streamer is complaining about missing something.  &lt;br /&gt;&lt;br /&gt;Don't get me wrong, I like troubleshooting broken software, but not my music player.  I just want that to work.  I don't care why it broke, or why Novell didn't include it by default, after fixing it once and having it break, I am at a point where I just want to hear music without having to read a bunch of knowledge base articles.&lt;br /&gt;&lt;br /&gt;However, overlooking media player issues, there are a ton of advantages to using Linux.  As a programmer, it is 10 times easier to get things done.  Web programming isn't the same when loading a local file in the browser.  You're not using http when you do this, you're using the file protocol.  AJAX, as well as other techniques, behave completely different under this scheme.  To get an accurate idea of what a JavaScript library or technique will do when served on a web server, you need a development platform that mirrors this environment.  In Linux, I can configure Apache, PHP, even Java's Tomcat servlet container, in under 30 minutes.  In Windows, I'm not as confident. &lt;br /&gt;&lt;br /&gt;I can also use tools like grep, vi, and locate in Linux.  In Windows, I am lost without these.  The cute puppy that appears in Windows Search is cool and all, but I don't have all day to search for a string in a file in the file system, I just want results.  Grep gives almost instant results.  Sure, there's no puppy, as my 7 year old nephew would say, but it's fast.&lt;br /&gt;&lt;br /&gt;Little by little, I have been moving data to the hard drive.  In the next couple weeks, I hope to have SUSE 10.3 installed on a partition.  I might also install Ubuntu.  We'll see what happens.&lt;br /&gt;&lt;br /&gt;Oh, and in case something happens to the hard drive, don't worry!  I've backed up the backup software on my computer.  Now you can sleep at night.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic"&gt;UPDATE (7/5/2008):  I installed Ubuntu 8.04 last month and love it!  I also &lt;a href="http://blog.opensourceopportunities.com/2008/07/share-vmware-image-between-dual-boot.html"&gt;share a VMWare Image with Windows using VMPlayer on Ubuntu&lt;/a&gt;, which is a great alternative and enhancement to dual-boot setups.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-9101838722107026476?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/9101838722107026476/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=9101838722107026476' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/9101838722107026476'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/9101838722107026476'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2008/03/500-gigabytes-of-relief.html' title='500 Gigabytes of Relief'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-4744505728157011448</id><published>2008-01-12T12:16:00.001-08:00</published><updated>2008-12-10T07:24:18.301-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Data Loss Prevention'/><title type='text'>Data Loss Prevention Tips</title><content type='html'>Oops! &lt;br /&gt;&lt;br /&gt;That's the sound of the second most common type of data loss!  We've all done it at one point or another.  No matter what industry you are in, whether it be software development, information technology, automotive repair, or homemaking, you've most likely experienced some form of data loss caused by some form of human error.  &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-WAA3c7s8sQ/R1r5nbNr3AI/AAAAAAAAAEI/JS7qe4voZKg/s1600-h/data-loss-pie-chart-oops.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_-WAA3c7s8sQ/R1r5nbNr3AI/AAAAAAAAAEI/JS7qe4voZKg/s320/data-loss-pie-chart-oops.JPG" border="0" alt="Most common types of data loss" id="BLOGGER_PHOTO_ID_5141696380312214530" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;According to several resources, this type of data loss accounts for 32% of all data losses and trails behind hardware failures, which account for 44% of all instances of data loss.  (I'm not going to bother to cite my sources; just simply search for data loss statistics and you'll see numbers very close to these.)&lt;br /&gt;&lt;br /&gt;The sad thing is, data loss can be prevented.  In fact, many people have made a lot of money developing backup solutions to help protect consumers and industries in the event that a data loss does occur.&lt;br /&gt;&lt;br /&gt;But I'm not promoting backup software.  Yes, backup software is important, but I think that there are other factors that are important to consider.  I've come up with a list of suggestions which can be utilized to help protect you from data loss.  I work in software development, so many of these suggestions will apply to my field.  However, the concept is the same.  Set yourself up for success, and protect you from yourself!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Data Loss Prevention Tips&lt;/h2&gt;&lt;br /&gt;&lt;h3&gt;Data Loss Prevention Tips for writing SQL Statements&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;SQL is not designed for human consumption.  In fact, the Linux command line is more user friendly than SQL.  Most of the tools that we use on computers are designed with functionality to help protect us from ourselves, but not SQL.&lt;br /&gt;&lt;br /&gt;SQL, or Structured Query Language, is a syntax used by developers and database administrators to modify the structure and data contained within a database.  While SELECT statements are relatively harmless, most other types of statements can be extremely hazardous to the health of your data.&lt;br /&gt;&lt;br /&gt;Consider this statement that may be used to update a balance in a bank account table:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;update accounts.checking set balance='100.00' where accountnumber='12345678';&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The above statement will change the balance in account 123456789 to $100.00.  Let's assume that there are 1,000,000 accounts in this table.  With this statement, we updated a single customer's account.&lt;br /&gt;&lt;br /&gt;Next, consider the following statement:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;update accounts.checking set balance='100.00';&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The above statement is missing a very important piece.  Without a where clause, the &lt;span style="font-style:italic"&gt;entire&lt;/span&gt; list of account balances is changed to $100.00!  This is a major, catastrophic error!  &lt;br /&gt;&lt;br /&gt;No single customer has the same banking habits or account balances as another customer.  Some people are constantly overdrawn while others have savings in excess of thousands of dollars.  Some have balances that remain fairly constant while those with debit cards tend to have more dynamic account balances.  Not only is a restore going to be necessary, but it must be coordinated with the fact that banks are a 24 hour a day 7 day per week business, and the restore will need to account for these changes as well.&lt;br /&gt;&lt;br /&gt;In my experience, the single most common cause of these types of SQL errors is that the query is executed before its author finished writing it.  A colleague of mine offers a very brilliant suggestion:  Purposely embed a syntax error into your query until you are sure that all of the components are in place:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;pdate accounts.checking set balance='100.00';&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The above statement -- when executed -- will throw a syntax error.  Syntax errors are good.  They let the user know that some required component is missing in order to complete an operation.  When a syntax error occurs, nothing happens!  This occurs with a majority of tools and software that's currently in use, but not with SQL.  With SQL, a developer or DBA has an executable statement at a very critical point in the process of writing the statement.  I've never written an update SQL statement that didn't involve a where clause.  They just aren't very common, but for a brief second when writing an update statement we have a fully executable statement capable of wreaking havoc.&lt;br /&gt;&lt;br /&gt;If I were to redesign the SQL language, I would put the where clause first.  It's perhaps the single most important piece of the statement, and if it's written first, accidents should happen much less.  Here is my version of SQL:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;update where accountnumber='12345678' set balance='100.00';&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;In my example above, if I execute before finishing the query, nothing happens!  But the bottom line is that SQL isn't going to change anytime soon.  There are people out there right now that are probably laughing at the fact that I've even considered rewriting SQL.  "Just be careful", they'll say!  "Just don't screw it up".  Well, yeah!  But sometimes things aren't that simple.  Some people are built differently, and for some of us who are accident prone, we have learned techniques to adapt.&lt;br /&gt;&lt;br /&gt;This is why I followed my colleagues advice and purposely write syntax errors into the beginning of my SQL statements.  That SQL statement can't be executed until I'm ready to execute it and have thoroughly examined it.  I keep all of my SQL update and insert statements saved in this format.  Only SQL statements that I want to run will be executed.  Yes, I am still very careful, but I also rely on this safety mechanism, just in case.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Data Loss Prevention Tips in Software Development and IT&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;We run a three-tier development system at work.  Each application has its own development, staging, and live server.  The development and staging servers are connected to a staging database that mirrors the live environment, and the live server is of course connected to the live database.  &lt;br /&gt;&lt;br /&gt;In any IT-related industry, the live server is the bread and butter.  If something happens to it, expect to see a negative sign followed be several zeros on the balance sheet.  The staging database isn't important.  Sure, it can be corrupted.  If something bad does happen to it, your friendly IT department probably won't be inviting you out to lunch for a few days because they'll have to add "restore Staging database" to their to-do list, but to external customers and the bottom line, it just doesn't matter.&lt;br /&gt;&lt;br /&gt;The staging environment is a developer's sandbox to do whatever he or she pleases.  When I'm working in a development environment, that part of my brain that gets real paranoid and makes me do crazy things (like write syntax errors into my SQL statements) shuts down.  There's really nothing to break.  Play, have fun, and if something breaks, find out why and move on. &lt;br /&gt;&lt;br /&gt;However, this is an area where human error can occur.  In small companies, developers sometimes configure their own development environments.  In my case, I configured my environment to use the staging database.  I set all of my environment variables to reflect development mode.  &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Data Loss Analogy&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_-WAA3c7s8sQ/R4kedJFo5FI/AAAAAAAAAEQ/dw4H-42YX1U/s1600-h/01040601030601160820071106b71cbfcd5668236098007ef7.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_-WAA3c7s8sQ/R4kedJFo5FI/AAAAAAAAAEQ/dw4H-42YX1U/s320/01040601030601160820071106b71cbfcd5668236098007ef7.jpg" border="0" alt="Data Loss Prevention Tips" id="BLOGGER_PHOTO_ID_5154684734506853458" /&gt;&lt;/a&gt;Have you ever walked out of a store into a packed parking lot, approached what you thought was your car with the key and tried to unlock the door?  Dodge Caravans are good examples.  They're everywhere, and they all look exactly the same.  Here are some factors that differentiate them:  Color, tires, hub caps, interior, window tinting, and many more.&lt;br /&gt;&lt;br /&gt;Now, if you made the mistake of approaching the wrong minivan, you wouldn't walk up to a blue minivan if you owned a red one.  That's easy to identify the difference.  But another red minivan, with the same hub caps, the same window tinting... well, maybe this is enough to fool you.  &lt;br /&gt;&lt;br /&gt;However, no matter how close the other minivan is in comparison to yours, the bottom line is it's NOT yours, and the key just won't fit.&lt;br /&gt;&lt;br /&gt;This analogy can be applied to configurations as well.  IP addresses all look alike.  They're numbers.  They're red minivans with window tinting.  Hostnames are different.  Now you have a blue minivan and a red one.  &lt;br /&gt;&lt;br /&gt;Other criteria that can be used to help an individual quickly spot a configuration problem are passwords.  Don't use the same passwords for your staging and live environments.  You shouldn't anyway for security, but someone who tries password A on server B when they meant to login to server A is going to realize their mistake before any damage can be done.  The IT specialist who looks at the development server configuration for the new developer and sees an obfuscated password instead of the hello world password that is used on the other development servers is going to realize something is amiss and correct the problem before the new mad scientist developer conducts science experiments on the live server.&lt;br /&gt;&lt;br /&gt;It's like documenting code.  The easiest way to document source code is to use variable names that convey information to other humans about what the code does.  This way, you kill two birds with one stone by telling not only the compiler, but also people.  &lt;br /&gt;&lt;br /&gt;Example 1:&lt;br /&gt;&lt;code&gt;//Send the account balance to the user via email&lt;br /&gt; s.s(a,u);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Example 2:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;CustomerEmailManager.sendAccountBalanceToUserViaEmail(accountNumber,userId);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Documenting code in this manner works extremely well, and if it works here, it should work in other areas as well.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Data Loss Prevention by Setting Read-only Flag&lt;/h3&gt;&lt;br /&gt;A read only file can still be deleted, but if you mark it as "read only", perhaps it will make you think before going through with actually deleting the file!&lt;br /&gt;&lt;br /&gt;These suggestions are no different than things like setting that bill that has to be paid next to your car keys so that you won't leave the house without it.  The only difference is that these suggestions are for situations that are way more technical.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-4744505728157011448?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/4744505728157011448/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=4744505728157011448' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/4744505728157011448'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/4744505728157011448'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2008/01/data-loss-prevention-tips.html' title='Data Loss Prevention Tips'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_-WAA3c7s8sQ/R1r5nbNr3AI/AAAAAAAAAEI/JS7qe4voZKg/s72-c/data-loss-pie-chart-oops.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-6312615664076296251</id><published>2007-12-08T12:05:00.000-08:00</published><updated>2007-12-08T12:49:41.325-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Business'/><category scheme='http://www.blogger.com/atom/ns#' term='Collaboration'/><category scheme='http://www.blogger.com/atom/ns#' term='Web 2.0'/><title type='text'>Corporate Intranet Blogging</title><content type='html'>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.  &lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.  &lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-6312615664076296251?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/6312615664076296251/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=6312615664076296251' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/6312615664076296251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/6312615664076296251'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2007/12/corporate-intranet-blogging.html' title='Corporate Intranet Blogging'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-6874913903724708922</id><published>2007-11-27T18:44:00.000-08:00</published><updated>2007-11-27T18:45:06.291-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Operating systems'/><category scheme='http://www.blogger.com/atom/ns#' term='Cross-platform'/><category scheme='http://www.blogger.com/atom/ns#' term='Business'/><category scheme='http://www.blogger.com/atom/ns#' term='Marketing'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Collaboration'/><title type='text'>A Quarterback's Operating System</title><content type='html'>&lt;blockquote&gt;&lt;span style="font-style:italic;"&gt;"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."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     - Matt Hartley at &lt;a href="http://www.madpenguin.org/cms/?m=show&amp;id=8019" target="_blank"&gt;Mad Penguin dot org&lt;/a&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;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.  &lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic"&gt;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!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;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?&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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!  &lt;br /&gt;&lt;br /&gt;No one ever said it was illegal to make sales from open source software!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-6874913903724708922?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/6874913903724708922/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=6874913903724708922' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/6874913903724708922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/6874913903724708922'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2007/11/quarterbacks-operating-system.html' title='A Quarterback&apos;s Operating System'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-6882478017796416773</id><published>2007-11-10T10:54:00.000-08:00</published><updated>2007-11-10T11:07:28.947-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Firefox development'/><category scheme='http://www.blogger.com/atom/ns#' term='Greasemonkey'/><category scheme='http://www.blogger.com/atom/ns#' term='HTML Signatures'/><category scheme='http://www.blogger.com/atom/ns#' term='Gmail'/><title type='text'>Google Releases New Version of Gmail</title><content type='html'>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.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://googlesystem.blogspot.com/2007/11/how-to-go-back-to-gmails-older-version.html" target="_blank"&gt;How to Go Back to Gmail's Older Version&lt;/a&gt; explains more of the details regarding the new version features as well as how to switch back to the older version.&lt;br /&gt;&lt;br /&gt;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, &lt;a href="http://en.wikipedia.org/wiki/Suicide_door" target="_blank"&gt;suicide doors&lt;/a&gt;, 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!&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;I'll post pictures of the car soon!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-6882478017796416773?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/6882478017796416773/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=6882478017796416773' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/6882478017796416773'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/6882478017796416773'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2007/11/google-releases-new-version-of-gmail.html' title='Google Releases New Version of Gmail'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-7714042665158389615</id><published>2007-11-01T20:03:00.000-07:00</published><updated>2008-12-10T07:24:18.705-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Operating systems'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><title type='text'>Rebooting Linux</title><content type='html'>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.&lt;br /&gt;&lt;br /&gt;"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.  &lt;br /&gt;&lt;br /&gt;"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.  &lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_-WAA3c7s8sQ/RxWh3H0q3WI/AAAAAAAAAD4/C4vujXJvT3k/s1600-h/restart.JPG"&gt;&lt;img style="float:right; margin:25px 0 10px 10px;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_-WAA3c7s8sQ/RxWh3H0q3WI/AAAAAAAAAD4/C4vujXJvT3k/s320/restart.JPG" border="0" alt="Restart or reboot the computer" id="BLOGGER_PHOTO_ID_5122178119568645474" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;"Well, when does it need to be rebooted?", asked my coworker.  Wow!  I never really thought about it like that before.  When &lt;span style="font-style:italic"&gt;does&lt;/span&gt; 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 &lt;span style="font-style:italic"&gt;why&lt;/span&gt; Linux would require a reboot.&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;1 - When updating or patching the operating system.&lt;br /&gt;2 - When installing new software of any kind.&lt;br /&gt;3 - When it locks up or slows down.&lt;br /&gt;4 - As the first step in any troubleshooting procedure.&lt;br /&gt;5 - As a secondary, tertiary, intermediary, or final step in any troubleshooting procedure.&lt;br /&gt;6 - Automatically, when you're not looking.&lt;br /&gt;7 - As a troubleshooting step.&lt;br /&gt;8 - When an application conflicts with the system.&lt;br /&gt;9 - As a troubleshooting step.&lt;br /&gt;10 - As a trou...&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;The conversation between my coworker and I continued:  "When do we need to reboot a server?", she asked.&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_-WAA3c7s8sQ/RxbSl30q3XI/AAAAAAAAAEA/HG4CpgORlv4/s1600-h/system-reconfiguration-restart.JPG"&gt;&lt;img style="float:left; margin:25px 10px 10px 0;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_-WAA3c7s8sQ/RxbSl30q3XI/AAAAAAAAAEA/HG4CpgORlv4/s320/system-reconfiguration-restart.JPG" border="0" alt="Restart or reboot computer" id="BLOGGER_PHOTO_ID_5122513174262373746" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;"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.  &lt;br /&gt;&lt;br /&gt;"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.  &lt;br /&gt;&lt;br /&gt;"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 --", &lt;span style="font-style:italic"&gt;probably because hours are easier to remember than months, &lt;/span&gt; "but if you could type uptime at the prompt it would probably tell you that it had been running for only a few days."&lt;br /&gt;&lt;br /&gt;"Oh!  Can I try uptime?", she asks.  &lt;br /&gt;&lt;br /&gt;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'."&lt;br /&gt;&lt;br /&gt;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."&lt;br /&gt;&lt;br /&gt;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.  &lt;br /&gt;&lt;br /&gt;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.  &lt;br /&gt;&lt;br /&gt;But why risk any downtime if you don't need to?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-7714042665158389615?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/7714042665158389615/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=7714042665158389615' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/7714042665158389615'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/7714042665158389615'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2007/11/rebooting-linux.html' title='Rebooting Linux'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_-WAA3c7s8sQ/RxWh3H0q3WI/AAAAAAAAAD4/C4vujXJvT3k/s72-c/restart.JPG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-340193710281040359</id><published>2007-10-27T17:08:00.000-07:00</published><updated>2008-07-05T15:13:54.306-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Operating systems'/><category scheme='http://www.blogger.com/atom/ns#' term='Cross-platform'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><title type='text'>Using VMWare as a Cross-Platform Virtualization Platform</title><content type='html'>As part of my Microsoft Windows XP Quit Date strategy, I have been looking into using &lt;a href="http://www.vmware.com/resources/opensource/" target="_blank"&gt;VMWare&lt;/a&gt; as a replacement technology for my &lt;a href="http://www.microsoft.com/windows/products/winfamily/virtualpc/default.mspx" target="_blank"&gt;Microsoft Virtual PC&lt;/a&gt; images.  &lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.  &lt;br /&gt;&lt;br /&gt;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!&lt;br /&gt;&lt;br /&gt;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.  &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The NavCalendar Application&lt;/h2&gt; &lt;br /&gt;&lt;br /&gt;For example, I'm working on a Calendar application for &lt;a href="http://www.educateya.org" target="_blank"&gt;Ed&amp;uacute;cate Ya&lt;/a&gt;.  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 http://dev.educateya.org 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 127.0.0.1).  &lt;br /&gt;&lt;br /&gt;I configured Apache using Virtual Hosting.  I created a configuration file mapping the IP address of the VMImage and port 80 to the hostname dev.educateya.org.  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.&lt;br /&gt;&lt;br /&gt;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!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Migrating to another Operating System&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://www.vmware.com/support/pubs/" target="_blank"&gt;VMWare Converter&lt;/a&gt;, Virtual PC users can convert an image to VMware format!  &lt;br /&gt;&lt;br /&gt;After getting more hard drive space, this will be the next step in preparing to quit using Microsoft Windows XP.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Running dual-boot setups concurrently&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;While writing this piece, I stumbled upon an article that describes how to &lt;a href="http://linux.sys-con.com/read/219877_2.htm" target="_blank"&gt;Run an Existing Windows Installation on Ubuntu with VMware Player&lt;/a&gt;.  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. &lt;br /&gt;&lt;br /&gt;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!&lt;br /&gt;&lt;br /&gt;In summary, I've included a list of cross-compatible open source software that I currently use:  &lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.mozilla.com/en-US/firefox/" target="_blank"&gt;Firefox&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.mozilla.com/en-US/thunderbird/" target="_blank"&gt;Thunderbird&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.mozilla.org/projects/calendar/lightning/" target="_blank"&gt;Lightning&lt;/a&gt;&lt;ul&gt;&lt;li&gt;A Calendar application installed as a Thunderbird Extension.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;a href="http://www.vim.org/" target="_blank"&gt;Vi&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Soon, I'll add &lt;a href="http://www.vmware.com/resources/opensource/" target="_blank"&gt;VMWare&lt;/a&gt; to the list.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic"&gt;UPDATE - 7/5/2008:  I have &lt;a href="http://blog.opensourceopportunities.com/2008/07/share-vmware-image-between-dual-boot.html"&gt;configured VMware Player on Ubuntu 8.04 to share a Windows XP VMWare image with Windows XP Pro&lt;/a&gt; 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!&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-340193710281040359?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/340193710281040359/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=340193710281040359' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/340193710281040359'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/340193710281040359'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2007/10/using-vmware-as-cross-platform.html' title='Using VMWare as a Cross-Platform Virtualization Platform'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-8058858757207967736</id><published>2007-10-21T20:50:00.000-07:00</published><updated>2007-10-21T20:48:58.729-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Collaboration'/><title type='text'>PHP Navigational Calendar</title><content type='html'>I'm working on a project for &lt;a href="http://www.educateya.org" target="_blank"&gt;Ed&amp;uacute;cate Ya&lt;/a&gt; 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.  &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;NavCalendar Application - Navigational Calendar&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;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.  &lt;br /&gt;&lt;br /&gt;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.  &lt;br /&gt;&lt;br /&gt;So, I decided to build a Calendar using PHP.  I chose PHP because the &lt;a href="http://www.educateya.org" target="_blank"&gt;Ed&amp;uacute;cate Ya&lt;/a&gt; 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.  &lt;br /&gt;&lt;br /&gt;I chose XML because the list of events for &lt;a href="http://www.educateya.org" target="_blank"&gt;Ed&amp;uacute;cate Ya&lt;/a&gt; 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.&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://www.educateya.org" target="_blank"&gt;Ed&amp;uacute;cate Ya&lt;/a&gt; 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.  &lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;I plan to use the open source cross-platform software &lt;a href="http://www.gimp.org/windows/" target="_blank"&gt;Gimp&lt;/a&gt; to apply the "chrome" for the calendar.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-8058858757207967736?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/8058858757207967736/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=8058858757207967736' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/8058858757207967736'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/8058858757207967736'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2007/10/php-navigational-calendar.html' title='PHP Navigational Calendar'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-7170750351521247654</id><published>2007-10-16T23:00:00.000-07:00</published><updated>2008-12-10T07:24:18.864-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Firefox development'/><category scheme='http://www.blogger.com/atom/ns#' term='Greasemonkey'/><category scheme='http://www.blogger.com/atom/ns#' term='HTML Signatures'/><category scheme='http://www.blogger.com/atom/ns#' term='Gmail'/><title type='text'>The Gmail Dependency</title><content type='html'>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 &lt;a href="http://www.joelonsoftware.com/articles/fog0000000027.html" target="_blank"&gt;code rusts&lt;/a&gt;.  Or because the code &lt;a href="http://blog.opensourceopportunities.com/2007/07/good-code-is-like-glass.html"&gt;cracked like glass&lt;/a&gt;, but because the foundation that it depends on cracked.  &lt;br /&gt;&lt;br /&gt;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.  &lt;code&gt;ui=1&lt;/code&gt;.  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.&lt;br /&gt;&lt;br /&gt;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.  &lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;An asterisk is all it takes.  One small character, just 2 bytes of data, is enough to break functionality.  &lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;div style="float:none"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-WAA3c7s8sQ/RxWgpX0q3VI/AAAAAAAAADw/jpLYwsq-Qew/s1600-h/screenshot-gmail-sig-greasemonkey-script-bugfix.JPG"&gt;&lt;img style="display:block; margin:0 10px 0px 10px;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_-WAA3c7s8sQ/RxWgpX0q3VI/AAAAAAAAADw/jpLYwsq-Qew/s320/screenshot-gmail-sig-greasemonkey-script-bugfix.JPG" border="0" alt="Manage Email Signatures in HTML Multiple Reply Signatures For Gmail" id="BLOGGER_PHOTO_ID_5122176783833816402" /&gt;&lt;/a&gt;&lt;br /&gt;- Click the "Edit" button.&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="float:none"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-WAA3c7s8sQ/RxWgeX0q3UI/AAAAAAAAADo/tHn0j0byRrk/s1600-h/screenshot-gmail-sig-greasemonkey-script-asterick.JPG"&gt;&lt;img style="display:block; margin:0px 0 0 0px; text-align:left;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_-WAA3c7s8sQ/RxWgeX0q3UI/AAAAAAAAADo/tHn0j0byRrk/s320/screenshot-gmail-sig-greasemonkey-script-asterick.JPG" border="0" alt="HTML Multiple Reply Signatures for Gmail" id="BLOGGER_PHOTO_ID_5122176594855255362" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;- Add the asterisk where indicated by the highlighting.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;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! &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-7170750351521247654?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/7170750351521247654/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=7170750351521247654' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/7170750351521247654'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/7170750351521247654'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2007/10/gmail-dependency.html' title='The Gmail Dependency'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_-WAA3c7s8sQ/RxWgpX0q3VI/AAAAAAAAADw/jpLYwsq-Qew/s72-c/screenshot-gmail-sig-greasemonkey-script-bugfix.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4210075784363570204.post-1951112387326596118</id><published>2007-10-11T22:30:00.000-07:00</published><updated>2008-07-05T15:26:20.917-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JavaScript'/><category scheme='http://www.blogger.com/atom/ns#' term='String parsing'/><category scheme='http://www.blogger.com/atom/ns#' term='PHP'/><category scheme='http://www.blogger.com/atom/ns#' term='Greasemonkey'/><title type='text'>Nested-Nested Quotes</title><content type='html'>Larry Wakeman of &lt;a href="http://www.memorypharma.com/" target="_blank"&gt;Memory Pharmaceuticals&lt;/a&gt; recently sent me a reminder about a follow-up article that I forgot to write.  Back in April, I addressed the concept of &lt;a href="http://blog.opensourceopportunities.com/2007/04/gmail-html-reply-signatures-and.html?GoogleAnalytics=disabled"&gt;quotes within quotes within quotes&lt;/a&gt; and how to handle this phenomenon. &lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;head&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/head&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;body&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;function alertParameter(stringParameter) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   alert(stringParameter);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var topLevel = "test";&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;function generateHTML(topLevel) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   document.write("&amp;lt;a href=\"#\" onclick=\"alertParameter('"+topLevel+"')\"&amp;gt;Click this link to see the result&amp;lt;/a&amp;gt;");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;generateHTML(topLevel);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;document.write(" /* These quotes are the outer quotes */ ");&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Nested JavaScript Quotes Example 1&lt;/h3&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;document.write("&amp;lt;div onclick=\"alert('ht')\"&amp;gt;click me&amp;lt;/div&amp;gt;");&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The above example is the same as the following example:&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Nested JavaScript Quotes Example 2&lt;/h3&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;document.write("&amp;lt;div onclick='alert(\"ht\")'&amp;gt;click me&amp;lt;/div&amp;gt;");&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Also, to demonstrate that we can use single-quotes as the outer quotes, check out this example:&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Nested JavaScript Quotes Example 3&lt;/h3&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;document.write('&amp;lt;div onclick="alert(\'ht\')"&amp;gt;click me&amp;lt;div&amp;gt;');&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Take a careful look at the above three JavaScript nested quote examples.  Understanding this concept is a prerequisite to understanding deeper JavaScript nested quotes.&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Nested JavaScript Quotes Example 1&lt;/h3&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;document.write("&amp;lt;div onclick=\"alert('ht')\"&amp;gt;click me&amp;lt;/div&amp;gt;");&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;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):&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;div onclick="alert('hi')"&amp;gt;click me&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;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. &lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Nested JavaScript Quotes Example 4&lt;/h3&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;document.write('&amp;lt;div onclick="alert(\'ht\')"&amp;gt;click me&amp;lt;/div&amp;gt;');&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;JavaScript Inner, inner quotes&lt;/h2&gt;&lt;br /&gt;&lt;br /&gt;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.  &lt;del&gt;Instead, from this point forward, nested quotes must alternate between single and double quotes.&lt;/del&gt;  Below is an example:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;head&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/head&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;body&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;function alertParameter(stringParameter) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   alert(stringParameter);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var topLevel = "test";&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;function generateHTML(topLevel) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   document.write("&amp;lt;a href=\"#\" onclick=\"alertParameter('Say \\'Hello World\\'')\"&amp;gt;Click this link to see the result&amp;lt;/a&amp;gt;");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;generateHTML(topLevel);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Say 'Hello World'&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;(" ... onclick=\"alertParameter('Say \\'Hello World\\'')\"&amp;gt; ... ")&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Outer quote = "  (This marks the beginning and end of the string)&lt;br /&gt;Inner quote = \"  (Escaped as to not flag "beginning/end of string")&lt;br /&gt;Third-tier quote = '  (Literal quote)&lt;br /&gt;Fourth-tier quote = \\'   (Literal quote that will be generated as an escaped outer quote)&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;script type="text/javascript"&amp;gt;document.write("&amp;lt;a href=\"#\" onclick=\"alert('Say \\'Hello World\\'');\"&amp;gt;click here&amp;lt;/a&amp;gt;");&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;? echo "&amp;lt;script type=\"text/javascript\"&amp;gt;document.write(\"&amp;lt;a href=\\\"#\\\" onclick=\\\"alert('Say \\\\'Hello World\\\\'');\\\"&amp;gt;click here&amp;lt;/a&amp;gt;  \");&amp;lt;/script&amp;gt;'"; ?&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;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!&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://www.opensourceopportunities.com/htmlmultiplereplysignatures.user.js" onclick="javascript:urchinTrackerWrapper('/downloads/htmlmultiplereplysignatures.user.js');"&gt;Multiple HTML Reply Signatures Embedder for Gmail&lt;/a&gt; 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!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4210075784363570204-1951112387326596118?l=blog.opensourceopportunities.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.opensourceopportunities.com/feeds/1951112387326596118/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=4210075784363570204&amp;postID=1951112387326596118' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/1951112387326596118'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4210075784363570204/posts/default/1951112387326596118'/><link rel='alternate' type='text/html' href='http://blog.opensourceopportunities.com/2007/10/nested-nested-quotes.html' title='Nested-Nested Quotes'/><author><name>James Mortensen</name><uri>http://www.blogger.com/profile/14761411429474089032</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='07776848407177990347'/></author><thr:total>12</thr:total></entry></feed>