Why WordPress Themes are Derivative of WordPress

In the past few days, WordPress has become entangled in a debate about WordPress theme licensing. It was specifically centered around Thesis, one of the last notable proprietary theme holdouts. Chris Pearson, who develops and sells Thesis, refuses to license Thesis under the GNU General Public License that applies to WordPress and all WordPress-derived code.

There are many aspects to the ongoing WordPress vs. Thesis brouhaha. Things like respect, copyright, freedom, GPL, ownership. There is no doubt that Thesis lifted lines of code, and even whole sections of code, directly from WordPress. The Thesis developer who did some of the lifting confessed to it (much to his credit).

Some people have changed their opinion on the matter when they learned of that wholesale code copying. That is, they changed their mind about Thesis specifically. But those revelations happened later in the fray, after Chris Pearson and Matt Mullenweg’s discussion on Mixergy about the matter. It is the position of the WordPress core developers that themes cannot be considered wholly original creations even when they don’t copy large sections of code in from WordPress. Theme code necessarily derives from WordPress and thus must be licensed under the GPL if it is distributed.

What is a WordPress theme?

WordPress themes are a collection of PHP files that are loaded together with WordPress and use WordPress functions and access WordPress core data in order to deliver HTML output. A theme may (and almost always does) include CSS files, JavaScript files, and image files. Note that WordPress theme PHP files are not “templates” or “documents” in the way that most people think of those words (though the word “template” is sometimes used, it is not strictly accurate). They are PHP script files that are parsed and run on the same exact level and by the same PHP process as all the core WordPress files.

Is a theme separate from WordPress?

There is a tendency to think that there are two things: WordPress, and the active theme. But they do not run separately. They run as one cohesive unit. They don’t even run in a sequential order. WordPress starts up, WordPress tells the theme to run its functions and register its hooks and filters, then WordPress runs some queries, then WordPress calls the appropriate theme PHP file, and then the theme hooks into the queried WordPress data and uses WordPress functions to display it, and then WordPress shuts down and finishes the request. On that simple view, it looks like a multi-layered sandwich. But the integration is even more amalgamated than the sandwich analogy suggests.

Here is one important takeaway: themes interact with WordPress (and WordPress with themes) the exact same way that WordPress interacts with itself. Give that a second read, and then we’ll digest.

The same core WordPress functions that themes use are used by WordPress itself. The same action/filter hook system that themes use is used by WordPress itself. Themes can thus disable core WordPress functionality, or modify WordPress core data. Not just take WordPress’ ultimate output and change it, but actually reach into the internals of WordPress and change those values before WordPress is finished working with them. If you were thinking that theme code is a separate work because it is contained in a separate file, also consider that many core WordPress files work the same way. They define functions, they use the WordPress hook system to insert themselves at various places in the code, they perform various functions on their own but also interact with the rest of WordPress, etc. No one would argue that these core files don’t have to be licensed under the GPL — but they operate in the same way that themes do!

It isn’t correct to think of WordPress and a theme as separate entities. As far as the code is concerned, they form one functional unit. The theme code doesn’t sit “on top of” WordPress. It is within it, in multiple different places, with multiple interdependencies. This forms a web of shared data structures and code all contained within a shared memory space. If you followed the code execution for Thesis as it jumped between WordPress core code and Thesis-specific code, you’d get a headache, because you’d be jumping back and forth literally hundreds of times. But that is an artificial distinction that you’d only be aware of based on which file contained a particular function. To the PHP parser, it is all one and the same. There isn’t WordPress core code and theme code. There is merely the resulting product, which parses as one code entity.

But it’s still in separate files!

I don’t think that matters. Linux Kernel Modules likewise are in separate files, but they’re considered by most to be derivative. If that argument doesn’t convince you, then note that the vast majority of themes derive from the original WordPress core themes. How they load different PHP subfiles, loop through posts, and get and interact with WordPress data is all covered by the original WordPress core themes, which are explicitly GPL. But I don’t think we need to resort to that argument, because of the way that themes combine with WordPress to form a modified work.

On APIs

WordPress has many external APIs that spit out data. Interacting with these APIs does not put your code on the same level as core WordPress code. These APIs include Atom, RSS, AtomPub, and XML-RPC. Something that interacts with these APIs sits entirely outside of WordPress. Google Reader doesn’t become part of WordPress by accessing your feed, and MarsEdit doesn’t become part of WordPress when you use it to publish a post on your WordPress blog. These are separate applications, running separately, on separate codebases. All they are doing is communicating. Applications that interact with WordPress this way are separate works, and the author can license them in any way they have authority to do so.

This is a wholly different model of interaction than with themes. Themes are not standalone applications. They are scripts that become part of WordPress itself, and interact with WordPress on the same level that WordPress interacts with itself.

Not just our opinion

Drupal and Joomla, both GPL PHP web publishing applications, have come to the same conclusion. To quote from Drupal:

Drupal modules and themes are a derivative work of Drupal. If you distribute them, you must do so under the terms of the GPL version 2 or later.

The Software Freedom Law Center did a specific analysis of the WordPress theme system and determined that WordPress theme code must inherit the GPL.

The PHP elements, taken together, are clearly derivative of WordPress code. The template is loaded via the include() function. Its contents are combined with the WordPress code in memory to be processed by PHP along with (and completely indistinguishable from) the rest of WordPress. The PHP code consists largely of calls to WordPress functions and sparse, minimal logic to control which WordPress functions are accessed and how many times they will be called. They are derivative of WordPress because every part of them is determined by the content of the WordPress functions they call. As works of authorship, they are designed only to be combined with WordPress into a larger work.

This is also the interpretation of the Free Software Foundation, which wrote the GPL. Here is what the FSF has to say in the GPL v2 FAQ. They wrote the license, so you should consider carefully what they have to say when trying to determine the spirit of the GPL:

If the modules are included in the same executable file, they are definitely combined in one program. If modules are designed to run linked together in a shared address space, that almost surely means combining them into one program.

The bolded part is how themes work in WordPress. The fact that themes don’t come bundled with WordPress is merely a result of WordPress’ flexible plugin/theme architecture and how non-compiled scripting languages like PHP work. The PHP opcode is compiled on the fly, so you can distribute portions of a WP+Plugins+Theme application piece by piece, and they’ll dynamically combine into one application.

FAQs

What about making money?

The GPL does not prohibit developers from charging for their code! The overwhelming majority of premium theme developers sell their themes under the GPL (and are making quite a lot of money doing it).

My JS/CSS/Images are 100% original. Do they have to be GPL?

No, they don’t. If they aren’t based on GPL’d JavaScript, CSS, or images, you are not forced to make them GPL. What you could do is offer a theme under a split license. The PHP would be under the GPL, but other static resources could be under some other license.

Won’t people just take my theme without paying for it?

You don’t have to offer it as an open download to everyone. You can put it behind a  pay wall. With regards to people getting it from a friend, or a torrent site, etc — this would happen even with a proprietary license. Do a Google search for “{proprietary theme name} torrent download” and you’ll see what I mean. What people are not able to get without paying is your support. This is a huge part of why people pay for premium themes — they have a knowledgable resource to call on if something goes wrong. That’s something that is irreplaceable, because no one knows the theme better than you do!

What about a developer license?

Theme PHP code must be GPL. You could do a split license on the CSS and JS and other non-GPL static resources. You can license those elements to one site, but let people with a developer license use them on multiple sites. Or, you could have an affiliate program that is only open to people with a developer license. You could seed betas to developers early. You could offer an exclusive developer forum. You could offer enhanced support. There are tons of possible models. The only thing you can’t do is restrict how people can use the GPL-derivative code.

Does this mean that the custom theme I developed for a client is GPL?

No. The GPL is triggered by distribution. Work-for-hire for a client is not distribution. In this case, they would have the copyright on the code. Distributing it would be up to them. As long as they didn’t distribute it, the GPL wouldn’t kick in. Your clients needn’t worry.

Can my employees take my custom theme and distribute it?

No, allowing access to GPL’d code by an employee is not distribution, and the company would have the copyright on the code. A company is considered one entity, so transferring the theme within that entity is not distribution.

What about plugins?

Everything in here applies to plugins as well as themes. The only difference between the two is that you generally have one theme active, but might have multiple plugins active. As far as interactions with WordPress go, they work the same way.

Conclusion

Theme code combines with WordPress code in a way that makes them one functional unit. This is what makes WordPress themes so powerful and flexible. Themes cannot stand by themselves, and are dependent on deeply integrating their code with WordPress core code in order to function at all. They cannot reasonably be considered original works. As such, theme PHP code (and any CSS/JS code that is derived from GPL’d code) must be licensed under the GPL if it is distributed.

If you refuse to abide by that licensing requirement, you forfeit your right to distribute WordPress extensions (themes or plugins). WordPress is copyrighted. If you do not accept WordPress’ license, you still have to respect our copyright. There are other platforms that do not have this licensing restriction (Drupal, Joomla, Movable Type Open Source, and Textpattern are all GPL, so you’d have the same issue with them).

Discussion

Please remember that this is about copyright and respecting the license that the WordPress copyright holders have chosen. It isn’t about money. Premium themes are fine. It is non-GPL themes (a.k.a. proprietary themes) that are the issue. Also realize that WordPress cannot change its license. It is forever locked to the GPL (version 2). Arguments along the lines of “WordPress should allow proprietary themes because of X,” are pointless. We are as much bound by the license as theme developers!

WordPress Q & A: Week of July 5th, 2010

Brad asks:

What’s the optimal way to store large amounts of meta data for a taxonomy without creating a custom table in WordPress?

WordPress has meta tables for the site (options table), posts, comments and users. It lacks a table for meta data about taxonomies (categories, tags, custom taxonomies). Solutions for this aren’t going to be simple, but I can think of a solution that doesn’t create extra tables. You could create a “shadow” entry in the posts table for each term, using a custom post type (say, “taxonomy-meta”). Then, just attach meta key/value pairs to that post entry.

As for linking the post proxy entry to its corresponding term, you could use the taxonomy system to place that term within that taxonomy, but it would probably be much faster to appropriate one of the existing fields, since this is a one-to-one relationship. I’d probably use post_name and make it something like taxonomy-meta-term-{$term_id}. That way, it’d be fairly straightforward to grab the proxy object that corresponded to a particular term.

I’d create four API functions. One backend function to get the post ID of the proxy object corresponding to a particular term. A backend function to create a proxy object for a term if it doesn’t exist. And then one to update taxonomy meta, and one to get taxonomy meta.

It sounds complicated, but it shouldn’t be more than 30-40 lines of code. And your API would be simple. Share the code if you end up doing this!

“K. K.” asks:

Can you explain how to become a core WordPress developer like you?

WordPress is a meritocracy, so to get the “props” you have to show your worth and put in the time. Start by lurking in Trac and seeing how we develop. Observe the weekly WordPress meetings in #wordpress-dev on Freenode. Then, when you feel confident, start submitting patches to Trac on tickets that need them. Or test the patches that are up there. Follow the tickets and respond to feedback. People who consistently provide quality patches and who seem to “get” the WordPress principles (e.g. options are bad, keep core light, target the 80% need, etc) will rise fairly quickly in prominence.

Ted asks:

Are there any plans to incorporate Facebook connect or any of the other 3rd-party authentication mechanisms into WordPress? If not, are there any FB connect plugins you’d recommend — ideally ones that work for both WP and BuddyPress?

Facebook Connect — no. We might consider third party mechanisms like OpenID+OAuth, but they’re not on the short-term roadmap. The most popular Facebook Connect plugin seems to be WP-FacebookConnect, written by a Facebook dev Simple Facebook Connect.

Web Hosts: WordPress is here to stay. Adapt!

WordPress is the number one user-installed web app, and its growth is showing no signs of slowing. If you are a web host, and you don’t have a specific strategy for WordPress, you’re likely operating your service inefficiently, and may be opening yourself up to security issues. This is the year to adapt, or be left behind by nimbler upstarts.

Performance

WordPress does not currently ship with any output caching. First, because most blogs never get enough traffic to need it, so it’s not worth the added complexity and configuration that it would add to our relatively nimble core. But also because every environment is different, and what works on one web host may actually degrade performance on another. So we leave it up to the WordPress user to choose whether they need a caching plugin, and which one to run.

As a web host, you know what caching strategies will work best with your server architecture. You have the ability to roll out things like Memcached or APC. You can route image requests to a lightweight web server or a CDN. These changes will result in a better user experience, and they’ll save you money.

Security

All code has bugs. WordPress has had its share of security issues through the years. As a web host, you can help keep your users out in front of security issues instead of just being reactive when someone gets hacked. First, by encouraging, or even demanding that users upgrade their sites to the newest available version of WordPress. In practice, there aren’t any widespread attacks against the current version of WordPress. The large scale attacks you see from time to time are against old versions of the software whose users haven’t updated in a while. It is in a web host’s interest to encourage upgrades and reduce the incidence of exploitation.

Because WordPress is so widespread, it also is often the victim of attacks that originated against other software or server misconfiguration. So a bad guy gets in using something else, and then once in, they look for WordPress installs to exploit. You can help users recover from these attacks by aggressively backing up their data and by looking for suspicious files or suspicious code that could indicate that a bad actor is exploiting their WordPress install.

What you can do

  • Get your company to abandon the mindset that you’re just a dumb host who doesn’t care what software your users are running. Users want and are willing to pay for a more specialized experience. If you tell them that it’s not your problem, they’re going to go find a service that will support their web hosting needs.
  • Offer WordPress-specific hosting. Specially optimized, prodigiously backed up, with a more locked-down environment. And because it is a specialty service, you can charge more than you do for your regular hosting products!
  • Build an internal WordPress Response Team that has in-depth training to help diagnose and fix WordPress bug, security and scaling issues. And in the meantime, hire a WordPress consultant like me or one of these fine consultancies to get your WordPress strategy rolling.

People ask me for hosting recommendations all the time. I have a few decent hosts that I’ll recommend, but I don’t have any hosts about which I can say “use them, because they know how to host WordPress, and they’ll support you.” I’d like nothing better than to have a dozen such hosts to recommend by this time next year. WordPress is here to stay, and it’s time for web hosts to adapt!

How to get your plugin removed from the directory

The following is a non-exhaustive list of things you can do to get your plugin rejected or removed from the WordPress.org plugin directory.

Yes, this is tongue-in-cheek. This is a list of things NOT TO DO.

  1. Give it a license that is incompatible with WordPress’ license.
  2. Host your plugin elsewhere, and only use the WordPress.org plugin listing as a pointer to that.
  3. Use base64 encoding to hide your plugin code or obfuscate HTML that you’re injecting into people’s blogs.
  4. Insert SEO spam links into people’s blogs (like <a href=”http://example.com/”>video poker</a>).
  5. Insert external links (like a credit link, <a href=”http://example.com/”>My Awesome Plugin by Awesome Sauce</a>) into their blog without explicitly asking their permission, or make the default option be to insert the link.
  6. Load portions of the code from an external site for no valid reason, or use any other trick to work around #3, #4 and #5.
  7. Harvest people’s e-mail addresses or require registration to activate the plugin.
  8. Explicitly state or imply that users of the plugin must pay you money in order to use the plugin.
  9. Make the plugin a “requirements check” or bootstrapper for some other plugin, hosted elsewhere. See #2.
  10. Make it do something illegal.
  11. Make it do something sneaky, underhanded, or otherwise dishonest or immoral. Maybe a plugin that disables all plugins by a plugin author you don’t particularly like. Harvest the user’s password. Use your imagination!

Again, this is a list of things not to do. It is not comprehensive. Be cool, think of how your plugin benefits its users, and write awesome plugins.

New Plugin – “I Make Plugins”

I have several WordPress plugins. They’re hosted on the WordPress.org plugin repository, but I also have a page for each plugin on my own site. I’ve found it tedious to have to update both places separately. Things get out of sync, or worse, I put off plugin updates because I loathe updating two places (with two different formats) with the same information.

The WordPress plugin repository has an API. Let’s use it! I Make Plugins is a plugin for WordPress plugin authors to let them easily showcase their plugins on their own site, solely by updating the plugin’s readme.txt file.

Adding a plugin is as simple as creating a new subpage of your plugin listing page, and giving it the name of your plugin in the repository. All the information comes from the API and is kept up to date.

Here is a nine and a half minute. boring-as-hell screencast with a full tour of the plugin.

I realize that writing a plugin for plugin developers is probably a futile gesture. Plugin developers are choosy people, and many may already have their own setup for managing their stable of plugins. I wrote this for myself — but let me know if you find it useful!

New in WordPress 2.9: Post Thumbnail Images

Many WordPress themes, especially those with “magazine-like” layouts, use an image to represent each post. It might just be on the front page. It might be alone, or alongside an excerpt. Until now, there was no standardized way to do this. Many themes would require you to tediously enter a Custom Field with the value being the URL you wanted to use. Often you had to do cropping yourself. With WordPress 2.9, theme authors can easily enable Post Thumbnail selection UI and call those image using simple template tags.

First, in the theme’s functions.php, declare that your theme supports this feature. This will enable the UI in the WP Admin.

add_theme_support( 'post-thumbnails' );

That will enable Post Thumbnail UI for both Post and Page content types. If you’d only like to add it to one, you can do it like this:

add_theme_support( 'post-thumbnails', array( 'post' ) ); // Add it for posts
add_theme_support( 'post-thumbnails', array( 'page' ) ); // Add it for pages

Simply remove the one you don’t want to support.

Next, you should specify the dimensions of your post thumbnails. You have two options here: box-resizing and hard-cropping. Box resizing shrinks an image proportionally (that is, without distorting it), until it fits inside the “box” you’ve specified with your width and height parameters. For example, a 100×50 image in a 50×50 box would be resized to 50×25. The benefit here is that the entire image shows. The downside is that the image produced isn’t always the same size. Sometimes it will be width-limited, and sometimes it will be height-limited. If you’d like to limit images to a certain width, but don’t care how tall they are, you can specify your width and then specify a height of 9999 or something ridiculously large that will never be hit.

set_post_thumbnail_size( 50, 50 ); // 50 pixels wide by 50 pixels tall, box resize mode

Your second option is hard-cropping. In this mode, the image is cropped to match the target aspect ratio, and is then shrunk to fit in the specified dimensions exactly. The benefit is that you get what you ask for. If you ask for a 50×50 thumbnail, you get a 50×50 thumbnail. The downside is that your image will be cropped (either from the sides, or from the top and bottom) to fit the target aspect ratio, and that part of the image won’t show up in the thumbnail.

set_post_thumbnail_size( 50, 50, true ); // 50 pixels wide by 50 pixels tall, hard crop mode

Now, you can make use of the template functions to display these images in the theme. These functions should be used in the loop.

has_post_thumbnail() returns true/false and indicates whether the current post has a manually-chosen Post Thumbnail (in the loop):

<?php
if ( has_post_thumbnail() ) {
	// the current post has a thumbnail
} else {
	// the current post lacks a thumbnail
}
?>

the_post_thumbnail() outputs the Post Thumbnail, if it exists (in the loop):

<?php the_post_thumbnail(); ?>

Those are the basics. How about some advanced stuff?

What if you want to use a small 50×50 hard-cropped image for the home page, but want to use a 400 pixel-wide (unlimited height) image on the post’s permalink page? You’re in luck. You can specify additional custom sizes! Here’s the code:

functions.php

add_theme_support( 'post-thumbnails' );
set_post_thumbnail_size( 50, 50, true ); // Normal post thumbnails
add_image_size( 'single-post-thumbnail', 400, 9999 ); // Permalink thumbnail size

home.php or index.php, depending on your theme structure (in the loop):

<?php the_post_thumbnail(); ?>

single.php (in the loop):

<?php the_post_thumbnail( 'single-post-thumbnail' ); ?>

That’s it! set_post_thumbnail_size() just calls add_image_size( 'post-thumbnail' ) — the default Post Thumbnail “handle.” But as you can see, you can add additional ones by calling add_image_size( $handle, $width, $height, {$hard_crop_switch} );, and then you use that new size by passing the handle to the_post_thumbnail( $handle );

If you want your theme to support earlier versions of WordPress, you’ll have to use function_exists() to keep from calling these new functions in those versions. I’ve omitted that code to keep these examples as simple as possible. Here would be the functions.php example with the wrapper code:

if ( function_exists( 'add_theme_support' ) ) { // Added in 2.9
	add_theme_support( 'post-thumbnails' );
	set_post_thumbnail_size( 50, 50, true ); // Normal post thumbnails
	add_image_size( 'single-post-thumbnail', 400, 9999 ); // Permalink thumbnail size
}

There is one caveat for this feature in WordPress 2.9 — it only works fully for new image uploads. We can’t yet resize images on the fly, although I’m strongly considering it for a future version. If you call the template functions on a post that has a Post Thumbnail that was uploaded prior to your theme having declared the new sizes, you won’t be able to do hard-cropping, and the box-resize will be done in the browser. As a temporary solution, Viper007Bond has a great plugin that will go back and create missing image sizes for you: Regenerate Thumbnails.

I’m looking forward to see what kinds of sites you can build with this feature!

How should “Post updated. View Post” links open?

We’ve gone back and forth on this. How should the “View Post” link that shows up next to the “Post updated” (or similar) text work? Should it open in the same window/tab, or should it open in a new window/tab?

The problem with this question is that the people who have really strong opinions in favor of opening the tab in the same window are all power users. They’re people like me. I don’t think I can give an objective answer on this, because manually opening a window in a new tab is a skill that I don’t even think about, I use it so much. I realize that’s probably not the case for many WordPress users.

We’re going to use the honor system on this, so be honest:

Do not vote in this poll if your mouse has more features than two buttons and a scroll wheel, and you know how to use them. Do not vote in this poll if you know what “middle-clicking” is.

I’m abstaining from voting, as my mouse has 7 buttons, one 4-way scroll wheel, and another two-way thumb wheel. :-)

Excluding your plugin or theme from update checks

There has been a vigorous discussion going on regarding what data WordPress installs send to WordPress.org when doing update checks. Because WordPress (the software) doesn’t know whether a theme or plugin is listed in the WordPress.org repositories, it has to check them all, and let the repository sort it out. Some have expressed concern that private plugins developed for a single client could contain sensitive information in their headers, like contact information for the developer, etc.

If you, as a plugin or theme developer, would like to exclude one of your plugins or themes from the update array, the following code will do the trick.

For plugins:

function cws_hidden_plugin_12345( $r, $url ) {
	if ( 0 !== strpos( $url, 'http://api.wordpress.org/plugins/update-check' ) )
		return $r; // Not a plugin update request. Bail immediately.
 
	$plugins = unserialize( $r['body']['plugins'] );
	unset( $plugins->plugins[ plugin_basename( __FILE__ ) ] );
	unset( $plugins->active[ array_search( plugin_basename( __FILE__ ), $plugins->active ) ] );
	$r['body']['plugins'] = serialize( $plugins );
	return $r;
}

add_filter( 'http_request_args', 'cws_hidden_plugin_12345', 5, 2 );

Just change the cws_hidden_plugin_12345 string (two instances) to a namespaced function name for your plugin, and you’re good to go.

For themes:

function cws_hidden_theme_12345( $r, $url ) {
	if ( 0 !== strpos( $url, 'http://api.wordpress.org/themes/update-check' ) )
		return $r; // Not a theme update request. Bail immediately.

	$themes = unserialize( $r['body']['themes'] );
	unset( $themes[ get_option( 'template' ) ] );
	unset( $themes[ get_option( 'stylesheet' ) ] );
	$r['body']['themes'] = serialize( $themes );
	return $r;
}

add_filter( 'http_request_args', 'cws_hidden_theme_12345', 5, 2 );

Put this in your theme’s functions.php Again, just change the cws_hidden_theme_12345 string (two instances) to a namespaced function name for your theme. Do note that this will only hide the ACTIVE theme. This code doesn’t get run if the theme isn’t active. If you want to hide non-active themes, you’ll have to put this code in a plugin and instead of using get_option( 'template' ) or get_option( 'stylesheet' ) you’d hardcode the values for the inactive theme you want to hide.

Just a note: I don’t want the comments to turn into another battlefield for the update check debate. I’m putting my code where my mouth is and showing you how you can keep private plugins/themes from contacting WordPress.org if you so wish. Comments about this code are welcomed!

Block-level comments trick

Block-level comments are useful for commenting out an entire block of code in PHP, CSS, and other code contexts.

/*
$this = 'code is deactivated';
$and = 'so is this';
*/

The only problem with this is that when you go to re-activate this code, you have to change both the opening and closing comment markers. That’s a pain.

While I was at WordCamp NYC last week, I saw Daisy Olsen using a very clever trick in her lightning round talk.

/*
$this = 'code is deactivated';
$and = 'so is this';
/**/

See what she did there? The closing comment marker is preceded by another opening marker. Because comment blocks can’t be nested, this second opening comment marker is ignored. This enabled her to re-enable this code by removing the opening marker.

$this = 'code is reactivated';
$and = 'so is this';
/**/

Brilliant! I can’t believe I haven’t seen this before. The one downside to this is that you are deleting two characters and destroying the opening marker. Here’s an even better method.

//*
$this = 'code is reactivated';
$and = 'so is this';
/**/

By adding a slash in front of the opening comment marker, I comment out the comment marker. It only takes one key press, and the corpse of the original opening marker is retained, allowing you to reinstate it with the deletion of a single character.

Props to Aleem Bawany for the second trick (he uses //*/ as the closing comment, which works pretty much the same way).

What other commenting tricks do you know?

Using PHP5 object constructors in WP Widget API

Someone mentioned to me that they couldn’t use PHP5-style object constructors when using the WP Widget API. I looked into it, and it turns out it does work. Example:

class My_Widget extends WP_Widget {
	function __construct() {
		$widget_ops = array( 'classname' => 'css-class', 'description' => 'Description' );
		parent::__construct( 'css-class', 'Title', $widget_ops );
	}
	// Rest of your widget subclass goes here
}

The key is using parent::__construct() instead of $this->WP_Widget().

Interview with Deutsche Welle on WordPress Security

I recently did a short interview with Deutsche Welle about WordPress security. Listen to it here.

To expand on the topic, here are some of the details that didn’t make it into the final cut of the interview:

If your blog is compromised, you should install the latest version of WordPress, but first you should remove your old files. This is to prevent a hacker from leaving a back door (something like wp-give-hacker-access-forever.php in your WordPress directory. Just dropping the new version over the old version wouldn’t replace a new file that a hacker may have added, which is the reason for getting rid of the old files. Once you’ve done that (being careful to back up your wp-config.php and all your wp-content files), upload a clean install of WordPress. Restore your custom files. Next, look for any user accounts that weren’t there before, or that have higher access than they should. Sort that out. And lastly, scan through your theme/plugin files looking for backdoors or hidden links. This is mostly a manual process, but there are some common things to look for. Most backdoors use the eval() function, so be on the lookout for that!

The best way to keep your blog safe is to stay updated with the latest WordPress version! We’ve tried to make it as easy as possible to update (one-click!), and we have big plans for making it even easier in the future.

I’ve never had one of my WordPress blogs compromised, and I don’t do anything “fancy.” I just stay updated.

Reminder: if you’re using WordPress.com or another “hosted” blog solution, they take care of security updates for you. The only thing you need to worry about is choosing an unguessable, complex password.

PHP $_SERVER variables are not safe for use in forms, links

A common security mistake I see WordPress plugin authors (and PHP coders in general) make is using $_SERVER['PHP_SELF'] or $_SERVER['REQUEST_URI'] as the action of a form or part of an anchor’s href attribute. This is not safe to do, and opens your code up to XSS (cross-site scripting) exploits.

Common example:

<form action="<?php echo $_SERVER['PHP_SELF']; ?>">

Another example:

<a href="<?php echo $_SERVER['PHP_SELF']' ?>?foo=bar">link title</a>

Here are my two rules regarding $_SERVER['PHP_SELF'] or $_SERVER['REQUEST_URI'] in forms:

  • Do not use them
  • If you use one of them, escape it with esc_url()

Most uses of $_SERVER['PHP_SELF'] and $_SERVER['REQUEST_URI'] are in HTML forms. If you want the action attribute to point to the current URL, leave it blank. URI references that are blank point to the current resource.

<form action="">

If you do want to specify the action (and there are good reasons for wanting to do that, such as stripping the query string from the current URL), you must run it through esc_url().

<form action="<?php echo esc_url( $_SERVER['PHP_SELF'] ); ?>">

The same applies to links… run the href attribute through esc_url().

<a href="<?php echo esc_url( $_SERVER['PHP_SELF'] . '?foo=bar' ); ?>">link title</a>

A quick search through the WordPress Plugin Directory showed that this problem is far too common.

Updates:

Examples of URLs that could exploit this for double-quoted actions:

script.php/"%20onmouseover='alert(document.cookie)'

And single-quoted actions:

script.php/'%20onmouseover='alert(document.cookie)'

No, just using a plain old htmlentities() wrapper is not going to help! That’s still vulnerable to XSS in certain situations. If you’re not using WordPress, you should copy the WordPress escaping functions (just remove the apply_filters() portions).

If you are using the base tag, Safari will apply that base to the blank action attribute. So if you use the base tag (I never do), a blank action isn’t going to be for you. Use what you’ve been using, but escape it.

Lester Chan has a handy snippet for the form action of WordPress plugin settings pages:

<form action="<?php echo admin_url( 'admin.php?page=' . plugin_basename( __FILE__ ) ); ?>">

admin_url() takes care of escaping for you, and is an easy way to create a full WP admin URL from a wp-admin-relative URL.

TextMate WordPress Widget Snippet

I love WordPress’ sidebar widgets. I also despise coding them.

I love how they let me offload menial management tasks directly to clients, avoiding all the “Change this word to another word!” e-mails. But every time I code them, it seems to involve 15 minutes of Googling, copy-pasting from a previous widget, and looking at documentation.

So I created this TextMate “snippet” to make it easier:

class ${1:PREFIX_Name}_Widget extends WP_Widget {
	function $1_Widget() {
		\$widget_ops = array( 'classname' => '${2:CSS class name}', 'description' => '${3:Description}' );
		\$this->WP_Widget( '$2', '${4:Title}', \$widget_ops );
	}

	function widget( \$args, \$instance ) {
		extract( \$args, EXTR_SKIP );
		echo \$before_widget;
		echo \$before_title;
		echo '$4'; // Can set this with a widget option, or omit altogether
		echo \$after_title;

		//
		// Widget display logic goes here
		//

		echo \$after_widget;
	}

	function update( \$new_instance, \$old_instance ) {
		// update logic goes here
		\$updated_instance = \$new_instance;
		return \$updated_instance;
	}

	function form( \$instance ) {
		\$instance = wp_parse_args( (array) \$instance, array( ${5:array of option_name => value pairs} ) );

		// display field names here using:
		// \$this->get_field_id('option_name') - the CSS ID
		// \$this->get_field_name('option_name') - the HTML name
		// \$instance['option_name'] - the option value
	}
}

add_action( 'widgets_init', create_function( '', "register_widget('$1_Widget');" ) );

Just create a WordPress TextMate bundle, create a new snippet, paste in that code and give it a trigger like wpwidget. Then just type that trigger, press TAB, and you’ll be in the first field. Type, hit TAB to go to the next field. Places where you enter the same thing twice are handled—you only have to enter it once. There are some helpful comments that’ll guide you through the rest once you’ve filled out the basics. I find that with this snippet, I can code up a new widget in a couple of minutes, tops. This is definitely going to make it more likely for me to create a widget for a client instead of just cheating and editing their theme by hand myself.

Public response to Chris Anderson’s “Free” on WordPress

I got a tip that Chris Anderson’s upcoming book Free has the following to say about WordPress:

2. Feature limited (Basic version free, more sophisticated version paid. This is the WordPress model.)

  • Upside: Best way to maximize reach. When customers convert to paid, they’re doing it for the right reason (they understand the value of what they’re paying for) and are likely to be more loyal and less price sensitive.
  • Downside: Need to create two versions of the product. If you put too many features in the free version, not enough people will convert. If you put too few, not enough will use it long enough to convert.

This is most assuredly not the WordPress model. Anyone and everyone can go to wordpress.org and download a completely free, completely unrestricted, and completely feature-complete version of WordPress to run for any purpose. There is no feature limited version of WordPress.

Chris might be getting confused by WordPress.com, which is a hosted WordPress solution (the biggest one, but certainly not the only one). It is true that WordPress.com charges money for certain features, such as CSS editing capabilities. But this is completely within the rights of Automattic, the company which operates the WordPress.com service. That one company is charging for certain aspects of a hosted WordPress solution does not change the fact that WordPress itself is free/open source software and has no monetization model and no tiered versioning system.

As we talked about at SXSW, Chris, it is WordPress services that are the “freemium” portion of WordPress. We give the software away, and thus create a vibrant market for third party WordPress services (this marketplace, to quote this blog’s quite literal catchphrase, puts food on my table).

Note that it would be correct to say that this is the Movable Type model, whereby Movable Type Pro and Movable Type Enterprise get features not available in the free/open source version of Movable Type.

Update: Chris fixed this error in the electronic version of Free, and it stands to reason that future print editions will have the correction. Thanks, Chris!