Category Archives: Programming

Checking to See if Packages are Installed in PHP or Perl

I have this love/hate thing with open source technology. It’s great that it’s free, bugs are openly discussed instead of hidden away, and ultimately I think the open source technologies are more robust.

But here’s what always gets me: the packages and their dependencies.

Perl

At the bash prompt, you can type:
perl -e 'use Some::Package'

If the package is installed, nothing will happen. The one line script executes without complaint. But if you DON’T have that package installed, you’ll get an error like this:
Can't locate Some/Package.pm in @INC (@INC contains: /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi
[...]
/usr/lib/perl5/5.8.8/i386-linux-thread-multi /usr/lib/perl5/5.8.8 .) at -e line 1.
BEGIN failed--compilation aborted at -e line 1.

If that’s the case, you need to find and install that package. With Perl, the way to go is to get familiar with www.cpan.org — yes, it’s a fugly site, but you can search for packages and read up on them. If you want to download them, I recommend using the CPAN command line tool. You run this utility by simply typing cpan on the bash command line. Take the time to understand this utility! It will save you SO MUCH TIME.

PHP

PHP is nowhere near as verbose as Perl when it comes to error messages and debugging; it’s also a bit more mysterious when it comes to its package structure. You can get a lot of information by examining the output of the phpinfo() function. Simply write following script and hit it with a web browser:


<?php phpinfo(); ?>

On the command line, you can use rpm to see if a specific package is installed… however, good luck guessing what the package name is. For example, here you can check the version of the GD graphics library:
rpm -q php-gd
If the package is installed, the result should be something like:
php-gd-5.1.6-20.el5_2.1

You can also have a look in the php module directory. For Linux systems, it’s often here: /usr/lib/php/modules/

Search the File System

If you’re still frustrated, you can search the file system for the file — modules are FILES… they live SOMEWHERE. In Linux, you can use the find command:
find /path/to/start/search -name 'name_of_file'
E.g. to search for myfile.txt in the current directory or beneath, you’d type this:

find . -name myfile.txt

All the Linux file name metacharacters are valid, e.g. “*.txt” to search for all text files. The path can also be specified as any valid pathname, e.g. “~/” to refer to the current user’s home directory.

It’s a bit messy in there, but hopefully this helps you evaluate a system to see if your scripts or pages will actually work!

Stealth Submit: Using AJAX to Save Form Data Without Submitting the Form

Ah, this is sneaky. You may think that a web site can’t read form fields until you hit the submit button, but this is not the case. Using AJAX, a site can read form data at any time. This could be used for nefarious purposes, but I’m presenting here for two reasons: 1) to let people know that it can be done and 2) to show people how to do it for legitimate purposes. What’s a legitimate use of this? Logging, mostly… a lot of work goes into studying why users may fill out only the first page of a form. If you log the data regardless of whether a user clicked submit, you can study user behavior and possibly improve your form.

This tutorial assumes the following: you have a web server running PHP 5 (or greater) and MySQL 5 (or greater) with the mysqli extension installed. There are several parts to how this works:

1. savedata.php: A processing page that grabs posted variables (e.g. savedata.php?variable=value).
2. db.php: A database interface file (usually contained above the document root, contains passwords and save logic).
3. index.php: The HTML page containing the form.
4. The prototype JavaScript library. This is a very handy library that’s pretty easy to use.

Here’s an image showing how these files are organized in their folder structure. /html is the document root of the site: all browser requests are directed in there. /lib is above the document root… only PHP can make calls inside that folder. That’s were we put our database connection logic, including usernames and passwords.

Folder structure used for Stealth Submit Files
Folder structure used for Stealth Submit Files

The files used in this demo are listed below, but because scripts tend to get buggy when they’ve undergone conversion to/from html-entities, I’m zipping up the files and uploading them here.
Stealth Submit Sample Files.zip

You should be able to unload the html and lib directories to your web server. Point your DocumentRoot at the html directory; be sure to run the SQL commands included at the top of the db.php file so your database looks the way that this script expects it to.

For the use of visibility, the contents of these files is included below:

html/savedata.php : the PHP Page that grabs and stores variables


<?php
/*
Test this page by hitting it in a browser with variables:
http://your_domain/savedata.php?first_name=Bart&last_name=Simpson&age=11&home_town=Springfield&job=Punk

*Add &debug=1 to the url to print out verbose messages.
*/

include_once($_SERVER['DOCUMENT_ROOT'] . "/../lib/db.php");
$debug = $_REQUEST['debug'];
$debug_msg ="<p>The following variables were passed:</p><hr/>";

// Harvest all form data: this works for posts and gets.
foreach ($_REQUEST as $var => $value) {
$debug_msg .= "<b>$var</b>: $value<br/>";
$form_data[$var] = $value;
}

if ($debug) {
echo $debug_msg . "<hr/>";
}

$result = save_user_data($form_data);

if ($debug) {
if ($result) {
echo "Data saved successfully. Id: $result";
} else {
echo "Error saving data.";
}
}

?>

lib/db.php : Here’s the Database Interface Page


<?php
/*
Contains database handle (username/password) and saving functions

Here's the table definition for the table used in this demo:

CREATE DATABASE ajax_demo;

CREATE TABLE `user` (
`id` int(11) NOT NULL auto_increment,
`first_name` char(64) default NULL,
`last_name` char(64) default NULL,
`age` tinyint(3) default NULL,
`home_town` char(64) default NULL,
`job` char(64) default NULL,
UNIQUE KEY `id` (`id`)
) ENGINE=MyISAM;

GRANT ALL PRIVILEGES ON ajax_demo.* TO 'peter'@'%'
IDENTIFIED BY 'abc123';
*/

// Test regex's here by uncommenting this line and executing this file.
// echo get_name_regex('Bob');
/*-------------------------------------------------------------------------
DEFINE Database constants here
---------------------------------------------------------------------------*/
define("DATABASE_HOST", 'localhost');
define("DATABASE", 'ajax_demo');
define("DEFAULT_USER", 'peter');
define("DEFAULT_USER_PASSWORD", 'abc123');

function connect_db ($user = DEFAULT_USER) {
/*
INPUT: $user
This function allows for multiple handles to be called, e.g. handles for
read-only, write-only, etc. Each user has its own permissions.
mysqli format is mysqli(DATABASE_HOST, USER, PASSWORD, DATABASE);
*/
switch($user) {
case DEFAULT_USER:
$link = new mysqli(DATABASE_HOST, DEFAULT_USER, DEFAULT_USER_PASSWORD, DATABASE);
break;
}

return $link;

}

/*-------------------------------------------------------------------------*/
function save_user_data ($input) {
/*
INPUT:
Hash with values from form, e.g. $input['first_name'].
OUTPUT:
id from database if successful insert; otherwise null.
*/

$link = connect_db();
/* check connection */
if ( mysqli_connect_errno() ) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}

$sql = "INSERT INTO user
(
first_name,
last_name,
home_town,
job,
age
) VALUES (
?,
?,
?,
?,
?
)";

$statement = $link->prepare($sql);

if (!$statement) {
printf('Error - SQLSTATE %s.\n', mysqli_sqlstate($db_connection));
exit();
};

// Filter data (regex's, validate, etc)
$first_name = get_name_regex($input['first_name']);
$last_name = get_name_regex($input['last_name']);
$home_town = get_name_regex($input['home_town']);
$job = get_name_regex($input['job']);
$age = get_integers_only_regex($input['age']);

// Bind-parameters: s=string, i=integer, d=double, b=blob
$statement->bind_param('ssssi', $first_name, $last_name, $home_town, $job, $age);

$statement->execute();

if ($link->error) {
echo $link->error;
}

if ($link->insert_id) {
$result = $link->insert_id;
}

echo

$link->close();

return $result;
}

/*====== DATA FILTERING and VALIDATION =============================*/
function get_name_regex ($input) {
$pattern = '/(;|\||`|=|--|\/|\.|>|<|&|^|"|'."\n|\r".'|{|}|[|]|\)|\(|[0-9])/i';
$input = preg_replace($pattern, ' ', $input);
return trim(ucfirst($input));
}

// Given any input, we only want a valid integer here, e.g. 2.24 --> 2
// Specify the length desired.
function get_integers_only_regex ($input, $len = 100) {
// $input = (int)$input; // typecast will fail if you have a zip w/ a leading 0, e.g. 09921
if ($len > 0) {
$pattern = '/\D/';
$input = preg_replace($pattern, '', $input);
$input = substr($input, 0, $len);
}
return $input;
}
?>

html/index.php : the HTML Page Containing the Form

<html>
<head><title>Stealth Submit</title>

<script src="/js/prototype-1.6.0.3.js"></script>
<script language = "Javascript">
function saveData() {
new Ajax.Request('savedata.php', {
method: 'post',
parameters: {
// $('form_id').serialize(true)
first_name: document.getElementById('first_name').value,
last_name: document.getElementById('last_name').value,
home_town: document.getElementById('home_town').value,
age: document.getElementById('age').value,
job: document.getElementById('job').value
}
});
}

</script>

</head>
<body onunload="saveData()">
<form id="form_id" method="post" action="action.php">
First Name: <input type="text" id="first_name" name="first_name"><br/>
Last Name: <input type="text" id="last_name" name="last_name"><br/>
Age: <input type="text" id="age" name="age"><br/>
Hometown: <input type="text" id="home_town" name="home_town"><br/>
Job: <input type="text" id="job" name="job"><br/>
<input type="submit" value="Submit" />
</form>

<a href="http://www.google.com/">Arbitrary Other Page... FORM NOT SUBMITTED</a>

</body>
</html>

A better solution to Presentations in Linux

You may have noticed that OpenOffice is great. You also may have noticed that this greatness runs out when you get to Impress. My primary complaint (Oh there are many, most of them “known issues” at the open office site for years) is a lack of anti-aliasing on shapes. In a business situation, a presentation on par with the expectations of 1995 will only get you so far.

A Circle in Impress
Jaggies...a lot of them
A Circle in Powerpoint
Same 200% zoom as Impress.

I in no way endorse the use of PowerPoint, but I haven’t had a [Professional] alternative. I acquired a new Linux-based laptop and just today realized that I wouldn’t be able to give presentations off it without jumping through hoops. Of course there are options (PDF slide viewers, LaTEX, etc.) but I want a straight-forward presentation program that meets my meager demands of Anti-Aliasing and a simple interface. Luckily, I tend to have an active Internet connection at most presentations. This brings me to: 280 Slides.

280 Slides is a WebApp that provides, nearly, full functional slide show creation.

A Circle in 280 Slides
200% Zoom
200% Zoom

It’s still in BETA, but it shows amazing promise. Registration is free, and as far as I can tell so far, it beats Google’s presentation ability by a long shot. I wonder how long before Google acquires them…

The Good:

  • Accessible on any OS from any computer with an active Internet connection.
  • Ability to save sideshow in .pptx, .ppt, .odp, and .pdf
  • Fairly faithful conversion to previously mentioned file types.
  • Ability to Import from uploads of the previously mentioned file types (sans .pdf).
  • Ability to insert Images, Video, Shapes, etc. You can even upload your own shapes.
  • Many themes included, all classier than some of PowerPoint’s ugly templates, or the 2 ridiculous themes that ship with Impress.
  • Ability to add “Notes” to each slide.
  • Straight forward, intuitive interface.
The Interface
The Interface

The Bad:

  • Currently no way to upload your own custom background image. Work Around: Insert it as an image and make it the size of the slide.
  • No transitions. In a serious presentation, however, do you really need objects flying in and spinning with cute sound effects? Only if you want to get laughed at.
  • No way to operate a “Presenter View.”
  • No “Master Slide” for objects and footers that are persistent across all slides.

Overall:

-This will be my new presentation software when I’m bound to my Linux system. If I have access to a Mac, though, I will use Keynote for its powerful elegance. I’m interested to see where this goes when it reaches full release. Hopefully registration will stay free.

-At a later date, I will be comparing 280 Slides to Slide Rocket (http://www.sliderocket.com/).  By “at a later date” I mean when Lan Support Services feels the need to update the flash on my office computer.  Feel free to check it out as another alternative.  [Thanks to Brian for pointing me to Slide Rocket]

Content Management Systems (CMS)

If you’ve been around the web block a few times and know a thing or two about putting up a web site, you’ve probably heard something about Content Management Systems (CMS). They can be real time-savers, and the basic premise is this: you forgo all the hand coding that you’ve been doing to keep your site going and you plug into the “already-invented-wheel” to get rolling.

CMS’s usually require a database (often MySQL) and a server side scripting language (often PHP). It’s a powerful combo: you can create templates that control how the content looks then add all the content you want. The templates go beyond the style sheets, they incorporate the html used by the pages that reference the CSS, and they can also include things like Javascript for controlling menus or fixed footers. Usually the templates rely on a placeholder that indicates where the content should be added.

There are a LOT of CMS’s out there, and it seems like every corporate code-monkey gets pegged to code a new CMS for in-house work at some point or another. http://opensourcecms.com/ provides a nice way to try out different CMS’s to get a feel for what they’re like. The site is a bit awkwardly laid-out, but you can get a long list of CMS’s on the left by opening the “portal” items under the “CMS Demo Menu” section.

One long weekend, I tried out a number of these… my choice? MODx — it’s free and it made a lot of sense to me. Still in beta, not a huge user base, but easy to work with (IMHO). But don’t take my word for it… you should evaluate what you need to do with your CMS. If it’s a quick and dirty blog you need, WordPress is hard to beat.

One big contender that costs about $100 is Expression Engine — it comes highly rated from people I work with who are in the know.

Here’s a list of the ones that have gotten the most air-play in my line of work (coding):

  1. Drupal — often recommended for people building “static” type sites with lots of fixed pages. Has a pretty good user base, but again, I disliked the boxy layout approach and the whacko documentation
  2. Joomla — made by most of the same people who made Mambo. Boxy layouts and weird vocabulary.
  3. MODx — My personal favorite. Nice AJAX back-end and easy compartmentalization between front-end and back-end contributions. It’s really easy to take an existing static site and drop in CMS functionality using MODx. It’s also bloody simple to add your own custom PHP scripts. MODx is a leader when it comes to an SEO friendly site.
  4. WordPress — quick and dirty, great for blogs, huge user base… but no so good if you have specific needs and the template system isn’t the easiest and adding custom PHP scripts can be painful

Here’s an intro video I made about MODx:

Dropbox: Mini-Review and Invitations (Online Storage Series)

Dropbox logo

At long last, I have found the online storage solution of my dreams. Dropbox is a service (currently in public beta) that not only seamlessly backs up your data, but can also sync it across multiple computers. Best of all, it all happens without you having to lift a finger.

Why am I so excited about Dropbox? First of all, I classify online storage into a few different categories:

All three types of services have their uses, and Dropbox tickles my fancy (am I allowed to say that?) because it handles all three types with aplomb. To make it even better, Dropbox works on both Windows and Mac systems, and a Linux client is currently in alpha.

Usage

Get this – actually using Dropbox takes almost no effort on your part. Once you install the Dropbox client, it creates a My Dropbox folder inside your Documents. Any files or folders that you put inside the My Dropbox folder will first upload to the Dropbox service and then sync across to any other computers that you have linked. The green check mark next to a folder or file means that it has been successfully uploaded and synced.

Delete a file on one computer, and it will be deleted first on Dropbox and then on the other linked computers. This is an incredible way to not only make sure your files are continuously backed up, but to also make sure you always have the latest version of your files across multiple computers. Imagine taking your laptop to a coffee shop to get some work done, and when you return home, ALL the data you modified is available on your desktop computer. Nice! No more e-mailing files or dumping everything onto a flash drive.

Even if you only have a single-computer setup, Dropbox is still an effortless way to keep your data backed up.

For those worried about security, Dropbox currently uses the Amazon S3 service to store files. All files are encrypted with AES-256 and all communication occurs over SSL.

Other Features

In addition to being an all-encompassing storage and sync solution, Dropbox has other tricks up its sleeve. For starters, there’s a versioning system for keeping track of changes to a file (or grabbing an earlier version in case of an emergency). There’s also a nifty web interface, a photo gallery, file sharing capabilities, and more! Don’t just take my word for it – check out the screen cast below.

http://www.youtube.com/watch?v=OcS9w9dpKNQ

If you can’t tell, Dropbox is undoubtedly my favorite online storage service, not only for its features, but for its sheer simplicity. It’s a service that I have no trouble recommending to others.

Dropbox Invitations!

As I mentioned, Dropbox is currently in beta and requires an invitation. Their beta service provides 2 GB of free storage, and beta users will have slightly more storage capacity than the regular free amount once they drop beta status. So, act now!

TipsFor.us currently has 0 invitations available. Simply post a comment below and we will e-mail you an invitation. First come, first serve! All invitations are gone, folks. Sorry. You can always join the waiting list for the beta. If we receive more invitations, this post will be updated.

If you enjoyed this article, please subscribe to our RSS feed for future updates.

3 Little Perl Debugging Tips

I’ll do a little walk-through of the Perl debugger in a separate post, but here are a couple hard-earned morsels of knowledge that I thought I could share:

If your code is NOT compiling, the most common hard-to-find error is forgetting a semi-colon or a paren or brace in the lines above. The error message usually clocks in on the line AFTER the goof. Look above the line listed in the error message and see if you didn’t forget a semi-colon somewhere.

If your code IS compiling, but you’re still getting weird results, here are a couple tips to help you along:

1. Make sure your code is written in coherent, bite-sized chunks. If you can’t see an entire function/action on the screen, then your building blocks are too big. Writing code in smaller chunks lets you test each chunk individually. Alas, this doesn’t always happen, so…

2. If you are using a lot of hash references ( stuff like $my_hash_ref->{$some_id}->{'some_value'} ), then you are bound to run into the pitfalls of using hashes: namely mispellings. Oops. Misspellings. (Did you catch that?) TRIPLE CHECK YOUR SPELLINGS. Highlight your variable name/hash-key do a search for it — if it doesn’t show up somewhere else, then you know you have a problem. Perl happily will do this:
$my_hash_ref->{$some_id}->{'some_valeu'} = 1;

Note the mispelling — you just stashed a value in the wrong place in the hash. Perl auto-vivified without any warnings because that’s what it’s supposed to do.

3. Make sure you haven’t botched your reference arrows. E.g.
$my_hash_ref->{$some_id}-{'some_value'}

Oops. Notice I forgot a ‘>’ there between the id and value. This actually compiles! But it’s not what you want! Do yourself a favor and search your code for any instances of ‘-{‘ — you may be surprised by the horrors you find.