Index: rver/lib/TODO
===================================================================
--- server/lib/TODO	(revision 30beeab008c68e1e024ed39a16b17a5d50ed07a3)
+++ 	(revision )
@@ -1,2 +1,0 @@
-- gutenbach-get-config should fail and error out if it can't find a
-   config file -- we can't use defaults since what would the defaults be?
Index: rver/lib/gutenbach-filter
===================================================================
--- server/lib/gutenbach-filter	(revision df510617607a17049c40187f93c7ce3d26508ae1)
+++ 	(revision )
@@ -1,348 +1,0 @@
-#!/usr/bin/perl
-# Play the data on STDIN as an audio file
-#
-# $Id: gutenbach-filter,v 1.26 2009/02/20 00:27:17 geofft Exp root $
-# $Source: /usr/local/bin/RCS/gutenbach-filter,v $
-#
-# TODO
-# ----
-# Make this structured code. It's a mess.
-# Repeat what we just played for EXT files too
-# Support HTTP Auth on ogg streams
-# License, cleanup and package
-#
-# Jered Floyd <jered@mit.edu> takes very little credit for this code
-# apparently neither does Quentin Smith <quentin@mit.edu>
-
-use strict;
-use warnings;
-use Image::ExifTool qw(ImageInfo);
-use File::Spec::Functions;
-use File::Temp qw{tempfile tempdir};
-use File::Basename qw(basename);
-use LWP::UserAgent;
-use Data::Dumper;
-use IPC::Open2;
-use English;
-
-use vars qw/$zephyr_class $host $queue $mixer $channel/;
-
-require "/usr/lib/gutenbach/config/gutenbach-filter-config.pl" or die "Unable to load configuration";
-
-my $ua = new LWP::UserAgent;
-
-# This variable contains the pid of the child process (which runs
-# mplayer) once it has been forked, so that we can kill it on SIGTERM
-my $pid;
-
-# Replace STDERR with a log file in /tmp.
-open(CUPS, ">&STDERR") or die "Unable to copy CUPS filehandle";
-close(STDERR);
-open(STDERR, ">>", "/tmp/gutenbach.log") or warn "Couldn't open log: $!";
-
-# Set the TERM environment (for the benefit of mplayer?)
-# I don't know why we do this --quentin
-$ENV{"TERM"}="vt100";
-
-print STDERR "STDERR FROM SPOOL FILTER\n";
-
-# CUPS provides us with these arguments:
-#
-# argv[1]
-# The job ID
-# argv[2]
-# The user printing the job
-# argv[3]
-# The job name/title
-# argv[4]
-# The number of copies to print
-# argv[5]
-# The options that were provided when the job was submitted
-# argv[6]
-# The file to print (first program only)
-#
-# The scheduler runs one or more of these programs to print any given
-# job. The first filter reads from the print file and writes to the
-# standard output, while the remaining filters read from the standard
-# input and write to the standard output. The backend is the last
-# filter in the chain and writes to the device.
-
-printf(STDERR "Got \@ARGV: %s\n", Dumper(\@ARGV));
-
-my %arguments = (
-		 "job-id" => $ARGV[0],
-		 user => $ARGV[1],
-		 "job-title" => $ARGV[2],
-		 copies => $ARGV[3],
-		 options => {split(/[= ]/, $ARGV[4])},
-		 file => $ARGV[5],
-		);
-
-# If we weren't given a filename, we need to read from stdin. Since
-# mplayer really wants a file, let's write out to a temporary file
-# first.
-if (!$arguments{"file"}) {
-  my ($fh, $file) = tempfile("gutenbachXXXXX", UNLINK => 1); # Ask File::Temp for a safe temporary file
-  my $buf;
-  while (read(STDIN, $buf, 1024*1024)) { # Read 1M at a time and put it in the temporary file
-    print $fh $buf;
-  }
-  close($fh);
-  $arguments{"file"} = $file;
-}
-
-printf(STDERR "Got \%arguments: %s\n", Dumper(\%arguments));
-
-# Open up a zwrite command to announce the current track.
-my @zwrite_command = (qw(/usr/bin/zwrite -d -n -c), $zephyr_class, "-i", $queue.'@'.$host, "-s", "Gutenbach Music Spooler");
-
-print STDERR "Invoking @zwrite_command\n";
-open(ZEPHYR, "|-", @zwrite_command) or die "Couldn't launch zwrite: $!";
-
-my $status;
-if (exists($arguments{"options"}{"job-originating-host-name"})) {
-    print(ZEPHYR $arguments{"user"},"\@",$arguments{"options"}{"job-originating-host-name"}," is playing:\n");
-    $status = "User: ".$arguments{"user"}."\@".$arguments{"options"}{"job-originating-host-name"};
-} else {
-    print(ZEPHYR $arguments{"user"}," is playing:\n");
-    $status = "User: ".$arguments{"user"};
-}
-
-# SIGHUP handler, in case we were aborted
-sub clear_status {
-  kill 15, $pid if $pid;
-  my @zwrite_command = (qw(/usr/bin/zwrite -d -n -c), $zephyr_class, "-i", $queue.'@'.$host, "-s", "Gutenbach Music Spooler");
-  open(ZEPH, "|-", @zwrite_command);
-  print(ZEPH "Playback aborted.\n");
-  close(ZEPH);
-
-  open(STATUS, ">", "/var/run/gutenbach/status");
-  print(STATUS "");
-  close(STATUS);
-  die;
-}
-
-$SIG{HUP} = \&clear_status;
-$SIG{TERM} = \&clear_status;
-$SIG{INT} = \&clear_status;
-
-# Read the metadata information from the file.
-my ($filepath) = $arguments{"file"};
-my ($fileinfo) = ImageInfo($filepath);
-my ($magic) = $fileinfo->{FileType};
-my ($tempdir);
-my ($newpath);
-my ($title);
-
-open(STATUS, ">", "/var/run/gutenbach/status");
-
-if ($magic) {
-  # $magic means that Image::ExifTool was able to identify the type of file
-  printf(ZEPHYR "%s file %s\n", $magic, $arguments{"job-title"});
-  #printf(STATUS $arguments{"job-title"});
-  $status .= sprintf(" Filetype: %s.", $magic);
-  $status .= sprintf(" Filename: %s.", $arguments{"job-title"});
-  if (exists $fileinfo->{'Title'}) {
-      $title = $fileinfo->{'Title'};
-    printf(ZEPHYR "\@b{%s}\n", $fileinfo->{'Title'}) if exists $fileinfo->{'Title'};
-    printf(STATUS "%s\n", $fileinfo->{'Title'}) if exists $fileinfo->{'Title'};
-    $status .= sprintf(" Title: %s.", $fileinfo->{'Title'});
-  }
-  foreach my $key (qw/Artist Album AlbumArtist/) {
-    if (exists $fileinfo->{$key}) {
-      printf(ZEPHYR "%s\n", $fileinfo->{$key}) if exists $fileinfo->{$key};
-      printf(STATUS "%s\n", $fileinfo->{$key}) if exists $fileinfo->{$key};
-      $status .= sprintf(" %s: %s\n", $key, $fileinfo->{$key});
-    }
-  }
-
-  $tempdir = tempdir();
-  #awful hack -- geofft
-  #== -- quentin
-  # This code appears to create a new temporary directory and symlink
-  # the job file into the temporary directory under the original
-  # filename. I think this is because mplayer sometimes uses the file
-  # extension to identify a filetype.
-  $newpath = $tempdir . '/' . basename($arguments{"job-title"});
-  symlink($filepath, $newpath);
-  $filepath = $newpath;
-}
-elsif ($arguments{copies} == 42) {
-  # This is a flag that is set by jobs queued by split_playlist(); it tells us to not try to split the playlist again.
-  # Call resolve_external_reference to apply some heuristics to determine the filetype.
-  $filepath = resolve_external_reference($filepath, \%arguments);
-  if ($filepath =~ m|http://www\.youtube\.com/watch\?v=|) {
-    # YouTube URLs are resolved by the youtube-dl command.
-    # Launch youtube-dl
-    $pid = open(YTDL, "-|", "youtube-dl","-b", "-g", $filepath) or die "Unable to invoke youtube-dl";
-	print ZEPHYR "YouTube video $filepath\n$title";
-	$status .= " YouTube video $filepath. $title.";
-	# youtube-dl prints the URL of the flash video, which we pass to mplayer as a filename.
-	$filepath = <YTDL>;
-	chomp $filepath;
-
-
-  } else { # Doesn't appear to be a YouTube URL.
-    print STDERR "Resolved external reference to $filepath\n";
-    printf(ZEPHYR "%s\n", $filepath);
-    $status .= sprintf(" External: %s\n", $filepath);
-  }
-}
-elsif (-T $filepath) { # If the file appears to be a text file, treat it as a playlist.
-  split_playlist($filepath, \%arguments);
-  close(ZEPHYR);
-  # See http://www.cups.org/documentation.php/api-filter.html#MESSAGES
-  print CUPS "NOTICE: $status\n";
-  exit 0;
-}
-
-close(ZEPHYR);
-close(STATUS);
-print CUPS "NOTICE: $status\n";
-play_mplayer_audio($filepath, \%arguments);
-
-# Remove the symlink we made earlier for the filetype.
-if ($magic) {
-  unlink($newpath);
-  rmdir($tempdir);
-}
-
-# Play an external stream reference
-sub resolve_external_reference {
-  # Retrieve those command line opts.
-  my ($filepath, $arguments) = @_;
-
-  my ($format, $uri, $userpass);
-
-  open(FILE, "<", $filepath) or die "Couldn't open spool file";
-  if (<FILE> =~ /^(\S+)/) {
-    # Take the leading non-whitespace as a URL
-    $uri=$1;
-
-    if ($uri =~ m|http://www\.youtube\.com/watch\?v=|) {
-      return $uri;
-    }
-
-    # Fetch the URL with a HEAD request to get the content type
-    my $response = $ua->head($uri);
-
-    my $contenttype=($response->content_type() or "unknown");
-
-    if ($contenttype eq "audio/mpeg") { $format="MP3" }
-    elsif ($contenttype eq "application/x-ogg") { $format="OGG" }
-    elsif ($contenttype eq "application/ogg") { $format="OGG" }
-    elsif ($contenttype eq "audio/x-scpls") { $format="SHOUTCAST" }
-    else {
-      print ZEPHYR
-	"Unknown Content-Type $contenttype for URI $uri\n";
-    }
-  } else { # Unable to match the URL regex
-    print ZEPHYR "Couldn't read URI for external reference\n";
-    # Return the existing path, in the hopes that mplayer knows what to do with it.
-    return $filepath;
-  }
-
-  if ($format eq "SHOUTCAST") {
-    print ZEPHYR "Shoutcast playlist...\n";
-    return get_shoutcast($uri);
-  } elsif ($format eq "MP3") {
-  } elsif ($format eq "OGG") {
-  } else {
-    print ZEPHYR "Unrecognized stream format: $format\n";
-  }
-  return $uri;
-}
-
-sub split_playlist {
-  my ($file, $arguments) = @_;
-
-  my $i = 0;
-
-  open(FILE, "<", $filepath) or die "Couldn't open spool file";
-  while (<FILE>) {
-    chomp;
-    if (/^([^#]\S+)/) {
-      printf (STDERR "Found playlist line: %s\n", $_);
-      $ENV{CUPS_SERVER}='localhost';
-      open(LP, "|-", "lp", "-d", "$queue", "-n", "42"); #'-#', '42', '-J', $arguments->{"job-title"}, '-o', 'job-priority=100');
-      print LP $1;
-      close(LP);
-      $i++;
-    }
-  }
-  printf(ZEPHYR "Playlist containing %d valid entries, split into separate jobs.\n", $i);
-}
-
-# Process a Shoutcast playlist
-# get_shoutcast(URI)
-sub get_shoutcast {
-  my $uri = shift(@_);
-
-  my $response = $ua->get($uri);
-  my (@titles, @uris);
-
-  foreach (split("\n", $response->content())) {
-      if (/^File\d+=(\S+)/) {
-	  push(@uris, $1);
-      }
-      if (/^Title\d+=(.+)$/) {
-	  push(@titles, $1);
-      }
-  }
-
-  # choose a random server
-  my $server = int(rand scalar(@uris));
-  # print the name of the stream if available
-  print ZEPHYR "$titles[$server]\n";
-  return $uris[$server];
-}
-
-sub play_mplayer_audio {
-  my ($filepath, $opts) = @_;
-
-  # Open up a zwrite command to show the mplayer output
-  my @zwrite_command = (qw(/usr/bin/zwrite -d -n -c), $zephyr_class, "-i", $queue.'@'.$host, "-s", "Gutenbach Music Spooler");
-
-  print STDERR "Invoking (from play_mplayer_audio): @zwrite_command\n";
-
-  # fork for mplayer
-  $pid = open(MP3STATUS, "-|");
-  unless (defined $pid) {
-    open(ZEPHYR, "|-", @zwrite_command) or die "Couldn't launch zwrite: $!";
-    print ZEPHYR "Couldn't fork: $!\n";
-    close(ZEPHYR);
-    return;
-  }
-
-  if ($pid) { #parent
-    # Check if there were any errors
-    if ($_ = <MP3STATUS>) {
-      open(ZEPHYR, "|-", @zwrite_command) or die "Couldn't launch zwrite: $!";
-      print ZEPHYR "Playback completed with the following errors:\n";
-      while (<MP3STATUS>) {
-	print ZEPHYR $_;
-      }
-      close(ZEPHYR);
-    } else {
-      open(ZEPHYR, "|-", @zwrite_command) or die "Couldn't launch zwrite: $!";
-      print ZEPHYR "Playback completed successfully.\n";
-      close(ZEPHYR);
-      open(STATUS, ">", "/var/run/gutenbach/status");
-      print(STATUS "");
-      close(STATUS);
-    }
-    close(MP3STATUS) || print ZEPHYR "mplayer exited $?\n";
-  }
-  else { # child
-    # redirect STDERR to STDOUT
-    open STDERR, '>&STDOUT';
-    # make sure that mplayer doesn't try to intepret the file as keyboard input
-    close(STDIN);
-    open(STDIN, "/dev/null");
-
-    my @args = (qw|/usr/bin/mplayer -vo fbdev2 -zoom -x 1024 -y 768 -framedrop -nolirc -cache 512 -ao alsa -really-quiet |, $filepath);
-    #pint STDERR "About to exec: ", Dumper([@args]);
-    exec(@args) ||
-      die "Couldn't exec";
-  }
-}
Index: rver/lib/gutenbach-get-config
===================================================================
--- server/lib/gutenbach-get-config	(revision 30beeab008c68e1e024ed39a16b17a5d50ed07a3)
+++ 	(revision )
@@ -1,35 +1,0 @@
-#!/usr/bin/perl
-use strict;
-# Get configuration of gutenbach
-
-my $zephyr_class = `hostname`;
-chomp($zephyr_class);
-my $host = `hostname`;
-chomp($zephyr_class);
-my $queue = "gutenbach";
-my $mixer = "PCM";
-my $channel = "Front Left";
-
-# Configuration
-my $config_file = "/usr/lib/gutenbach/config/gutenbach-filter-config.pl";
-if (-r $config_file) {
-    # Inline the configuration file
-    local $/;
-    my $fh;
-    open $fh, $config_file;
-    eval <$fh>;
-}
-
-my %config = (
-    'zephyr-class' => $zephyr_class,
-    'host' => $host,
-    'queue' => $queue,
-    'mixer' => $mixer,
-    'channel' => $channel,
-);
-
-foreach my $argv (@ARGV)
-{
-    #print $argv . "\n";
-    print $config{$argv};
-}
Index: rver/lib/ipplib.py
===================================================================
--- server/lib/ipplib.py	(revision d56a0bc5dc7dc8786c30fb5dfefec198f02e53df)
+++ 	(revision )
@@ -1,579 +1,0 @@
-#! /usr/bin/env python
-import sys,os,urllib2,socket
-from struct import pack, unpack
-
-IPP_VERSION = "1.1"
-
-IPP_PORT = 631
-
-IPP_MAX_NAME = 256
-IPP_MAX_VALUES = 8
-
-IPP_TAG_ZERO = 0x00
-IPP_TAG_OPERATION = 0x01
-IPP_TAG_JOB = 0x02
-IPP_TAG_END = 0x03
-IPP_TAG_PRINTER = 0x04
-IPP_TAG_UNSUPPORTED_GROUP = 0x05
-IPP_TAG_SUBSCRIPTION = 0x06
-IPP_TAG_EVENT_NOTIFICATION = 0x07
-IPP_TAG_UNSUPPORTED_VALUE = 0x10
-IPP_TAG_DEFAULT = 0x11
-IPP_TAG_UNKNOWN = 0x12
-IPP_TAG_NOVALUE = 0x13
-IPP_TAG_NOTSETTABLE = 0x15
-IPP_TAG_DELETEATTR = 0x16
-IPP_TAG_ADMINDEFINE = 0x17
-IPP_TAG_INTEGER = 0x21
-IPP_TAG_BOOLEAN = 0x22
-IPP_TAG_ENUM = 0x23
-IPP_TAG_STRING = 0x30
-IPP_TAG_DATE = 0x31
-IPP_TAG_RESOLUTION = 0x32
-IPP_TAG_RANGE = 0x33
-IPP_TAG_BEGIN_COLLECTION = 0x34
-IPP_TAG_TEXTLANG = 0x35
-IPP_TAG_NAMELANG = 0x36
-IPP_TAG_END_COLLECTION = 0x37
-IPP_TAG_TEXT = 0x41
-IPP_TAG_NAME = 0x42
-IPP_TAG_KEYWORD = 0x44
-IPP_TAG_URI = 0x45
-IPP_TAG_URISCHEME = 0x46
-IPP_TAG_CHARSET = 0x47
-IPP_TAG_LANGUAGE = 0x48
-IPP_TAG_MIMETYPE = 0x49
-IPP_TAG_MEMBERNAME = 0x4a
-IPP_TAG_MASK = 0x7fffffff
-IPP_TAG_COPY = -0x7fffffff-1
-
-IPP_RES_PER_INCH = 3
-IPP_RES_PER_CM = 4
-
-IPP_FINISHINGS_NONE = 3
-IPP_FINISHINGS_STAPLE = 4
-IPP_FINISHINGS_PUNCH = 5
-IPP_FINISHINGS_COVER = 6
-IPP_FINISHINGS_BIND = 7
-IPP_FINISHINGS_SADDLE_STITCH = 8
-IPP_FINISHINGS_EDGE_STITCH = 9
-IPP_FINISHINGS_FOLD = 10
-IPP_FINISHINGS_TRIM = 11
-IPP_FINISHINGS_BALE = 12
-IPP_FINISHINGS_BOOKLET_MAKER = 13
-IPP_FINISHINGS_JOB_OFFSET = 14
-IPP_FINISHINGS_STAPLE_TOP_LEFT = 20
-IPP_FINISHINGS_STAPLE_BOTTOM_LEFT = 21
-IPP_FINISHINGS_STAPLE_TOP_RIGHT = 22
-IPP_FINISHINGS_STAPLE_BOTTOM_RIGHT = 23
-IPP_FINISHINGS_EDGE_STITCH_LEFT = 24
-IPP_FINISHINGS_EDGE_STITCH_TOP = 25
-IPP_FINISHINGS_EDGE_STITCH_RIGHT = 26
-IPP_FINISHINGS_EDGE_STITCH_BOTTOM = 27
-IPP_FINISHINGS_STAPLE_DUAL_LEFT = 28
-IPP_FINISHINGS_STAPLE_DUAL_TOP = 29
-IPP_FINISHINGS_STAPLE_DUAL_RIGHT = 30
-IPP_FINISHINGS_STAPLE_DUAL_BOTTOM = 31
-IPP_FINISHINGS_BIND_LEFT = 50
-IPP_FINISHINGS_BIND_TOP = 51
-IPP_FINISHINGS_BIND_RIGHT = 52
-IPP_FINISHINGS_BIND_BOTTO = 53
-
-IPP_PORTRAIT = 3
-IPP_LANDSCAPE = 4
-IPP_REVERSE_LANDSCAPE = 5
-IPP_REVERSE_PORTRAIT = 6
-
-IPP_QUALITY_DRAFT = 3
-IPP_QUALITY_NORMAL = 4
-IPP_QUALITY_HIGH = 5
-
-IPP_JOB_PENDING = 3
-IPP_JOB_HELD = 4
-IPP_JOB_PROCESSING = 5
-IPP_JOB_STOPPED = 6
-IPP_JOB_CANCELLED = 7
-IPP_JOB_ABORTED = 8
-IPP_JOB_COMPLETE = 9
-
-IPP_PRINTER_IDLE = 3
-IPP_PRINTER_PROCESSING = 4
-IPP_PRINTER_STOPPED = 5
-
-IPP_ERROR = -1
-IPP_IDLE = 0
-IPP_HEADER = 1
-IPP_ATTRIBUTE = 2
-IPP_DATA = 3
-
-IPP_PRINT_JOB = 0x0002
-IPP_PRINT_URI = 0x0003
-IPP_VALIDATE_JOB = 0x0004
-IPP_CREATE_JOB = 0x0005
-IPP_SEND_DOCUMENT = 0x0006
-IPP_SEND_URI = 0x0007
-IPP_CANCEL_JOB = 0x0008
-IPP_GET_JOB_ATTRIBUTES = 0x0009
-IPP_GET_JOBS = 0x000a
-IPP_GET_PRINTER_ATTRIBUTES = 0x000b
-IPP_HOLD_JOB = 0x000c
-IPP_RELEASE_JOB = 0x000d
-IPP_RESTART_JOB = 0x000e
-IPP_PAUSE_PRINTER = 0x0010
-IPP_RESUME_PRINTER = 0x0011
-IPP_PURGE_JOBS = 0x0012
-IPP_SET_PRINTER_ATTRIBUTES = 0x0013
-IPP_SET_JOB_ATTRIBUTES = 0x0014
-IPP_GET_PRINTER_SUPPORTED_VALUES = 0x0015
-IPP_CREATE_PRINTER_SUBSCRIPTION = 0x0016
-IPP_CREATE_JOB_SUBSCRIPTION = 0x0017
-IPP_GET_SUBSCRIPTION_ATTRIBUTES = 0x0018
-IPP_GET_SUBSCRIPTIONS = 0x0019
-IPP_RENEW_SUBSCRIPTION = 0x001a
-IPP_CANCEL_SUBSCRIPTION = 0x001b
-IPP_GET_NOTIFICATIONS = 0x001c
-IPP_SEND_NOTIFICATIONS = 0x001d
-IPP_GET_PRINT_SUPPORT_FILES = 0x0021
-IPP_ENABLE_PRINTER = 0x0022
-IPP_DISABLE_PRINTER = 0x0023
-IPP_PAUSE_PRINTER_AFTER_CURRENT_JOB = 0x0024
-IPP_HOLD_NEW_JOBS = 0x0025
-IPP_RELEASE_HELD_NEW_JOBS = 0x0026
-IPP_DEACTIVATE_PRINTER = 0x0027
-IPP_ACTIVATE_PRINTER = 0x0028
-IPP_RESTART_PRINTER = 0x0029
-IPP_SHUTDOWN_PRINTER = 0x002a
-IPP_STARTUP_PRINTER = 0x002b
-IPP_REPROCESS_JOB = 0x002c
-IPP_CANCEL_CURRENT_JOB = 0x002d
-IPP_SUSPEND_CURRENT_JOB = 0x002e
-IPP_RESUME_JOB = 0x002f
-IPP_PROMOTE_JOB = 0x0030
-IPP_SCHEDULE_JOB_AFTER = 0x0031
-IPP_PRIVATE = 0x4000
-CUPS_GET_DEFAULT = 0x4001
-CUPS_GET_PRINTERS = 0x4002
-CUPS_ADD_PRINTER = 0x4003
-CUPS_DELETE_PRINTER = 0x4004
-CUPS_GET_CLASSES = 0x4005
-CUPS_ADD_CLASS = 0x4006
-CUPS_DELETE_CLASS = 0x4007
-CUPS_ACCEPT_JOBS = 0x4008
-CUPS_REJECT_JOBS = 0x4009
-CUPS_SET_DEFAULT = 0x400a
-CUPS_GET_DEVICES = 0x400b
-CUPS_GET_PPDS = 0x400c
-CUPS_MOVE_JOB = 0x400d
-CUPS_AUTHENTICATE_JOB = 0x400e
-
-IPP_OK = 0x0000
-IPP_OK_SUBST = 0x0001
-IPP_OK_CONFLICT = 0x0002
-IPP_OK_IGNORED_SUBSCRIPTIONS = 0x0003
-IPP_OK_IGNORED_NOTIFICATIONS = 0x0004
-IPP_OK_TOO_MANY_EVENTS = 0x0005
-IPP_OK_BUT_CANCEL_SUBSCRIPTION = 0x0006
-IPP_REDIRECTION_OTHER_SITE = 0x0300
-IPP_BAD_REQUEST = 0x0400
-IPP_FORBIDDEN = 0x0401
-IPP_NOT_AUTHENTICATED = 0x0402
-IPP_NOT_AUTHORIZED = 0x0403
-IPP_NOT_POSSIBLE = 0x0404
-IPP_TIMEOUT = 0x0405
-IPP_NOT_FOUND = 0x0406
-IPP_GONE = 0x0407
-IPP_REQUEST_ENTITY = 0x0408
-IPP_REQUEST_VALUE = 0x0409
-IPP_DOCUMENT_FORMAT = 0x040a
-IPP_ATTRIBUTES = 0x040b
-IPP_URI_SCHEME = 0x040c
-IPP_CHARSET = 0x040d
-IPP_CONFLICT = 0x040e
-IPP_COMPRESSION_NOT_SUPPORTED = 0x040f
-IPP_COMPRESSION_ERROR = 0x0410
-IPP_DOCUMENT_FORMAT_ERROR = 0x0411
-IPP_DOCUMENT_ACCESS_ERROR = 0x0412
-IPP_ATTRIBUTES_NOT_SETTABLE = 0x0413
-IPP_IGNORED_ALL_SUBSCRIPTIONS = 0x0414
-IPP_TOO_MANY_SUBSCRIPTIONS = 0x0415
-IPP_IGNORED_ALL_NOTIFICATIONS = 0x0416
-IPP_PRINT_SUPPORT_FILE_NOT_FOUND = 0x0417
-
-IPP_INTERNAL_ERROR = 0x0500
-IPP_OPERATION_NOT_SUPPORTED = 0x0501
-IPP_SERVICE_UNAVAILABLE = 0x0502
-IPP_VERSION_NOT_SUPPORTED = 0x0503
-IPP_DEVICE_ERROR = 0x0504
-IPP_TEMPORARY_ERROR = 0x0505
-IPP_NOT_ACCEPTING = 0x0506
-IPP_PRINTER_BUSY = 0x0507
-IPP_ERROR_JOB_CANCELLED = 0x0508
-IPP_MULTIPLE_JOBS_NOT_SUPPORTED = 0x0509
-IPP_PRINTER_IS_DEACTIVATED = 0x50a
-  
-CUPS_PRINTER_LOCAL = 0x0000
-CUPS_PRINTER_CLASS = 0x0001
-CUPS_PRINTER_REMOTE = 0x0002
-CUPS_PRINTER_BW = 0x0004
-CUPS_PRINTER_COLOR = 0x0008
-CUPS_PRINTER_DUPLEX = 0x0010
-CUPS_PRINTER_STAPLE = 0x0020
-CUPS_PRINTER_COPIES = 0x0040
-CUPS_PRINTER_COLLATE = 0x0080
-CUPS_PRINTER_PUNCH = 0x0100
-CUPS_PRINTER_COVER = 0x0200
-CUPS_PRINTER_BIND = 0x0400
-CUPS_PRINTER_SORT = 0x0800
-CUPS_PRINTER_SMALL = 0x1000
-CUPS_PRINTER_MEDIUM = 0x2000
-CUPS_PRINTER_LARGE = 0x4000
-CUPS_PRINTER_VARIABLE = 0x8000
-CUPS_PRINTER_IMPLICIT = 0x10000
-CUPS_PRINTER_DEFAULT = 0x20000
-CUPS_PRINTER_FAX = 0x40000
-CUPS_PRINTER_REJECTING = 0x80000
-CUPS_PRINTER_DELETE = 0x100000
-CUPS_PRINTER_NOT_SHARED = 0x200000
-CUPS_PRINTER_AUTHENTICATED = 0x400000
-CUPS_PRINTER_COMMANDS = 0x800000
-CUPS_PRINTER_OPTIONS = 0xe6ff
-  
-  
-class IPPError(Exception) :
-    """An exception for IPP related stuff."""
-    def __init__(self, message = ""):
-        self.message = message
-        Exception.__init__(self, message)
-    def __repr__(self):
-        return self.message
-    __str__ = __repr__
-
-class FakeAttribute :
-    """Fakes an IPPRequest attribute to simplify usage syntax."""
-    def __init__(self, request, name) :
-        """Initializes the fake attribute."""
-        self.request = request
-        self.name = name
-        
-    def __setitem__(self, key, value) :
-        """Appends the value to the real attribute."""
-        attributeslist = getattr(self.request, "_%s_attributes" % self.name)
-        for i in range(len(attributeslist)) :
-            attribute = attributeslist[i]
-            for j in range(len(attribute)) :
-                (attrname, attrvalue) = attribute[j]
-                if attrname == key :
-                    attribute[j][1].append(value)
-                    return
-            attribute.append((key, [value]))
-            
-    def __getitem__(self, key) :
-        """Returns an attribute's value."""
-        answer = []
-        attributeslist = getattr(self.request, "_%s_attributes" % self.name)
-        for i in range(len(attributeslist)) :
-            attribute = attributeslist[i]
-            for j in range(len(attribute)) :
-                (attrname, attrvalue) = attribute[j]
-                if attrname == key :
-                    answer.extend(attrvalue)
-        if answer :
-            return answer
-        raise KeyError, key
-    
-class IPPRequest :
-    """A class for IPP requests."""
-    attributes_types = ("operation", "job", "printer", "unsupported", \
-                                     "subscription", "event_notification")
-    def __init__(self, data="", version=IPP_VERSION,
-                                operation_id=None, \
-                                request_id=None, \
-                                debug=False) :
-        """Initializes an IPP Message object.
-        
-           Parameters :
-           
-             data : the complete IPP Message's content.
-             debug : a boolean value to output debug info on stderr.
-        """
-        self.debug = debug
-        self._data = data
-        self.parsed = False
-        
-        # Initializes message
-        self.setVersion(version)
-        self.setOperationId(operation_id)
-        self.setRequestId(request_id)
-        self.data = ""
-        
-        for attrtype in self.attributes_types :
-            setattr(self, "_%s_attributes" % attrtype, [[]])
-        
-        # Initialize tags    
-        self.tags = [ None ] * 256 # by default all tags reserved
-        
-        # Delimiter tags
-        self.tags[0x01] = "operation-attributes-tag"
-        self.tags[0x02] = "job-attributes-tag"
-        self.tags[0x03] = "end-of-attributes-tag"
-        self.tags[0x04] = "printer-attributes-tag"
-        self.tags[0x05] = "unsupported-attributes-tag"
-        self.tags[0x06] = "subscription-attributes-tag"
-        self.tags[0x07] = "event_notification-attributes-tag"
-        
-        # out of band values
-        self.tags[0x10] = "unsupported"
-        self.tags[0x11] = "reserved-for-future-default"
-        self.tags[0x12] = "unknown"
-        self.tags[0x13] = "no-value"
-        self.tags[0x15] = "not-settable"
-        self.tags[0x16] = "delete-attribute"
-        self.tags[0x17] = "admin-define"
-  
-        # integer values
-        self.tags[0x20] = "generic-integer"
-        self.tags[0x21] = "integer"
-        self.tags[0x22] = "boolean"
-        self.tags[0x23] = "enum"
-        
-        # octetString
-        self.tags[0x30] = "octetString-with-an-unspecified-format"
-        self.tags[0x31] = "dateTime"
-        self.tags[0x32] = "resolution"
-        self.tags[0x33] = "rangeOfInteger"
-        self.tags[0x34] = "begCollection"
-        self.tags[0x35] = "textWithLanguage"
-        self.tags[0x36] = "nameWithLanguage"
-        self.tags[0x37] = "endCollection"
-        
-        # character strings
-        self.tags[0x40] = "generic-character-string"
-        self.tags[0x41] = "textWithoutLanguage"
-        self.tags[0x42] = "nameWithoutLanguage"
-        self.tags[0x44] = "keyword"
-        self.tags[0x45] = "uri"
-        self.tags[0x46] = "uriScheme"
-        self.tags[0x47] = "charset"
-        self.tags[0x48] = "naturalLanguage"
-        self.tags[0x49] = "mimeMediaType"
-        self.tags[0x4a] = "memberAttrName"
-        
-        # Reverse mapping to generate IPP messages
-        self.tagvalues = {}
-        for i in range(len(self.tags)) :
-            value = self.tags[i]
-            if value is not None :
-                self.tagvalues[value] = i
-                                     
-    def __getattr__(self, name) :
-        """Fakes attribute access."""
-        if name in self.attributes_types :
-            return FakeAttribute(self, name)
-        else :
-            raise AttributeError, name
-            
-    def __str__(self) :
-        """Returns the parsed IPP message in a readable form."""
-        if not self.parsed :
-            return ""
-        mybuffer = []
-        mybuffer.append("IPP version : %s.%s" % self.version)
-        mybuffer.append("IPP operation Id : 0x%04x" % self.operation_id)
-        mybuffer.append("IPP request Id : 0x%08x" % self.request_id)
-        for attrtype in self.attributes_types :
-            for attribute in getattr(self, "_%s_attributes" % attrtype) :
-                if attribute :
-                    mybuffer.append("%s attributes :" % attrtype.title())
-                for (name, value) in attribute :
-                    mybuffer.append("  %s : %s" % (name, value))
-        # if self.data :
-        #     mybuffer.append("IPP datas : %s" % repr(self.data))
-        return "\n".join(mybuffer)
-        
-    def logDebug(self, msg) :
-        """Prints a debug message."""
-        if self.debug :
-            sys.stderr.write("%s\n" % msg)
-            sys.stderr.flush()
-            
-    def setVersion(self, version) :
-        """Sets the request's operation id."""
-        if version is not None :
-            try :
-                self.version = [int(p) for p in version.split(".")]
-            except AttributeError :
-                if len(version) == 2 : # 2-tuple
-                    self.version = version
-                else :
-                    try :
-                        self.version = [int(p) for p in str(float(version)).split(".")]
-                    except :
-                        self.version = [int(p) for p in IPP_VERSION.split(".")]
-        
-    def setOperationId(self, opid) :
-        """Sets the request's operation id."""
-        self.operation_id = opid
-        
-    def setRequestId(self, reqid) :
-        """Sets the request's request id."""
-        self.request_id = reqid
-        
-    def dump(self) :
-        """Generates an IPP Message.
-        
-           Returns the message as a string of text.
-        """    
-        mybuffer = []
-        if None not in (self.version, self.operation_id) :
-            mybuffer.append(chr(self.version[0]) + chr(self.version[1]))
-            mybuffer.append(pack(">H", self.operation_id))
-            mybuffer.append(pack(">I", self.request_id or 1))
-            for attrtype in self.attributes_types :
-                for attribute in getattr(self, "_%s_attributes" % attrtype) :
-                    if attribute :
-                        mybuffer.append(chr(self.tagvalues["%s-attributes-tag" % attrtype]))
-                    for (attrname, value) in attribute :
-                        nameprinted = 0
-                        for (vtype, val) in value :
-                            mybuffer.append(chr(self.tagvalues[vtype]))
-                            if not nameprinted :
-                                mybuffer.append(pack(">H", len(attrname)))
-                                mybuffer.append(attrname)
-                                nameprinted = 1
-                            else :
-                                mybuffer.append(pack(">H", 0))
-                            if vtype in ("integer", "enum") :
-                                mybuffer.append(pack(">H", 4))
-                                mybuffer.append(pack(">I", val))
-                            elif vtype == "boolean" :
-                                mybuffer.append(pack(">H", 1))
-                                mybuffer.append(chr(val))
-                            else :
-                                mybuffer.append(pack(">H", len(val)))
-                                mybuffer.append(val)
-            mybuffer.append(chr(self.tagvalues["end-of-attributes-tag"]))
-        mybuffer.append(self.data)
-        return "".join(mybuffer)
-
-    def parse(self) :
-        """Parses an IPP Request.
-        
-           NB : Only a subset of RFC2910 is implemented.
-        """
-        self._curname = None
-        self._curattributes = None
-        
-        self.setVersion((ord(self._data[0]), ord(self._data[1])))
-        self.setOperationId(unpack(">H", self._data[2:4])[0])
-        self.setRequestId(unpack(">I", self._data[4:8])[0])
-        self.position = 8
-        endofattributes = self.tagvalues["end-of-attributes-tag"]
-        maxdelimiter = self.tagvalues["event_notification-attributes-tag"]
-        nulloffset = lambda : 0
-        #try :
-        if 1:
-            tag = ord(self._data[self.position])
-            while tag != endofattributes :
-                self.position += 1
-                name = self.tags[tag]
-                if name is not None :
-                    func = getattr(self, name.replace("-", "_"), nulloffset)
-                    self.position += func()
-                    if ord(self._data[self.position]) > maxdelimiter :
-                        self.position -= 1
-                        continue
-                oldtag = tag
-                tag = ord(self._data[self.position])
-                if tag == oldtag :
-                    self._curattributes.append([])
-        #except IndexError :
-        #    raise IPPError, "Unexpected end of IPP message."
-            
-        self.data = self._data[self.position+1:]
-        self.parsed = True
-        
-    def parseTag(self) :
-        """Extracts information from an IPP tag."""
-        pos = self.position
-        tagtype = self.tags[ord(self._data[pos])]
-        if tagtype == 'end-of-attributes-tag':
-            return 0
-        pos += 1
-        posend = pos2 = pos + 2
-        namelength = unpack(">H", self._data[pos:pos2])[0]
-        if not namelength :
-            name = self._curname
-        else :
-            posend += namelength
-            self._curname = name = self._data[pos2:posend]
-        pos2 = posend + 2
-        valuelength = unpack(">H", self._data[posend:pos2])[0]
-        posend = pos2 + valuelength
-        value = self._data[pos2:posend]
-        if tagtype in ("integer", "enum") :
-            value = unpack(">I", value)[0]
-        elif tagtype == "boolean" :
-            value = ord(value)
-        try :
-            (oldname, oldval) = self._curattributes[-1][-1]
-            if oldname == name :
-                oldval.append((tagtype, value))
-            else :
-                raise IndexError
-        except IndexError :
-            self._curattributes[-1].append((name, [(tagtype, value)]))
-        self.logDebug("%s(%s) : %s" % (name, tagtype, value))
-        return posend - self.position
-        
-    def operation_attributes_tag(self) :
-        """Indicates that the parser enters into an operation-attributes-tag group."""
-        self._curattributes = self._operation_attributes
-        return self.parseTag()
-        
-    def job_attributes_tag(self) :
-        """Indicates that the parser enters into a job-attributes-tag group."""
-        self._curattributes = self._job_attributes
-        return self.parseTag()
-        
-    def printer_attributes_tag(self) :
-        """Indicates that the parser enters into a printer-attributes-tag group."""
-        self._curattributes = self._printer_attributes
-        return self.parseTag()
-        
-    def unsupported_attributes_tag(self) :
-        """Indicates that the parser enters into an unsupported-attributes-tag group."""
-        self._curattributes = self._unsupported_attributes
-        return self.parseTag()
-        
-    def subscription_attributes_tag(self) :
-        """Indicates that the parser enters into a subscription-attributes-tag group."""
-        self._curattributes = self._subscription_attributes
-        return self.parseTag()
-        
-    def event_notification_attributes_tag(self) :
-        """Indicates that the parser enters into an event-notification-attributes-tag group."""
-        self._curattributes = self._event_notification_attributes
-        return self.parseTag()
-
-if __name__ == "__main__" :
-    if (len(sys.argv) < 2) or (sys.argv[1] == "--debug") :
-        print "usage : python pkipplib.py /var/spool/cups/c00005 [--debug] (for example)\n"
-    else :
-        infile = open(sys.argv[1], "rb")
-        filedata = infile.read()
-        infile.close()
-        
-        msg = IPPRequest(filedata, debug=(sys.argv[-1]=="--debug"))
-        msg.parse()
-        msg2 = IPPRequest(msg.dump())
-        msg2.parse()
-        filedata2 = msg2.dump()
-        
-        if filedata == filedata2 :
-            print "Test OK : parsing original and parsing the output of the dump produce the same dump !"
-            print str(msg)
-        else :
-            print "Test Failed !"
-            print str(msg)
-            print
-            print str(msg2)
Index: rver/lib/quickprint-ipp.py
===================================================================
--- server/lib/quickprint-ipp.py	(revision 7a1c039c27cd8beefe98c73143f72e3cbaa8b79e)
+++ 	(revision )
@@ -1,168 +1,0 @@
-#!/usr/bin/env python
-
-# Adapted from the Quickprint IPP server code (http://quikprint.mit.edu)
-# Modifications and additions written by Jessica Hamrick (jhamrick@mit.edu)
-
-# Notes and Todo:
-#   - make sure package creates gutenbach folder in /var/log
-
-import os, sys
-import cgi, cgitb
-import logging
-import MySQLdb
-import ipplib
-
-from ipprequest import IPPRequest
-from tempfile import mkstemp
-from shutil import move
-from logging import debug, info, warning, error, critical
-
-# set up logging
-LOGFILE = "/var/log/gutenbach/ipp.log"
-logging.basicConfig(filename=LOGFILE, level=logging.DEBUG)
-cgitb.enable(logdir='/var/log/gutenbach/cgi.log')
-
-# make sure a temporary folder exists
-TEMPDIR = '/tmp/gutenbach/ipp'
-try:
-    if not os.path.exists(TEMPDIR):
-        info("Creating temporay directory '%s'" % TEMPDIR)
-        os.makedirs(TEMPDIR)
-except e, Exception:
-    error("Could not create temporary directory '%s'" % TEMPDIR)
-
-# print the content type for our request
-print "Content-type: application/ipp\n"
-
-class IPPServer(object):
-    
-    # nothing to do in the init
-    def __init__(self):
-        """
-        This function doesn't actually do anything.
-        """
-        pass
-
-    # this function processes an IPP request and sends a response
-    def process(self, request_in, response_out):
-        """
-        Processes an IPP request and sends a response.
-
-        Arguments:
-
-            request_in -- a file handle to read in the request
-
-            request_out -- a file handle to print the response
-        """
-        
-        # parse the request from request_in
-        request = IPPRequest(request=request_in)
-
-        # create the response, copying the version, operation-id, and
-        # request-id from the request
-        response = IPPRequest(version=request.version,
-                              operation_id=request.operation_id,
-                              request_id=request.request_id)
-        
-        handler = getattr(self, "_operation_%d" % request.operation_id, None)
-
-        response._operation_attributes = [[]]
-        response._operation_attributes[0] = filter( \
-            lambda x: x[0] in ('attributes-charset', 'attributes-natural-language', 'printer-uri'),
-            request._operation_attributes[0])
-
-        # f = file('/tmp/gutenbach/ipp/printer2.log','a')
-        # f.write("\n" + "*"*80 + "\n")
-        # f.write(str(request))
-        if handler is not None:
-            response.setOperationId(handler(request, response))
-            data_out = response.dump()
-            response_out.write(data_out)
-            response_test = IPPRequest(data=data_out)
-            response_test.parse()
-        #     f.write("\n" + "-"*80 + "\n")
-        #     f.write(str(response_test))
-        # f.write("\n" + "*"*80 + "\n")
-        # f.close()
-
-    def _operation_2(self, request, response):
-        """print-job response"""
-        (fno, fname) = mkstemp(dir='/tmp/gutenbach/ipp')
-        os.write(fno, request.data)
-        os.close(fno)
-        opattr = filter(lambda x: x[0] in ('job-name'),
-            request._operation_attributes[0])
-        jname = 'unknown'
-        if len(opattr) and opattr[0][0] == 'job-name':
-            jname = opattr[0][1][0][1]
-        jstat = os.stat(fname)
-        jsize = jstat.st_size
-        c = db.cursor()
-        c.execute("INSERT INTO job (juser, jname, jfile, jsize, jtype) VALUES (%s, %s, %s, %s, %s)", \
-                (AUTH, jname, fname, jsize, 'PostScript',))
-        jid = db.insert_id()
-        jfile = '/mit/gutenbach/jobs/' + AUTH + '_' + str(jid)
-        move(fname, jfile)
-        c.execute("UPDATE job SET jfile=%s, dupdated=NOW() WHERE jid=%s", \
-                (jfile, str(jid),))
-        response._job_attributes = [[ \
-            ('job-id', [('integer', jid)]), \
-            ('printer-uri', [('uri', printer_uri)]), \
-            ('job-state', [('enum', ipplib.IPP_JOB_HELD)])]]
-        return ipplib.IPP_OK
-
-    def _operation_8(self, request, response):
-        """delete-job response"""
-        opattr = filter(lambda x: x[0] in ('job-id'),
-            request._operation_attributes[0])
-        if len(opattr) and opattr[0][0] == 'job-id':
-            jid = opattr[0][1][0][1]
-            c = db.cursor()
-            c.execute("UPDATE job SET jstate = 'DEL' WHERE juser = %s AND jid = %s", \
-                (AUTH, int(jid)))
-        return ipplib.IPP_OK
-
-    def _operation_9(self, request, response):
-        """get-job-properties response"""
-        opattr = filter(lambda x: x[0] in ('job-id'),
-            request._operation_attributes[0])
-        if len(opattr) and opattr[0][0] == 'job-id':
-            jid = opattr[0][1][0][1]
-        response._job_attributes.append([ \
-            ('job-id', [('integer', jid)]), \
-        #    ('job-name', [('nameWithoutLanguage', x[1])]), \
-            ('job-originating-user-name', [('nameWithoutLanguage', AUTH)]), \
-        #    ('job-k-octets', [('integer', x[2]/1024)]), \
-            ('job-state', [('enum', ipplib.IPP_JOB_COMPLETE)])
-        ])
-        return ipplib.IPP_OK
-
-    def _operation_10(self, request, response):
-        """get-jobs response"""
-        c = db.cursor()
-        c.execute("SELECT jid, jname, jsize, jstate FROM job WHERE juser = %s AND jstate != %s ORDER BY dadded", \
-            (AUTH, 'DEL',))
-        response._job_attributes = []
-        for x in c.fetchall():
-            if x[3] == 'NEW':
-                state = ipplib.IPP_JOB_HELD
-            elif x[3] == 'DONE':
-                state = ipplib.IPP_JOB_COMPLETE
-            else:
-                state = 0
-            response._job_attributes.append([ \
-                ('job-id', [('integer', x[0])]), \
-                ('job-name', [('nameWithoutLanguage', x[1])]), \
-                ('job-originating-user-name', [('nameWithoutLanguage', AUTH)]), \
-                ('job-k-octets', [('integer', x[2]/1024)]), \
-                ('job-state', [('enum', state)])
-            ])
-        return ipplib.IPP_OK
-
-    def _operation_11(self, request, response):
-        """get-printer-attributes response"""
-        response._printer_attributes = \
-            [[('printer-name', [('nameWithoutLanguage', 'Gutenbach')])]]
-        return ipplib.IPP_OK
-
-IPPServer().process(sys.stdin,sys.stdout)
