Latest Publications

PHP 5.3.1 + MySQL on Windows 7

Ok, this was a bit of a hassle getting these two running on my laptop, using Windows 7 Business. I encountered several problems with both MySQL and PHP.

MySQL has issues on Windows 7 setting up the instance configuration. The problem is that the innodb_log_file_size parameter in my.ini is different than what MySQL thinks it is. You have to manually change the innodb_log_file_size in your my.ini file to what mysql thinks it should be. In order to see this, you need to run the command

SHOW GLOBAL STATUS

and change your value in my.ini to match the value from the command.

The second problem I had was that PHP could not talk to MySQL over the localhost. This is because in Windows 7, by default the line

127.0.0.1       localhost

in your host file is commented out. To uncomment this line, open the file C:\Windows\System32\drivers\etc\hosts. and remove the # sign from the line mentioned above.

I’m using the apache available from apachelounge so that I can build PHP extensions from C++ on this version of apache. The PHP I am using is VC9 Thread Safe. It is important that you use the thread safe version, so that you can use mod_php to connect PHP to apache.

Objected Oriented Widgets with Prototype and Scriptaculous

Making objected oriented widgets with prototype and scriptaculous becomes easy with prototype’s Class.create function. In this demo, I will examine how to make a custom alert dialog.

First, let’s take a quick peek at the code:

/**
 * @author Andy Daykin
 * @website http://andydaykin.com
 * @param {Object} text
 * @param {Object} callerElem
 */
 
var Dialog = Class.create({
	initialize: function (text, callerElem) {
		var height = (document.height !== undefined) ? document.height : document.body.offsetHeight;
		height += 25;
		new Insertion.Bottom(document.body, "<div id='overlay' style='position: absolute; width: 100%; top: 0px; left: 0px; z-index: 100;'></div>");
		$('overlay').setStyle({ height: height + "px" });
 
	        var div = document.createElement('div');
		Element.extend(div);
		div.id = 'dialog';
		div.addClassName('dialog');
		div.update("<div class='dialogWrap' id='dialog'><div id='dialogHandle'><span class='dialogHeader'>Error:</span><span id='dialogClose'>X</span><br />" + 
			"</div><div id='dialogDivider' style='display: none;'></div><p>" + text + "</p><div class='dialogBtn' id='okBtn'>OK</div></div>");
		div.setStyle({ 'display': 'none' });
		document.body.appendChild(div);
 
		// Calculate position
		var height = div.getHeight() / 2;
		var width = div.getWidth() / 2;
 
		var scroll = (document.all) ? document.body.scrollTop : window.pageYOffset;
 
		// Calculate the middle of the screen
		var top = (document.viewport.getHeight() + scroll) / 2 - height;
		var left = document.viewport.getWidth() / 2 - width;	
		div.setStyle({ 'left': left + 'px', 'top': top + 'px' });
 
		div.show();
		$('dialogClose').observe('click', this.closeDialog.curry(callerElem));
		$('okBtn').observe('click', this.closeDialog.curry(callerElem));
		new Draggable('dialog', { handle: 'dialogHandle', 
			starteffect: function(e) {
				$('dialogDivider').show();
				$('dialogHandle').setStyle({ backgroundColor: '#5777AF' });
				new Effect.Opacity('dialog', { from: 1.0, to: 0.7 });
			},
			endeffect: function(e) {
				$('dialogDivider').hide();
				$('dialogHandle').setStyle({ backgroundColor: '#2C508F' });
				new Effect.Opacity('dialog', { from: 0.7, to: 1.0 });
			} 
		});
	},
 
	closeDialog: function(callerElem) {
		$('overlay').remove();
		new Effect.Fade('dialog', { duration: .8, afterFinish: function(e) {
			$('dialog').remove();
			callerElem.focus();
		}});
	}
});

There is a reserved function in prototype classes called “initialize”, which acts as a constructor function, for those of you who have experience with other object oriented languages. In my initialize function, I take two parameters, the text and the caller element. The text is the message which will be displayed in the dialog. The text parameter can contain both a plain text string and HTML in it, since prototype’s update function can take in either. The callerElem is the id of the element which will take focus after the dialog is closed.

In order to make this a true alert statement, we need to display an overlay, so the user must click on the dialog before they can do anything else. To make our overlay we need to find the width and height of the user’s screen.

var height = (document.height !== undefined) ? document.height : document.body.offsetHeight;
height += 25;
new Insertion.Bottom(document.body, "<div id='overlay' style='position: absolute; width: 100%; top: 0px; left: 0px; z-index: 100;'></div>");
$('overlay').setStyle({ height: height + "px" });

After the height is obtained, we need to insert the overlay at the bottom, so it covers the entire document. Note the z-index value set at 100, so the overlay is set on top of everything.

Next we need to create our dialog widget. The dialog already has some css to make it more user friendly, but I will leave that part up to you, to style your own widget. It is important to note that the dialog css class does have some rules which must be put in place for it to function properly.

.dialog {
	border: 1px solid black;
	position: absolute;
	width: 275px;
	background-color: #2C508F;
	color: white;
	z-index: 200;
}

The z-index on your dialog should be greater than whatever you set your overlay to, so the dialog shows up.

Now let’s create the element and calculate or position. To do so, we will use document.createElement, and then extend the element. By extending the element you are able to use prototype’s element methods on the widget, such as setStyle, addClassName, and update.

After setting the styles we can calculate the middle of the screen so our dialog mimics the behavior of the alert dialog.

var div = document.createElement('div');
Element.extend(div);
div.id = 'dialog';
div.addClassName('dialog');
div.update("<div class='dialogWrap' id='dialog'><div id='dialogHandle'><span class='dialogHeader'>Error:</span><span id='dialogClose'>X</span><br />" + 
			"</div><div id='dialogDivider' style='display: none;'></div><p>" + text + "</p><div class='dialogBtn' id='okBtn'>OK</div></div>");
div.setStyle({ 'display': 'none' });
document.body.appendChild(div);
 
// Calculate position
var height = div.getHeight() / 2;
var width = div.getWidth() / 2;
 
var scroll = (document.all) ? document.body.scrollTop : window.pageYOffset;
 
// Calculate the middle of the screen
var top = (document.viewport.getHeight() + scroll) / 2 - height;
var left = document.viewport.getWidth() / 2 - width;	
div.setStyle({ 'left': left + 'px', 'top': top + 'px' });

Once we have set our style and placed the element properly it’s time to show it and add our close event handler. By using prototype’s curry method we can pass along the id of our element to the close event handler. We also make our dialog draggable, and change the style of the upper part of our element when we do so to give the handle effect.

div.show();
$('dialogClose').observe('click', this.closeDialog.curry(callerElem));
$('okBtn').observe('click', this.closeDialog.curry(callerElem));
new Draggable('dialog', { handle: 'dialogHandle', 
	starteffect: function(e) {
		$('dialogDivider').show();
		$('dialogHandle').setStyle({ backgroundColor: '#5777AF' });
		new Effect.Opacity('dialog', { from: 1.0, to: 0.7 });
	},
	endeffect: function(e) {
		$('dialogDivider').hide();
		$('dialogHandle').setStyle({ backgroundColor: '#2C508F' });
		new Effect.Opacity('dialog', { from: 0.7, to: 1.0 });
	} 
});

Finally we come to our close handler. When the close handler is clicked, the overlay will be removed. After the overlay is removed, we get rid of the dialog, and focus on the element that initially triggered the dialog.

closeDialog: function(callerElem) {
	$('overlay').remove();
	new Effect.Fade('dialog', { duration: .8, afterFinish: function(e) {
		$('dialog').remove();
		callerElem.focus();
	}});
}

Calling the dialog widget is just a simple matter of saying

var form = $('contact');
 
if($(form['name']).getValue() == "") {
	new Dialog("Please enter your name", $(form['name']));
	return false;
}

Enabling .htaccess in opensuse 11.1

By default .htaccess files will have no effect in opensuse 11.1 out of the box. In order to enable a .htaccess file, you must allow your web root directory to override controls. To do this navigate to your apache directory. For me it is:

cd /etc/apache2

Find the file named default-server-conf. Open it with your favorite text editor

nano default-server.conf

Find the line

<Directory "/srv/www/htdocs">

Everything between the directory tags will help you manage your web root of your server, in my case it is /srv/www/htdocs. The line you are looking for is

AllowOverride None

Change “None” to “All”. Your .htaccess files can now override directives set in your httpd.conf, default-server.conf, and php.ini files, among others. This will enable .htaccess to do things like limit viewing of .inc, .sql, .log, and .ini files by putting

<Files ~ "\.(inc|sql|log|ini)$">
  order allow,deny
  deny from all
</Files>

in your .htaccess file.

Compiling Java With an External Jar From the Command Line

It took me a while to firgure this out, but I’m sure someone else will find it useful. In order to compile from the command line, you need to set the classpath of the jar, when you compile, and run the class. Here is an example:

javac -classpath .:/pathtojar/jarname.jar ClassName.java

java -classpath .:/pathtojar/jarname.jar ClassName

Creating a Web Based Backup System With PEAR’s Archive_Tar package

I needed to create a web based backup system and the natural choice of language for the task was php (although I am looking into some perl modules as well). After tweaking with the thought of using a shell command to run a tar command I looked into PEAR’s Archive_Tar package. The class is fairly straightforward to use, my code to backup one particular directory was:

error_reporting(E_ALL);
ini_set('display_errors', 1);
require_once 'Archive/Tar.php';
PEAR::setErrorHandling(PEAR_ERROR_DIE);
 
$tar = new Archive_Tar("data.tar");
$dir = "../";
$handle = opendir("$dir");
while (false !== ($file = readdir($handle)))
{
	echo "$file \n";
	echo "";
	$tar-&gt;add($dir . "/" . $file) or die ("Could not add file!");
}
closedir($handle);

Telling PEAR to die on errors, and spit out the error message was especially helpful when debugging the script. In order for the script to run from a browser, the user running the script (apache in my case), must have write permissions on the directory the script is running from.