WishlistCast goes open source

Over 5 years ago, I released the first version of Wishlistcast – a plugin to link the Nanacast shopping cart and the popular Wishlist Member membership plugin for WordPress.

Since its release, countless folks have downloaded the free Wishlistcast plugin – and it has benefited greatly from the feedback provided.

In addition, it has connected me with clients, fellow WordPress enthusiasts, Nanacast specialists and opened doors to a wide range of diverse coding projects.

It’s been an absolute blast and I’ve thoroughly enjoyed the ride.

However… all things come to an end… and after turning down several WordPress membership projects this year, and too often finding “wishlistcast”-related queries at the bottom of my inbox – I’ve realised it’s time for me to open Wishlistcast up so others can work on it.

To that end I have open-sourced the code for Wishlistcast. Any WordPress-PHP developer can now access and feel free to modify the code here:

https://github.com/steveovens/wishlistcast/

You can download the latest version of the plugin here:

https://s3.amazonaws.com/wishlistcast/wishlistcast_v1.5.2.zip

You can get the “PRO” version (previously only available to my personal clients) here:

https://s3.amazonaws.com/wishlistcast/wishlistcastpro_v1.5.2.zip

Note that these are offered completely on an “as-is” basis. (They DO work with latest WordPress and Wishlist Member and Nanacast). I can no longer offer any sort of support or installation service for these plugins. If you need technical help, then any competent WordPress developer will be able to get these up and running. Sites like UpWork.com or Fiverr.com are a good place to find skilled people for small tasks. If you need WordPress specialists for larger projects, then I HIGHLY recommend TopTal.

And if you’re wondering what I’m up to…

Nowadays I’m focussing on realtime and mobile app development using full-stack Javascript and MongoDB (Meteor) – which is quite different from WordPress/PHP and MySQL. If you’re interested, you’ll find me over at wellcraftedapps.com.

WishlistCast Plugin Security

A client of mine recently had some dramas with HostGator making an unannounced modification to her server’s mod_security which broke her site – specifically, it blocked Nanacast from talking to WishlistCast – so her new members that bought her online program were not getting added to her Wishlist membership. You can imagine the implications to her business. This is the exact issue I describe in more detail here, which is the most common cause of “Wishlistcast not working” emails and skype messages I receive. When speaking to Hostgator support, they provided my client with this information:

(11:03:30pm)HG Support.:I would highly recommend you contact that plugins developer. Any developer worth thier salt knows sending anything via GET is highly insecure.
(11:03:44pm)HG Support.:This is especially true when sending a security code, like was the case here.
(11:03:50pm)client:which developer
(11:03:57pm)HG Support.:The one for wishlist
(11:03:57pm)client:wishlist
(11:04:27pm)HG Support.:Sending a jumble of letters like that is seen by nearly any security software as a spam request, cause frankly it looks like one
(11:04:39pm)client:oh ok
(11:04:56pm)HG Support.:Combine this with WordPress’s javascript concatenation, and you have a spammy request URI and jumbled javascript being sent via an ajax call to another file.

Anyway, ignoring the complete FUD about javascript concatenation and Ajax requests (which have nothing to do with anything here), and the dig at my potential lack of developer salt-worthiness (really? I’m crushed!), I thought it would be constructive to transparently explain the design and security implications of using the Wishlistcast plugin. I am open to any constructive feedback and suggestions for improvement.

Background / Overview

The WishlistCast plugin adds an api end-point URL to your Wishlist site (http://www.yoursites.com/wp-content/plugins/wishlistcast/wishlistcast_api.php), allowing Nanacast (or technically another program) to add new users to your Wishlist membership.
When a new user is added to your Nanacast membership, Nanacast makes an Outgoing API call to the WishlistCast plugin API requesting it to “add a new user”. The Outgoing API call is a HTTP request – and the information WishlistCast needs to authorise and fulfill the request is sent as a combination of GET and POST parameters.
In order to authenticate the request, WishlistCast uses a “security_code” parameter, which is unique to your wishlist installation. You can think of this as an “API key”.
Because Nanacast can be configured to send multiple (up to 5) Outgoing API requests, and each of these can go to potentially different wishlist installations, the security_code parameter is sent as a GET parameter (so it can hold a different value for each Outgoing API Request).
In English what this means is – if you have multiple Wishlist membership sites, and you want to add someone to single Nanacast membership and have this add them to all of your wishlist sites, Nanacast needs to talk to each site individually. To do this within Nanacast’s design, you must pass the security_code as a GET parameter so it is unique to each outgoing call.

Security Implications of Using GET Parameters

The main security concerns around GET parameters, is that – because they form part of the URL – they are cached in a user’s browser, and are also open to being “packet sniffed” if sent over a WiFi network (e.g. browsing at your local coffee shop). They are also commonly recorded in your server’s history logs – where they are available if someone has access to (or hacks) your computer server.
However – in our case – it is not users who are browsing to the wishlistcast_api.php URL – so there are no concerns with browser history or WiFi packet sniffing.
The HTTP request is being sent from Nanacast directly to WishlistCast. It is a computer-to-computer call, with no humans or browsers in between.
So – the only real issue is that the URL with the security_code parameter might be visible in your server log. Of course, if someone has access to your server log, there are far easier ways for them to do damage than trying to figure out how to hack some obscure wishlistcast_api…

How WishlistCast Handles the Nanacast Request

Here is the code from the top of the WishlistCast plugin:
$f = array_merge( $_POST, $_GET );

// v1.4.6 introduce transaction logging with replay capability (for use by support)
$replaying = false;
if ( array_key_exists( 'replay', $f ) || !empty( $f['replay'] ) ) {
 // Note: The transaction replay functionality is not included in the public release
 if ( file_exists( dirname( __FILE__ ) . '/replay/replay_txns.php' ) ) {
 include_once(dirname( __FILE__ ) . '/replay/replay_txns.php');
 }
}

if ( !array_key_exists( 'mode', $f ) || $f['mode'] == '' ) {
 return; // Not executing as a result of being called from Nanacast - probably plugin activation
}
As you can see – the very first line of code merges the GET and POST parameters into a single array of parameters (called “$f”) – with priority given to the GET parameters in case of duplicate parameter names.
Then there is a block of code that checks if this is a transaction replay. The code to support “replay” functionality  is only available in my personal copy of the plugin and is used for support purposes – so even if someone sent a “replay” parameter, the file_exists check would fail.
Finally, there is a “sanity check” test to see if the “mode” parameter is present. This early check essentially tests to see if this call most likely originated from Nanacast, which ALWAYS sends a “mode” parameter. If this “mode” parameter is not present, the code returns (ends) immediately. You can see this for yourself if you visit the wishlistcast_api.php URL in your browser – you will just get a blank screen.
After this, there is some code to hook WishlistCast to WordPress (so we can talk to Wishlist) as well as set up logging. Note that adding Wordpress happens AFTER we have already grabbed our GET and POST parameters into $f. WordPress is not processing our parameters or doing any kind of javascript concatenation or Ajax mumbo-jumbo.
Then, there is this code to authenticate the request:
if ( isset( $f['verify_field'] ) && isset( $f['verify_value'] ) && ($f[$f['verify_field']] != $f['verify_value']) ) {
 logmsgandClose( 'Request ignored. Verification failed: ' . $f['verify_field'] . ' value is [' . $f[$f['verify_field']] . ']. Verification value is [' . $f['verify_value'] . ']' );
 return;
}

// Check secret key matches Wishlist Generic secret key from Wishlist Integration panel
if ( class_exists( 'WLMAPI' ) ) {
 $wishlist_security_code = WLMAPI::GetOption( 'genericsecret' );
 if ( $wishlist_security_code != '' && $wishlist_security_code != $f['security_code'] ) {
 logmsg( "Incoming Secret Key '" . $f['security_code'] . "' does not match the Secret Key in WishList Generic Integration settings", PEAR_LOG_NOTICE );
 die( "Incoming Secret Key '" . $f['security_code'] . "' does not match the Secret Key in WishList Generic Integration settings" );
 }
 unset( $wishlist_security_code );
}
The first block is an undocumented feature that allows you to add a verification field and value to the request – which allows you to control whether a particular request is handled or not. The specific use case for this is a client I had who wanted to manually verify payments before adding users to a membership. So I created a hidden “is_paid” field inside their nanacast membership with a default value of “N”, and on receipt of payment, he would edit the users nanacast membership and change the field to a “Y”. Ugly but effective. The verify field name was set to is_paid and the verify value was set to “Y”.
The second block compares the security_code parameter with the Wishlist Generic Secret code from your Wishlist installation.
You will notice that (if logging is enabled) I do log the (incorrect) security code that was passed in, however I do NOT log the expected value. So someone browsing the wishlistcast log file would not be able to use this to uncover the real security code.

TL; DR – Short Version

The wishlistcast_api code is designed with a set of sensible security checks at the start of the code to ensure that only valid, authenticated requests are processed. All of the code in the wishlistcast plugin follows best coding security practises to the best of my knowledge.

What About Using HTTPS?

You could install a SSL certificate on your site and send the request using an encrypted HTTPS call. Because the call is secured at the network level, this would make the call unreadable to an attacker who is able to monitor the network traffic between nanacast and your wishlist server. However, the URL (with parameters) would probably still appear unencrypted in your server logs, so this would result in NO improvement in security.

What Do You Think?

I am open to comments, constructive feedback and suggestions for improvement. Please comment below!

Wishlistcast Plugin Not Working?? Read This…

The WishlistCast plugin is used by hundreds of sites worldwide, and is tested against latest WordPress (3.8.1) and latest Wishlist (2.80.2002 at time of writing). It will generally work with older versions of both WordPress and Wishlist too, though I recommend staying up-to-date wherever possible.

So what happens if you’ve configured it all and it still isn’t working for you?

Or worse – it was working fine, and suddenly stopped working.

Well, there are really only two things that can be wrong:
1) Something is amiss in your configuration, or,
2) Something is blocking the call from getting from Nanacast to the plugin

Checking your configuration
From helping a number of people debug issues in their configuration, the most common mistake I see is spaces being added to the front, end or even in the middle of the Outgoing API when it is copied into the Nanacast setup. There should be no spaces anywhere in this URL. Or quotation marks for that matter! You should be able to copy and paste the URL into your browser. You should see a plain white screen. If you see an error message, then that’s probably the clue you are looking for.

 

Is the call being blocked?
Another common issue is when the call from nanacast is not reaching the wishlistcast API. In every case I’ve investigated so far, this has been caused by over-zealous mod_security rules put in place by the hosting company. In this situation, you need to contact your hosting company and get them to identify and white-list the mod-security rule.

You can check whether the call is getting through by examining the Outgoing API Call Log inside your Nanacast account. It’s a little hidden away in the menu – here is the direct URL (you need to be logged in to your account):

http://nanacast.com/api/outboundlogging.php (Outbound API Call Log)

See the notes below on how to check the Outgoing Call Log for issues.

It was working – and it has suddenly stopped working
Ahhh.. my favorite kind of bug. The mysterious “it stopped working” bug.

After over 30 years of creating software, I can say with some degree of certainty, that if a piece of software has been working fine and then suddenly stops working, then 99.9% of the time, something has changed to cause it to stop working. (The 0.1% allows for unanticipated conditions in the code itself – remember the “Y2K bug” that was going to bring an end to civilisation as we know it… but I digress… back to Wishlistcast…)

If you have just upgraded WordPress, or Wishlist, or changed your membership levels, or upgraded to a new version of the Wishlistcast plugin, then it is possible that one of these upgrades is the culprit.

If you’ve just installed a new plugin (for example a security plugin for WordPress – particularly if you’ve used that security plugin and/or manually managed to change the location of your wp-content directory), then the new plugin might be causing havoc.

If nothing has been changed in your WordPress setup – then quite probably it is not the software that has stopped working that is at fault.

Like when I upgraded my Mac earlier this year and suddenly my scanner stopped scanning. The scanner had not changed. But the software that talks to it (Mac OSX Mavericks in this case) certainly had.

In this situation – chances are you will find the culprit by examining the Outgoing API Call Log in Nanacast.

Checking Outbound API Log – What You SHOULD See

wpid335-Checking_Outbound_API_Log_-_What_You_SHOULD_See.png

This is what the Outgoing Call Log should look like on a successful call.

If you click on the “Data” area, you will see all of the parameters being passed by nanacast to the plugin. These should include the members email address and password.

When you click on the “Server Response” area you will see what Nanacast received as a response to the call.
Note that you have to click on the Server Response to see the error in the response – an empty value in the column does not indicate a blank response!

If everything is working, this will usually be empty – which shows up as a small white box when you click on it.

Outbound API Log – What An Error Response Looks Like

wpid336-Outbound_API_Log_-_What_An_Error_Response_Looks_Like.png

This is an example of what the Outgoing Call Log will look like if the server response is NOT what we want to see.

This example is the dreaded Mod_Security issue – which means that your server host is blocking the call. (You need to contact your hosting support to help resolve this).

You may also see “403 – Forbidden” errors – for example if a WordPress security plugin is preventing the call getting through.

Or “404 – Not Found” errors if you have a bad URL in the Outgoing API.

A side note on Mod_Security:
Be aware that Mod_security issues are more difficult to debug than other server issues – and my experience has been that the front-line support person won’t be able to spot the issue.

As an example – here is a direct quote from a hosting support person in a situation where I KNEW the call was getting blocked by mod_security (because I could see the message in my Nanacast Outgoing API Log):
“Adam R.:We are not seeing any mod_sec rules being hit by that URL.”

Given that the server is very clearly responding with a message telling me that mod_sec rules ARE being hit… well, let’s just say I tend to believe the computer in this case – they aren’t good at making stuff up… 🙂

Keep in mind that these poor over-worked and under-appreciated folks are usually following a standard trouble-shooting checklist, and are likely incented to close calls as quickly as possible. If they can tell you “no problem here” and move on to the next call in the queue, then that is a good outcome for them.

Unfortunately – the checklist has them looking in the wrong place. Typically they look at the server error logs – which don’t show mod-security issues.

To see the mod_security issue and figure out which rule is being triggered, they will need to get a server admin to use ‘apachegrep’ to specifically look for your domain while you are triggering the rule (for example, by manually adding a member through Nanacast).

Once they know which rule is being tripped, they can whitelist that rule for your site – preferrably JUST for the wishlistcast_api.php URL being called from nanacast.

If the calls are being blocked by Mod_Security, then the only people that can help you unblock it are your server admins – i.e. your hosting company. Unfortunately – there is nothing Nanacast support or I can do to “work around” the problem. The only way this can get resolved is for your hosting company to take ownership of and resolve the issue for you.

If you are really stuck, then go to Fiverr.com or UpWork.com and hire a WordPress expert for a couple of hours. And if it takes them more than a couple of hours, then trust me, they aren’t an expert!

Need more than a quick fix?
If you need a full custom membership site built from scratch, then get in touch with Jon Hollenberg at FiveByFive. Jon literally wrote the book on WordPress – the Five-By-Five team do awesome work!

 

Disable the WordPress Upgrade Nag

I love WordPress – it’s awesome and it let’s me build fantastic and functional sites for my clients.

But I HATE that upgrade nag you get whenever a new release comes out.

Because invariably, one of my clients will log in, see the “WordPress 3.0 is available! Please update now.” message, and think that they are supposed to click the link. And you can guess the rest of the story… we’ll spend the next 2 hours restoring the site from backup because two of their critical plugins aren’t yet compatible with the latest version of WordPress.

As an aside, I’ve lately been using iTheme’s brilliant BackupBuddy plugin to copy client’s entire sites to a test domain to trial new plugins and generally test upgrades. Highly recommended – really makes transferring sites between domains a snap!

Anyway, I finally decided to bite the bullet and hide the upgrade nag message for everyone who is logged in to the site except for me.

Here’s the code I used – it goes in your theme’s functions.php file – or custom-functions.php if you’re using Thesis. Obvioulsy change the user name from “steve” to YOUR user name (check top-right corner of Admin dashboard – Howdy, xxxxx).

function hide_update_notice() {
 global $user_login , $user_email;
 get_currentuserinfo();
 if ($user_login != "steve") {
 remove_action( 'admin_notices', 'update_nag', 3 );
 }
}
add_action( 'admin_notices', 'hide_update_notice', 1 );

I borrowed heavily from http://gunnerpress.com/wordpress/disable-non-admins-from-seeing-the-wp-version-update-notification and Yoast’s http://yoast.com/disable-update-nag/ in pulling this together. Thanks!