print documents via web interface

This simple php code will allow to choose one or more documents and prints them using the local cups printer. There is also a possibility to select one of the locally installed printers.

There are some prerequesites as follows:

  • install unoconv and openoffice/libreoffice (import filters are required)
  • install calc, writer, impress, draw as required (import formats)
  • local lpr printing programm and lpstat for list of installed printers are required
  • upload is putting any non-pdf document in a local folder on the webserver for conversion this folder must be writable by PHP/apache
  • copy this file to location accessible by apache
<?php ############# HEAD  ############################
echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n";
echo "<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n";
/* Short Introduction
 * 
 * - install unoconv and openoffice/libreoffice (import filters are required)
 * - install calc, writer, impress, draw as required (import formats)
 * - local lpr printing programm and lpstat for list of installed printers are required
 * - upload is putting any non-pdf document in a local folder on the webserver for conversion
 *   this folder must be writable by PHP/apache
 * - copy this file to location accessible by apache
 */
############# Configuration ##########################
$print_command = "/usr/bin/lpr -P ";# local print command
$conv_command = "unoconv -f pdf ";# conversion command
$upload_directory ="/var/www/PDF/";# dir where all the magic takes place
$filesize = 100000;# file size limit in kB
$printer_default = "PDF";# default printer for first start
### no changes should be necessary beneathe this line
$reg_printer = "/^device for (.*): .*$/im";# examination of lpstat to get list of installed printers
$PHP_SELF = htmlspecialchars($_SERVER['PHP_SELF']); 
$uploadcounter = 1;#default value for number of upload buttons
echo "<title>Print File</title>\n</head>\n<body>\n\n";
###### debug output of POST
# debugging function to show HTML variables
#
function debug_output(){
	echo "<pre><br><h1>Show internal variables</h1>";
	print_r($_POST);echo "<br>";
	print_r($_FILES);
	echo "</pre>"; return ;
}
###### get local printerrs #############
# function will examine lpstat to get list of
# locally installed printers
#
function get_local_printer($printer_default){
	global $reg_printer;
	$output = shell_exec("/usr/bin/lpstat -s");
	if (preg_match_all($reg_printer, $output, $printer)) {
		echo "<SELECT name='printer' size='1'>\n";
		foreach ($printer[1] as $key => $value){
		echo "<OPTION";if ($printer_default == $value) echo " selected";echo "> ".$value." </OPTION>\n";
		}
		echo "</SELECT>";
	}
	return;
}
###### file upload box with comment text
# show file upload box with in-/decrease button
#
function fileupload_box($text, $count=1){
	global $filesize;
	if ($text != "") echo "<h2>".$text."</h2>\n";# show status information on top
	echo '<input type="hidden" name="MAX_FILE_SIZE" value="'.$filesize.'" >';
	echo "<table border='0'>";# Table for formatting
	for ($i=0; $i < $count; $i++){
		echo "<tr><td><input type='submit' name='addcounter' value='+'></td>";
		echo "<td><input type='submit' name='delcounter' value='-'></td>";
		echo "<td>File to print Nr. ".$i." :</td><td><INPUT TYPE='file' NAME='print_file[]' size='50'></td></tr>\n";
	}
	echo "<tr><td colspan='4'>&nbsp; </td></tr>";
	echo "<tr><td colspan='4' align='center'><INPUT TYPE='SUBMIT' NAME='UPLOAD' value=' PRINT '></td></tr>\n</table>\n";
}
############################## MAIN ##################################
echo "<form method='post' action='$PHP_SELF' enctype='multipart/form-data'>\n";# form for file upload
if (isset($_POST['uploadcounter'])) $uploadcounter = $_POST['uploadcounter'];
if (isset($_POST['addcounter'])) $uploadcounter = $uploadcounter+1;# additional upload button please
if (isset($_POST['delcounter'])) $uploadcounter = $uploadcounter-1;# delete one upload button please
if (isset($_POST['printer'])) $printer_default = $_POST['printer'];# keep choosen printer
if ($uploadcounter < 1) $uploadcounter=1;# at least one entry must remain
echo "<table width='100%'><tr><td><h1>Print selected Files</h1></td>\n";$text = "";
echo "<td>Choose Printer:</td><td>";get_local_printer($printer_default);
echo "</td></tr></table>\n";
if (isset($_POST['UPLOAD'])) {# upload button pressed;the magic begins
	for ($i=0; $i < $uploadcounter; $i++){# iterate over list of files
		$file = $_FILES['print_file']['tmp_name'][$i];# temporary file name
		$filename = $upload_directory.basename($file);# final doc name incl folder
		if ($file == "" || $_FILES['print_file']['size'][$i] == 0 || !is_file($file)) { # no file selected 
			$text = "Please choose files to print!";
		}
		else {
			if (is_uploaded_file($file)) { # check for upload errors
				if(!move_uploaded_file($file, $filename))# copy files to dir
					echo "<h2>Moving file".$file." to destination ".$upload_directory." failed!</h2>";
				else{
					if (strripos(mime_content_type($filename), "pdf") === false){# check if file mime type is pdf
						shell_exec( $conv_command." ".$filename." -o ".$filename.".pdf > /dev/null");# unoconv -f pdf file
						shell_exec( $print_command.$printer_default." ".$filename.".pdf > /dev/null");# execute print command
						echo "<p style='color:#aaaaaa, font-size:50%'> (".$print_command.$printer_default." ".$filename.".pdf) </p>";
					}
					else # file is pdf, so print directly
						shell_exec( $print_command.$printer_default." ".$file." > /dev/null");# execute print command
					echo "<br>Printouts may be found in your local printer\n";# be polite ;-)
				}
			}
			else { # file upload went wrong
				$text = "File Upload error";
			}
		}
	}
	$uploadcounter=1;# reset counter
}
echo "<input type='hidden' name='uploadcounter' value='".$uploadcounter."'>";# take hidden counter for number of upload buttons
fileupload_box($text, $uploadcounter);# generate upload boxes
#debug_output();# show debug information
echo "</form>\n</Body></HTML>\n";# The End!
########### END ###################################?>

Cups Print Server with remote printer driver

To enable remote printing on a print server first setup the server with the correct printer drivers. In my case I had to install foo2zjs package in order to get my printer running. My network printer was than configured using the cups webinterface as socket://:9100 which is quiet specific for my HP printer.
The remote printing must be configured using the following entries in cupsd.conf:

Listen ip of printserver:631
BrowseOrder Deny,Allow
BrowseAllow From local net/255.255.255.0

Order deny,allow
Deny From All
Allow From localnet /255.255.255.0

on the client side please add the following directive to cupsd.conf:

BrowsePoll ip of printserver :631

In newer versions of cups the directive must be placed in cups-browsed.conf. The directive itself remains the same.

Do not forget to start both servers in order to get the new directives working. On the client machine the remote printers should be available in the webinterface as newly added printers ready for jobs.

In newer versions do not forget to restart the cups-browsed service also.