Awnist

Get a list of the most active IPs based on specific urls in Apache logs

grep KEYWORD access.log | grep KEYWORD2 | awk ‘{print $1}’ | sort -n | uniq -c | sort -rn

Migrating WP users to WPMU

This technique will migrate:

  • Usernames
  • Email
  • Password

It does not concern itself with

  • User meta
  • Anything else

It assumes

  • Admin on WPMU has already been created.
  • Admin on original WP install is user id #1
  • All new users are subscribers on blog #1 in WPMU

Firstly, run this sql in your mysql install:

select concat('Array(', concat_ws(', ', quote(user_login), quote(user_email), quote(user_pass)), '),') from wp_users where id != 1

Now drop this script into the base directory of your WPMU install. Paste the results from above where noted.

<?

$users = Array(
	// Array('example user', 'user email', 'user password hash'),
	// PASTE RESULTS FROM MYSQL HERE
);

require_once("wp-config.php");
require_once("wp-includes/registration.php");

foreach ($users as $v) { add_user($v[0], $v[1], $v[2]); }

echo "Done.";

function add_user($user_login, $user_email, $password)
{
	global $user, $wpdb, $allowedtags, $blog_id;

	$wpdb->show_errors();

	if (username_exists($user_login))
		return;

	if (email_exists($user_email))
		return;

	echo "$user_login..";

	if ( ! $user_id = wpmu_create_user($user_login, 'temp', $user_email) )
	{
		print_r(new WP_Error('create_user', __('Could not create user'), $user_id));
		exit;
	}

	add_user_to_blog(1, $user_id, 'subscriber');
	update_usermeta($user_id, 'source_domain', 'YOURDOMAIN.COM');
	do_action('wpmu_activate_user', $user_id, $password, Array());
	$wpdb->query("UPDATE wp_users SET user_pass = '$password' WHERE ID = '$user_id'");
}

?>

The end.

CakePHP controller for Imagemagick

URL Example:

http://yourcakedomain.com/images/thumbnail/100_1/example.jpg

This would load the source image (example.jpg), apply Imagick::thumbnailImage(100, 100, 1) to the file, then save it in a special cache directory.

You may also define your own methods within the controller.

Before images are loaded, _preimage_{method} functions are checked for existence. this allows you to change image paths and do any other preliminary data calls you may need.

Once the image is loaded into memory, _image_{method} functions are called.

One example included is _preimage_in(), which redefines the source image before anything is loaded by Imagick:

http://yourcakedomain.com/images/in/infile.gif/outfile.jpg

Another example is _image_addborder(), and would be called similarly:

http://yourcakedomain.com/images/addborder/10_10/example.jpg

Both image methods and filetypes are whitelisted, so make sure you update $whitelisted_* if you want access to new methods.

Lastly, you can stack methods as you wish:

http://yourcakedomain.com/images/thumbnail/100_1/addborder/10_10/example.jpg

But you may want to hide method arguments from public view with custom methods.

Add the following to your routes files to remove the view method from the URL:
config/routes.php

Router::connect('/images/*', array('controller' => 'images', 'action' => 'view'));

because /images/stuff is prettier than /images/view/stuff.

controllers/images_controller.php

<?php
/**
 * Imagemagick controller
 *
 * This controller processes images with PHP Imagick and serves up cached files.
 * It takes arguments as key/value pairs in URL, and supports custom methods.
 * 
 * _preimage_{method name}() and _image_{method name}() functions defined in
 * this class are given priority. If they don't exist, Imagick methods are
 * checked also.
 *
 * Example:
 * http://mysite.com/images/method/argument_argument/image.jpg
 *
 * Would first run
 * 	_preimage_method(argument, argument)
 * before the image is loaded, and then run
 * 	_image_method(argument, argument)
 * after the image is loaded.
 * 
 * Methods can be stacked as so:
 * http://mysite.com/images/method1/argument_argument/method2/argument_argument/image.jpg
 *
 * If desired, arguments can be hidden from public access with a custom method:
 * function _image_t () { $this->im('thumbnail',Array(100,1); }
 * Would allow for thumbnail creation with this URL:
 * http://mysite.com/images/t/_/image.jpg
 *
 *
 * PHP version 5 and Imagick library are required.
 *
 * Comments and bug reports welcome to http://awnist.com/
 *
 * Full list of Imagick methods: http://www.php.net/imagick
 * See also: http://cvs.horde.org/co.php/framework/Image/Image/imagick.php
 * 
 * Licensed under The MIT License
 *
 * TODO: - relative paths
 *       - restrict number of args
 *       - check and enforce argument integrity
 *       - allow for image methods with no args (use /method/_/ for now)
 *       - solve for long cache names
 *
 * @writtenby      Awnist
 * @lastmodified   Date: March 7, 2009
 * @license        http://www.opensource.org/licenses/mit-license.php The MIT License
 */ 

class ImagesController extends AppController {

var $uses = array();

/**
 * Full path to cache directory. Images should be cached after creation
 * due to the process-heavy nature of Imagemagick.
 *
 * @var string
 * @access public
 */
var $dir_cache = '/full/path/to/cache/';

/**
 * Full path to source image directory. This is not technically required
 * if you are supplying images programmatically, but it is convention
 * otherwise.
 *
 * @var string
 * @access public
 */
var $dir_images = '/full/path/to/source/images/';

/**
 * List of allowed methods to be called from URL. You can directly expose
 * Imagick methods by listing them here, but it's probably a better idea
 * to only expose custom methods that check and enforce argument ranges.
 *
 * @var array
 * @access public
 */
var $whitelist_methods = Array('in','thumbnail','addborder');

/**
 * Pipe delimited string of allowed image/file extensions. You can
 * technically read anything that Imagemagick can, but it's a good
 * idea to limit at this level for security's sake.
 *
 * @var string
 * @access public
 */
var $whitelist_types = 'gif|jpeg|jpg|png|bmp|tif';

/**
 * Full image URL to redirect to on fatal errors. This should be outside
 * of this controller's reach to prevent infinite loops.
 *
 * @var string
 * @access public
 */
var $image_error = 'http://mysite.com/global/images/nav-dot.gif';

/**
 * When this image is supplied as source image, don't load anything. This is for
 * custom methods that supply their own source image or create one programmatically.
 * Example: "/images/in/loadme.gif/image.jpg" would load "loadme.gif" and save as jpg.
 * "image.jpg" is the dummy image, only provided as a convenience to the browser. 
 *
 * @var string
 * @access public
 */
var $image_dummy = 'image.jpg';


/**
 * Character to split method arguments in URL.
 * Example: /resize/100_100/ would call the resize method with
 * (100,100) as arguments.
 *
 * @var string
 * @access public
 */
var $arg_delimiter = '_';


/**
 * Eventually contains the type of image that was requested (jpg, gif, etc.)
 *
 * @var string
 * @access public
 */
var $request_type = null;

/**
 * Eventually contains the file name of the source image (without path)
 *
 * @var string
 * @access public
 */
var $image_name = null;

/**
 * Eventually contains the full file path of the source image.
 *
 * @var string
 * @access public
 */
var $image_source = null;

/**
 * Eventually contains the file name of the cached image (without path)
 *
 * @var string
 * @access public
 */
var $cache_name = null;

/**
 * Eventually contains the full file path of the cached image.
 *
 * @var string
 * @access public
 */
var $cache_source = null;


function beforeFilter() {
	// Pull last element in url off as image. (foo/bar/image.jpg)
		$this->request_name = array_pop($this->params['pass']);

	// Check image suffix against whitelist
		if (!preg_match('/^.+\.('.$this->whitelist_types.')$/',$this->request_name,$matches))
			$this->_serve_error();

	// Set request_type to the requested image type
		$this->request_type = $matches[1];

	// If the image matches $image_dummy, we don't want to load the source image.
		if ($this->image_dummy != $this->request_name)
			$this->source_name = $this->request_name;
}

function view() {
	// Iterate through url arguments and make sure they're all whitelisted actions. 
		$p = &$this->params['pass'];
		$_actions = Array();

		// TODO: bug, this will break if current($p) = 0
		while ($u = current($p)) 
		{
			if (array_search($u, $this->whitelist_methods) !== false)
				$_actions[$u] = next($p);

			next($p);
		}

	// If there are no valid actions found for image, serve the original.
		if (!$_actions)
			$this->_serve_image($this->dir_images . $this->request_name);

	// Alphabetize array so files are cached uniformly if url args are out of order.
		$_cactions = $_actions;
		ksort($_cactions);

	// Run prefilters on image
		foreach($_actions as $k=>$v)
		{
			// Check for method _preimage_{function} in this controller
			if (method_exists($this, '_preimage_'.$k))
				call_user_func_array(array($this, '_preimage_'.$k), explode($this->arg_delimiter, $v));
		}

	// See if the source file has been set yet, and append directory if needed
		if (!$this->image_source && $this->source_name)
			{ $this->image_source = $this->dir_images . $this->source_name; }

	// Check if the requested source image exists
		if ($this->image_source && !file_exists($this->image_source))
			$this->_serve_image(false);

	// If cache name was not set in a _preimage method, generate it programmatically.
		if (!$this->cache_name)
			{ $this->cache_name = preg_replace('/[^\w]/', '', urldecode(http_build_query($_cactions, '', '_'))).'_'.$this->request_name; }
		else
			{
				// TODO: normalize user-supplied cache_name here
			}

	// Set full path to cache file
		if (!$this->cache_source)
			$this->cache_source = $this->dir_cache.$this->cache_name;

	// Decide if we should serve the cached file
		if(	(!$this->image_source &&
			file_exists($this->cache_source)) ||

			($this->image_source &&
			file_exists($this->cache_source) &&
			@filemtime($this->cache_source) > @filemtime($this->image_source))
		){
			$this->_serve_image($this->cache_source);
		}

	// Begin processing image with Imagemagick
		$this->imagick = new Imagick();

		if ($this->image_source)
			$this->im('readImage', $this->image_source);

	// Apply each of the requested methods.
		foreach($_actions as $k=>$v)
		{
			// check for method _image_{function} in this controller
			if (method_exists($this, '_image_'.$k))
				call_user_func_array(array($this, '_image_'.$k), explode($this->arg_delimiter, $v));

			// check for method Imagick::{function}Image()
			elseif (method_exists($this->imagick, $k.'Image'))
				$this->im($k.'Image', explode($this->arg_delimiter, $v));

			// check for method Imagick::{function}()
			elseif (method_exists($this->imagick, $k))
				$this->im($k, explode($this->arg_delimiter, $v));
		}

	// Set cache filename in Imagemagick
		$this->im('setImageFileName',$this->cache_source);

	// Set image format to the requested type
		$this->im('setFormat',$this->request_type);

	// Write to cache
		$this->im('writeImage');

	// Display the image
		header("Content-type: ".$this->im('getFormat'));
		echo $this->im('getimageblob');
		exit;
}

/**
 * Wrapper to perform safe Imagick methods with try and catch.
 *
 * Accepts alternate usage with multiple Imagick calls passed within
 * first argument as Array: Array('method'=>Array(args), 'method'=>Array(args),..)
 *
 * @param string $method Imagick method to run
 * @param array $args Args to pass into method
 * @access public
 */   
function im($method, $args=null)
{
	if (gettype($method) == 'array')
	{
		foreach ($method as $m=>$a) { $this->__im($m,$a); }
	}
	else
	{
		return $this->_im($method,$args);
	}
}

/**
 * Sub-wrapper that actually runs methods and traps errors. Should
 * not be used directly.
 * 
 * @param string $method Imagick method to run
 * @param array $args Args to pass into method
 * @access protected
 */
function _im($method, $args=null)
{
	if (!method_exists($this->imagick, $method))
		return;

	if (gettype($args) != 'array')
		$args = Array($args);

	try {
		return call_user_func_array(array($this->imagick, $method), $args);
	} catch (ImagickException $e) {
		$this->_serve_error();
	}
}

/**
 * Serves images from local filepaths.
 * 
 * @param string $image Full path of image to serve
 * @access protected
 */
function _serve_image($image=null) {
	if ($image && file_exists($image))
		{
			// Kludge
				$size	= getimagesize($image);
				$mime	= $size['mime'];
			$data = file_get_contents($image);
			header("Content-type: $mime");
			header('Content-Length: ' . strlen($data));
			echo $data;
			exit;
		}
	else
		{ $this->_serve_error(); }
}

/**
 * Redirects users to error image. 
 * 
 * @access protected
 */
function _serve_error()	{ $this->redirect($this->image_error); }



//----------------
// Begin custom image methods.
// These are called from the URL and applied to images.
//----------------

// Example custom _preimage method. This will grab a different source file.
// This technique is handy for converting files: /in/convert-me.gif/outfile.jpg
function _preimage_in ($image) { $this->source_name = $image; }

// Example custom _image method.
// Call it with /images/addborder/width_height/image.jpg
function _image_addborder ($border_width, $border_height) {
	$this->im('borderImage', Array(new ImagickPixel("white"),$border_width,$border_height));
}


}
?>

CakePHP whmcs module – interacting with whmcs api via Cake

<?php

App::import('Core', array('HttpSocket'));

class WhmcsComponent extends Object {
/**
* WHMCS component
*
* Rudimentary wrapper for curl-based API connection to WHMCS.
*
* PHP version 5
*
* Licensed under The MIT License
*
* @lastmodified    Date: March 24, 2009
* @license        http://www.opensource.org/licenses/mit-license.php The MIT License
*/

/**
* URL of WHMCS api.
*
* @var string
* @access public
*/
var $api_url = 'http://yoursite.com/whmcs/includes/api.php';

/**
* Admin username for WHMCS access
*
* @var string
* @access public
*/
var $api_username = 'adminuser';

/**
* Admin password for WHMCS access
*
* @var string
* @access public
*/
var $api_password = 'adminpassword';

/**
* Holds last WHMCS resultset
*
* @var array
* @access public
*/
var $last_result = Array();
function __construct() {
$this->Http = new HttpSocket();
}

/**
* Raw access to WHMCS API. Throws warning and returns false on any error, returns array-based resultset otherwise.
*
*    $this->Whmcs->api('addclient', Array(
*        "firstname" => "test",
*        "lastname" => "test",
*        "companyname" => "test",
*        "email" => "test@test.com",
*        "address1" => "test",
*        "address2" => "test",
*        "city" => "test",
*        "state" => "test",
*        "postcode" => "1231231",
*        "country" => "test",
*        "phonenumber" => "5551212",
*        "password2" => "test",
*    ));
*
* @param string $action WHMCS action to be performed. ("addclient" for example)
* @param array $data Array of data to be sent to WHMCS.
* @access public
*/

function api($action, $data)
{

// Make sure WHMCS username and password have been set
if ($this->api_username == 'adminuser' || $this->api_password == 'adminpassword')
{
trigger_error(__('Can\'t connect to WHMCS without api username and password.', true), E_USER_WARNING);
return false;
}
// Data to be sent to WHMCS.
$_pass_data = array_merge(
Array(
"username" => $this->api_username,
"password" => md5($this->api_password),
"action" => $action,
),
$data
);

// Connect to WHMCS
$_result = $this->Http->post($this->api_url, http_build_query($_pass_data));

$code = (int)$this->Http->response['status']['code'];

if ($_result === null || $_result === false || preg_match('/^(4|5)/', $code))
{
trigger_error(__(
'Error from HttpSocket: HTTP code '.$code.
($this->Http->lastError()?', HttpSocket error code: '.$this->Http->lastError():'')
, true), E_USER_WARNING);
return false;
}
// Parse returned data from WHMCS
$_return = Array();

foreach (explode(';', $_result) as $x)
{
parse_str($x, $a);
$_return = array_merge($_return, $a);
}
$this->last_result = $_return;
// Check for invalid dataset
if (count($_return) == 0)
{
trigger_error(__('WHMCS returned empty result set.', true), E_USER_WARNING);
return false;
}

// Check for WHMCS result error
if ($_return['result'] === 'error' && preg_match('/^Authentication/', $_return['message']))
{
trigger_error(__('WHMCS returned error: '.$_return['message'], true), E_USER_WARNING);
return false;
}

// Return WHMCS data
return (array)$_return;
}

}
?>

Recursively find PHP files with trailing spaces after the PHP close tag

# ruby -e ‘Dir.glob( “**/*.php” ) { |file| puts file if IO.read(file).match( /?>s{2,}Z/m) }’

Easily upgrade Ubuntu from commandline using update-manager-core

Used to upgrade from Hardy Heron to Intrepid Ibex. Super easy.

  1. # sudo apt-get install update-manager-core
  2. # sudo vi /etc/update-manager/release-upgrades
  3. change Prompt=lts to Prompt=normal
  4. # sudo apt-get update
  5. # sudo do-release-upgrade

    Checking for a new ubuntu release
    Done Upgrade tool signature
    Done Upgrade tool
    Done downloading
    extracting ‘intrepid.tar.gz’
    authenticate ‘intrepid.tar.gz’ against ‘intrepid.tar.gz.gpg’

    Do you want to start the upgrade?

    11 packages are going to be removed. 56 new packages are going to be
    installed. 493 packages are going to be upgraded.

    You have to download a total of 307M. This download will take about
    21 minutes with your connection.

    Fetching and installing the upgrade can take several hours. Once the
    download has finished, the process cannot be cancelled.

    Continue [yN]  Details [d]