Old Dogs

I wrote my first line of computer code in 1977, 43 years ago as of today. Back then, when I was 13, a friend and I would go to our local Radio Shack store after school or on the weekend and fool around with the TRS-80 they had on display. We were end users, loading games from the cassette “drive” connected to the machine, but we both had the desire to make the computer do something more. We wanted to make it draw pictures!

A few weeks later, my friend’s father bought a TRS-80 for his son. Victor and I spent the day learning to use it. We immediately sat down and started writing WET code, bugs, and printing it all out on a dot-matrix printer to make sure we had typed it in properly. I remember I went to his house shortly after lunch. By dinner time, after not having left his room for hours, our progress was, well, about what you would expect from two kids who had never done a programming tutorial in their lives (because they didn’t exist) and who were not terribly fond of RTFM.

After all those hours, the only thing we’d managed to make the computer do was draw an outline of a house on the screen and save the instructions on the cassette. IIRC, we were so uninformed about programming that our program consisted of something like: GO TO 1,1; PRINT 1; GO TO 1,2; PRINT 1; GO TO 1,3; PRINT 1, etc. until we’d managed to turn on every pixel in the form of an outline of a house. Needless to say, fourteen years passed before I attempted programming again.

New Tricks

In 1991 I bought a Mac LC with 4MB of RAM and a 20MB hard drive (and a color monitor, which was a novelty at the time). It came with HyperCard (“magic“) and my employer at the time gave me a licensed copy of Macromedia Director 3.1! Although Director could barely run on my low-powered Motorola 68020 processor, my world was changed forever, and for the better.

Over the course of 4 years I produced a bookkeeping system to balance my checkbook in HyperCard, two interactive multimedia games for learning Spanish in Director, and even ventured down the path of trying to write a document versioning system in HyperCard (so students could see how their documents were changed after a teacher’s review – I gave up pretty quickly on that one). And then in 1995 I received a copy of Claris Home Page, and again, my life would never be the same ever after.

Another Old Dog

In 1996 I was asked to build more than a few web sites. I soon realized that Claris Home Page, although it was actually a reasonably good WYSIWYG editor, was not the right tool for interactive sites or sites consisting of more than a few pages. I started hearing about Perl and then soon after, PHP, and this really frightening thing called Linux (and open source – shareware had existed for a while, but licensed open source was still relatively new to me).

In 1998 I created my first interactive web site that included a proper (open source) search engine. I was so fascinated by it I started to participate on the mailing list, trying to help others to understand and make use of it. I even wrote a bunch of classes in PHP that abstracted the ht-://dig interface and published them on phpclasses.org. ht-://dig really was my first experience working on an open source project but all I did was participate on the mailing list, test beta versions, and create a Mac OS X package to facilitate installation. I didn’t submit patches (what we used to call pull requests) and certainly didn’t have any kind of write access to the repo (which was probably in CVS IIRC).

Fast Forward 20 Years

Since those early years I’ve “contributed” to a variety of open and closed source projects including Sequel Pro (financial support and translations), Dreamweaver (I was a beta tester in the late 1990s), BBEdit (PHP Clippings, I’m even in the credits on that one), PHP Documentation, PHP Fusebox (a PHP port of the Cold Fusion Fusebox web application framework), and more, a lot more, more than I can actually remember TBH.

But over all these years I’ve never, ever submitted a pull request, until now!

I’ve been an avid user of wp-cli for years. I’ve been active on and off on the Slack channel and tried to report bugs and suggest changes but never went all the way. A year ago, when I was first experimenting with the wp scaffold plugin-tests command, I discovered an irregularity that I found frustrating, and finally reported it. Months went by with apparently no action on the bug (but the maintainers didn’t close the bug, to their credit). A few weeks ago another user chimed in with signs of similar frustration and I decided it was time to do something about it.

I read some instructions on how to submit a pull request and low and behold, I got some traction. James Nylen reviewed my code and left some suggestions on how it could be improved. I followed his lead and submitted my changes. Then, the principal project maintainer, Alain Schlesser, chimed in with more changes, which I addressed as best I could. This back and forth went on for a few weeks and finally, my pull request has been accepted and merged onto master. My first PR at 55 years young!

Lessons Learned

  1. It really is never too late
  2. Every action paves the way to the future
  3. Go easy on maintainers. It’s often a thankless job, so be sure to thank them along the way.

I’m feeling empowered now and you know what they say: a little knowledge is a dangerous thing… If you’re an open source maintainer and you’re reading this now, be prepared. I’m coming your way!

Current version of saywire.com.

Current version of saywire.com.


  • Among the first social Network for Minors
  • Live in 2007


Saywire is one of the first social networks for minors complying in large part with COPPA. In fact, it was started even before the term social network came into common use. My company was hired to provide remote web application development services, both front and back ends. We set up and maintained the code repository and automated deployment into staging and production environments, including the ability to roll back if needed. We provided PHP and corresponding MySQL, HTML, and JavaScript for large portions of early versions of the web site and provided input on how best to use the Fusebox web application framework.


Early versions of saywire.com were based on Fusebox in a LAMP environment. We used Subversion as our code repository and incorporated a variety of client-side technologies (CSS2 and JavaScript).


Desde verano de 2009 he estado desarrollando la tienda web de Carolan, una tienda de disfraces y otros artículos de fiesta con sede en Las Palmas de Gran Canaria. Ya he perdido el control de las horas totales que he invertido en este proyecto porque se ha convertido en una obsesión por cumplir con las “mejoras prácticas” (best practices).

El pensamiento corriente dice que cuando uno quiere montar una tienda web, coge el sistema de software libre de moda y la monte sin más. La alternativa (desarrollar una tienda a medida, desde cero) seguramente me habría costado el doble, ¿o no? De esto se trata este artículo…

Carolan vende artículos de fiesta y productos de un solo uso. Tienen una gran variedad de artículos como disfraces, copas, servilletas, guirnaldas, decoraciones y mucho más. En realidad tienen más de 20.000 artículos catalogados. Cuando empecé a trabajar con el equipo de Carolan, uno de sus principales deseos era crear una conexión “viva” entre su base de datos y la tienda web para minimizar gastos e incrementar la eficacia. Otro deseo importante era que la web fuera fácil de usar (y los artículos fáciles de encontrar) y dinámica con una portada que variara según la temporada y que la tienda saliera bien en los resultados de los buscadores.

Analizando sus deseos / necesidades determiné que la mejor opción era la adopción de una tienda de software libre. Creía que me ahorraría montón de tiempo pero ahora no lo tengo tan claro y quiero saber qué opinas tú. Aquí resumo las modificaciones que se han tenido que hacer desde que empecé con la instalación de la tienda. Ten en cuenta que no detallo TODAS las modificaciones sino las más gordas / importantes.


Por defecto Zen Cart viene con una opción que te permite hacer las URLs “search engine safe” (legibles a los buscadores). Básicamente convierte
(o algo por el estilo). No está mal pero hoy en día este tipo de transformación no es necesaria.

Lo que sí quería era convertir la URL en algo como /disfraces-y-complementos/disfraz/adulto/mujer/disfraz-abeja-adulto.html para tener palabras claves en la URL. Lo logré con un par de modificaciones al código base de Zen Cart y algunas transformaciones via mod_rewrite. Me ha costado perfeccionar el método pero de momento parece estar funcionando más o menos bien.

Etiqueta Title

El valor de la etiqueta Title por defecto de Zen Cart no se presta a una buena indexación por parte de los buscadores. Tuve que modificarla unos cuanto sitios para que fuera siempre único (no repetido) ya que valores repetidos minimiza la usabilidad.

Optimización de Velocidad y de Código Fuente

Cada vez más la velocidad de una web determina su ranking dentro de los resultados de una búsqueda. He intentado cumplir con todas las sugerencias de Yahoo! and Google referente mejorar la velocidad de la web. Según mis cálculos, la web empezó cargándose en 7 segundos (sin cache, incluyendo lentitud de la red). Tras estos cambios, las peticiones terminan en menos de 1.5 segundos y para implementar estas sugerencias tuve que tocar:

  • el diseño general: se implementaron sprites, se combinaron hojas de estilo y ficheros .js
  • el diseño del perfil de un artículo (minimicé la cantidad de HTML generado por la tienda)
  • el diseño del buscador (se mejoraron el diseño de los enlaces a las páginas siguientes, se modificó la presentación de resultados, se modificó la etiqueta Title de los resultados para incluir los nombres de los productos y no solo el número de la página, se creó un Índice de productos)
  • se modificó el diseño, y el proceso, de “checkout” (pasar por caja)
  • se eliminarón los caracteres “codificados” (á se convirtió en á)
  • se redujo el número de peticiones por página de 40~ a menos de 20
  • se implementó el uso de dominios sin cookies y de una Red Distribuidora de Contenidos (Content Distribution Network – CDN)

En fin, tras todos estos cambios y teniendo en cuenta que sólo utilizan un método de pago, me pregunto si realmente me he ahorrado algo usando zen-cart (lo cual supuso una inversión de tiempo para aprenderlo). ¿Qué opinas tú?

A new version of the PHP BBEdit Clipping Set is available for download (for free) immediately:


HIGHLIGHT: The new set contains more than 9,200 clippings (that’s about 3,000 more than the previous version).

Changes in this version

– all clippings (optionally) conform as closely as possible to the Zend/PEAR style guides

– removed hundreds of duplicate clippings (mostly constants)

– removed “cruft” (primarily from Snippets and Control Structures)

– reorganized clippings into more logical folder structures

– based this set on a very recent version of the manual

– the set now includes more than 9,200 functions, constants, methods, properties, snippets, control structures and more

– added additional “interactive” functionality to some date functions (I could never remember exactly which switches to use when formatting dates)

– the set now includes class methods and properties

– renamed the clipping set to just “PHP.php” (except for the “Loose” version, see page for details)


I hope you enjoy and be sure to let me know if you find any bugs or have any requests for improvement!


Ted Stresen-Reuter

I recently implemented a newsletter subscription form in ASP.NET (2.0) for the CGIAR Secretariat on behalf of CGNET. This is the second project I’ve done in ASP.NET for CGIAR. I’ve never considered myself a skilled ASP developer and like many, picked up my ASP skills based on code I’d seen on the intertubes and via transfer from related languages. In other words, prior to this project, I was a somewhat capable ASP spaghetti coder.

Tired of producing mediocre code and eager to learn what this whole .Net thing was all about, I decided to invest some time learning how to write better ASP and take advantage of as many features of .Net as I could. Armed with two really good books on the subject (Beginning ASP.NET 3.5 in C# and VB and Programming ASP.NET 3.5, 4th Edition), I learned a lot about the .Net revolution and in the end I significantly improved the quality of my code.

DOT.NET borrows heavily from other MVC-like frameworks. I was surprised by the number of similarities between the ASP.NET-way of doing things and the Fusebox-way of doing things. The rest of this post examines some of these similarities and other aspects of working with ASP.NET. This is mostly an examination of ASP.NET from a (PHP) Fusebox developers point of view.

The Project

The CGIAR Secretariat is responsible for www.cgiar.org. The CGIAR Newsroom is one of the primary
sections of their web site. It includes an aggregate RSS news feed of all news items coming out of many of the CGIAR centers. Since many people still are unaware of the advantages of RSS, the CGIAR Secretariat asked if we could set up a system that would allow people to subscribe to the feed via email. Specifically, the system we set up allows people to subscribe and/or unsubscribe via cgiar.org which then automatically sends periodic emails of recently added news items (as they’re added, of course).

The Bottom Line

As an “experienced” web application developer I very much appreciated the ASP.NET-way of doing things. There was nothing in this project that ASP.NET wasn’t able to handle elegantly and more or less efficiently. The project consisted of implementing the following features:

  • A public subscribe and unsubscribe form with CAPTCHA
  • A nightly script that produces a notification email, with alternate views (plain text and html), consisting of news items that had not been sent in prior emails (which implies keeping track of what’s been sent and what hasn’t)
  • A password protected administration interface

The entire project was completed in about 80 hours (including an initial version of the administration interface which was later tabled).

If given the choice of doing the same project in PHP Fusebox, assuming I had the same knowledge and experience with PHP that I had with ASP when I started, would I have chosen PHP Fusebox over ASP.NET? Maybe…

Master Pages

One of the goals of any application framework is to maximize code reuse (and conversely, minimize code duplication). Functions (methods) are one example of how this is accomplished, but when it comes to the presentation level, developers often find they need a more powerful programming model. Both ASP.NET and Fusebox (and many other web application frameworks) provide tools
capable of complete solutions. In ASP.NET, a Master Page is a template for all the pages of a site although its functionality goes beyond a simple templating engine. Master Pages also let you define “behaviors” common to all pages, similar, somewhat, to the Fusebox 3 fbx_Settings file or the Fusebox 4 fusebox.init file.

A powerful templating engine will frequently go beyond “one layer” and allow the developer to subdivide sections of the Master to be handled by other parts of the application. ASP.NET offers this functionality directly and at least one project I’ve worked on in Fusebox had the same functionality. I found a few opportunities to use this feature on this project.

Fusebox does not offer a templating engine out of the box, but you can easily create much of this capability in Fusebox 4 (and to some degree in Fusebox 3) using Content Variables and a “layout” circuit. Most projects I work on offer some such circuit.

In the end I got a lot of milage out of Master Pages for this project and hope to be able to use them in future projects for CGIAR.


By default, every ASP.NET page contains a form that executes on the server. The value of the “action” attribute for the form is the current file. Microsoft has termed this approach “postback” because you post the form back to the same document that created it. In some respects this is similar to the Fusebox implementation of the Front Controller design pattern, where every request is for the same server-side script (e.g.: /index.php) followed by a Query String containing directions on what files, functions, and procedures to execute.

ASP.NET offers the developer server-side elements knows as panels. Panels are “controls” (elements?) that contain other controls. By setting the visible property of a panel you can control whether or not its contents are visible on the page. For the CGIAR project mentioned above, I used this technique to display either the subscription form or the “thank you” message following a successful subscription. I suppose that, if each ASP.NET page is the equivalent of a Fusebox circuit, that each panel could be the equivalent of a Fuseaction. You would simply set the display for all for all of them to false (except the default fuseaction 😉 ) and then display them as needed. Coming from Fusebox, I found the concept very easy to grasp.


Microsoft made an attempt to separate application logic from presentation with DOT.NET. In my opinion, they succeeded.

In order to minimize the amount of raw code found in HTML, .Net provides something known as “code-behind” pages, which are essentially includes with the same name as the file they are attached to. The idea is that your application code goes in the code-behind page and if you need to modify the presentation (the HTML) from within the application code, you do so by referencing elements in your HTML page via their ID attribute (this is an oversimplification but summarizes the approach).

Fusebox, on the other hand, tries to separate code by prefixing file names with one of dsp_, qry_, act_ (and sometimes lyt_).

  • qry_ files contain datasource queries and (usually) return some sort of object or array echoed to the browser by a dsp_ file.
  • act_ files are for those instances in which you need process data prior to executing a query or echoing to the browser.
  • lyt_ files are, in essence, the same as Master Pages in ASP.NET.

In ASP.NET the “HTML” files contain a LOT of .Net namespaced elements. This means the files can be completely valid XHTML (with the single, notable exception of the Processing Instructions found at the top of each page). The benefit is that these files are suddenly very portable and can be consumed by any system capable of reading XML.

If you wanted to reproduce this ASP.NET functionality in Fusebox, you would need to write a plug-in that parses the dsp_ files looking for <fbx: elements and responds accordingly. You could put all of your code in act_ files which would essentially turn them into code-behind files. Now there’s a potential open source time sucker!

Data Controls

As one would expect, the data controls are very complete, but figuring out how to do something like
nesting GridViews was not obvious and were it not for a Nested GridView walk-through article on MSDN, I never would have been able to figure out how to do it. Furthermore, I’m not convinced executing sql on EVERY ROW of a record set is really a good idea (the authors of the walk-through admit this is not the best approach, but only as it concerns caching…).

Much of the CGIAR Newsroom revolves around their RSS feed (which is a compilation of feeds from all of the CGIAR Centers). ASP.NET 2.0 and above include controls for using XML as a data source and thus facilitating the display of XML data in a web page.

Unfortunately, in version 2.0 of .Net (and possibly higher), using XML as a data source only allows you to display the data. It does not allow you to use the built-in INSERT, UPDATE, and DELETE
features of the GridView control. There are work-arounds for implementing this missing functionality but I have to wonder if you save any time hacking in the functionality vs. building the entire administration interface the “old” way (which can be done pretty quickly using XSLT). By my estimates, it’s a draw, at best.

ASP.NET Advantages

For my needs, web controls, validation in particular, significantly reduce web application development time. I simply cannot express how much I like the validation controls and WISH PHP had something similar!

IntelliSense greatly speeds up coding – Microsoft offers several free (web) application development tools that work quite well and are more than adequate for the projects I usually work on and many include IntelliSense.

I don’t think I could have completed this project as quickly without IntelliSense.

ASP.NET Ambiguities and Disadvantages

Since no language is free of sin, here is my list of things that got the best of me while working on this project:

  • web.config cannot be part of code repository since it is machine dependent. If application configuration options are so different between deployment environments, then maybe the author of the application should consider using a different development environment. I would prefer to have the application configuration code right in the application tucked into code that “sniffs” the environment and configures accordingly. This makes for MUCH more portable code.
  • .Net developers frequently publish their source code, but it usually needs to be compiled so unless you’re into that or have the time to learn how to do it (and do it right), you won’t find the same kind of huge Open Source community of code that exists for PHP
  • ASP.NET 2.0 includes some Authentication and Authorization controls, but like most stuff like this, you have to do things the ASP.NET-way or you can’t use these controls. In other words, there is no (apparent) way to retrofit these controls onto existing authentication mechanisms. In the end this is probably a good thing since most existing authentication methods are not very secure, but in the real world most clients simply are not willing to put money into changing existing systems unless you can clearly demonstrate they are broken.
  • One of the main complaints of Fusebox 4 was the XML files. Rather than being used simply for configuration, you could easily add business logic to them. More than one programmer has asked herself: “Why bother with XML to represent classes? Why not just use classes directly?” I must say, when programming in ASP.NET, I often feel like I’m simply setting application configuration parameters which, for anything but the most basic interactions, makes programming harder (and possibly more time-consuming) rather than easier (and faster) since you have to have a clear understanding of what state the application is in at the exact point where your code appears. This can be harder than it seems.

In the end, if I had to do it all over again (and had the choice), I would probably stick with PHP Fusebox but I’m grateful I had the opportunity to improve my knowledge ASP.NET and I wish the CGIAR Secretariat the best with their new system.

Convert ASP.NET applications into real MVC frameworks

Fusebox Basics

Comparison of Web Application Frameworks

I’ve finally updated my PHP BBEdit Clipping Set (formerly known as a glossary). The new clipping set:

  • Continues to contain around 6,000 function definitions (whatever is in the official PHP documentation)
  • Is based on a recent version of the official documentation
  • Allows tabbing between function parameters (very handy…)
  • Provides additional information when inserting a function (the return type, for example)
  • Optionally includes predefined constants for each function

Download PHP BBEdit Clipping Set

Hinshaw & Culbertson LLP Intranet Home PageHighlights

  • Role-based, Page-level Security
  • Integrated Windows Authentication
  • WYSIWYG Content Management
  • Modular Application Framework (Fusebox)
  • Firm Directory with Photos
  • Firm Calendar, News, and Links
  • Security Aware Recently Modified Block
  • Security Aware Search Engine with Support for Phrase Searching and “Best Match” Results Ranking


This is the first version of the firm’s intranet. The Managers and Directors provided the required input on the type of content they wanted on the intranet and how they hoped to be able to update it. Self-publishing was a requirement as was Role-based security. The system includes a variety of content management features like custom display order of section contents, recategorizing entire sections (and their children), attaching documents to a given section, limiting access to a section to members of administrator-defined groups and much more. The system was first released in the summer of 2002 and remains in active use.


Technical Info

The system was built in PHP with the Fusebox application framework (http://www.fusebox.org/). The database is SQL Server. Access to the database server is provided by the ADODB Database Abstraction Library (http://php.weblogs.com/ADODB/). The WYSIWYG editing functionality is provided by Interactive Tools (http://www.htmlarea.com/). The system uses the Htdig search engine (http://www.htdig.org/). The system is served on Windows 2000, IIS 5 and all pages are valid and compliant XHTML 1.0 Transitional.

Monroe Manor Condo AssociationHighlights

  • Role-based Security
  • Document Sharing System
  • Community Calendar
  • Bulletin Board Classified and Messages
  • Self-registration System for Owners


Intranet for all members of the Monroe Manor condo association. System allows site administrators (usually the president of the association or her delegate) to maintain a document repository for all types of association documents. Additionally, the management company has limited access (to help maintain the document repository) but is unable to access the user forums (so the owners can complain about the management company without their knowing about it). All owners have access to the system and can participate in a variety of ways including adding a listing for their unit if it is for sale or rent, posting other classified adds in the Garage Sale section, and commenting on any issue regarding the community in the Owners Forum. Owners can also update their profile indicating, among other things, the units they own. This was one of the first password-protected sites I ever developed (2000).

Technical Info

Written in PHP with MySQL database. Also uses the ADODB PHP database abstraction library.

Chicago PhilanthropyHighlights

  • Self-generating Table of Contents
  • Search Engine
  • Logical Site Structure


Chicago Philanthropy magazine, in circulation starting about 1996, went online in about 1998, including archived versions of every issue of the magazine. The site was created and maintained using Dreamweaver and its templating system, but the main menu was generated by a PHP script. The site structure reflected the organization of the content, e.g. /1997/01/interview.html. The site is no longer active.

Technical Info

Apache web server. Mostly static pages. Htdig search engine.

People visiting your site can easily download or copy your copyrighted images without your permission using four different methods: hotlinkingright clickingscreen shots, and web archiving.

What follows is a description of each method including:

  • counter measures for inhibiting unauthorized copying
  • methods for circumventing the counter measures
  • potential incompatibilities / issues of implementing a counter measure
  • some of the system requirements for each counter measure.


Hot Linking is when someone sets the SRC attribute of an IMG tag to an image on your web site. Besides making it look like your images are on their web page, they also consume some of your allotted bandwidth.The following is an example of the HTML one would use to display an image from susansexton.com on their own web site.

<img src="http://www.susansexton.com/images/horse1.jpg" alt="" />

Counter Measures
Limit display of images to users who are visiting your site (your domain). This is accomplished by implementing two server-side technologies: Sessions and custom File Handler rules.

When a user first visits your site, they are sent a cookie that uniquely identifies them. Before each image is sent to the browser, the system checks to see if the cookie has been set. If it has, the image is sent. If it hasn’t, no image is sent. This method requires users to view your images in the context of a web page on the first visit. From that point on, they can, theoretically, access the images directly by entering the image’s SRC attribute in their browser’s Location bar.
Custom File Handler Rules
This method can be modified so that images can only be viewed in the context of a web page. This is accomplished by telling the web server to handle image files using a custom script. The custom script looks for a unique key in the Session variable. If the key exists, the image is served. If not, it’s not.In practice, we set the key at the start of the page. The server then sends the image and destroys the key immediately after the image has been sent. If the key doesn’t exist, the images cannot be viewed and thus, cannot be viewed except in the context of a web page. This is accomplished in Apache by adding the following two lines to .htacces (for the directory you wish to protect):
Action blockhotlinking /hotlinkcheck.php
AddHandler blockhotlinking .jpg .jpeg

where hotlinkcheck.php is a PHP script that does what we’ve described.

Any anti-hotlinking counter measure incorporating both of these techniques will be very successful.

Circumvention Techniques
This technique can be circumvented by hacking the server, which is not the kind of activity people seeking to copy pictures are likely to engage in. This technique may also be circumvented by Web Archiving programs, but in our experience, if the script is written correctly, even these programs can be prevented from siphoning the images.
Potential Incompatibilites/Issues
Such a system makes designing the pages difficult because all images are “generated” on the fly and thus, cannot be viewed in the standard WYSIWYG HTML design program (such as Dreamweaver of GoLive). This system can be used, however, with automated image gallery creation tools such as iView Media Pro. Click here for more information. Also, users who don’t accept cookies will experience problems too. In fact, people with hotmail.com email accounts frequently experience problems since by default, Internet Explorer for Windows doesn’t allow framed documents from another domain to send cookies. The work-around is to include some JavaScript that breaks your site out of frames (keeps your site from being framed by someone else).

System Requirements

 Any server that can be configured to handle image files using a custom script or with some sort of server-side scripting capabilities.This system does not require the GD library but could benefit from having it available.
Cookies are used by default, but the system can be configured to use a transparent ID in cases where cookies are not allowed.

Right Clicking

Users can right click on an image and choose to save it on their computer. This is the same as dragging the image to the desktop.
Counter Measures
There are four counter measures that can be used to inhibit right clicking or dragging and dropping of images: Spacer w/ Background Image, JavaScript Hide Source, Microsoft Meta Tag, and A Thousand Images. These counter measures can be used together or separately as they each address a different aspect of the right click feature.

Spacer w/Background Image
This is my personal favorite technique because it is widely supported, does not require any special JavaScript, fools most attempts at copying the image, can be used in a WYSIWYG HTML editor, and when used in conjunction with the hotlinking counter measures, is nearly foolproof. Basically, each image is displayed as a transparent GIF whose size and background image is set to the image you want to display. The result is that the user sees the image as she normally would, but when she tries to right click to save the image, she ends up saving the clear GIF rather than the actual image.
JavaScript Hide Source
Using JavaScript, the functionality of the right mouse button can be altered to prohibit downloading of images. It can also be used to hide the source code of a page so that the user can not navigate directly to the image outside the context of the actualy page. Because this is a very complicated topic, no examples of how to do this are provided here. Regardless, here are a couple of links in case you’re interested: hide source code and disable right click.
Microsoft Meta Tag
This doesn’t really disable right clicking, but it does disable the Microsft “Image Bar” that appears when Internet Explorer (version 6) users hover their mouse over an image. Simply put this code in the HEAD element of your web pages:
A Thousand Images
Adobe ImageReady (the web companion to Photoshop) allows you to slice images up into little pieces. You could slice each image up into individual pixels making it very time consuming to download each pixel and recreate the image. This may be more practical than it seems…
Circumvention Techniques
To view the source of a page that is using JavaScript to hide the source, you can either enter this into the location bar and press Enter: java script: alert ( document.body.innerHTML ); or you could visit the site with Mozilla and use the DOM Browser to view the source code as a Document Object Model tree (and thus see the SRC attribute of the image you are after) to get at the image directly.To view an image that is being protected by an invisible GIF (the first method on this page), just look at the source and point your browser to the actual image you wish to download (and the image will appear in isolation in its own window).There is no way, that I’m aware of, to circumvent the capturing of an image that’s been split into a thousand pieces, except downloading them one by one.
Potential Incompatibilites/Issues
Incompatible JavaScript versions: It is very, very difficult to write JavaScript code that works the same on all browsers and platforms. In all likelihood, any script you find or write yourself, will fail in one environment or another. Incompatible CSS/browser: Not all browsers will know how to display background images. Failure to do so means the users won’t see your image.
System Requirements
In any situation where JavaScript is required, you must include the tags with some sort of content that explains why JavaScript is needed.Similarly, you may need to test wheter or not Cascading Style Sheets in enabled before displaying your page, if you want to be sure that your visitors see what you intend.

Screen Shots

The user presses PrtScr (Print Screen) on Windows or Command+Shift+3 (or 4) to capture the computer display as a separate image. On Windows systems, the screen is on the clipboard and needs to be pasted into an application before it can be viewed. On the Macintosh, the screen is saved as a file on the user’s desktop, usually named Picture 1.pdf.There are a variety of system utilities that also provide this functionality and it is important for people reading this to understand that it is very valuable to be able to take a picture of your screen and share it with someone else.
Counter Measures
Counter measures for this method are virtually impossible. This is because web pages have very limited access to controlling, or even being cognizent of when certain keys are pressed. You could, conceivably, swap the image out for a blank image whenever a key is pressed. Because this counter measure relies on JavaScript, you have to content with everything that entails (browser compatibility, noscript fallback tags, etc.)
Circumvention Techniques
Even if you could disable all keys and mouse activity, the visitor could write a script that opens their browser, goes to your page, and executes a screen shot, all without touching any of the keys or the mouse. This seems extreme, but it hints at the limited capabilities of browsers to control what their owners do.
Potential Incompatibilites/Issues
JavaScript implementations across browsers and platforms.
System Requirements
In any situation where JavaScript is required, you must include the tags with some sort of content that explains why JavaScript is needed.

Web Archiving

Users save the page as a Web Archive (a self-contained version of the entire page, including all images) or print the page (or save it as a PDF).
Counter Measures
Same as Screen Shots, but even more limited; display image in modal window using a Java applet or Flash.
Circumvention Techniques
It depends on what kind of counter measure is used, but usually, taking a screen shot can circumvent them.
Potential Incompatibilites/Issues
Many people like to use Flash as the “player” for their images because it protects their images rather well (by disabling many of the methods, except for screen shots, listed on this page). For the most part, Flash is widely suppported (available on most computers). For people who use Java or who don’t have the Flash player installed, however, it can mean that they don’t see anything at all.
System Requirements
Depends on the method…