WordPress, concrete5, ZF2, PHP, mysql database dump

Here is a very simple script that once uploaded locks onto various architectures and extracts the database using the captured details.

For example, wordpress and concrete5 have been detected here:

Screenshot from 2017-03-22 11-18-40

When nothing is detected it will still offer the manual entering of the username and password.

Screenshot from 2017-03-22 11-18-47

It currently supports Concrete5 and WordPress, but I can easily upgrade it to support many more like ZF1, ZF2, Magento, Drupal, Joomla, etc, if there is any interest.

This is handy when you need to quickly copy a database, you simply upload this script to the doc_root and the script will attempt to handle the rest for you.

The script comes with password protection to prevent unauthorised usage, or it will not just be you downloading the database.

Screenshot from 2017-03-22 12-28-36

The script stores the username and password of those authorised to use it within the code, the password can be entered in plain text, or you can define your own algorithm and store the password encrypted in this way, within the code.

The script can be downloaded from github here and the full source code is below.

/*


Adrian Callaghan 21 Mar 2017 

Very lightweight database dumper that automatically locks access details provided by other PHP frameworks



****** How to use ******

Enter your usernames and passwords into the constructor in either plain text (insecure if read by someone else) or encypted



Example 1: allowing bob access with the password 1234 and joe access with password 5678 - no encryption 

	dbDump::Init(array(
		'users'	=> array(
			array('username'=>'bob','password'=>'1234'),
			array('username'=>'joe','password'=>'5678'),
		)));



Example 2: allowing bob access with the password 1234 and joe access with password 5678 - with encyption method and hashed passwords that must match the method result

	dbDump::Init(array(
		'users'	=> array(
			array('username'=>'bob','password'=>'81dc9bdb52d04dc20036dbd8313ed055'),
			array('username'=>'joe','password'=>'674f3c2c1a8a6f90461e8a66fb5550ba'),
		),
		'passwordEncryption'=>function($pass){
			return md5($pass);
		}
	));

*/




/******************

Constructor

*******************/
dbDump::Init(array(
	'users'	=> array(
		array('username'=>'bob','password'=>'81dc9bdb52d04dc20036dbd8313ed055'),
		array('username'=>'joe','password'=>'674f3c2c1a8a6f90461e8a66fb5550ba'),
	),
	'passwordEncryption'=>function($pass){
		return md5($pass);
	}
));







/******************

Class starts...

*******************/
final class dbDump{

	const APP_STATE = 'state';
	const APP_AUTH 	= 'MY_TOKEN';
	const APP_SALT  = 'MY_SALT';

	private $_users;
	private $_passwordEncryption;

	protected function destroySession(){
		$this->initSession();
		session_destroy();
		return $this;
	}

	protected function initSession(){
		if (session_status() == PHP_SESSION_NONE) {
		    session_start();
		}

		return $this;
	}

	protected function getSession($object = true){
		$this->initSession();
		return $object ? (object) $_SESSION : $_SESSION;
    }

   	protected function getSessionVar($var = ''){
   		return isset($this->session->{$var}) ? $this->session->{$var} : false;
    }

    protected function setSessionVar($key, $val){
    	$session 			= $this->session;
    	$session->{$key} 	= $val;
    	$this->session = (array) $session;
    }

    protected function setSession(array $values){
    	$this->initSession();
    	$_SESSION = $values;
    	return $this;
    }

	protected function getGet($object = true){
		return $object ? (object) $_GET : $_GET;
	}

	protected function getGetVar($var = ''){
   		return isset($this->post->{$var}) ? $this->post->{$var} : false;
    }

    protected function isPost(){
    	return empty($this->getPost(false)) ? false : true;
    }

	protected function getPost($object = true){
		return $object ? (object) $_POST : $_POST;
	}

	protected function getPostVar($var = ''){
   		return isset($this->post->{$var}) ? $this->post->{$var} : false;
    }

	protected function getState(){
		return $this->getSessionVar(self::APP_STATE);
	}

	protected function setState($state = ''){
		$this->setSessionVar(self::APP_STATE, $state);
		return $this;
	}

	protected function is_constant($token) {
	    return $token == T_CONSTANT_ENCAPSED_STRING || $token == T_STRING || $token == T_LNUMBER || $token == T_DNUMBER;
	}

	protected function strip($value) {
	    return preg_replace('!^([\'"])(.*)\1$!', '$2', $value);
	}

	protected function getDefinitions($php){

		$defines 	= array();
		$state 		= 0;
		$key 		= '';
		$value 		= '';
		$tokens 	= token_get_all($php);
		$token 		= reset($tokens);
		while ($token) {
		//    dump($state, $token);
		    if (is_array($token)) {
		        if ($token[0] == T_WHITESPACE || $token[0] == T_COMMENT || $token[0] == T_DOC_COMMENT) {
		            // do nothing
		        } else if ($token[0] == T_STRING && strtolower($token[1]) == 'define') {
		            $state = 1;
		        } else if ($state == 2 && $this->is_constant($token[0])) {
		            $key = $token[1];
		            $state = 3;
		        } else if ($state == 4 && $this->is_constant($token[0])) {
		            $value = $token[1];
		            $state = 5;
		        }
		    } else {
		        $symbol = trim($token);
		        if ($symbol == '(' && $state == 1) {
		            $state = 2;
		        } else if ($symbol == ',' && $state == 3) {
		            $state = 4;
		        } else if ($symbol == ')' && $state == 5) {
		            $defines[$this->strip($key)] = $this->strip($value);
		            $state = 0;
		        }
		    }
		    $token = next($tokens);
		}

		return $defines;

	}

	protected function generateDbForm($fields = null, $forceDisplay = false){

		if ($fields===null && !$forceDisplay){
			return;
		}

		$form = "
"; $form.= "
"; $form.= "
"; $form.= "
"; $form.= "
"; $form.= "
"; $form.= "
"; return $form; } protected function getPlatform($options){ $error = '
'; $notFound = '
'; $found = '
'; $out = '
  • '; $logoW = isset($options->logoW) ? $options->logoW : '213'; $logoH = isset($options->logoH) ? $options->logoH : '120'; $logo = "platform logo"; $dbArgs = new StdClass(); if (isset($options->conf) && file_exists($options->conf)){ if (($fp = fopen($options->conf, "r"))!==false){ $params = (object) $this->getDefinitions(stream_get_contents($fp)); foreach(array('host','table','username','password') AS $option){ $dbArgs->{$option} = isset($options->{$option}) && isset($params->{$options->{$option}}) ? $params->{$options->{$option}} : ''; } $out .= $found.$logo.$this->generateDbForm($dbArgs, isset($options->force) ? $options->force : null); fclose($fp); } else { $out .= $error.$logo.$this->generateDbForm(null, isset($options->force) ? $options->force : null); } } else { $out .= $notFound.$logo.$this->generateDbForm(null, isset($options->force) ? $options->force : null); } $out.= '
  • '; return $out; } protected function getPlatforms(){ $out = '
      '; $out .= $this->getPlatform((object) array( 'conf' => 'wp-config.php', 'logo' => 'https://s.w.org/about/images/logos/wordpress-logo-32-blue.png', 'logoW' => '32', 'logoH' => '32', 'host' => 'DB_HOST', 'table' => 'DB_NAME', 'username' => 'DB_USER', 'password' => 'DB_PASSWORD' )); $out .= $this->getPlatform((object) array( 'conf' => 'config/site.php', 'logo' => 'https://www.concrete5.org/files/3613/5517/8150/concrete5_Wordmark_200x37.png', 'logoW' => '200', 'logoH' => '37', 'host' => 'DB_SERVER', 'table' => 'DB_DATABASE', 'username' => 'DB_USERNAME', 'password' => 'DB_PASSWORD' )); /*$out .= $this->getPlatform((object) array( 'conf' => 'config/autoload/local.php', 'logo' => 'http://clloh.com/wp-content/uploads/2015/08/zf2-logo-128x128.png', 'logoW' => '128', 'logoH' => '128', 'host' => 'DB_SERVER', 'table' => 'DB_DATABASE', 'username' => 'DB_USERNAME', 'password' => 'DB_PASSWORD' ));*/ $out .= $this->getPlatform((object) array( 'logo' => 'https://www.mysql.com/common/logos/logo-mysql-170x115.png', 'logoW' => '170', 'logoH' => '115', 'force' => true, )); return $out.'
    '; } protected function getHeader(){ return 'Restricted area
    '; } protected function getFooter(){ $footer = '
    '; if ($this->authentication) { $footer .= ' '; } return $footer; } protected function loginForm($inErrorState = false){ return '

    '.($inErrorState ? 'Access Denied' : 'Secure Area' ).'

    '.($inErrorState ? '
    • Invalid username & password combination
    ' : '').'
    '.($inErrorState ? '
    • Invalid username & password combination
    ' : '').'
    '; } protected function getDownloadOptions($inErrorState = false){ return '
     Export options
    '.$this->platforms.'
    '; } protected function setUsers(array $users = null){ if ($users==null){ $users = array(); } foreach($users AS $key=>$user){ $users[$key] = (object) $user; } $this->_users = (object) $users; return $this; } protected function getUsers(){ if (!isset($this->_users)){ $this->setUsers(); } return $this->_users; } protected function setPasswordEncryption($function = null){ if ($function==null){ $function = function($val){return $val;}; } $this->_passwordEncryption = $function; return $this; } protected function getPasswordEncryption(){ if (!isset($this->_passwordEncryption)){ $this->setPasswordEncryption(); } return $this->_passwordEncryption; } protected function PasswordEncrypt($pass = ''){ $encryptor = $this->getPasswordEncryption(); return call_user_func($encryptor, $pass); } protected function generateUserToken(\StdClass $user){ return md5((isset($user->username) ? $user->username : uniqid()).self::APP_SALT.(isset($user->password) ? $user->password : uniqid())); } protected function setAuthentication(\StdClass $user){ $this->setSessionVar(self::APP_AUTH, $this->generateUserToken($user)); return $this; } protected function getAuthentication(){ $token = $this->getSessionVar(self::APP_AUTH); foreach($this->users AS $validUser){ $validToken = $this->generateUserToken($validUser); if ($token==$validToken){ return $validUser; } } } protected function authenticateUser(\StdClass $user){ foreach($this->users AS $validUser){ if ($user->username==$validUser->username && $this->passwordEncrypt($user->password)==$validUser->password){ $this->authentication = $validUser; $this->state = 'options'; return $this->authentication; } } } public static function Init(array $options = array()){ static $inst = null; if ($inst === null) { $inst = new dbDump($options); } if (isset($inst->get->logout)){ $inst->destroySession(); header('Location: '.$_SERVER['PHP_SELF']); die; } if (!$inst->authentication){ $inst->state = null; } switch($inst->state){ case 'options': //var_dump($inst->authentication); if ($inst->isPost()){ $hostname = $inst->getPostVar('host'); $table = $inst->getPostVar('table'); $username = $inst->getPostVar('username'); $password = $inst->getPostVar('password'); $command = "mysqldump --add-drop-table --host=$hostname --user=$username --password=$password $table"; header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename='.basename($table."_".date("Y-m-d_H-i-s").".sql")); system($command); exit(); } else { echo $inst->header; echo $inst->downloadOptions; echo $inst->footer; } break; default: if ($inst->isPost()){ if ($inst->authenticateUser($inst->post)){ $inst->state = 'options'; header("Refresh:0"); die; } else { echo $inst->header; echo $inst->loginForm(true); echo $inst->footer; } } else { echo $inst->header; echo $inst->loginForm(); echo $inst->footer; } break; } } public function __set($name, $value) { $method = 'set' . $name; if (method_exists($this, $method)) { $this->$method($value); return $this; } throw new \Exception('"'.$name.'" is an invalid property of '.__CLASS__.' assignment failed!'); } public function __get($name) { $method = 'get' . $name; if (method_exists($this, $method)) { return $this->$method(); } throw new \Exception('Invalid '.__CLASS__.' property '.$name); } public function setOptions(array $options) { $methods = get_class_methods($this); foreach ($options as $key => $value) { $method = 'set' . ucfirst($key); if (in_array($method, $methods)) { $this->$method($value); } } return $this; } private function __construct(array $options = null) { // env set_time_limit(20); if (is_array($options)) { $this->setOptions($options); } } private function __clone(){} }

    Remote controlling Tivo

    I was interested in what my ethernet port was doing on my virgin media TIVO box, so I ran some tests and found I could control my TIVO box from my laptop, here are my findings.

    First, I went into the Tivo boxes settings on screen and enabled network access.

    Next, I logged into my home hub/router to find out what IP address it had been allocated
    http://192.168.100.1/ and clicked devices.

    Once I had its IP address, (192.168.0.7) I scanned its ports and found the following services:

    adrian@adrian-laptop:~$ nmap 192.168.0.7
    
    Starting Nmap 5.00 ( http://nmap.org ) at 2012-10-21 10:37 BST
    Interesting ports on 192.168.0.7:
    Not shown: 997 filtered ports
    PORT     STATE SERVICE
    443/tcp  open  https
    2190/tcp open  unknown
    2191/tcp open  unknown
    
    Nmap done: 1 IP address (1 host up) scanned in 5.50 seconds
    

    The obvious one that stands out is port 443, so visiting https://192.168.0.7/ shows a web server requesting login, I found that the username is tivo and the password is your media key found in settings > mediakey.

    Once logged in, a list of recorded programmes will be displayed but however streaming and downloading are disabled :(.

    I tried for sometime to circumvent the streaming restriction using various techniques the closest I came was with VLC and special plugins http://tivo-vlc.sourceforge.net/notes.php#install, but so far I haven’t been able to achieve this.

    I looked into what the box is, and it turns out its fundamentally Linux box with a glossy coat, with some features disabled (like streaming something to do with UK copyright laws).

    Along the way I found I could telnet to port 31339 on the box

    telnet 192.168.0.7 31339

    which responded with

    CH_STATUS 0213 RECORDING

    This is the status of the two tuners, and what they are doing, you can now use commands like:

    KEYBOARD (Dunno what this does)

    TELEPORT - e.g TIVO, LIVETV, GUIDE, and NOWPLAYING.

    SETCH - Change channel. If the current tuner is recording a program, it will change the other tuner. If both tuners are recording, the TiVo will respond with "CH_FAILED RECORDING . Using this command while Tivo is replaying will give "CH_FAILED NO_LIVE".</p> <p>FORCECH <CHANNEL> - This command will force the current tuner to the tune the desired channel regardless of what it's doing. If a recording is being recorded it will cancel the recording and change the channel without confirmation.<br /> </code><br /> Also a complete set of IRCODE’s exist <code>IRCODE <COMMAND></code></p> <p> a quick google and I found the following IRCODE commands that seem to work.</p> <p>UP<br /> DOWN<br /> LEFT<br /> RIGHT<br /> SELECT<br /> TIVO<br /> LIVETV<br /> THUMBSUP<br /> THUMBSDOWN<br /> CHANNELUP<br /> CHANNELDOWN<br /> RECORD<br /> DISPLAY<br /> DIRECTV<br /> NUM0<br /> NUM1<br /> NUM2<br /> NUM3<br /> NUM4<br /> NUM5<br /> NUM6<br /> NUM7<br /> NUM8<br /> NUM9<br /> ENTER<br /> CLEAR<br /> PLAY<br /> PAUSE<br /> SLOW<br /> FORWARD<br /> REVERSE<br /> STANDBY<br /> NOWSHOWING<br /> REPLAY<br /> ADVANCE<br /> DELIMITER<br /> GUIDE</p> <p>Typing these commands into the telnet session, made the tivo box change channel etc…. cool!</p> <p>To exit the telnet session press <code>CTRL + ]</code> thats right, control and right square bracket!!, then type quit at the prompt</p> <p>I was able to source a nice GUI that can automate these commands https://github.com/wmcbrine/tivoremote</p> <p>So, as long as you have Python installed (Mac & linux users by default), just running the script produces a nice GUI that can manage your Tivo box from your laptop.</p> <p>I also found, if your interested in developing apps for it, its SDK is written for AS3 and can be found here http://developer.tivo.com/</p> </div> </article> <article id="post-679" class="post-item"> <!-- Regular Post Style --> <header class="post-header"> <h2 class="post-title"> <a href="https://adriancallaghan.co.uk/thickdialog/">thickdialog</a> </h2> <div class="post-meta"> <span class="post-date">[2012.06.20]</span> <span class="post-author">[by Adrian]</span> <span class="post-categories">[<a href="https://adriancallaghan.co.uk/Categorys/programming/javascript/" rel="category tag">Javascript</a>, <a href="https://adriancallaghan.co.uk/Categorys/programming/" rel="category tag">Programming</a>, <a href="https://adriancallaghan.co.uk/Categorys/programming/thickdialog/" rel="category tag">Thickdialog</a>]</span> <span class="post-views">[370 Views]</span> </div> </header> <div class="post-content"> <link href="/demos/thickdialog/code/jquery-ui.css" media="screen" rel="stylesheet" type="text/css" ><script type="text/javascript" src="/demos/thickdialog/code/jquery-1.7.2.min.js"></script><script type="text/javascript" src="/demos/thickdialog/code/jquery-ui-1.8.21.custom.min.js"></script><script type="text/javascript" src="/demos/thickdialog/code/thickdialog.js"></script>Jquery dialog can be made to work as a either an ajax form, a dialog box or confirmation box just by use of a class similair to the way in which thickbox used to work (the examples work perfectly outside of wordpress).<br /> <style type="text/css"> h1,h2 {font-size:12px;} #dialog {font-size:10px;} </style> <h1>ThickDialog examples</h1> <p> <a href="/demos/thickdialog/thickdialog.zip" target="_BLANK" style="color:red;">Download</a></p> <h2>Simple thickbox style popup</h2> <p> <a href="/demos/thickdialog/popup.html" title="A pop up" class="dialog-box">Popup example</a><br /> code: </p> <pre lang="xml"><a href="/demos/thickdialog/popup.html" title="A pop up" class="dialog-box">Popup example</a></pre> <p> usage: add the class “dialog-box” to make this work </p> <h2>Simple thickbox style confirmation box</h2> <p> <a href="/demos/thickdialog/delete.html" title="Are you sure?" class="dialog-confirm">Confirm example</a><br /> code: </p> <pre lang="xml"><a href="/demos/thickdialog/delete.html" title="Are you sure?" class="dialog-confirm">Confirm example</a></pre> <p> usage: add the class “dialog-confirm” to make this work </p> <h2>Simple thickbox style form submission</h2> <p> <a href="/demos/thickdialog/form.php" title="Please complete" class="dialog-form">Form example</a><br /> code: </p> <pre lang="xml"><a href="/demos/thickdialog/form.php" title="Please complete" class="dialog-confirm">Form example</a></pre> <p> usage: add the class “dialog-form” to make this work </p> </div> </article> <article id="post-677" class="post-item"> <!-- Regular Post Style --> <header class="post-header"> <h2 class="post-title"> <a href="https://adriancallaghan.co.uk/jquery-ui-ajax-form-thickbox/">jquery ui ajax form thickbox</a> </h2> <div class="post-meta"> <span class="post-date">[2012.06.20]</span> <span class="post-author">[by Adrian]</span> <span class="post-categories">[<a href="https://adriancallaghan.co.uk/Categorys/programming/javascript/" rel="category tag">Javascript</a>, <a href="https://adriancallaghan.co.uk/Categorys/programming/" rel="category tag">Programming</a>, <a href="https://adriancallaghan.co.uk/Categorys/programming/thickdialog/" rel="category tag">Thickdialog</a>]</span> <span class="post-views">[204 Views]</span> </div> </header> <div class="post-content"> <link href="/demos/thickdialog/code/jquery-ui.css" media="screen" rel="stylesheet" type="text/css" ><script type="text/javascript" src="/demos/thickdialog/code/jquery-1.7.2.min.js"></script><script type="text/javascript" src="/demos/thickdialog/code/jquery-ui-1.8.21.custom.min.js"></script><script type="text/javascript" src="/demos/thickdialog/code/thickdialog.js"></script>Jquery dialog can be made to work as a ajax form in a similair way to thickbox. <p>The link to the form (such as registration form), can be made to load inside a popup, and loaded using ajax by simply adding a class to the href.</p> <p>For example <a href="/demos/thickdialog/form.php" target="_BLANK">this link</a> could perform a registration, just like thickbox used to behave adding the class ‘dialog-form’ (the title is used to title the form popup) loading the content on submission.</p> <pre lang="xml"> <a href="/demos/thickdialog/form.php" class="dialog-form" title="Register">register</a> </pre> <p>Example: <a href="/demos/thickdialog/form.php" class="dialog-form" title="Register">register</a></p> <p>In order to do this you will need <a href="http://jquery.com/">Jquery</a>, and <a href="http://jqueryui.com/">Jquery-UI</a> and the code below.</p> <p>Alternatively I have written a library called <a href="/thickdialog/">thickdialog</a> which supports the form, confirmation box and pop ups just by adding a simple class, which is compatible with any framework and can be downloaded from there.</p> <pre lang="javascript"> // form pop ups, just give an anchor point the class dialog_form, and the title will be used as the title $(function (){ function submitBind(layout,original_url){ $(layout).find('form').submit(function(event){ /* stop form from submitting normally */ event.preventDefault(); url = $(this).attr('action')=='' ? original_url : $(this).attr('action'); /* Send the data using post and put the results in a div */ $.post( url, $(this).serialize(), function(data) { $('#dialog').empty(); $('#dialog').append(data); $('#dialog').dialog('option', 'position', 'center'); submitBind(layout, original_url); }); }); } $('a.dialog-form').click(function() { var original_url = this.href; var title = this.title; // show a spinner or something via css var dialog = $('<div id="dialog" style="display:none" class="loading">Loading</div>').appendTo('body'); // open the dialog dialog.dialog({ width: dialogBox_width, // add a close listener to prevent adding multiple divs to the document close: function(event, ui) { // remove div with all data and events dialog.remove(); }, modal: true }); // load remote content dialog.load( original_url, function (responseText, textStatus, XMLHttpRequest) { // remove the loading class dialog.removeClass('loading'); dialog.dialog('option', 'position', 'center'); dialog.dialog('option', 'title', title); submitBind(this,original_url); } ); //prevent the browser to follow the link return false; }); }); </pre> </div> </article> <article id="post-675" class="post-item"> <!-- Regular Post Style --> <header class="post-header"> <h2 class="post-title"> <a href="https://adriancallaghan.co.uk/jquery-confirmation-box-thickbox/">jquery confirmation box thickbox</a> </h2> <div class="post-meta"> <span class="post-date">[2012.06.20]</span> <span class="post-author">[by Adrian]</span> <span class="post-categories">[<a href="https://adriancallaghan.co.uk/Categorys/programming/javascript/" rel="category tag">Javascript</a>, <a href="https://adriancallaghan.co.uk/Categorys/programming/" rel="category tag">Programming</a>, <a href="https://adriancallaghan.co.uk/Categorys/programming/thickdialog/" rel="category tag">Thickdialog</a>]</span> <span class="post-views">[272 Views]</span> </div> </header> <div class="post-content"> <link href="/demos/thickdialog/code/jquery-ui.css" media="screen" rel="stylesheet" type="text/css" ><script type="text/javascript" src="/demos/thickdialog/code/jquery-1.7.2.min.js"></script><script type="text/javascript" src="/demos/thickdialog/code/jquery-ui-1.8.21.custom.min.js"></script><script type="text/javascript" src="/demos/thickdialog/code/thickdialog.js"></script>Jquery dialog can be made to work as a confirmation box in a similair way to thickbox. <p>The link to the action (such as deletion), can be made to display a confirmation box before it completes, by simply adding a class to the href.</p> <p>For example <a href="/demos/thickdialog/delete.php" target="_BLANK">this link</a> could perform a deletion, just like thickbox used to behave adding the class ‘dialog-confirm’ (the title is used to title the dialog confirm) will request the user to confrim firstly.</p> <pre lang="xml"> <a href="/demos/thickdialog/delete.php" class="dialog-confirm" title="Are you sure about this?">delete</a> </pre> <p>Example: <a href="/demos/thickdialog/delete.php" class="dialog-confirm" title="Are you sure about this?">delete</a>(example works fine outside of wordpress)</p> <p>In order to do this you will need <a href="http://jquery.com/">Jquery</a>, and <a href="http://jqueryui.com/">Jquery-UI</a> and the code below.</p> <p>Alternatively I have written a library called <a href="/thickdialog/">thickdialog</a> which supports the confirmation box, pop ups and forms just by adding a simple class, which is compatible with any framework and can be downloaded from there.</p> <pre lang="javascript"> // confirm box, add the class dialog-confirm and a title and it does the rest $(function (){ $('a.dialog-confirm').click(function() { var url = this.href; var dialog = $('<div id="dialog" style="display:none" title="Are you sure?">'+this.title+'</div>').appendTo('body'); dialog.dialog({ resizable: false, height:confirmBox_height, modal: true, buttons: { "Yes": function() { $(this).dialog( "close" ); window.location.href = url; }, "No": function() { $(this).dialog( "close" ); } } }); dialog.dialog('option', 'position', 'center'); //prevent the browser to follow the link return false; }); }); </pre> </div> </article> <article id="post-665" class="post-item"> <!-- Regular Post Style --> <header class="post-header"> <h2 class="post-title"> <a href="https://adriancallaghan.co.uk/jquery-dialog-thickbo/">Jquery dialog thickbox</a> </h2> <div class="post-meta"> <span class="post-date">[2012.06.20]</span> <span class="post-author">[by Adrian]</span> <span class="post-categories">[<a href="https://adriancallaghan.co.uk/Categorys/programming/javascript/" rel="category tag">Javascript</a>, <a href="https://adriancallaghan.co.uk/Categorys/programming/" rel="category tag">Programming</a>, <a href="https://adriancallaghan.co.uk/Categorys/programming/thickdialog/" rel="category tag">Thickdialog</a>]</span> <span class="post-views">[261 Views]</span> </div> </header> <div class="post-content"> <link href="/demos/thickdialog/code/jquery-ui.css" media="screen" rel="stylesheet" type="text/css" ><script type="text/javascript" src="/demos/thickdialog/code/jquery-1.7.2.min.js"></script><script type="text/javascript" src="/demos/thickdialog/code/jquery-ui-1.8.21.custom.min.js"></script><script type="text/javascript" src="/demos/thickdialog/code/thickdialog.js"></script>Jquery dialog can be made to work in a similair way to thickbox. <p>Any link to content, can have its content loaded into a jquery dialog box, by simply adding a class to the href.</p> <p>For example this standard <a href="/demos/thickdialog/page.php" target="_BLANK">page</a> can be made to behave like a thickbox pop-up by adding the class ‘dialog-box’ (the title is used to title the dialog box).</p> <pre lang="xml"> <a href="/demos/thickdialog/page.php" class="dialog-box" title="popup">popup</a> </pre> <p>Example: <a href="/demos/thickdialog/page.php" class="dialog-box" title="popup">popup</a> (example works fine outside of wordpress)</p> <p>In order to do this you will need <a href="http://jquery.com/">Jquery</a>, and <a href="http://jqueryui.com/">Jquery-UI</a> and the code below.</p> <p>Alternatively I have written a library called <a href="/thickdialog/">thickdialog</a> which supports the popups, confirmation boxes and forms just by adding a simple class, which is compatible with any framework and can be downloaded from there.</p> <pre lang="javascript"> // pop ups, just give an anchor point the class dialog_box, and the title will be used as the title $(function (){ $('a.dialog-box').click(function() { var url = this.href; var title = this.title; // show a spinner or something via css var dialog = $('<div id="dialog" style="display:none" class="loading">Loading</div>').appendTo('body'); // open the dialog dialog.dialog({ width: dialogBox_width, // add a close listener to prevent adding multiple divs to the document close: function(event, ui) { // remove div with all data and events dialog.remove(); }, modal: true }); // load remote content dialog.load( url, {}, // omit this param object to issue a GET request instead a POST request, otherwise you may provide post parameters within the object function (responseText, textStatus, XMLHttpRequest) { // remove the loading class dialog.removeClass('loading'); dialog.dialog('option', 'position', 'center'); dialog.dialog('option', 'title', title); } ); //prevent the browser to follow the link return false; }); }); </pre> </div> </article> <article id="post-615" class="post-item"> <!-- Regular Post Style --> <header class="post-header"> <h2 class="post-title"> <a href="https://adriancallaghan.co.uk/database-class-php/">database class php</a> </h2> <div class="post-meta"> <span class="post-date">[2011.08.08]</span> <span class="post-author">[by Adrian]</span> <span class="post-categories">[<a href="https://adriancallaghan.co.uk/Categorys/programming/php/" rel="category tag">Php</a>, <a href="https://adriancallaghan.co.uk/Categorys/programming/" rel="category tag">Programming</a>]</span> <span class="post-views">[201 Views]</span> </div> </header> <div class="post-content"> <p>Updated the database class </p> <p>Usage:</p> <pre lang="php" line="1"> // min instantiation $dataBase = new DB('hostname','username','password','database'); // max instantiation $dataBase = new DB('hostname','username','password','database',DEBUG_LEVEL,array('admin@domain.com','admin@domain2.com)); </pre> <p>Class:</p> <pre lang="php" line="1"> class DB{ /* * DESCRIPTION: Object class, Handles all database requests and returns content accordingly * WRITER: Adrian Callaghan 12,08,08 * UPDATED: Adrian Callaghan 08,08,11 * * * errLvl * (0), none, * (1) show a user error, * (2) (1) + mysql error * (3) (2) + show a full error (mysql errors), * (4) (3) + plus debugging */ private $host, $usr, $pwd, $errLvl, $mySqlHost, $dataBase, $emailAddresses; public function __construct($host, $usr, $pwd, $db, $errLvl=0, $adminEmails=array()) { /* * Sets up a new connection */ // MIN required $this->setHost($host); $this->setUsr($usr); $this->setPwd($pwd); $this->setErrLvl($errLvl); // sets defualt RTE $this->setEmailErrsTo($adminEmails); // connect $this->connect(); $this->setDb($db); } public function __destruct(){ /* * Close the connection */ $this->disconnect(); } protected function setHost($host='localhost'){ /* * Sets the hostname */ $this->host = $host; } protected function setUsr($usr=''){ /* * Sets the username */ $this->usr = $usr; } protected function setPwd($pwd=''){ /* * Sets the password */ $this->pwd = $pwd; } protected function setErrLvl($errLvl=0){ /* * Sets the error reporting level */ $this->errLvl = $errLvl; } protected function connect(){ /* * Connect to server */ $this->mySqlHost = @mysql_connect($this->host, $this->usr, $this->pwd); if (!$this->mySqlHost) { $this->error('Cannot connect to server',mysql_error()); } } protected function disconnect() { /* * closes current connection */ @mysql_close($this->mySqlHost); } public function setDb($db){ /* * Set the database */ $this->dataBase = @mysql_select_db($db,$this->mySqlHost); if (!$this->dataBase) { $this->error('Cannot select database',mysql_error()); } } public function setEmailErrsTo($email = array()){ // ensure it is an array $email = !is_array($email) ? array($email) : $email; // if empty return if (empty($email)){ return; } // assign the email addresses $this->emailAddresses = $email; } function getQuery($SQL){ // executes a query $result = @mysql_query($SQL); if (!$result) { $this->error('Invalid query',mysql_error(),$SQL); } // create a 2D array of results $return = array(); while ($row = mysql_fetch_assoc($result)) $return[] = $row; return $return; } function setQuery($SQL){ // executes a query without returning any results, used for insert, create etc, returns the ID of the last auto-increment $result = @mysql_query($SQL); if (!$result) { $this->error('Invalid query',mysql_error(),$SQL); } $return = mysql_insert_id(); return $return; } public function error($message, $mysqlErr='', $SQL=''){ /* * Handles errors * */ switch ($this->errLvl){ case 0: break; case 1: $mysqlErr=''; // kill the mysql output case 2: $SQL=''; // kill the sql output case 3: case 4: echo "<h1 style='color:#444444;'>$message</h1><hr>"; if ($mysqlErr!=='') { echo "<p><span style='color:#ff0000; font-weight:bold;'>Mysql: </span>$mysqlErr</p>"; } if ($SQL!=='') { echo "<p><span style='color:#ff0000; font-weight:bold;'>Whole query: </span>$SQL</p>"; } } $email = $this->generateEmail(array('Error'=>$message,'Mysql'=>$mysqlErr,'Sql'=>$SQL,'Err Level'=>$this->errLvl)); // three is for debugging if ($this->errLvl>3){ echo $email; } if (!empty($this->emailAddresses)){ $sent = $this->sendEmails($email); if ($sent) echo '<h2>The administrator has been notified</h2>'; else { echo '<h2>Please notify the administrator'; echo count($this->emailAddresses)>1 ? "'s " : " "; echo implode(' or ',$this->emailAddresses); echo '</h2>'; } } exit(); } private function generateEmail($err=array()){ $fields = array( 'Server name'=>$_SERVER['SERVER_NAME'], 'Query'=>$_SERVER['SCRIPT_FILENAME'].'?'.$_SERVER['QUERY_STRING'], 'Ip'=>$_SERVER['REMOTE_ADDR'].':'.$_SERVER['REMOTE_PORT'], '@'=>date("D dS M,Y h:i a") ); $rtn = '<table bgcolor="#cccccc">'; foreach (array_merge($fields, $err) AS $title=>$value){ $rtn.="<tr><td bgcolor='#aaaaaa'>$title</td><td bgcolor='#bbbbbb'>$value</td></tr>"; } return $rtn.'</table>'; } public function sendEmails($reciptents=array()){ // email message $Name = $_SERVER['SERVER_NAME']; //senders name $email = "noreply@".$_SERVER['SERVER_NAME']; //senders e-mail adress $subject = $_SERVER['SERVER_NAME']." Error"; //subject $header = 'MIME-Version: 1.0' . "\r\n"; $header.= 'Content-type: text/html; charset=iso-8859-1' . "\r\n"; $header.= "From: ". $Name . " <" . $email . ">\r\n"; $success=false; foreach ($this->emailAddresses AS $admin_email){ $sent = @mail($admin_email, $subject, $mail_body, $header); if ($sent) $success=true; // holds state for any email being succesfully sent } return $success; } } </pre> </div> </article> <article id="post-579" class="post-item"> <!-- Regular Post Style --> <header class="post-header"> <h2 class="post-title"> <a href="https://adriancallaghan.co.uk/simple-mvc/">simple mvc</a> </h2> <div class="post-meta"> <span class="post-date">[2010.08.30]</span> <span class="post-author">[by Adrian]</span> <span class="post-categories">[<a href="https://adriancallaghan.co.uk/Categorys/programming/" rel="category tag">Programming</a>]</span> <span class="post-views">[184 Views]</span> </div> </header> <div class="post-content"> <p>Need a lightweight, fast, php mvc framework?</p> <p>I have written a small framework named “<a href="http://adriancallaghan.co.uk/wp-content/downloads/simple_mvc.zip">Simple MVC</a>” it does exactly what it says on the box, its quick to install and can be configured to handle most tasks.</p> <p>Once the file is unzipped you will be presented with this structure:<br /> <a href="http://adriancallaghan.co.uk/wp-content/uploads/2010/08/layout.jpg"><img loading="lazy" decoding="async" src="http://adriancallaghan.co.uk/wp-content/uploads/2010/08/layout.jpg" alt="" title="layout" width="211" height="129" class="alignnone size-full wp-image-580" /></a></p> <p>Simply upload the whole structure, and the framework will work.</p> <p>It is designed to be very fast and lightweight, however it can be configured, opening the file mvc_env.php within the “<a href="http://adriancallaghan.co.uk/wp-content/downloads/simple_mvc.zip">Simple MVC</a>” folder displays the following preferences:</p> <pre lang="php" line="1"> <?php /* * * Simple MVC settings file (this file does not need to be present) * Examples of different settings are contained here, just uncomment to use * * By Adrian Callaghan 300810 * */ // error controller // defines a controller to handle errors, namely the page not found // the controller is automatically exempt from an actual page request /* $env->error['controller']='error'; $env->error['view']='index'; $env->error['pageNotFoundAction']='pageNotFound'; */ // routerMap // holds controller and action mappings to different controller, action (comma delimited) /* $env->routerMap['foo,bar']='index,index'; */ // routerDeny // holds controller and action mappings to deny (comma delimited) /* $env->routerDeny[]='controller,action'; // will deny the page /controller/action/ $env->routerDeny[]=''; // will deny homepage */ // prelayout // defines an array of elements to be included before the main view /* $env->prelayout = array('header'); */ // postlayout // defines an array of elements to be included after the main view /* $env->postlayout = array('sidebar','footer'); */ </pre> <p>As you can see, page routing, error controllers, page denials etc can all be added here.</p> <p>The whole framework is just one file and the source looks like this</p> <pre lang="php" line="1"> <?php /* * * Simple MVC * * By Adrian Callaghan 300810 * */ // enviroment $env = new stdClass(); // url mapping $env->url['base'] = dirname($_SERVER['SCRIPT_NAME']); $env->url['path'] = realpath('.'); $env->url['relative'] = str_replace('//','/',dirname(__FILE__)).'/../application/'; $env->url['request'] = htmlentities($_SERVER['REQUEST_URI']); $env->url['request_array'] = explode('/',trim($_GET['__url'],'/')); // mvc $env->controller = !empty($env->url['request_array'][0]) ? $env->url['request_array'][0] : 'index'; $env->action = !empty($env->url['request_array'][1]) ? $env->url['request_array'][1] : 'index'; $env->view = $env->controller; // settings @include_once('mvc_env.php'); // tell the controllers where to load models from function __autoload($class_name) { global $env; require_once "{$env->url['relative']}models/$class_name.php"; } // add custom error controller to list of denys if (isset($env->error['controller'])){ $env->routerDeny[] = $env->error['controller']; } // mapping if (isset($env->routerMap) && in_array("{$env->controller},{$env->action}",array_keys($env->routerMap))){ $route = explode(',',$env->routerMap["{$env->controller},{$env->action}"]); $env->controller = $route[0]; $env->action = $route[1]; $env->view = $env->controller; } // get the controller if (file_exists("{$env->url['relative']}/controllers/{$env->controller}.php")) { require_once("{$env->url['relative']}/controllers/{$env->controller}.php"); $controller = new $env->controller(); } // unset the controller if this is a denied resource, this is done on URL only, so not to interfere with any mappings if (isset($env->routerDeny) && in_array(implode(',',$env->url['request_array']),$env->routerDeny)){ unset($controller, $env->controller); } // if neither the controller or action was found set an error for the error controller to handle if (!isset($controller) || !method_exists($controller,$env->action)){ // can we run the error handler? if (isset($env->error)){ $env->controller = $env->error['controller']; $env->action = $env->error['pageNotFoundAction']; $env->view = $env->error['view']; @require_once("{$env->url['relative']}/controllers/{$env->controller}.php"); $controller = new $env->controller(); if (!method_exists($controller,$env->action)) { die("<h1>Fatal error</h1>Missing action: <b>{$env->action}</b> in controller: <b>{$env->controller}</b>"); } // output will be handled by the dispatcher below } else { // if we do not even have an error handler, throw a traditional 404 and die ob_start(); ?> <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head><title>404 Not Found

    Not Found

    The requested URL url['request']; ?> was not found on this server.

    {$env->action}(); // check to see if the view has been altered $env->view = isset($controller->view) ? $controller->view : $env->view; // set up the content and view $content = $controller->content; if (isset($env->prelayout)) foreach ($env->prelayout AS $element) include_once("{$env->url['relative']}/views/$element.phtml"); include_once("{$env->url['relative']}/views/{$env->view}.phtml"); if (isset($env->postlayout)) foreach ($env->postlayout AS $element) include_once("{$env->url['relative']}/views/$element.phtml");

    A helloworld quickstart can be downloaded from here

    The helloworld also has examples of where to instaniate the models, and how to redirect the view in the comments.

    wordpress comment count as a button

    Styling the wordpress comment count as a button/icon etc can be tricky because the normal call to the comments

    comments_popup_link(__('Comments (0)'), __('Comments (1)'), __('Comments (%)')); 
    

    formats the output as an anchor point with the correct link, alt tags etc already set up.

    So in order to intercept this and then add you own anchor point with divs/imagery etc you need to make a custom request

    
    // SQL
    $SQL = "SELECT COUNT(*) AS Count FROM $wpdb->comments WHERE comment_approved='1'";
    $SQL.= "AND comment_post_ID='".intval($post->ID)."'";
    
    // Sort the array into a string prefixed with 'Comments '
    list($comments) = $wpdb->get_results($SQL, ARRAY_A); 	
    $comments='Comments ('.$comments['Count'].')';
    
    // generate the alt and title tags
    $alt = 'Comment on '.$post->post_title;
    
    // echo the button if this is not a single and not a page
    if (!is_single() && !is_page()) {
    
    // anchor open
    echo '';
    
    // complex formatting rules for the comment pop up, go here
    echo $comments;
    
    // anchor close
    echo '';
    }
    
    

    The above does exactly the same, formats the link etc, but now you can access the anchor point directly and format it your own way.

    Pagenation with php example

    Pagenate an array into a table using PHP.

    This is a basic example and has been depreciated, a far more advanced and upto date example can be found here.

    (Thanks to Andrew (Morf) for his help on this)

    To see it in action click here

    There are user configurable values at the top, such as query name, and number of results per page etc, the important thing to remember though, is the page link must be correct

    
    
    
    $val){ $args.= $key!=$queryString ? "&".$key."=".$val : "" ; } if($all>0){ if(($listing+1) > $all_pages){$listing=0;} $of = 0; ////////////////////////////////////////// navigation starts if(($listing+1) > 1 && ($listing+1) <= $all_pages){ // up echo '«'; } if ($all_pages>1){ // goto page for($i=0;$i<$all_pages;$i++){ // echo`s the number also checks to see if this is the current page echo $listing==$i ? ''.($i+1).'' : ''.($i+1).''; if($i < ($all_pages-1)) echo ' | '; } } if(($listing+1) < $all_pages){ // down echo ' »'; } ///////////////////////////////////////// navigation ends ?>
    Thing 1 Thing 2 Thing 3
    No results found'; } ?>

     

    You can download the complete zipped file here

    I have now developed a fully automated function here which is far superior.

    LOADING...
    Initializing CyberDev systems...