Monthly Archives: March 2014

CUPS-to-CUPS printing with server-side processing and page_log

Printer sharing on Windows is easy: the client receives the driver from the server, presents the driver GUI and passes on an intermediate format along with the options selected in the driver to the server, which then renders the print job for the printer (usually into PostScript).

In the Unix (Mac OS X in my case, but Linux would be the same) world, CUPS is commonly used for printing. It’s very powerful, but I find the documentation severely lacks details about the exact way something is implemented in the code. Luckily, the code is open-source and Michael Sweet, the developer of CUPS who now works at Apple and still maintains CUPS, managed to create a very structured piece of software with code that’s reasonably easy to understand.

If you just add a CUPS server’s print queue as a new printer on a CUPS client, it will work fine, but you might run into some inconveniences:

Problems

  1. The job might get run through a vendor-supplied filter twice, once on the server and once on the client. This usually works fine, but the print job might significantly increase in size (observed on an HP LaserJet).

  2. The page_log on the server might not contain the number of pages and copies a job consisted of and list 1 for both instead.

  3. The page_log on the server might not contain things like page format, duplex status or attributes you manually added to PrintLogFormat.

Reasons

  1. This happens if the PPD both on the client and on the server contains a line starting with *cupsFilter, which links to a vendor-supplied filter. Such a filter usually produces a MIME type of application/postscript.

  2. This happens if the job does not get run through the pstops filter by CUPS. CUPS bypasses that filter if the client submits the job with a MIME type of application/vnd.cups-postscript, i.e. it was already run through pstops on the client.

  3. This is either caused by the same things as (1) or (2), but I’m not sure which one.

Solution

Simply add the following lines to the PPD on the client. That way, it passes the job straight to the server for server-side processing.

*cupsFilter: "application/pdf 0 -"
*cupsFilter: "image/* 0 -"
*cupsFilter: "application/postscript 0 -"
*cupsFilter: "application/vnd.cups-postscript 0 -"
*cupsFilter: "application/vnd.cups-command 0 -"

By the way, if you use Mac OS X and let the “Add Printer” wizard automatically add a print queue from a remote CUPS server discovered via Bonjour, this is exactly what it does.

Notes

If you append something like %{SelectColor} to your PageLogFormat because that’s the attribute your printer uses to determine whether it should print in color or grayscale and you’d like to log that, please note that the default value (either as specified by the PPD or as specified by you via lpadmin -d printername -d SelectColor=Grayscale or via the CUPS web interface’s “Set Printer Defaults”) will never be written to the page_log. Only deviations from the default value will be logged. The defaults set on the server-side CUPS do not matter here, this is determined by the client-side CUPS.

Per the filter(7) documentation (italic comments were added by me):

Options passed on the command-line typically do not include the default choices the printer’s PPD file. […] use the ppdMarkDefaults [which sets all options to the defaults specified inside the PPD] and cupsMarkOptions [which sets the options to the values specified in the driver GUI] functions in the CUPS library to use the correct mapping, and ppdFindMarkedChoice [which reads from the options array composed from the defaults and the selected options] to get the user-selected choice.

WordPress Plugins

After I recently set up a blog for a friend, I thought I’d post a list of plugins I use on the various WordPress instances I run for various people and myself.

  • Simple Custom CSS. Allows you to add custom CSS to your blog without having to modify theme files. This makes it easy to update themes in the future without breaking your customizations.
  • Include plus Shortcodes Everywhere. This allows you to create a Text Widget that displays a static page from your blog using a tag like [include id="15"].
  • Category Order. Allows you to reorder the list of categories in the sidebar.
  • KB Easy PicasaWeb. Converts Picasa links into embedded photo galleries.
  • WP Events Calendar. Gives you a simple calendar widget into which you can manually enter events.
  • Jetpack. Enables some useful features like infinite scrolling, custom CSS, sharing links, and mobile theme.
  • Akismet. A must-have spam filter if you allow comments on your blog.
  • Contact Form 7 plus Really Simple CAPTCHA. Highly flexible contact form including CAPTCHAs.
  • WP Permalauts. A must-have if you blog in a language that has accented letters or umlauts. It converts those letters to the non-accented ones in permalinks.
  • WP Hide Post. Lets you selectively hide posts from categories, front page, etc. while they remain accessible through other ways and direct links.
  • BackWPup. Does full backups of your WordPress data and database to a tarball on the server or your Dropbox. Can run on a schedule to automate the backups.

A theme that I quite like is Sunspot. You can display the featured image, title and lead text of two posts next to each other and customize how many posts you want per page in total. It also has enough space for widgets in its sidebars and is responsive. The downloadable version does not currently do infinite scrolling, but I believe hosted WordPress.com has such a version.

Calling the parent constructor in PHP 5

Say you write a PHP class that needs to call the parent constructor. At first sight, this is simple:
function __construct()
{
parent::__construct();
}

Say you want to pass some arguments to the parent constructor:
function __construct($arg1, $arg2)
{
parent::__construct($arg1, $arg2);
}

Now what do you do if you have default arguments?
function __construct($arg1 = NULL, $arg2 = NULL)
{
if ($arg1 == NULL && $arg2 == NULL) parent::__construct();
elseif ($arg2 == NULL) parent::__construct($arg1);
else parent::__construct($arg1, $arg2);
}

Not pretty, especially if you have many possible arguments. The obvious generalization would be
function __construct()
{
call_user_func_array(array('parent','__construct'), func_get_args());
}

However, this actually fails for two reasons on PHP below version 5.3: func_get_args() cannot be used as a function argument, and call_user_func_array does not treat parent correctly.
So here’s the entire constructor I ended up with that does absolutely nothing but calling the parent function:
function __construct()
{
$args = func_get_args();
if (version_compare(PHP_VERSION, '5.3.0') >= 0)
{
call_user_func_array(array('parent','__construct'), $args);
}
else
{
$refl = new ReflectionObject($this);
$method = $refl->getParentClass()->getConstructor();
$method->invokeArgs($this, $args);
}
}

Seriously, you have to use reflections for this seemingly simple task?!