A Programmer’s Perspective twitter
A Programmer’s Perspective Rss

PHP File Streaming with cat and passthru

Posted by Jason | Posted in linux, mysql, php | Posted on 09-11-2009

3

The problem

This weekend, I needed to figure out how to make an on-request, downloadable, backup of an entire MySQL database (for Magento, in case you were wondering).
At first, I attempted the simplest approach, which was to perform the backup via system() or exec(), and then serve the file as a download using either file_get_contents or fopen/fread, etc. This wouldn’t work because PHP would run out of memory when reading the file. I even tried stream_get_contents() with the same result.

Hmmm….

I’m sure there are other ways of getting this done, but my approach has been working flawlessly so far and I thought I’d share with you.

The solution

Here is the entire code segment which performs the backup, bzips the SQL file, then serves it as a download using passthru and cat.


//Define where backup will go
$backup_folder = getenv("DOCUMENT_ROOT") . $settings['base_url'] . '/backup/';
$backup_file = 'aps_backup_' . date("Y-m-d-H-i-s") . '.sql.bz2';
$backupFile = $backup_folder . $backup_file;

//Perform the database backup
$command = "mysqldump --opt -h$dbhost -u$dbuser -p$dbpass $dbname | bzip2 > $backupFile";
error_log("Executing: $command");
exec($command);

//Serve file as download
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$backup_file\"");
passthru("cat $backupFile");

As you can see, the database backup command is executed, and the output is bzipped and stored in the “backup” folder.
Once the command is completed, the headers are setup to serve a file download, and using the passthru command, we simply cat the file.
This effectively streams the file as a download, thus alleviating the memory limit errors I was receiving when trying to open/read/serve the large file download.
Obviously, this wouldn’t work on Windows.

I’m curious if anyone else has been faced with this problem, and what your solution(s) were?

PHPMailer Inline String Attachment

Posted by Jason | Posted in mysql, php | Posted on 09-09-2009

1

Recently, while using PHPMailer, I needed the ability to have an inline string attachment, however this functionality is not present as of version 5.0.2, so I wrote my own.

For those who don’t know, PHPMailer has a number of ways you can create email attachments:

  • Standard Attachment – works as you’d expect
  • Inline Attachment – attachments you can reference in the message body. For instance, if you attach an image, you can then reference that image using the IMG tag in the body
  • String Attachment – builds an attachment from blob data (usually stored in a database)

Inline attachments and String attachments rock, however there was no combination of the two. So, I wrote one. Simply add this block of code to your phpmailer class and you’re good to go.


/**
* Adds a string or binary attachment (non-filesystem) to the list.
* This method can be used to attach ascii or binary data,
* such as a BLOB record from a database.
* @param string $string String attachment data.
* @param string $cid Content ID of the attachment. Use this to identify
* the Id for accessing the image in an HTML form.
* @param string $filename Name of the attachment.
* @param string $encoding File encoding (see $Encoding).
* @param string $type File extension (MIME) type.
* @return void
*/
public function AddInlineStringAttachment($string, $cid, $filename, $encoding = 'base64', $type = 'application/octet-stream') {
// Append to $attachment array
$this->attachment[] = array(
0 => $string,
1 => $filename,
2 => $filename,
3 => $encoding,
4 => $type,
5 => true, // isStringAttachment
6 => 'inline',
7 => $cid
);
}

Wordpress API

Posted by Jason | Posted in php | Posted on 05-07-2009

4

Recently I’ve gotten into Wordpress plugin development. I’ve created a few plugins for clients that include widgets, settings pages, and hooks into several actions. However, one thing I’ve not yet been able to figure out is how to encrypt settings page options. Has anyone done this?

There are currently a few ways to create settings pages. You can either write out the entire form, or you can create sections and fields using the API. Each option, however, utilizes get_option() to show the current value.

This is fine, however there is no API function (that I’ve found) that runs BEFORE an option is updated. The only function I have right now is update_option_(the_option)(). But, this runs AFTER the update has already happened. So, if I wanted to encrypt those options using server-side encryption, I would enter into an infinite loop since I’d be calling update_option_(the_option)() over and over again.

Has anyone ever encrypted settings page option values before? If so, how do you go about doing it properly?

I’m sure I can hack together a solution that encrypts & decrypts the values using Javascript on the form, but that just seems dirty to me.

I’d be interested to hear if anyone else has had this problem.

Kaltura Wordpress Plugin – Switching Partner IDs

Posted by Jason | Posted in mysql, php | Posted on 26-05-2009

0

I am using the Kaltura All-In-One-Video Wordpress Plugin on a project these days and I’ve come across a situation where I needed to switch my Partner ID to a new one (we purchased a paid account).

However, there is currently no way of doing this in the interface or by editing any of the plugin files… weird.

After calling their support and getting no answer, I found my own solution and I’m posting it here in hopes that it may help you.

This involves deleting a few rows from the wordpress database, so I’d recommend doing a backup before any of this.

Simply running the following SQL statement on your wordpress database will remove all Kaltura configurations:

delete from wp_options WHERE option_name LIKE ‘kaltura%’;

After running this statement, login to the admin area of Wordpress and you will now be prompted to Create a Partner ID (or specify an existing one).

Hope this helps!

Antipodr

Posted by Jason | Posted in php | Posted on 29-10-2008

5

Antipodr is a simple little tool I created with Jake Rutter that allows you to calculate the exact spot on the other side of the planet from any location you enter.  A complete waste of time, yes, but fun!

Antipodr utilizes Google Maps and the Google Geocoding Web Service to bring you the end result.  Once the system determines the coordinates, a simple calculation determines the antipodal point (hence the domain name) and displays the map of that area.

On a side note, it turns out you’d have to live in Chile or Argentina in order to dig to China.  Lies!

Antipodr - Find the other side of the world!

Antipodr - Find the other side of the world!

Check out Antipodr now!

PHP Autoload Issue

Posted by Jason | Posted in php | Posted on 11-09-2008

0

On a recent project, I couldn’t figure out why the following block of code worked on OSX but not Red Hat Linux.


function __autoload($class_name) {
require_once 'lib/' . $class_name . '.class.php';
}

I had a class named ‘bank.class.php’ which autoload was attempting to find.  It worked properly on OSX, however on Linux it wouldn’t work.  I quickly discovered that Linux required the file to be renamed to ‘Bank.class.php’.  Alternatively I could have changed the autoload to:


function __autoload($class_name) {
require_once 'lib/' . strtolower($class_name) . '.class.php';
}