Posts tagged ‘plugin’

One of the easier to understand vulnerabilities is the CSRF. It’s also one of the most common issues we see in plugins and themes, because people rarely think about it.

Imagine that I have a form that takes input, like so:

<form action="http://example.com/example.php" method="GET">
<input type="text" name="demo" />
</form>

Now, that’s a simple form (and missing a submit button to boot), but you get the idea. It takes a text input. Presumably, something on the other end (at /example.php) processes that input, saves it in a database, something like that. Easy.

First question: Is this necessary?

The main question I see asked when this concept is explained to people is “why is this necessary?”. Some people believe that since you have to be logged in to access admin screens in the first place, then you can’t get to the forms and submit them. Why have all this protection and checking for a form submission when the form is hidden behind a login screen?

What you need to understand is the difference between “authority” and “intent“.

Authority

In real world cases where we are processing that input, we generally want to limit who is allowed to submit that form in some way. A plugin will want to only allow admins to change settings. A theme will only want to allow site owners to adjust the display of the site. Things of that nature. For these cases, we use methods of authentication.

There’s several ways to do this, we can check the current_user information. WordPress has capability checks for users to know what they are and are not allowed to do. When we check these, we’re verifying authority. Making sure that the user is allowed to do these things.

But something else that we need to check which most people don’t think about is intent. Did the user actually intend to submit that form, or did their browser submit it for them automatically, perhaps without their knowledge?

Examine that form again, and consider what would happen if you were to visit a webpage, anywhere on the internet, that contains this:

<img src="http://example.com/example.php?demo=pwned" />

Now, you might be thinking that this is a rather contrived example, and you’d be right on that score, but it serves to demonstrate the point. Your browser loads this URL and that is the equivalent action to submitting that form, with “pwned” as the text in question.

Here’s the kicker, all those authority checks do us no good in preventing this. You actually do have the authority to submit that form, and your browser, using your authority, just submitted it for you. Pwned, indeed.

(For those of you thinking “just use POST forms”, consider that javascript can submit POST forms. So that’s really no help.)

Intent

What we need is to verify intent. We need to know that the user submitted that form, and not just the browser doing it for them automatically.

WordPress used to do this (a looong time ago) using the referer. For those who don’t know, referer is a URL passed by your browser to indicate where a user came from. So one could check that the referer says that the form was submitted from the form’s page and not from some other page on the internet. The problem is that referer is not reliable. Some browsers have the ability for script to fake the referer. Firewalls and proxies often strip the referer out, for privacy concerns. And so forth.

Nonces

WordPress now does this using nonces. A nonce is a “number used once” in its purest form. Basically, it’s a one-time password. When we generate the form, we generate a number. When the form is submitted, we check the number. If the number is wrong or missing, we don’t allow the form to be submitted. A script cannot know the number in advance. Other sites cannot guess the number.

Now, technically, WordPress doesn’t use real nonces, because they’re not “used once”. Instead, WordPress nonces revolve on a 12 hour rotating system (where 24 hours are accepted). For any given 12 hour period, the nonce number for a given action will be the same. But it’s close enough to a real nonce to eliminate the issue, but notably it’s only for the issue of verifying intent. Don’t try to use WordPress nonces for anything else. πŸ™‚

So, when we generate a form, we generate a nonce. This nonce is based on five things: site, user, time, the action being performed, and the object that the action is being performed on. Changing any of these gives us a different nonce.

Let’s say I want to delete a post. To do that, I need to know the nonce for deleting that specific post, as me, on my site, within the last 24 hours. Without that nonce, I cannot perform the action. More importantly, in order for somebody to “trick” my browser into doing it for me, they need to get that specific nonce and get my browser to load it within 24 hours. Tough to do. And even if they pull it off, they only have been able to perform that very specific action, the nonce obtained is useless for any other purpose. They don’t get any form of full control via this manner. They can’t make my browser do anything on mysite that they don’t have the nonce for.

Using nonces

So, let’s get down to brass tacks. Generating a nonce in WordPress is easy and can be done in many different ways depending on your particular needs. You might want to protect a simple link, or you might want to protect a form, or you might even need to protect a javascript ajax call.

Protecting a link can be done with wp_nonce_url(). It takes a URL and an action and adds a valid nonce onto that URL. It works like this:

$nonced_url = wp_nonce_url( $url, 'action_'.$object_id );

Here, we’re taking some URL, and adding a nonce onto it for a specific action on some specific object. This is important, actions and objects need to both be specified if there is some object being referred to. An example might be a link to delete a specific post. Such code would look like this:

wp_nonce_url( $url, 'trash-post_'.$post->ID )

The action is “trash-post” and the post being trashed has its ID number appended to that action. Thus, the nonce will let you trash that post and only that post.

On the other hand, maybe we have a form that we need to protect instead. Inside that form, we can add something like this:

wp_nonce_field( 'delete-comment_'.$comment_id );

This is the nonce for deleting a comment. It outputs a couple of form fields, like so:

<input type="hidden" id="_wpnonce" name="_wpnonce" value="1234567890" />
<input type="hidden" name="_wp_http_referer" value="/wp-admin/edit-comments.php" />

The value for the nonce will be specific to deleting that comment, on that site, by that user.

Sometimes we just need to generate the nonce directly, in no specific format. One case might be for an AJAX type call, where the data is being submitted by jQuery. In such a case, you can use the wp_create_nonce function to get just that nonce value, like so:

wp_create_nonce( 'action_'.$object_id );

For AJAX requests, you’ll want to include that nonce value in the submitted data with a name of “_ajax_nonce”. Why that particular name? Because it’s what WordPress checks when verifying the nonce. Speaking of verification:

Verifying nonces

Generating these numbers is no good if you don’t check them as well. Fortunately, WordPress makes this easy. There’s two functions to verify incoming nonces.

check_admin_referer( 'action_'.$object_id );

The name of the function refers back to the time before nonces, when this function call was checking the referer value from the browser. Nowadays, it checks nonces instead. If the _wpnonce sent back in the form does not match the action and ID here, then this function stops further processing. This is the cause of the “Are you sure you want to do this?” screen that is sometimes reported by users. To avoid getting this screen, the nonce being checked has to match.

An alternative to checking forms or links is checking ajax requests, which is why we have this function:

check_ajax_referer( 'action_'.$object_id );

This performs the same basic check, but if it fails, it returns a simple “-1” response and then halts processing. Your AJAX javascript code can recognise that response and take appropriate action based on it.

In either case, if the nonce fails, the script exits. No action is taken. The form is not processed, the post not deleted. That’s the sort of check you need to prevent CSRF attacks.

Bottom Line

If you have a plugin or a theme or any type of code that “does something” in WordPress, then you need to protect that action with a nonce. If you’re not protecting it with a nonce, then it’s possible for somebody else to trick your browser into performing that action on your behalf.

Also, note that it’s not enough to just name the action. You generally are taking action on some specific “thing”, and the ID of that thing needs to be included in your nonce as well. The more specific the action, the better.

Any form, any action, no matter how much “authentication” you have on checking it, can be exploited, because you’re not really authenticating the “user”, you’re authenticating that it’s coming from “the user’s browser”. You need to have something else that changes regularly, so that you can verify that the user did indeed load that particular form and submit it relatively recently, and thus probably intended to perform that action.

Nonces are easy to implement. So do it already. We have enough plugins not doing it that this clearly needs to be said. πŸ™‚

Shortlink:

In trying to figure out what to talk about at WordCamp Atlanta, I remembered a question put to me in WordCamp Birmingham. The question was how can a theme developer easily make a plugin-dependency in their theme?

I wrote some code to do this sort of thing, just as an example/test/demonstration, but then after looking over the schedule, I found that Thomas Griffin had beat me to it. After looking over his slides and having him walk me through his code, I realized that his solution was much more fully featured than mine, so I’m glad I didn’t present anything on this topic. (I ended up just doing an answer session where I tried to answer any question put to me, and frankly that was much more fun than having slides, so I’m probably just going to do that from now on.)

You can find his cool library here, BTW: http://tgmpluginactivation.com/

However, his solution is highly complex. The class he came up with is well done and fully-featured. He has capabilities for making notifications in the header space on the admin section, lightbox popups, bulk installs, forced activation, custom skinning, etc. It’s a big thing. While that’s great for a lot of people in terms of having code you can just drop-in and use, I thought that it doesn’t do much to teach how one can DIY it.

See, the code I wrote was tiny. It basically just provides some minor functionality to show a theme author how to detect installed plugins, how to detect when they’re active, how to build install and activate links, etc. It doesn’t do any pretty stuff. No custom skinning. No lightbox popups. All these things are possible, but if somebody hands you a hunk of library code to do them, then you know how to use that library, not how it works. I dislike using libraries for this reason.

So here’s the small class I wrote to do the same sort of thing, but in a very bare-bones style.

/* 

Simple class to let themes add dependencies on plugins in ways they might find useful

Example usage:

	$test = new Theme_Plugin_Dependency( 'simple-facebook-connect', 'http://ottopress.com/wordpress-plugins/simple-facebook-connect/' );
	if ( $test->check_active() ) 
		echo 'SFC is installed and activated!';
	else if ( $test->check() ) 
		echo 'SFC is installed, but not activated. <a href="'.$test->activate_link().'">Click here to activate the plugin.</a>';
	else if ( $install_link = $test->install_link() )
		echo 'SFC is not installed. <a href="'.$install_link.'">Click here to install the plugin.</a>';
	else 
		echo 'SFC is not installed and could not be found in the Plugin Directory. Please install this plugin manually.';

*/
if (!class_exists('Theme_Plugin_Dependency')) {
	class Theme_Plugin_Dependency {
		// input information from the theme
		var $slug;
		var $uri;

		// installed plugins and uris of them
		private $plugins; // holds the list of plugins and their info
		private $uris; // holds just the URIs for quick and easy searching

		// both slug and PluginURI are required for checking things
		function __construct( $slug, $uri ) {
			$this->slug = $slug;
			$this->uri = $uri;
			if ( empty( $this->plugins ) ) 
				$this->plugins = get_plugins();
			if ( empty( $this->uris ) ) 
				$this->uris = wp_list_pluck($this->plugins, 'PluginURI');
		}

		// return true if installed, false if not
		function check() {
			return in_array($this->uri, $this->uris);
		}

		// return true if installed and activated, false if not
		function check_active() {
			$plugin_file = $this->get_plugin_file();
			if ($plugin_file) return is_plugin_active($plugin_file);
			return false;
		}

		// gives a link to activate the plugin
		function activate_link() {
			$plugin_file = $this->get_plugin_file();
			if ($plugin_file) return wp_nonce_url(self_admin_url('plugins.php?action=activate&plugin='.$plugin_file), 'activate-plugin_'.$plugin_file);
			return false;
		}

		// return a nonced installation link for the plugin. checks wordpress.org to make sure it's there first.
		function install_link() {
			include_once ABSPATH . 'wp-admin/includes/plugin-install.php';

			$info = plugins_api('plugin_information', array('slug' => $this->slug ));

			if ( is_wp_error( $info ) ) 
				return false; // plugin not available from wordpress.org

			return wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=' . $this->slug), 'install-plugin_' . $this->slug);
		}

		// return array key of plugin if installed, false if not, private because this isn't needed for themes, generally
		private function get_plugin_file() {
			return array_search($this->uri, $this->uris);
		}
	}
}

Obviously, for theme authors wanting to do something, they’re going to want to make much prettier means of displaying things and installing things. Thus, this code is meant as an example, to show the basics of how to detect such things.

So, use it directly if you like (it works), but more importantly, if you want to put plugin dependancies in your theme, then I suggest reading it and figuring out how it works instead. Then you can see how plugins can be detected and how to build simple install and activation links.

(BTW, note that I used the slug and the PluginURI for a reason. Plugins should be using a unique URL for the plugin in their code, and that URL is very likely to be the most unique thing about the plugin, and therefore the best way to check for a plugin already being there or not. Slugs can be duplicated by accident or design, but URLs are generally going to be unique and specific to a particular plugin.)

Shortlink:

Google came out with an experimental specification for websites to provide “hints” on forms, to allow things like autocomplete to work better and be more standardized. Seems useful.

Here’s a quick plugin snippet you can use to make your comments form use this specification. Only Chrome 15 and up is using this at the moment, but in the long run I think most browsers will be implementing something similar to this, since filling out forms is just one of those endless pieces of drudgery that we could all stand to do away with.

Note that your theme will need to be using the comment_form() function call for this to work, otherwise you’ll just have to edit your comment form in the theme manually.

<?php
/*
Plugin Name: Add X-Autocomplete Fields to Comment Form
*/
add_filter('comment_form_default_fields','add_x_autocompletetype');
function add_x_autocompletetype($fields) {
	$fields['author'] = str_replace('<input', '<input x-autocompletetype="name-full"', $fields['author']);
	$fields['email'] = str_replace('<input', '<input x-autocompletetype="email"', $fields['email']);
	return $fields;
}

Simple little bit of code, really. Should work with any theme using the normal comment_form() function call.

Shortlink:

If you read “how-to” stuff for WordPress sites around the web, then you frequently run across what many people like to call “snippets”. Short bits of code or functions to do various things.Β I myself post snippets frequently, usually made up on the fly to solve somebody’s specific problem.

One question I get a fair amount is “where do I add this code?”

The usual answer to this for a lot of people is “in the theme’s functions.php file”. This is a quick solution, but it is often a problematic one.

The reason this has become the more or less go-to place to add these snippets is because it’s complicated to explain to a newbie how to make a plugin and activate it, or to point out the problems with modifying core code, or plugin code. Saying to look for a specific file in their theme, on the other hand, is quick and easy, and until recently theme upgrades have been fairly rare.

However, as themes get upgrades, it becomes more and more incorrect to tell people to modify them directly. And telling people how to create child themes is complex, even if it’s easy to do.

So I’d like to start a new trend, and recommend that people start making Site-Specific Plugins. Most people who run WP sites on a serious level do this in some way already, but if you make it sorta-standard practice, then it’ll make things simpler all around.

How to create a Site-Specific Plugin

1. Create a new directory in the plugins directory. Name it after the site in some fashion. For example, /wp-content/plugins/example.com or something like that.

2. Create a new php file in that directory. Name is dealer’s choice.

3. Put this in the file:

<?php
/*
Plugin Name: Site Plugin for example.com
Description: Site specific code changes for example.com
*/

4. Finally, go activate your new blank plugin on the site.

Now you have a simple and specific place to add snippets. It will survive upgrades of any sort, and you can edit it to add new code on an as needed basis. What’s more, it’s kinda sorta break-proof. If the user uses the built-in plugin editor to edit it, and they add code that breaks the site, then the editor detects that on saving the code and deactivates the plugin, preventing the “white screen of death” for their site.

This is a much better way to use “snippets” than the theme’s functions.php file, and we should really use it more often in our replies to users.

Shortlink:

My post about how to customize WordPress images with tricks like greyscale and such got me lots of feedback, so I figured I might as well turn it into a plugin.

The ImageFX plugin allows you to customize the image sizes from WordPress or custom ones for your theme, by applying filters to them.

The way it works is basically identical to my original post on the topic, only it allows the filters to be defined on a per-image-size level. It also allows the addition of a “slug” to be appended to the image filename, which is useful for cases where you want to have two images at the same size, but with different filters.

Since it was easy to do, I went ahead and created several other simple image filters that you can use for your images:

  • Greyscale (black and white)
  • Sepia tone (old-timey!)
  • Colorize with red, yellow, green, blue, or purple
  • Photonegative
  • Emboss
  • Brighten
  • Greyscale except red, green, or blue (classy!)

Here’s some examples. This a pic of me, Nacin, Rose, and Matt at WordCamp San Francisco. I ran it through the sepia, blue colorize, and grey-except-red filters.



These are some of the default filters included, but since I could, I went ahead and made it easily expandable too. All you have to do to define a filter is to create a function to do the image filtering you want, then call the imagefx_register_filter() function to add it.

To implement your own custom filter, you can do it like this:

imagefx_register_filter('custom-name','my_custom_filter');
function my_custom_filter(&$image) {
 // modify the $image here as you see fit
}

Note that the $image is passed by reference, so you don’t have to return it. This is because the $image resource takes up a lot of memory, so to save on memory usage, you are manipulating it in place, sort of thing.

You can use any of the image functions in PHP to change the image however you like. The filters I’ve implemented are mostly pretty simple. You can see them all in the filters.php file, in the plugin.

Caveats: The plugin will only filter JPG images, to avoid the overhead of recompressing PNGs and to avoid breaking animated GIF files. Also note that I haven’t tested these filters extensively. They’re only a starting point, sort of thing. I spent all of about 20 minutes writing them, so don’t expect miracles. πŸ™‚

You can download version 0.1 of the plugin from the WordPress plugin directory:Β http://wordpress.org/extend/plugins/imagefx/

Enjoy!

Shortlink:

Facebook recently made a breaking change to the developer process, which makes it impossible for new applications to get the correct API keys. Since this essentially broke all previous versions of SFC, I went ahead and pushed the beta version public. It’s still unfinished, but Facebook didn’t really give me a lot of choice.

So, this is a quick walkthrough of some of the new features of SFC 1.0.

Upgrade Process

The upgrade process is slightly more involved for this one. It is recommended that you deactivate the old SFC plugins before upgrading. Why? Well, if you don’t, you’ll get a bunch of errors when visiting the Plugins screen later, saying that all the old SFC plugins either don’t exist or have an invalid header. These errors are normal, because of the next feature:

One plugin only

No more sub-plugins

Simple Facebook Connect is now a single plugin, with modular features. If you examine the plugins screen, you’ll find only one entry: Simple Facebook Connect.

The many-plugins-in-one was a useful experiment, IMO, and I still think it’s a better way to do things. But many people find it confusing, and some have disagreed with the notion. A lack of useful core support for plugin dependencies and user feedback convinced me to switch it up. So now, SFC is one plugin. But it’s still modular!

Sub-module selections

As you can see in the image, you can still turn on and off pieces of the plugin. Why have a piece running and consuming valuable resources if you’re not using it? Turning a module off completely disables it in the code. And the core of SFC itself is still written modularly, for maximum performance (since integrating Facebook itself is such a drag on performance for a site to begin with).

Support for new Facebook code

Over a year ago, Facebook stopped supporting the original Facebook Connect libraries. This was a major problem for sites, however the old code still worked. So as time went on, and the old Connect libraries started to degrade and become less and less useful, SFC was rewritten from the ground up to use all the newer supported libraries. Facebook’s JS SDK is used. FB’s Graph API is used. The old Facebook REST Platform code is completely gone, as are the older incompatible Facebook Connect libraries. OpenGraph meta tags (including embed info for images and video) are inserted into the entire site, completely automatically, allowing Facebook to see the content of your site and act accordingly.

Many of the plugins themselves have been rewritten fairly extensively as well, but with this comes some removal of older code.

Faux Share button settings

The Share button is gone. It was previously implemented using the older Connect libraries, but with the newer libraries from Facebook, it’s been completely removed. There was just no good way to retain it, Facebook has simply dropped any and all support for it. So, in it’s place (because it was so handy) is a modified Like button, which can still look sorta like the old Share button. The SFC module is still named Share, for ease of transition. The Like button itself is still around too, so you can use both Like and Share to get two Like buttons on the same post, perhaps for different placement.

The Bookmark widget is gone. It simply isn’t supported anymore, and didn’t work anyway.

The Find on Facebook widget is gone. This didn’t do really anything special to begin with, other than place the Find Us image into a widget, with a link to the Facebook Page. The image it once used is still included in the plugin, for people that want to do this themselves via a text widget.

The Connect widget is gone, but may make a return in the next version, as soon as some bugs are sorted out.

The Upcoming Events widget is gone. It rarely worked properly to begin with, and the newer XFBML libraries doesn’t have support for it anymore. A alternate approach to this may make it back into the next version.

All the remaining widgets have been combined into a single module for use on the widgets screen. In addition, most of them still have a way to access them directly, such as from a function call in a theme.

Publisher settings

The Publisher has been simplified greatly. For one, auto-publishing now works even for Applications! The confusing permissions dialogs have been reduced to one. Colored indicators have been added, showing when the plugin has the necessary “tokens” from Facebook in order to be able to publish properly. The manual publishing functionality is still on the edit post screens too.Β And for those people using the auto-publish, a new system for pulling Facebook comments on their published posts back into the blog has been implemented.

For those who wanted it, Custom Post Type support has been added to the publisher as well. Any CPT marked as “public” gets shared like everything else.

Register screen

The Register system has been completely rewritten to take advantage of Facebook’s new register plugin functionality. It can handle standalone registrations, or registrations using Facebook information. It even adds a Facebook created captcha to prevent spam registrations.

Login has been improved. One of the most common complaints was “What does ‘User not recognized’ mean?” This should be severely reduced now, since the Login module will auto-detect existing users and automatically connect their local WP accounts with their FB accounts, when they try to login. This follows Facebook’s own Registration Flow Models for connecting users to sites.

The Comment system has been improved. The share-after-comment system now happens in the background, no extra popups for users to have to click on. The whole system is now using the Graph API, so no more strange javascript errors causing weirdness. Although there is still some javascript to display the user their picture and info after logging in, so it still has that same look and feel.

There’s a lot more too. I’ll be updating this post with new stuff soon!

 

Shortlink:

First, WordPress plugin authors: Please don’t do this.

if ( isset($_GET['resource']) && !empty($_GET['resource']) ) {
	$resources = array(
		'icon1.png' => '... base 64 encoded code ...',
		'icon2.png' => '... base 64 encoded code ...',
		);

	if ( array_key_exists($_GET['resource'], $resources) ) {
		$content = base64_decode($resources[ $_GET['resource'] ]);
                header('Content-Length: '.strlen($content));
                header('Content-Type: image/png');
            	echo $content;
		exit;
	}
}

I’ve seen a few different versions of this, and while the idea is nice, this is really the wrong way to go about it.

The idea is to include small icons or images in the plugin file itself, instead of as separate files. This sort of code then lets you reference them by calling a URL of ?resource=icon1.png or whatever. When that resource variable is detected, the plugin kicks in and serves up the image instead of the site.

Advantages to this sort of thing:

  • No need for extra icon files

Disadvantages to this sort of thing:

  • Now every http request to get an icon file on your admin page results in loading up the WordPress code, causing extra CPU usage.

Here’s a better way. It’s called the Data URI.

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />

Here’s that code in action, right here: Red dot

Why this is better:

  • Same benefits as before, no need for extra icon files
  • No extra CPU load from loading WordPress to get that icon file
  • No extra HTTP requests at all, in fact, since the data for the tiny icon is contained right there in the code

Disadvantage:

  • Doesn’t work in IE7. You can work around this by detecting IE7 and serving up the image separately, if you really want. Or you can just ignore it like most people do. Seriously. IE7 is insecure (link, link) and nobody should be using it, anywhere. WordPress itself will probably drop IE7 support in the admin in the next couple of versions.

So use Data URIs for small images (under 32KB in size). They’re fast and easy. They’re an idea whose time has come.

Shortlink:

Google rolled out their +1 button today. So I added it here. You’ll find it below all the posts. Try it out.

Here’s the simple-stupid plugin I wrote to do it. While you can just edit your theme, I like making these sort of things into plugins. That way, I can turn them off at will, and I know exactly where to go to change them without having to dive into my theme code. Also, if I change themes, the code still works on the new theme.

<?php 
/* 
Plugin Name: Otto's Google +1 Button
Description: Add a +1 button after the content.
Author: Otto
Version: 999
*/

add_filter('the_content', 'google_plusone');

function google_plusone($content) {
	$content = $content.'<div class="plusone"><g:plusone size="tall" href="'.get_permalink().'"></g:plusone></div>';
	return $content;
}

add_action ('wp_enqueue_scripts','google_plusone_script');

function google_plusone_script() {
	wp_enqueue_script('google-plusone', 'https://apis.google.com/js/plusone.js', array(), null);
}

I wrapped the button in a div so that I could style it. In my particular case, I’m floating it right and giving it a margin, same as the Twitter and Facebook plugins. One day, I’ll make all these little Google plugins more generic and configurable, and roll them into a Simple Google Connect plugin. πŸ™‚

One thing I don’t like is that the +1 button only works for people who are logged into a GMail account. Sorry Google Apps users, you’re out of luck. Complain to Google until they fix it.

If you want to add more parameters to the plugin and reconfigure it, you can find out about the available parameters here: http://code.google.com/apis/+1button/#configuration

Shortlink:

I got tired of waiting for a “proper” YOURLS WordPress plugin to come out, so I did it myself. Hey, I’ve got other stuff to do, and I needed a working shortlink solution.

Basically, this is the “YOURLS: WordPress to Twitter” plugin, with all the Twitter bits removed.

While I was in there, I also fixed the password saving bug that I kept having in Chrome (just cut out the submit button JS), switched it to eliminate the Pear_JSON package entirely (WordPress has JSON support built in already), and did some other minor things. I’m sure I missed some bits, but for the most part it was really just a hack and slash job. Eliminated about 30% of the plugin’s main code and all the ancillary Twitter libraries.

On a side note, this sort of thing only reinforces something I’ve said before: Plugins should only try to do one thing, and to do it well. Trying to have a twitter solution in this plugin when I didn’t want to use that bit at all basically just made it stop doing the shortlinks correctly. That’s a real problem when it’s really a shortlink plugin to begin with. I already had a really good twitter solution, trying to have all this extra crap in there just made it not work properly.

If I had more time, I’d also remove all the JS stuff on the settings page too. That’s not really necessary when you only have a few fields to enter. But I guess it works, sort of. Whatever. Not important.

Anyway, here you go. I won’t be putting this in the plugins repository, since it’s not really my code. But I am posting it here in case it helps anybody. And if Ozh changes his plugin to eliminate the Twitter stuff (or to at least make it optional without impacting functionality), then it would be worth switching to that in the future. I won’t be supporting this plugin anytime soon.

YOURLS – WordPress (no Twitter)

Edit: Note that I did this mainly because I wanted to use my own Simple Twitter Connect instead for posting items to Twitter. That works fine and uses the shortlink from this plugin fine. But the extra Twitter stuff in the original plugin interfered with it, and there was no good way to disable that stuff short of editing the plugin. I’m a fan of not editing other people’s plugins, but in this case there really wasn’t a lot of choice. YOURLS is a good system and I like using it, I just wish the WP plugin for it wasn’t trying to do so much. Just so you know. πŸ™‚

Shortlink: