The perils of “nulled” WordPress themes

Having the largest ecosystem of any CMS ever, WordPress users have a lot of choice when it comes to themes. There’s thousands of open source offerings on as well as many more paid for ones on marketplaces such as Envato.

I recently wanted to assess the code quality of a few different paid themes before deciding on one to buy, so I downloaded some “not quit legitimate” copies from one of the many shady “nulled theme” sites, to run in a sandbox. Obviously you’d have to be a) quite immoral and b) an idiot to use such things in production, but I figured what’s the harm if the winning one’s going to be bought anyway.

After choosing the winner I thought I’d diff the two copies I had. Just how bad was the malware going to be?

Continue reading “The perils of “nulled” WordPress themes”

Local Theme Development on WordPress MultiSite

So this blog runs as part of my WP Multi Site network. Multi-site is great – one click to upgrade the WP core for all sites, one setup for caching etc.

One problem is local dev though. You don’t want to pull the whole network down to your local machine to work on a theme (it’d take ages) but you still want to develop against the posts and pages that are on the live site.

Interesting solution to this:

WP Multi-site stores DB tables with different prefixes for each site. So for instance you’d have wp_2_postswp_2_options etc. for site No. 2.

Let’s try altering a few bits in wp-config.php to make use of this:

define('WP_HOME', 'http://localsite.loc');
define('WP_SITEURL', 'http://localsite.loc');
define('DB_NAME', 'your_multisite_db');
define('DB_USER', 'your_multisite_user');
define('DB_PASSWORD', 'yourpw');
define('DB_HOST', '');
$table_prefix = 'wp_2_';

Finally create an SSH tunnel so you can access the DB running on your server on local port 3307 (Your local MySQL will be running on 3306). …..presuming you need to do this of course (article all about this here):

ssh -L user@yourserver -N

That done, you should be good to go! One important caveat with this method: wp_users and wp_usermeta tables are global to all sites in the Multisite network (along with a few others). Therefore you won’t be able to login on your local copy and anything involving users on the front end will be screwed (like displaying post authors for instance). This really wasn’t much of a problem for my purposes on this site though. …so I thought I’d share.

Hope this helps someone!

Fixing slow wp-cron requests on servers behind NAT routing

So we’ve been having a weird problem with WordPress installs on supposedly fast linux VMs running very slowly. It was mainly noticeable on server requests for the Dashboard by logged in users. After a bit of analysis using New Relic, we narrowed it down to external web requests taking a long time.

The trouble was, these requests were mainly pointed back to the server itself. For instance:


The actual load on Nginx & PHP processes was practically non-existent. PHP was just waiting for it’s cURL requests to come back. How strange.

As it turns out, the server was receiving all it’s network traffic via NAT, which meant that while resolved to, say, (an external IP), all the actual box was aware of was it’s internal IP, say The external was never directly configured as one of it’s network interfaces. This meant that requests like the above had to make a round trip all around the network and back again before they’d get processed. Not good.

Our solution was to setup an alias for the loopback interface so the external IP would behave exactly the same as when it was requested internally, and so never leave the box:

vi /etc/sysconfig/network-scripts/ifcfg-lo:1


“service network restart” or a quick reboot and job done!

This was on CentOS 6.5 btw, but I’m sure it’s pretty similar for Ubuntu or any other flavour of Linux.

Large Menus in WordPress

I recently had a problem where a very large nav menu (200+ items) in WordPress wouldn’t save without cutting off the last few items. Turns out it isn’t a WordPress bug but to do with PHP configuration. In your php.ini, up this value and all should be good:

[bash]max_input_vars = 4096[/bash]

You may also have to up these, depending on if you’re running Suhosin on your production box (PHP security stuff):

[bash] = 4096
suhosin.request.max_vars = 4096[/bash]

The problem arises because WordPress posts the entire structure of the nav menu back to the server every time it saves it. Not exactly great when you’re dealing with large navigation I know. Sure there must be a better way, although I suppose it’s not exactly what WP was designed for. Anyway. Strange but true.