Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVamsi Krishna Davuluri <iwikiwi@localhost.localdomain>2009-08-10 09:15:19 (GMT)
committer Vamsi Krishna Davuluri <iwikiwi@localhost.localdomain>2009-08-10 09:15:19 (GMT)
commitcc6ebd36e0068bbefa0102fe0e51133dcf1b8b42 (patch)
tree016b4e91b3c27eb9103473e9389125343df9ceff
parent1d5d2e992192d79d6e90dd13da4a566bc9cc66ef (diff)
Added aa's spinbutton suggestion. added Moodle Print Module as sub directory.
-rwxr-xr-x[-rw-r--r--].gitignore0
-rwxr-xr-x[-rw-r--r--].goutputstream-JNP5VU0
-rwxr-xr-x[-rw-r--r--].goutputstream-ST50VU0
-rwxr-xr-x[-rw-r--r--]AUTHORS0
-rwxr-xr-x[-rw-r--r--]COPYING0
-rwxr-xr-xMoodle/mod/print/BasicIPP.php1832
-rwxr-xr-xMoodle/mod/print/CupsPrintIPP.php671
-rwxr-xr-xMoodle/mod/print/ExtendedPrintIPP.php1441
-rwxr-xr-xMoodle/mod/print/PrintIPP.php1875
-rwxr-xr-xMoodle/mod/print/README.txt75
-rwxr-xr-xMoodle/mod/print/db/access.php71
-rwxr-xr-xMoodle/mod/print/db/install.xml58
-rwxr-xr-xMoodle/mod/print/db/upgrade.php134
-rwxr-xr-xMoodle/mod/print/delete.php41
-rwxr-xr-xMoodle/mod/print/http_class.php629
-rwxr-xr-xMoodle/mod/print/icon.gifbin0 -> 128 bytes
-rwxr-xr-xMoodle/mod/print/index.php89
-rwxr-xr-xMoodle/mod/print/lang/en_utf8/help/newmodule/index.html6
-rwxr-xr-xMoodle/mod/print/lang/en_utf8/help/newmodule/mods.html18
-rwxr-xr-xMoodle/mod/print/lang/en_utf8/newmodule.php12
-rwxr-xr-xMoodle/mod/print/lib.php1195
-rwxr-xr-xMoodle/mod/print/lib11.php3090
-rwxr-xr-xMoodle/mod/print/log.txt47
-rwxr-xr-xMoodle/mod/print/mod_form.php52
-rwxr-xr-xMoodle/mod/print/print_xmlrpc.php133
-rwxr-xr-xMoodle/mod/print/styles.php176
-rwxr-xr-xMoodle/mod/print/submissions.php50
-rwxr-xr-xMoodle/mod/print/test.php56
-rwxr-xr-xMoodle/mod/print/upload.php41
-rwxr-xr-xMoodle/mod/print/version.php15
-rwxr-xr-xMoodle/mod/print/view.php41
-rwxr-xr-x[-rw-r--r--]activity/activity-read.svg0
-rwxr-xr-x[-rw-r--r--]activity/activity.info0
-rwxr-xr-x[-rw-r--r--]activity/gnome-pdf.svg0
-rwxr-xr-x[-rw-r--r--]activity/ooo_printeradmin.svg0
-rw-r--r--cookiemagic.py57
-rwxr-xr-x[-rw-r--r--]cupsinfo.txt0
-rwxr-xr-x[-rw-r--r--]po/Read.pot0
-rwxr-xr-x[-rw-r--r--]po/af.po0
-rwxr-xr-x[-rw-r--r--]po/am.po0
-rwxr-xr-x[-rw-r--r--]po/ar.po0
-rwxr-xr-x[-rw-r--r--]po/ay.po0
-rwxr-xr-x[-rw-r--r--]po/bg.po0
-rwxr-xr-x[-rw-r--r--]po/bi.po0
-rwxr-xr-x[-rw-r--r--]po/bn.po0
-rwxr-xr-x[-rw-r--r--]po/bn_IN.po0
-rwxr-xr-x[-rw-r--r--]po/ca.po0
-rwxr-xr-x[-rw-r--r--]po/cpp.po0
-rwxr-xr-x[-rw-r--r--]po/cs.po0
-rwxr-xr-x[-rw-r--r--]po/de.po0
-rwxr-xr-x[-rw-r--r--]po/dz.po0
-rwxr-xr-x[-rw-r--r--]po/el.po0
-rwxr-xr-x[-rw-r--r--]po/en.po0
-rwxr-xr-x[-rw-r--r--]po/en_US.po0
-rwxr-xr-x[-rw-r--r--]po/es.po0
-rwxr-xr-x[-rw-r--r--]po/fa.po0
-rwxr-xr-x[-rw-r--r--]po/fa_AF.po0
-rwxr-xr-x[-rw-r--r--]po/ff.po0
-rwxr-xr-x[-rw-r--r--]po/fi.po0
-rwxr-xr-x[-rw-r--r--]po/fr.po0
-rwxr-xr-x[-rw-r--r--]po/gu.po0
-rwxr-xr-x[-rw-r--r--]po/ha.po0
-rwxr-xr-x[-rw-r--r--]po/he.po0
-rwxr-xr-x[-rw-r--r--]po/hi.po0
-rwxr-xr-x[-rw-r--r--]po/ht.po0
-rwxr-xr-x[-rw-r--r--]po/hu.po0
-rwxr-xr-x[-rw-r--r--]po/ig.po0
-rwxr-xr-x[-rw-r--r--]po/is.po0
-rwxr-xr-x[-rw-r--r--]po/it.po0
-rwxr-xr-x[-rw-r--r--]po/ja.po0
-rwxr-xr-x[-rw-r--r--]po/km.po0
-rwxr-xr-x[-rw-r--r--]po/ko.po0
-rwxr-xr-x[-rw-r--r--]po/mi.po0
-rwxr-xr-x[-rw-r--r--]po/mk.po0
-rwxr-xr-x[-rw-r--r--]po/ml.po0
-rwxr-xr-x[-rw-r--r--]po/mn.po0
-rwxr-xr-x[-rw-r--r--]po/mr.po0
-rwxr-xr-x[-rw-r--r--]po/ms.po0
-rwxr-xr-x[-rw-r--r--]po/mvo.po0
-rwxr-xr-x[-rw-r--r--]po/nb.po0
-rwxr-xr-x[-rw-r--r--]po/ne.po0
-rwxr-xr-x[-rw-r--r--]po/nl.po0
-rwxr-xr-x[-rw-r--r--]po/pa.po0
-rwxr-xr-x[-rw-r--r--]po/pap.po0
-rwxr-xr-x[-rw-r--r--]po/pis.po0
-rwxr-xr-x[-rw-r--r--]po/pl.po0
-rwxr-xr-x[-rw-r--r--]po/ps.po0
-rwxr-xr-x[-rw-r--r--]po/pseudo.po0
-rwxr-xr-x[-rw-r--r--]po/pt.po0
-rwxr-xr-x[-rw-r--r--]po/pt_BR.po0
-rwxr-xr-x[-rw-r--r--]po/qu.po0
-rwxr-xr-x[-rw-r--r--]po/ro.po0
-rwxr-xr-x[-rw-r--r--]po/ru.po0
-rwxr-xr-x[-rw-r--r--]po/rw.po0
-rwxr-xr-x[-rw-r--r--]po/sd.po0
-rwxr-xr-x[-rw-r--r--]po/si.po0
-rwxr-xr-x[-rw-r--r--]po/sk.po0
-rwxr-xr-x[-rw-r--r--]po/sl.po0
-rwxr-xr-x[-rw-r--r--]po/sv.po0
-rwxr-xr-x[-rw-r--r--]po/sw.po0
-rwxr-xr-x[-rw-r--r--]po/te.po0
-rwxr-xr-x[-rw-r--r--]po/th.po0
-rwxr-xr-x[-rw-r--r--]po/tpi.po0
-rwxr-xr-x[-rw-r--r--]po/tr.po0
-rwxr-xr-x[-rw-r--r--]po/ug.po0
-rwxr-xr-x[-rw-r--r--]po/ur.po0
-rwxr-xr-x[-rw-r--r--]po/vi.po0
-rwxr-xr-x[-rw-r--r--]po/wa.po0
-rwxr-xr-x[-rw-r--r--]po/yo.po0
-rwxr-xr-x[-rw-r--r--]po/zh_CN.po0
-rwxr-xr-x[-rw-r--r--]po/zh_TW.po0
-rwxr-xr-x[-rw-r--r--]printactivity.py14
-rwxr-xr-x[-rw-r--r--]printer1.py0
-rwxr-xr-x[-rw-r--r--]printerDeviceIcon.py6
-rwxr-xr-x[-rw-r--r--]printscript.py59
-rwxr-xr-xprintscriptCupsVersion.py307
-rwxr-xr-x[-rw-r--r--]printtoolbar.py139
-rwxr-xr-x[-rw-r--r--]test.pcapbin434 -> 434 bytes
-rwxr-xr-x[-rw-r--r--]xmlrpc.txt0
119 files changed, 12375 insertions, 55 deletions
diff --git a/.gitignore b/.gitignore
index 3c16e81..3c16e81 100644..100755
--- a/.gitignore
+++ b/.gitignore
diff --git a/.goutputstream-JNP5VU b/.goutputstream-JNP5VU
index e69de29..e69de29 100644..100755
--- a/.goutputstream-JNP5VU
+++ b/.goutputstream-JNP5VU
diff --git a/.goutputstream-ST50VU b/.goutputstream-ST50VU
index e69de29..e69de29 100644..100755
--- a/.goutputstream-ST50VU
+++ b/.goutputstream-ST50VU
diff --git a/AUTHORS b/AUTHORS
index fe61bd3..fe61bd3 100644..100755
--- a/AUTHORS
+++ b/AUTHORS
diff --git a/COPYING b/COPYING
index d511905..d511905 100644..100755
--- a/COPYING
+++ b/COPYING
diff --git a/Moodle/mod/print/BasicIPP.php b/Moodle/mod/print/BasicIPP.php
new file mode 100755
index 0000000..6537fd2
--- /dev/null
+++ b/Moodle/mod/print/BasicIPP.php
@@ -0,0 +1,1832 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
+ /* @(#) $Header: /sources/phpprintipp/phpprintipp/php_classes/BasicIPP.php,v 1.1 2008/06/21 00:30:56 harding Exp $
+ *
+ * Class BasicIPP - Send Basic IPP requests, Get and parses IPP Responses.
+ *
+ * Copyright (C) 2005-2006 Thomas HARDING
+ * Parts Copyright (C) 2005-2006 Manuel Lemos
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * mailto:thomas.harding@laposte.net
+ * Thomas Harding, 56 rue de la bourie rouge, 45 000 ORLEANS -- FRANCE
+ *
+ */
+
+/*
+
+ This class is intended to implement Internet Printing Protocol on client side.
+
+ References needed to debug / add functionnalities:
+ - RFC 2910
+ - RFC 2911
+ - RFC 3380
+ - RFC 3382
+*/
+/*
+ TODO: beta tests on other servers than Cups
+*/
+
+
+ // {{{ required and included files
+
+ require_once("http_class.php");
+
+ // If you want http backend from http://www.phpclasses.org/browse/package/3.html
+ /*
+ require_once("HTTP/http.php");
+ include_once("SASL/sasl.php");
+ include_once("SASL/basic_sasl_client.php");
+ include_once("SASL/digest_sasl_client.php");
+ include_once("SASL/ntlm_sasl_client.php");
+ */
+ // }}}
+
+
+/***********************
+*
+* ippException class
+*
+************************/
+
+ // {{{ class ippException
+class ippException extends Exception {
+
+ protected $errno;
+
+ public function __construct($msg,$errno=null) {
+ parent :: __construct($msg);
+ $this->errno = $errno;
+ }
+
+ public function getErrorFormatted() {
+
+ $return = sprintf("[ipp]: %s -- "._(" file %s, line %s"),
+ $this->getMessage(),
+ $this->getFile(),
+ $this->getLine());
+
+ return $return;
+ }
+
+ public function getErrno() {
+
+ return $this->errno ;
+ }
+
+}
+ // }}}
+
+
+
+class BasicIPP {
+
+ // {{{ variables declaration
+ // setup variables
+ public $paths = array("root" => "/",
+ "admin" => "/admin/",
+ "printers" => "/printers/",
+ "jobs" => "/jobs/");
+ public $http_timeout = 0; // timeout at http connection (seconds) 0 => default => 30.
+ public $http_data_timeout = 0; // data reading timeout (milliseconds) 0 => default => 30.
+ public $ssl = false;
+ public $debug_level = 3; // max 3: almost silent
+ public $alert_on_end_tag;// debugging purpose: echo "END tag OK" if (1 and reads while end tag)
+ public $with_exceptions = 0; // compatibility mode for old scripts
+ public $handle_http_exceptions = 1;
+ // readables variables
+ public $jobs = array();
+ public $jobs_uri = array();
+ public $status = array();
+ public $response_completed = array();
+ public $last_job = "";
+ public $attributes; // object you can read: attributes after validateJob()
+ public $printer_attributes; // object you can read: printer's attributes after getPrinterAttributes()
+ public $job_attributes; // object you can read: last job attributes
+ public $jobs_attributes; // object you can read: jobs attributes after getJobs()
+ public $available_printers = array();
+ public $printers_uri = array();
+ public $debug = array();
+ public $response;
+
+ // {{{ protected variables;
+
+ protected $log_level = 2; // max 3: very verbose
+ protected $log_type = 3; // 3: file | 1: e-mail | 0: logger
+ protected $log_destination; // e-mail or file
+ protected $serveroutput;
+ protected $setup;
+ protected $stringjob;
+ protected $data;
+ protected $debug_count = 0;
+ protected $username;
+ protected $charset;
+ protected $password;
+ protected $requesring_user;
+ protected $client_hostname = "localhost";
+ protected $stream;
+ protected $host = "localhost";
+ protected $port = "631";
+ protected $printer_uri;
+ protected $timeout = "20"; //20 secs
+ protected $errNo;
+ protected $errStr;
+ protected $datatype;
+ protected $datahead;
+ protected $datatail;
+ public $meta;
+ protected $operation_id;
+ protected $delay;
+ protected $error_generation; //devel feature
+ protected $debug_http = 0;
+ protected $no_disconnect;
+ protected $job_tags;
+ protected $operation_tags;
+ protected $index;
+ protected $collection ; //RFC3382
+ protected $collection_index; //RFC3382
+ protected $collection_key = array(); //RFC3382
+ protected $collection_depth = -1; //RFC3382
+ protected $end_collection = false; //RFC3382
+ protected $collection_nbr = array(); //RFC3382
+ protected $unix = false; // true -> use unix sockets instead of http
+ // }}}
+ // }}}
+
+ // {{{ constructor
+ public function __construct() {
+ $tz = getenv("date.timezone");
+ if (!$tz)
+ $tz = date_default_timezone_get();
+ date_default_timezone_set($tz);
+
+ $this->meta = new stdClass();
+ $this->setup = new stdClass();
+ $this->values = new stdClass();
+ $this->serveroutput = new stdClass();
+ $this->error_generation = new stdClass();
+ $this->_parsing = new stdClass();
+
+ self::_initTags ();
+ }
+ // }}}
+
+/*****************
+*
+* PUBLIC FUNCTIONS
+*
+*******************/
+
+
+// SETUP
+
+ // {{{ setPort($port='631')
+ public function setPort($port='631'){
+ $this->port = $port;
+ self::_putDebug("Port is ".$this->port,2);
+ }
+ // }}}
+
+ // {{{ setUnix($socket='/var/run/cups/cups.sock')
+ public function setUnix($socket='/var/run/cups/cups.sock') {
+ $this->host = $socket;
+ $this->unix = true;
+ self::_putDebug("Host is ".$this->host,2);
+ }
+ // }}}
+
+ // {{{ setHost($host='localhost')
+ public function setHost($host='localhost'){
+ $this->host = $host;
+ $this->unix = false;
+ self::_putDebug("Host is ".$this->host,2);
+ }
+ // }}}
+
+ // {{{ setTimeout($timeout)
+ public function setTimeout($timeout){
+ $this->timeout = $timeout;
+ }
+ // }}}
+
+ // {{{ setPrinterURI ($uri)
+ public function setPrinterURI ($uri) {
+
+
+ $length = strlen ($uri);
+ $length = chr($length);
+
+ while (strlen($length) < 2)
+ $length = chr(0x00) . $length;
+
+ $this->meta->printer_uri = chr(0x45) // uri type | value-tag
+ . chr(0x00) . chr(0x0B) // name-length
+ . "printer-uri" // printer-uri | name
+ . $length
+ . $uri;
+
+ $this->printer_uri = $uri;
+
+ self::_putDebug(sprintf(_("Printer URI: %s"),$uri),2);
+
+ $this->setup->uri = 1;
+
+ }
+ // }}}
+
+ // {{{ setData($data)
+ public function setData($data){
+ //
+ $this->data = $data;
+ self::_putDebug("Data set",2);
+ }
+ // }}}
+
+ // {{{ setRawText ()
+ public function setRawText () {
+ $this->setup->datatype = 'TEXT';
+ $this->meta->mime_media_type = "";
+ $this->setup->mime_media_type = 1;
+ $this->datahead = chr(0x16);
+
+ if (is_readable($this->data)){
+ //It's a filename. Open and stream.
+ $data = fopen($this->data, "rb");
+ while(!feof($data))
+ $output = fread($data, 8192);
+ } else {
+ $output = $this->data;
+ }
+
+ if (substr($output,-1,1) != chr(0x0c))
+ if (!isset($this->setup->noFormFeed))
+ $this->datatail = chr(0x0c);
+
+ self::_putDebug(_("Forcing data to be interpreted as RAW TEXT"),2);
+ }
+ // }}}
+
+ // {{{ unsetRawText ()
+ public function unsetRawText () {
+
+ $this->setup->datatype = 'BINARY';
+ $this->datahead = '';
+ $this->datatail = '';
+ self::_putDebug(_("Unset forcing data to be interpreted as RAW TEXT"),2);
+
+ }
+ // }}}
+
+ // {{{ setBinary()
+ public function setBinary () {
+ self::unsetRawText();
+ }
+ // }}}
+
+ // {{{ setFormFeed ()
+ public function setFormFeed () {
+ $this->datatail = "\r\n".chr(0x0c);
+ unset($this->setup->noFormFeed);
+ }
+ // }}}
+
+ // {{{ unsetFormFeed ()
+ public function unsetFormFeed () {
+ $this->datatail = '';
+ $this->setup->noFormFeed = 1;
+ }
+ // }}}
+
+ // {{{ setCharset ($charset)
+ public function setCharset ($charset='us-ascii') {
+
+ $charset = strtolower($charset);
+ $this->charset = $charset;
+
+ $this->meta->charset = chr(0x47) // charset type | value-tag
+ . chr(0x00) . chr(0x12) // name-length
+ . "attributes-charset" // attributes-charset | name
+ . self::_giveMeStringLength($charset) // value-length
+ . $charset; // value
+
+ self::_putDebug(sprintf(_("Charset: %s"),$charset),2);
+
+ $this->setup->charset = 1;
+ }
+ // }}}
+
+ // {{{ setLanguage($language)
+ public function setLanguage($language='en_us') {
+
+ $language = strtolower($language);
+
+ $this->meta->language = chr(0x48) // natural-language type | value-tag
+ . chr(0x00) . chr(0x1B) // name-length
+ . "attributes-natural-language" //attributes-natural-language
+ . self::_giveMeStringLength($language) // value-length
+ . $language; // value
+
+ self::_putDebug(sprintf(_("Language: %s"),$language),2);
+
+ $this->setup->language = 1;
+ }
+ // }}}
+
+ // {{{ setMimeMediaType ($mime_media_type='application/octet-stream')
+ public function setMimeMediaType ($mime_media_type='') {
+
+ self::setBinary();
+
+ $length = strlen ($mime_media_type);
+ if ($length == 0)
+ {
+ $this->meta->mime_media_type = "";
+ }
+ else
+ {
+ $length = chr($length);
+
+ while (strlen($length) < 2)
+ $length = chr(0x00) . $length;
+
+
+ self::_putDebug( sprintf(_("mime type: %s"),$mime_media_type),2);
+
+ $this->meta->mime_media_type = chr(0x49) // document-format tag
+ . self::_giveMeStringLength('document-format')
+ . 'document-format' //
+ . self::_giveMeStringLength($mime_media_type)
+ . $mime_media_type; // value
+ }
+ $this->setup->mime_media_type = 1;
+ }
+ // }}}
+
+ // {{{ setDocumentFormat ($mime_media_type="application/octet-stream") // setMimeMediaType alias
+ public function setDocumentFormat ($mime_media_type="application/octet-stream") {
+ self::setMimeMediaType ($mime_media_type);
+ }
+ // }}}
+
+ // {{{ setCopies ($nbrcopies=1)
+ public function setCopies ($nbrcopies=1) {
+
+ $this->meta->copies = "";
+ if ($nbrcopies == 1 || !$nbrcopies)
+ return true;
+
+ $copies = self::_integerBuild($nbrcopies);
+
+ $this->meta->copies = chr(0x21) // integer type | value-tag
+ . chr(0x00) .chr(0x06) // name-length
+ . "copies" // copies | name
+ . self::_giveMeStringLength($copies) // value-length
+ . $copies;
+
+ self::_putDebug( sprintf(_("Copies: %s"),$nbrcopies),2);
+
+ $this->setup->copies = 1;
+
+ }
+ // }}}
+
+ // {{{ setDocumentName ($document_name)
+ public function setDocumentName ($document_name="") {
+
+ $this->meta->document_name = "";
+ if (!$document_name)
+ return true;
+
+ $document_name = substr($document_name,0,1023);
+
+ $length = strlen ($document_name);
+ $length = chr($length);
+
+ while (strlen($length) < 2)
+ $length = chr(0x00) . $length;
+
+
+ self::_putDebug( sprintf(_("document name: %s"),$document_name),2);
+
+ $this->meta->document_name = chr(0x41) // textWithoutLanguage tag
+ . chr(0x00) . chr(0x0d) // name-length
+ . "document-name" // mimeMediaType
+ . self::_giveMeStringLength($document_name)
+ . $document_name; // value
+
+ }
+ // }}}
+
+ // {{{ setJobName ($jobname='(PHP)',$absolute=false)
+ public function setJobName ($jobname='',$absolute=false) {
+
+ $this->meta->jobname = '';
+ if ($jobname=='')
+ {
+ $this->meta->jobname = '';
+ return true;
+ }
+ $postpend = date('-H:i:s-') . $this->_setJobId();
+
+ if ($absolute)
+ $postpend = '';
+
+ if (isset($this->values->jobname) && $jobname == '(PHP)')
+ $jobname = $this->values->jobname;
+
+ $this->values->jobname = $jobname;
+
+ $jobname .= $postpend;
+
+ $this->meta->jobname = chr(0x42) // nameWithoutLanguage type || value-tag
+ . chr(0x00) . chr(0x08) // name-length
+ . "job-name" // job-name || name
+ . self::_giveMeStringLength($jobname) // value-length
+ . $jobname ; // value
+
+ self::_putDebug( sprintf(_("Job name: %s"),$jobname),2);
+ $this->setup->jobname = 1;
+ }
+ // }}}
+
+ // {{{ setUserName ($username='PHP-SERVER')
+ public function setUserName ($username='PHP-SERVER') {
+
+ $this->requesting_user = $username;
+ $this->meta->username = '';
+ if (!$username)
+ return true;
+
+ if ($username == 'PHP-SERVER' && isset($this->meta->username))
+ return TRUE;
+
+ $value_length = 0x00;
+ for ($i = 0 ; $i < strlen($username) ; $i ++) {
+ $value_length += 0x01;
+ }
+ $value_length = chr($value_length);
+
+ while (strlen($value_length) < 2)
+ $value_length = chr(0x00) . $value_length;
+
+ $this->meta->username = chr(0x42) // keyword type || value-tag
+ . chr(0x00). chr(0x14) // name-length
+ . "requesting-user-name"
+ . $value_length
+ . $username;
+
+ self::_putDebug( sprintf(_("Username: %s"),$username),2);
+ $this->setup->username = 1;
+ }
+ // }}}
+
+ // {{{ setAuthentification ($username,$password)
+ public function setAuthentification ($username,$password) {
+ self::setAuthentication ($username,$password);
+ }
+ // }}}
+
+ // {{{ setAuthentication ($username,$password)
+ public function setAuthentication ($username,$password) {
+ $this->password = $password;
+ $this->username = $username;
+
+ self::_putDebug( _("Setting password"),2);
+ $this->setup->password = 1;
+ }
+ // }}}
+
+ // {{{ setSides ($sides=2)
+ public function setSides ($sides=2) {
+
+ $this->meta->sides = '';
+ if (!$sides)
+ return true;
+
+ switch ($sides) {
+ case 1:
+ $sides = "one-sided";
+ break;
+ case 2:
+ $sides = "two-sided-long-edge";
+ break;
+ case "2CE":
+ $sides = "two-sided-short-edge";
+ break;
+ default:
+ $sides = $sides; // yeah, what ?
+ break;
+ }
+
+
+ $this->meta->sides = chr(0x44) // keyword type | value-tag
+ . chr(0x00). chr(0x05) // name-length
+ . "sides" // sides | name
+ . self::_giveMeStringLength($sides) // value-length
+ . $sides ; // one-sided | value
+
+ self::_putDebug( sprintf(_("Sides value set to %s"), $sides),2);
+ }
+ // }}}
+
+ // {{{ setFidelity ()
+ public function setFidelity () {
+
+ // whether the server can't replace any attributes (eg, 2 sided print is not possible,
+ // so print one sided) and DO NOT THE JOB.
+ $this->meta->fidelity = chr(0x22) // boolean type | value-tag
+ . chr(0x00). chr(0x16) // name-length
+ . "ipp-attribute-fidelity" // ipp-attribute-fidelity | name
+ . chr(0x00) . chr(0x01) // value-length
+ . chr(0x01); // true | value
+
+ self::_putDebug( _("Fidelity attribute is set (paranoid mode)"),3);
+
+ }
+ // }}}
+
+ // {{{ unsetFidelity ()
+ public function unsetFidelity () {
+
+ // whether the server can replace any attributes (eg, 2 sided print is not possible,
+ // so print one sided) and DO THE JOB.
+
+ $this->meta->fidelity = chr(0x22) // boolean type | value-tag
+ . chr(0x00). chr(0x16) // name-length
+ . "ipp-attribute-fidelity" // ipp-attribute-fidelity | name
+ . chr(0x00) . chr(0x01) // value-length
+ . chr(0x00); // false | value
+
+ self::_putDebug( _("Fidelity attribute is unset"),2);
+ }
+ // }}}
+
+ // {{{ setMessage()
+ public function setMessage ($message='') {
+
+ $this->meta->message = '';
+ if (!$message)
+ return true;
+
+ $this->meta->message = chr(0x41) // attribute type = textWithoutLanguage
+ . chr(0x00) . chr(0x07)
+ . "message"
+ . self::_giveMeStringLength(substr($message,0,127))
+ . substr($message,0,127);
+
+ self::_putDebug( sprintf(_('Setting message to "%s"'),$message),2);
+ }
+ // }}}
+
+ // {{{ setPageRanges($page_ranges)
+ public function setPageRanges($page_ranges) {
+
+ // $pages_ranges = string: "1:5 10:25 40:52 ..."
+ // to unset, specify an empty string.
+
+ $this->meta->page_range = '';
+
+ if (!$page_ranges)
+ return true;
+
+ $page_ranges = trim(str_replace("-",":",$page_ranges));
+
+ $first = true;
+ $page_ranges = split(' ',$page_ranges);
+ foreach ($page_ranges as $page_range) {
+ $value = self::_rangeOfIntegerBuild($page_range);
+
+ if ($first)
+ $this->meta->page_ranges .= $this->tags_types['rangeOfInteger']['tag']
+ . self::_giveMeStringLength('page-ranges')
+ . 'page-ranges'
+ . self::_giveMeStringLength($value)
+ . $value;
+ else
+ $this->meta->page_ranges .= $this->tags_types['rangeOfInteger']['tag']
+ . self::_giveMeStringLength('')
+ . self::_giveMeStringLength($value)
+ . $value;
+ $first = false;
+ }
+
+ }
+ // }}}
+
+ // {{{ setAttribute($attribute,$value)
+ public function setAttribute($attribute,$values) {
+
+ $operation_attributes_tags = array_keys($this->operation_tags);
+ $job_attributes_tags = array_keys($this->job_tags);
+ $printer_attributes_tags = array_keys($this->printer_tags);
+ self::unsetAttribute($attribute);
+
+ if (in_array($attribute,$operation_attributes_tags)) {
+ if (!is_array($values))
+ self::_setOperationAttribute ($attribute,$values);
+ else
+ foreach ($values as $value)
+ self::_setOperationAttribute ($attribute,$value);
+
+ } elseif (in_array($attribute,$job_attributes_tags)) {
+ if (!is_array($values))
+ self::_setJobAttribute ($attribute,$values);
+ else
+ foreach ($values as $value)
+ self::_setJobAttribute ($attribute,$value);
+ } elseif (in_array($attribute,$printer_attributes_tags)) {
+ if (!is_array($values))
+ self::_setPrinterAttribute ($attribute,$values);
+ else
+ foreach ($values as $value)
+ self::_setPrinterAttribute ($attribute,$value);
+
+ } else {
+ trigger_error(sprintf(_('SetAttribute: Tag "%s" is not a printer or a job attribute'),$attribute),E_USER_NOTICE);
+ self::_putDebug(sprintf(_('SetAttribute: Tag "%s" is not a printer or a job attribute'),$attribute),3);
+ self::_errorLog(sprintf(_('SetAttribute: Tag "%s" is not a printer or a job attribute'),$attribute),2);
+ return FALSE;
+ }
+
+ }
+ // }}}
+
+ // {{{ unsetAttribute($attribute)
+ public function unsetAttribute($attribute) {
+
+ $operation_attributes_tags = array_keys($this->operation_tags);
+ $job_attributes_tags = array_keys($this->job_tags);
+ $printer_attributes_tags = array_keys($this->printer_tags);
+
+ if (in_array($attribute,$operation_attributes_tags))
+ unset ($this->operation_tags[$attribute]['value'], $this->operation_tags[$attribute]['systag']);
+ elseif (in_array($attribute,$job_attributes_tags))
+ unset ($this->job_tags[$attribute]['value'], $this->job_tags[$attribute]['systag']);
+ elseif (in_array($attribute,$printer_attributes_tags))
+ unset ($this->printer_tags[$attribute]['value'], $this->printer_tags[$attribute]['systag']);
+ else {
+ trigger_error(sprintf(_('unsetAttribute: Tag "%s" is not a printer or a job attribute'),$attribute),E_USER_NOTICE);
+ self::_putDebug(sprintf(_('unsetAttribute: Tag "%s" is not a printer or a job attribute'),$attribute),3);
+ self::_errorLog(sprintf(_('unsetAttribute: Tag "%s" is not a printer or a job attribute'),$attribute),2);
+ return FALSE;
+ }
+
+ return true;
+ }
+ // }}}
+
+// LOGGING / DEBUGGING
+
+ // {{{ setLog ($log_destination,$destination_type='file',$level=2)
+ public function setLog ($log_destination,$destination_type='file',$level=2) {
+
+ if (is_string($log_destination) && !empty($log_destination))
+ $this->log_destination = $log_destination;
+
+ switch ($destination_type) {
+ case 'file':
+ case 3:
+ $this->log_destination = $log_destination;
+ $this->log_type = 3;
+ break;
+ case 'logger':
+ case 0:
+ $this->log_destination = '';
+ $this->log_type = 0;
+ break;
+ case 'e-mail':
+ case 1:
+ $this->log_destination = $log_destination;
+ $this->log_type = 1;
+ break;
+ }
+ $this->log_level = $level;
+
+ }
+ // }}}
+
+ // {{{ printDebug()
+ public function printDebug() {
+ for ($i = 0 ; $i < $this->debug_count ; $i++)
+ echo $this->debug[$i], "\n";
+ $this->debug = array();
+ $this->debug_count = 0;
+ }
+ // }}}
+
+ // {{{ getDebug()
+ public function getDebug() {
+ $debug = '';
+ for ($i = 0 ; $i < $this->debug_count ; $i++)
+ $debug .= $this->debug[$i];
+ $this->debug = array();
+ $this->debug_count = 0;
+ return $debug;
+ }
+ // }}}
+
+// OPERATIONS
+
+ // {{{ printJob()
+ public function printJob(){
+ // this version of printJob do not parse server output for job's attributes
+
+ self::_putDebug( sprintf("************** Date: %s ***********",
+ date('Y-m-d H:i:s')));
+
+ if (!$this->_stringJob())
+ return FALSE;
+
+ if (is_readable($this->data)){
+ self::_putDebug( _("Printing a FILE"));
+
+ $this->output = $this->stringjob;
+
+ if ($this->setup->datatype == "TEXT")
+ $this->output .= chr(0x16);
+
+
+ $post_values = array( "Content-Type" => "application/ipp",
+ "Data" => $this->output,
+ "File" => $this->data);
+
+ if ($this->setup->datatype == "TEXT" && !isset($this->setup->noFormFeed))
+ $post_values = array_merge($post_values,array("Filetype"=>"TEXT"));
+
+ } else {
+ self::_putDebug( _("Printing DATA"));
+
+ $this->output = $this->stringjob;
+ $this->output .= $this->datahead;
+ $this->output .= $this->data;
+ $this->output .= $this->datatail;
+
+ $post_values = array( "Content-Type" => "application/ipp",
+ "Data" => $this->output);
+
+
+ }
+
+ if (self::_sendHttp ($post_values,$this->paths["printers"]))
+ self::_parseServerOutput();
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog(sprintf("printing job %s: ",$this->last_job) .$this->serveroutput->status,3);
+ else
+ self::_errorLog(sprintf("printing job: ",$this->last_job) .$this->serveroutput->status,1);
+
+ return $this->serveroutput->status;
+
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+ self::_errorLog("printing job : OPERATION FAILED",1);
+
+ return false;
+ }
+ // }}}
+
+
+/******************
+*
+* PROTECTED FUNCTIONS
+*
+*******************/
+
+// HTTP OUTPUT
+
+ // {{{ _sendHttp ($post_values,$uri)
+ protected function _sendHttp ($post_values,$uri) {
+ /*
+ This function Copyright (C) 2005-2006 Thomas Harding, Manuel Lemos
+ */
+
+ $this->response_completed[] = "no";
+ unset($this->serverouptut);
+
+ self::_putDebug( _("Processing HTTP request"),2);
+
+ $this->serveroutput->headers = array();
+ $this->serveroutput->body = "";
+
+ $http = new http_class;
+ if (!$this->unix)
+ $http->host = $this->host;
+ else
+ $http->host = "localhost";
+ $http->with_exceptions = $this->with_exceptions;
+
+
+ if ($this->debug_http) {
+ $http->debug = 1;
+ $http->html_debug=0;
+ } else {
+ $http->debug=0;
+ $http->html_debug=0;
+ }
+
+ $url="http://".$this->host;
+ if ($this->ssl)
+ $url="https://".$this->host;
+ if ($this->unix)
+ $url="unix://".$this->host;
+
+ $http->port = $this->port;
+ $http->timeout = $this->http_timeout;
+ $http->data_timeout= $this->http_data_timeout;
+
+ $http->force_multipart_form_post = false;
+
+ $http->user = $this->username;
+ $http->password = $this->password;
+
+ $error=$http->GetRequestArguments($url,$arguments);
+ $arguments["RequestMethod"]="POST";
+ $arguments["Headers"] = array("Content-Type" => "application/ipp");
+ $arguments["BodyStream"] = array( array("Data" => $post_values["Data"]) );
+
+ if (isset($post_values["File"]))
+ $arguments["BodyStream"][]=array("File"=>$post_values["File"]);
+ if (isset($post_values["FileType"])
+ && !strcmp($post_values["FileType"],"TEXT"))
+ $arguments["BodyStream"][]=array("Data"=>Chr(12));
+
+ $arguments["RequestURI"] = $uri;
+
+ if ($this->with_exceptions && $this->handle_http_exceptions)
+ {
+ try
+ {
+ $error=$http->Open($arguments);
+ }
+ catch (httpException $e)
+ {
+ throw new ippException(sprintf("http error: %s", $e->getMessage()),$e->getErrno());
+ }
+ }
+ else
+ {
+ $error=$http->Open($arguments);
+ }
+
+ if($error=="") {
+ $error=$http->SendRequest($arguments);
+
+ if($error=="") {
+
+ self::_putDebug( "H T T P R E Q U E S T :");
+ self::_putDebug("Request headers:");
+
+ for(Reset($http->request_headers),$header=0;$header<count($http->request_headers);Next($http->request_headers),$header++) {
+
+ $header_name=Key($http->request_headers);
+ if(GetType($http->request_headers[$header_name])=="array") {
+ for($header_value=0;$header_value<count($http->request_headers[$header_name]);$header_value++)
+ self::_putDebug( $header_name.": ".$http->request_headers[$header_name][$header_value]);
+ } else
+ self::_putDebug( $header_name.": ".$http->request_headers[$header_name]);
+
+ }
+ self::_putDebug( "Request body:");
+ self::_putDebug( htmlspecialchars($http->request_body)
+ ."*********** END REQUEST BODY *********");
+
+
+ $i = 0;
+ $headers=array();
+ unset($this->serveroutput->headers);
+ $error=$http->ReadReplyHeaders($headers);
+
+ self::_putDebug( "H T T P R E S P O N S E :");
+ if($error=="") {
+
+ self::_putDebug("Response headers:");
+ for(Reset($headers),$header=0;$header<count($headers);Next($headers),$header++) {
+ $header_name=Key($headers);
+ if(GetType($headers[$header_name])=="array") {
+ for($header_value=0;$header_value<count($headers[$header_name]);$header_value++) {
+ self::_putDebug( $header_name.": ".$headers[$header_name][$header_value]);
+ $this->serveroutput->headers[$i] = $header_name.": ".$headers[$header_name][$header_value];
+ $i++;
+ }
+ } else {
+ self::_putDebug( $header_name.": ".$headers[$header_name]);
+ $this->serveroutput->headers[$i] = $header_name.": ".$headers[$header_name];
+ $i++;
+ }
+ }
+
+ self::_putDebug( "\n\nResponse body:\n");
+ $this->serveroutput->body = "";
+ for(;;) {
+ $error=$http->ReadReplyBody($body,1024);
+ if($error!="" || strlen($body)==0)
+ break;
+ self::_putDebug(htmlentities($body));
+ $this->serveroutput->body .= $body;
+ }
+ }
+ self::_putDebug( "********* END RESPONSE BODY ********");
+ }
+ }
+ $http->Close();
+ if(strlen($error)) {
+ self::_putDebug($error,4);
+ if ($this->with_exceptions) {
+ $this->serveroutput->status = $error;
+ throw new ippException($error);
+ }
+ trigger_error($error,E_USER_WARNING);
+ $this->serveroutput->status = $error;
+ return FALSE;
+ }
+ return true;
+ }
+ // }}}
+
+// INIT
+
+ // {{{ _initTags ()
+ protected function _initTags () {
+
+ $this->tags_types = array ( "unsupported" => array ("tag" => chr(0x10),
+ "build" => ""),
+ "reserved" => array ("tag" => chr(0x11),
+ "build" => ""),
+ "unknown" => array ("tag" => chr(0x12),
+ "build" => ""),
+ "no-value" => array ("tag" => chr(0x13),
+ "build" => "no_value"),
+ "integer" => array ("tag" => chr(0x21),
+ "build" => "integer"),
+ "boolean" => array ("tag" => chr(0x22),
+ "build" => "boolean"),
+ "enum" => array ("tag" => chr(0x23),
+ "build" => "enum"),
+ "octetString" => array ("tag" => chr(0x30),
+ "build" => "octet_string"),
+ "datetime" => array ("tag" => chr(0x31),
+ "build" => "datetime"),
+ "resolution" => array ("tag" => chr(0x32),
+ "build" => "resolution"),
+ "rangeOfInteger" => array ("tag" => chr(0x33),
+ "build" => "range_of_integers"),
+ "textWithLanguage" => array ("tag" => chr(0x35),
+ "build" => "string"),
+ "nameWithLanguage" => array ("tag" => chr(0x36),
+ "build" => "string"),
+ /*
+ "text" => array ("tag" => chr(0x40),
+ "build" => "string"),
+ "text string" => array ("tag" => chr(0x40),
+ "build" => "string"),
+ */
+ "textWithoutLanguage" => array ("tag" => chr(0x41),
+ "build" => "string"),
+ "nameWithoutLanguage" => array ("tag" => chr(0x42),
+ "buid" => "string"),
+ "keyword" => array ("tag" => chr(0x44),
+ "build" => "string"),
+ "uri" => array ("tag" => chr(0x45),
+ "build" => "string"),
+ "uriScheme" => array ("tag" => chr(0x46),
+ "build" => "string"),
+ "charset" => array ("tag" => chr(0x47),
+ "build" => "string"),
+ "naturalLanguage" => array ("tag" => chr(0x48),
+ "build" => "string"),
+ "mimeMediaType" => array ("tag" => chr(0x49),
+ "build" => "string"),
+ "extendedAttributes" => array ("tag" => chr(0x7F),
+ "build" => "extended"),
+ );
+
+
+ $this->operation_tags = array ("compression" => array("tag" => "keyword"),
+ "document-natural-language" => array("tag" => "naturalLanguage"),
+ "job-k-octets" => array("tag" => "integer"),
+ "job-impressions" => array("tag" => "integer"),
+ "job-media-sheets" => array("tag" => "integer"),
+ );
+
+ $this->job_tags = array ( "job-priority" => array("tag" => "integer"),
+ "job-hold-until" => array("tag" => "keyword"),
+ "job-sheets" => array("tag" => "keyword"), //banner page
+ "multiple-document-handling" => array("tag" => "keyword"),
+ //"copies" => array("tag" => "integer"),
+ "finishings" => array("tag" => "enum"),
+ //"page-ranges" => array("tag" => "rangeOfInteger"), // has its own function
+ //"sides" => array("tag" => "keyword"), // has its own function
+ "number-up" => array("tag" => "integer"),
+ "orientation-requested" => array("tag" => "enum"),
+ "media" => array("tag" => "keyword"),
+ "printer-resolution" => array("tag" => "resolution"),
+ "print-quality" => array("tag" => "enum"),
+ "job-message-from-operator" => array("tag" => "textWithoutLanguage"),
+ );
+
+ $this->printer_tags = array ( "requested-attributes" => array("tag" => "keyword"));
+ }
+ // }}}
+
+// SETUP
+
+ // {{{ _setOperationId ()
+ protected function _setOperationId () {
+ $prepend = '';
+ $this->operation_id += 1;
+ $this->meta->operation_id = self::_integerBuild($this->operation_id);
+ self::_putDebug( "operation id is: ".$this->operation_id,2);
+ }
+ // }}}
+
+ // {{{ _setJobId()
+ protected function _setJobId() {
+
+ $this->meta->jobid +=1;
+ $prepend = '';
+ $prepend_length = 4 - strlen($this->meta->jobid);
+ for ($i = 0; $i < $prepend_length ; $i++ )
+ $prepend .= '0';
+
+ return $prepend.$this->meta->jobid;
+ }
+ // }}}
+
+ // {{{ _setJobUri ($job_uri)
+ protected function _setJobUri ($job_uri) {
+
+ $this->meta->job_uri = chr(0x45) // type uri
+ . chr(0x00).chr(0x07) // name-length
+ . "job-uri"
+ //. chr(0x00).chr(strlen($job_uri))
+ . self::_giveMeStringLength($job_uri)
+ . $job_uri;
+
+ self::_putDebug( "job-uri is: ".$job_uri,2);
+ }
+ // }}}
+
+// RESPONSE PARSING
+
+ // {{{ _parseServerOutput ()
+ protected function _parseServerOutput () {
+
+ $this->serveroutput->response = array();
+
+ if (!self::_parseHttpHeaders ()) return FALSE;
+
+ $this->_parsing->offset = 0;
+
+ self::_parseIppVersion ();
+ self::_parseStatusCode ();
+ self::_parseRequestID ();
+ $this->_parseResponse ();
+
+ //devel
+ self::_putDebug( sprintf("***** IPP STATUS: %s ******",$this->serveroutput->status),4);
+ self::_putDebug( "****** END OF OPERATION ****");
+
+ return true;
+ }
+ // }}}
+
+ // {{{ _parseHttpHeaders
+ protected function _parseHttpHeaders () {
+
+ $response = "";
+
+ switch ($this->serveroutput->headers[0]) {
+
+ case "http/1.1 200 ok: ":
+ $this->serveroutput->httpstatus = "HTTP/1.1 200 OK";
+ $response = "OK";
+ break;
+ case "http/1.1 100 continue: ":
+ $this->serveroutput->httpstatus = "HTTP/1.1 100 CONTINUE";
+ $response = "OK";
+ break;
+ case "":
+ $this->serveroutput->httpstatus = "HTTP/1.1 000 No Response From Server";
+ $this->serveroutput->status = "HTTP-ERROR-000_NO_RESPONSE_FROM_SERVER";
+ trigger_error("No Response From Server",E_USER_WARNING);
+ self::_errorLog("No Response From Server",1);
+ $this->disconnected = 1;
+ return FALSE;
+ break;
+ default:
+ $server_response = preg_replace("/: $/",'',$this->serveroutput->headers[0]);
+ $strings = split(' ',$server_response,3);
+ $errno = $strings[1];
+ $string = strtoupper(str_replace(' ','_',$strings[2]));
+ trigger_error(sprintf(_("server responds %s"),$server_response),E_USER_WARNING);
+ self::_errorLog("server responds ".$server_response,1);
+ $this->serveroutput->httpstatus = strtoupper($strings[0])." ".$errno." ".ucfirst($strings[2]);
+ $this->serveroutput->status = "HTTP-ERROR-".$errno."-".$string;
+ $this->disconnected = 1;
+ return FALSE;
+ break;
+ }
+
+ unset ($this->serveroutput->headers);
+
+ return TRUE;
+ }
+ // }}}
+
+ // {{{ _parseIppVersion ()
+ protected function _parseIppVersion () {
+
+ $ippversion = (ord($this->serveroutput->body[ $this->_parsing->offset]) * 256)
+ + ord($this->serveroutput->body[$this->_parsing->offset + 1]);
+
+ switch($ippversion) {
+ case 0x0101:
+ $this->serveroutput->ipp_version = "1.1";
+ break;
+ default:
+ $this->serveroutput->ipp_version = sprintf("%u.%u (Unknown)",ord($this->serveroutput->body[ $this->_parsing->offset]) * 256,ord($this->serveroutput->body[$this->_parsing->offset + 1]));
+ break;
+ }
+
+ self::_putDebug( "I P P R E S P O N S E :\n\n");
+ self::_putDebug( sprintf("IPP version %s%s: %s",
+ ord($this->serveroutput->body[ $this->_parsing->offset]),
+ ord($this->serveroutput->body[$this->_parsing->offset + 1]),
+ $this->serveroutput->ipp_version));
+
+ $this->_parsing->offset += 2;
+ return;
+ }
+ // }}}
+
+ // {{{ _parseStatusCode ()
+ protected function _parseStatusCode () {
+ $status_code = (ord($this->serveroutput->body[$this->_parsing->offset]) * 256)
+ + ord($this->serveroutput->body[$this->_parsing->offset + 1]);
+
+
+ $this->serveroutput->status ="NOT PARSED";
+
+ $this->_parsing->offset += 2;
+
+ if (strlen($this->serveroutput->body) < $this->_parsing->offset)
+ return false;
+
+
+ if ($status_code < 0x00FF) {
+ $this->serveroutput->status = "successfull";
+ } elseif ($status_code < 0x01FF) {
+ $this->serveroutput->status = "informational";
+ } elseif ($status_code < 0x02FF) {
+ $this->serveroutput->status = "redirection";
+ } elseif ($status_code < 0x04FF) {
+ $this->serveroutput->status = "client-error";
+ } elseif ($status_code < 0x05FF) {
+ $this->serveroutput->status = "server-error";
+ }
+
+ switch ($status_code) {
+ case 0x0000:
+ $this->serveroutput->status = "successfull-ok";
+ break;
+ case 0x0001:
+ $this->serveroutput->status = "successful-ok-ignored-or-substituted-attributes";
+ break;
+ case 0x002:
+ $this->serveroutput->status = "successful-ok-conflicting-attributes";
+ break;
+ case 0x0400:
+ $this->serveroutput->status = "client-error-bad-request";
+ break;
+ case 0x0401:
+ $this->serveroutput->status = "client-error-forbidden";
+ break;
+ case 0x0402:
+ $this->serveroutput->status = "client-error-not-authenticated";
+ break;
+ case 0x0403:
+ $this->serveroutput->status = "client-error-not-authorized";
+ break;
+ case 0x0404:
+ $this->serveroutput->status = "client-error-not-possible";
+ break;
+ case 0x0405:
+ $this->serveroutput->status = "client-error-timeout";
+ break;
+ case 0x0406:
+ $this->serveroutput->status = "client-error-not-found";
+ break;
+ case 0x0407:
+ $this->serveroutput->status = "client-error-gone";
+ break;
+ case 0x0408:
+ $this->serveroutput->status = "client-error-request-entity-too-large";
+ break;
+ case 0x0409:
+ $this->serveroutput->status = "client-error-request-value-too-long";
+ break;
+ case 0x040A:
+ $this->serveroutput->status = "client-error-document-format-not-supported";
+ break;
+ case 0x040B:
+ $this->serveroutput->status = "client-error-attributes-or-values-not-supported";
+ break;
+ case 0x040C:
+ $this->serveroutput->status = "client-error-uri-scheme-not-supported";
+ break;
+ case 0x040D:
+ $this->serveroutput->status = "client-error-charset-not-supported";
+ break;
+ case 0x040E:
+ $this->serveroutput->status = "client-error-conflicting-attributes";
+ break;
+ case 0x040F:
+ $this->serveroutput->status = "client-error-compression-not-supported";
+ break;
+ case 0x0410:
+ $this->serveroutput->status = "client-error-compression-error";
+ break;
+ case 0x0411:
+ $this->serveroutput->status = "client-error-document-format-error";
+ break;
+ case 0x0412:
+ $this->serveroutput->status = "client-error-document-access-error";
+ break;
+ case 0x0413: // RFC3380
+ $this->serveroutput->status = "client-error-attributes-not-settable";
+ break;
+ case 0x0500:
+ $this->serveroutput->status = "server-error-internal-error";
+ break;
+ case 0x0501:
+ $this->serveroutput->status = "server-error-operation-not-supported";
+ break;
+ case 0x0502:
+ $this->serveroutput->status = "server-error-service-unavailable";
+ break;
+ case 0x0503:
+ $this->serveroutput->status = "server-error-version-not-supported";
+ break;
+ case 0x0504:
+ $this->serveroutput->status = "server-error-device-error";
+ break;
+ case 0x0505:
+ $this->serveroutput->status = "server-error-temporary-error";
+ break;
+ case 0x0506:
+ $this->serveroutput->status = "server-error-not-accepting-jobs";
+ break;
+ case 0x0507:
+ $this->serveroutput->status = "server-error-busy";
+ break;
+ case 0x0508:
+ $this->serveroutput->status = "server-error-job-canceled";
+ break;
+ case 0x0509:
+ $this->serveroutput->status = "server-error-multiple-document-jobs-not-supported";
+ break;
+ default:
+ break;
+ }
+
+
+ self::_putDebug( sprintf("status-code: %s%s: %s ",$this->serveroutput->body[$this->_parsing->offset],
+ $this->serveroutput->body[$this->_parsing->offset + 1],
+ $this->serveroutput->status),4);
+
+ return;
+ }
+ // }}}
+
+ // {{{ _parseRequestID ()
+ protected function _parseRequestID () {
+
+ $this->serveroutput->request_id = self::_interpretInteger(substr($this->serveroutput->body,$this->_parsing->offset,4));
+ self::_putDebug( "request-id ". $this->serveroutput->request_id,2);
+ $this->_parsing->offset += 4;
+
+ return;
+ }
+ // }}}
+
+ // {{{ _interpretInteger($value)
+ protected function _interpretInteger($value) {
+
+ // they are _signed_ integers
+ $value_parsed = 0;
+
+ for ($i = strlen($value) ; $i > 0 ; $i --)
+ $value_parsed += (1 << (($i - 1)*8)) * ord($value[strlen($value) - $i]);
+ if ($value_parsed >= 2147483648)
+ $value_parsed -= 4294967296;
+ return $value_parsed;
+ }
+ // }}}
+
+ // {{{ _parseResponse () {}
+ protected function _parseResponse () {}
+ // }}}
+// REQUEST BUILDING
+
+ // {{{ _stringJob ()
+ protected function _stringJob () {
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+ if (!isset($this->setup->datatype))
+ self::setBinary();
+
+ if (!isset($this->setup->uri)) {
+ $this->getPrinters();
+ unset($this->jobs[count($this->jobs) - 1]);
+ unset($this->jobs_uri[count($this->jobs_uri) - 1]);
+ unset($this->status[count($this->status) - 1]);
+
+ if (array_key_exists(0,$this->available_printers))
+ self::setPrinterURI($this->available_printers[0]);
+ else {
+ trigger_error(_("_stringJob: Printer URI is not set: die"),E_USER_WARNING);
+ self::_putDebug( _("_stringJob: Printer URI is not set: die"),4);
+ self::_errorLog(" Printer URI is not set, die",2);
+ return FALSE;
+ }
+ }
+
+ if (!isset($this->setup->copies))
+ self::setCopies(1);
+ if (!isset($this->setup->language))
+ self::setLanguage('en_us');
+
+ if (!isset($this->setup->mime_media_type))
+ self::setMimeMediaType();
+ if ($this->setup->datatype != "TEXT")
+ unset ($this->setup->mime_media_type);
+
+ if (!isset($this->setup->jobname))
+ self::setJobName();
+ unset($this->setup->jobname);
+
+ if (!isset($this->meta->username))
+ self::setUserName();
+
+ if (!isset($this->meta->fidelity))
+ $this->meta->fidelity = '';
+
+ if (!isset($this->meta->document_name))
+ $this->meta->document_name = '';
+
+ if (!isset($this->meta->sides))
+ $this->meta->sides = '';
+
+ if (!isset($this->meta->page_ranges))
+ $this->meta->page_ranges = '';
+
+ $jobattributes = '';
+ $operationattributes = '';
+ $printerattributes = '';
+ $this->_buildValues($operationattributes,$jobattributes,$printerattributes);
+ self::_setOperationId();
+
+ if (!isset($this->error_generation->request_body_malformed))
+ $this->error_generation->request_body_malformed = "";
+
+ $this->stringjob = chr(0x01) . chr(0x01) // 1.1 | version-number
+ . chr(0x00) . chr (0x02) // Print-Job | operation-id
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . $this->meta->printer_uri
+ . $this->meta->username
+ . $this->meta->jobname
+ . $this->meta->fidelity
+ . $this->meta->document_name
+ . $this->meta->mime_media_type
+ . $operationattributes;
+ if ($this->meta->copies
+ || $this->meta->sides
+ || $this->meta->page_ranges
+ || !empty($jobattributes))
+ {
+ $this->stringjob .= chr(0x02) // start job-attributes | job-attributes-tag
+ . $this->meta->copies
+ . $this->meta->sides
+ . $this->meta->page_ranges
+ . $jobattributes;
+ }
+ $this->stringjob .= chr(0x03); // end-of-attributes | end-of-attributes-tag
+
+ self::_putDebug( sprintf(_("String sent to the server is: %s"), $this->stringjob));
+ return TRUE;
+ }
+ // }}}
+
+ // {{{ _buildValues (&$operationattributes,&$jobattributes);
+ protected function _buildValues (&$operationattributes,&$jobattributes,&$printerattributes) {
+
+ $operationattributes = '';
+ foreach ($this->operation_tags as $key => $values) {
+ $item = 0;
+ if (array_key_exists('value',$values))
+ foreach ($values['value'] as $item_value) {
+ if ($item == 0)
+ $operationattributes .= $values['systag']
+ . self::_giveMeStringLength($key)
+ . $key
+ . self::_giveMeStringLength($item_value)
+ . $item_value;
+ else
+ $operationattributes .= $values['systag']
+ . self::_giveMeStringLength('')
+ . self::_giveMeStringLength($item_value)
+ . $item_value;
+
+ $item++;
+ }
+ }
+
+ $jobattributes = '';
+ foreach ($this->job_tags as $key => $values)
+ {
+ $item = 0;
+ if (array_key_exists('value',$values))
+ {
+ foreach ($values['value'] as $item_value) {
+ if ($item == 0)
+ $jobattributes .= $values['systag']
+ . self::_giveMeStringLength($key)
+ . $key
+ . self::_giveMeStringLength($item_value)
+ . $item_value;
+ else
+ $jobattributes .= $values['systag']
+ . self::_giveMeStringLength('')
+ . self::_giveMeStringLength($item_value)
+ . $item_value;
+
+ $item++;
+ }
+ }
+ }
+
+ $printerattributes = '';
+ foreach ($this->printer_tags as $key => $values) {
+ $item = 0;
+ if (array_key_exists('value',$values))
+ foreach ($values['value'] as $item_value) {
+ if ($item == 0)
+ $printerattributes .= $values['systag']
+ . self::_giveMeStringLength($key)
+ . $key
+ . self::_giveMeStringLength($item_value)
+ . $item_value;
+ else
+ $printerattributes .= $values['systag']
+ . self::_giveMeStringLength('')
+ . self::_giveMeStringLength($item_value)
+ . $item_value;
+
+ $item++;
+ }
+ }
+
+ reset ($this->job_tags);
+ reset ($this->operation_tags);
+ reset ($this->printer_tags);
+ return true;
+ }
+ // }}}
+
+ // {{{ _giveMeStringLength ($string)
+ protected function _giveMeStringLength ($string) {
+
+ $prepend = '';
+ $length = strlen($string);
+ $lengthlength = strlen(chr($length));
+ while ($lengthlength < 2) {
+ $prepend .= chr(0x00);
+ $lengthlength += 1;
+ }
+ $length = $prepend . chr($length);
+
+ return $length;
+ }
+ // }}}
+
+ // {{{ _enumBuild ($tag,$value)
+ protected function _enumBuild ($tag,$value) {
+
+ switch ($tag) {
+ case "orientation-requested":
+ switch ($value) {
+ case 'portrait':
+ $value = chr(3);
+ break;
+ case 'landscape':
+ $value = chr(4);
+ break;
+ case 'reverse-landscape':
+ $value = chr(5);
+ break;
+ case 'reverse-portrait':
+ $value = chr(6);
+ break;
+ }
+ break;
+ case "print-quality":
+ switch($value) {
+ case 'draft':
+ $value = chr(3);
+ break;
+ case 'normal':
+ $value = chr(4);
+ break;
+ case 'high':
+ $value = chr(5);
+ break;
+ }
+ break;
+ case "finishing":
+ switch ($value) {
+ case 'none':
+ $value = chr(3);
+ break;
+ case 'staple':
+ $value = chr(4);
+ break;
+ case 'punch':
+ $value = chr(5);
+ break;
+ case 'cover':
+ $value = chr(6);
+ break;
+ case 'bind':
+ $value = chr(7);
+ break;
+ case 'saddle-stitch':
+ $value = chr(8);
+ break;
+ case 'edge-stitch':
+ $value = chr(9);
+ break;
+ case 'staple-top-left':
+ $value = chr(20);
+ break;
+ case 'staple-bottom-left':
+ $value = chr(21);
+ break;
+ case 'staple-top-right':
+ $value = chr(22);
+ break;
+ case 'staple-bottom-right':
+ $value = chr(23);
+ break;
+ case 'edge-stitch-left':
+ $value = chr(24);
+ break;
+ case 'edge-stitch-top':
+ $value = chr(25);
+ break;
+ case 'edge-stitch-right':
+ $value = chr(26);
+ break;
+ case 'edge-stitch-bottom':
+ $value = chr(27);
+ break;
+ case 'staple-dual-left':
+ $value = chr(28);
+ break;
+ case 'staple-dual-top':
+ $value = chr(29);
+ break;
+ case 'staple-dual-right':
+ $value = chr(30);
+ break;
+ case 'staple-dual-bottom':
+ $value = chr(31);
+ break;
+ }
+ break;
+ }
+
+ $prepend = '';
+ while ((strlen($value) + strlen($prepend)) < 4)
+ $prepend .= chr(0);
+
+ return $prepend.$value;
+ }
+ // }}}
+
+ // {{{ _integerBuild ($integer)
+ protected function _integerBuild ($value) {
+
+ if ($value >= 2147483647 || $value < -2147483648) {
+ trigger_error(_("Values must be between -2147483648 and 2147483647: assuming '0'"),E_USER_WARNING);
+ return chr(0x00).chr(0x00).chr(0x00).chr(0x00);
+ }
+
+ $initial_value = $value;
+
+ $int1 = $value & 0xFF;
+ $value -= $int1;
+ $value = $value >> 8;
+ $int2 = $value & 0xFF;
+ $value -= $int2;
+ $value = $value >> 8;
+ $int3 = $value & 0xFF;
+ $value -= $int3;
+ $value = $value >> 8;
+ $int4 = $value & 0xFF; //64bits
+
+ if ($initial_value < 0)
+ $int4 = chr($int4) | chr(0x80);
+ else
+ $int4 = chr($int4);
+
+ $value = $int4.chr($int3).chr($int2).chr($int1);
+
+ return $value;
+ }
+ // }}}
+
+ // {{{ _rangeOfIntegerBuild ($integers)
+ protected function _rangeOfIntegerBuild ($integers) {
+
+ $integers = split(":",$integers);
+
+ for ($i = 0 ; $i < 2 ; $i++)
+ $outvalue[$i] = self::_integerBuild($integers[$i]);
+
+ return $outvalue[0].$outvalue[1];
+ }
+ // }}}
+
+ // {{{ _setJobAttribute ($attribute,$value)
+ protected function _setJobAttribute ($attribute,$value) {
+ //used by setAttribute
+
+ $tag_type = $this->job_tags[$attribute]['tag'];
+ switch ($tag_type) {
+ case 'integer':
+ $this->job_tags[$attribute]['value'][] = self::_integerBuild($value);
+ break;
+ case 'nameWithoutLanguage':
+ case 'nameWithLanguage':
+ case 'textWithoutLanguage':
+ case 'textWithLanguage':
+ case 'keyword':
+ case 'naturalLanguage':
+ $this->job_tags[$attribute]['value'][] = $value;
+ break;
+ case 'enum':
+ $value = $this->_enumBuild($attribute,$value); // may be overwritten by children
+ $this->job_tags[$attribute]['value'][] = $value;
+ break;
+ case 'rangeOfInteger':
+ // $value have to be: INT1:INT2 , eg 100:1000
+ $this->job_tags[$attribute]['value'][] = self::_rangeOfIntegerBuild($value);
+ break;
+ case 'resolution':
+ if (preg_match("#dpi#",$value)) $unit = chr(0x3);
+ if (preg_match("#dpc#",$value)) $unit = chr(0x4);
+ $search = array("#(dpi|dpc)#",'#(x|-)#');
+ $replace = array("",":");
+ $value = self::_rangeOfIntegerBuild(preg_replace($search,$replace,$value)).$unit;
+ $this->job_tags[$attribute]['value'][] = $value;
+ break;
+ default:
+ trigger_error(sprintf(_('SetAttribute: Tag "%s": cannot set attribute'),$attribute),E_USER_NOTICE);
+ self::_putDebug(sprintf(_('SetAttribute: Tag "%s": cannot set attribute'),$attribute),2);
+ self::_errorLog(sprintf(_('SetAttribute: Tag "%s": cannot set attribute'),$attribute),2);
+ return FALSE;
+ break;
+ }
+ $this->job_tags[$attribute]['systag'] = $this->tags_types[$tag_type]['tag'];
+
+ }
+ // }}}
+
+ // {{{ _setOperationAttribute ($attribute,$value)
+ protected function _setOperationAttribute ($attribute,$value) {
+ //used by setAttribute
+ $tag_type = $this->operation_tags[$attribute]['tag'];
+ switch ($tag_type) {
+ case 'integer':
+ $this->operation_tags[$attribute]['value'][] = self::_integerBuild($value);
+ break;
+ case 'keyword':
+ case 'naturalLanguage':
+ $this->operation_tags[$attribute]['value'][] = $value;
+ break;
+ default:
+ trigger_error(sprintf(_('SetAttribute: Tag "%s": cannot set attribute'),$attribute),E_USER_NOTICE);
+ self::_putDebug(sprintf(_('SetAttribute: Tag "%s": cannot set attribute'),$attribute),2);
+ self::_errorLog(sprintf(_('SetAttribute: Tag "%s": cannot set attribute'),$attribute),2);
+ return FALSE;
+ break;
+ }
+ $this->operation_tags[$attribute]['systag'] = $this->tags_types[$tag_type]['tag'];
+
+ }
+ // }}}
+
+ // {{{ _setPrinterAttribute ($attribute,$value)
+ protected function _setPrinterAttribute ($attribute,$value) {
+ //used by setAttribute
+ $tag_type = $this->printer_tags[$attribute]['tag'];
+ switch ($tag_type) {
+ case 'integer':
+ $this->printer_tags[$attribute]['value'][] = self::_integerBuild($value);
+ break;
+ case 'keyword':
+ case 'naturalLanguage':
+ $this->printer_tags[$attribute]['value'][] = $value;
+ break;
+ default:
+ trigger_error(sprintf(_('SetAttribute: Tag "%s": cannot set attribute'),$attribute),E_USER_NOTICE);
+ self::_putDebug(sprintf(_('SetAttribute: Tag "%s": cannot set attribute'),$attribute),2);
+ self::_errorLog(sprintf(_('SetAttribute: Tag "%s": cannot set attribute'),$attribute),2);
+ return FALSE;
+ break;
+ }
+ $this->printer_tags[$attribute]['systag'] = $this->tags_types[$tag_type]['tag'];
+
+ }
+ // }}}
+// DEBUGGING
+
+ // {{{ _putDebug($string,$level)
+ protected function _putDebug($string,$level=1) {
+ if ($level === false)
+ return;
+ if ($level < $this->debug_level)
+ return;
+ $this->debug[$this->debug_count] = substr($string,0,1024);
+ $this->debug_count ++;
+ //$this->debug .= substr($string,0,1024);
+ }
+ // }}}
+
+// LOGGING
+
+ // {{{ _errorLog($log,$level)
+ protected function _errorLog($string_to_log,$level) {
+
+ if ($level < $this->log_level)
+ return;
+
+ $string = sprintf('%s : %s:%s user %s : %s',
+ basename($_SERVER['PHP_SELF']),
+ $this->host,
+ $this->port,
+ $this->requesting_user,
+ $string_to_log);
+
+ if ($this->log_type == 0) {
+ error_log($string);
+ return;
+ }
+
+ $string = sprintf("%s %s Host %s:%s user %s : %s\n",
+ date('M d H:i:s'),
+ basename($_SERVER['PHP_SELF']),
+ $this->host,
+ $this->port,
+ $this->requesting_user,
+ $string_to_log);
+ error_log($string,$this->log_type,$this->log_destination);
+
+ return;
+ }
+ // }}}
+
+};
+
+/*
+ * Local variables:
+ * mode: php
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
+?>
diff --git a/Moodle/mod/print/CupsPrintIPP.php b/Moodle/mod/print/CupsPrintIPP.php
new file mode 100755
index 0000000..a7e5a30
--- /dev/null
+++ b/Moodle/mod/print/CupsPrintIPP.php
@@ -0,0 +1,671 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
+/* @(#) $Header: /sources/phpprintipp/phpprintipp/php_classes/CupsPrintIPP.php,v 1.1 2008/06/21 00:30:56 harding Exp $
+ *
+ * Class PrintIPP - Send extended IPP requests.
+ *
+ * Copyright (C) 2005-2006 Thomas HARDING
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * mailto:thomas.harding@laposte.net
+ * Thomas Harding, 56 rue de la bourie rouge, 45 000 ORLEANS -- FRANCE
+ *
+ */
+
+/*
+
+ This class is intended to implement Internet Printing Protocol on client side.
+
+ References needed to debug / add functionnalities:
+ - RFC 2910
+ - RFC 2911
+ - RFC 3382
+ - ...
+ - CUPS-IPP-1.1
+*/
+
+require_once("ExtendedPrintIPP.php");
+
+class CupsPrintIPP extends ExtendedPrintIPP {
+
+ // {{{ variables declaration
+
+ public $printers_attributes;
+ public $defaults_attributes;
+
+ // }}}
+
+ // {{{ constructor
+ public function __construct() {
+ parent::__construct();
+ self::_initTags();
+ }
+ // }}}
+
+//
+// OPERATIONS
+//
+
+ // {{{ cupsGetDefaults ($attributes="all")
+ public function cupsGetDefaults($attributes=array("all")) {
+ //The CUPS-Get-Default operation returns the default printer URI and attributes
+
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+ $this->parsed = array();
+ unset($this->printer_attributes);
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en');
+
+ self::_setOperationId();
+
+ for($i = 0 ; $i < count($attributes) ; $i++)
+ if ($i == 0)
+ $this->meta->attributes = chr(0x44) // Keyword
+ . self::_giveMeStringLength('requested-attributes')
+ . 'requested-attributes'
+ . self::_giveMeStringLength($attributes[0])
+ . $attributes[0];
+ else
+ $this->meta->attributes .= chr(0x44) // Keyword
+ . chr(0x0).chr(0x0) // zero-length name
+ . self::_giveMeStringLength($attributes[$i])
+ . $attributes[$i];
+
+ $this->stringjob = chr(0x01) . chr(0x01) // IPP version 1.1
+ . chr(0x40). chr(0x01) // operation: cups vendor extension: get defaults
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . $this->meta->attributes
+ . chr(0x03); // end operations attribute
+
+ $this->output = $this->stringjob;
+
+ self::_putDebug("Request: ".$this->output);
+
+ $post_values = array( "Content-Type" => "application/ipp",
+ "Data" => $this->output);
+
+ if (self::_sendHttp ($post_values,'/')) {
+
+ if(self::_parseServerOutput())
+ self::_parsePrinterAttributes();
+ }
+
+ $this->attributes = &$this->printer_attributes;
+
+ if (isset($this->printer_attributes->printer_type)) {
+ $printer_type = $this->printer_attributes->printer_type->_value0;
+ $table = self::_interpretPrinterType($printer_type);
+
+ for($i = 0 ; $i < count($table) ; $i++ ) {
+ $index = '_value'.$i;
+ $this->printer_attributes->printer_type->$index = $table[$i];
+ }
+
+ }
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog("getting defaults: ".$this->serveroutput->status,3);
+ else
+ self::_errorLog("getting defaults: ".$this->serveroutput->status,1);
+
+ return $this->serveroutput->status;
+
+ } else {
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog("getting defaults : OPERATION FAILED",1);
+ }
+ return false;
+ }
+ // }}}
+
+ // {{{ cupsAcceptJobs ($printer_uri)
+ public function cupsAcceptJobs($printer_uri) {
+ //The CUPS-Get-Default operation returns the default printer URI and attributes
+
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+ $this->parsed = array();
+ unset($this->printer_attributes);
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en');
+
+ self::_setOperationId();
+
+ $this->stringjob = chr(0x01) . chr(0x01) // IPP version 1.1
+ . chr(0x40). chr(0x08) // operation: cups vendor extension: Accept-Jobs
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . chr(0x45) // uri
+ . self::_giveMeStringLength('printer-uri')
+ . 'printer-uri'
+ . self::_giveMeStringLength($printer_uri)
+ . $printer_uri
+ . chr(0x03); // end operations attribute
+
+ $this->output = $this->stringjob;
+
+ self::_putDebug("Request: ".$this->output);
+
+ $post_values = array( "Content-Type" => "application/ipp",
+ "Data" => $this->output);
+
+ if (self::_sendHttp ($post_values,'/admin/')) {
+
+ if(self::_parseServerOutput())
+ self::_parseAttributes();
+ }
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog("getting defaults: ".$this->serveroutput->status,3);
+ else
+ self::_errorLog("getting defaults: ".$this->serveroutput->status,1);
+
+ return $this->serveroutput->status;
+
+ } else {
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog("getting defaults : OPERATION FAILED",1);
+ }
+ return false;
+ }
+ // }}}
+
+ // {{{ cupsRejectJobs ($printer_uri,$printer_state_message=false)
+ public function cupsRejectJobs($printer_uri,$printer_state_message) {
+ //The CUPS-Get-Default operation returns the default printer URI and attributes
+
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+ $this->parsed = array();
+ unset($this->attributes);
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en');
+
+ self::_setOperationId();
+
+ $message = "";
+ if ($printer_state_message)
+ $message = chr(0x04) // start printer-attributes
+ . chr(0x41) // textWithoutLanguage
+ . self::_giveMeStringLength("printer-state-message")
+ . "printer-state-message"
+ . self::_giveMeStringLength($printer_state_message)
+ . $printer_state_message;
+
+ $this->stringjob = chr(0x01) . chr(0x01) // IPP version 1.1
+ . chr(0x40). chr(0x09) // operation: cups vendor extension: Reject-Jobs
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . chr(0x45) // uri
+ . self::_giveMeStringLength('printer-uri')
+ . 'printer-uri'
+ . self::_giveMeStringLength($printer_uri)
+ . $printer_uri
+ . $message
+ . chr(0x03); // end operations attribute
+
+ $this->output = $this->stringjob;
+
+ self::_putDebug("Request: ".$this->output);
+
+ $post_values = array( "Content-Type" => "application/ipp",
+ "Data" => $this->output);
+
+ if (self::_sendHttp ($post_values,'/admin/')) {
+
+ if(self::_parseServerOutput())
+ self::_parseAttributes();
+ }
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog("getting defaults: ".$this->serveroutput->status,3);
+ else
+ self::_errorLog("getting defaults: ".$this->serveroutput->status,1);
+
+ return $this->serveroutput->status;
+
+ } else {
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog("getting defaults : OPERATION FAILED",1);
+ }
+ return false;
+ }
+ // }}}
+
+ // {{{ getPrinters()
+ public function getPrinters($printer_location=false,$printer_info=false,$attributes=array()) {
+
+ if (count($attributes) == 0)
+ true;
+ $attributes=array('printer-uri-supported','printer-location','printer-info','printer-type','color-supported');
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+
+ unset ($this->printers_attributes);
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en-us');
+
+ self::_setOperationId();
+
+ $this->meta->attributes='';
+
+ if ($printer_location)
+ $this->meta->attributes .= chr(0x41) // textWithoutLanguage
+ . self::_giveMeStringLength('printer-location')
+ . 'printer-location'
+ . self::_giveMeStringLength($printer_location)
+ . $printer_location;
+
+
+ if ($printer_info)
+ $this->meta->attributes .= chr(0x41) // textWithoutLanguage
+ . self::_giveMeStringLength('printer-info')
+ . 'printer-info'
+ . self::_giveMeStringLength($printer_info)
+ . $printer_info;
+
+ for($i = 0 ; $i < count($attributes) ; $i++)
+ if ($i == 0)
+ $this->meta->attributes .= chr(0x44) // Keyword
+ . self::_giveMeStringLength('requested-attributes')
+ . 'requested-attributes'
+ . self::_giveMeStringLength($attributes[0])
+ . $attributes[0];
+ else
+ $this->meta->attributes .= chr(0x44) // Keyword
+ . chr(0x0).chr(0x0) // zero-length name
+ . self::_giveMeStringLength($attributes[$i])
+ . $attributes[$i];
+
+
+ $this->stringjob = chr(0x01) . chr(0x01) // IPP version 1.1
+ . chr(0x40). chr(0x02) // operation: cups vendor extension: get printers
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . $this->meta->attributes
+ . chr(0x03); // end operations attribute
+
+ $this->output = $this->stringjob;
+
+ $post_values = array( "Content-Type" => "application/ipp",
+ "Data" => $this->output);
+
+ if (self::_sendHttp ($post_values,'/')) {
+
+ if(self::_parseServerOutput())
+ $this->_getAvailablePrinters();
+
+ }
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog("getting printers: ".$this->serveroutput->status,3);
+ else
+ self::_errorLog("getting printers: ".$this->serveroutput->status,1);
+ return $this->serveroutput->status;
+
+ } else {
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog("getting printers : OPERATION FAILED",1);
+ }
+ return false;
+ }
+ // }}}
+
+ // {{{ cupsGetPrinters ()
+ public function cupsGetPrinters () {
+ // alias for getPrinters();
+ self::getPrinters();
+ }
+ // }}}
+
+ // {{{ getPrinterAttributes()
+ public function getPrinterAttributes() {
+ // complete informations from parent with Cups-specific stuff
+
+ if(!$result = parent::getPrinterAttributes())
+ return FALSE;
+ if(!isset($this->printer_attributes))
+ return FALSE;
+
+ if (isset ($this->printer_attributes->printer_type)) {
+ $printer_type = $this->printer_attributes->printer_type->_value0;
+ $table = self::_interpretPrinterType($printer_type);
+
+ for($i = 0 ; $i < count($table) ; $i++ ) {
+ $index = '_value'.$i;
+ $this->printer_attributes->printer_type->$index = $table[$i];
+ }
+ }
+
+ return $result;
+ }
+ // }}}
+
+//
+// SETUP
+//
+
+ // {{{ _initTags ()
+ protected function _initTags () {
+
+ // override parent with specific cups attributes
+
+ $operation_tags = array ();
+ $this->operation_tags = array_merge ($this->operation_tags, $operation_tags);
+
+ $job_tags = array ( "job-billing" => array("tag" => "textWithoutLanguage"),
+ "blackplot" => array("tag" => "boolean"),
+ "brightness" => array("tag" => "integer"),
+ "columns" => array("tag" => "integer"),
+ "cpi" => array("tag" => "enum"),
+ "fitplot" => array("tag" => "boolean"),
+ "gamma" => array("tag" => "integer"),
+ "hue" => array("tag" => "integer"),
+ "lpi" => array("tag" => "enum"),
+ "mirror" => array("tag","boolean"),
+ "natural-scaling" => array("tag" => "integer"),
+ "number-up-layout" => array("tag" => "keyword"),
+ "page-border" => array("tag" => "keyword"),
+ "page-bottom" => array("tag" => "integer"),
+ "page-label" => array("tag" => "textWithoutLanguage"),
+ "page-left" => array("tag" => "integer"),
+ "page-right" => array("tag" => "integer"),
+ "page-set" => array("tag" => "keyword"),
+ "page-top" => array("tag" => "integer"),
+ "penwidth" => array("tag" => "integer"),
+ "position" => array("tag" => "keyword"),
+ "ppi" => array("tag" => "integer"),
+ "prettyprint" => array("tag","boolean"),
+ "saturation" => array("tag" => "integer"),
+ "scaling" => array("tag" => "integer"),
+ "wrap" => array("tag","boolean"),
+
+ );
+ $this->job_tags = array_merge ($this->job_tags, $job_tags);
+ }
+ // }}}
+
+//
+// REQUEST BUILDING
+//
+
+ // {{{ _enumBuild ($tag,$value)
+ protected function _enumBuild ($tag,$value) {
+
+ $value_built = parent::_enumBuild($tag,$value);
+
+
+ switch ($tag) {
+ case "cpi":
+ switch ($value) {
+ case '10':
+ $value_built = chr(10);
+ break;
+ case '12':
+ $value_built = chr(12);
+ break;
+ case '17':
+ $value_built = chr(17);
+ break;
+ default:
+ $value_built = chr(10);
+ }
+ break;
+ case "lpi":
+ switch ($value) {
+ case '6':
+ $value_built = chr(6);
+ break;
+ case '8':
+ $value_built = chr(8);
+ break;
+ default:
+ $value_built = chr(6);
+ }
+ break;
+ }
+
+ $prepend = '';
+ while ((strlen($value_built) + strlen($prepend)) < 4)
+ $prepend .= chr(0);
+ return $prepend.$value_built;
+ }
+ // }}}
+
+//
+// RESPONSE PARSING
+//
+
+ // {{{ _getAvailablePrinters ()
+ private function _getAvailablePrinters () {
+
+ $this->available_printers = array();
+ $k = 0;
+ $this->printers_attributes = new stdClass();
+
+ for ($i = 0 ; (array_key_exists($i,$this->serveroutput->response)) ; $i ++)
+ if (($this->serveroutput->response[$i]['attributes']) == "printer-attributes") {
+ $phpname = "_printer".$k;
+ $this->printers_attributes->$phpname = new stdClass();
+ for ($j = 0 ; array_key_exists($j,$this->serveroutput->response[$i]) ; $j++) {
+
+ $value = $this->serveroutput->response[$i][$j]['value'];
+ $name = str_replace("-","_",$this->serveroutput->response[$i][$j]['name']);
+
+ switch ($name) {
+ case "printer_uri_supported":
+ $this->available_printers = array_merge($this->available_printers,array($value));
+ break;
+ case "printer_type":
+ $table = self::_interpretPrinterType($value);
+ $this->printers_attributes->$phpname->$name = new stdClass();
+
+ for($l = 0 ; $l < count($table) ; $l++ ) {
+ $index = '_value'.$l;
+ $this->printers_attributes->$phpname->$name->$index = $table[$l];
+ }
+
+ break;
+ case '':
+ break;
+ default:
+ $this->printers_attributes->$phpname->$name = $value;
+ break;
+ }
+
+ }
+ $k ++;
+ }
+ }
+ // }}}
+
+ // {{{ _getEnumVendorExtensions
+ protected function _getEnumVendorExtensions ($value_parsed) {
+ switch ($value_parsed) {
+ case 0x4002:
+ $value = 'Get-Availables-Printers';
+ break;
+ default:
+ $value = sprintf('Unknown(Cups extension for operations): 0x%x',$value_parsed);
+ break;
+ }
+
+ if (isset($value))
+ return ($value);
+
+ return sprintf('Unknown: 0x%x',$value_parsed);
+ }
+ // }}}
+
+ // {{{ _interpretPrinterType($type)
+ private function _interpretPrinterType($value) {
+ $value_parsed = 0;
+ for ($i = strlen($value) ; $i > 0 ; $i --)
+ $value_parsed += pow(256,($i - 1)) * ord($value[strlen($value) - $i]);
+
+ $type[0] = $type[1] = $type[2] = $type[3] = $type[4] = $type[5] = '';
+ $type[6] = $type[7] = $type[8] = $type[9] = $type[10] = '';
+ $type[11] = $type[12] = $type[13] = $type[14] = $type[15] = '';
+ $type[16] = $type[17] = $type[18] = $type[19] = '';
+
+ if ($value_parsed %2 == 1) {
+ $type[0] = 'printer-class';
+ $value_parsed -= 1;
+ }
+ if ($value_parsed %4 == 2 ) {
+ $type[1] = 'remote-destination';
+ $value_parsed -= 2;
+ }
+ if ($value_parsed %8 == 4 ) {
+ $type[2] = 'print-black';
+ $value_parsed -= 4;
+ }
+ if ($value_parsed %16 == 8 ) {
+ $type[3] = 'print-color';
+ $value_parsed -= 8;
+ }
+ if ($value_parsed %32 == 16) {
+ $type[4] = 'hardware-print-on-both-sides';
+ $value_parsed -= 16;
+ }
+ if ($value_parsed %64 == 32) {
+ $type[5] = 'hardware-staple-output';
+ $value_parsed -= 32;
+ }
+ if ($value_parsed %128 == 64) {
+ $type[6] = 'hardware-fast-copies';
+ $value_parsed -= 64;
+ }
+ if ($value_parsed %256 == 128) {
+ $type[7] = 'hardware-fast-copy-collation';
+ $value_parsed -= 128;
+ }
+ if ($value_parsed %512 == 256) {
+ $type[8] = 'punch-output';
+ $value_parsed -= 256;
+ }
+ if ($value_parsed %1024 == 512) {
+ $type[9] = 'cover-output';
+ $value_parsed -= 512;
+ }
+ if ($value_parsed %2048 == 1024) {
+ $type[10] = 'bind-output';
+ $value_parsed -= 1024;
+ }
+ if ($value_parsed %4096 == 2048) {
+ $type[11] = 'sort-output';
+ $value_parsed -= 2048;
+ }
+ if ($value_parsed %8192 == 4096) {
+ $type[12] = 'handle-media-up-to-US-Legal-A4';
+ $value_parsed -= 4096;
+ }
+ if ($value_parsed %16384 == 8192) {
+ $type[13] = 'handle-media-between-US-Legal-A4-and-ISO_C-A2';
+ $value_parsed -= 8192;
+ }
+ if ($value_parsed %32768 == 16384) {
+ $type[14] = 'handle-media-larger-than-ISO_C-A2';
+ $value_parsed -= 16384;
+ }
+ if ($value_parsed %65536 == 32768) {
+ $type[15] = 'handle-user-defined-media-sizes';
+ $value_parsed -= 32768;
+ }
+ if ($value_parsed %131072 == 65536) {
+ $type[16] = 'implicit-server-generated-class';
+ $value_parsed -= 65536;
+ }
+ if ($value_parsed %262144 == 131072) {
+ $type[17] = 'network-default-printer';
+ $value_parsed -= 131072;
+ }
+ if ($value_parsed %524288 == 262144) {
+ $type[18] = 'fax-device';
+ $value_parsed -= 262144;
+ }
+ return $type;
+ }
+ // }}}
+
+ // {{{ _interpretEnum()
+ protected function _interpretEnum($attribute_name,$value) {
+
+ $value_parsed = self::_interpretInteger($value);
+
+ switch ($attribute_name) {
+ case 'cpi':
+ case 'lpi':
+ $value = $value_parsed;
+ break;
+ default:
+ $value = parent::_interpretEnum($attribute_name,$value);
+ break;
+ }
+
+
+ return $value;
+ }
+ // }}}
+
+};
+
+/*
+ * Local variables:
+ * mode: php
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
+?>
diff --git a/Moodle/mod/print/ExtendedPrintIPP.php b/Moodle/mod/print/ExtendedPrintIPP.php
new file mode 100755
index 0000000..e736f4b
--- /dev/null
+++ b/Moodle/mod/print/ExtendedPrintIPP.php
@@ -0,0 +1,1441 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
+/* @(#) $Header: /sources/phpprintipp/phpprintipp/php_classes/ExtendedPrintIPP.php,v 1.1 2008/06/21 00:30:57 harding Exp $
+ *
+ * Class PrintIPP - Send extended IPP requests.
+ *
+ * Copyright (C) 2005-2006 Thomas HARDING
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * mailto:thomas.harding@laposte.net
+ * Thomas Harding, 56 rue de la bourie rouge, 45 000 ORLEANS -- FRANCE
+ *
+ */
+
+/*
+
+ This class is intended to implement non required operations of
+ Internet Printing Protocol on client side.
+
+ References needed to debug / add functionnalities:
+ - RFC 2910
+ - RFC 2911
+ - RFC 3380
+ - RFC 3995
+ - RFC 3996
+ - RFC 3997
+ - RFC 3998
+ - ...
+*/
+
+require_once("PrintIPP.php");
+
+class ExtendedPrintIPP extends PrintIPP {
+
+
+ // {{{ constructor
+ public function __construct() {
+ parent::__construct();
+ }
+ // }}}
+
+
+/******************
+*
+* PUBLIC FUNCTIONS
+*
+*******************/
+
+
+// OPERATIONS
+
+ // {{{ printURI ($uri)
+ public function printURI ($uri) {
+
+ self::_putDebug( sprintf("*************************\nDate: %s\n*************************\n\n",date('Y-m-d H:i:s')));
+
+ if (!empty($uri)) {
+ $this->document_uri = $uri;
+ $this->setup->uri = 1;
+ }
+
+ if(!$this->_stringUri())
+ return FALSE;
+
+ $this->output = $this->stringjob;
+
+ $post_values = array( "Content-Type" => "application/ipp",
+ "Data" => $this->output);
+
+
+ if (self::_sendHttp ($post_values,$this->paths['printers'])) {
+
+ if(self::_parseServerOutput()) {
+ $this->_parseJobAttributes();
+ $this->_getJobId();
+ //$this->_getPrinterUri();
+ $this->_getJobUri();
+ }
+ }
+
+ $this->attributes = &$this->job_attributes;
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog(sprintf("printing uri %s, job %s: ",$uri,$this->last_job)
+ .$this->serveroutput->status,3);
+ else {
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+ self::_errorLog(sprintf("printing uri %s: ",$uri,$this->last_job)
+ .$this->serveroutput->status,1);
+ }
+ return $this->serveroutput->status;
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog("printing uri $uri : OPERATION FAILED",1);
+
+ return false;
+ }
+ // }}}
+
+ // {{{ purgeJobs()
+ public function purgeJobs() {
+
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+
+ self::_setOperationId();
+ $this->parsed = array();
+ unset($this->printer_attributes);
+
+ if (!isset($this->setup->uri)) {
+ $this->getPrinters();
+ unset($this->jobs[count($this->jobs) - 1]);
+ unset($this->jobs_uri[count($this->jobs_uri) - 1]);
+ unset($this->status[count($this->status) - 1]);
+
+ if (array_key_exists(0,$this->available_printers))
+ self::setPrinterURI($this->available_printers[0]);
+ else {
+ trigger_error(_("purgeJobs: Printer URI is not set: die"),E_USER_WARNING);
+ self::_putDebug( _("purgeJobs: Printer URI is not set: die\n"));
+ self::_errorLog("purgeJobs: Printer URI is not set, die",2);
+ return FALSE;
+ }
+ }
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en_us');
+
+ if (!isset($this->meta->username))
+ self::setUserName();
+
+ $this->stringjob = chr(0x01) . chr(0x01) // 1.1 | version-number
+ . chr(0x00) . chr (0x12) // purge-Jobs | operation-id
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . $this->meta->printer_uri
+ . $this->meta->username
+ . chr(0x22)
+ . self::_giveMeStringLength("purge-jobs")
+ . "purge-jobs"
+ . self::_giveMeStringLength(chr(0x01))
+ . chr(0x01)
+ . chr(0x03); // end-of-attributes | end-of-attributes-tag
+
+ self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
+
+ self::_putDebug(sprintf(_("purging jobs of %s\n"),$this->printer_uri));
+
+ $this->output = $this->stringjob;
+
+ $post_values = array( "Content-Type"=>"application/ipp",
+ "Data"=>$this->output);
+
+ if (self::_sendHttp ($post_values,$this->paths['admin'])) {
+ self::_parseServerOutput();
+ self::_parseAttributes();
+ }
+
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog(sprintf(_("purging jobs of %s: "),$this->printer_uri)
+ .$this->serveroutput->status,3);
+ else
+ self::_errorLog(sprintf(_("purging jobs of %s: "),$this->printer_uri)
+ .$this->serveroutput->status,1);
+
+ return $this->serveroutput->status;
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog(date("Y-m-d H:i:s : ")
+ .basename($_SERVER['PHP_SELF'])
+ .sprintf(_("purging jobs of %s : OPERATION FAILED"),
+ $this->printer_uri),3);
+
+ return false;
+ }
+
+ // }}}
+
+ // {{{ createJob()
+ public function createJob() {
+
+
+ self::_setOperationId();
+ $this->parsed = array();
+ unset($this->printer_attributes);
+
+ if (!isset($this->setup->uri)) {
+ $this->getPrinters();
+ unset($this->jobs[count($this->jobs) - 1]);
+ unset($this->jobs_uri[count($this->jobs_uri) - 1]);
+ unset($this->status[count($this->status) - 1]);
+
+ if (array_key_exists(0,$this->available_printers))
+ self::setPrinterURI($this->available_printers[0]);
+ else {
+ trigger_error(_("createJob: Printer URI is not set: die"),E_USER_WARNING);
+ self::_putDebug( _("createJob: Printer URI is not set: die\n"));
+ self::_errorLog("createJob: Printer URI is not set, die",2);
+ return FALSE;
+ }
+ }
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en_us');
+
+ if (!isset($this->meta->username))
+ self::setUserName();
+
+ if (!isset($this->setup->copies))
+ self::setCopies(1);
+
+ if (!isset($this->meta->fidelity))
+ $this->meta->fidelity = '';
+
+ if (!isset($this->meta->sides))
+ $this->meta->sides = '';
+
+ if (!isset($this->meta->page_ranges))
+ $this->meta->page_ranges = '';
+
+ if (!isset($this->setup->jobname))
+ if (is_readable($this->data))
+ self::setJobName(basename($this->data),true);
+ else
+ self::setJobName();
+ unset($this->setup->jobname);
+
+ if (!isset($this->timeout))
+ $this->timeout = 60;
+
+ $timeout = self::_integerBuild($this->timeout);
+
+
+ $this->meta->timeout = chr(0x21) // integer
+ . self::_giveMeStringLength("multiple-operation-time-out")
+ . "multiple-operation-time-out"
+ . self::_giveMeStringLength($timeout)
+ . $timeout;
+
+ $jobattributes = '';
+ $operationattributes = '';
+ $printerattributes = '';
+ self::_buildValues($operationattributes,$jobattributes,$printerattributes);
+
+ $this->stringjob = chr(0x01) . chr(0x01) // 1.1 | version-number
+ . chr(0x00) . chr (0x05) // Create-Job | operation-id
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . $this->meta->printer_uri
+ . $this->meta->username
+ . $this->meta->jobname
+ . $this->meta->fidelity
+ . $this->meta->timeout
+ . $operationattributes
+ . chr(0x02) // start job-attributes | job-attributes-tag
+ . $this->meta->copies
+ . $this->meta->sides
+ . $this->meta->page_ranges
+ . $jobattributes
+ . chr(0x03); // end-of-attributes | end-of-attributes-tag
+
+ unset ($this->meta->copies,$this->meta->sides,$this->meta->page_ranges);
+
+ self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
+
+ self::_putDebug(sprintf(_("creating job %s, printer %s\n"),$this->last_job,$this->printer_uri));
+
+ $this->output = $this->stringjob;
+
+ $post_values = array( "Content-Type"=>"application/ipp",
+ "Data"=>$this->output);
+
+ if (self::_sendHttp ($post_values,$this->paths['printers']))
+ if(self::_parseServerOutput()) {
+ $this->_getJobId();
+ $this->_getJobUri();
+ $this->_parseJobAttributes();
+ } else {
+ $this->jobs = array_merge($this->jobs,array(''));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(''));
+ }
+
+
+
+
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog(sprintf(_("Create job: job %s"),$this->last_job)
+ .$this->serveroutput->status,3);
+ else {
+
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+ self::_errorLog(sprintf(_("Create-Job: %s"),$this->serveroutput->status),1);
+ }
+ return $this->serveroutput->status;
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog(date("Y-m-d H:i:s : ")
+ .basename($_SERVER['PHP_SELF'])
+ .sprintf(_("Creating job on %s : OPERATION FAILED"),
+ $this->printer_uri),3);
+
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+ return false;
+ }
+
+ // }}}
+
+ // {{{ sendDocument($job)
+ public function sendDocument($job,$is_last=false){
+
+ self::_putDebug( sprintf("*************************\nDate: %s\n*************************\n\n",date('Y-m-d H:i:s')));
+
+ if (!$this->_stringDocument($job,$is_last))
+ return FALSE;
+
+ if (is_readable($this->data)){
+ self::_putDebug( _("sending Document\n"));
+
+ $this->output = $this->stringjob;
+
+ if ($this->setup->datatype == "TEXT")
+ $this->output .= chr(0x16); // ASCII "SYN"
+
+
+ $post_values = array( "Content-Type" => "application/ipp",
+ "Data" => $this->output,
+ "File" => $this->data);
+
+ if ($this->setup->datatype == "TEXT" && !isset($this->setup->noFormFeed))
+ $post_values = array_merge($post_values,array("Filetype"=>"TEXT"));
+
+ } else {
+ self::_putDebug( _("sending DATA as document\n"));
+
+ $this->output = $this->stringjob;
+ $this->output .= $this->datahead;
+ $this->output .= $this->data;
+ $this->output .= $this->datatail;
+
+ $post_values = array( "Content-Type" => "application/ipp",
+ "Data" => $this->output);
+
+
+ }
+
+ if (self::_sendHttp ($post_values,$this->paths['printers'])) {
+
+ if(self::_parseServerOutput()) {
+ $this->_getJobId();
+ //$this->_getPrinterUri();
+ $this->_getJobUri();
+ $this->_parseJobAttributes();
+ } else {
+ $this->jobs = array_merge($this->jobs,array($job));
+ $this->jobs_uri = array_merge($this->jobs_uri,array($job));
+ }
+
+ }
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog(sprintf("sending document, job %s: %s",$job,$this->serveroutput->status),3);
+ else {
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+ self::_errorLog(sprintf("sending document, job %s: %s",$job,$this->serveroutput->status),1);
+ }
+ return $this->serveroutput->status;
+
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ $this->jobs = array_merge($this->jobs,array($job));
+ $this->jobs_uri = array_merge($this->jobs_uri,array($job));
+ self::_errorLog(sprintf("sending document, job %s : OPERATION FAILED",$job),1);
+
+ return false;
+ }
+ // }}}
+
+ // {{{ sendURI ($uri,$job,$is_last=false)
+ public function sendURI ($uri,$job,$is_last=false){
+
+ self::_putDebug( sprintf("*************************\nDate: %s\n*************************\n\n",date('Y-m-d H:i:s')));
+
+ if (!$this->_stringSendUri($uri,$job,$is_last))
+ return FALSE;
+
+ self::_putDebug( _("sending URI $uri\n"));
+
+ $this->output = $this->stringjob;
+
+ $post_values = array( "Content-Type" => "application/ipp",
+ "Data" => $this->output);
+
+ if (self::_sendHttp ($post_values,$this->paths['printers'])) {
+
+ if(self::_parseServerOutput()) {
+ $this->_getJobId();
+ //$this->_getPrinterUri();
+ $this->_getJobUri();
+ $this->_parseJobAttributes();
+ } else {
+ $this->jobs = array_merge($this->jobs,array($job));
+ $this->jobs_uri = array_merge($this->jobs_uri,array($job));
+ }
+
+ }
+
+ $this->attributes = &$this->job_attributes;
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog(sprintf("sending uri %s, job %s: %s",$uri,$job,$this->serveroutput->status),3);
+ else {
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+ self::_errorLog(sprintf("sending uri, job %s: %s",$uri,$job,$this->serveroutput->status),1);
+ }
+ return $this->serveroutput->status;
+
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ $this->jobs = array_merge($this->jobs,array($job));
+ $this->jobs_uri = array_merge($this->jobs_uri,array($job));
+ self::_errorLog(sprintf("sending uri %s, job %s : OPERATION FAILED",$uri,$job),1);
+
+ return false;
+ }
+ // }}}
+
+ // {{{ pausePrinter ()
+ public function pausePrinter() {
+
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+
+ self::_setOperationId();
+ $this->parsed = array();
+ unset($this->printer_attributes);
+
+ if (!isset($this->setup->uri)) {
+ $this->getPrinters();
+ unset($this->jobs[count($this->jobs) - 1]);
+ unset($this->jobs_uri[count($this->jobs_uri) - 1]);
+ unset($this->status[count($this->status) - 1]);
+
+ if (array_key_exists(0,$this->available_printers))
+ self::setPrinterURI($this->available_printers[0]);
+ else {
+ trigger_error(_("pausePrinter: Printer URI is not set: die"),E_USER_WARNING);
+ self::_putDebug( _("pausePrinter: Printer URI is not set: die\n"));
+ self::_errorLog("pausePrinter: Printer URI is not set, die",2);
+ return FALSE;
+ }
+ }
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en_us');
+
+ if (!isset($this->meta->username))
+ self::setUserName();
+
+ $this->stringjob = chr(0x01) . chr(0x01) // 1.1 | version-number
+ . chr(0x00) . chr (0x10) // Pause-Printer | operation-id
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . $this->meta->printer_uri
+ . $this->meta->username
+ /* . chr(0x22)
+ . self::_giveMeStringLength("purge-jobs")
+ . "purge-jobs"
+ . self::_giveMeStringLength(chr(0x01))
+ . chr(0x01) */
+ . chr(0x03); // end-of-attributes | end-of-attributes-tag
+
+ self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
+
+ self::_putDebug(sprintf(_("pause printer %s\n"),$this->printer_uri));
+
+ $this->output = $this->stringjob;
+
+ $post_values = array( "Content-Type"=>"application/ipp",
+ "Data"=>$this->output);
+
+ if (self::_sendHttp ($post_values,$this->paths['admin'])) {
+ self::_parseServerOutput();
+ self::_parseAttributes();
+ }
+
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog(sprintf(_("Pause printer %s: "),$this->printer_uri)
+ .$this->serveroutput->status,3);
+ else
+ self::_errorLog(sprintf(_("pause printer %s: "),$this->printer_uri)
+ .$this->serveroutput->status,1);
+
+ return $this->serveroutput->status;
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog(date("Y-m-d H:i:s : ")
+ .basename($_SERVER['PHP_SELF'])
+ .sprintf(_("pause printer %s : OPERATION FAILED"),
+ $this->printer_uri),3);
+
+ return false;
+ }
+ // }}}
+
+ // {{{ resumePrinter ()
+ public function resumePrinter() {
+
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+
+ self::_setOperationId();
+ $this->parsed = array();
+ unset($this->printer_attributes);
+
+ if (!isset($this->setup->uri)) {
+ $this->getPrinters();
+ unset($this->jobs[count($this->jobs) - 1]);
+ unset($this->jobs_uri[count($this->jobs_uri) - 1]);
+ unset($this->status[count($this->status) - 1]);
+
+ if (array_key_exists(0,$this->available_printers))
+ self::setPrinterURI($this->available_printers[0]);
+ else {
+ trigger_error(_("resumePrinter: Printer URI is not set: die"),E_USER_WARNING);
+ self::_putDebug( _("resumePrinter: Printer URI is not set: die\n"));
+ self::_errorLog(" Printer URI is not set, die",2);
+ return FALSE;
+ }
+ }
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en_us');
+
+ if (!isset($this->meta->username))
+ self::setUserName();
+
+ $this->stringjob = chr(0x01) . chr(0x01) // 1.1 | version-number
+ . chr(0x00) . chr (0x11) // suse-Printer | operation-id
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . $this->meta->printer_uri
+ . $this->meta->username
+ . chr(0x03); // end-of-attributes | end-of-attributes-tag
+
+ self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
+
+ self::_putDebug(sprintf(_("resume printer %s\n"),$this->printer_uri));
+
+ $this->output = $this->stringjob;
+
+ $post_values = array( "Content-Type"=>"application/ipp",
+ "Data"=>$this->output);
+
+ if (self::_sendHttp ($post_values,$this->paths['admin'])) {
+ self::_parseServerOutput();
+ self::_parseAttributes();
+ }
+
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog(sprintf(_("resume printer %s: "),$this->printer_uri)
+ .$this->serveroutput->status,3);
+ else
+ self::_errorLog(sprintf(_("resume printer %s: "),$this->printer_uri)
+ .$this->serveroutput->status,1);
+
+ return $this->serveroutput->status;
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog(date("Y-m-d H:i:s : ")
+ .basename($_SERVER['PHP_SELF'])
+ .sprintf(_("resume printer %s : OPERATION FAILED"),
+ $this->printer_uri),3);
+
+ return false;
+ }
+ // }}}
+
+ // {{{ holdJob ($job_uri)
+ public function holdJob ($job_uri,$until='indefinite') {
+
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(trim($job_uri)));
+
+ self::_setOperationId();
+ $this->parsed = array();
+ unset($this->printer_attributes);
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en_us');
+
+ if (!isset($this->meta->username))
+ self::setUserName();
+
+ if (!isset($this->meta->message))
+ $this->meta->message = '';
+
+ self::_setJobUri($job_uri);
+
+ $until_strings = array('no-hold','day-time','evening','night','weekend','second-shift','third-shift');
+ if (in_array($until,$until_strings))
+ true;
+ else
+ $until = 'indefinite';
+
+ $this->meta->job_hold_until = chr(0x42) // keyword
+ . self::_giveMeStringLength('job-hold-until')
+ . 'job-hold-until'
+ . self::_giveMeStringLength($until)
+ . $until;
+
+ $this->stringjob = chr(0x01) . chr(0x01) // 1.1 | version-number
+ . chr(0x00) . chr (0x0C) // Hold-Job | operation-id
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . $this->meta->username
+ . $this->meta->job_uri
+ . $this->meta->message
+ . $this->meta->job_hold_until
+ . chr(0x03); // end-of-attributes | end-of-attributes-tag
+
+ self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
+
+ self::_putDebug(sprintf(_("hold job %s until %s\n"),$job_uri,$until));
+
+ $this->output = $this->stringjob;
+
+ $post_values = array( "Content-Type"=>"application/ipp",
+ "Data"=>$this->output);
+
+ if (self::_sendHttp ($post_values,$this->paths['jobs'])) {
+ self::_parseServerOutput();
+ self::_parseAttributes();
+ }
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog(sprintf(_("hold job %s until %s: "),$job_uri,$until)
+ .$this->serveroutput->status,3);
+ else
+ self::_errorLog(sprintf(_("hold job %s until %s: "),$job_uri,$until)
+ .$this->serveroutput->status,1);
+
+ return $this->serveroutput->status;
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog(date("Y-m-d H:i:s : ")
+ .basename($_SERVER['PHP_SELF'])
+ .sprintf(_("hold job %s until %s : OPERATION FAILED"),
+ $job_uri,$until),3);
+
+ return false;
+ }
+ // }}}
+
+ // {{{ releaseJob ($job_uri)
+ public function releaseJob ($job_uri) {
+
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(trim($job_uri)));
+
+ self::_setOperationId();
+ $this->parsed = array();
+ unset($this->printer_attributes);
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en_us');
+
+ if (!isset($this->meta->username))
+ self::setUserName();
+
+ if (!isset($this->meta->message))
+ $this->meta->message = '';
+
+ self::_setJobUri($job_uri);
+
+ $this->stringjob = chr(0x01) . chr(0x01) // 1.1 | version-number
+ . chr(0x00) . chr (0x0D) // Hold-Job | operation-id
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . $this->meta->job_uri
+ . $this->meta->username
+ . $this->meta->message
+ . chr(0x03); // end-of-attributes | end-of-attributes-tag
+
+ self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
+
+ self::_putDebug(sprintf(_("release job %s\n"),$job_uri));
+
+ $this->output = $this->stringjob;
+
+ $post_values = array( "Content-Type"=>"application/ipp",
+ "Data"=>$this->output);
+
+ if (self::_sendHttp ($post_values,$this->paths['jobs'])) {
+ self::_parseServerOutput();
+ self::_parseAttributes();
+ }
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog(sprintf(_("release job %s: "),$job_uri)
+ .$this->serveroutput->status,3);
+ else
+ self::_errorLog(sprintf(_("release job %s: "),$job_uri)
+ .$this->serveroutput->status,1);
+
+ return $this->serveroutput->status;
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog(date("Y-m-d H:i:s : ")
+ .basename($_SERVER['PHP_SELF'])
+ .sprintf(_("release job %s: OPERATION FAILED"),
+ $job_uri),3);
+
+ return false;
+ }
+ // }}}
+
+ // {{{ restartJob ($job_uri)
+ public function restartJob ($job_uri) {
+
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(trim($job_uri)));
+
+ self::_setOperationId();
+ $this->parsed = array();
+ unset($this->printer_attributes);
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en_us');
+
+ if (!isset($this->meta->username))
+ self::setUserName();
+
+ if (!isset($this->meta->message))
+ $this->meta->message = '';
+
+ self::_setJobUri($job_uri);
+
+
+ $jobattributes = '';
+ $operationattributes = '';
+ $printerattributes = '';
+ self::_buildValues ($operationattributes,$jobattributes,$printerattributes);
+
+
+ $this->stringjob = chr(0x01) . chr(0x01) // 1.1 | version-number
+ . chr(0x00) . chr (0x0E) // Hold-Job | operation-id
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . $this->meta->job_uri
+ . $this->meta->username
+ . $this->meta->message
+ . $jobattributes // job-hold-until is set by setAttribute($attribute,$value)
+ . chr(0x03); // end-of-attributes | end-of-attributes-tag
+
+ self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
+
+ self::_putDebug(sprintf(_("release job %s\n"),$job_uri));
+
+ $this->output = $this->stringjob;
+
+ $post_values = array( "Content-Type"=>"application/ipp",
+ "Data"=>$this->output);
+
+ if (self::_sendHttp ($post_values,$this->paths['jobs'])) {
+ self::_parseServerOutput();
+ self::_parseAttributes();
+ }
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog(sprintf(_("release job %s: "),$job_uri)
+ .$this->serveroutput->status,3);
+ else
+ self::_errorLog(sprintf(_("release job %s: "),$job_uri)
+ .$this->serveroutput->status,1);
+
+ return $this->serveroutput->status;
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog(date("Y-m-d H:i:s : ")
+ .basename($_SERVER['PHP_SELF'])
+ .sprintf(_("release job %s: OPERATION FAILED"),
+ $job_uri),3);
+
+ return false;
+ }
+ // }}}
+
+ // {{{ setJobAttributes ($job_uri,$deleted_attributes=array())
+ public function setJobAttributes ($job_uri,$deleted_attributes=array()) {
+
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(trim($job_uri)));
+
+ self::_setOperationId();
+ $this->parsed = array();
+ unset ($this->attributes);
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en_us');
+
+ if (!isset($this->meta->username))
+ self::setUserName();
+
+ if (!isset($this->meta->message))
+ $this->meta->message = '';
+
+
+ if (!isset($this->meta->copies))
+ $this->meta->copies = '';
+
+ if (!isset($this->meta->sides))
+ $this->meta->sides = '';
+
+ if (!isset($this->meta->page_ranges))
+ $this->meta->page_ranges = '';
+
+ self::_setJobUri($job_uri);
+
+ $operationattributes = '';
+ $jobattributes = '';
+ $printerattributes = '';
+ self::_buildValues ($operationattributes,$jobattributes,$printerattributes);
+
+ $this->meta->deleted_attributes = "";
+ for ($i = 0 ; $i < count($deleted_attributes) ; $i++)
+ $this->meta->deleted_attributes .= chr(0x16) // out-of-band value
+ . self::_giveMeStringLength($deleted_attributes[$i])
+ . $deleted_attributes[$i]
+ . chr(0x0).chr(0x0); // value-length = 0;
+
+
+ $this->stringjob = chr(0x01) . chr(0x01) // 1.1 | version-number
+ . chr(0x00) . chr (0x14) // Set-Job-Attributes | operation-id
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . $this->meta->job_uri
+ . $this->meta->username
+ . $this->meta->message
+ . chr(0x02) // start job-attributes
+ . $jobattributes // setteds by setAttribute($attribute,$value)
+ . $this->meta->copies
+ . $this->meta->sides
+ . $this->meta->page_ranges
+ . $this->meta->deleted_attributes
+ . chr(0x03); // end-of-attributes | end-of-attributes-tag
+
+ self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
+
+ self::_putDebug(sprintf(_("set job attributes for job %s\n"),$job_uri));
+
+ $this->output = $this->stringjob;
+
+ $post_values = array( "Content-Type"=>"application/ipp",
+ "Data"=>$this->output);
+
+ if (self::_sendHttp ($post_values,$this->paths['jobs'])) {
+ self::_parseServerOutput();
+ self::_parseAttributes();
+ }
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog(sprintf(_("set job attributes for job %s: "),$job_uri)
+ .$this->serveroutput->status,3);
+ else
+ self::_errorLog(sprintf(_("set job attributes for job %s: "),$job_uri)
+ .$this->serveroutput->status,1);
+ $this->last_job = $job_uri;
+ $this->jobs_uri[count($this->jobs_uri) - 1] = $job_uri;
+ return $this->serveroutput->status;
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog(date("Y-m-d H:i:s : ")
+ .basename($_SERVER['PHP_SELF'])
+ .sprintf(_("set job attributes for job %s: OPERATION FAILED"),
+ $job_uri),3);
+
+ return false;
+ }
+ // }}}
+
+ // {{{ setPrinterAttributes ()
+ public function setPrinterAttributes ($document_format='',$deleted_attributes=array()) {
+ /* $document_format (RFC 3380)
+ If the client includes this attribute, the Printer MUST change
+ the supplied attributes for the document format specified by
+ this attribute. If a supplied attribute is a member of the
+ "document-format-varying-attributes" (i.e., the attribute
+ varies by document format, see section 6.3), the Printer MUST
+ change the supplied attribute for the document format specified
+ by this attribute, but not for other document formats. If a
+ supplied attribute isn't a member of the "document-format-
+ varying-attributes" (i.e., it doesn't vary by document format),
+ the Printer MUST change the supplied attribute for all document
+ formats.
+
+ If the client omits this attribute, the Printer MUST change the
+ supplied attributes for all document formats, whether or not
+ they vary by document-format.
+ */
+
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+ unset ($this->attributes);
+
+ self::_setOperationId();
+ $this->parsed = array();
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en_us');
+
+ if (!isset($this->meta->username))
+ self::setUserName();
+
+ if (!isset($this->meta->message))
+ $this->meta->message = '';
+
+ if (!isset($this->meta->copies))
+ $this->meta->copies = '';
+
+ if (!isset($this->meta->sides))
+ $this->meta->sides = '';
+
+ if (!isset($this->meta->page_ranges))
+ $this->meta->page_ranges = '';
+
+ if ($document_format)
+ $document_format = chr(0x49) // document-format tag
+ . self::_giveMeStringLength('document-format')
+ . 'document-format' //
+ . self::_giveMeStringLength($document_format)
+ . $document_format; // value
+
+ $operationattributes = '';
+ $jobattributes = '';
+ $printerattributes = '';
+ self::_buildValues ($operationattributes,$jobattributes,$printerattributes);
+
+ $this->meta->deleted_attributes = "";
+ for ($i = 0 ; $i < count($deleted_attributes) ; $i++)
+ $this->meta->deleted_attributes .= chr(0x16) // out-of-band "deleted" value
+ . self::_giveMeStringLength($deleted_attributes[$i])
+ . $deleted_attributes[$i]
+ . chr(0x0).chr(0x0); // value-length = 0;
+
+
+ $this->stringjob = chr(0x01) . chr(0x01) // 1.1 | version-number
+ . chr(0x00) . chr (0x13) // Set-Printer-Attributes | operation-id
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . $this->meta->printer_uri
+ . $this->meta->username
+ . $this->meta->message
+ . $operationattributes
+ . chr(0x02) // start job-attributes
+ . $jobattributes // setteds by setAttribute($attribute,$value)
+ . $this->meta->copies
+ . $this->meta->sides
+ . $this->meta->page_ranges
+ . $this->meta->deleted_attributes
+ . chr(0x03); // end-of-attributes | end-of-attributes-tag
+
+ self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
+
+ self::_putDebug(sprintf(_("set printer attributes for job %s\n"),$this->printer_uri));
+
+ $this->output = $this->stringjob;
+
+ $post_values = array( "Content-Type"=>"application/ipp",
+ "Data"=>$this->output);
+
+ if (self::_sendHttp ($post_values,$this->paths['printers'])) {
+ self::_parseServerOutput();
+ self::_parseAttributes();
+ }
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog(sprintf(_("set printer attributes for printer %s: "),$this->printer_uri)
+ .$this->serveroutput->status,3);
+ else
+ self::_errorLog(sprintf(_("set printer attributes for printer %s: "),$this->printer_uri)
+ .$this->serveroutput->status,1);
+
+ return $this->serveroutput->status;
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog(date("Y-m-d H:i:s : ")
+ .basename($_SERVER['PHP_SELF'])
+ .sprintf(_("set printer attributes for printer %s: OPERATION FAILED"),
+ $this->printer_uri),1);
+
+ return false;
+
+ }
+ // }}}
+
+// REQUEST BUILDING
+
+ // {{{ _setDocumentUri ($job_uri)
+ protected function _setDocumentUri () {
+
+ $this->meta->document_uri = chr(0x45) // type uri
+ . chr(0x00).chr(0x0c) // name-length
+ . "document-uri"
+ . self::_giveMeStringLength($this->document_uri)
+ . $this->document_uri;
+
+ self::_putDebug( "document uri is: ".$this->document_uri."\n");
+ $this->setup->document_uri = 1;
+
+ }
+ // }}}
+
+ // {{{ _stringUri ()
+ protected function _stringUri () {
+
+ self::_setDocumentUri();
+
+ if (!isset($this->setup->document_uri)) {
+ trigger_error(_("_stringUri: Document URI is not set: die"),E_USER_WARNING);
+ self::_putDebug( _("_stringUri: Document URI is not set: die\n"));
+ self::_errorLog("Document URI is not set, die",2);
+ return FALSE;
+ }
+ unset ($this->setup->document_uri);
+
+ if (!isset($this->setup->uri)) {
+ $this->getPrinters();
+ unset($this->jobs[count($this->jobs) - 1]);
+ unset($this->jobs_uri[count($this->jobs) - 1]);
+ unset($this->status[count($this->status) - 1]);
+
+ if (array_key_exists(0,$this->available_printers))
+ self::setPrinterURI($this->available_printers[0]);
+ else {
+ trigger_error(_("_stringUri: Printer URI is not set: die"),E_USER_WARNING);
+ self::_putDebug( _("_stringUri: Printer URI is not set: die\n"));
+ self::_errorLog("_stringUri: Printer URI is not set, die",2);
+ return FALSE;
+ }
+ }
+
+ if (!isset($this->setup->charset))
+ $this->meta->charset = "";
+ // self::setCharset('us-ascii');
+ if (!isset($this->setup->datatype))
+ self::setBinary();
+ if (!isset($this->setup->uri)) {
+ trigger_error(_("_stringUri: Printer URI is not set: die"),E_USER_WARNING);
+ self::_putDebug( _("_stringUri: Printer URI is not set: die\n"));
+ self::_errorLog("Printer URI is not set, die",2);
+ return FALSE;
+ }
+ if (!isset($this->setup->copies))
+ self::setCopies(1);
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en_us');
+
+ if (!isset($this->setup->mime_media_type))
+ self::setMimeMediaType();
+ unset ($this->setup->mime_media_type);
+
+ if (!isset($this->setup->jobname))
+ if (is_readable($this->data))
+ self::setJobName(basename($this->data),true);
+ else
+ self::setJobName();
+ unset($this->setup->jobname);
+
+ if (!isset($this->meta->username))
+ self::setUserName();
+
+ if (!isset($this->meta->fidelity))
+ $this->meta->fidelity = '';
+
+ if (!isset($this->meta->document_name))
+ $this->meta->document_name = '';
+
+ if (!isset($this->meta->sides))
+ $this->meta->sides = '';
+
+ if (!isset($this->meta->page_ranges))
+ $this->meta->page_ranges = '';
+
+ $jobattributes = '';
+ $operationattributes = '';
+ $printerattributes = '';
+ self::_buildValues($operationattributes,$jobattributes,$printerattributes);
+
+ self::_setOperationId();
+
+ if (!isset($this->error_generation->request_body_malformed))
+ $this->error_generation->request_body_malformed = "";
+
+ $this->stringjob = chr(0x01) . chr(0x01) // 1.1 | version-number
+ . chr(0x00) . chr (0x03) // Print-URI | operation-id
+ . $this->meta->operation_id // request-id
+ . $this->error_generation->request_body_malformed
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . $this->meta->printer_uri
+ . $this->meta->jobname
+ . $this->meta->username
+ . $this->meta->fidelity
+ . $this->meta->document_name
+ . $this->meta->document_uri
+ . $operationattributes
+ . chr(0x02) // start job-attributes | job-attributes-tag
+ . $this->meta->copies
+ . $this->meta->sides
+ . $this->meta->page_ranges
+ . $jobattributes
+ . chr(0x03); // end-of-attributes | end-of-attributes-tag
+
+ self::_putDebug( sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
+ return TRUE;
+ }
+ // }}}
+
+ // {{{ _stringDocument ($job,$is_last)
+ protected function _stringDocument ($job,$is_last) {
+
+ if ($is_last == false)
+ $is_last = chr(0x00);
+ else
+ $is_last = chr(0x01);
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+ if (!isset($this->setup->datatype))
+ self::setBinary();
+
+ if (!isset($this->setup->uri)) {
+ $this->getPrinters();
+ unset($this->jobs[count($this->jobs) - 1]);
+ unset($this->jobs_uri[count($this->jobs_uri) - 1]);
+ unset($this->status[count($this->status) - 1]);
+
+ if (array_key_exists(0,$this->available_printers))
+ self::setPrinterURI($this->available_printers[0]);
+ else {
+ trigger_error(_("_stringJob: Printer URI is not set: die"),E_USER_WARNING);
+ self::_putDebug( _("_stringJob: Printer URI is not set: die\n"));
+ self::_errorLog(" Printer URI is not set, die",2);
+ return FALSE;
+ }
+ }
+
+ if (!isset($this->setup->copies))
+ $this->meta->copies = "";
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en_us');
+
+ if (!isset($this->setup->mime_media_type))
+ $this->meta->mime_media_type = "";
+ if ($this->setup->datatype != "TEXT")
+ unset ($this->setup->mime_media_type);
+
+ if (!isset($this->meta->fidelity))
+ $this->meta->fidelity = '';
+
+ if (!isset($this->meta->document_name))
+ $this->meta->document_name = '';
+
+ if (!isset($this->meta->sides))
+ $this->meta->sides = '';
+
+ if (!isset($this->meta->page_ranges))
+ $this->meta->page_ranges = '';
+
+ $operationattributes = '';
+ $jobattributes = '';
+ $printerattributes = '';
+ self::_buildValues($operationattributes,$jobattributes,$printerattributes);
+
+ self::_setOperationId();
+
+
+ $this->stringjob = chr(0x01) . chr(0x01) // 1.1 | version-number
+ . chr(0x00) . chr (0x06) // Send-Document | operation-id
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . chr(0x45) // attribute-type: uri
+ . self::_giveMeStringLength("job-uri")
+ . "job-uri"
+ . self::_giveMeStringLength($job)
+ . $job
+ . $this->meta->username
+ . $this->meta->document_name
+ . $this->meta->fidelity
+ . $this->meta->mime_media_type
+ . $operationattributes
+ . chr(0x22) // boolean
+ . self::_giveMeStringLength("last-document")
+ . "last-document"
+ . self::_giveMeStringLength($is_last)
+ . $is_last
+ . chr(0x03); // end-of-attributes | end-of-attributes-tag
+
+
+ self::_putDebug( sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
+ return TRUE;
+ }
+ // }}}
+
+ // {{{ _stringSendUri ($uri,$job,$is_last)
+ protected function _stringSendUri ($uri,$job,$is_last) {
+
+ $this->document_uri = $uri;
+ self::_setDocumentUri();
+
+ if (!isset($this->setup->document_uri)) {
+ trigger_error(_("_stringUri: Document URI is not set: die"),E_USER_WARNING);
+ self::_putDebug( _("_stringUri: Document URI is not set: die\n"));
+ self::_errorLog("Document URI is not set, die",2);
+ return FALSE;
+ }
+ unset ($this->setup->document_uri);
+
+
+ if ($is_last == false)
+ $is_last = chr(0x00);
+ else
+ $is_last = chr(0x01);
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+ if (!isset($this->setup->datatype))
+ self::setBinary();
+
+ if (!isset($this->setup->uri)) {
+ $this->getPrinters();
+ unset($this->jobs[count($this->jobs) - 1]);
+ unset($this->jobs_uri[count($this->jobs_uri) - 1]);
+ unset($this->status[count($this->status) - 1]);
+
+ if (array_key_exists(0,$this->available_printers))
+ self::setPrinterURI($this->available_printers[0]);
+ else {
+ trigger_error(_("_stringJob: Printer URI is not set: die"),E_USER_WARNING);
+ self::_putDebug( _("_stringJob: Printer URI is not set: die\n"));
+ self::_errorLog(" Printer URI is not set, die",2);
+ return FALSE;
+ }
+ }
+
+ if (!isset($this->setup->copies))
+ $this->meta->copies = "";
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en_us');
+
+ if (!isset($this->setup->mime_media_type))
+ $this->meta->mime_media_type = "";
+ unset ($this->setup->mime_media_type);
+
+ if (!isset($this->meta->fidelity))
+ $this->meta->fidelity = '';
+
+ if (!isset($this->meta->document_name))
+ $this->meta->document_name = '';
+
+ if (!isset($this->meta->sides))
+ $this->meta->sides = '';
+
+ if (!isset($this->meta->page_ranges))
+ $this->meta->page_ranges = '';
+
+ $operationattributes = '';
+ $jobattributes = '';
+ $printerattributes = '';
+ self::_buildValues($operationattributes,$jobattributes,$printerattributes);
+
+ self::_setOperationId();
+
+
+ $this->stringjob = chr(0x01) . chr(0x01) // 1.1 | version-number
+ . chr(0x00) . chr (0x07) // Send-Uri | operation-id
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . chr(0x45) // attribute-type: uri
+ . self::_giveMeStringLength("job-uri")
+ . "job-uri"
+ . self::_giveMeStringLength($job)
+ . $job
+ . $this->meta->username
+ . $this->meta->document_uri
+ . $this->meta->fidelity
+ . $this->meta->mime_media_type
+ . $operationattributes
+ . chr(0x22) // boolean
+ . self::_giveMeStringLength("last-document")
+ . "last-document"
+ . self::_giveMeStringLength($is_last)
+ . $is_last
+ . chr(0x03); // end-of-attributes | end-of-attributes-tag
+
+
+ self::_putDebug( sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
+ return TRUE;
+ }
+ // }}}
+
+};
+
+/*
+ * Local variables:
+ * mode: php
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
+?>
diff --git a/Moodle/mod/print/PrintIPP.php b/Moodle/mod/print/PrintIPP.php
new file mode 100755
index 0000000..7a2ce93
--- /dev/null
+++ b/Moodle/mod/print/PrintIPP.php
@@ -0,0 +1,1875 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
+ /* @(#) $Header: /sources/phpprintipp/phpprintipp/php_classes/PrintIPP.php,v 1.1 2008/06/21 00:30:57 harding Exp $
+ *
+ * Class PrintIPP - Send IPP requests, Get and parses IPP Responses.
+ *
+ * Copyright (C) 2005-2006 Thomas HARDING
+ * Parts Copyright (C) 2005-2006 Manuel Lemos
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * mailto:thomas.harding@laposte.net
+ * Thomas Harding, 56 rue de la bourie rouge, 45 000 ORLEANS -- FRANCE
+ *
+ */
+
+/*
+
+ This class is intended to implement Internet Printing Protocol on client side.
+
+ References needed to debug / add functionnalities:
+ - RFC 2910
+ - RFC 2911
+ - RFC 3380
+ - RFC 3382
+*/
+/*
+ TODO: beta tests on other servers than Cups
+*/
+
+
+ // {{{ required and included files
+
+ require_once("BasicIPP.php");
+
+ // }}}
+
+
+class PrintIPP extends BasicIPP {
+
+ // {{{ constructor
+ public function __construct() {
+ parent::__construct();
+ }
+ // }}}
+
+/*****************
+*
+* PUBLIC FUNCTIONS
+*
+*******************/
+// SETTINGS
+
+// OPERATIONS
+
+ // {{{ printJob()
+ public function printJob(){
+
+ self::_putDebug( sprintf("*************************\nDate: %s\n*************************\n\n",date('Y-m-d H:i:s')));
+
+ if (!$this->_stringJob())
+ return FALSE;
+
+ if (is_readable($this->data)){
+ self::_putDebug( _("Printing a FILE\n"),3);
+
+ $this->output = $this->stringjob;
+
+ if ($this->setup->datatype == "TEXT")
+ $this->output .= chr(0x16);
+
+
+ $post_values = array( "Content-Type" => "application/ipp",
+ "Data" => $this->output,
+ "File" => $this->data);
+
+ if ($this->setup->datatype == "TEXT" && !isset($this->setup->noFormFeed))
+ $post_values = array_merge($post_values,array("Filetype"=>"TEXT"));
+
+ } else {
+ self::_putDebug( _("Printing DATA\n"),3);
+
+ $this->output = $this->stringjob;
+ $this->output .= $this->datahead;
+ $this->output .= $this->data;
+ $this->output .= $this->datatail;
+
+ $post_values = array( "Content-Type" => "application/ipp",
+ "Data" => $this->output);
+
+
+ }
+
+ if (self::_sendHttp ($post_values,$this->paths['printers'])) {
+
+ if(self::_parseServerOutput()) {
+ $this->_getJobId();
+ $this->_getJobUri();
+ $this->_parseJobAttributes();
+ } else {
+ $this->jobs = array_merge($this->jobs,array(''));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(''));
+ }
+
+ }
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+
+ if ($this->serveroutput->status == "successfull-ok")
+ {
+ self::_errorLog(sprintf("printing job %s: ",$this->last_job) .$this->serveroutput->status,3);
+ }
+ else
+ {
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+ self::_errorLog(sprintf("printing job: ",$this->last_job) .$this->serveroutput->status,1);
+ if ($this->with_exceptions)
+ {
+ throw new ippException(sprintf("job status: %s",
+ $this->serveroutput->status));
+ }
+ }
+ return $this->serveroutput->status;
+
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+ self::_errorLog("printing job : OPERATION FAILED",1);
+
+ return false;
+ }
+ // }}}
+
+ // {{{ cancelJob ($job_uri)
+ public function cancelJob ($job_uri) {
+
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+
+ self::_putDebug( sprintf("*************************\nDate: %s\n*************************\n\n",date('Y-m-d H:i:s')));
+
+ if (!$this->_stringCancel($job_uri))
+ return FALSE;
+
+ self::_putDebug( _("Cancelling Job $job_uri\n"),3);
+
+ $this->output = $this->stringjob;
+
+ $post_values = array( "Content-Type"=>"application/ipp",
+ "Data"=>$this->output);
+
+ if (self::_sendHttp ($post_values,$this->paths['jobs']))
+ self::_parseServerOutput();
+
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog("cancelling job $job_uri: ".$this->serveroutput->status,3);
+ else
+ self::_errorLog("cancelling job $job_uri: ".$this->serveroutput->status,1);
+ return $this->serveroutput->status;
+
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog("cancelling job : OPERATION FAILED",3);
+
+ return false;
+ }
+ // }}}
+
+ // {{{ validateJob ()
+ public function validateJob () {
+
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+
+ $this->serveroutput->response = '';
+
+ self::_putDebug( sprintf("*************************\nDate: %s\n*************************\n\n",date('Y-m-d H:i:s')));
+
+
+ self::_putDebug( _("Validate Job\n"),2);
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+ if (!isset($this->setup->datatype))
+ self::setBinary();
+
+ if (!isset($this->setup->uri)) {
+ $this->getPrinters();
+ unset($this->jobs[count($this->jobs) - 1]);
+ unset($this->jobs_uri[count($this->jobs_uri) - 1]);
+ unset($this->status[count($this->status) - 1]);
+
+ if (array_key_exists(0,$this->available_printers))
+ self::setPrinterURI($this->available_printers[0]);
+ else {
+ trigger_error(_("_stringJob: Printer URI is not set: die"),E_USER_WARNING);
+ self::_putDebug( _("_stringJob: Printer URI is not set: die\n"),3);
+ self::_errorLog(" Printer URI is not set, die",2);
+ return FALSE;
+ }
+ }
+
+ if (!isset($this->meta->copies))
+ self::setCopies(1);
+ if (!isset($this->setup->copies))
+ self::setCopies(1);
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en_us');
+
+ if (!isset($this->setup->mime_media_type))
+ self::setMimeMediaType();
+ if ($this->setup->datatype != "TEXT")
+ unset ($this->setup->mime_media_type);
+
+ if (!isset($this->setup->jobname))
+ if (is_readable($this->data))
+ self::setJobName(basename($this->data),true);
+ else
+ self::setJobName();
+ unset($this->setup->jobname);
+
+ if (!isset($this->meta->username))
+ self::setUserName();
+
+ if (!isset($this->meta->fidelity))
+ $this->meta->fidelity = '';
+
+ if (!isset($this->meta->document_name))
+ $this->meta->document_name = '';
+
+ if (!isset($this->meta->sides))
+ $this->meta->sides = '';
+
+ if (!isset($this->meta->page_ranges))
+ $this->meta->page_ranges = '';
+
+ $jobattributes = '';
+ $operationattributes = '';
+ $printerattributes = '';
+ self::_buildValues ($operationattributes,$jobattributes,$printerattributes);
+
+ self::_setOperationId();
+
+ $this->stringjob = chr(0x01) . chr(0x01) // 1.1 | version-number
+ . chr(0x00) . chr (0x04) // Validate-Job | operation-id
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . $this->meta->printer_uri
+ . $this->meta->username
+ . $this->meta->jobname
+ . $this->meta->fidelity
+ . $this->meta->document_name
+ . $this->meta->mime_media_type
+ . $operationattributes
+ . chr(0x02) // start job-attributes | job-attributes-tag
+ . $this->meta->copies
+ . $this->meta->sides
+ . $this->meta->page_ranges
+ . $jobattributes
+ . chr(0x03); // end-of-attributes | end-of-attributes-tag
+
+
+ self::_putDebug( sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
+
+ $this->output = $this->stringjob;
+
+ $post_values = array( "Content-Type"=>"application/ipp",
+ "Data"=>$this->output);
+
+ if (self::_sendHttp ($post_values,$this->paths['printers']))
+ if(self::_parseServerOutput())
+ self::_parseAttributes();
+
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog("validate job: ".$this->serveroutput->status,3);
+ else
+ self::_errorLog("validate job: ".$this->serveroutput->status,1);
+
+ return $this->serveroutput->status;
+
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog("validate job : OPERATION FAILED",3);
+
+ return false;
+ }
+ // }}}
+
+ // {{{ getPrinterAttributes()
+ public function getPrinterAttributes() {
+
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+
+ $jobattributes = '';
+ $operationattributes = '';
+ self::_buildValues($operationattributes,$jobattributes,$printerattributes);
+ self::_setOperationId();
+ $this->parsed = array();
+ unset($this->printer_attributes);
+
+ if (!isset($this->setup->uri)) {
+ $this->getPrinters();
+ unset($this->jobs[count($this->jobs) - 1]);
+ unset($this->jobs_uri[count($this->jobs_uri) - 1]);
+ unset($this->status[count($this->status) - 1]);
+
+ if (array_key_exists(0,$this->available_printers))
+ self::setPrinterURI($this->available_printers[0]);
+ else {
+ trigger_error(_("_stringJob: Printer URI is not set: die"),E_USER_WARNING);
+ self::_putDebug( _("_stringJob: Printer URI is not set: die\n"),3);
+ self::_errorLog(" Printer URI is not set, die",2);
+ return FALSE;
+ }
+ }
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en_us');
+
+ if (!isset($this->meta->username))
+ self::setUserName();
+
+ $this->stringjob = chr(0x01) . chr(0x01) // 1.1 | version-number
+ . chr(0x00) . chr (0x0b) // Print-URI | operation-id
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . $this->meta->printer_uri
+ . $this->meta->username
+ . $printerattributes
+ . chr(0x03); // end-of-attributes | end-of-attributes-tag
+
+ self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
+
+ self::_putDebug(sprintf(_("Getting printer attributes of %s\n"),$this->printer_uri),2);
+
+ $this->output = $this->stringjob;
+
+ $post_values = array( "Content-Type"=>"application/ipp",
+ "Data"=>$this->output);
+
+ if (self::_sendHttp ($post_values,$this->paths['root']))
+ if (self::_parseServerOutput())
+ self::_parsePrinterAttributes();
+
+ $this->attributes = &$this->printer_attributes;
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog(sprintf(_("getting printer attributes of %s: %s"),$this->printer_uri,
+ $this->serveroutput->status),3);
+ else
+ self::_errorLog(sprintf(_("getting printer attributes of %s: %s"),$this->printer_uri,
+ $this->serveroutput->status),1);
+
+ return $this->serveroutput->status;
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog(date("Y-m-d H:i:s : ")
+ .basename($_SERVER['PHP_SELF'])
+ .sprintf(_("getting printer's attributes of %s : OPERATION FAILED"),
+ $this->printer_uri),3);
+
+ return false;
+ }
+ // }}}
+
+ // {{{ getJobs ($my_jobs=true,$limit=0,$which_jobs="");
+ public function getJobs($my_jobs=true,$limit=0,$which_jobs="not-completed",$subset=false) {
+
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+
+ self::_setOperationId();
+ $this->parsed = array();
+ unset($this->printer_attributes);
+
+ if (!isset($this->setup->uri)) {
+ $this->getPrinters();
+ unset($this->jobs[count($this->jobs) - 1]);
+ unset($this->jobs_uri[count($this->jobs_uri) - 1]);
+ unset($this->status[count($this->status) - 1]);
+
+ if (array_key_exists(0,$this->available_printers))
+ self::setPrinterURI($this->available_printers[0]);
+ else {
+ trigger_error(_("getJobs: Printer URI is not set: die"),E_USER_WARNING);
+ self::_putDebug( _("_stringJob: Printer URI is not set: die\n"),3);
+ self::_errorLog("getJobs: Printer URI is not set, die",2);
+ return FALSE;
+ }
+ }
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en_us');
+
+ if (!isset($this->meta->username))
+ self::setUserName();
+
+ if ($limit) {
+ $limit = self::_integerBuild($limit);
+ $this->meta->limit = chr(0x21) // integer
+ . self::_giveMeStringLength('limit')
+ . 'limit'
+ . self::_giveMeStringLength($limit)
+ . $limit;
+ } else
+ $this->meta->limit = '';
+
+ if ($which_jobs == 'completed')
+ $this->meta->which_jobs = chr(0x44) // keyword
+ . self::_giveMeStringLength('which-jobs')
+ . 'which-jobs'
+ . self::_giveMeStringLength($which_jobs)
+ . $which_jobs;
+ else
+ $this->meta->which_jobs = "";
+
+ if ($my_jobs)
+ $this->meta->my_jobs = chr(0x22) // boolean
+ . self::_giveMeStringLength('my-jobs')
+ . 'my-jobs'
+ . self::_giveMeStringLength(chr(0x01))
+ . chr(0x01);
+ else
+ $this->meta->my_jobs = '';
+
+ $this->stringjob = chr(0x01) . chr(0x01) // 1.1 | version-number
+ . chr(0x00) . chr (0x0A) // Get-Jobs | operation-id
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . $this->meta->printer_uri
+ . $this->meta->username
+ . $this->meta->limit
+ . $this->meta->which_jobs
+ . $this->meta->my_jobs
+ ;
+ if ($subset)
+ $this->stringjob .=
+ chr(0x44) // keyword
+ . self::_giveMeStringLength('requested-attributes')
+ . 'requested-attributes'
+ . self::_giveMeStringLength('job-uri')
+ . 'job-uri'
+ . chr(0x44) // keyword
+ . self::_giveMeStringLength('')
+ . ''
+ . self::_giveMeStringLength('job-name')
+ . 'job-name'
+ . chr(0x44) // keyword
+ . self::_giveMeStringLength('')
+ . ''
+ . self::_giveMeStringLength('job-state')
+ . 'job-state'
+ . chr(0x44) // keyword
+ . self::_giveMeStringLength('')
+ . ''
+ . self::_giveMeStringLength('job-state-reason')
+ . 'job-state-reason'
+ ;
+ $this->stringjob .= chr(0x03); // end-of-attributes | end-of-attributes-tag
+
+ self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
+
+ self::_putDebug(sprintf(_("getting jobs of %s\n"),$this->printer_uri),2);
+
+ $this->output = $this->stringjob;
+
+ $post_values = array( "Content-Type"=>"application/ipp",
+ "Data"=>$this->output);
+
+ if (self::_sendHttp ($post_values,$this->paths['jobs']))
+ if (self::_parseServerOutput())
+ self::_parseJobsAttributes();
+
+ $this->attributes = &$this->jobs_attributes;
+
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog(sprintf(_("getting jobs of printer %s: "),$this->printer_uri)
+ .$this->serveroutput->status,3);
+ else
+ self::_errorLog(sprintf(_("getting jobs of printer %s: "),$this->printer_uri)
+ .$this->serveroutput->status,1);
+
+ return $this->serveroutput->status;
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog(date("Y-m-d H:i:s : ")
+ .basename($_SERVER['PHP_SELF'])
+ .sprintf(_("getting jobs of %s : OPERATION FAILED"),
+ $this->printer_uri),3);
+
+ return false;
+ }
+ // }}}
+
+ // {{{ getJobAttributes ($job_uri,subset="false",$attributes_group="all");
+ public function getJobAttributes($job_uri,$subset=false,$attributes_group="all") {
+
+ $this->jobs = array_merge($this->jobs,array(""));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(""));
+
+ if (!$job_uri) {
+ trigger_error(_("getJobAttributes: Job URI is not set, die."));
+ return FALSE;
+ }
+
+ self::_setOperationId();
+ $this->parsed = array();
+ unset($this->printer_attributes);
+
+ if (!isset($this->setup->uri)) {
+ $this->getPrinters();
+ unset($this->jobs[count($this->jobs) - 1]);
+ unset($this->jobs_uri[count($this->jobs_uri) - 1]);
+ unset($this->status[count($this->status) - 1]);
+
+ if (array_key_exists(0,$this->available_printers))
+ self::setPrinterURI($this->available_printers[0]);
+ else {
+ trigger_error(_("getJobs: Printer URI is not set: die"),E_USER_WARNING);
+ self::_putDebug( _("_stringJob: Printer URI is not set: die\n"),3);
+ self::_errorLog("getJobs: Printer URI is not set, die",2);
+ return FALSE;
+ }
+ }
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+
+ if (!isset($this->setup->language))
+ self::setLanguage('en_us');
+
+ if (!isset($this->meta->username))
+ self::setUserName();
+
+ $this->meta->job_uri = chr(0x45) // URI
+ . self::_giveMeStringLength('job-uri')
+ . 'job-uri'
+ . self::_giveMeStringLength($job_uri)
+ . $job_uri;
+
+ $this->stringjob = chr(0x01) . chr(0x01) // 1.1 | version-number
+ . chr(0x00) . chr (0x09) // Get-Job-Attributes | operation-id
+ . $this->meta->operation_id // request-id
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . $this->meta->job_uri
+ . $this->meta->username
+ ;
+ if ($subset)
+ $this->stringjob .=
+ chr(0x44) // keyword
+ . self::_giveMeStringLength('requested-attributes')
+ . 'requested-attributes'
+ . self::_giveMeStringLength('job-uri')
+ . 'job-uri'
+ . chr(0x44) // keyword
+ . self::_giveMeStringLength('')
+ . ''
+ . self::_giveMeStringLength('job-name')
+ . 'job-name'
+ . chr(0x44) // keyword
+ . self::_giveMeStringLength('')
+ . ''
+ . self::_giveMeStringLength('job-state')
+ . 'job-state'
+ . chr(0x44) // keyword
+ . self::_giveMeStringLength('')
+ . ''
+ . self::_giveMeStringLength('job-state-reason')
+ . 'job-state-reason'
+ ;
+ elseif($attributes_group) {
+ switch($attributes_group) {
+ case 'job-template':
+ break;
+ case 'job-description':
+ break;
+ case 'all':
+ break;
+ default:
+ trigger_error(_('not a valid attribute group: ').$attributes_group,E_USER_NOTICE);
+ $attributes_group = '';
+ break;
+ }
+ $this->stringjob .=
+ chr(0x44) // keyword
+ . self::_giveMeStringLength('requested-attributes')
+ . 'requested-attributes'
+ . self::_giveMeStringLength($attributes_group)
+ . $attributes_group;
+ }
+ $this->stringjob .= chr(0x03); // end-of-attributes | end-of-attributes-tag
+
+ self::_putDebug(sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
+
+ self::_putDebug(sprintf(_("getting jobs of %s\n"),$this->printer_uri),2);
+
+ $this->output = $this->stringjob;
+
+ $post_values = array( "Content-Type"=>"application/ipp",
+ "Data"=>$this->output);
+
+ if (self::_sendHttp ($post_values,$this->paths['jobs']))
+ if (self::_parseServerOutput())
+ self::_parseJobAttributes();
+
+ $this->attributes = &$this->job_attributes;
+
+ if (isset($this->serveroutput) && isset($this->serveroutput->status)) {
+
+ $this->status = array_merge($this->status,array($this->serveroutput->status));
+
+ if ($this->serveroutput->status == "successfull-ok")
+ self::_errorLog(sprintf(_("getting job attributes for %s: "),$job_uri)
+ .$this->serveroutput->status,3);
+ else
+ self::_errorLog(sprintf(_("getting job attributes for %s: "),$job_uri)
+ .$this->serveroutput->status,1);
+
+ return $this->serveroutput->status;
+ }
+
+ $this->status = array_merge($this->status,array("OPERATION FAILED"));
+ self::_errorLog(date("Y-m-d H:i:s : ")
+ .basename($_SERVER['PHP_SELF'])
+ .sprintf(_("getting jobs attributes of %s : OPERATION FAILED"),
+ $job_uri),3);
+
+ return false;
+ }
+
+ // }}}
+
+ // {{{ getPrinters();
+ public function getPrinters() {
+
+ // placeholder for vendor extension operation (getAvailablePrinters for CUPS)
+ $this->jobs = array_merge($this->jobs,array(''));
+ $this->jobs_uri = array_merge($this->jobs_uri,array(''));
+ $this->status = array_merge($this->status,array(''));
+ }
+ // }}}
+
+/******************
+*
+* DEVELOPPEMENT FUNCTIONS
+*
+*******************/
+
+ // {{{ generateError($error)
+ public function generateError ($error) {
+ switch ($error) {
+ case "request_body_malformed":
+ $this->error_generation->request_body_malformed = chr(0xFF);
+ break;
+ default:
+ true;
+ break;
+ }
+ // }}}
+
+ // {{{ resetError ($error)
+ trigger_error(sprintf(_('Setting Error %s'),$error),E_USER_NOTICE);
+ }
+
+ public function resetError ($error) {
+ unset ($this->error_generation->$error);
+ trigger_error(sprintf(_('Reset Error %s'),$error),E_USER_NOTICE);
+ }
+ // }}}
+
+/******************
+*
+* PROTECTED FUNCTIONS
+*
+*******************/
+
+// SETUP
+
+ // {{{ _setOperationId ()
+ protected function _setOperationId () {
+ $prepend = '';
+ $this->operation_id += 1;
+ $this->meta->operation_id = self::_integerBuild($this->operation_id);
+ self::_putDebug( "operation id is: ".$this->operation_id."\n",2);
+ }
+ // }}}
+
+ // {{{ _setJobId()
+ protected function _setJobId() {
+
+ $this->meta->jobid +=1;
+ $prepend = '';
+ $prepend_length = 4 - strlen($this->meta->jobid);
+ for ($i = 0; $i < $prepend_length ; $i++ )
+ $prepend .= '0';
+
+ return $prepend.$this->meta->jobid;
+ }
+ // }}}
+
+ // {{{ _setJobUri ($job_uri)
+ protected function _setJobUri ($job_uri) {
+
+ $this->meta->job_uri = chr(0x45) // type uri
+ . chr(0x00).chr(0x07) // name-length
+ . "job-uri"
+ //. chr(0x00).chr(strlen($job_uri))
+ . self::_giveMeStringLength($job_uri)
+ . $job_uri;
+
+ self::_putDebug( "job-uri is: ".$job_uri."\n",2);
+ }
+ // }}}
+
+// RESPONSE PARSING
+
+ // {{{ _parsePrinterAttributes()
+ protected function _parsePrinterAttributes() {
+
+ //if (!preg_match('#successful#',$this->serveroutput->status))
+ // return false;
+
+ $k = -1;
+ for ($i = 0 ; $i < count($this->serveroutput->response) ; $i++)
+ for ($j = 0 ; $j < (count($this->serveroutput->response[$i]) - 1) ; $j ++)
+ if (!empty($this->serveroutput->response[$i][$j]['name'])) {
+ $k++;
+ $l = 0;
+ $this->parsed[$k]['range'] = $this->serveroutput->response[$i]['attributes'];
+ $this->parsed[$k]['name'] = $this->serveroutput->response[$i][$j]['name'];
+ $this->parsed[$k]['type'] = $this->serveroutput->response[$i][$j]['type'];
+ $this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
+ } else {
+ $l ++;
+ $this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
+ }
+ $this->serveroutput->response = array();
+
+ $this->printer_attributes = new stdClass();
+ for ($i = 0 ; $i < count($this->parsed) ; $i ++) {
+ $name = $this->parsed[$i]['name'];
+ $php_name = str_replace('-','_',$name);
+ $type = $this->parsed[$i]['type'];
+ $range = $this->parsed[$i]['range'];
+ $this->printer_attributes->$php_name = new stdClass();
+ $this->printer_attributes->$php_name->_type = $type;
+ $this->printer_attributes->$php_name->_range = $range;
+ for ($j = 0 ; $j < (count($this->parsed[$i]) - 3) ; $j ++) {
+ $value = $this->parsed[$i][$j];
+ $index = '_value'.$j;
+ $this->printer_attributes->$php_name->$index = $value;
+ }
+ }
+
+ $this->parsed = array();
+
+
+ }
+ // }}}
+
+ // {{{ _parseJobsAttributes()
+ protected function _parseJobsAttributes() {
+
+ //if ($this->serveroutput->status != "successfull-ok")
+ // return false;
+
+ $job = -1;
+ for ($i = 0 ; $i < count($this->serveroutput->response) ; $i++) {
+ if ($this->serveroutput->response[$i]['attributes'] == "job-attributes")
+ $job ++;
+ $k = -1;
+ for ($j = 0 ; $j < (count($this->serveroutput->response[$i]) - 1) ; $j ++)
+ if (!empty($this->serveroutput->response[$i][$j]['name'])) {
+ $k++;
+ $l = 0;
+ $this->parsed[$job][$k]['range'] = $this->serveroutput->response[$i]['attributes'];
+ $this->parsed[$job][$k]['name'] = $this->serveroutput->response[$i][$j]['name'];
+ $this->parsed[$job][$k]['type'] = $this->serveroutput->response[$i][$j]['type'];
+ $this->parsed[$job][$k][$l] = $this->serveroutput->response[$i][$j]['value'];
+ } else {
+ $l ++;
+ $this->parsed[$job][$k][$l] = $this->serveroutput->response[$i][$j]['value'];
+ }
+ }
+
+ $this->serveroutput->response = array();
+ $this->jobs_attributes = new stdClass();
+ for ($job_nbr = 0 ; $job_nbr <= $job ; $job_nbr ++) {
+ $job_index = "job_".$job_nbr;
+ $this->jobs_attributes->$job_index = new stdClass();
+ for ($i = 0 ; $i < count($this->parsed[$job_nbr]) ; $i ++) {
+ $name = $this->parsed[$job_nbr][$i]['name'];
+ $php_name = str_replace('-','_',$name);
+ $type = $this->parsed[$job_nbr][$i]['type'];
+ $range = $this->parsed[$job_nbr][$i]['range'];
+ $this->jobs_attributes->$job_index->$php_name = new stdClass();
+ $this->jobs_attributes->$job_index->$php_name->_type = $type;
+ $this->jobs_attributes->$job_index->$php_name->_range = $range;
+ for ($j = 0 ; $j < (count($this->parsed[$job_nbr][$i]) - 3) ; $j ++) {
+ $value = self::_interpretAttribute($name,$type,$this->parsed[$job_nbr][$i][$j]);
+ $index = '_value'.$j;
+ $this->jobs_attributes->$job_index->$php_name->$index = $value;
+ }
+ }
+ }
+
+ $this->parsed = array();
+
+
+ }
+ // }}}
+
+ // {{{ _readAttribute($attributes_type,$ji,&$collection=false)
+ protected function _readAttribute($attributes_type) {
+
+ $tag = ord($this->serveroutput->body[$this->_parsing->offset]);
+
+ $this->_parsing->offset += 1;
+ $j = $this->index;
+
+ $tag = self::_readTag($tag);
+
+ switch ($tag) {
+ case "begCollection": //RFC3382 (BLIND CODE)
+ if ($this->end_collection)
+ $this->index --;
+ $this->end_collection = false;
+ $this->serveroutput->response[$attributes_type][$j]['type'] = "collection";
+ self::_putDebug( "tag is: begCollection\n");
+ self::_readAttributeName ($attributes_type,$j);
+ if (!$this->serveroutput->response[$attributes_type][$j]['name']) { // it is a multi-valued collection
+ $this->collection_depth ++;
+ $this->index --;
+ $this->collection_nbr[$this->collection_depth] ++;
+ } else {
+ $this->collection_depth ++;
+ if ($this->collection_depth == 0)
+ $this->collection = (object) 'collection';
+ if (array_key_exists($this->collection_depth,$this->collection_nbr))
+ $this->collection_nbr[$this->collection_depth] ++;
+ else
+ $this->collection_nbr[$this->collection_depth] = 0;
+ unset($this->end_collection);
+
+ }
+ self::_readValue ("begCollection",$attributes_type,$j);
+ break;
+ case "endCollection": //RFC3382 (BLIND CODE)
+ $this->serveroutput->response[$attributes_type][$j]['type'] = "collection";
+ self::_putDebug( "tag is: endCollection\n");
+ self::_readAttributeName ($attributes_type,$j,0);
+ self::_readValue ('name',$attributes_type,$j,0);
+ $this->collection_depth --;
+ $this->collection_key[$this->collection_depth] = 0;
+ $this->end_collection = true;
+ break;
+ case "memberAttrName": // RFC3382 (BLIND CODE)
+ $this->serveroutput->response[$attributes_type][$j]['type'] = "memberAttrName";
+ $this->index -- ;
+ self::_putDebug( "tag is: memberAttrName\n");
+ self::_readCollection ($attributes_type,$j);
+ break;
+
+ default:
+ $this->collection_depth = -1;
+ $this->collection_key = array();
+ $this->collection_nbr = array();
+ $this->serveroutput->response[$attributes_type][$j]['type'] = $tag;
+ self::_putDebug( "tag is: $tag\n");
+ $attribute_name = self::_readAttributeName ($attributes_type,$j);
+ if (!$attribute_name)
+ $attribute_name = $this->attribute_name;
+ else
+ $this->attribute_name = $attribute_name;
+ $value = self::_readValue ($tag,$attributes_type,$j);
+ $this->serveroutput->response[$attributes_type][$j]['value'] =
+ self::_interpretAttribute($attribute_name,$tag,$this->serveroutput->response[$attributes_type][$j]['value']);
+ break;
+
+ }
+ return;
+ }
+ // }}}
+
+ // {{{ _readTag($tag)
+ protected function _readTag($tag) {
+
+ switch ($tag) {
+ case 0x10:
+ $tag = "unsupported";
+ break;
+ case 0x11:
+ $tag = "reserved for 'default'";
+ break;
+ case 0x12:
+ $tag = "unknown";
+ break;
+ case 0x13:
+ $tag = "no-value";
+ break;
+ case 0x15: // RFC 3380
+ $tag = "not-settable";
+ break;
+ case 0x16: // RFC 3380
+ $tag = "delete-attribute";
+ break;
+ case 0x17: // RFC 3380
+ $tag = "admin-define";
+ break;
+ case 0x20:
+ $tag = "IETF reserved (generic integer)";
+ break;
+ case 0x21:
+ $tag = "integer";
+ break;
+ case 0x22:
+ $tag = "boolean";
+ break;
+ case 0x23:
+ $tag = "enum";
+ break;
+ case 0x30:
+ $tag = "octetString";
+ break;
+ case 0x31:
+ $tag = "datetime";
+ break;
+ case 0x32:
+ $tag = "resolution";
+ break;
+ case 0x33:
+ $tag = "rangeOfInteger";
+ break;
+ case 0x34: //RFC3382 (BLIND CODE)
+ $tag = "begCollection";
+ break;
+ case 0x35:
+ $tag = "textWithLanguage";
+ break;
+ case 0x36:
+ $tag = "nameWithLanguage";
+ break;
+ case 0x37: //RFC3382 (BLIND CODE)
+ $tag = "endCollection";
+ break;
+ case 0x40:
+ $tag = "IETF reserved text string";
+ break;
+ case 0x41:
+ $tag = "textWithoutLanguage";
+ break;
+ case 0x42:
+ $tag = "nameWithoutLanguage";
+ break;
+ case 0x43:
+ $tag = "IETF reserved for future";
+ break;
+ case 0x44:
+ $tag = "keyword";
+ break;
+ case 0x45:
+ $tag = "uri";
+ break;
+ case 0x46:
+ $tag = "uriScheme";
+ break;
+ case 0x47:
+ $tag = "charset";
+ break;
+ case 0x48:
+ $tag = "naturalLanguage";
+ break;
+ case 0x49:
+ $tag = "mimeMediaType";
+ break;
+ case 0x4A: // RFC3382 (BLIND CODE)
+ $tag = "memberAttrName";
+ break;
+ case 0x7F:
+ $tag = "extended type";
+ break;
+ default:
+
+ if ($tag >= 0x14 && $tag < 0x15 && $tag > 0x17 && $tag <= 0x1f)
+ $tag = "out-of-band";
+ elseif (0x24 <= $tag && $tag <= 0x2f)
+ $tag = "new integer type";
+ elseif (0x38 <= $tag && $tag <= 0x3F)
+ $tag = "new octet-stream type";
+ elseif (0x4B <= $tag && $tag <= 0x5F)
+ $tag = "new character string type";
+ elseif ((0x60 <= $tag && $tag < 0x7f) || $tag >= 0x80 )
+ $tag = "IETF reserved for future";
+ else
+ $tag = sprintf("UNKNOWN: 0x%x (%u)",$tag,$tag);
+
+ break;
+ }
+ return $tag;
+ }
+ // }}}
+
+ // {{{ _readCollection($attributes_type,$j,&$collection)
+ protected function _readCollection($attributes_type,$j) {
+
+ $name_length = ord($this->serveroutput->body[$this->_parsing->offset]) * 256
+ + ord($this->serveroutput->body[$this->_parsing->offset + 1]);
+
+ $this->_parsing->offset += 2;
+
+ self::_putDebug( "Collection name_length ". $name_length ."\n");
+
+ $name = '';
+ for ($i = 0; $i < $name_length; $i++) {
+ $name .= $this->serveroutput->body[$this->_parsing->offset];
+ $this->_parsing->offset += 1;
+ if ($this->_parsing->offset > strlen($this->serveroutput->body))
+ return;
+ }
+
+ $collection_name = $name;
+
+ $name_length = ord($this->serveroutput->body[$this->_parsing->offset]) * 256
+ + ord($this->serveroutput->body[$this->_parsing->offset + 1]);
+ $this->_parsing->offset += 2;
+
+ self::_putDebug( "Attribute name_length ". $name_length ."\n");
+
+ $name = '';
+ for ($i = 0; $i < $name_length; $i++) {
+ $name .= $this->serveroutput->body[$this->_parsing->offset];
+ $this->_parsing->offset += 1;
+ if ($this->_parsing->offset > strlen($this->serveroutput->body))
+ return;
+ }
+
+ $attribute_name = $name;
+ if ($attribute_name == "") {
+ $attribute_name = $this->last_attribute_name;
+ $this->collection_key[$this->collection_depth] ++;
+ } else {
+ $this->collection_key[$this->collection_depth] = 0;
+ }
+ $this->last_attribute_name = $attribute_name;
+
+ self::_putDebug( "Attribute name ".$name."\n");
+
+ $tag = self::_readTag(ord($this->serveroutput->body[$this->_parsing->offset]));
+ $this->_parsing->offset ++;
+
+ $type = $tag;
+
+ $name_length = ord($this->serveroutput->body[$this->_parsing->offset]) * 256
+ + ord($this->serveroutput->body[$this->_parsing->offset + 1]);
+ $this->_parsing->offset += 2;
+
+ self::_putDebug( "Collection2 name_length ". $name_length ."\n");
+
+ $name = '';
+ for ($i = 0; $i < $name_length; $i++) {
+ $name .= $this->serveroutput->body[$this->_parsing->offset];
+ $this->_parsing->offset += 1;
+ if ($this->_parsing->offset > strlen($this->serveroutput->body))
+ return;
+ }
+
+ $collection_value = $name;
+ $value_length = ord($this->serveroutput->body[$this->_parsing->offset]) * 256
+ + ord($this->serveroutput->body[$this->_parsing->offset + 1]);
+
+ self::_putDebug( "Collection value_length ".$this->serveroutput->body[ $this->_parsing->offset]
+ . $this->serveroutput->body[$this->_parsing->offset + 1]
+ .": "
+ . $value_length
+ . " ");
+
+ $this->_parsing->offset += 2;
+
+ $value = '';
+ for ($i = 0; $i < $value_length; $i++) {
+
+ if ($this->_parsing->offset >= strlen($this->serveroutput->body))
+ return;
+ $value .= $this->serveroutput->body[$this->_parsing->offset];
+ $this->_parsing->offset += 1;
+
+ }
+
+ $object = &$this->collection;
+ for ($i = 0 ; $i <= $this->collection_depth ; $i ++) {
+ $indice = "_indice".$this->collection_nbr[$i];
+ if (!isset($object->$indice))
+ $object->$indice = (object) 'indice';
+ $object = &$object->$indice;
+ }
+
+ $value_key = "_value".$this->collection_key[$this->collection_depth];
+ $col_name_key = "_collection_name".$this->collection_key[$this->collection_depth];
+ $col_val_key = "_collection_value".$this->collection_key[$this->collection_depth];
+
+ $attribute_value = self::_interpretAttribute($attribute_name,$tag,$value);
+ $attribute_name = str_replace('-','_',$attribute_name);
+
+
+ self::_putDebug( sprintf("Value: %s\n",$value));
+ $object->$attribute_name->_type = $type;
+ $object->$attribute_name->$value_key = $attribute_value;
+ $object->$attribute_name->$col_name_key = $collection_name;
+ $object->$attribute_name->$col_val_key = $collection_value;
+
+ $this->serveroutput->response[$attributes_type][$j]['value'] = $this->collection;
+ }
+ // }}}
+
+ // {{{ _readAttributeName ($attributes_type,$j)
+ protected function _readAttributeName ($attributes_type,$j,$write=1) {
+
+ $name_length = ord($this->serveroutput->body[ $this->_parsing->offset]) * 256
+ + ord($this->serveroutput->body[$this->_parsing->offset + 1]);
+ $this->_parsing->offset += 2;
+
+ self::_putDebug( "name_length ". $name_length ."\n");
+
+ $name = '';
+ for ($i = 0; $i < $name_length; $i++) {
+ if ($this->_parsing->offset >= strlen($this->serveroutput->body))
+ return;
+ $name .= $this->serveroutput->body[$this->_parsing->offset];
+ $this->_parsing->offset += 1;
+ }
+
+ if($write)
+ $this->serveroutput->response[$attributes_type][$j]['name'] = $name;
+
+ self::_putDebug( "name " . $name . "\n");
+
+ return $name;
+ }
+ // }}}
+
+ // {{{ _readValue ($type,$attributes_type,$j)
+ protected function _readValue ($type,$attributes_type,$j,$write=1) {
+
+ $value_length = ord($this->serveroutput->body[$this->_parsing->offset]) * 256
+ + ord($this->serveroutput->body[$this->_parsing->offset + 1]);
+
+ self::_putDebug( "value_length ".$this->serveroutput->body[ $this->_parsing->offset]
+ . $this->serveroutput->body[$this->_parsing->offset + 1]
+ .": "
+ . $value_length
+ . " ");
+
+ $this->_parsing->offset += 2;
+
+ $value = '';
+ for ($i = 0; $i < $value_length; $i++) {
+
+ if ($this->_parsing->offset >= strlen($this->serveroutput->body))
+ return;
+ $value .= $this->serveroutput->body[$this->_parsing->offset];
+ $this->_parsing->offset += 1;
+
+ }
+
+ self::_putDebug( sprintf("Value: %s\n",$value));
+
+ if ($write)
+ $this->serveroutput->response[$attributes_type][$j]['value'] = $value;
+
+ return $value;
+ }
+ // }}}
+
+ // {{{ _parseAttributes()
+ protected function _parseAttributes() {
+
+ $k = -1;
+ for ($i = 0 ; $i < count($this->serveroutput->response) ; $i++)
+ for ($j = 0 ; $j < (count($this->serveroutput->response[$i]) - 1) ; $j ++)
+ if (!empty($this->serveroutput->response[$i][$j]['name'])) {
+ $k++;
+ $l = 0;
+ $this->parsed[$k]['range'] = $this->serveroutput->response[$i]['attributes'];
+ $this->parsed[$k]['name'] = $this->serveroutput->response[$i][$j]['name'];
+ $this->parsed[$k]['type'] = $this->serveroutput->response[$i][$j]['type'];
+ $this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
+ } else {
+ $l ++;
+ $this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
+ }
+ $this->serveroutput->response = array();
+ $this->attributes = new stdClass();
+ for ($i = 0 ; $i < count($this->parsed) ; $i ++) {
+ $name = $this->parsed[$i]['name'];
+ $php_name = str_replace('-','_',$name);
+ $type = $this->parsed[$i]['type'];
+ $range = $this->parsed[$i]['range'];
+ $this->attributes->$php_name = new stdClass();
+ $this->attributes->$php_name->_type = $type;
+ $this->attributes->$php_name->_range = $range;
+ for ($j = 0 ; $j < (count($this->parsed[$i]) - 3) ; $j ++) {
+ $value = $this->parsed[$i][$j];
+ $index = '_value'.$j;
+ $this->attributes->$php_name->$index = $value;
+ }
+ }
+
+ $this->parsed = array();
+
+ }
+ // }}}
+
+ // {{{ _parseJobAttributes()
+ protected function _parseJobAttributes() {
+
+ //if (!preg_match('#successful#',$this->serveroutput->status))
+ // return false;
+
+ $k = -1;
+ for ($i = 0 ; $i < count($this->serveroutput->response) ; $i++)
+ for ($j = 0 ; $j < (count($this->serveroutput->response[$i]) - 1) ; $j ++)
+ if (!empty($this->serveroutput->response[$i][$j]['name'])) {
+ $k++;
+ $l = 0;
+ $this->parsed[$k]['range'] = $this->serveroutput->response[$i]['attributes'];
+ $this->parsed[$k]['name'] = $this->serveroutput->response[$i][$j]['name'];
+ $this->parsed[$k]['type'] = $this->serveroutput->response[$i][$j]['type'];
+ $this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
+ } else {
+ $l ++;
+ $this->parsed[$k][$l] = $this->serveroutput->response[$i][$j]['value'];
+ }
+
+ $this->serveroutput->response = array();
+
+ $this->job_attributes = new stdClass();
+ for ($i = 0 ; $i < count($this->parsed) ; $i ++) {
+ $name = $this->parsed[$i]['name'];
+ $php_name = str_replace('-','_',$name);
+ $type = $this->parsed[$i]['type'];
+ $range = $this->parsed[$i]['range'];
+ $this->job_attributes->$php_name = new stdClass();
+ $this->job_attributes->$php_name->_type = $type;
+ $this->job_attributes->$php_name->_range = $range;
+ for ($j = 0 ; $j < (count($this->parsed[$i]) - 3) ; $j ++) {
+ $value = $this->parsed[$i][$j];
+ $index = '_value'.$j;
+ $this->job_attributes->$php_name->$index = $value;
+ }
+ }
+
+ $this->parsed = array();
+
+
+ }
+ // }}}
+
+ // {{{ _interpretAttribute($attribute_name,$type,$value)
+ protected function _interpretAttribute($attribute_name,$type,$value) {
+
+ switch ($type) {
+ case "integer":
+ $value = self::_interpretInteger($value);
+ break;
+ case "rangeOfInteger":
+ $value = self::_interpretRangeOfInteger($value);
+ break;
+ case 'boolean':
+ $value = ord($value);
+ if ($value == 0x00)
+ $value = 'false';
+ else
+ $value = 'true';
+ break;
+ case 'datetime':
+ $value = self::_interpretDateTime($value);
+ break;
+ case 'enum':
+ $value = $this->_interpretEnum($attribute_name,$value); // must be overwritten by children
+ break;
+ case 'resolution':
+ $unit = $value[8];
+ $value = self::_interpretRangeOfInteger(substr($value,0,8));
+ switch($unit) {
+ case chr(0x03):
+ $unit = "dpi";
+ break;
+ case chr(0x04):
+ $unit = "dpc";
+ break;
+ }
+ $value = $value." ".$unit;
+ break;
+ default:
+ break;
+ }
+ return $value;
+ }
+ // }}}
+
+ // {{{ _interpretRangeOfInteger($value)
+ protected function _interpretRangeOfInteger($value) {
+
+ $value_parsed = 0;
+ $integer1 = $integer2 = 0;
+
+ $halfsize = strlen($value) / 2;
+
+ $integer1 = self::_interpretInteger(substr($value,0,$halfsize));
+ $integer2 = self::_interpretInteger(substr($value,$halfsize,$halfsize));
+
+ $value_parsed = sprintf('%s-%s',$integer1,$integer2);
+
+
+ return $value_parsed;
+ }
+ // }}}
+
+ // {{{ _interpretDateTime($date) {
+ protected function _interpretDateTime($date) {
+ $year = self::_interpretInteger(substr($date,0,2));
+ $month = self::_interpretInteger(substr($date,2,1));
+ $day = self::_interpretInteger(substr($date,3,1));
+ $hour = self::_interpretInteger(substr($date,4,1));
+ $minute = self::_interpretInteger(substr($date,5,1));
+ $second = self::_interpretInteger(substr($date,6,1));
+ $direction = substr($date,8,1);
+ $hours_from_utc = self::_interpretInteger(substr($date,9,1));
+ $minutes_from_utc = self::_interpretInteger(substr($date,10,1));
+
+ $date = sprintf('%s-%s-%s %s:%s:%s %s%s:%s',$year,$month,$day,$hour,$minute,$second,$direction,$hours_from_utc,$minutes_from_utc);
+
+ return $date;
+ }
+ // }}}
+
+ // {{{ _interpretEnum()
+ protected function _interpretEnum($attribute_name,$value) {
+
+ $value_parsed = self::_interpretInteger($value);
+
+ switch ($attribute_name) {
+ case 'job-state':
+ switch ($value_parsed) {
+ case 0x03:
+ $value = 'pending';
+ break;
+ case 0x04:
+ $value = 'pending-held';
+ break;
+ case 0x05:
+ $value = 'processing';
+ break;
+ case 0x06:
+ $value = 'processing-stopped';
+ break;
+ case 0x07:
+ $value = 'canceled';
+ break;
+ case 0x08:
+ $value = 'aborted';
+ break;
+ case 0x09:
+ $value = 'completed';
+ break;
+ }
+ if ($value_parsed > 0x09)
+ $value = sprintf('Unknown(IETF standards track "job-state" reserved): 0x%x',$value_parsed);
+ break;
+ case 'print-quality':
+ case 'print-quality-supported':
+ case 'print-quality-default':
+ switch ($value_parsed) {
+ case 0x03:
+ $value = 'draft';
+ break;
+ case 0x04:
+ $value = 'normal';
+ break;
+ case 0x05:
+ $value = 'high';
+ break;
+ }
+ break;
+ case 'printer-state':
+ switch ($value_parsed) {
+ case 0x03:
+ $value = 'idle';
+ break;
+ case 0x04:
+ $value = 'processing';
+ break;
+ case 0x05:
+ $value = 'stopped';
+ break;
+ }
+ if ($value_parsed > 0x05)
+ $value = sprintf('Unknown(IETF standards track "printer-state" reserved): 0x%x',$value_parsed);
+ break;
+
+ case 'operations-supported':
+ switch($value_parsed) {
+ case 0x0000:
+ case 0x0001:
+ $value = sprintf('Unknown(reserved) : %s',ord($value));
+ break;
+ case 0x0002:
+ $value = 'Print-Job';
+ break;
+ case 0x0003:
+ $value = 'Print-URI';
+ break;
+ case 0x0004:
+ $value = 'Validate-Job';
+ break;
+ case 0x0005:
+ $value = 'Create-Job';
+ break;
+ case 0x0006:
+ $value = 'Send-Document';
+ break;
+ case 0x0007:
+ $value = 'Send-URI';
+ break;
+ case 0x0008:
+ $value = 'Cancel-Job';
+ break;
+ case 0x0009:
+ $value = 'Get-Job-Attributes';
+ break;
+ case 0x000A:
+ $value = 'Get-Jobs';
+ break;
+ case 0x000B:
+ $value = 'Get-Printer-Attributes';
+ break;
+ case 0x000C:
+ $value = 'Hold-Job';
+ break;
+ case 0x000D:
+ $value = 'Release-Job';
+ break;
+ case 0x000E:
+ $value = 'Restart-Job';
+ break;
+ case 0x000F:
+ $value = 'Unknown(reserved for a future operation)';
+ break;
+ case 0x0010:
+ $value = 'Pause-Printer';
+ break;
+ case 0x0011:
+ $value = 'Resume-Printer';
+ break;
+ case 0x0012:
+ $value = 'Purge-Jobs';
+ break;
+ case 0x0013:
+ $value = 'Set-Printer-Attributes'; // RFC3380
+ break;
+ case 0x0014:
+ $value = 'Set-Job-Attributes'; // RFC3380
+ break;
+ case 0x0015:
+ $value = 'Get-Printer-Supported-Values'; // RFC3380
+ break;
+ case 0x0016:
+ $value = 'Create-Printer-Subscriptions';
+ break;
+ case 0x0017:
+ $value = 'Create-Job-Subscriptions';
+ break;
+ case 0x0018:
+ $value = 'Get-Subscription-Attributes';
+ break;
+ case 0x0019:
+ $value = 'Get-Subscriptions';
+ break;
+ case 0x001A:
+ $value = 'Renew-Subscription';
+ break;
+ case 0x001B:
+ $value = 'Cancel-Subscription';
+ break;
+ case 0x001C:
+ $value = 'Get-Notifications';
+ break;
+ case 0x001D:
+ $value = sprintf('Unknown (reserved IETF "operations"): 0x%x',ord($value));
+ break;
+ case 0x001E:
+ $value = sprintf('Unknown (reserved IETF "operations"): 0x%x',ord($value));
+ break;
+ case 0x001F:
+ $value = sprintf('Unknown (reserved IETF "operations"): 0x%x',ord($value));
+ break;
+ case 0x0020:
+ $value = sprintf('Unknown (reserved IETF "operations"): 0x%x',ord($value));
+ break;
+ case 0x0021:
+ $value = sprintf('Unknown (reserved IETF "operations"): 0x%x',ord($value));
+ break;
+ case 0x0022:
+ $value = 'Enable-Printer';
+ break;
+ case 0x0023:
+ $value = 'Disable-Printer';
+ break;
+ case 0x0024:
+ $value = 'Pause-Printer-After-Current-Job';
+ break;
+ case 0x0025:
+ $value = 'Hold-New-Jobs';
+ break;
+ case 0x0026:
+ $value = 'Release-Held-New-Jobs';
+ break;
+ case 0x0027:
+ $value = 'Deactivate-Printer';
+ break;
+ case 0x0028:
+ $value = 'Activate-Printer';
+ break;
+ case 0x0029:
+ $value = 'Restart-Printer';
+ break;
+ case 0x002A:
+ $value = 'Shutdown-Printer';
+ break;
+ case 0x002B:
+ $value = 'Startup-Printer';
+ break;
+ }
+ if ($value_parsed > 0x002B && $value_parsed <= 0x3FFF)
+ $value = sprintf('Unknown(IETF standards track operations reserved): 0x%x',$value_parsed);
+ elseif ($value_parsed >= 0x4000 && $value_parsed <= 0x8FFF) {
+ if (method_exists($this,'_getEnumVendorExtensions')) {
+ $value = $this->_getEnumVendorExtensions($value_parsed);
+ } else
+ $value = sprintf('Unknown(Vendor extension for operations): 0x%x',$value_parsed);
+ } elseif ($value_parsed > 0x8FFF)
+ $value = sprintf('Unknown operation (should not exists): 0x%x',$value_parsed);
+
+ break;
+ case 'finishings':
+ case 'finishings-default':
+ case 'finishings-supported':
+ switch ($value_parsed) {
+ case 3:
+ $value = 'none';
+ break;
+ case 4:
+ $value = 'staple';
+ break;
+ case 5:
+ $value = 'punch';
+ break;
+ case 6:
+ $value = 'cover';
+ break;
+ case 7:
+ $value = 'bind';
+ break;
+ case 8:
+ $value = 'saddle-stitch';
+ break;
+ case 9:
+ $value = 'edge-stitch';
+ break;
+ case 20:
+ $value = 'staple-top-left';
+ break;
+ case 21:
+ $value = 'staple-bottom-left';
+ break;
+ case 22:
+ $value = 'staple-top-right';
+ break;
+ case 23:
+ $value = 'staple-bottom-right';
+ break;
+ case 24:
+ $value = 'edge-stitch-left';
+ break;
+ case 25:
+ $value = 'edge-stitch-top';
+ break;
+ case 26:
+ $value = 'edge-stitch-right';
+ break;
+ case 27:
+ $value = 'edge-stitch-bottom';
+ break;
+ case 28:
+ $value = 'staple-dual-left';
+ break;
+ case 29:
+ $value = 'staple-dual-top';
+ break;
+ case 30:
+ $value = 'staple-dual-right';
+ break;
+ case 31:
+ $value = 'staple-dual-bottom';
+ break;
+ }
+ if ($value_parsed > 31)
+ $value = sprintf('Unknown(IETF standards track "finishing" reserved): 0x%x',$value_parsed);
+ break;
+
+ case 'orientation-requested':
+ case 'orientation-requested-supported':
+ case 'orientation-requested-default':
+ switch ($value_parsed) {
+ case 0x03:
+ $value = 'portrait';
+ break;
+ case 0x04:
+ $value = 'landscape';
+ break;
+ case 0x05:
+ $value = 'reverse-landscape';
+ break;
+ case 0x06:
+ $value = 'reverse-portrait';
+ break;
+ }
+ if ($value_parsed > 0x06)
+ $value = sprintf('Unknown(IETF standards track "orientation" reserved): 0x%x',$value_parsed);
+ break;
+
+ default:
+ break;
+ }
+ return $value;
+ }
+ // }}}
+
+ // {{{ _getJobId ()
+ protected function _getJobId () {
+
+ if (!isset($this->serveroutput->response))
+ $this->jobs = array_merge($this->jobs,array('NO JOB'));
+
+ $jobfinded = false;
+ for ($i = 0 ; (!$jobfinded && array_key_exists($i,$this->serveroutput->response)) ; $i ++)
+ if (($this->serveroutput->response[$i]['attributes']) == "job-attributes")
+ for ($j = 0 ; array_key_exists($j,$this->serveroutput->response[$i]) ; $j++)
+ if ($this->serveroutput->response[$i][$j]['name'] == "job-id") {
+ $this->last_job = $this->serveroutput->response[$i][$j]['value'];
+ $this->jobs = array_merge($this->jobs,array($this->serveroutput->response[$i][$j]['value']));
+ return;
+
+ }
+
+ }
+ // }}}
+
+ // {{{ _getJobUri ()
+ protected function _getJobUri () {
+
+ if (!isset($this->jobs_uri))
+ $this->jobs_uri = array();
+
+ $jobfinded = false;
+ for ($i = 0 ; (!$jobfinded && array_key_exists($i,$this->serveroutput->response)) ; $i ++)
+ if (($this->serveroutput->response[$i]['attributes']) == "job-attributes")
+ for ($j = 0 ; array_key_exists($j,$this->serveroutput->response[$i]) ; $j++)
+ if ($this->serveroutput->response[$i][$j]['name'] == "job-uri") {
+ $this->last_job = $this->serveroutput->response[$i][$j]['value'];
+ $this->jobs_uri = array_merge($this->jobs_uri,array($this->last_job));
+ return;
+
+ }
+ $this->last_job = '';
+
+ }
+ // }}}
+
+ // {{{ _parseResponse ()
+ protected function _parseResponse () {
+ $j = -1;
+ $this->index = 0;
+ for ($i = $this->_parsing->offset; $i < strlen($this->serveroutput->body) ; $i = $this->_parsing->offset) {
+
+
+ $tag = ord($this->serveroutput->body[$this->_parsing->offset]);
+
+
+ if ($tag > 0x0F) {
+
+ self::_readAttribute($j);
+ $this->index ++;
+ continue;
+ }
+
+ switch ($tag) {
+ case 0x01:
+ $j += 1;
+ $this->serveroutput->response[$j]['attributes'] = "operation-attributes";
+ $this->index = 0;
+ $this->_parsing->offset += 1;
+ break;
+ case 0x02:
+ $j += 1;
+ $this->serveroutput->response[$j]['attributes'] = "job-attributes";
+ $this->index = 0;
+ $this->_parsing->offset += 1;
+ break;
+ case 0x03:
+ $j +=1;
+ $this->serveroutput->response[$j]['attributes'] = "end-of-attributes";
+ self::_putDebug( "tag is: ".$this->serveroutput->response[$j]['attributes']."\n");
+ if ($this->alert_on_end_tag === 1)
+ echo "END tag OK<br />";
+ $this->response_completed[(count($this->response_completed) -1)] = "completed";
+ return;
+ case 0x04:
+ $j += 1;
+ $this->serveroutput->response[$j]['attributes'] = "printer-attributes";
+ $this->index = 0;
+ $this->_parsing->offset += 1;
+ break;
+ case 0x05:
+ $j += 1;
+ $this->serveroutput->response[$j]['attributes'] = "unsupported-attributes";
+ $this->index = 0;
+ $this->_parsing->offset += 1;
+ break;
+ default:
+ $j += 1;
+ $this->serveroutput->response[$j]['attributes'] = sprintf(_("0x%x (%u) : attributes tag Unknown (reserved for future versions of IPP"),$tag,$tag);
+ $this->index = 0;
+ $this->_parsing->offset += 1;
+ break;
+ }
+
+ self::_putDebug( "tag is: ".$this->serveroutput->response[$j]['attributes']."\n\n\n");
+
+ }
+ return;
+ }
+ // }}}
+
+
+
+
+ /*
+ // NOTICE : HAVE TO READ AGAIN RFC 2911 TO SEE IF IT IS PART OF SERVER'S RESPONSE (CUPS DO NOT)
+ // {{{ _getPrinterUri ()
+ protected function _getPrinterUri () {
+
+ for ($i = 0 ; (array_key_exists($i,$this->serveroutput->response)) ; $i ++)
+ if (($this->serveroutput->response[$i]['attributes']) == "job-attributes")
+ for ($j = 0 ; array_key_exists($j,$this->serveroutput->response[$i]) ; $j++)
+ if ($this->serveroutput->response[$i][$j]['name'] == "printer-uri") {
+ $this->printers_uri = array_merge($this->printers_uri,array($this->serveroutput->response[$i][$j]['value']));
+
+ return;
+
+ }
+
+ $this->printers_uri = array_merge($this->printers_uri,array(''));
+
+ }
+ // }}}
+ */
+
+// REQUEST BUILDING
+
+ // {{{ _stringCancel ()
+ protected function _stringCancel ($job_uri) {
+
+ if (!isset($this->setup->charset))
+ self::setCharset('us-ascii');
+ if (!isset($this->setup->datatype))
+ self::setBinary();
+ if (!isset($this->setup->language))
+ self::setLanguage('en_us');
+ if (!$this->requesting_user)
+ self::setUserName();
+ if (!isset($this->meta->message))
+ $this->meta->message = '';
+
+ self::_setOperationId();
+
+ self::_setJobUri($job_uri);
+
+ if (!isset($this->error_generation->request_body_malformed))
+ $this->error_generation->request_body_malformed = "";
+
+ $this->stringjob = chr(0x01) . chr(0x01) // 1.1 | version-number
+ . chr(0x00) . chr (0x08) // cancel-Job | operation-id
+ . $this->meta->operation_id // request-id
+ . $this->error_generation->request_body_malformed
+ . chr(0x01) // start operation-attributes | operation-attributes-tag
+ . $this->meta->charset
+ . $this->meta->language
+ . $this->meta->job_uri
+ . $this->meta->username
+ . $this->meta->message
+ . chr(0x03); // end-of-attributes | end-of-attributes-tag
+
+ self::_putDebug( sprintf(_("String sent to the server is:\n%s\n"), $this->stringjob));
+ return TRUE;
+ }
+ // }}}
+
+
+};
+
+/*
+ * Local variables:
+ * mode: php
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
+?>
diff --git a/Moodle/mod/print/README.txt b/Moodle/mod/print/README.txt
new file mode 100755
index 0000000..c9d7bf1
--- /dev/null
+++ b/Moodle/mod/print/README.txt
@@ -0,0 +1,75 @@
+$Id: README.txt,v 1.2.2.2 2009/03/18 14:49:20 mudrd8mz Exp $
+
+HOW TO STARTUP WITH A NEW ACTIVITY MODULE
+=========================================
+
+The following steps should get you up and running with
+this module template code.
+
+As you are able to read this file, you have probably managed to get this
+source code from either the CVS repository or from the zip archive. Well done!
+
+Read this README file.
+
+Make sure you have read this file :-)
+
+Rename the NEWMODULE folder into a lower case name of your module. Make sure
+your name is not used by any standard or contributed modules (see
+http://cvs.moodle.org/contrib/plugins/mod/ for the list of currently
+contributed modules).
+
+Edit all the files in this directory and its subdirectories and change all the
+instances of string "print" to your new module name (eg "widget").
+
+Rename the file lang/en_utf8/print.php to widget.php or whatever your
+module name is.
+
+Place the widget folder into the /mod folder of your development moodle
+directory.
+
+Go to http://localhost/your/moodle/admin/xmldb/ directory. Try to not to visit
+the main admin page (Notifications) so the module is not installed yet. If it
+gets installed accidentaly, uninstall it from the database via Manage
+activities admin page. You will probably uninstall and reinstall the module
+quite often during the early stages of the development.
+
+In XMLDB editor, add all tables, fields and statements needed to implement the
+module features. See http://docs.moodle.org/en/Development:Using_XMLDB for
+more information. Do not forget to use the [Save] link at the XMLDB main page
+so the changes are written into install.xml file. If the link is not active,
+the web server process (eg. apache user) does not have permission to write
+into mod/widget/db/install.xml file
+
+Visit the admin Notifications page (admin/index.php). The module tables should
+get installed.
+
+You can go to Modules > Activities in the Site Administration block. You
+should find that this print has been added to the list of recognized
+modules.
+
+You may now proceed to run your own code in an attempt to develop for moodle.
+Good luck with that. For help with developing code for moodle, visit the
+"Activity modules" developers forum in the online course called "Using Moodle"
+at http://moodle.org.
+
+
+What to do next
+---------------
+
+Go through the lib.php, index.php and view.php files.
+
+You will probably want to add some capabilities regarding your module. Look at
+db/access.php. Note that you have to increase the version number defined in
+version.php to let Moodle update the capabilities information.
+
+If you do any change to the database structure (adding a field, changing the
+field definition etc.) use XMLDB editor again. Use the PHP code generated by
+XMLDB and push it into db/upgrade.php. Save the change into install.xml (for
+fresh installations), increase the version number and go to admin/index.php
+again. During upgrade, Moodle calls a function in db/upgrade.php to perform
+the DB changes.
+
+Credits for work on this NEWMODULE template
+-------------------------------------------
+Martin Dougiamas for the original work
+Chris B Stones (http://www.welcometochrisworld.com) for revision of the code
diff --git a/Moodle/mod/print/db/access.php b/Moodle/mod/print/db/access.php
new file mode 100755
index 0000000..7196b71
--- /dev/null
+++ b/Moodle/mod/print/db/access.php
@@ -0,0 +1,71 @@
+<?php
+//
+// Capability definitions for the assignment module.
+//
+// The capabilities are loaded into the database table when the module is
+// installed or updated. Whenever the capability definitions are updated,
+// the module version number should be bumped up.
+//
+// The system has four possible values for a capability:
+// CAP_ALLOW, CAP_PREVENT, CAP_PROHIBIT, and inherit (not set).
+//
+//
+// CAPABILITY NAMING CONVENTION
+//
+// It is important that capability names are unique. The naming convention
+// for capabilities that are specific to modules and blocks is as follows:
+// [mod/block]/<component_name>:<capabilityname>
+//
+// component_name should be the same as the directory name of the mod or block.
+//
+// Core moodle capabilities are defined thus:
+// moodle/<capabilityclass>:<capabilityname>
+//
+// Examples: mod/forum:viewpost
+// block/recent_activity:view
+// moodle/site:deleteuser
+//
+// The variable name for the capability definitions array follows the format
+// $<componenttype>_<component_name>_capabilities
+//
+// For the core capabilities, the variable is $moodle_capabilities.
+
+
+$mod_print_capabilities = array(
+
+ 'mod/print:view' => array(
+
+ 'captype' => 'read',
+ 'contextlevel' => CONTEXT_MODULE,
+ 'legacy' => array(
+ 'guest' => CAP_ALLOW,
+ 'student' => CAP_ALLOW,
+ 'teacher' => CAP_ALLOW,
+ 'editingteacher' => CAP_ALLOW,
+ 'admin' => CAP_ALLOW
+ )
+ ),
+
+ 'mod/print:submit' => array(
+
+ 'captype' => 'write',
+ 'contextlevel' => CONTEXT_MODULE,
+ 'legacy' => array(
+ 'student' => CAP_ALLOW
+ )
+ ),
+
+ 'mod/print:grade' => array(
+ 'riskbitmask' => RISK_XSS,
+
+ 'captype' => 'write',
+ 'contextlevel' => CONTEXT_MODULE,
+ 'legacy' => array(
+ 'teacher' => CAP_ALLOW,
+ 'editingteacher' => CAP_ALLOW,
+ 'admin' => CAP_ALLOW
+ )
+ )
+);
+
+?> \ No newline at end of file
diff --git a/Moodle/mod/print/db/install.xml b/Moodle/mod/print/db/install.xml
new file mode 100755
index 0000000..7df1ee3
--- /dev/null
+++ b/Moodle/mod/print/db/install.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<XMLDB PATH="mod/print/db" VERSION="20070401" COMMENT="XMLDB file for Moodle mod/print"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
+>
+ <TABLES>
+ <TABLE NAME="print" COMMENT="Default comment for print, please edit me" NEXT="print_submissions">
+ <FIELDS>
+ <FIELD NAME="user" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" COMMENT="Owner of the printjob" NEXT="id"/>
+ <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" ENUM="false" PREVIOUS="user" NEXT="course"/>
+ <FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="Course print activity belongs to" PREVIOUS="id" NEXT="name"/>
+ <FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" ENUM="false" COMMENT="name field for moodle instances" PREVIOUS="course" NEXT="intro"/>
+ <FIELD NAME="intro" TYPE="text" LENGTH="medium" NOTNULL="false" SEQUENCE="false" ENUM="false" COMMENT="General introduction of the print activity" PREVIOUS="name" NEXT="introformat"/>
+ <FIELD NAME="introformat" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="Format of the intro field (MOODLE, HTML, MARKDOWN...)" PREVIOUS="intro" NEXT="timecreated"/>
+ <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="introformat" NEXT="timemodified"/>
+ <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="timecreated" NEXT="maxbytes"/>
+ <FIELD NAME="maxbytes" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="100000" SEQUENCE="false" ENUM="false" PREVIOUS="timemodified"/>
+ </FIELDS>
+ <KEYS>
+ <KEY NAME="primary" TYPE="primary" FIELDS="id" />
+ </KEYS>
+ <INDEXES>
+ <INDEX NAME="course" UNIQUE="false" FIELDS="course"/>
+ </INDEXES>
+ </TABLE>
+ <TABLE NAME="print_submissions" COMMENT="Info about submitted assignments" PREVIOUS="print">
+ <FIELDS>
+ <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" ENUM="false" NEXT="assignment"/>
+ <FIELD NAME="assignment" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="id" NEXT="userid"/>
+ <FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="assignment" NEXT="timecreated"/>
+ <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="userid" NEXT="timemodified"/>
+ <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="timecreated" NEXT="numfiles"/>
+ <FIELD NAME="numfiles" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="timemodified" NEXT="data1"/>
+ <FIELD NAME="data1" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" ENUM="false" PREVIOUS="numfiles" NEXT="data2"/>
+ <FIELD NAME="data2" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" ENUM="false" PREVIOUS="data1" NEXT="submissioncomment"/>
+ <FIELD NAME="submissioncomment" TYPE="text" LENGTH="small" NOTNULL="true" SEQUENCE="false" ENUM="false" PREVIOUS="data2" NEXT="format"/>
+ <FIELD NAME="format" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="submissioncomment" NEXT="teacher"/>
+ <FIELD NAME="teacher" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="format" NEXT="timemarked"/>
+ <FIELD NAME="timemarked" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" PREVIOUS="teacher" NEXT="filepath"/>
+ <FIELD NAME="filepath" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" ENUM="false" PREVIOUS="timemarked"/>
+
+ </FIELDS>
+ <KEYS>
+ <KEY NAME="primary" TYPE="primary" FIELDS="id" NEXT="assignment"/>
+ <KEY NAME="assignment" TYPE="foreign" FIELDS="assignment" REFTABLE="assignment" REFFIELDS="id" PREVIOUS="primary"/>
+ </KEYS>
+ </TABLE>
+ </TABLES>
+ <STATEMENTS>
+ <STATEMENT NAME="insert log_display" TYPE="insert" TABLE="log_display" COMMENT="Initial insert of records on table log_display. Each record describes how data will be showed by log reports.">
+ <SENTENCES>
+ <SENTENCE TEXT="(module, action, mtable, field) VALUES ('print', 'add', 'print', 'name')" />
+ <SENTENCE TEXT="(module, action, mtable, field) VALUES ('print', 'update', 'print', 'name')" />
+ <SENTENCE TEXT="(module, action, mtable, field) VALUES ('print', 'view', 'print', 'name')" />
+ </SENTENCES>
+ </STATEMENT>
+ </STATEMENTS>
+</XMLDB>
diff --git a/Moodle/mod/print/db/upgrade.php b/Moodle/mod/print/db/upgrade.php
new file mode 100755
index 0000000..632c262
--- /dev/null
+++ b/Moodle/mod/print/db/upgrade.php
@@ -0,0 +1,134 @@
+<?php //$Id: upgrade.php,v 1.2 2007/08/08 22:36:54 stronk7 Exp $
+
+// This file keeps track of upgrades to
+// the print module
+//
+// Sometimes, changes between versions involve
+// alterations to database structures and other
+// major things that may break installations.
+//
+// The upgrade function in this file will attempt
+// to perform all the necessary actions to upgrade
+// your older installtion to the current version.
+//
+// If there's something it cannot do itself, it
+// will tell you what you need to do.
+//
+// The commands in here will all be database-neutral,
+// using the functions defined in lib/ddllib.php
+
+function xmldb_print_upgrade($oldversion=0) {
+
+ global $CFG, $THEME, $db;
+
+ $result = true;
+
+/// And upgrade begins here. For each one, you'll need one
+/// block of code similar to the next one. Please, delete
+/// this comment lines once this file start handling proper
+/// upgrade code.
+
+/// if ($result && $oldversion < YYYYMMDD00) { //New version in version.php
+/// $result = result of "/lib/ddllib.php" function calls
+/// }
+
+/// Lines below (this included) MUST BE DELETED once you get the first version
+/// of your module ready to be installed. They are here only
+/// for demonstrative purposes and to show how the print
+/// iself has been upgraded.
+
+/// For each upgrade block, the file print/version.php
+/// needs to be updated . Such change allows Moodle to know
+/// that this file has to be processed.
+
+/// To know more about how to write correct DB upgrade scripts it's
+/// highly recommended to read information available at:
+/// http://docs.moodle.org/en/Development:XMLDB_Documentation
+/// and to play with the XMLDB Editor (in the admin menu) and its
+/// PHP generation posibilities.
+
+/// First example, some fields were added to the module on 20070400
+ if ($result && $oldversion < 2007040100) {
+
+ /// Define field course to be added to print
+ $table = new XMLDBTable('print');
+ $field = new XMLDBField('course');
+ $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'id');
+ /// Launch add field course
+ $result = $result && add_field($table, $field);
+
+ /// Define field intro to be added to print
+ $table = new XMLDBTable('print');
+ $field = new XMLDBField('intro');
+ $field->setAttributes(XMLDB_TYPE_TEXT, 'medium', null, null, null, null, null, null, 'name');
+ /// Launch add field intro
+ $result = $result && add_field($table, $field);
+
+ /// Define field introformat to be added to print
+ $table = new XMLDBTable('print');
+ $field = new XMLDBField('introformat');
+ $field->setAttributes(XMLDB_TYPE_INTEGER, '4', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'intro');
+ /// Launch add field introformat
+ $result = $result && add_field($table, $field);
+ }
+
+/// Second example, some hours later, the same day 20070401
+/// two more fields and one index were added (note the increment
+/// "01" in the last two digits of the version
+ if ($result && $oldversion < 2007040101) {
+
+ /// Define field timecreated to be added to print
+ $table = new XMLDBTable('print');
+ $field = new XMLDBField('timecreated');
+ $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'introformat');
+ /// Launch add field timecreated
+ $result = $result && add_field($table, $field);
+
+ /// Define field timemodified to be added to print
+ $table = new XMLDBTable('print');
+ $field = new XMLDBField('timemodified');
+ $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'timecreated');
+ /// Launch add field timemodified
+ $result = $result && add_field($table, $field);
+
+ /// Define index course (not unique) to be added to print
+ $table = new XMLDBTable('print');
+ $index = new XMLDBIndex('course');
+ $index->setAttributes(XMLDB_INDEX_NOTUNIQUE, array('course'));
+ /// Launch add index course
+ $result = $result && add_index($table, $index);
+ }
+
+/// Third example, the next day, 20070402 (with the trailing 00), some inserts were performed, related with the module
+ if ($result && $oldversion < 2007040200) {
+ /// Add some actions to get them properly displayed in the logs
+ $rec = new stdClass;
+ $rec->module = 'print';
+ $rec->action = 'add';
+ $rec->mtable = 'print';
+ $rec->filed = 'name';
+ /// Insert the add action in log_display
+ $result = insert_record('log_display', $rec);
+ /// Now the update action
+ $rec->action = 'update';
+ $result = insert_record('log_display', $rec);
+ /// Now the view action
+ $rec->action = 'view';
+ $result = insert_record('log_display', $rec);
+ }
+
+/// And that's all. Please, examine and understand the 3 example blocks above. Also
+/// it's interesting to look how other modules are using this script. Remember that
+/// the basic idea is to have "blocks" of code (each one being executed only once,
+/// when the module version (version.php) is updated.
+
+/// Lines above (this included) MUST BE DELETED once you get the first version of
+/// yout module working. Each time you need to modify something in the module (DB
+/// related, you'll raise the version and add one upgrade block here.
+
+/// Final return of upgrade result (true/false) to Moodle. Must be
+/// always the last line in the script
+ return $result;
+}
+
+?>
diff --git a/Moodle/mod/print/delete.php b/Moodle/mod/print/delete.php
new file mode 100755
index 0000000..9636d3c
--- /dev/null
+++ b/Moodle/mod/print/delete.php
@@ -0,0 +1,41 @@
+<?php // $Id: delete.php,v 1.1 2006/09/30 15:41:24 skodak Exp $
+
+ require_once('../../config.php');
+ require_once('lib.php');
+
+ $id = optional_param('id', 0, PARAM_INT); // Course module ID
+ $a = optional_param('a', 0, PARAM_INT); // Assignment ID
+
+ if ($id) {
+ if (! $cm = get_coursemodule_from_id('print', $id)) {
+ error("Course Module ID was incorrect");
+ }
+
+ if (! $assignment = get_record('print', 'id', $cm->instance)) {
+ error("assignment ID was incorrect");
+ }
+
+ if (! $course = get_record('course', 'id', $assignment->course)) {
+ error("Course is misconfigured");
+ }
+ } else {
+ if (!$assignment = get_record('print', 'id', $a)) {
+ error("Course module is incorrect");
+ }
+ if (! $course = get_record('course', 'id', $assignment->course)) {
+ error("Course is misconfigured");
+ }
+ if (! $cm = get_coursemodule_from_instance('print', $assignment->id, $course->id)) {
+ error("Course Module ID was incorrect");
+ }
+ }
+
+ require_login($course->id, false, $cm);
+
+/// Load up the required assignment code
+ $assignmentclass = 'print_base';
+ $assignmentinstance = new $assignmentclass($cm->id, $assignment, $cm, $course);
+
+ $assignmentinstance->delete(); // delete something
+
+?>
diff --git a/Moodle/mod/print/http_class.php b/Moodle/mod/print/http_class.php
new file mode 100755
index 0000000..f0285af
--- /dev/null
+++ b/Moodle/mod/print/http_class.php
@@ -0,0 +1,629 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
+ /* @(#) $Header: /sources/phpprintipp/phpprintipp/php_classes/http_class.php,v 1.1 2008/06/21 00:30:58 harding Exp $
+ *
+ *
+ * Class http_class - Basic http client with "Basic" authorization mechanism.
+ * handle ipv6 addresses and https
+ *
+ * Copyright (C) 2006 Thomas HARDING
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * mailto:thomas.harding@laposte.net
+ * Thomas Harding, 56 rue de la bourie rouge, 45 000 ORLEANS -- FRANCE
+ *
+ */
+
+/*
+
+ This class is intended to implement a subset of Hyper Text Transfer Protocol (HTTP/1.1) on client side.
+ (currently: POST operation)
+ It is a replacement for http://www.phpclasses.org/browse/package/3.html
+ in versions post-
+
+ It can perform Basic and Digest authentication.
+ It was tested only in clear mode
+
+ References needed to debug / add functionnalities:
+ - RFC 2616
+ - RFC 2617
+*/
+/*
+ TODO: beta tests on servers other than loopback one
+*/
+
+/***********************
+*
+* httpException class
+*
+************************/
+
+ // {{{ class httpException
+class httpException extends Exception {
+
+ protected $errno;
+
+ public function __construct($msg,$errno=null) {
+ parent :: __construct($msg);
+ $this->errno = $errno;
+ }
+
+ public function getErrorFormatted() {
+
+ $return = sprintf("[http_class]: %s -- "._(" file %s, line %s"),
+ $this->getMessage(),
+ $this->getFile(),
+ $this->getLine());
+
+ return $return;
+ }
+
+ public function getErrno() {
+
+ return $this->errno ;
+ }
+
+}
+ // }}}
+
+/*************************
+*
+* class http_class
+*
+**************************/
+
+class http_class {
+
+ // {{{ variables declaration
+ public $debug;
+ public $html_debug;
+ public $timeout = 30; // time waiting for connection, seconds
+ public $data_timeout = 30; // time waiting for data, milliseconds
+ public $force_multipart_form_post;
+ public $username;
+ public $password;
+ public $request_headers = array();
+ public $request_body = "Not a useful information";
+ public $status;
+ public $window_size = 10000; // chunk size of data
+ public $with_exceptions = 0; // compatibility mode for old scripts
+ public $port;
+ public $host;
+
+ private $default_port = 631;
+ private $headers;
+ private $reply_headers = array();
+ private $reply_body = array();
+ private $connection;
+ private $arguments;
+ private $bodystream = array();
+ private $last_limit;
+ private $connected;
+ private $nc = 1;
+ private $user_agent = "PRINTIPP/0.81";
+ // }}}
+
+ // {{{ constructor
+ public function __construct() {
+ true;
+ }
+ // }}}
+
+/*********************
+*
+* Public functions
+*
+**********************/
+
+ // {{{ GetRequestArguments ($url,&$arguments)
+ public function GetRequestArguments ($url,&$arguments) {
+
+ $this->arguments = array();
+
+ $arguments["URL"] = $this->arguments["URL"] = $url;
+ $arguments["RequestMethod"] = $this->arguments["RequestMethod"] = "POST";
+ $this->headers["Content-Length"] = 0;
+ $this->headers["Content-Type"] = "application/octet-stream";
+ $this->headers["Host"] = $this->host;
+ $this->headers["User-Agent"] = $this->user_agent;
+ //$this->headers["Expect"] = "100-continue";
+ }
+ // }}}
+
+ // {{{ Open ($arguments)
+ public function Open ($arguments) {
+ $this->connected = false;
+ if (!$this->timeout)
+ $this->timeout = 30;
+ $url = $arguments["URL"];
+ $port = $this->default_port;
+
+ $url = split (':',$url,2);
+ $transport_type = $url[0];
+ $unix = false;
+ switch($transport_type) {
+ case 'http':
+ $transport_type = 'tcp://';
+ break;
+ case 'https':
+ $transport_type = 'tls://';
+ break;
+ case 'unix':
+ $transport_type = 'unix://';
+ $port = 0;
+ $unix = true;
+ break;
+ default:
+ $transport_type = 'tcp://';
+ break;
+ }
+ $url = $url[1];
+ if (!$unix) {
+ $url = split("/",preg_replace("#^/{1,}#",'',$url),2);
+ $url = $url[0];
+ $port = $this->port;
+ $error = sprintf(_("Cannot resolve url: %s"),$url);
+ $ip = gethostbyname($url);
+ $ip = @gethostbyaddr($ip);
+ if (!$ip)
+ if ($this->with_exceptions)
+ throw new httpException($error);
+ else
+ {
+ trigger_error($error,E_USER_WARNING);
+ return false;
+ }
+ if (strstr($url,":")) // we got an ipv6 address
+ if (!strstr($url,"[")) // it is not escaped
+ $url = sprintf("[%s]",$url);
+ }
+ $this->connection = @fsockopen($transport_type.$url, $port, $errno, $errstr, $this->timeout);
+ $error = sprintf (_('Unable to connect to "%s%s port %s": %s'),
+ $transport_type,
+ $url,
+ $port,
+ $errstr);
+
+ if (!$this->connection)
+ if ($this->with_exceptions)
+ {
+ $this->connected = false;
+ throw new httpException($error,$errno);
+ }
+ else
+ {
+ trigger_error($error,E_USER_WARNING);
+ $this->connected = false;
+ return $error;
+ }
+ $this->connected = true;
+ }
+ // }}}
+
+ // {{{ SendRequest($arguments)
+ public function SendRequest($arguments) {
+
+ if (!$this->data_timeout)
+ $this->data_timeout = 30;
+
+ if(!$result = self::_StreamRequest($arguments))
+ return("SendRequest: unknown error");
+
+ self::_ReadReply();
+
+ if (!preg_match('#http/1.1 401 unauthorized#',$this->status))
+ return;
+
+
+ $headers = array_keys ($this->reply_headers);
+ if (!in_array("www-authenticate",$headers))
+ return("SendRequest: need authentication but no mechanism provided");
+
+ $authtype = split(' ',$this->reply_headers["www-authenticate"]);
+ $authtype = strtolower($authtype[0]);
+
+ switch ($authtype) {
+ case 'basic':
+ $pass = base64_encode($this->user.":".$this->password);
+ $arguments["Headers"]["Authorization"] = "Basic ".$pass;
+ break;
+ case 'digest':
+ $arguments["Headers"]["Authorization"] = self::_BuildDigest();
+ break;
+ default:
+ return sprintf(_("http_class: need '%s' authentication mechanism, but have not, sorry"),$authtype[0]);
+ }
+
+ self::Close();
+ self::Open($arguments);
+
+ if(!$result = self::_StreamRequest($arguments))
+ return("SendRequest: unknown error");
+
+ self::_ReadReply();
+
+ }
+ // }}}
+
+ // {{{ ReadReplyHeaders (&$headers)
+ public function ReadReplyHeaders (&$headers) {
+ if ($this->connected)
+ $headers = $this->reply_headers;
+ }
+ // }}}
+
+ // {{{ ReadReplyBody (&$body,$chunk_size)
+ public function ReadReplyBody (&$body,$chunk_size) {
+ $body = substr($this->reply_body,$this->last_limit,$chunk_size);
+ $this->last_limit += $chunk_size;
+ }
+ // }}}
+
+ // {{{ Close ()
+ public function Close () {
+ if (!$this->connected) return;
+ fclose ($this->connection);
+ }
+ // }}}
+
+/*********************
+*
+* Private functions
+*
+**********************/
+
+ // {{{ _StreamRequest ($arguments)
+ private function _StreamRequest ($arguments) {
+ if (!$this->connected) return;
+
+ $this->status = "";
+ $this->reply_headers = array();
+ $this->reply_body = "";
+
+ $this->arguments = $arguments;
+
+ $content_length = 0;
+ foreach ($this->arguments["BodyStream"] as $argument) {
+
+ list($type,$value) = each($argument);
+ reset ($argument);
+
+ if ($type == "Data")
+ $length = strlen($value);
+
+ elseif ($type == "File")
+ if (is_readable($value))
+ $length = filesize($value);
+ else {
+ $length = 0;
+ trigger_error(sprintf(_("%s: file is not readable"),$value),E_USER_WARNING);
+ }
+
+ else {
+ $length = 0;
+ trigger_error(sprintf(_("%s: not a valid argument for content"),$type),E_USER_WARNING);
+ }
+
+ $content_length += $length;
+ }
+
+ $this->request_body = sprintf(_("%s Bytes"), $content_length);
+ $this->headers["Content-Length"] = $content_length;
+ $this->arguments["Headers"] = array_merge($this->headers,$this->arguments["Headers"]);
+
+ //$read = array($this->connection);
+ $status = stream_get_meta_data($this->connection);
+ if (isset($status['unread-bytes']) && $status['unread-bytes']) {
+ // server talks!
+ trigger_error(_("http_class: server talk first, quit"),E_USER_WARNING);
+ return false;
+ }
+
+ if ($this->arguments["RequestMethod"] != "POST") {
+ trigger_error (sprintf(_("%s: method not implemented"),$arguments["RequestMethod"]),E_USER_WARNING);
+ return sprintf(_("%s: method not implemented"),$arguments["RequestMethod"]);
+ }
+
+ $string = sprintf("POST %s HTTP/1.1\r\n",$this->arguments["RequestURI"]);
+ $error = fwrite($this->connection,$string);
+ $this->request_headers[$string] = '';
+
+ //if(stream_select($read, $write = NULL, $except = NULL, 0) === 1) // server talks!
+ $status = stream_get_meta_data($this->connection);
+ if (isset($status['unread-bytes']) && $status['unread-bytes'])
+ return "server-talk";
+ if (!$error) {
+ trigger_error(_("Error while puts first header"),E_USER_WARNING);
+ return _("Stream closed while puts first header");
+ }
+
+ foreach ($this->arguments["Headers"] as $header => $value) {
+
+ $error = @fwrite($this->connection,sprintf("%s: %s\r\n", $header, $value));
+ $this->request_headers[$header] = $value;
+ //if(stream_select($read, $write = NULL, $except = NULL, 0) === 1)
+ $status = stream_get_meta_data($this->connection);
+ if (isset($status['unread-bytes']) && $status['unread-bytes'])
+ return "server-talk";
+
+ if (!$error) {
+ trigger_error(_("Error while puts HTTP headers"),E_USER_WARNING);
+ return _("Stream closed while puts HTTP headers");
+ }
+ }
+
+ $error = fwrite($this->connection,"\r\n");
+ //fflush($this->connection);
+
+ //if($strselect = stream_select($read, $write = NULL, $except = NULL, 0,$this->data_timeout*1000) === 1)
+ //usleep($this->data_timeout*1000);
+ $status = stream_get_meta_data($this->connection);
+ if (isset($status['unread-bytes']) && $status['unread-bytes'])
+ return "server-talk";
+
+ if (!$error) {
+ trigger_error(_("Error while ends HTTP headers"),E_USER_WARNING);
+ return _("Stream closed while ends HTTP headers");
+ }
+
+ foreach ($this->arguments["BodyStream"] as $argument) {
+
+ list($type,$value) = each($argument);
+ reset ($argument);
+
+
+ if ($type == "Data") {
+ $streamed_length = 0;
+ while ($streamed_length < strlen($value)) {
+ //if(stream_select($read, $write = NULL, $except = NULL, 0) === 1)
+ //usleep($this->data_timeout*1000);
+ $status = stream_get_meta_data($this->connection);
+ if (isset($status['unread-bytes']) && $status['unread-bytes'])
+ return "server-talk";
+
+ // not very clean...
+ $error = @fwrite($this->connection,substr($value,$streamed_length,$this->window_size));
+ if (!$error)
+ return "error-while-push-data";
+ $streamed_length += $this->window_size;
+ }
+ }
+
+ if (!$error)
+ return _("error-while-push-data");
+
+ elseif ($type == "File") {
+ if (is_readable($value)) {
+ $file = fopen($value,'rb');
+ while(!feof($file)) {
+
+ if(gettype($block = @fread($file,$this->window_size)) != "string") {
+ trigger_error(_("cannot read file to upload"),E_USER_WARNING);
+ return _("cannot read file to upload");
+ }
+
+ //if(stream_select($read, $write = NULL, $except = NULL, 0) === 1)
+ $status = stream_get_meta_data($this->connection);
+ if (isset($status['unread-bytes']) && $status['unread-bytes'])
+ return "server-talks";
+
+ // not very clean...
+ $error = @fwrite($this->connection,$block);
+ if (!$error)
+ return "error-while-push-data";
+
+ }
+ }
+ }
+
+ //if(stream_select($read, $write = NULL, $except = NULL, 0) === 1)
+ $status = stream_get_meta_data($this->connection);
+ if (isset($status['unread-bytes']) && $status['unread-bytes'])
+ return "server-talks";
+
+ }
+
+ return true;
+ }
+ // }}}
+
+ // {{{ _ReadReply ()
+ private function _ReadReply () {
+
+ if (!$this->connected) return;
+
+ $this->reply_headers = array();
+ $this->reply_body = "";
+
+
+
+ $line = "1\r\n";
+ $headers = "";
+ $body = "";
+ while (!feof($this->connection)) {
+ $line = fgets($this->connection,1024);
+ if (strlen($line) <= 2)
+ break;
+ $headers .= $line;
+ }
+ $chunk = true;
+
+ $headers = preg_split('#\r\n#',$headers);
+
+ $this->status = strtolower($headers[0]);
+
+ foreach($headers as $header) {
+ if (!preg_match('#www-authenticate: #i',$header))
+ $header = strtolower($header);
+
+ $header = preg_split("#: #",$header);
+ $header[0] = strtolower($header[0]);
+
+ $this->reply_headers["{$header[0]}"] = array_key_exists(1,$header) ? $header[1] : "";
+ }
+ unset ($this->reply_headers['']);
+
+ //giving 3 chances to complete reading
+ $read = array($this->connection);
+ for ($i = 0 ; $i < 2 ; $i++) {
+ if (self::_ReadStream() === "completed")
+ break;
+ //$strselect = stream_select($read, $write = NULL, $except = NULL, 0,$this->data_timeout*1000);
+ //if (!$strselect)
+ //usleep($this->data_timeout*1000);
+ $status = stream_get_meta_data ($this->connection);
+ if ($status["unread_bytes"] == 0)
+ break;
+ }
+
+ return true;
+ }
+ // }}}
+
+ // {{{ _ReadStream ()
+ private function _ReadStream () {
+
+ $content_length = 0;
+ if (array_key_exists("content-length",$this->reply_headers));
+ $content_length = $this->reply_headers["content-length"];
+
+ stream_set_blocking ($this->connection, 0 );
+ usleep($this->data_timeout * 1000);
+ $total = 0;
+ $chunk = true;
+ while (true) {
+ if ($content_length)
+ if (strlen($this->reply_body) >= $content_length)
+ return "completed";
+ else
+ if (!$chunk)
+ break;
+ usleep (1000);
+ $chunk = @fread($this->connection,$this->window_size);
+ $this->reply_body .= $chunk;
+
+ $status = stream_get_meta_data ($this->connection);
+ if ($status["unread_bytes"] == 0)
+ break;
+ }
+ stream_set_blocking ($this->connection, 1 );
+ return true;
+ }
+ // }}}
+
+ // {{{ _BuildDigest ()
+ private function _BuildDigest () {
+
+ $auth = $this->reply_headers["www-authenticate"];
+
+ list($head, $auth) = split(" ",$auth,2);
+
+ $auth=split(", ",$auth);
+ foreach ($auth as $sheme) {
+ list($sheme,$value) = split('=',$sheme);
+ $fields[$sheme] = trim(trim($value),'"');
+ }
+
+ $nc = sprintf('%x',$this->nc);
+ $prepend = "";
+ while ((strlen($nc) + strlen($prepend)) < 8)
+ $prepend .= "0";
+ $nc=$prepend.$nc;
+
+ $cnonce = "printipp";
+
+ $username = $this->user;
+ $password = $this->password;
+
+ $A1 = $username.":".$fields["realm"].":".$password;
+
+ if (array_key_exists("algorithm",$fields)) {
+ $algorithm = strtolower($fields["algorithm"]);
+ switch ($algorithm) {
+ case "md5":
+ break;
+ case "md5-sess":
+ $A1 = $username.":".$fields["realm"].":".$password.":".$fields['nonce'].":".$cnonce;
+ break;
+ case "token":
+ trigger_error("http_class: digest Authorization: algorithm 'token' not implemented", E_USER_WARNING);
+ return false;
+ break;
+ }
+
+ }
+
+ $A2 = "POST:".$this->arguments["RequestURI"];
+
+
+ if (array_key_exists("qop",$fields)) {
+ $qop = strtolower($fields["qop"]);
+ $qop = split(" ",$qop);
+ if (in_array("auth",$qop))
+ $qop = "auth";
+ else {
+ trigger_error("http_class: digest Authorization: qop others than 'auth' not implemented", E_USER_WARNING);
+ return false;
+ }
+ }
+
+ //echo $A1,":",$fields["nonce"],":",$A2,"<br />";
+ $response = md5(md5($A1).":". $fields["nonce"].":" .md5($A2));
+
+ if (isset($qop) && ($qop == "auth"))
+ {
+ $response = md5(md5($A1).":".$fields["nonce"].":".$nc.":".$cnonce.":".$qop.":".$A2);
+ }
+
+ $auth_scheme = sprintf('Digest username="%s", realm="%s", nonce="%s", uri="%s", response="%s"',
+ $username,
+ $fields["realm"],
+ $fields['nonce'],
+ $this->arguments["RequestURI"],
+ $response
+ );
+ //echo $auth_scheme,"<br />";
+ if (isset($algorithm))
+ $auth_scheme .= sprintf(', algorithm="%s"',$algorithm);
+
+ if (isset($qop))
+ $auth_scheme .= sprintf(', cnonce="%s"',$cnonce);
+
+ if(array_key_exists("opaque",$fields))
+ $auth_scheme .= sprintf(', opaque="%s"',$fields['opaque']);
+
+ if (isset($qop))
+ $auth_scheme .= sprintf(', qop="%s"',$qop);
+
+ $auth_scheme .= sprintf(', nc=%s',$nc);
+
+ $this->nc++;
+
+ return $auth_scheme;
+ }
+ // }}}
+
+};
+
+
+/*
+ * Local variables:
+ * mode: php
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
+?>
diff --git a/Moodle/mod/print/icon.gif b/Moodle/mod/print/icon.gif
new file mode 100755
index 0000000..550df5d
--- /dev/null
+++ b/Moodle/mod/print/icon.gif
Binary files differ
diff --git a/Moodle/mod/print/index.php b/Moodle/mod/print/index.php
new file mode 100755
index 0000000..f69e372
--- /dev/null
+++ b/Moodle/mod/print/index.php
@@ -0,0 +1,89 @@
+<?php // $Id: index.php,v 1.7.2.2 2009/03/31 13:07:21 mudrd8mz Exp $
+
+/**
+ * This page lists all the instances of print in a particular course
+ *
+ * @author Your Name <your@email.address>
+ * @version $Id: index.php,v 1.7.2.2 2009/03/31 13:07:21 mudrd8mz Exp $
+ * @package mod/print
+ */
+
+/// Replace print with the name of your module and remove this line
+
+require_once(dirname(dirname(dirname(__FILE__))).'/config.php');
+require_once(dirname(__FILE__).'/lib.php');
+
+$id = required_param('id', PARAM_INT); // course
+
+if (! $course = get_record('course', 'id', $id)) {
+ error('Course ID is incorrect');
+}
+
+require_course_login($course);
+
+add_to_log($course->id, 'print', 'view all', "index.php?id=$course->id", '');
+
+
+/// Get all required stringsprint
+
+$strprints = get_string('modulenameplural', 'print');
+$strprint = get_string('modulename', 'print');
+
+
+/// Print the header
+
+$navlinks = array();
+$navlinks[] = array('name' => $strprints, 'link' => '', 'type' => 'activity');
+$navigation = build_navigation($navlinks);
+
+print_header_simple($strprints, '', $navigation, '', '', true, '', navmenu($course));
+
+/// Get all the appropriate data
+
+if (! $prints = get_all_instances_in_course('print', $course)) {
+ notice('There are no instances of print', "../../course/view.php?id=$course->id");
+ die;
+}
+
+/// Print the list of instances (your module will probably extend this)
+
+$timenow = time();
+$strname = get_string('name');
+$strweek = get_string('week');
+$strtopic = get_string('topic');
+
+if ($course->format == 'weeks') {
+ $table->head = array ($strweek, $strname);
+ $table->align = array ('center', 'left');
+} else if ($course->format == 'topics') {
+ $table->head = array ($strtopic, $strname);
+ $table->align = array ('center', 'left', 'left', 'left');
+} else {
+ $table->head = array ($strname);
+ $table->align = array ('left', 'left', 'left');
+}
+
+foreach ($prints as $print) {
+ if (!$print->visible) {
+ //Show dimmed if the mod is hidden
+ $link = "<a class=\"dimmed\" href=\"view.php?id=$print->coursemodule\">$print->name</a>";
+ } else {
+ //Show normal if the mod is visible
+ $link = "<a href=\"view.php?id=$print->coursemodule\">$print->name</a>";
+ }
+
+ if ($course->format == 'weeks' or $course->format == 'topics') {
+ $table->data[] = array ($print->section, $link);
+ } else {
+ $table->data[] = array ($link);
+ }
+}
+
+print_heading($strprints);
+print_table($table);
+
+/// Finish the page
+
+print_footer($course);
+
+?>
diff --git a/Moodle/mod/print/lang/en_utf8/help/newmodule/index.html b/Moodle/mod/print/lang/en_utf8/help/newmodule/index.html
new file mode 100755
index 0000000..5927327
--- /dev/null
+++ b/Moodle/mod/print/lang/en_utf8/help/newmodule/index.html
@@ -0,0 +1,6 @@
+<p>print</p>
+<p>Delete me! This file contains a list of all the help files available for the module. Don't
+ forget to add each individual help file to the html list below. Delete me!</p>
+<ul>
+ <li><a href="help.php?module=print&amp;file=mods.html">print General Info</a></li>
+</ul>
diff --git a/Moodle/mod/print/lang/en_utf8/help/newmodule/mods.html b/Moodle/mod/print/lang/en_utf8/help/newmodule/mods.html
new file mode 100755
index 0000000..f018f4c
--- /dev/null
+++ b/Moodle/mod/print/lang/en_utf8/help/newmodule/mods.html
@@ -0,0 +1,18 @@
+<p><img alt="" src="<?php echo $CFG->wwwroot?>/mod/print/icon.gif" />&nbsp;<b>print</b></p>
+<div class="indent">
+<p>This file contains the main description of the print module. Usually, it's used to
+explain the main features of the activity, with a natural language. Also, the overall
+process of the activity is detailed here with its pedagogical foundation.</p>
+
+<p>From a developer perspective, this "help" directory will contain simple html files
+like this that you will be able to link from print code when any sort of
+explanation is necessary (it's easier to add those links automatically, both from
+the formslib stuff (see mod_form.php) and from everywhere else (see the helpbutton()
+function).</p>
+
+<p>Also, don't forget to add one link to this help file from the print/help "index.html"
+file, it will allow Moodle to show all the existing help files related to the module when the
+complete list of available help files is requested.</p>
+
+<p>Please, replace me with the real information about the print!</p>
+</div>
diff --git a/Moodle/mod/print/lang/en_utf8/newmodule.php b/Moodle/mod/print/lang/en_utf8/newmodule.php
new file mode 100755
index 0000000..13026b3
--- /dev/null
+++ b/Moodle/mod/print/lang/en_utf8/newmodule.php
@@ -0,0 +1,12 @@
+<?php
+
+$string['print'] = 'print';
+
+$string['modulename'] = 'print';
+$string['modulenameplural'] = 'prints';
+
+$string['printfieldset'] = 'Custom example fieldset';
+$string['printintro'] = 'print Intro';
+$string['printname'] = 'print Name';
+
+?>
diff --git a/Moodle/mod/print/lib.php b/Moodle/mod/print/lib.php
new file mode 100755
index 0000000..6bcc38c
--- /dev/null
+++ b/Moodle/mod/print/lib.php
@@ -0,0 +1,1195 @@
+<?php // $Id: lib.php,v 1.7.2.5 2009/04/22 21:30:57 skodak Exp $
+
+/**
+ * Library of functions and constants for module print
+ * This file should have two well differenced parts:
+ * - All the core Moodle functions, neeeded to allow
+ * the module to work integrated in Moodle.
+ * - All the print specific functions, needed
+ * to implement all the module logic. Please, note
+ * that, if the module become complex and this lib
+ * grows a lot, it's HIGHLY recommended to move all
+ * these module specific functions to a new php file,
+ * called "locallib.php" (see forum, quiz...). This will
+ * help to save some memory when Moodle is performing
+ * actions across all modules.
+ */
+
+
+
+/**
+ * Given an object containing all the necessary data,
+ * (defined by the form in mod_form.php) this function
+ * will create a new instance and return the id number
+ * of the new instance.
+ *
+ * @param object $print An object from the form in mod_form.php
+ * @return int The id of the newly inserted print record
+ */
+
+
+class print_base {
+
+ var $cm;
+ var $course;
+ var $printconfig;
+ var $submission;
+
+ function print_base($cmid='staticonly', $printconfig=NULL, $cm=NULL, $course=NULL) {
+
+ if ($cmid == 'staticonly') {
+ //use static functions only!
+ return;
+ }
+
+ global $CFG;
+
+ if ($cm) {
+ $this->cm = $cm;
+ } else if (! $this->cm = get_coursemodule_from_id('print', $cmid)) {
+ error('Course Module ID was incorrect');
+ }
+ $this->context = get_context_instance(CONTEXT_MODULE, $this->cm->id);
+
+ if ($course) {
+ $this->course = $course;
+ } else if ($this->cm->course == $COURSE->id) {
+ $this->course = $COURSE;
+ } else if (! $this->course = get_record('course', 'id', $this->cm->course)) {
+ error('Course is misconfigured');
+ }
+
+ if ($printconfig) {
+ $this->printconfig = $printconfig;
+ } else if (! $this->printconfig = get_record('print', 'id', $this->cm->instance)) {
+ error('print ID was incorrect');
+ }
+
+ #$this->submissions = $this->check_database("print_submissions");
+ $this->printconfig->cmidnumber = $this->cm->id; // compatibility with modedit assignment obj
+ $this->printconfig->courseid = $this->course->id; // compatibility with modedit assignment obj
+ $this->printconfig->maxbytes = 2097152;
+}
+function check_database($table) {
+ global $CFG,$USER;
+ $sql = "SELECT *
+ FROM {$CFG->prefix}$table
+ WHERE userid = '$USER->id'
+ AND assignment = '{$this->printconfig->id}'";
+
+ return $sql;
+
+}
+
+function view1() {
+ global $USER;
+
+ require_capability('mod/print:view', $this->context);
+
+ add_to_log($this->course->id, 'print', 'view', "view.php?id={$this->cm->id}", $this->printconfig->id, $this->cm->id);
+
+ $this->view_header();
+
+
+ if (has_capability('mod/print:submit', $this->context)) {
+
+ if ($this->submissions = get_records_sql($this->check_database("print_submissions"))) {
+
+
+ } else {
+ $substring = "No Submissions yet";
+ print_simple_box(get_string('nofilesyet', 'assignment'), 'center');
+ }
+
+
+ $filecount = $this->count_user_files($USER->id);
+ $submission = $this->get_submissions1($USER->id);
+
+ # $this->view_feedback();
+
+ print_heading(get_string('submissiondraft', 'assignment'), '', 3);
+
+
+ if ($filecount and $submission) {
+ print_simple_box($this->print_user_files($USER->id, true), 'center');
+ } else {
+ print_simple_box(get_string('nofilesyet', 'assignment'), 'center');
+ }
+
+
+ $this->view_upload_form();
+
+
+ }
+ }
+ function view_header($subpage='') {
+
+ global $CFG;
+
+
+ if ($subpage) {
+ $navigation = build_navigation($subpage, $this->cm);
+ } else {
+ $navigation = build_navigation('', $this->cm);
+ }
+
+ print_header('Print Uploads', $this->course->fullname, $navigation, '', '',
+ true, update_module_button($this->cm->id, $this->course->id, ''),
+ navmenu($this->course, $this->cm));
+
+ groups_print_activity_menu($this->cm, 'view.php?id=' . $this->cm->id);
+
+ echo '<div class="reportlink">'.$this->submittedlink().'</div>';
+ echo '<div class="clearer"></div>';
+ }
+
+ function submissions($mode) {
+ ///The main switch is changed to facilitate
+ ///1) Batch fast grading
+ ///2) Skip to the next one on the popup
+ ///3) Save and Skip to the next one on the popup
+
+ //make user global so we can use the id
+ global $USER;
+
+
+ switch ($mode) {
+ case 'single': // We are in a popup window displaying submission
+ $this->display_submission();
+ break;
+
+ case 'all': // Main window, display everything
+ $this->display_submissions();
+ break;
+
+
+ foreach ($_POST[$col] as $id => $unusedvalue){
+
+ $id = (int)$id; //clean parameter name
+
+ $this->process_outcomes($id);
+
+ if (!$submission = $this->get_submission($id)) {
+ $submission = $this->prepare_new_submission($id);
+ $newsubmission = true;
+ } else {
+ $newsubmission = false;
+ }
+ unset($submission->data1); // Don't need to update this.
+ unset($submission->data2); // Don't need to update this.
+
+ //for fast grade, we need to check if any changes take place
+ $updatedb = false;
+
+ if ($commenting) {
+ $commentvalue = trim($_POST['submissioncomment'][$id]);
+ $updatedb = $updatedb || ($submission->submissioncomment != stripslashes($commentvalue));
+ $submission->submissioncomment = $commentvalue;
+ } else {
+ unset($submission->submissioncomment); // Don't need to update this.
+ }
+
+ $submission->teacher = $USER->id;
+ if ($updatedb) {
+ $submission->mailed = (int)(!$mailinfo);
+ }
+
+ $submission->timemarked = time();
+
+ //if it is not an update, we don't change the last modified time etc.
+ //this will also not write into database if no submissioncomment and grade is entered.
+
+ if ($updatedb){
+ if ($newsubmission) {
+ if (!isset($submission->submissioncomment)) {
+ $submission->submissioncomment = '';
+ }
+ if (!$sid = insert_record('print_submissions', $submission)) {
+ return false;
+ }
+ $submission->id = $sid;
+ } else {
+ if (!update_record('print_submissions', $submission)) {
+ return false;
+ }
+ }
+
+ // triger grade event
+ $this->update_grade($submission);
+
+ //add to log only if updating
+ add_to_log($this->course->id, 'print', 'update grades',
+ 'submissions.php?id='.$this->printconfig->id.'&user='.$submission->userid,
+ $submission->userid, $this->cm->id);
+ }
+
+ }
+
+ $message = notify(get_string('changessaved'), 'notifysuccess', 'center', true);
+
+ $this->display_submissions($message);
+ break;
+
+
+ case 'next':
+ /// We are currently in pop up, but we want to skip to next one without saving.
+ /// This turns out to be similar to a single case
+ /// The URL used is for the next submission.
+
+ $this->display_submission();
+ break;
+
+ case 'saveandnext':
+ ///We are in pop up. save the current one and go to the next one.
+ //first we save the current changes
+ if ($submission = $this->process_feedback()) {
+ //print_heading(get_string('changessaved'));
+ $extra_javascript = $this->update_main_listing($submission);
+ }
+
+ //then we display the next submission
+ $this->display_submission($extra_javascript);
+ break;
+
+ default:
+ echo "something seriously is wrong!!";
+ break;
+ }
+
+}
+ function display_submissions($message='') {
+ global $CFG, $db, $USER;
+ require_once($CFG->libdir.'/gradelib.php');
+
+ /* first we check to see if the form has just been submitted
+ * to request user_preference updates
+ */
+
+ if (isset($_POST['updatepref'])){
+ $perpage = optional_param('perpage', 10, PARAM_INT);
+ $perpage = ($perpage <= 0) ? 10 : $perpage ;
+ set_user_preference('assignment_perpage', $perpage);
+ set_user_preference('assignment_quickgrade', optional_param('quickgrade', 0, PARAM_BOOL));
+ }
+
+ /* next we get perpage and quickgrade (allow quick grade) params
+ * from database
+ */
+ $perpage = get_user_preferences('assignment_perpage', 10);
+
+
+ if (!empty($CFG->enableoutcomes) and !empty($grading_info->outcomes)) {
+ $uses_outcomes = true;
+ } else {
+ $uses_outcomes = false;
+ }
+
+ $page = optional_param('page', 0, PARAM_INT);
+ $strsaveallfeedback = get_string('saveallfeedback', 'assignment');
+
+ /// Some shortcuts to make the code read better
+
+ $course = $this->course;
+ $assignment = $this->printconfig;
+ $cm = $this->cm;
+
+ $tabindex = 1; //tabindex for quick grading tabbing; Not working for dropdowns yet
+ add_to_log($course->id, 'print', 'view submission', 'submissions.php?id='.$this->cm->id, $this->printconfig->id, $this->cm->id);
+ $navigation = build_navigation('submissions', $this->cm);
+ print_header_simple(format_string($this->printconfig->name,true), "", $navigation,
+ '', '', true, update_module_button($cm->id, $course->id, 'print'), navmenu($course, $cm));
+
+ $course_context = get_context_instance(CONTEXT_COURSE, $course->id);
+
+
+ if (!empty($message)) {
+ echo $message; // display messages here if any
+ }
+
+ $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+
+ /// Check to see if groups are being used in this assignment
+
+ /// find out current groups mode
+ $groupmode = groups_get_activity_groupmode($cm);
+ $currentgroup = groups_get_activity_group($cm, true);
+ groups_print_activity_menu($cm, 'submissions.php?id=' . $this->cm->id);
+
+ /// Get all ppl that are allowed to submit assignments
+ if ($users = get_users_by_capability($context, 'mod/print:submit', 'u.id', '', '', '', $currentgroup, '', false)) {
+ $users = array_keys($users);
+ }
+
+ // if groupmembersonly used, remove users who are not in any group
+ if ($users and !empty($CFG->enablegroupings) and $cm->groupmembersonly) {
+ if ($groupingusers = groups_get_grouping_members($cm->groupingid, 'u.id', 'u.id')) {
+ $users = array_intersect($users, array_keys($groupingusers));
+ }
+ }
+
+ $tablecolumns = array('picture', 'fullname', 'status', 'submissions');
+
+
+ $tableheaders = array('',
+ get_string('fullname'),
+ get_string('status'),
+ 'submissions');
+
+ require_once($CFG->libdir.'/tablelib.php');
+ $table = new flexible_table('mod-print-submissions');
+
+ $table->define_columns($tablecolumns);
+ $table->define_headers($tableheaders);
+ $table->define_baseurl($CFG->wwwroot.'/mod/print/submissions.php?id='.$this->cm->id.'&amp;currentgroup='.$currentgroup);
+
+ $table->sortable(true, 'lastname');//sorted by lastname by default
+ $table->collapsible(true);
+ $table->initialbars(true);
+
+ $table->column_suppress('picture');
+ $table->column_suppress('fullname');
+
+ $table->column_class('picture', 'picture');
+ $table->column_class('fullname', 'fullname');
+ $table->column_class('status', 'status');
+ $table->column_class('submissions','submissions');
+
+ $table->set_attribute('cellspacing', '0');
+ $table->set_attribute('id', 'attempts');
+ $table->set_attribute('class', 'submissions');
+ $table->set_attribute('width', '100%');
+ $table->set_attribute('align', 'center');
+
+ $table->no_sorting('outcome');
+
+ // Start working -- this is necessary as soon as the niceties are over
+ $table->setup();
+
+ if (empty($users)) {
+ print_heading(get_string('nosubmitusers','assignment'));
+ return true;
+ }
+
+ /// Construct the SQL
+
+ if ($where = $table->get_sql_where()) {
+ $where .= ' AND ';
+ }
+
+ if ($sort = $table->get_sql_sort()) {
+ $sort = ' ORDER BY '.$sort;
+ }
+
+ $select = 'SELECT u.id, u.firstname, u.lastname, u.picture, u.imagealt,
+ s.id AS submissionid,
+ COALESCE(SIGN(SIGN(s.timemarked) + SIGN(s.timemarked - s.timemodified)), 0) AS status ';
+ $sql = 'FROM '.$CFG->prefix.'user u '.
+ 'LEFT JOIN '.$CFG->prefix.'print_submissions s ON u.id = s.userid
+ AND s.assignment = '.$this->printconfig->id.' '.
+ 'WHERE '.$where.'u.id IN ('.implode(',',$users).') ';
+
+ $table->pagesize($perpage, count($users));
+
+ ///offset used to calculate index of student in that particular query, needed for the pop up to know who's next
+ $offset = $page * $perpage;
+
+ $strupdate = get_string('update');
+ $strgrade = get_string('grade');
+ #$grademenu = make_grades_menu($this->printconfig->grade);
+
+ if (($ausers = get_records_sql($select.$sql.$sort, $table->get_page_start(), $table->get_page_size())) !== false) {
+ foreach ($ausers as $auser) {
+
+ /// Calculate user status
+ $picture = print_user_picture($auser, $course->id, $auser->picture, false, true);
+
+
+ if (empty($auser->status)) { /// Confirm we have exclusively 0 or 1
+ $auser->status = 0;
+ } else {
+ $auser->status = 1;
+ }
+
+ $buttontext = ($auser->status == 1) ? $strupdate : $strgrade;
+
+ ///No more buttons, we use popups ;-).
+ $popup_url = '/mod/print/submissions.php?id='.$this->cm->id
+ . '&amp;userid='.$auser->id.'&amp;mode=single'.'&amp;offset='.$offset++;
+ $button = link_to_popup_window ($popup_url, 'grade'.$auser->id, $buttontext, 600, 780,
+ $buttontext, 'none', true, 'button'.$auser->id);
+
+ $status = '<div id="up'.$auser->id.'" class="s'.$auser->status.'">'.$button.'</div>';
+ $url = $this->print_user_files($auser->id,true,true);
+ $submissions = '<div id="down'.$auser->id.'" class="s'.$auser->status.'">'.$url.'</div>';
+
+ $userlink = '<a href="' . $CFG->wwwroot . '/user/view.php?id=' . $auser->id . '&amp;course=' . $course->id . '">' . fullname($auser) . '</a>';
+ $row = array($picture, $userlink, $status, $submissions);
+ if ($uses_outcomes) {
+ $row[] = $outcomes;
+ }
+
+ $table->add_data($row);
+ }
+ }
+
+
+ /// Print quickgrade form around the table
+ echo '<form action="submissions.php" id="fastg" method="post">';
+ echo '<div>';
+ echo '<input type="hidden" name="id" value="'.$this->cm->id.'" />';
+ echo '<input type="hidden" name="mode" value="fastgrade" />';
+ echo '<input type="hidden" name="page" value="'.$page.'" />';
+ echo '</div>';
+
+ $table->print_html(); /// Print the whole table
+
+ $lastmailinfo = get_user_preferences('assignment_mailinfo', 1) ? 'checked="checked"' : '';
+ echo '<div class="fgcontrols">';
+ echo '<div class="emailnotification">';
+ echo '<label for="mailinfo">'.get_string('enableemailnotification','assignment').'</label>';
+ echo '<input type="hidden" name="mailinfo" value="0" />';
+ echo '<input type="checkbox" id="mailinfo" name="mailinfo" value="1" '.$lastmailinfo.' />';
+ helpbutton('emailnotification', get_string('enableemailnotification', 'assignment'), 'assignment').'</p></div>';
+ echo '</div>';
+ echo '<div class="fastgbutton"><input type="submit" name="fastg" value="'.get_string('saveallfeedback', 'assignment').'" /></div>';
+ echo '</div>';
+ echo '</form>';
+ /// End of fast grading form
+
+ /// Mini form for setting user preference
+ echo '<div class="qgprefs">';
+ echo '<form id="options" action="submissions.php?id='.$this->cm->id.'" method="post"><div>';
+ echo '<input type="hidden" name="updatepref" value="1" />';
+ echo '<table id="optiontable">';
+ echo '<tr><td>';
+ echo '<label for="perpage">'.get_string('pagesize','assignment').'</label>';
+ echo '</td>';
+ echo '<td>';
+ echo '<input type="text" id="perpage" name="perpage" size="1" value="'.$perpage.'" />';
+ helpbutton('pagesize', get_string('pagesize','assignment'), 'assignment');
+ echo '</td></tr>';
+ echo '<tr><td>';
+ echo '</td>';
+ echo '<td>';
+ echo '</td></tr>';
+ echo '<tr><td colspan="2">';
+ echo '<input type="submit" value="'.get_string('savepreferences').'" />';
+ echo '</td></tr></table>';
+ echo '</div></form></div>';
+ ///End of mini form
+# print_footer($this->course);
+ }
+
+
+
+ function printit($file) {
+ printit_real($file);
+ }
+
+
+ function submittedlink($allgroups=false) {
+ global $USER;
+
+ $submitted = '';
+
+ $context = get_context_instance(CONTEXT_MODULE,$this->cm->id);
+ if ($allgroups and has_capability('moodle/site:accessallgroups', $context)) {
+ $group = 0;
+ } else {
+ $group = groups_get_activity_group($this->cm);
+ }
+ if (has_capability('moodle/site:accessallgroups', $context)) {
+ if ($count = $this->count_real_submissions($group)) {
+ $submitted = '<a href="submissions.php?id='.$this->cm->id.'">'.
+ get_string('viewsubmissions', 'assignment', $count).'</a>';
+ } else {
+ $submitted = '<a href="submissions.php?id='.$this->cm->id.'">'.
+ get_string('noattempts', 'assignment').'</a>';
+ }
+ } else {
+ $submitted = '';
+ }
+ return $submitted;
+ }
+ function count_real_submissions($groupid=0) {
+ return print_count_real_submissions($this->cm, $groupid);
+ }
+
+ function print_user_files($userid=0, $return=false, $url=false) {
+ global $CFG, $USER;
+
+ $mode = optional_param('mode', '', PARAM_ALPHA);
+ $offset = optional_param('offset', 0, PARAM_INT);
+
+ if (!$userid) {
+ if (!isloggedin()) {
+ return '';
+ }
+ $userid = $USER->id;
+ }
+ $filearea = $this->file_area_name($userid);
+
+ $output = '';
+
+ if ($submissions = $this->get_submissions1($userid)) {
+ foreach ($submissions as $submission) {
+ $candelete = $this->can_delete_files($submission);
+ }
+ }
+ $strdelete = get_string('delete');
+
+ $output .= '<strong>'.get_string('draft', 'assignment').':</strong><br />';
+
+
+ if ($basedir = $this->file_area($userid)) {
+ if ($files = get_directory_list($basedir, 'responses')) {
+ require_once($CFG->libdir.'/filelib.php');
+ foreach ($files as $key => $file) {
+
+ $icon = mimeinfo('icon', $file);
+ $ffurl = get_file_url("$filearea/$file");
+ if(!$url) {
+ $output .= '<a href="'.$ffurl.'" ><img src="'.$CFG->pixpath.'/f/'.$icon.'" class="icon" alt="'.$icon.'" />'.$file.'</a>';
+ }
+ if ($url){
+ $path = $basedir.'/'.$file;
+ $output .= '<a href="'.$ffurl.'" ><img src="'.$CFG->pixpath.'/f/'.$icon.'" class="icon" alt="'.$icon.'" />'.$file.'</a>'.
+ '<form action="submissions.php" method="post">'.
+ '<input type="hidden" name="path" value="'.$path.'">'.
+ '<input type="submit" name="SUBMIT" value="Print">'.
+ '</form>';
+ $sql = "SELECT userid
+ FROM {$CFG->prefix}print_submissions
+ WHERE filepath = '$path'
+ AND assignment = '{$this->printconfig->id}'";
+ $submission = get_record_sql($sql);
+ $candelete = true;
+ }
+ if ($candelete) {
+ $delurl = "$CFG->wwwroot/mod/print/delete.php?id={$this->cm->id}&amp;file=$file&amp;userid={$submission->userid}&amp;mode=$mode&amp;offset=$offset";
+
+ $output .= '<a href="'.$delurl.'">&nbsp;'
+ .'<img title="'.$strdelete.'" src="'.$CFG->pixpath.'/t/delete.gif" class="iconsmall" alt="" /></a> ';
+ }
+
+ $output .= '<br />';
+ }
+ }
+ }
+
+
+ $output = '<div class="files">'.$output.'</div>';
+
+ if ($return) {
+ return $output;
+ }
+ echo $output;
+
+}
+ function print_get_path($userid) {
+ global $CFG;
+ $sql = "SELECT filepath
+ FROM {$CFG->prefix}print_submissions
+ WHERE userid = '$userid'
+ AND assignment = '{$this->printconfig->id}'";
+ $records = get_records_sql($sql);
+
+ return $records;
+
+ }
+
+ function delete() {
+ $action = optional_param('action', '', PARAM_ALPHA);
+
+ switch ($action) {
+ case 'response':
+ $this->delete_responsefile();
+ break;
+ default:
+ $this->delete_file();
+ }
+ die;
+ }
+ function delete_file() {
+ global $CFG;
+
+ $file = required_param('file', PARAM_FILE);
+ $userid = required_param('userid', PARAM_INT);
+ $confirm = optional_param('confirm', 0, PARAM_BOOL);
+ $mode = optional_param('mode', '', PARAM_ALPHA);
+ $offset = optional_param('offset', 0, PARAM_INT);
+
+ require_login($this->course->id, false, $this->cm);
+
+ if (empty($mode)) {
+ $urlreturn = 'view.php';
+ $optionsreturn = array('id'=>$this->cm->id);
+ $returnurl = 'view.php?id='.$this->cm->id;
+ } else {
+ $urlreturn = 'submissions.php';
+ $optionsreturn = array('id'=>$this->cm->id, 'offset'=>$offset, 'mode'=>$mode, 'userid'=>$userid);
+ $returnurl = "submissions.php?id={$this->cm->id}&amp;offset=$offset&amp;mode=$mode&amp;userid=$userid";
+ }
+
+
+ $dir = $this->file_area_name($userid);
+
+ if (!data_submitted('nomatch') or !$confirm) {
+ $optionsyes = array ('id'=>$this->cm->id, 'file'=>$file, 'userid'=>$userid, 'confirm'=>1, 'sesskey'=>sesskey(), 'mode'=>$mode, 'offset'=>$offset);
+ if (empty($mode)) {
+ #$this->view_header(get_string('delete'));
+ } else {
+ print_header(get_string('delete'));
+ }
+ print_heading(get_string('delete'));
+ notice_yesno(get_string('confirmdeletefile', 'assignment', $file), 'delete.php', $urlreturn, $optionsyes, $optionsreturn, 'post', 'get');
+ if (empty($mode)) {
+ #$this->view_footer();
+ } else {
+ print_footer('none');
+ }
+ die;
+ }
+
+ $filepath = $CFG->dataroot.'/'.$dir.'/'.$file;
+ if (file_exists($filepath)) {
+ if (@unlink($filepath)) {
+ $sql = "DELETE
+ FROM {$CFG->prefix}print_submissions
+ WHERE filepath = '$filepath'
+ AND assignment = '{$this->printconfig->id}'";
+ get_records_sql($sql);
+ redirect($returnurl);
+ }
+ }
+
+ // print delete error
+ if (empty($mode)) {
+ #$this->view_header(get_string('delete'));
+ } else {
+ #print_header(get_string('delete'));
+ }
+ notify(get_string('deletefilefailed', 'assignment'));
+ print_continue($returnurl);
+ if (empty($mode)) {
+ # $this->view_footer();
+ } else {
+ #print_footer('none');
+ }
+ die;
+ }
+
+ function can_delete_files($submission) {
+ global $USER;
+
+
+ if (has_capability('mod/print:submit', $this->context)
+ and $USER->id == $submission->userid) { // no deleting after final submission
+ return true;
+ } else {
+ return false;
+ }
+ }
+ function upload() {
+ $action = required_param('action', PARAM_ALPHA);
+
+ $this->upload_file();
+ }
+
+ function count_user_files($userid) {
+ global $CFG;
+
+ $filearea = $this->file_area_name($userid);
+
+ if ( is_dir($CFG->dataroot.'/'.$filearea) && $basedir = $this->file_area($userid)) {
+ if ($files = get_directory_list($basedir)) {
+ return count($files);
+ }
+ }
+ return 0;
+ }
+ function setup_elements(&$mform) {
+ global $CFG, $COURSE;
+
+ $ynoptions = array( 0 => get_string('no'), 1 => get_string('yes'));
+
+ $choices = get_max_upload_sizes($CFG->print_maxbytes, 0);
+ $choices[0] = get_string('courseuploadlimit') . ' ('.display_size($CFG->print_maxbytes).')';
+ $mform->addElement('select', 'maxbytes', get_string('maximumsize', 'assignment'), $choices);
+ $mform->setDefault('maxbytes', $CFG->print_maxbytes);
+
+ $options = array();
+ for($i = 1; $i <= 20; $i++) {
+ $options[$i] = $i;
+ }
+ $mform->addElement('select', 'var1', get_string("allowmaxfiles", "assignment"), $options);
+ $mform->setHelpButton('var1', array('allowmaxfiles', get_string('allowmaxfiles', 'assignment'), 'assignment'));
+ $mform->setDefault('var1', 3);
+
+
+
+ }
+
+ function view_upload_form() {
+ global $CFG, $USER;
+
+ if(!$this->submissions = get_records_sql($this->check_database("print_submissions"))) {
+ $this->submission = $this->submissions[1];
+ }
+ $struploadafile = get_string('uploadafile');
+ $maxbytes = $this->printconfig->maxbytes == 0 ? $this->course->maxbytes : $this->printconfig->maxbytes;
+ $strmaxsize = get_string('maxsize', '', display_size($maxbytes));
+
+
+ if ($this->can_upload_file($this->submission)) {
+ echo '<div style="text-align:center">';
+ echo '<form enctype="multipart/form-data" method="post" action="upload.php">';
+ echo '<fieldset class="invisiblefieldset">';
+ echo "<p>$struploadafile ($strmaxsize)</p>";
+ echo '<input type="hidden" name="id" value="'.$this->cm->id.'" />';
+ echo '<input type="hidden" name="action" value="uploadfile" />';
+ require_once($CFG->libdir.'/uploadlib.php');
+ upload_print_form_fragment(1,array('newfile'),null,false,null,0,$this->printconfig->maxbytes,false);
+ echo '<input type="submit" name="save" value="'.get_string('uploadthisfile').'" />';
+ echo '</fieldset>';
+ echo '</form>';
+ echo '</div>';
+ echo '<br />';
+ }
+
+ }
+ function upload_file() {
+ global $CFG, $USER;
+
+ $mode = optional_param('mode', '', PARAM_ALPHA);
+ $offset = optional_param('offset', 0, PARAM_INT);
+
+ $returnurl = 'view.php?id='.$this->cm->id;
+
+ $filecount = $this->count_user_files($USER->id);
+ $submission = $this->get_submission($USER->id);
+
+ if (!$this->can_upload_file($submission)) {
+ $this->view_header(get_string('upload'));
+ notify(get_string('uploaderror', 'assignment'));
+ print_continue($returnurl);
+ # $this->view_footer();
+ die;
+ }
+
+ $dir = $this->file_area_name($USER->id);
+ check_dir_exists($CFG->dataroot.'/'.$dir, true, true); // better to create now so that student submissions do not block it later
+
+ require_once($CFG->dirroot.'/lib/uploadlib.php');
+ $um = new upload_manager('newfile',false,true,$this->course,false,$this->printconfig->maxbytes,true);
+
+ if ($um->process_file_uploads($dir)) {
+ $updated = new object();
+ $updated->assignment = $this->printconfig->id;
+ $updated->id = $submission->id;
+ $updated->timemodified = time();
+ $updated->filepath = $um->get_new_filepath();
+ $updated->userid = $USER->id;
+
+ if (insert_record('print_submissions', $updated)) {
+ add_to_log($this->course->id, 'print', 'upload',
+ 'view.php?a='.$this->printconfig->id, $this->printconfig->id, $this->cm->id);
+ $submission = $this->get_submission($USER->id);
+ } else {
+ $new_filename = $um->get_new_filename();
+ $this->view_header(get_string('upload'));
+ notify(get_string('uploadnotregistered', 'assignment', $new_filename));
+ print_continue($returnurl);
+ # $this->view_footer();
+ die;
+ }
+ redirect('view.php?id='.$this->cm->id);
+ }
+ $this->view_header(get_string('upload'));
+ notify(get_string('uploaderror', 'assignment'));
+ echo $um->get_errors();
+ print_continue($returnurl);
+ #$this->view_footer();
+ die;
+ }
+
+ function upload_xmlrpc($filepath, $userid, $title, $id) {
+ $updated = new object();
+ $updated->timemodified = time();
+ $updated->filepath = $filepath;
+ $updated->userid = $userid;
+ $updated->assignment = $id;
+ insert_record('print_submissions', $updated);
+ return 1;
+ }
+
+ function get_submissions1($userid=0, $createnew=false, $teachermodified=false) {
+ global $USER;
+
+ if (empty($userid)) {
+ $userid = $USER->id;
+ }
+
+ $submission = get_records('print_submissions', 'userid', $userid);
+ #print var_dump($submission);
+ if ($submission || !$createnew) {
+ return $submission;
+ }
+ $newsubmission = $this->prepare_new_submission($userid, $teachermodified);
+ if (!insert_record("print_submissions", $newsubmission)) {
+ error("Could not insert a new empty submission");
+ }
+
+ return get_record('print_submissions', 'assignment', $this->printconfig->id, 'userid', $userid);
+ }
+
+ function get_submission($userid=0, $createnew=false, $teachermodified=false) {
+ global $USER;
+
+ if (empty($userid)) {
+ $userid = $USER->id;
+ }
+
+ $submission = get_record('print_submissions', 'userid', $userid);
+ #print var_dump($submission);
+ if ($submission || !$createnew) {
+ return $submission;
+ }
+ $newsubmission = $this->prepare_new_submission($userid, $teachermodified);
+ if (!insert_record("print_submissions", $newsubmission)) {
+ error("Could not insert a new empty submission");
+ }
+
+ return get_record('print_submissions', 'assignment', $this->printconfig->id, 'userid', $userid);
+ }
+
+ function prepare_new_submission($userid, $teachermodified=false) {
+ $submission = new Object;
+ $submission->assignment = $this->printconfig->id;
+ $submission->userid = $userid;
+ //$submission->timecreated = time();
+ $submission->timecreated = '';
+ // teachers should not be modifying modified date, except offline assignments
+ if ($teachermodified) {
+ $submission->timemodified = 0;
+ } else {
+ $submission->timemodified = $submission->timecreated;
+ }
+ $submission->numfiles = 0;
+ $submission->data1 = '';
+ $submission->data2 = '';
+ $submission->grade = -1;
+ $submission->submissioncomment = '';
+ $submission->format = 0;
+ $submission->teacher = 0;
+ $submission->timemarked = 0;
+ $submission->mailed = 0;
+ return $submission;
+ }
+ function file_area_name($userid) {
+ global $CFG;
+
+ return $this->course->id.'/'.$CFG->moddata.'/print/'.$this->printconfig->id.'/'.$userid;
+ }
+
+ function file_area($userid) {
+ return make_upload_directory( $this->file_area_name($userid) );
+ }
+
+
+ function can_upload_file($submission) {
+ global $USER;
+
+ if (has_capability('mod/print:submit', $this->context) // can submit
+ // assignment not closed yet
+ and (empty($submission) or $submission->userid == $USER->id)) { // no uploading after final submission
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+
+ function get_submissions($sort='', $dir='DESC') {
+ return print_get_all_submissions($this->printconfig, $sort, $dir);
+ }
+}
+
+function print_count_real_submissions($cm, $groupid=0) {
+ global $CFG;
+
+ $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+
+ // this is all the users with this capability set, in this context or higher
+ if ($users = get_users_by_capability($context, 'mod/print:submit', 'u.id', '', '', '', $groupid, '', false)) {
+ $users = array_keys($users);
+ }
+
+ // if groupmembersonly used, remove users who are not in any group
+ if ($users and !empty($CFG->enablegroupings) and $cm->groupmembersonly) {
+ if ($groupingusers = groups_get_grouping_members($cm->groupingid, 'u.id', 'u.id')) {
+ $users = array_intersect($users, array_keys($groupingusers));
+ }
+ }
+
+ if (empty($users)) {
+ return 0;
+ }
+
+ $userlists = implode(',', $users);
+
+ return count_records_sql("SELECT COUNT('x')
+ FROM {$CFG->prefix}print_submissions
+ WHERE assignment = $cm->instance AND
+ timemodified > 0 AND
+ userid IN ($userlists)");
+}
+
+
+function print_get_all_submissions($assignment, $sort="", $dir="DESC") {
+/// Return all assignment submissions by ENROLLED students (even empty)
+ global $CFG;
+
+ if ($sort == "lastname" or $sort == "firstname") {
+ $sort = "u.$sort $dir";
+ } else if (empty($sort)) {
+ $sort = "a.timemodified DESC";
+ } else {
+ $sort = "a.$sort $dir";
+ }
+
+ /* not sure this is needed at all since assignmenet already has a course define, so this join?
+ $select = "s.course = '$assignment->course' AND";
+ if ($assignment->course == SITEID) {
+ $select = '';
+ }*/
+
+ return get_records_sql("SELECT a.*
+ FROM {$CFG->prefix}print_submissions a,
+ {$CFG->prefix}user u
+ WHERE u.id = a.userid
+ AND a.assignment = '$assignment->id'
+ ORDER BY $sort");
+
+ /* return get_records_sql("SELECT a.*
+ FROM {$CFG->prefix}assignment_submissions a,
+ {$CFG->prefix}user_students s,
+ {$CFG->prefix}user u
+ WHERE a.userid = s.userid
+ AND u.id = a.userid
+ AND $select a.assignment = '$assignment->id'
+ ORDER BY $sort");
+ */
+}
+
+function print_add_instance($print) {
+
+
+ $print->timemodified = time();
+ $print->courseid = $print->course;
+
+ # You may have to add extra stuff in here #
+
+ return insert_record('print', $print);
+}
+
+
+/**
+ * Given an object containing all the necessary data,
+ * (defined by the form in mod_form.php) this function
+ * will update an existing instance with new data.
+ *
+ * @param object $print An object from the form in mod_form.php
+ * @return boolean Success/Fail
+ */
+function print_update_instance($print) {
+
+ $print->timemodified = time();
+ $print->id = $print->instance;
+
+ # You may have to add extra stuff in here #
+
+ return update_record('print', $print);
+}
+
+
+/**
+ * Given an ID of an instance of this module,
+ * this function will permanently delete the instance
+ * and any data that depends on it.
+ *
+ * @param int $id Id of the module instance
+ * @return boolean Success/Failure
+ */
+function print_delete_instance($id) {
+
+ if (! $print = get_record('print', 'id', $id)) {
+ return false;
+ }
+
+ $result = true;
+
+ # Delete any dependent records here #
+
+ if (! delete_records('print', 'id', $print->id)) {
+ $result = false;
+ }
+
+ return $result;
+}
+
+
+/**
+ * Return a small object with summary information about what a
+ * user has done with a given particular instance of this module
+ * Used for user activity reports.
+ * $return->time = the time they did it
+ * $return->info = a short text description
+ *
+ * @return null
+ * @todo Finish documenting this function
+ */
+function print_user_outline($course, $user, $mod, $print) {
+ return $return;
+}
+
+
+/**
+ * Print a detailed representation of what a user has done with
+ * a given particular instance of this module, for user activity reports.
+ *
+ * @return boolean
+ * @todo Finish documenting this function
+ */
+function print_user_complete($course, $user, $mod, $print) {
+ return true;
+}
+
+
+/**
+ * Given a course and a time, this module should find recent activity
+ * that has occurred in print activities and print it out.
+ * Return true if there was output, or false is there was none.
+ *
+ * @return boolean
+ * @todo Finish documenting this function
+ */
+function print_print_recent_activity($course, $isteacher, $timestart) {
+ return false; // True if anything was printed, otherwise false
+}
+
+
+/**
+ * Function to be run periodically according to the moodle cron
+ * This function searches for things that need to be done, such
+ * as sending out mail, toggling flags etc ...
+ *
+ * @return boolean
+ * @todo Finish documenting this function
+ **/
+function print_cron () {
+ return true;
+}
+
+
+/**
+ * Must return an array of user records (all data) who are participants
+ * for a given instance of print. Must include every user involved
+ * in the instance, independient of his role (student, teacher, admin...)
+ * See other modules as example.
+ *
+ * @param int $printid ID of an instance of this module
+ * @return mixed boolean/array of students
+ */
+function print_get_participants($printid) {
+ return false;
+}
+
+
+/**
+ * This function returns if a scale is being used by one print
+ * if it has support for grading and scales. Commented code should be
+ * modified if necessary. See forum, glossary or journal modules
+ * as reference.
+ *
+ * @param int $printid ID of an instance of this module
+ * @return mixed
+ * @todo Finish documenting this function
+ */
+function print_scale_used($printid, $scaleid) {
+ $return = false;
+
+ //$rec = get_record("print","id","$printid","scale","-$scaleid");
+ //
+ //if (!empty($rec) && !empty($scaleid)) {
+ // $return = true;
+ //}
+
+ return $return;
+}
+
+
+/**
+ * Checks if scale is being used by any instance of print.
+ * This function was added in 1.9
+ *
+ * This is used to find out if scale used anywhere
+ * @param $scaleid int
+ * @return boolean True if the scale is used by any print
+ */
+function print_scale_used_anywhere($scaleid) {
+ if ($scaleid and record_exists('print', 'grade', -$scaleid)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+/**
+ * Execute post-install custom actions for the module
+ * This function was added in 1.9
+ *
+ * @return boolean true if success, false on error
+ */
+function print_install() {
+ return true;
+}
+
+function printit_real($file) {
+
+ require_once('PrintIPP.php');
+ require_once('CupsPrintIPP.php');
+ $ipp = new CupsPrintIPP;
+ $ipp->getPrinters();
+ $uri = $ipp->available_printers[0];
+ #$ipp->setUserName($username='iwikiwi@localhost');
+ #$ipp->setAuthentication('iwikiwi@localhost','dbzdbz');
+ $ipp->setHost("localhost");
+ $ipp->setPrinterURI($uri);
+ $ipp->setLog('log.txt');
+ $ipp->setData($file); // Path to file.
+ $ipp->printJob();
+
+}
+
+
+/**
+ * Execute post-uninstall custom actions for the module
+ * This function was added in 1.9
+ *
+ * @return boolean true if success, false on error
+ */
+function print_uninstall() {
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////
+/// Any other print functions go here. Each of them must have a name that
+/// starts with print_
+/// Remember (see note in first lines) that, if this section grows, it's HIGHLY
+/// recommended to move all funcions below to a new "localib.php" file.
+
+
+?>
diff --git a/Moodle/mod/print/lib11.php b/Moodle/mod/print/lib11.php
new file mode 100755
index 0000000..7b011f7
--- /dev/null
+++ b/Moodle/mod/print/lib11.php
@@ -0,0 +1,3090 @@
+<?PHP // $Id$
+/**
+ * assignment_base is the base class for assignment types
+ *
+ * This class provides all the functionality for an assignment
+ */
+
+DEFINE ('ASSIGNMENT_COUNT_WORDS', 1);
+DEFINE ('ASSIGNMENT_COUNT_LETTERS', 2);
+
+/**
+ * Standard base class for all assignment submodules (assignment types).
+ */
+class assignment_base {
+
+ var $cm;
+ var $course;
+ var $assignment;
+ var $strassignment;
+ var $strassignments;
+ var $strsubmissions;
+ var $strlastmodified;
+ var $pagetitle;
+ var $usehtmleditor;
+ var $defaultformat;
+ var $context;
+ var $type;
+
+ /**
+ * Constructor for the base assignment class
+ *
+ * Constructor for the base assignment class.
+ * If cmid is set create the cm, course, assignment objects.
+ * If the assignment is hidden and the user is not a teacher then
+ * this prints a page header and notice.
+ *
+ * @param cmid integer, the current course module id - not set for new assignments
+ * @param assignment object, usually null, but if we have it we pass it to save db access
+ * @param cm object, usually null, but if we have it we pass it to save db access
+ * @param course object, usually null, but if we have it we pass it to save db access
+ */
+ function assignment_base($cmid='staticonly', $assignment=NULL, $cm=NULL, $course=NULL) {
+ global $COURSE;
+
+ if ($cmid == 'staticonly') {
+ //use static functions only!
+ return;
+ }
+
+ global $CFG;
+
+ if ($cm) {
+ $this->cm = $cm;
+ } else if (! $this->cm = get_coursemodule_from_id('assignment', $cmid)) {
+ error('Course Module ID was incorrect');
+ }
+
+ $this->context = get_context_instance(CONTEXT_MODULE, $this->cm->id);
+
+ if ($course) {
+ $this->course = $course;
+ } else if ($this->cm->course == $COURSE->id) {
+ $this->course = $COURSE;
+ } else if (! $this->course = get_record('course', 'id', $this->cm->course)) {
+ error('Course is misconfigured');
+ }
+
+ if ($assignment) {
+ $this->assignment = $assignment;
+ } else if (! $this->assignment = get_record('assignment', 'id', $this->cm->instance)) {
+ error('assignment ID was incorrect');
+ }
+
+ $this->assignment->cmidnumber = $this->cm->id; // compatibility with modedit assignment obj
+ $this->assignment->courseid = $this->course->id; // compatibility with modedit assignment obj
+
+ $this->strassignment = get_string('modulename', 'assignment');
+ $this->strassignments = get_string('modulenameplural', 'assignment');
+ $this->strsubmissions = get_string('submissions', 'assignment');
+ $this->strlastmodified = get_string('lastmodified');
+ $this->pagetitle = strip_tags($this->course->shortname.': '.$this->strassignment.': '.format_string($this->assignment->name,true));
+
+ // visibility handled by require_login() with $cm parameter
+ // get current group only when really needed
+
+ /// Set up things for a HTML editor if it's needed
+ if ($this->usehtmleditor = can_use_html_editor()) {
+ $this->defaultformat = FORMAT_HTML;
+ } else {
+ $this->defaultformat = FORMAT_MOODLE;
+ }
+ }
+
+ /**
+ * Display the assignment, used by view.php
+ *
+ * This in turn calls the methods producing individual parts of the page
+ */
+ function view() {
+
+ $context = get_context_instance(CONTEXT_MODULE,$this->cm->id);
+ require_capability('mod/assignment:view', $context);
+
+ add_to_log($this->course->id, "assignment", "view", "view.php?id={$this->cm->id}",
+ $this->assignment->id, $this->cm->id);
+
+ $this->view_header();
+
+ $this->view_intro();
+
+ $this->view_dates();
+
+ $this->view_feedback();
+
+ $this->view_footer();
+ }
+
+ /**
+ * Display the header and top of a page
+ *
+ * (this doesn't change much for assignment types)
+ * This is used by the view() method to print the header of view.php but
+ * it can be used on other pages in which case the string to denote the
+ * page in the navigation trail should be passed as an argument
+ *
+ * @param $subpage string Description of subpage to be used in navigation trail
+ */
+ function view_header($subpage='') {
+
+ global $CFG;
+
+
+ if ($subpage) {
+ $navigation = build_navigation($subpage, $this->cm);
+ } else {
+ $navigation = build_navigation('', $this->cm);
+ }
+
+ print_header($this->pagetitle, $this->course->fullname, $navigation, '', '',
+ true, update_module_button($this->cm->id, $this->course->id, $this->strassignment),
+ navmenu($this->course, $this->cm));
+
+ groups_print_activity_menu($this->cm, 'view.php?id=' . $this->cm->id);
+
+ echo '<div class="reportlink">'.$this->submittedlink().'</div>';
+ echo '<div class="clearer"></div>';
+ }
+
+
+ /**
+ * Display the assignment intro
+ *
+ * This will most likely be extended by assignment type plug-ins
+ * The default implementation prints the assignment description in a box
+ */
+ function view_intro() {
+ print_simple_box_start('center', '', '', 0, 'generalbox', 'intro');
+ $formatoptions = new stdClass;
+ $formatoptions->noclean = true;
+ echo format_text($this->assignment->description, $this->assignment->format, $formatoptions);
+ print_simple_box_end();
+ }
+
+ /**
+ * Display the assignment dates
+ *
+ * Prints the assignment start and end dates in a box.
+ * This will be suitable for most assignment types
+ */
+ function view_dates() {
+ if (!$this->assignment->timeavailable && !$this->assignment->timedue) {
+ return;
+ }
+
+ print_simple_box_start('center', '', '', 0, 'generalbox', 'dates');
+ echo '<table>';
+ if ($this->assignment->timeavailable) {
+ echo '<tr><td class="c0">'.get_string('availabledate','assignment').':</td>';
+ echo ' <td class="c1">'.userdate($this->assignment->timeavailable).'</td></tr>';
+ }
+ if ($this->assignment->timedue) {
+ echo '<tr><td class="c0">'.get_string('duedate','assignment').':</td>';
+ echo ' <td class="c1">'.userdate($this->assignment->timedue).'</td></tr>';
+ }
+ echo '</table>';
+ print_simple_box_end();
+ }
+
+
+ /**
+ * Display the bottom and footer of a page
+ *
+ * This default method just prints the footer.
+ * This will be suitable for most assignment types
+ */
+ function view_footer() {
+ print_footer($this->course);
+ }
+
+ /**
+ * Display the feedback to the student
+ *
+ * This default method prints the teacher picture and name, date when marked,
+ * grade and teacher submissioncomment.
+ *
+ * @param $submission object The submission object or NULL in which case it will be loaded
+ */
+ function view_feedback($submission=NULL) {
+ global $USER, $CFG;
+ require_once($CFG->libdir.'/gradelib.php');
+
+ if (!has_capability('mod/assignment:submit', $this->context, $USER->id, false)) {
+ // can not submit assignments -> no feedback
+ return;
+ }
+
+ if (!$submission) { /// Get submission for this assignment
+ $submission = $this->get_submission($USER->id);
+ }
+
+ $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, $USER->id);
+ $item = $grading_info->items[0];
+ $grade = $item->grades[$USER->id];
+
+ if ($grade->hidden or $grade->grade === false) { // hidden or error
+ return;
+ }
+
+ if ($grade->grade === null and empty($grade->str_feedback)) { /// Nothing to show yet
+ return;
+ }
+
+ $graded_date = $grade->dategraded;
+ $graded_by = $grade->usermodified;
+
+ /// We need the teacher info
+ if (!$teacher = get_record('user', 'id', $graded_by)) {
+ error('Could not find the teacher');
+ }
+
+ /// Print the feedback
+ print_heading(get_string('feedbackfromteacher', 'assignment', $this->course->teacher)); // TODO: fix teacher string
+
+ echo '<table cellspacing="0" class="feedback">';
+
+ echo '<tr>';
+ echo '<td class="left picture">';
+ if ($teacher) {
+ print_user_picture($teacher, $this->course->id, $teacher->picture);
+ }
+ echo '</td>';
+ echo '<td class="topic">';
+ echo '<div class="from">';
+ if ($teacher) {
+ echo '<div class="fullname">'.fullname($teacher).'</div>';
+ }
+ echo '<div class="time">'.userdate($graded_date).'</div>';
+ echo '</div>';
+ echo '</td>';
+ echo '</tr>';
+
+ echo '<tr>';
+ echo '<td class="left side">&nbsp;</td>';
+ echo '<td class="content">';
+ echo '<div class="grade">';
+ echo get_string("grade").': '.$grade->str_long_grade;
+ echo '</div>';
+ echo '<div class="clearer"></div>';
+
+ echo '<div class="comment">';
+ echo $grade->str_feedback;
+ echo '</div>';
+ echo '</tr>';
+
+ echo '</table>';
+ }
+
+ /**
+ * Returns a link with info about the state of the assignment submissions
+ *
+ * This is used by view_header to put this link at the top right of the page.
+ * For teachers it gives the number of submitted assignments with a link
+ * For students it gives the time of their submission.
+ * This will be suitable for most assignment types.
+ * @param bool $allgroup print all groups info if user can access all groups, suitable for index.php
+ * @return string
+ */
+ function submittedlink($allgroups=false) {
+ global $USER;
+
+ $submitted = '';
+
+ $context = get_context_instance(CONTEXT_MODULE,$this->cm->id);
+ if (has_capability('mod/assignment:grade', $context)) {
+ if ($allgroups and has_capability('moodle/site:accessallgroups', $context)) {
+ $group = 0;
+ } else {
+ $group = groups_get_activity_group($this->cm);
+ }
+ if ($count = $this->count_real_submissions($group)) {
+ $submitted = '<a href="submissions.php?id='.$this->cm->id.'">'.
+ get_string('viewsubmissions', 'assignment', $count).'</a>';
+ } else {
+ $submitted = '<a href="submissions.php?id='.$this->cm->id.'">'.
+ get_string('noattempts', 'assignment').'</a>';
+ }
+ } else {
+ if (!empty($USER->id)) {
+ if ($submission = $this->get_submission($USER->id)) {
+ if ($submission->timemodified) {
+ if ($submission->timemodified <= $this->assignment->timedue || empty($this->assignment->timedue)) {
+ $submitted = '<span class="early">'.userdate($submission->timemodified).'</span>';
+ } else {
+ $submitted = '<span class="late">'.userdate($submission->timemodified).'</span>';
+ }
+ }
+ }
+ }
+ }
+
+ return $submitted;
+ }
+
+
+ function setup_elements(&$mform) {
+
+ }
+
+ /**
+ * Create a new assignment activity
+ *
+ * Given an object containing all the necessary data,
+ * (defined by the form in mod.html) this function
+ * will create a new instance and return the id number
+ * of the new instance.
+ * The due data is added to the calendar
+ * This is common to all assignment types.
+ *
+ * @param $assignment object The data from the form on mod.html
+ * @return int The id of the assignment
+ */
+ function add_instance($assignment) {
+ global $COURSE;
+
+ $assignment->timemodified = time();
+ $assignment->courseid = $assignment->course;
+
+ if ($returnid = insert_record("assignment", $assignment)) {
+ $assignment->id = $returnid;
+
+ if ($assignment->timedue) {
+ $event = new object();
+ $event->name = $assignment->name;
+ $event->description = $assignment->description;
+ $event->courseid = $assignment->course;
+ $event->groupid = 0;
+ $event->userid = 0;
+ $event->modulename = 'assignment';
+ $event->instance = $returnid;
+ $event->eventtype = 'due';
+ $event->timestart = $assignment->timedue;
+ $event->timeduration = 0;
+
+ add_event($event);
+ }
+
+ $assignment = stripslashes_recursive($assignment);
+ assignment_grade_item_update($assignment);
+
+ }
+
+
+ return $returnid;
+ }
+
+ /**
+ * Deletes an assignment activity
+ *
+ * Deletes all database records, files and calendar events for this assignment.
+ * @param $assignment object The assignment to be deleted
+ * @return boolean False indicates error
+ */
+ function delete_instance($assignment) {
+ global $CFG;
+
+ $assignment->courseid = $assignment->course;
+
+ $result = true;
+
+ if (! delete_records('assignment_submissions', 'assignment', $assignment->id)) {
+ $result = false;
+ }
+
+ if (! delete_records('assignment', 'id', $assignment->id)) {
+ $result = false;
+ }
+
+ if (! delete_records('event', 'modulename', 'assignment', 'instance', $assignment->id)) {
+ $result = false;
+ }
+
+ // delete file area with all attachments - ignore errors
+ require_once($CFG->libdir.'/filelib.php');
+ fulldelete($CFG->dataroot.'/'.$assignment->course.'/'.$CFG->moddata.'/assignment/'.$assignment->id);
+
+ assignment_grade_item_delete($assignment);
+
+ return $result;
+ }
+
+ /**
+ * Updates a new assignment activity
+ *
+ * Given an object containing all the necessary data,
+ * (defined by the form in mod.html) this function
+ * will update the assignment instance and return the id number
+ * The due date is updated in the calendar
+ * This is common to all assignment types.
+ *
+ * @param $assignment object The data from the form on mod.html
+ * @return int The assignment id
+ */
+ function update_instance($assignment) {
+ global $COURSE;
+
+ $assignment->timemodified = time();
+
+ $assignment->id = $assignment->instance;
+ $assignment->courseid = $assignment->course;
+
+ if (!update_record('assignment', $assignment)) {
+ return false;
+ }
+
+ if ($assignment->timedue) {
+ $event = new object();
+
+ if ($event->id = get_field('event', 'id', 'modulename', 'assignment', 'instance', $assignment->id)) {
+
+ $event->name = $assignment->name;
+ $event->description = $assignment->description;
+ $event->timestart = $assignment->timedue;
+
+ update_event($event);
+ } else {
+ $event = new object();
+ $event->name = $assignment->name;
+ $event->description = $assignment->description;
+ $event->courseid = $assignment->course;
+ $event->groupid = 0;
+ $event->userid = 0;
+ $event->modulename = 'assignment';
+ $event->instance = $assignment->id;
+ $event->eventtype = 'due';
+ $event->timestart = $assignment->timedue;
+ $event->timeduration = 0;
+
+ add_event($event);
+ }
+ } else {
+ delete_records('event', 'modulename', 'assignment', 'instance', $assignment->id);
+ }
+
+ // get existing grade item
+ $assignment = stripslashes_recursive($assignment);
+
+ assignment_grade_item_update($assignment);
+
+ return true;
+ }
+
+ /**
+ * Update grade item for this submission.
+ */
+ function update_grade($submission) {
+ assignment_update_grades($this->assignment, $submission->userid);
+ }
+
+ /**
+ * Top-level function for handling of submissions called by submissions.php
+ *
+ * This is for handling the teacher interaction with the grading interface
+ * This should be suitable for most assignment types.
+ *
+ * @param $mode string Specifies the kind of teacher interaction taking place
+ */
+ function submissions($mode) {
+ ///The main switch is changed to facilitate
+ ///1) Batch fast grading
+ ///2) Skip to the next one on the popup
+ ///3) Save and Skip to the next one on the popup
+
+ //make user global so we can use the id
+ global $USER;
+
+ $mailinfo = optional_param('mailinfo', null, PARAM_BOOL);
+ if (is_null($mailinfo)) {
+ $mailinfo = get_user_preferences('assignment_mailinfo', 0);
+ } else {
+ set_user_preference('assignment_mailinfo', $mailinfo);
+ }
+
+ switch ($mode) {
+ case 'grade': // We are in a popup window grading
+ if ($submission = $this->process_feedback()) {
+ //IE needs proper header with encoding
+ print_header(get_string('feedback', 'assignment').':'.format_string($this->assignment->name));
+ print_heading(get_string('changessaved'));
+ print $this->update_main_listing($submission);
+ }
+ close_window();
+ break;
+
+ case 'single': // We are in a popup window displaying submission
+ $this->display_submission();
+ break;
+
+ case 'all': // Main window, display everything
+ $this->display_submissions();
+ break;
+
+ case 'fastgrade':
+ ///do the fast grading stuff - this process should work for all 3 subclasses
+
+ $grading = false;
+ $commenting = false;
+ $col = false;
+ if (isset($_POST['submissioncomment'])) {
+ $col = 'submissioncomment';
+ $commenting = true;
+ }
+ if (isset($_POST['menu'])) {
+ $col = 'menu';
+ $grading = true;
+ }
+ if (!$col) {
+ //both submissioncomment and grade columns collapsed..
+ $this->display_submissions();
+ break;
+ }
+
+ foreach ($_POST[$col] as $id => $unusedvalue){
+
+ $id = (int)$id; //clean parameter name
+
+ $this->process_outcomes($id);
+
+ if (!$submission = $this->get_submission($id)) {
+ $submission = $this->prepare_new_submission($id);
+ $newsubmission = true;
+ } else {
+ $newsubmission = false;
+ }
+ unset($submission->data1); // Don't need to update this.
+ unset($submission->data2); // Don't need to update this.
+
+ //for fast grade, we need to check if any changes take place
+ $updatedb = false;
+
+ if ($grading) {
+ $grade = $_POST['menu'][$id];
+ $updatedb = $updatedb || ($submission->grade != $grade);
+ $submission->grade = $grade;
+ } else {
+ if (!$newsubmission) {
+ unset($submission->grade); // Don't need to update this.
+ }
+ }
+ if ($commenting) {
+ $commentvalue = trim($_POST['submissioncomment'][$id]);
+ $updatedb = $updatedb || ($submission->submissioncomment != stripslashes($commentvalue));
+ $submission->submissioncomment = $commentvalue;
+ } else {
+ unset($submission->submissioncomment); // Don't need to update this.
+ }
+
+ $submission->teacher = $USER->id;
+ if ($updatedb) {
+ $submission->mailed = (int)(!$mailinfo);
+ }
+
+ $submission->timemarked = time();
+
+ //if it is not an update, we don't change the last modified time etc.
+ //this will also not write into database if no submissioncomment and grade is entered.
+
+ if ($updatedb){
+ if ($newsubmission) {
+ if (!isset($submission->submissioncomment)) {
+ $submission->submissioncomment = '';
+ }
+ if (!$sid = insert_record('assignment_submissions', $submission)) {
+ return false;
+ }
+ $submission->id = $sid;
+ } else {
+ if (!update_record('assignment_submissions', $submission)) {
+ return false;
+ }
+ }
+
+ // triger grade event
+ $this->update_grade($submission);
+
+ //add to log only if updating
+ add_to_log($this->course->id, 'assignment', 'update grades',
+ 'submissions.php?id='.$this->assignment->id.'&user='.$submission->userid,
+ $submission->userid, $this->cm->id);
+ }
+
+ }
+
+ $message = notify(get_string('changessaved'), 'notifysuccess', 'center', true);
+
+ $this->display_submissions($message);
+ break;
+
+
+ case 'next':
+ /// We are currently in pop up, but we want to skip to next one without saving.
+ /// This turns out to be similar to a single case
+ /// The URL used is for the next submission.
+
+ $this->display_submission();
+ break;
+
+ case 'saveandnext':
+ ///We are in pop up. save the current one and go to the next one.
+ //first we save the current changes
+ if ($submission = $this->process_feedback()) {
+ //print_heading(get_string('changessaved'));
+ $extra_javascript = $this->update_main_listing($submission);
+ }
+
+ //then we display the next submission
+ $this->display_submission($extra_javascript);
+ break;
+
+ default:
+ echo "something seriously is wrong!!";
+ break;
+ }
+ }
+
+ /**
+ * Helper method updating the listing on the main script from popup using javascript
+ *
+ * @param $submission object The submission whose data is to be updated on the main page
+ */
+ function update_main_listing($submission) {
+ global $SESSION, $CFG;
+
+ $output = '';
+
+ $perpage = get_user_preferences('assignment_perpage', 10);
+
+ $quickgrade = get_user_preferences('assignment_quickgrade', 0);
+
+ /// Run some Javascript to try and update the parent page
+ $output .= '<script type="text/javascript">'."\n<!--\n";
+ if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['submissioncomment'])) {
+ if ($quickgrade){
+ $output.= 'opener.document.getElementById("submissioncomment'.$submission->userid.'").value="'
+ .trim($submission->submissioncomment).'";'."\n";
+ } else {
+ $output.= 'opener.document.getElementById("com'.$submission->userid.
+ '").innerHTML="'.shorten_text(trim(strip_tags($submission->submissioncomment)), 15)."\";\n";
+ }
+ }
+
+ if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['grade'])) {
+ //echo optional_param('menuindex');
+ if ($quickgrade){
+ $output.= 'opener.document.getElementById("menumenu'.$submission->userid.
+ '").selectedIndex="'.optional_param('menuindex', 0, PARAM_INT).'";'."\n";
+ } else {
+ $output.= 'opener.document.getElementById("g'.$submission->userid.'").innerHTML="'.
+ $this->display_grade($submission->grade)."\";\n";
+ }
+ }
+ //need to add student's assignments in there too.
+ if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['timemodified']) &&
+ $submission->timemodified) {
+ $output.= 'opener.document.getElementById("ts'.$submission->userid.
+ '").innerHTML="'.addslashes_js($this->print_student_answer($submission->userid)).userdate($submission->timemodified)."\";\n";
+ }
+
+ if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['timemarked']) &&
+ $submission->timemarked) {
+ $output.= 'opener.document.getElementById("tt'.$submission->userid.
+ '").innerHTML="'.userdate($submission->timemarked)."\";\n";
+ }
+
+ if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['status'])) {
+ $output.= 'opener.document.getElementById("up'.$submission->userid.'").className="s1";';
+ $buttontext = get_string('update');
+ $button = link_to_popup_window ('/mod/assignment/submissions.php?id='.$this->cm->id.'&amp;userid='.$submission->userid.'&amp;mode=single'.'&amp;offset='.(optional_param('offset', '', PARAM_INT)-1),
+ 'grade'.$submission->userid, $buttontext, 450, 700, $buttontext, 'none', true, 'button'.$submission->userid);
+ $output.= 'opener.document.getElementById("up'.$submission->userid.'").innerHTML="'.addslashes_js($button).'";';
+ }
+
+ $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, $submission->userid);
+
+ if (empty($SESSION->flextable['mod-assignment-submissions']->collapse['finalgrade'])) {
+ $output.= 'opener.document.getElementById("finalgrade_'.$submission->userid.
+ '").innerHTML="'.$grading_info->items[0]->grades[$submission->userid]->str_grade.'";'."\n";
+ }
+
+ if (!empty($CFG->enableoutcomes) and empty($SESSION->flextable['mod-assignment-submissions']->collapse['outcome'])) {
+
+ if (!empty($grading_info->outcomes)) {
+ foreach($grading_info->outcomes as $n=>$outcome) {
+ if ($outcome->grades[$submission->userid]->locked) {
+ continue;
+ }
+
+ if ($quickgrade){
+ $output.= 'opener.document.getElementById("outcome_'.$n.'_'.$submission->userid.
+ '").selectedIndex="'.$outcome->grades[$submission->userid]->grade.'";'."\n";
+
+ } else {
+ $options = make_grades_menu(-$outcome->scaleid);
+ $options[0] = get_string('nooutcome', 'grades');
+ $output.= 'opener.document.getElementById("outcome_'.$n.'_'.$submission->userid.'").innerHTML="'.$options[$outcome->grades[$submission->userid]->grade]."\";\n";
+ }
+
+ }
+ }
+ }
+
+ $output .= "\n-->\n</script>";
+ return $output;
+ }
+
+ /**
+ * Return a grade in user-friendly form, whether it's a scale or not
+ *
+ * @param $grade
+ * @return string User-friendly representation of grade
+ */
+ function display_grade($grade) {
+
+ static $scalegrades = array(); // Cache scales for each assignment - they might have different scales!!
+
+ if ($this->assignment->grade >= 0) { // Normal number
+ if ($grade == -1) {
+ return '-';
+ } else {
+ return $grade.' / '.$this->assignment->grade;
+ }
+
+ } else { // Scale
+ if (empty($scalegrades[$this->assignment->id])) {
+ if ($scale = get_record('scale', 'id', -($this->assignment->grade))) {
+ $scalegrades[$this->assignment->id] = make_menu_from_list($scale->scale);
+ } else {
+ return '-';
+ }
+ }
+ if (isset($scalegrades[$this->assignment->id][$grade])) {
+ return $scalegrades[$this->assignment->id][$grade];
+ }
+ return '-';
+ }
+ }
+
+ /**
+ * Display a single submission, ready for grading on a popup window
+ *
+ * This default method prints the teacher info and submissioncomment box at the top and
+ * the student info and submission at the bottom.
+ * This method also fetches the necessary data in order to be able to
+ * provide a "Next submission" button.
+ * Calls preprocess_submission() to give assignment type plug-ins a chance
+ * to process submissions before they are graded
+ * This method gets its arguments from the page parameters userid and offset
+ */
+ function display_submission($extra_javascript = '') {
+
+ global $CFG;
+ require_once($CFG->libdir.'/gradelib.php');
+ require_once($CFG->libdir.'/tablelib.php');
+
+ $userid = required_param('userid', PARAM_INT);
+ $offset = required_param('offset', PARAM_INT);//offset for where to start looking for student.
+
+ if (!$user = get_record('user', 'id', $userid)) {
+ error('No such user!');
+ }
+
+ if (!$submission = $this->get_submission($user->id)) {
+ $submission = $this->prepare_new_submission($userid);
+ }
+ if ($submission->timemodified > $submission->timemarked) {
+ $subtype = 'assignmentnew';
+ } else {
+ $subtype = 'assignmentold';
+ }
+
+ $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, array($user->id));
+ $disabled = $grading_info->items[0]->grades[$userid]->locked || $grading_info->items[0]->grades[$userid]->overridden;
+
+ /// construct SQL, using current offset to find the data of the next student
+ $course = $this->course;
+ $assignment = $this->assignment;
+ $cm = $this->cm;
+ $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+
+ /// Get all ppl that can submit assignments
+
+ $currentgroup = groups_get_activity_group($cm);
+ if ($users = get_users_by_capability($context, 'mod/assignment:submit', 'u.id', '', '', '', $currentgroup, '', false)) {
+ $users = array_keys($users);
+ }
+
+ // if groupmembersonly used, remove users who are not in any group
+ if ($users and !empty($CFG->enablegroupings) and $cm->groupmembersonly) {
+ if ($groupingusers = groups_get_grouping_members($cm->groupingid, 'u.id', 'u.id')) {
+ $users = array_intersect($users, array_keys($groupingusers));
+ }
+ }
+
+ $nextid = 0;
+
+ if ($users) {
+ $select = 'SELECT u.id, u.firstname, u.lastname, u.picture, u.imagealt,
+ s.id AS submissionid, s.grade, s.submissioncomment,
+ s.timemodified, s.timemarked,
+ COALESCE(SIGN(SIGN(s.timemarked) + SIGN(s.timemarked - s.timemodified)), 0) AS status ';
+ $sql = 'FROM '.$CFG->prefix.'user u '.
+ 'LEFT JOIN '.$CFG->prefix.'assignment_submissions s ON u.id = s.userid
+ AND s.assignment = '.$this->assignment->id.' '.
+ 'WHERE u.id IN ('.implode(',', $users).') ';
+
+ if ($sort = flexible_table::get_sql_sort('mod-assignment-submissions')) {
+ $sort = 'ORDER BY '.$sort.' ';
+ }
+
+ if (($auser = get_records_sql($select.$sql.$sort, $offset+1, 1)) !== false) {
+ $nextuser = array_shift($auser);
+ /// Calculate user status
+ $nextuser->status = ($nextuser->timemarked > 0) && ($nextuser->timemarked >= $nextuser->timemodified);
+ $nextid = $nextuser->id;
+ }
+ }
+
+ print_header(get_string('feedback', 'assignment').':'.fullname($user, true).':'.format_string($this->assignment->name));
+
+ /// Print any extra javascript needed for saveandnext
+ echo $extra_javascript;
+
+ ///SOme javascript to help with setting up >.>
+
+ echo '<script type="text/javascript">'."\n";
+ echo 'function setNext(){'."\n";
+ echo 'document.getElementById(\'submitform\').mode.value=\'next\';'."\n";
+ echo 'document.getElementById(\'submitform\').userid.value="'.$nextid.'";'."\n";
+ echo '}'."\n";
+
+ echo 'function saveNext(){'."\n";
+ echo 'document.getElementById(\'submitform\').mode.value=\'saveandnext\';'."\n";
+ echo 'document.getElementById(\'submitform\').userid.value="'.$nextid.'";'."\n";
+ echo 'document.getElementById(\'submitform\').saveuserid.value="'.$userid.'";'."\n";
+ echo 'document.getElementById(\'submitform\').menuindex.value = document.getElementById(\'submitform\').grade.selectedIndex;'."\n";
+ echo '}'."\n";
+
+ echo '</script>'."\n";
+ echo '<table cellspacing="0" class="feedback '.$subtype.'" >';
+
+ ///Start of teacher info row
+
+ echo '<tr>';
+ echo '<td class="picture teacher">';
+ if ($submission->teacher) {
+ $teacher = get_record('user', 'id', $submission->teacher);
+ } else {
+ global $USER;
+ $teacher = $USER;
+ }
+ print_user_picture($teacher, $this->course->id, $teacher->picture);
+ echo '</td>';
+ echo '<td class="content">';
+ echo '<form id="submitform" action="submissions.php" method="post">';
+ echo '<div>'; // xhtml compatibility - invisiblefieldset was breaking layout here
+ echo '<input type="hidden" name="offset" value="'.($offset+1).'" />';
+ echo '<input type="hidden" name="userid" value="'.$userid.'" />';
+ echo '<input type="hidden" name="id" value="'.$this->cm->id.'" />';
+ echo '<input type="hidden" name="mode" value="grade" />';
+ echo '<input type="hidden" name="menuindex" value="0" />';//selected menu index
+
+ //new hidden field, initialized to -1.
+ echo '<input type="hidden" name="saveuserid" value="-1" />';
+
+ if ($submission->timemarked) {
+ echo '<div class="from">';
+ echo '<div class="fullname">'.fullname($teacher, true).'</div>';
+ echo '<div class="time">'.userdate($submission->timemarked).'</div>';
+ echo '</div>';
+ }
+ echo '<div class="grade"><label for="menugrade">'.get_string('grade').'</label> ';
+ choose_from_menu(make_grades_menu($this->assignment->grade), 'grade', $submission->grade, get_string('nograde'), '', -1, false, $disabled);
+ echo '</div>';
+
+ echo '<div class="clearer"></div>';
+ echo '<div class="finalgrade">'.get_string('finalgrade', 'grades').': '.$grading_info->items[0]->grades[$userid]->str_grade.'</div>';
+ echo '<div class="clearer"></div>';
+
+ if (!empty($CFG->enableoutcomes)) {
+ foreach($grading_info->outcomes as $n=>$outcome) {
+ echo '<div class="outcome"><label for="menuoutcome_'.$n.'">'.$outcome->name.'</label> ';
+ $options = make_grades_menu(-$outcome->scaleid);
+ if ($outcome->grades[$submission->userid]->locked) {
+ $options[0] = get_string('nooutcome', 'grades');
+ echo $options[$outcome->grades[$submission->userid]->grade];
+ } else {
+ choose_from_menu($options, 'outcome_'.$n.'['.$userid.']', $outcome->grades[$submission->userid]->grade, get_string('nooutcome', 'grades'), '', 0, false, false, 0, 'menuoutcome_'.$n);
+ }
+ echo '</div>';
+ echo '<div class="clearer"></div>';
+ }
+ }
+
+
+ $this->preprocess_submission($submission);
+
+ if ($disabled) {
+ echo '<div class="disabledfeedback">'.$grading_info->items[0]->grades[$userid]->str_feedback.'</div>';
+
+ } else {
+ print_textarea($this->usehtmleditor, 14, 58, 0, 0, 'submissioncomment', $submission->submissioncomment, $this->course->id);
+ if ($this->usehtmleditor) {
+ echo '<input type="hidden" name="format" value="'.FORMAT_HTML.'" />';
+ } else {
+ echo '<div class="format">';
+ choose_from_menu(format_text_menu(), "format", $submission->format, "");
+ helpbutton("textformat", get_string("helpformatting"));
+ echo '</div>';
+ }
+ }
+
+ $lastmailinfo = get_user_preferences('assignment_mailinfo', 1) ? 'checked="checked"' : '';
+
+ ///Print Buttons in Single View
+ echo '<input type="hidden" name="mailinfo" value="0" />';
+ echo '<input type="checkbox" id="mailinfo" name="mailinfo" value="1" '.$lastmailinfo.' /><label for="mailinfo">'.get_string('enableemailnotification','assignment').'</label>';
+ echo '<div class="buttons">';
+ echo '<input type="submit" name="submit" value="'.get_string('savechanges').'" onclick = "document.getElementById(\'submitform\').menuindex.value = document.getElementById(\'submitform\').grade.selectedIndex" />';
+ echo '<input type="submit" name="cancel" value="'.get_string('cancel').'" />';
+ //if there are more to be graded.
+ if ($nextid) {
+ echo '<input type="submit" name="saveandnext" value="'.get_string('saveandnext').'" onclick="saveNext()" />';
+ echo '<input type="submit" name="next" value="'.get_string('next').'" onclick="setNext();" />';
+ }
+ echo '</div>';
+ echo '</div></form>';
+
+ $customfeedback = $this->custom_feedbackform($submission, true);
+ if (!empty($customfeedback)) {
+ echo $customfeedback;
+ }
+
+ echo '</td></tr>';
+
+ ///End of teacher info row, Start of student info row
+ echo '<tr>';
+ echo '<td class="picture user">';
+ print_user_picture($user, $this->course->id, $user->picture);
+ echo '</td>';
+ echo '<td class="topic">';
+ echo '<div class="from">';
+ echo '<div class="fullname">'.fullname($user, true).'</div>';
+ if ($submission->timemodified) {
+ echo '<div class="time">'.userdate($submission->timemodified).
+ $this->display_lateness($submission->timemodified).'</div>';
+ }
+ echo '</div>';
+ $this->print_user_files($user->id);
+ echo '</td>';
+ echo '</tr>';
+
+ ///End of student info row
+
+ echo '</table>';
+
+ if (!$disabled and $this->usehtmleditor) {
+ use_html_editor();
+ }
+
+ print_footer('none');
+ }
+
+ /**
+ * Preprocess submission before grading
+ *
+ * Called by display_submission()
+ * The default type does nothing here.
+ * @param $submission object The submission object
+ */
+ function preprocess_submission(&$submission) {
+ }
+
+ /**
+ * Display all the submissions ready for grading
+ */
+ function display_submissions($message='') {
+ global $CFG, $db, $USER;
+ require_once($CFG->libdir.'/gradelib.php');
+
+ /* first we check to see if the form has just been submitted
+ * to request user_preference updates
+ */
+
+ if (isset($_POST['updatepref'])){
+ $perpage = optional_param('perpage', 10, PARAM_INT);
+ $perpage = ($perpage <= 0) ? 10 : $perpage ;
+ set_user_preference('assignment_perpage', $perpage);
+ set_user_preference('assignment_quickgrade', optional_param('quickgrade', 0, PARAM_BOOL));
+ }
+
+ /* next we get perpage and quickgrade (allow quick grade) params
+ * from database
+ */
+ $perpage = get_user_preferences('assignment_perpage', 10);
+
+ $quickgrade = get_user_preferences('assignment_quickgrade', 0);
+
+ $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id);
+
+ if (!empty($CFG->enableoutcomes) and !empty($grading_info->outcomes)) {
+ $uses_outcomes = true;
+ } else {
+ $uses_outcomes = false;
+ }
+
+ $page = optional_param('page', 0, PARAM_INT);
+ $strsaveallfeedback = get_string('saveallfeedback', 'assignment');
+
+ /// Some shortcuts to make the code read better
+
+ $course = $this->course;
+ $assignment = $this->assignment;
+ $cm = $this->cm;
+
+ $tabindex = 1; //tabindex for quick grading tabbing; Not working for dropdowns yet
+ add_to_log($course->id, 'assignment', 'view submission', 'submissions.php?id='.$this->cm->id, $this->assignment->id, $this->cm->id);
+ $navigation = build_navigation($this->strsubmissions, $this->cm);
+ print_header_simple(format_string($this->assignment->name,true), "", $navigation,
+ '', '', true, update_module_button($cm->id, $course->id, $this->strassignment), navmenu($course, $cm));
+
+ $course_context = get_context_instance(CONTEXT_COURSE, $course->id);
+ if (has_capability('gradereport/grader:view', $course_context) && has_capability('moodle/grade:viewall', $course_context)) {
+ echo '<div class="allcoursegrades"><a href="' . $CFG->wwwroot . '/grade/report/grader/index.php?id=' . $course->id . '">'
+ . get_string('seeallcoursegrades', 'grades') . '</a></div>';
+ }
+
+ if (!empty($message)) {
+ echo $message; // display messages here if any
+ }
+
+ $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+
+ /// Check to see if groups are being used in this assignment
+
+ /// find out current groups mode
+ $groupmode = groups_get_activity_groupmode($cm);
+ $currentgroup = groups_get_activity_group($cm, true);
+ groups_print_activity_menu($cm, 'submissions.php?id=' . $this->cm->id);
+
+ /// Get all ppl that are allowed to submit assignments
+ if ($users = get_users_by_capability($context, 'mod/assignment:submit', 'u.id', '', '', '', $currentgroup, '', false)) {
+ $users = array_keys($users);
+ }
+
+ // if groupmembersonly used, remove users who are not in any group
+ if ($users and !empty($CFG->enablegroupings) and $cm->groupmembersonly) {
+ if ($groupingusers = groups_get_grouping_members($cm->groupingid, 'u.id', 'u.id')) {
+ $users = array_intersect($users, array_keys($groupingusers));
+ }
+ }
+
+ $tablecolumns = array('picture', 'fullname', 'grade', 'submissioncomment', 'timemodified', 'timemarked', 'status', 'finalgrade');
+ if ($uses_outcomes) {
+ $tablecolumns[] = 'outcome'; // no sorting based on outcomes column
+ }
+
+ $tableheaders = array('',
+ get_string('fullname'),
+ get_string('grade'),
+ get_string('comment', 'assignment'),
+ get_string('lastmodified').' ('.$course->student.')',
+ get_string('lastmodified').' ('.$course->teacher.')',
+ get_string('status'),
+ get_string('finalgrade', 'grades'));
+ if ($uses_outcomes) {
+ $tableheaders[] = get_string('outcome', 'grades');
+ }
+
+ require_once($CFG->libdir.'/tablelib.php');
+ $table = new flexible_table('mod-assignment-submissions');
+
+ $table->define_columns($tablecolumns);
+ $table->define_headers($tableheaders);
+ $table->define_baseurl($CFG->wwwroot.'/mod/assignment/submissions.php?id='.$this->cm->id.'&amp;currentgroup='.$currentgroup);
+
+ $table->sortable(true, 'lastname');//sorted by lastname by default
+ $table->collapsible(true);
+ $table->initialbars(true);
+
+ $table->column_suppress('picture');
+ $table->column_suppress('fullname');
+
+ $table->column_class('picture', 'picture');
+ $table->column_class('fullname', 'fullname');
+ $table->column_class('grade', 'grade');
+ $table->column_class('submissioncomment', 'comment');
+ $table->column_class('timemodified', 'timemodified');
+ $table->column_class('timemarked', 'timemarked');
+ $table->column_class('status', 'status');
+ $table->column_class('finalgrade', 'finalgrade');
+ if ($uses_outcomes) {
+ $table->column_class('outcome', 'outcome');
+ }
+
+ $table->set_attribute('cellspacing', '0');
+ $table->set_attribute('id', 'attempts');
+ $table->set_attribute('class', 'submissions');
+ $table->set_attribute('width', '100%');
+ //$table->set_attribute('align', 'center');
+
+ $table->no_sorting('finalgrade');
+ $table->no_sorting('outcome');
+
+ // Start working -- this is necessary as soon as the niceties are over
+ $table->setup();
+
+ if (empty($users)) {
+ print_heading(get_string('nosubmitusers','assignment'));
+ return true;
+ }
+
+ /// Construct the SQL
+
+ if ($where = $table->get_sql_where()) {
+ $where .= ' AND ';
+ }
+
+ if ($sort = $table->get_sql_sort()) {
+ $sort = ' ORDER BY '.$sort;
+ }
+
+ $select = 'SELECT u.id, u.firstname, u.lastname, u.picture, u.imagealt,
+ s.id AS submissionid, s.grade, s.submissioncomment,
+ s.timemodified, s.timemarked,
+ COALESCE(SIGN(SIGN(s.timemarked) + SIGN(s.timemarked - s.timemodified)), 0) AS status ';
+ $sql = 'FROM '.$CFG->prefix.'user u '.
+ 'LEFT JOIN '.$CFG->prefix.'assignment_submissions s ON u.id = s.userid
+ AND s.assignment = '.$this->assignment->id.' '.
+ 'WHERE '.$where.'u.id IN ('.implode(',',$users).') ';
+
+ $table->pagesize($perpage, count($users));
+
+ ///offset used to calculate index of student in that particular query, needed for the pop up to know who's next
+ $offset = $page * $perpage;
+
+ $strupdate = get_string('update');
+ $strgrade = get_string('grade');
+ $grademenu = make_grades_menu($this->assignment->grade);
+
+ if (($ausers = get_records_sql($select.$sql.$sort, $table->get_page_start(), $table->get_page_size())) !== false) {
+ $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, array_keys($ausers));
+ foreach ($ausers as $auser) {
+ $final_grade = $grading_info->items[0]->grades[$auser->id];
+ $grademax = $grading_info->items[0]->grademax;
+ $final_grade->formatted_grade = round($final_grade->grade,2) .' / ' . round($grademax,2);
+ $locked_overridden = 'locked';
+ if ($final_grade->overridden) {
+ $locked_overridden = 'overridden';
+ }
+
+ /// Calculate user status
+ $auser->status = ($auser->timemarked > 0) && ($auser->timemarked >= $auser->timemodified);
+ $picture = print_user_picture($auser, $course->id, $auser->picture, false, true);
+
+ if (empty($auser->submissionid)) {
+ $auser->grade = -1; //no submission yet
+ }
+
+ if (!empty($auser->submissionid)) {
+ ///Prints student answer and student modified date
+ ///attach file or print link to student answer, depending on the type of the assignment.
+ ///Refer to print_student_answer in inherited classes.
+ if ($auser->timemodified > 0) {
+ $studentmodified = '<div id="ts'.$auser->id.'">'.$this->print_student_answer($auser->id)
+ . userdate($auser->timemodified).'</div>';
+ } else {
+ $studentmodified = '<div id="ts'.$auser->id.'">&nbsp;</div>';
+ }
+ ///Print grade, dropdown or text
+ if ($auser->timemarked > 0) {
+ $teachermodified = '<div id="tt'.$auser->id.'">'.userdate($auser->timemarked).'</div>';
+
+ if ($final_grade->locked or $final_grade->overridden) {
+ $grade = '<div id="g'.$auser->id.'" class="'. $locked_overridden .'">'.$final_grade->formatted_grade.'</div>';
+ } else if ($quickgrade) {
+ $menu = choose_from_menu(make_grades_menu($this->assignment->grade),
+ 'menu['.$auser->id.']', $auser->grade,
+ get_string('nograde'),'',-1,true,false,$tabindex++);
+ $grade = '<div id="g'.$auser->id.'">'. $menu .'</div>';
+ } else {
+ $grade = '<div id="g'.$auser->id.'">'.$this->display_grade($auser->grade).'</div>';
+ }
+
+ } else {
+ $teachermodified = '<div id="tt'.$auser->id.'">&nbsp;</div>';
+ if ($final_grade->locked or $final_grade->overridden) {
+ $grade = '<div id="g'.$auser->id.'" class="'. $locked_overridden .'">'.$final_grade->formatted_grade.'</div>';
+ } else if ($quickgrade) {
+ $menu = choose_from_menu(make_grades_menu($this->assignment->grade),
+ 'menu['.$auser->id.']', $auser->grade,
+ get_string('nograde'),'',-1,true,false,$tabindex++);
+ $grade = '<div id="g'.$auser->id.'">'.$menu.'</div>';
+ } else {
+ $grade = '<div id="g'.$auser->id.'">'.$this->display_grade($auser->grade).'</div>';
+ }
+ }
+ ///Print Comment
+ if ($final_grade->locked or $final_grade->overridden) {
+ $comment = '<div id="com'.$auser->id.'">'.shorten_text(strip_tags($final_grade->str_feedback),15).'</div>';
+
+ } else if ($quickgrade) {
+ $comment = '<div id="com'.$auser->id.'">'
+ . '<textarea tabindex="'.$tabindex++.'" name="submissioncomment['.$auser->id.']" id="submissioncomment'
+ . $auser->id.'" rows="2" cols="20">'.($auser->submissioncomment).'</textarea></div>';
+ } else {
+ $comment = '<div id="com'.$auser->id.'">'.shorten_text(strip_tags($auser->submissioncomment),15).'</div>';
+ }
+ } else {
+ $studentmodified = '<div id="ts'.$auser->id.'">&nbsp;</div>';
+ $teachermodified = '<div id="tt'.$auser->id.'">&nbsp;</div>';
+ $status = '<div id="st'.$auser->id.'">&nbsp;</div>';
+
+ if ($final_grade->locked or $final_grade->overridden) {
+ $grade = '<div id="g'.$auser->id.'">'.$final_grade->formatted_grade . '</div>';
+ } else if ($quickgrade) { // allow editing
+ $menu = choose_from_menu(make_grades_menu($this->assignment->grade),
+ 'menu['.$auser->id.']', $auser->grade,
+ get_string('nograde'),'',-1,true,false,$tabindex++);
+ $grade = '<div id="g'.$auser->id.'">'.$menu.'</div>';
+ } else {
+ $grade = '<div id="g'.$auser->id.'">-</div>';
+ }
+
+ if ($final_grade->locked or $final_grade->overridden) {
+ $comment = '<div id="com'.$auser->id.'">'.$final_grade->str_feedback.'</div>';
+ } else if ($quickgrade) {
+ $comment = '<div id="com'.$auser->id.'">'
+ . '<textarea tabindex="'.$tabindex++.'" name="submissioncomment['.$auser->id.']" id="submissioncomment'
+ . $auser->id.'" rows="2" cols="20">'.($auser->submissioncomment).'</textarea></div>';
+ } else {
+ $comment = '<div id="com'.$auser->id.'">&nbsp;</div>';
+ }
+ }
+
+ if (empty($auser->status)) { /// Confirm we have exclusively 0 or 1
+ $auser->status = 0;
+ } else {
+ $auser->status = 1;
+ }
+
+ $buttontext = ($auser->status == 1) ? $strupdate : $strgrade;
+
+ ///No more buttons, we use popups ;-).
+ $popup_url = '/mod/assignment/submissions.php?id='.$this->cm->id
+ . '&amp;userid='.$auser->id.'&amp;mode=single'.'&amp;offset='.$offset++;
+ $button = link_to_popup_window ($popup_url, 'grade'.$auser->id, $buttontext, 600, 780,
+ $buttontext, 'none', true, 'button'.$auser->id);
+
+ $status = '<div id="up'.$auser->id.'" class="s'.$auser->status.'">'.$button.'</div>';
+
+ $finalgrade = '<span id="finalgrade_'.$auser->id.'">'.$final_grade->str_grade.'</span>';
+
+ $outcomes = '';
+
+ if ($uses_outcomes) {
+
+ foreach($grading_info->outcomes as $n=>$outcome) {
+ $outcomes .= '<div class="outcome"><label>'.$outcome->name.'</label>';
+ $options = make_grades_menu(-$outcome->scaleid);
+
+ if ($outcome->grades[$auser->id]->locked or !$quickgrade) {
+ $options[0] = get_string('nooutcome', 'grades');
+ $outcomes .= ': <span id="outcome_'.$n.'_'.$auser->id.'">'.$options[$outcome->grades[$auser->id]->grade].'</span>';
+ } else {
+ $outcomes .= ' ';
+ $outcomes .= choose_from_menu($options, 'outcome_'.$n.'['.$auser->id.']',
+ $outcome->grades[$auser->id]->grade, get_string('nooutcome', 'grades'), '', 0, true, false, 0, 'outcome_'.$n.'_'.$auser->id);
+ }
+ $outcomes .= '</div>';
+ }
+ }
+
+ $userlink = '<a href="' . $CFG->wwwroot . '/user/view.php?id=' . $auser->id . '&amp;course=' . $course->id . '">' . fullname($auser) . '</a>';
+ $row = array($picture, $userlink, $grade, $comment, $studentmodified, $teachermodified, $status, $finalgrade);
+ if ($uses_outcomes) {
+ $row[] = $outcomes;
+ }
+
+ $table->add_data($row);
+ }
+ }
+
+ /// Print quickgrade form around the table
+ if ($quickgrade){
+ echo '<form action="submissions.php" id="fastg" method="post">';
+ echo '<div>';
+ echo '<input type="hidden" name="id" value="'.$this->cm->id.'" />';
+ echo '<input type="hidden" name="mode" value="fastgrade" />';
+ echo '<input type="hidden" name="page" value="'.$page.'" />';
+ echo '</div>';
+ }
+
+ $table->print_html(); /// Print the whole table
+
+ if ($quickgrade){
+ $lastmailinfo = get_user_preferences('assignment_mailinfo', 1) ? 'checked="checked"' : '';
+ echo '<div class="fgcontrols">';
+ echo '<div class="emailnotification">';
+ echo '<label for="mailinfo">'.get_string('enableemailnotification','assignment').'</label>';
+ echo '<input type="hidden" name="mailinfo" value="0" />';
+ echo '<input type="checkbox" id="mailinfo" name="mailinfo" value="1" '.$lastmailinfo.' />';
+ helpbutton('emailnotification', get_string('enableemailnotification', 'assignment'), 'assignment').'</p></div>';
+ echo '</div>';
+ echo '<div class="fastgbutton"><input type="submit" name="fastg" value="'.get_string('saveallfeedback', 'assignment').'" /></div>';
+ echo '</div>';
+ echo '</form>';
+ }
+ /// End of fast grading form
+
+ /// Mini form for setting user preference
+ echo '<div class="qgprefs">';
+ echo '<form id="options" action="submissions.php?id='.$this->cm->id.'" method="post"><div>';
+ echo '<input type="hidden" name="updatepref" value="1" />';
+ echo '<table id="optiontable">';
+ echo '<tr><td>';
+ echo '<label for="perpage">'.get_string('pagesize','assignment').'</label>';
+ echo '</td>';
+ echo '<td>';
+ echo '<input type="text" id="perpage" name="perpage" size="1" value="'.$perpage.'" />';
+ helpbutton('pagesize', get_string('pagesize','assignment'), 'assignment');
+ echo '</td></tr>';
+ echo '<tr><td>';
+ echo '<label for="quickgrade">'.get_string('quickgrade','assignment').'</label>';
+ echo '</td>';
+ echo '<td>';
+ $checked = $quickgrade ? 'checked="checked"' : '';
+ echo '<input type="checkbox" id="quickgrade" name="quickgrade" value="1" '.$checked.' />';
+ helpbutton('quickgrade', get_string('quickgrade', 'assignment'), 'assignment').'</p></div>';
+ echo '</td></tr>';
+ echo '<tr><td colspan="2">';
+ echo '<input type="submit" value="'.get_string('savepreferences').'" />';
+ echo '</td></tr></table>';
+ echo '</div></form></div>';
+ ///End of mini form
+ print_footer($this->course);
+ }
+
+ /**
+ * Process teacher feedback submission
+ *
+ * This is called by submissions() when a grading even has taken place.
+ * It gets its data from the submitted form.
+ * @return object The updated submission object
+ */
+ function process_feedback() {
+ global $CFG, $USER;
+ require_once($CFG->libdir.'/gradelib.php');
+
+ if (!$feedback = data_submitted()) { // No incoming data?
+ return false;
+ }
+
+ ///For save and next, we need to know the userid to save, and the userid to go
+ ///We use a new hidden field in the form, and set it to -1. If it's set, we use this
+ ///as the userid to store
+ if ((int)$feedback->saveuserid !== -1){
+ $feedback->userid = $feedback->saveuserid;
+ }
+
+ if (!empty($feedback->cancel)) { // User hit cancel button
+ return false;
+ }
+
+ $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, $feedback->userid);
+
+ // store outcomes if needed
+ $this->process_outcomes($feedback->userid);
+
+ $submission = $this->get_submission($feedback->userid, true); // Get or make one
+
+ if (!$grading_info->items[0]->grades[$feedback->userid]->locked and
+ !$grading_info->items[0]->grades[$feedback->userid]->overridden) {
+
+ $submission->grade = $feedback->grade;
+ $submission->submissioncomment = $feedback->submissioncomment;
+ $submission->format = $feedback->format;
+ $submission->teacher = $USER->id;
+ $mailinfo = get_user_preferences('assignment_mailinfo', 0);
+ if (!$mailinfo) {
+ $submission->mailed = 1; // treat as already mailed
+ } else {
+ $submission->mailed = 0; // Make sure mail goes out (again, even)
+ }
+ $submission->timemarked = time();
+
+ unset($submission->data1); // Don't need to update this.
+ unset($submission->data2); // Don't need to update this.
+
+ if (empty($submission->timemodified)) { // eg for offline assignments
+ // $submission->timemodified = time();
+ }
+
+ if (! update_record('assignment_submissions', $submission)) {
+ return false;
+ }
+
+ // triger grade event
+ $this->update_grade($submission);
+
+ add_to_log($this->course->id, 'assignment', 'update grades',
+ 'submissions.php?id='.$this->assignment->id.'&user='.$feedback->userid, $feedback->userid, $this->cm->id);
+ }
+
+ return $submission;
+
+ }
+
+ function process_outcomes($userid) {
+ global $CFG, $USER;
+
+ if (empty($CFG->enableoutcomes)) {
+ return;
+ }
+
+ require_once($CFG->libdir.'/gradelib.php');
+
+ if (!$formdata = data_submitted()) {
+ return;
+ }
+
+ $data = array();
+ $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, $userid);
+
+ if (!empty($grading_info->outcomes)) {
+ foreach($grading_info->outcomes as $n=>$old) {
+ $name = 'outcome_'.$n;
+ if (isset($formdata->{$name}[$userid]) and $old->grades[$userid]->grade != $formdata->{$name}[$userid]) {
+ $data[$n] = $formdata->{$name}[$userid];
+ }
+ }
+ }
+ if (count($data) > 0) {
+ grade_update_outcomes('mod/assignment', $this->course->id, 'mod', 'assignment', $this->assignment->id, $userid, $data);
+ }
+
+ }
+
+ /**
+ * Load the submission object for a particular user
+ *
+ * @param $userid int The id of the user whose submission we want or 0 in which case USER->id is used
+ * @param $createnew boolean optional Defaults to false. If set to true a new submission object will be created in the database
+ * @param bool $teachermodified student submission set if false
+ * @return object The submission
+ */
+ function get_submission($userid=0, $createnew=false, $teachermodified=false) {
+ global $USER;
+
+ if (empty($userid)) {
+ $userid = $USER->id;
+ }
+
+ $submission = get_record('assignment_submissions', 'assignment', $this->assignment->id, 'userid', $userid);
+
+ if ($submission || !$createnew) {
+ return $submission;
+ }
+ $newsubmission = $this->prepare_new_submission($userid, $teachermodified);
+ if (!insert_record("assignment_submissions", $newsubmission)) {
+ error("Could not insert a new empty submission");
+ }
+
+ return get_record('assignment_submissions', 'assignment', $this->assignment->id, 'userid', $userid);
+ }
+
+ /**
+ * Instantiates a new submission object for a given user
+ *
+ * Sets the assignment, userid and times, everything else is set to default values.
+ * @param $userid int The userid for which we want a submission object
+ * @param bool $teachermodified student submission set if false
+ * @return object The submission
+ */
+ function prepare_new_submission($userid, $teachermodified=false) {
+ $submission = new Object;
+ $submission->assignment = $this->assignment->id;
+ $submission->userid = $userid;
+ //$submission->timecreated = time();
+ $submission->timecreated = '';
+ // teachers should not be modifying modified date, except offline assignments
+ if ($teachermodified) {
+ $submission->timemodified = 0;
+ } else {
+ $submission->timemodified = $submission->timecreated;
+ }
+ $submission->numfiles = 0;
+ $submission->data1 = '';
+ $submission->data2 = '';
+ $submission->grade = -1;
+ $submission->submissioncomment = '';
+ $submission->format = 0;
+ $submission->teacher = 0;
+ $submission->timemarked = 0;
+ $submission->mailed = 0;
+ return $submission;
+ }
+
+ /**
+ * Return all assignment submissions by ENROLLED students (even empty)
+ *
+ * @param $sort string optional field names for the ORDER BY in the sql query
+ * @param $dir string optional specifying the sort direction, defaults to DESC
+ * @return array The submission objects indexed by id
+ */
+ function get_submissions($sort='', $dir='DESC') {
+ return assignment_get_all_submissions($this->assignment, $sort, $dir);
+ }
+
+ /**
+ * Counts all real assignment submissions by ENROLLED students (not empty ones)
+ *
+ * @param $groupid int optional If nonzero then count is restricted to this group
+ * @return int The number of submissions
+ */
+ function count_real_submissions($groupid=0) {
+ return assignment_count_real_submissions($this->cm, $groupid);
+ }
+
+ /**
+ * Alerts teachers by email of new or changed assignments that need grading
+ *
+ * First checks whether the option to email teachers is set for this assignment.
+ * Sends an email to ALL teachers in the course (or in the group if using separate groups).
+ * Uses the methods email_teachers_text() and email_teachers_html() to construct the content.
+ * @param $submission object The submission that has changed
+ */
+ function email_teachers($submission) {
+ global $CFG;
+
+ if (empty($this->assignment->emailteachers)) { // No need to do anything
+ return;
+ }
+
+ $user = get_record('user', 'id', $submission->userid);
+
+ if ($teachers = $this->get_graders($user)) {
+
+ $strassignments = get_string('modulenameplural', 'assignment');
+ $strassignment = get_string('modulename', 'assignment');
+ $strsubmitted = get_string('submitted', 'assignment');
+
+ foreach ($teachers as $teacher) {
+ $info = new object();
+ $info->username = fullname($user, true);
+ $info->assignment = format_string($this->assignment->name,true);
+ $info->url = $CFG->wwwroot.'/mod/assignment/submissions.php?id='.$this->cm->id;
+
+ $postsubject = $strsubmitted.': '.$info->username.' -> '.$this->assignment->name;
+ $posttext = $this->email_teachers_text($info);
+ $posthtml = ($teacher->mailformat == 1) ? $this->email_teachers_html($info) : '';
+
+ @email_to_user($teacher, $user, $postsubject, $posttext, $posthtml); // If it fails, oh well, too bad.
+ }
+ }
+ }
+
+ /**
+ * Returns a list of teachers that should be grading given submission
+ */
+ function get_graders($user) {
+ //potential graders
+ $potgraders = get_users_by_capability($this->context, 'mod/assignment:grade', '', '', '', '', '', '', false, false);
+
+ $graders = array();
+ if (groups_get_activity_groupmode($this->cm) == SEPARATEGROUPS) { // Separate groups are being used
+ if ($groups = groups_get_all_groups($this->course->id, $user->id)) { // Try to find all groups
+ foreach ($groups as $group) {
+ foreach ($potgraders as $t) {
+ if ($t->id == $user->id) {
+ continue; // do not send self
+ }
+ if (groups_is_member($group->id, $t->id)) {
+ $graders[$t->id] = $t;
+ }
+ }
+ }
+ } else {
+ // user not in group, try to find graders without group
+ foreach ($potgraders as $t) {
+ if ($t->id == $user->id) {
+ continue; // do not send self
+ }
+ if (!groups_get_all_groups($this->course->id, $t->id)) { //ugly hack
+ $graders[$t->id] = $t;
+ }
+ }
+ }
+ } else {
+ foreach ($potgraders as $t) {
+ if ($t->id == $user->id) {
+ continue; // do not send self
+ }
+ $graders[$t->id] = $t;
+ }
+ }
+ return $graders;
+ }
+
+ /**
+ * Creates the text content for emails to teachers
+ *
+ * @param $info object The info used by the 'emailteachermail' language string
+ * @return string
+ */
+ function email_teachers_text($info) {
+ $posttext = format_string($this->course->shortname).' -> '.$this->strassignments.' -> '.
+ format_string($this->assignment->name)."\n";
+ $posttext .= '---------------------------------------------------------------------'."\n";
+ $posttext .= get_string("emailteachermail", "assignment", $info)."\n";
+ $posttext .= "\n---------------------------------------------------------------------\n";
+ return $posttext;
+ }
+
+ /**
+ * Creates the html content for emails to teachers
+ *
+ * @param $info object The info used by the 'emailteachermailhtml' language string
+ * @return string
+ */
+ function email_teachers_html($info) {
+ global $CFG;
+ $posthtml = '<p><font face="sans-serif">'.
+ '<a href="'.$CFG->wwwroot.'/course/view.php?id='.$this->course->id.'">'.format_string($this->course->shortname).'</a> ->'.
+ '<a href="'.$CFG->wwwroot.'/mod/assignment/index.php?id='.$this->course->id.'">'.$this->strassignments.'</a> ->'.
+ '<a href="'.$CFG->wwwroot.'/mod/assignment/view.php?id='.$this->cm->id.'">'.format_string($this->assignment->name).'</a></font></p>';
+ $posthtml .= '<hr /><font face="sans-serif">';
+ $posthtml .= '<p>'.get_string('emailteachermailhtml', 'assignment', $info).'</p>';
+ $posthtml .= '</font><hr />';
+ return $posthtml;
+ }
+
+ /**
+ * Produces a list of links to the files uploaded by a user
+ *
+ * @param $userid int optional id of the user. If 0 then $USER->id is used.
+ * @param $return boolean optional defaults to false. If true the list is returned rather than printed
+ * @return string optional
+ */
+ function print_user_files($userid=0, $return=false) {
+ global $CFG, $USER;
+
+ if (!$userid) {
+ if (!isloggedin()) {
+ return '';
+ }
+ $userid = $USER->id;
+ }
+
+ $filearea = $this->file_area_name($userid);
+
+ $output = '';
+
+ if ($basedir = $this->file_area($userid)) {
+ if ($files = get_directory_list($basedir)) {
+ require_once($CFG->libdir.'/filelib.php');
+ foreach ($files as $key => $file) {
+
+ $icon = mimeinfo('icon', $file);
+ $ffurl = get_file_url("$filearea/$file", array('forcedownload'=>1));
+
+ $output .= '<img src="'.$CFG->pixpath.'/f/'.$icon.'" class="icon" alt="'.$icon.'" />'.
+ '<a href="'.$ffurl.'" >'.$file.'</a><br />';
+ }
+ }
+ }
+
+ $output = '<div class="files">'.$output.'</div>';
+
+ if ($return) {
+ return $output;
+ }
+ echo $output;
+ }
+
+ /**
+ * Count the files uploaded by a given user
+ *
+ * @param $userid int The user id
+ * @return int
+ */
+ function count_user_files($userid) {
+ global $CFG;
+
+ $filearea = $this->file_area_name($userid);
+
+ if ( is_dir($CFG->dataroot.'/'.$filearea) && $basedir = $this->file_area($userid)) {
+ if ($files = get_directory_list($basedir)) {
+ return count($files);
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Creates a directory file name, suitable for make_upload_directory()
+ *
+ * @param $userid int The user id
+ * @return string path to file area
+ */
+ function file_area_name($userid) {
+ global $CFG;
+
+ return $this->course->id.'/'.$CFG->moddata.'/assignment/'.$this->assignment->id.'/'.$userid;
+ }
+
+ /**
+ * Makes an upload directory
+ *
+ * @param $userid int The user id
+ * @return string path to file area.
+ */
+ function file_area($userid) {
+ return make_upload_directory( $this->file_area_name($userid) );
+ }
+
+ /**
+ * Returns true if the student is allowed to submit
+ *
+ * Checks that the assignment has started and, if the option to prevent late
+ * submissions is set, also checks that the assignment has not yet closed.
+ * @return boolean
+ */
+ function isopen() {
+ $time = time();
+ if ($this->assignment->preventlate && $this->assignment->timedue) {
+ return ($this->assignment->timeavailable <= $time && $time <= $this->assignment->timedue);
+ } else {
+ return ($this->assignment->timeavailable <= $time);
+ }
+ }
+
+
+ /**
+ * Return true if is set description is hidden till available date
+ *
+ * This is needed by calendar so that hidden descriptions do not
+ * come up in upcoming events.
+ *
+ * Check that description is hidden till available date
+ * By default return false
+ * Assignments types should implement this method if needed
+ * @return boolen
+ */
+ function description_is_hidden() {
+ return false;
+ }
+
+ /**
+ * Return an outline of the user's interaction with the assignment
+ *
+ * The default method prints the grade and timemodified
+ * @param $user object
+ * @return object with properties ->info and ->time
+ */
+ function user_outline($user) {
+ if ($submission = $this->get_submission($user->id)) {
+
+ $result = new object();
+ $result->info = get_string('grade').': '.$this->display_grade($submission->grade);
+ $result->time = $submission->timemodified;
+ return $result;
+ }
+ return NULL;
+ }
+
+ /**
+ * Print complete information about the user's interaction with the assignment
+ *
+ * @param $user object
+ */
+ function user_complete($user) {
+ if ($submission = $this->get_submission($user->id)) {
+ if ($basedir = $this->file_area($user->id)) {
+ if ($files = get_directory_list($basedir)) {
+ $countfiles = count($files)." ".get_string("uploadedfiles", "assignment");
+ foreach ($files as $file) {
+ $countfiles .= "; $file";
+ }
+ }
+ }
+
+ print_simple_box_start();
+ echo get_string("lastmodified").": ";
+ echo userdate($submission->timemodified);
+ echo $this->display_lateness($submission->timemodified);
+
+ $this->print_user_files($user->id);
+
+ echo '<br />';
+
+ if (empty($submission->timemarked)) {
+ print_string("notgradedyet", "assignment");
+ } else {
+ $this->view_feedback($submission);
+ }
+
+ print_simple_box_end();
+
+ } else {
+ print_string("notsubmittedyet", "assignment");
+ }
+ }
+
+ /**
+ * Return a string indicating how late a submission is
+ *
+ * @param $timesubmitted int
+ * @return string
+ */
+ function display_lateness($timesubmitted) {
+ return assignment_display_lateness($timesubmitted, $this->assignment->timedue);
+ }
+
+ /**
+ * Empty method stub for all delete actions.
+ */
+ function delete() {
+ //nothing by default
+ redirect('view.php?id='.$this->cm->id);
+ }
+
+ /**
+ * Empty custom feedback grading form.
+ */
+ function custom_feedbackform($submission, $return=false) {
+ //nothing by default
+ return '';
+ }
+
+ /**
+ * Add a get_coursemodule_info function in case any assignment type wants to add 'extra' information
+ * for the course (see resource).
+ *
+ * Given a course_module object, this function returns any "extra" information that may be needed
+ * when printing this activity in a course listing. See get_array_of_activities() in course/lib.php.
+ *
+ * @param $coursemodule object The coursemodule object (record).
+ * @return object An object on information that the coures will know about (most noticeably, an icon).
+ *
+ */
+ function get_coursemodule_info($coursemodule) {
+ return false;
+ }
+
+ /**
+ * Plugin cron method - do not use $this here, create new assignment instances if needed.
+ * @return void
+ */
+ function cron() {
+ //no plugin cron by default - override if needed
+ }
+
+ /**
+ * Reset all submissions
+ */
+ function reset_userdata($data) {
+ global $CFG;
+ require_once($CFG->libdir.'/filelib.php');
+
+ if (!count_records('assignment', 'course', $data->courseid, 'assignmenttype', $this->type)) {
+ return array(); // no assignments of this type present
+ }
+
+ $componentstr = get_string('modulenameplural', 'assignment');
+ $status = array();
+
+ $typestr = get_string('type'.$this->type, 'assignment');
+
+ if (!empty($data->reset_assignment_submissions)) {
+ $assignmentssql = "SELECT a.id
+ FROM {$CFG->prefix}assignment a
+ WHERE a.course={$data->courseid} AND a.assignmenttype='{$this->type}'";
+
+ delete_records_select('assignment_submissions', "assignment IN ($assignmentssql)");
+
+ if ($assignments = get_records_sql($assignmentssql)) {
+ foreach ($assignments as $assignmentid=>$unused) {
+ fulldelete($CFG->dataroot.'/'.$data->courseid.'/moddata/assignment/'.$assignmentid);
+ }
+ }
+
+ $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallsubmissions','assignment').': '.$typestr, 'error'=>false);
+
+ if (empty($data->reset_gradebook_grades)) {
+ // remove all grades from gradebook
+ assignment_reset_gradebook($data->courseid, $this->type);
+ }
+ }
+
+ /// updating dates - shift may be negative too
+ if ($data->timeshift) {
+ shift_course_mod_dates('assignment', array('timedue', 'timeavailable'), $data->timeshift, $data->courseid);
+ $status[] = array('component'=>$componentstr, 'item'=>get_string('datechanged').': '.$typestr, 'error'=>false);
+ }
+
+ return $status;
+ }
+} ////// End of the assignment_base class
+
+
+
+/// OTHER STANDARD FUNCTIONS ////////////////////////////////////////////////////////
+
+/**
+ * Deletes an assignment instance
+ *
+ * This is done by calling the delete_instance() method of the assignment type class
+ */
+function assignment_delete_instance($id){
+ global $CFG;
+
+ if (! $assignment = get_record('assignment', 'id', $id)) {
+ return false;
+ }
+
+ // fall back to base class if plugin missing
+ $classfile = "$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php";
+ if (file_exists($classfile)) {
+ require_once($classfile);
+ $assignmentclass = "assignment_$assignment->assignmenttype";
+
+ } else {
+ debugging("Missing assignment plug-in: {$assignment->assignmenttype}. Using base class for deleting instead.");
+ $assignmentclass = "assignment_base";
+ }
+
+ $ass = new $assignmentclass();
+ return $ass->delete_instance($assignment);
+}
+
+
+/**
+ * Updates an assignment instance
+ *
+ * This is done by calling the update_instance() method of the assignment type class
+ */
+function assignment_update_instance($assignment){
+ global $CFG;
+
+ $assignment->assignmenttype = clean_param($assignment->assignmenttype, PARAM_SAFEDIR);
+
+ require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
+ $assignmentclass = "assignment_$assignment->assignmenttype";
+ $ass = new $assignmentclass();
+ return $ass->update_instance($assignment);
+}
+
+
+/**
+ * Adds an assignment instance
+ *
+ * This is done by calling the add_instance() method of the assignment type class
+ */
+function assignment_add_instance($assignment) {
+ global $CFG;
+
+ $assignment->assignmenttype = clean_param($assignment->assignmenttype, PARAM_SAFEDIR);
+
+ require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
+ $assignmentclass = "assignment_$assignment->assignmenttype";
+ $ass = new $assignmentclass();
+ return $ass->add_instance($assignment);
+}
+
+
+/**
+ * Returns an outline of a user interaction with an assignment
+ *
+ * This is done by calling the user_outline() method of the assignment type class
+ */
+function assignment_user_outline($course, $user, $mod, $assignment) {
+ global $CFG;
+
+ require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
+ $assignmentclass = "assignment_$assignment->assignmenttype";
+ $ass = new $assignmentclass($mod->id, $assignment, $mod, $course);
+ return $ass->user_outline($user);
+}
+
+/**
+ * Prints the complete info about a user's interaction with an assignment
+ *
+ * This is done by calling the user_complete() method of the assignment type class
+ */
+function assignment_user_complete($course, $user, $mod, $assignment) {
+ global $CFG;
+
+ require_once("$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php");
+ $assignmentclass = "assignment_$assignment->assignmenttype";
+ $ass = new $assignmentclass($mod->id, $assignment, $mod, $course);
+ return $ass->user_complete($user);
+}
+
+/**
+ * Function to be run periodically according to the moodle cron
+ *
+ * Finds all assignment notifications that have yet to be mailed out, and mails them
+ */
+function assignment_cron () {
+
+ global $CFG, $USER;
+
+ /// first execute all crons in plugins
+ if ($plugins = get_list_of_plugins('mod/assignment/type')) {
+ foreach ($plugins as $plugin) {
+ require_once("$CFG->dirroot/mod/assignment/type/$plugin/assignment.class.php");
+ $assignmentclass = "assignment_$plugin";
+ $ass = new $assignmentclass();
+ $ass->cron();
+ }
+ }
+
+ /// Notices older than 1 day will not be mailed. This is to avoid the problem where
+ /// cron has not been running for a long time, and then suddenly people are flooded
+ /// with mail from the past few weeks or months
+
+ $timenow = time();
+ $endtime = $timenow - $CFG->maxeditingtime;
+ $starttime = $endtime - 24 * 3600; /// One day earlier
+
+ if ($submissions = assignment_get_unmailed_submissions($starttime, $endtime)) {
+
+ $realuser = clone($USER);
+
+ foreach ($submissions as $key => $submission) {
+ if (! set_field("assignment_submissions", "mailed", "1", "id", "$submission->id")) {
+ echo "Could not update the mailed field for id $submission->id. Not mailed.\n";
+ unset($submissions[$key]);
+ }
+ }
+
+ $timenow = time();
+
+ foreach ($submissions as $submission) {
+
+ echo "Processing assignment submission $submission->id\n";
+
+ if (! $user = get_record("user", "id", "$submission->userid")) {
+ echo "Could not find user $post->userid\n";
+ continue;
+ }
+
+ if (! $course = get_record("course", "id", "$submission->course")) {
+ echo "Could not find course $submission->course\n";
+ continue;
+ }
+
+ /// Override the language and timezone of the "current" user, so that
+ /// mail is customised for the receiver.
+ $USER = $user;
+ course_setup($course);
+
+ if (!has_capability('moodle/course:view', get_context_instance(CONTEXT_COURSE, $submission->course), $user->id)) {
+ echo fullname($user)." not an active participant in " . format_string($course->shortname) . "\n";
+ continue;
+ }
+
+ if (! $teacher = get_record("user", "id", "$submission->teacher")) {
+ echo "Could not find teacher $submission->teacher\n";
+ continue;
+ }
+
+ if (! $mod = get_coursemodule_from_instance("assignment", $submission->assignment, $course->id)) {
+ echo "Could not find course module for assignment id $submission->assignment\n";
+ continue;
+ }
+
+ if (! $mod->visible) { /// Hold mail notification for hidden assignments until later
+ continue;
+ }
+
+ $strassignments = get_string("modulenameplural", "assignment");
+ $strassignment = get_string("modulename", "assignment");
+
+ $assignmentinfo = new object();
+ $assignmentinfo->teacher = fullname($teacher);
+ $assignmentinfo->assignment = format_string($submission->name,true);
+ $assignmentinfo->url = "$CFG->wwwroot/mod/assignment/view.php?id=$mod->id";
+
+ $postsubject = "$course->shortname: $strassignments: ".format_string($submission->name,true);
+ $posttext = "$course->shortname -> $strassignments -> ".format_string($submission->name,true)."\n";
+ $posttext .= "---------------------------------------------------------------------\n";
+ $posttext .= get_string("assignmentmail", "assignment", $assignmentinfo)."\n";
+ $posttext .= "---------------------------------------------------------------------\n";
+
+ if ($user->mailformat == 1) { // HTML
+ $posthtml = "<p><font face=\"sans-serif\">".
+ "<a href=\"$CFG->wwwroot/course/view.php?id=$course->id\">$course->shortname</a> ->".
+ "<a href=\"$CFG->wwwroot/mod/assignment/index.php?id=$course->id\">$strassignments</a> ->".
+ "<a href=\"$CFG->wwwroot/mod/assignment/view.php?id=$mod->id\">".format_string($submission->name,true)."</a></font></p>";
+ $posthtml .= "<hr /><font face=\"sans-serif\">";
+ $posthtml .= "<p>".get_string("assignmentmailhtml", "assignment", $assignmentinfo)."</p>";
+ $posthtml .= "</font><hr />";
+ } else {
+ $posthtml = "";
+ }
+
+ if (! email_to_user($user, $teacher, $postsubject, $posttext, $posthtml)) {
+ echo "Error: assignment cron: Could not send out mail for id $submission->id to user $user->id ($user->email)\n";
+ }
+ }
+
+ $USER = $realuser;
+ course_setup(SITEID); // reset cron user language, theme and timezone settings
+
+ }
+
+ return true;
+}
+
+/**
+ * Return grade for given user or all users.
+ *
+ * @param int $assignmentid id of assignment
+ * @param int $userid optional user id, 0 means all users
+ * @return array array of grades, false if none
+ */
+function assignment_get_user_grades($assignment, $userid=0) {
+ global $CFG;
+
+ $user = $userid ? "AND u.id = $userid" : "";
+
+ $sql = "SELECT u.id, u.id AS userid, s.grade AS rawgrade, s.submissioncomment AS feedback, s.format AS feedbackformat,
+ s.teacher AS usermodified, s.timemarked AS dategraded, s.timemodified AS datesubmitted
+ FROM {$CFG->prefix}user u, {$CFG->prefix}assignment_submissions s
+ WHERE u.id = s.userid AND s.assignment = $assignment->id
+ $user";
+
+ return get_records_sql($sql);
+}
+
+/**
+ * Update grades by firing grade_updated event
+ *
+ * @param object $assignment null means all assignments
+ * @param int $userid specific user only, 0 mean all
+ */
+function assignment_update_grades($assignment=null, $userid=0, $nullifnone=true) {
+ global $CFG;
+ if (!function_exists('grade_update')) { //workaround for buggy PHP versions
+ require_once($CFG->libdir.'/gradelib.php');
+ }
+
+ if ($assignment != null) {
+ if ($grades = assignment_get_user_grades($assignment, $userid)) {
+ foreach($grades as $k=>$v) {
+ if ($v->rawgrade == -1) {
+ $grades[$k]->rawgrade = null;
+ }
+ }
+ assignment_grade_item_update($assignment, $grades);
+ } else {
+ assignment_grade_item_update($assignment);
+ }
+
+ } else {
+ $sql = "SELECT a.*, cm.idnumber as cmidnumber, a.course as courseid
+ FROM {$CFG->prefix}assignment a, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules m
+ WHERE m.name='assignment' AND m.id=cm.module AND cm.instance=a.id";
+ if ($rs = get_recordset_sql($sql)) {
+ while ($assignment = rs_fetch_next_record($rs)) {
+ if ($assignment->grade != 0) {
+ assignment_update_grades($assignment);
+ } else {
+ assignment_grade_item_update($assignment);
+ }
+ }
+ rs_close($rs);
+ }
+ }
+}
+
+/**
+ * Create grade item for given assignment
+ *
+ * @param object $assignment object with extra cmidnumber
+ * @param mixed optional array/object of grade(s); 'reset' means reset grades in gradebook
+ * @return int 0 if ok, error code otherwise
+ */
+function assignment_grade_item_update($assignment, $grades=NULL) {
+ global $CFG;
+ if (!function_exists('grade_update')) { //workaround for buggy PHP versions
+ require_once($CFG->libdir.'/gradelib.php');
+ }
+
+ if (!isset($assignment->courseid)) {
+ $assignment->courseid = $assignment->course;
+ }
+
+ $params = array('itemname'=>$assignment->name, 'idnumber'=>$assignment->cmidnumber);
+
+ if ($assignment->grade > 0) {
+ $params['gradetype'] = GRADE_TYPE_VALUE;
+ $params['grademax'] = $assignment->grade;
+ $params['grademin'] = 0;
+
+ } else if ($assignment->grade < 0) {
+ $params['gradetype'] = GRADE_TYPE_SCALE;
+ $params['scaleid'] = -$assignment->grade;
+
+ } else {
+ $params['gradetype'] = GRADE_TYPE_TEXT; // allow text comments only
+ }
+
+ if ($grades === 'reset') {
+ $params['reset'] = true;
+ $grades = NULL;
+ }
+
+ return grade_update('mod/assignment', $assignment->courseid, 'mod', 'assignment', $assignment->id, 0, $grades, $params);
+}
+
+/**
+ * Delete grade item for given assignment
+ *
+ * @param object $assignment object
+ * @return object assignment
+ */
+function assignment_grade_item_delete($assignment) {
+ global $CFG;
+ require_once($CFG->libdir.'/gradelib.php');
+
+ if (!isset($assignment->courseid)) {
+ $assignment->courseid = $assignment->course;
+ }
+
+ return grade_update('mod/assignment', $assignment->courseid, 'mod', 'assignment', $assignment->id, 0, NULL, array('deleted'=>1));
+}
+
+/**
+ * Returns the users with data in one assignment (students and teachers)
+ *
+ * @param $assignmentid int
+ * @return array of user objects
+ */
+function assignment_get_participants($assignmentid) {
+
+ global $CFG;
+
+ //Get students
+ $students = get_records_sql("SELECT DISTINCT u.id, u.id
+ FROM {$CFG->prefix}user u,
+ {$CFG->prefix}assignment_submissions a
+ WHERE a.assignment = '$assignmentid' and
+ u.id = a.userid");
+ //Get teachers
+ $teachers = get_records_sql("SELECT DISTINCT u.id, u.id
+ FROM {$CFG->prefix}user u,
+ {$CFG->prefix}assignment_submissions a
+ WHERE a.assignment = '$assignmentid' and
+ u.id = a.teacher");
+
+ //Add teachers to students
+ if ($teachers) {
+ foreach ($teachers as $teacher) {
+ $students[$teacher->id] = $teacher;
+ }
+ }
+ //Return students array (it contains an array of unique users)
+ return ($students);
+}
+
+/**
+ * Checks if a scale is being used by an assignment
+ *
+ * This is used by the backup code to decide whether to back up a scale
+ * @param $assignmentid int
+ * @param $scaleid int
+ * @return boolean True if the scale is used by the assignment
+ */
+function assignment_scale_used($assignmentid, $scaleid) {
+
+ $return = false;
+
+ $rec = get_record('assignment','id',$assignmentid,'grade',-$scaleid);
+
+ if (!empty($rec) && !empty($scaleid)) {
+ $return = true;
+ }
+
+ return $return;
+}
+
+/**
+ * Checks if scale is being used by any instance of assignment
+ *
+ * This is used to find out if scale used anywhere
+ * @param $scaleid int
+ * @return boolean True if the scale is used by any assignment
+ */
+function assignment_scale_used_anywhere($scaleid) {
+ if ($scaleid and record_exists('assignment', 'grade', -$scaleid)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/**
+ * Make sure up-to-date events are created for all assignment instances
+ *
+ * This standard function will check all instances of this module
+ * and make sure there are up-to-date events created for each of them.
+ * If courseid = 0, then every assignment event in the site is checked, else
+ * only assignment events belonging to the course specified are checked.
+ * This function is used, in its new format, by restore_refresh_events()
+ *
+ * @param $courseid int optional If zero then all assignments for all courses are covered
+ * @return boolean Always returns true
+ */
+function assignment_refresh_events($courseid = 0) {
+
+ if ($courseid == 0) {
+ if (! $assignments = get_records("assignment")) {
+ return true;
+ }
+ } else {
+ if (! $assignments = get_records("assignment", "course", $courseid)) {
+ return true;
+ }
+ }
+ $moduleid = get_field('modules', 'id', 'name', 'assignment');
+
+ foreach ($assignments as $assignment) {
+ $event = NULL;
+ $event->name = addslashes($assignment->name);
+ $event->description = addslashes($assignment->description);
+ $event->timestart = $assignment->timedue;
+
+ if ($event->id = get_field('event', 'id', 'modulename', 'assignment', 'instance', $assignment->id)) {
+ update_event($event);
+
+ } else {
+ $event->courseid = $assignment->course;
+ $event->groupid = 0;
+ $event->userid = 0;
+ $event->modulename = 'assignment';
+ $event->instance = $assignment->id;
+ $event->eventtype = 'due';
+ $event->timeduration = 0;
+ $event->visible = get_field('course_modules', 'visible', 'module', $moduleid, 'instance', $assignment->id);
+ add_event($event);
+ }
+
+ }
+ return true;
+}
+
+/**
+ * Print recent activity from all assignments in a given course
+ *
+ * This is used by the recent activity block
+ */
+function assignment_print_recent_activity($course, $viewfullnames, $timestart) {
+ global $CFG, $USER;
+
+ // do not use log table if possible, it may be huge
+
+ if (!$submissions = get_records_sql("SELECT asb.id, asb.timemodified, cm.id AS cmid, asb.userid,
+ u.firstname, u.lastname, u.email, u.picture
+ FROM {$CFG->prefix}assignment_submissions asb
+ JOIN {$CFG->prefix}assignment a ON a.id = asb.assignment
+ JOIN {$CFG->prefix}course_modules cm ON cm.instance = a.id
+ JOIN {$CFG->prefix}modules md ON md.id = cm.module
+ JOIN {$CFG->prefix}user u ON u.id = asb.userid
+ WHERE asb.timemodified > $timestart AND
+ a.course = {$course->id} AND
+ md.name = 'assignment'
+ ORDER BY asb.timemodified ASC")) {
+ return false;
+ }
+
+ $modinfo =& get_fast_modinfo($course); // reference needed because we might load the groups
+ $show = array();
+ $grader = array();
+
+ foreach($submissions as $submission) {
+ if (!array_key_exists($submission->cmid, $modinfo->cms)) {
+ continue;
+ }
+ $cm = $modinfo->cms[$submission->cmid];
+ if (!$cm->uservisible) {
+ continue;
+ }
+ if ($submission->userid == $USER->id) {
+ $show[] = $submission;
+ continue;
+ }
+
+ // the act of sumbitting of assignment may be considered private - only graders will see it if specified
+ if (empty($CFG->assignment_showrecentsubmissions)) {
+ if (!array_key_exists($cm->id, $grader)) {
+ $grader[$cm->id] = has_capability('moodle/grade:viewall', get_context_instance(CONTEXT_MODULE, $cm->id));
+ }
+ if (!$grader[$cm->id]) {
+ continue;
+ }
+ }
+
+ $groupmode = groups_get_activity_groupmode($cm, $course);
+
+ if ($groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', get_context_instance(CONTEXT_MODULE, $cm->id))) {
+ if (isguestuser()) {
+ // shortcut - guest user does not belong into any group
+ continue;
+ }
+
+ if (is_null($modinfo->groups)) {
+ $modinfo->groups = groups_get_user_groups($course->id); // load all my groups and cache it in modinfo
+ }
+
+ // this will be slow - show only users that share group with me in this cm
+ if (empty($modinfo->groups[$cm->id])) {
+ continue;
+ }
+ $usersgroups = groups_get_all_groups($course->id, $cm->userid, $cm->groupingid);
+ if (is_array($usersgroups)) {
+ $usersgroups = array_keys($usersgroups);
+ $interset = array_intersect($usersgroups, $modinfo->groups[$cm->id]);
+ if (empty($intersect)) {
+ continue;
+ }
+ }
+ }
+ $show[] = $submission;
+ }
+
+ if (empty($show)) {
+ return false;
+ }
+
+ print_headline(get_string('newsubmissions', 'assignment').':');
+
+ foreach ($show as $submission) {
+ $cm = $modinfo->cms[$submission->cmid];
+ $link = $CFG->wwwroot.'/mod/assignment/view.php?id='.$cm->id;
+ print_recent_activity_note($submission->timemodified, $submission, $cm->name, $link, false, $viewfullnames);
+ }
+
+ return true;
+}
+
+
+/**
+ * Returns all assignments since a given time in specified forum.
+ */
+function assignment_get_recent_mod_activity(&$activities, &$index, $timestart, $courseid, $cmid, $userid=0, $groupid=0) {
+
+ global $CFG, $COURSE, $USER;
+
+ if ($COURSE->id == $courseid) {
+ $course = $COURSE;
+ } else {
+ $course = get_record('course', 'id', $courseid);
+ }
+
+ $modinfo =& get_fast_modinfo($course);
+
+ $cm = $modinfo->cms[$cmid];
+
+ if ($userid) {
+ $userselect = "AND u.id = $userid";
+ } else {
+ $userselect = "";
+ }
+
+ if ($groupid) {
+ $groupselect = "AND gm.groupid = $groupid";
+ $groupjoin = "JOIN {$CFG->prefix}groups_members gm ON gm.userid=u.id";
+ } else {
+ $groupselect = "";
+ $groupjoin = "";
+ }
+
+ if (!$submissions = get_records_sql("SELECT asb.id, asb.timemodified, asb.userid,
+ u.firstname, u.lastname, u.email, u.picture
+ FROM {$CFG->prefix}assignment_submissions asb
+ JOIN {$CFG->prefix}assignment a ON a.id = asb.assignment
+ JOIN {$CFG->prefix}user u ON u.id = asb.userid
+ $groupjoin
+ WHERE asb.timemodified > $timestart AND a.id = $cm->instance
+ $userselect $groupselect
+ ORDER BY asb.timemodified ASC")) {
+ return;
+ }
+
+ $groupmode = groups_get_activity_groupmode($cm, $course);
+ $cm_context = get_context_instance(CONTEXT_MODULE, $cm->id);
+ $grader = has_capability('moodle/grade:viewall', $cm_context);
+ $accessallgroups = has_capability('moodle/site:accessallgroups', $cm_context);
+ $viewfullnames = has_capability('moodle/site:viewfullnames', $cm_context);
+
+ if (is_null($modinfo->groups)) {
+ $modinfo->groups = groups_get_user_groups($course->id); // load all my groups and cache it in modinfo
+ }
+
+ $show = array();
+
+ foreach($submissions as $submission) {
+ if ($submission->userid == $USER->id) {
+ $show[] = $submission;
+ continue;
+ }
+ // the act of submitting of assignment may be considered private - only graders will see it if specified
+ if (empty($CFG->assignment_showrecentsubmissions)) {
+ if (!$grader) {
+ continue;
+ }
+ }
+
+ if ($groupmode == SEPARATEGROUPS and !$accessallgroups) {
+ if (isguestuser()) {
+ // shortcut - guest user does not belong into any group
+ continue;
+ }
+
+ // this will be slow - show only users that share group with me in this cm
+ if (empty($modinfo->groups[$cm->id])) {
+ continue;
+ }
+ $usersgroups = groups_get_all_groups($course->id, $cm->userid, $cm->groupingid);
+ if (is_array($usersgroups)) {
+ $usersgroups = array_keys($usersgroups);
+ $interset = array_intersect($usersgroups, $modinfo->groups[$cm->id]);
+ if (empty($intersect)) {
+ continue;
+ }
+ }
+ }
+ $show[] = $submission;
+ }
+
+ if (empty($show)) {
+ return;
+ }
+
+ if ($grader) {
+ require_once($CFG->libdir.'/gradelib.php');
+ $userids = array();
+ foreach ($show as $id=>$submission) {
+ $userids[] = $submission->userid;
+
+ }
+ $grades = grade_get_grades($courseid, 'mod', 'assignment', $cm->instance, $userids);
+ }
+
+ $aname = format_string($cm->name,true);
+ foreach ($show as $submission) {
+ $tmpactivity = new object();
+
+ $tmpactivity->type = 'assignment';
+ $tmpactivity->cmid = $cm->id;
+ $tmpactivity->name = $aname;
+ $tmpactivity->sectionnum = $cm->sectionnum;
+ $tmpactivity->timestamp = $submission->timemodified;
+
+ if ($grader) {
+ $tmpactivity->grade = $grades->items[0]->grades[$submission->userid]->str_long_grade;
+ }
+
+ $tmpactivity->user->userid = $submission->userid;
+ $tmpactivity->user->fullname = fullname($submission, $viewfullnames);
+ $tmpactivity->user->picture = $submission->picture;
+
+ $activities[$index++] = $tmpactivity;
+ }
+
+ return;
+}
+
+/**
+ * Print recent activity from all assignments in a given course
+ *
+ * This is used by course/recent.php
+ */
+function assignment_print_recent_mod_activity($activity, $courseid, $detail, $modnames) {
+ global $CFG;
+
+ echo '<table border="0" cellpadding="3" cellspacing="0" class="assignment-recent">';
+
+ echo "<tr><td class=\"userpicture\" valign=\"top\">";
+ print_user_picture($activity->user->userid, $courseid, $activity->user->picture);
+ echo "</td><td>";
+
+ if ($detail) {
+ $modname = $modnames[$activity->type];
+ echo '<div class="title">';
+ echo "<img src=\"$CFG->modpixpath/assignment/icon.gif\" ".
+ "class=\"icon\" alt=\"$modname\">";
+ echo "<a href=\"$CFG->wwwroot/mod/assignment/view.php?id={$activity->cmid}\">{$activity->name}</a>";
+ echo '</div>';
+ }
+
+ if (isset($activity->grade)) {
+ echo '<div class="grade">';
+ echo get_string('grade').': ';
+ echo $activity->grade;
+ echo '</div>';
+ }
+
+ echo '<div class="user">';
+ echo "<a href=\"$CFG->wwwroot/user/view.php?id={$activity->user->userid}&amp;course=$courseid\">"
+ ."{$activity->user->fullname}</a> - ".userdate($activity->timestamp);
+ echo '</div>';
+
+ echo "</td></tr></table>";
+}
+
+/// GENERIC SQL FUNCTIONS
+
+/**
+ * Fetch info from logs
+ *
+ * @param $log object with properties ->info (the assignment id) and ->userid
+ * @return array with assignment name and user firstname and lastname
+ */
+function assignment_log_info($log) {
+ global $CFG;
+ return get_record_sql("SELECT a.name, u.firstname, u.lastname
+ FROM {$CFG->prefix}assignment a,
+ {$CFG->prefix}user u
+ WHERE a.id = '$log->info'
+ AND u.id = '$log->userid'");
+}
+
+/**
+ * Return list of marked submissions that have not been mailed out for currently enrolled students
+ *
+ * @return array
+ */
+function assignment_get_unmailed_submissions($starttime, $endtime) {
+
+ global $CFG;
+
+ return get_records_sql("SELECT s.*, a.course, a.name
+ FROM {$CFG->prefix}assignment_submissions s,
+ {$CFG->prefix}assignment a
+ WHERE s.mailed = 0
+ AND s.timemarked <= $endtime
+ AND s.timemarked >= $starttime
+ AND s.assignment = a.id");
+
+ /* return get_records_sql("SELECT s.*, a.course, a.name
+ FROM {$CFG->prefix}assignment_submissions s,
+ {$CFG->prefix}assignment a,
+ {$CFG->prefix}user_students us
+ WHERE s.mailed = 0
+ AND s.timemarked <= $endtime
+ AND s.timemarked >= $starttime
+ AND s.assignment = a.id
+ AND s.userid = us.userid
+ AND a.course = us.course");
+ */
+}
+
+/**
+ * Counts all real assignment submissions by ENROLLED students (not empty ones)
+ *
+ * There are also assignment type methods count_real_submissions() wich in the default
+ * implementation simply call this function.
+ * @param $groupid int optional If nonzero then count is restricted to this group
+ * @return int The number of submissions
+ */
+function assignment_count_real_submissions($cm, $groupid=0) {
+ global $CFG;
+
+ $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+
+ // this is all the users with this capability set, in this context or higher
+ if ($users = get_users_by_capability($context, 'mod/assignment:submit', 'u.id', '', '', '', $groupid, '', false)) {
+ $users = array_keys($users);
+ }
+
+ // if groupmembersonly used, remove users who are not in any group
+ if ($users and !empty($CFG->enablegroupings) and $cm->groupmembersonly) {
+ if ($groupingusers = groups_get_grouping_members($cm->groupingid, 'u.id', 'u.id')) {
+ $users = array_intersect($users, array_keys($groupingusers));
+ }
+ }
+
+ if (empty($users)) {
+ return 0;
+ }
+
+ $userlists = implode(',', $users);
+
+ return count_records_sql("SELECT COUNT('x')
+ FROM {$CFG->prefix}assignment_submissions
+ WHERE assignment = $cm->instance AND
+ timemodified > 0 AND
+ userid IN ($userlists)");
+}
+
+
+/**
+ * Return all assignment submissions by ENROLLED students (even empty)
+ *
+ * There are also assignment type methods get_submissions() wich in the default
+ * implementation simply call this function.
+ * @param $sort string optional field names for the ORDER BY in the sql query
+ * @param $dir string optional specifying the sort direction, defaults to DESC
+ * @return array The submission objects indexed by id
+ */
+function assignment_get_all_submissions($assignment, $sort="", $dir="DESC") {
+/// Return all assignment submissions by ENROLLED students (even empty)
+ global $CFG;
+
+ if ($sort == "lastname" or $sort == "firstname") {
+ $sort = "u.$sort $dir";
+ } else if (empty($sort)) {
+ $sort = "a.timemodified DESC";
+ } else {
+ $sort = "a.$sort $dir";
+ }
+
+ /* not sure this is needed at all since assignmenet already has a course define, so this join?
+ $select = "s.course = '$assignment->course' AND";
+ if ($assignment->course == SITEID) {
+ $select = '';
+ }*/
+
+ return get_records_sql("SELECT a.*
+ FROM {$CFG->prefix}assignment_submissions a,
+ {$CFG->prefix}user u
+ WHERE u.id = a.userid
+ AND a.assignment = '$assignment->id'
+ ORDER BY $sort");
+
+ /* return get_records_sql("SELECT a.*
+ FROM {$CFG->prefix}assignment_submissions a,
+ {$CFG->prefix}user_students s,
+ {$CFG->prefix}user u
+ WHERE a.userid = s.userid
+ AND u.id = a.userid
+ AND $select a.assignment = '$assignment->id'
+ ORDER BY $sort");
+ */
+}
+
+/**
+ * Add a get_coursemodule_info function in case any assignment type wants to add 'extra' information
+ * for the course (see resource).
+ *
+ * Given a course_module object, this function returns any "extra" information that may be needed
+ * when printing this activity in a course listing. See get_array_of_activities() in course/lib.php.
+ *
+ * @param $coursemodule object The coursemodule object (record).
+ * @return object An object on information that the coures will know about (most noticeably, an icon).
+ *
+ */
+function assignment_get_coursemodule_info($coursemodule) {
+ global $CFG;
+
+ if (! $assignment = get_record('assignment', 'id', $coursemodule->instance, '', '', '', '', 'id, assignmenttype, name')) {
+ return false;
+ }
+
+ $libfile = "$CFG->dirroot/mod/assignment/type/$assignment->assignmenttype/assignment.class.php";
+
+ if (file_exists($libfile)) {
+ require_once($libfile);
+ $assignmentclass = "assignment_$assignment->assignmenttype";
+ $ass = new $assignmentclass('staticonly');
+ if ($result = $ass->get_coursemodule_info($coursemodule)) {
+ return $result;
+ } else {
+ $info = new object();
+ $info->name = $assignment->name;
+ return $info;
+ }
+
+ } else {
+ debugging('Incorrect assignment type: '.$assignment->assignmenttype);
+ return false;
+ }
+}
+
+
+
+/// OTHER GENERAL FUNCTIONS FOR ASSIGNMENTS ///////////////////////////////////////
+
+/**
+ * Returns an array of installed assignment types indexed and sorted by name
+ *
+ * @return array The index is the name of the assignment type, the value its full name from the language strings
+ */
+function assignment_types() {
+ $types = array();
+ $names = get_list_of_plugins('mod/assignment/type');
+ foreach ($names as $name) {
+ $types[$name] = get_string('type'.$name, 'assignment');
+ }
+ asort($types);
+ return $types;
+}
+
+/**
+ * Executes upgrade scripts for assignment types when necessary
+ */
+function assignment_upgrade_submodules() {
+
+ global $CFG;
+
+/// Install/upgrade assignment types (it uses, simply, the standard plugin architecture)
+ upgrade_plugins('assignment_type', 'mod/assignment/type', "$CFG->wwwroot/$CFG->admin/index.php");
+
+}
+
+function assignment_print_overview($courses, &$htmlarray) {
+
+ global $USER, $CFG;
+
+ if (empty($courses) || !is_array($courses) || count($courses) == 0) {
+ return array();
+ }
+
+ if (!$assignments = get_all_instances_in_courses('assignment',$courses)) {
+ return;
+ }
+
+ $assignmentids = array();
+
+ // Do assignment_base::isopen() here without loading the whole thing for speed
+ foreach ($assignments as $key => $assignment) {
+ $time = time();
+ if ($assignment->timedue) {
+ if ($assignment->preventlate) {
+ $isopen = ($assignment->timeavailable <= $time && $time <= $assignment->timedue);
+ } else {
+ $isopen = ($assignment->timeavailable <= $time);
+ }
+ }
+ if (empty($isopen) || empty($assignment->timedue)) {
+ unset($assignments[$key]);
+ }else{
+ $assignmentids[] = $assignment->id;
+ }
+ }
+
+ if(empty($assignmentids)){
+ // no assigments to look at - we're done
+ return true;
+ }
+
+ $strduedate = get_string('duedate', 'assignment');
+ $strduedateno = get_string('duedateno', 'assignment');
+ $strgraded = get_string('graded', 'assignment');
+ $strnotgradedyet = get_string('notgradedyet', 'assignment');
+ $strnotsubmittedyet = get_string('notsubmittedyet', 'assignment');
+ $strsubmitted = get_string('submitted', 'assignment');
+ $strassignment = get_string('modulename', 'assignment');
+ $strreviewed = get_string('reviewed','assignment');
+
+
+ // NOTE: we do all possible database work here *outside* of the loop to ensure this scales
+
+ // build up and array of unmarked submissions indexed by assigment id/ userid
+ // for use where the user has grading rights on assigment
+ $rs = get_recordset_sql("SELECT id, assignment, userid
+ FROM {$CFG->prefix}assignment_submissions
+ WHERE teacher = 0 AND timemarked = 0
+ AND assignment IN (". implode(',', $assignmentids).")");
+
+ $unmarkedsubmissions = array();
+ while ($ra = rs_fetch_next_record($rs)) {
+ $unmarkedsubmissions[$ra->assignment][$ra->userid] = $ra->id;
+ }
+ rs_close($rs);
+
+
+ // get all user submissions, indexed by assigment id
+ $mysubmissions = get_records_sql("SELECT assignment, timemarked, teacher, grade
+ FROM {$CFG->prefix}assignment_submissions
+ WHERE userid = {$USER->id} AND
+ assignment IN (".implode(',', $assignmentids).")");
+
+ foreach ($assignments as $assignment) {
+ $str = '<div class="assignment overview"><div class="name">'.$strassignment. ': '.
+ '<a '.($assignment->visible ? '':' class="dimmed"').
+ 'title="'.$strassignment.'" href="'.$CFG->wwwroot.
+ '/mod/assignment/view.php?id='.$assignment->coursemodule.'">'.
+ $assignment->name.'</a></div>';
+ if ($assignment->timedue) {
+ $str .= '<div class="info">'.$strduedate.': '.userdate($assignment->timedue).'</div>';
+ } else {
+ $str .= '<div class="info">'.$strduedateno.'</div>';
+ }
+ $context = get_context_instance(CONTEXT_MODULE, $assignment->coursemodule);
+ if (has_capability('mod/assignment:grade', $context)) {
+
+ // count how many people can submit
+ $submissions = 0; // init
+ if ($students = get_users_by_capability($context, 'mod/assignment:submit', 'u.id', '', '', '', 0, '', false)) {
+ foreach($students as $student){
+ if(isset($unmarkedsubmissions[$assignment->id][$student->id])){
+ $submissions++;
+ }
+ }
+ }
+
+ if ($submissions) {
+ $str .= get_string('submissionsnotgraded', 'assignment', $submissions);
+ }
+ } else {
+ if(isset($mysubmissions[$assignment->id])){
+
+ $submission = $mysubmissions[$assignment->id];
+
+ if ($submission->teacher == 0 && $submission->timemarked == 0) {
+ $str .= $strsubmitted . ', ' . $strnotgradedyet;
+ } else if ($submission->grade <= 0) {
+ $str .= $strsubmitted . ', ' . $strreviewed;
+ } else {
+ $str .= $strsubmitted . ', ' . $strgraded;
+ }
+ } else {
+ $str .= $strnotsubmittedyet . ' ' . assignment_display_lateness(time(), $assignment->timedue);
+ }
+ }
+ $str .= '</div>';
+ if (empty($htmlarray[$assignment->course]['assignment'])) {
+ $htmlarray[$assignment->course]['assignment'] = $str;
+ } else {
+ $htmlarray[$assignment->course]['assignment'] .= $str;
+ }
+ }
+}
+
+function assignment_display_lateness($timesubmitted, $timedue) {
+ if (!$timedue) {
+ return '';
+ }
+ $time = $timedue - $timesubmitted;
+ if ($time < 0) {
+ $timetext = get_string('late', 'assignment', format_time($time));
+ return ' (<span class="late">'.$timetext.'</span>)';
+ } else {
+ $timetext = get_string('early', 'assignment', format_time($time));
+ return ' (<span class="early">'.$timetext.'</span>)';
+ }
+}
+
+function assignment_get_view_actions() {
+ return array('view');
+}
+
+function assignment_get_post_actions() {
+ return array('upload');
+}
+
+function assignment_get_types() {
+ global $CFG;
+ $types = array();
+
+ $type = new object();
+ $type->modclass = MOD_CLASS_ACTIVITY;
+ $type->type = "assignment_group_start";
+ $type->typestr = '--'.get_string('modulenameplural', 'assignment');
+ $types[] = $type;
+
+ $standardassignments = array('upload','online','uploadsingle','offline');
+ foreach ($standardassignments as $assignmenttype) {
+ $type = new object();
+ $type->modclass = MOD_CLASS_ACTIVITY;
+ $type->type = "assignment&amp;type=$assignmenttype";
+ $type->typestr = get_string("type$assignmenttype", 'assignment');
+ $types[] = $type;
+ }
+
+ /// Drop-in extra assignment types
+ $assignmenttypes = get_list_of_plugins('mod/assignment/type');
+ foreach ($assignmenttypes as $assignmenttype) {
+ if (!empty($CFG->{'assignment_hide_'.$assignmenttype})) { // Not wanted
+ continue;
+ }
+ if (!in_array($assignmenttype, $standardassignments)) {
+ $type = new object();
+ $type->modclass = MOD_CLASS_ACTIVITY;
+ $type->type = "assignment&amp;type=$assignmenttype";
+ $type->typestr = get_string("type$assignmenttype", 'assignment');
+ $types[] = $type;
+ }
+ }
+
+ $type = new object();
+ $type->modclass = MOD_CLASS_ACTIVITY;
+ $type->type = "assignment_group_end";
+ $type->typestr = '--';
+ $types[] = $type;
+
+ return $types;
+}
+
+/**
+ * Removes all grades from gradebook
+ * @param int $courseid
+ * @param string optional type
+ */
+function assignment_reset_gradebook($courseid, $type='') {
+ global $CFG;
+
+ $type = $type ? "AND a.assignmenttype='$type'" : '';
+
+ $sql = "SELECT a.*, cm.idnumber as cmidnumber, a.course as courseid
+ FROM {$CFG->prefix}assignment a, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules m
+ WHERE m.name='assignment' AND m.id=cm.module AND cm.instance=a.id AND a.course=$courseid $type";
+
+ if ($assignments = get_records_sql($sql)) {
+ foreach ($assignments as $assignment) {
+ assignment_grade_item_update($assignment, 'reset');
+ }
+ }
+}
+
+/**
+ * This function is used by the reset_course_userdata function in moodlelib.
+ * This function will remove all posts from the specified assignment
+ * and clean up any related data.
+ * @param $data the data submitted from the reset course.
+ * @return array status array
+ */
+function assignment_reset_userdata($data) {
+ global $CFG;
+
+ $status = array();
+
+ foreach (get_list_of_plugins('mod/assignment/type') as $type) {
+ require_once("$CFG->dirroot/mod/assignment/type/$type/assignment.class.php");
+ $assignmentclass = "assignment_$type";
+ $ass = new $assignmentclass();
+ $status = array_merge($status, $ass->reset_userdata($data));
+ }
+
+ return $status;
+}
+
+/**
+ * Implementation of the function for printing the form elements that control
+ * whether the course reset functionality affects the assignment.
+ * @param $mform form passed by reference
+ */
+function assignment_reset_course_form_definition(&$mform) {
+ $mform->addElement('header', 'assignmentheader', get_string('modulenameplural', 'assignment'));
+ $mform->addElement('advcheckbox', 'reset_assignment_submissions', get_string('deleteallsubmissions','assignment'));
+}
+
+/**
+ * Course reset form defaults.
+ */
+function assignment_reset_course_form_defaults($course) {
+ return array('reset_assignment_submissions'=>1);
+}
+
+/**
+ * Returns all other caps used in module
+ */
+function assignment_get_extra_capabilities() {
+ return array('moodle/site:accessallgroups', 'moodle/site:viewfullnames');
+}
+
+?>
diff --git a/Moodle/mod/print/log.txt b/Moodle/mod/print/log.txt
new file mode 100755
index 0000000..85c4b69
--- /dev/null
+++ b/Moodle/mod/print/log.txt
@@ -0,0 +1,47 @@
+Jul 14 05:29:13 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/7: successfull-ok
+Jul 14 05:38:00 submissions.php Host localhost:631 user iwikiwi@localhost : printing job http://localhost.localdomain:631/jobs/8: successfull-ok
+Jul 14 05:40:18 submissions.php Host localhost:631 user iwikiwi@localhost : printing job http://localhost.localdomain:631/jobs/9: successfull-ok
+Jul 14 06:20:21 submissions.php Host localhost:631 user iwikiwi@localhost : printing job http://localhost.localdomain:631/jobs/10: successfull-ok
+Jul 14 06:22:54 submissions.php Host localhost:631 user iwikiwi@localhost : printing job http://localhost.localdomain:631/jobs/11: successfull-ok
+Jul 14 06:23:51 submissions.php Host localhost:631 user iwikiwi@localhost : printing job http://localhost.localdomain:631/jobs/12: successfull-ok
+Jul 14 06:23:56 submissions.php Host localhost:631 user iwikiwi@localhost : printing job http://localhost.localdomain:631/jobs/13: successfull-ok
+Jul 14 06:45:47 submissions.php Host localhost:631 user iwikiwi@localhost : printing job http://localhost.localdomain:631/jobs/14: successfull-ok
+Jul 14 06:48:14 submissions.php Host localhost:631 user iwikiwi@localhost : printing job http://localhost.localdomain:631/jobs/15: successfull-ok
+Jul 14 06:59:20 submissions.php Host localhost:631 user iwikiwi@localhost : printing job http://localhost.localdomain:631/jobs/16: successfull-ok
+Jul 14 07:01:33 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/17: successfull-ok
+Jul 14 07:03:13 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/18: successfull-ok
+Jul 14 07:03:43 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/19: successfull-ok
+Jul 14 07:07:53 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/20: successfull-ok
+Jul 14 07:17:46 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/21: successfull-ok
+Jul 14 07:27:07 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/22: successfull-ok
+Jul 14 12:56:36 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/23: successfull-ok
+Jul 14 12:59:01 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/24: successfull-ok
+Jul 14 14:36:15 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/25: successfull-ok
+Jul 14 14:36:20 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/26: successfull-ok
+Jul 14 14:59:51 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/27: successfull-ok
+Jul 14 15:02:17 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/28: successfull-ok
+Jul 14 15:02:50 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/29: successfull-ok
+Jul 14 15:03:14 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/30: successfull-ok
+Jul 14 15:03:38 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/31: successfull-ok
+Jul 14 15:03:41 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/32: successfull-ok
+Jul 14 15:03:43 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/33: successfull-ok
+Jul 14 15:03:46 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/34: successfull-ok
+Jul 14 15:07:10 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/35: successfull-ok
+Jul 14 15:07:42 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/36: successfull-ok
+Jul 14 15:14:16 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/37: successfull-ok
+Jul 14 19:30:03 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/38: successfull-ok
+Jul 14 19:51:32 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/39: successfull-ok
+Jul 29 21:09:56 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/83: successfull-ok
+Jul 30 14:06:29 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/84: successfull-ok
+Jul 30 14:23:06 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/85: successfull-ok
+Jul 30 14:26:06 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/86: successfull-ok
+Jul 31 00:22:54 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/87: successfull-ok
+Jul 31 03:46:42 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/88: successfull-ok
+Jul 31 03:47:52 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/89: successfull-ok
+Jul 31 03:48:15 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/90: successfull-ok
+Jul 31 03:55:34 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/91: successfull-ok
+Jul 31 04:02:54 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/92: successfull-ok
+Jul 31 04:04:01 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/93: successfull-ok
+Jul 31 05:24:19 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/94: successfull-ok
+Jul 31 05:26:26 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/95: successfull-ok
+Jul 31 05:28:31 submissions.php Host localhost:631 user PHP-SERVER : printing job http://localhost.localdomain:631/jobs/96: successfull-ok
diff --git a/Moodle/mod/print/mod_form.php b/Moodle/mod/print/mod_form.php
new file mode 100755
index 0000000..ce519d8
--- /dev/null
+++ b/Moodle/mod/print/mod_form.php
@@ -0,0 +1,52 @@
+<?php
+require_once ($CFG->dirroot.'/course/moodleform_mod.php');
+
+class mod_print_mod_form extends moodleform_mod {
+
+ function definition() {
+ global $CFG;
+ $mform =& $this->_form;
+
+
+ require_once($CFG->dirroot.'/mod/print/lib.php');
+ $assignmentclass = 'print_base';
+ $assignmentinstance = new $assignmentclass();
+
+//-------------------------------------------------------------------------------
+ $mform->addElement('header', 'general', get_string('general', 'form'));
+
+ $mform->addElement('text', 'name', get_string('assignmentname', 'assignment'), array('size'=>'64'));
+ if (!empty($CFG->formatstringstriptags)) {
+ $mform->setType('name', PARAM_TEXT);
+ } else {
+ $mform->setType('name', PARAM_CLEAN);
+ }
+ $mform->addRule('name', null, 'required', null, 'client');
+
+ $mform->addElement('htmleditor', 'description', get_string('description', 'assignment'));
+ $mform->setType('description', PARAM_RAW);
+ $mform->setHelpButton('description', array('writing', 'questions', 'richtext'), false, 'editorhelpbutton');
+ $mform->addRule('description', get_string('required'), 'required', null, 'client');
+
+
+ $mform->addElement('date_time_selector', 'timeavailable', get_string('availabledate', 'assignment'), array('optional'=>true));
+ $mform->setDefault('timeavailable', time());
+
+ $ynoptions = array( 0 => get_string('no'), 1 => get_string('yes'));
+
+ $mform->addElement('header', 'typedesc', get_string('typeupload','assignment'));
+ $assignmentinstance->setup_elements($mform);
+
+ $features = new stdClass;
+ $features->groups = true;
+ $features->groupings = true;
+ $features->groupmembersonly = true;
+ $this->standard_coursemodule_elements($features);
+
+ $this->add_action_buttons();
+ }
+
+
+
+}
+?> \ No newline at end of file
diff --git a/Moodle/mod/print/print_xmlrpc.php b/Moodle/mod/print/print_xmlrpc.php
new file mode 100755
index 0000000..63df086
--- /dev/null
+++ b/Moodle/mod/print/print_xmlrpc.php
@@ -0,0 +1,133 @@
+<?php
+/*
+ * First, we define some PHP functions to expose via
+ * XML-RPC. Any functions that will be called by a
+ * XML-RPC client need to take three parameters:
+ * The first parameter passed is the name of the
+ * XML-RPC method called, the second is an array
+ * Containing the parameters sent by the client, and
+ * The third is any data sent in the app_data
+ * parameter of the xmlrpc_server_call_method()
+ * function (see below).
+ */
+require_once("../../config.php");
+require_once('lib.php');
+
+function actual_func($file, $title) {
+ require_once("../../config.php");
+ require_once("lib.php");
+ require_once("../../lib/moodlelib.php");
+ global $CFG;
+ global $USER;
+ error_log("okay first step done", 0);
+ #require_login();
+ $olpcxs = get_auth_plugin('olpcxs');
+ $olpcxs->loginpage_hook();
+
+ error_log("require login done", 0);
+ #$userrecord = get_record('user', 'username', $username);
+ #$userid = $userrecord->id;
+ $id = 2;
+ if ($id) {
+ if (! $cm = get_coursemodule_from_id('print', $id)) {
+ error("Course Module ID was incorrect");
+ }
+
+ if (! $assignment = get_record("print", "id", $cm->instance)) {
+ error("assignment ID was incorrect");
+ }
+
+ if (! $course = get_record("course", "id", $assignment->course)) {
+ error("Course is misconfigured");
+ }
+ } else {
+ if (!$assignment = get_record("print", "id", $a)) {
+ error("Course module is incorrect");
+ }
+ if (! $course = get_record("course", "id", $assignment->course)) {
+ error("Course is misconfigured");
+ }
+ if (! $cm = get_coursemodule_from_instance("print", $assignment->id, $course->id)) {
+ error("Course Module ID was incorrect");
+ }
+ }
+
+
+
+
+ $assignmentinstance = new print_base($cm->id, $assignment, $cm, $course);
+ $filearea = $assignmentinstance->file_area_name($USER->id);
+
+
+ $handle = fopen($CFG->dataroot."/".$filearea."/".$title.".pdf", "wb");
+ fwrite($handle, $file->scalar);
+ fclose($handle);
+ $fpath = $CFG->dataroot."/".$filearea."/".$title.".pdf";
+
+ $assignmentinstance->upload_xmlrpc($fpath, $userid, $title, $assignment);// Display or process the submissions
+ return 1;
+}
+function send_func($method_name, $params, $app_data) {
+ $file = $params[0];
+ $title = $params[1];
+ actual_func($file, $title);
+ return 1;
+}
+
+function greeting_func($method_name, $params, $app_data)
+{
+ $name = $params[0];
+ return "Hello, $name. How are you today?";
+}
+
+/*
+ * This creates a server and sets a handle for the
+ * server in the variable $xmlrpc_server
+ */
+$xmlrpc_server = xmlrpc_server_create();
+
+/*
+ * xmlrpc_server_register_method() registers a PHP
+ * function as an XML-RPC method. It takes three
+ * parameters:
+ * The first is the handle of a server created with
+ * xmlrpc_server_create(), the second is the name to
+ * register the server under (this is what needs to
+ * be in the <methodName> of a request for this
+ * method), and the third is the name of the PHP
+ * function to register.
+ */
+
+xmlrpc_server_register_method($xmlrpc_server, "send_func", "send_func");
+xmlrpc_server_register_method($xmlrpc_server, "greeting_func", "greeting_func");
+
+/*
+ * When an XML-RPC request is sent to this script, it
+ * can be found in the raw post data.
+ */
+$request_xml = $HTTP_RAW_POST_DATA;
+
+/*
+ * The xmlrpc_server_call_method() sends a request to
+ * the server and returns the response XML. In this case,
+ * it sends the raw post data we got before. It requires
+ * 3 arguments:
+ * The first is the handle of a server created with
+ * xmlrpc_server_create(), the second is a string containing
+ * an XML-RPC request, and the third is for application data.
+ * Whatever is passed into the third parameter of this function
+ * is passed as the third paramater of the PHP function that the
+ * request is asking for.
+ */
+$response = xmlrpc_server_call_method($xmlrpc_server, $request_xml, '');
+
+// Now we print the response for the client to read.
+print $response;
+
+/*
+ * This method frees the resources for the server specified
+ * It takes one argument, a handle of a server created with
+ * xmlrpc_server_create().
+ */
+xmlrpc_server_destroy($xmlrpc_server);
+?>
diff --git a/Moodle/mod/print/styles.php b/Moodle/mod/print/styles.php
new file mode 100755
index 0000000..658e8ae
--- /dev/null
+++ b/Moodle/mod/print/styles.php
@@ -0,0 +1,176 @@
+#mod-print-submissions .feedback .content,
+#mod-print-submissions .feedback .topic,
+#mod-print-submissions .feedback .picture
+{
+ padding: 10px;
+ border-width:1px;
+ border-style:solid;
+ border-color:#DDDDDD;
+}
+
+#mod-print-submissions form#options div {
+ text-align:right;
+ margin-left:auto;
+ margin-right:20px;
+}
+
+.mod-print .feedback .files {
+ float: right;
+ background-color: #EFEFEF;
+ padding:5px;
+}
+
+.mod-print .feedback .grade,
+.mod-print .feedback .outcome,
+.mod-print .feedback .finalgrade {
+ float: right;
+}
+
+.mod-print .feedback .disabledfeedback {
+ width: 500px;
+ height: 250px;
+}
+
+.mod-print .feedback .from {
+ float: left;
+}
+
+.mod-print .feedback .time {
+ font-size: 0.8em;
+}
+
+.mod-print .late {
+ color: red;
+}
+
+.mod-print .files img {
+ margin-right: 4px;
+}
+
+.mod-print .files a {
+ white-space:nowrap;
+}
+
+#mod-print-submissions .generaltable .r1 {
+ background-color: #FFFFFF;
+}
+
+#mod-print-submissions .header .commands {
+ display: inline;
+}
+
+#mod-print-submissions .s0 {
+ background: #FFD991;
+}
+
+#mod-print-submissions table.submissions td,
+#mod-print-submissions table.submissions th
+{
+ border-width: 1px;
+ border-style: solid;
+ border-color: #DDDDDD;
+ vertical-align: middle;
+ padding-left: 5px;
+ padding-right: 5px;
+}
+
+#mod-print-submissions .submissions .grade {
+ text-align: right;
+ font-weight:bold;
+}
+
+#mod-print-submissions .picture {
+ width: 35px;
+}
+
+#mod-print-submissions .fullname {
+ text-align: left;
+}
+
+#mod-print-submissions .timemodified,
+#mod-print-submissions .timemarked
+{
+ text-align: left;
+ font-size: 0.9em;
+}
+
+#mod-print-submissions .status {
+ text-align: center;
+}
+
+#mod-print-submissions .submissions .outcome,
+#mod-print-submissions .submissions .finalgrade {
+ text-align: right;
+}
+
+#mod-print-view #online .singlebutton {
+ text-align: center;
+}
+
+#mod-print-view #dates {
+ font-size: 0.8em;
+ margin-top: 30px;
+ margin-bottom: 30px;
+}
+
+#mod-print-view #dates .c0{
+ text-align:right;
+ font-weight:bold;
+}
+
+#mod-print-view .feedback {
+ border-width:1px;
+ border-style:solid;
+ border-color:#DDDDDD;
+ margin-top: 15px;
+ width: 80%;
+ margin-left: 10%;
+ margin-right: 10%;
+}
+
+#mod-print-view .feedback .topic {
+ padding: 4px;
+ border-style:solid;
+ border-width: 0px;
+ border-bottom-width: 1px;
+ border-color:#DDDDDD;
+}
+
+#mod-print-view .feedback .fullname {
+ font-weight: bold;
+}
+
+#mod-print-view .feedback .date {
+ font-size: 0.8em;
+}
+
+#mod-print-view .feedback .content {
+ padding: 4px;
+}
+
+#mod-print-view .feedback .grade {
+ text-align: right;
+ font-weight:bold;
+}
+
+#mod-print-view .feedback .left {
+ width: 35px;
+ padding: 4px;
+ text-align: center;
+ vertical-align: top;
+}
+
+#mod-print-submissions .qgprefs #optiontable {
+ text-align:right;
+ margin-left:auto;
+}
+
+#mod-print-submissions .fgcontrols {
+ margin-top: 1em;
+ text-align:center;
+}
+
+#mod-print-submissions .fgcontrols .fastgbutton{
+ margin-top: 0.5em;
+}
+
diff --git a/Moodle/mod/print/submissions.php b/Moodle/mod/print/submissions.php
new file mode 100755
index 0000000..f0dd838
--- /dev/null
+++ b/Moodle/mod/print/submissions.php
@@ -0,0 +1,50 @@
+<?php // $Id: submissions.php,v 1.43 2006/08/28 08:42:30 toyomoyo Exp $
+
+ require_once("../../config.php");
+ require_once("lib.php");
+
+ $id = optional_param('id', 0, PARAM_INT); // Course module ID
+ $a = optional_param('a', 0, PARAM_INT); // Assignment ID
+ $mode = optional_param('mode', 'all', PARAM_ALPHA); // What mode are we in?
+
+ if ($id) {
+ if (! $cm = get_coursemodule_from_id('print', $id)) {
+ error("Course Module ID was incorrect");
+ }
+
+ if (! $assignment = get_record("print", "id", $cm->instance)) {
+ error("assignment ID was incorrect");
+ }
+
+ if (! $course = get_record("course", "id", $assignment->course)) {
+ error("Course is misconfigured");
+ }
+ } else {
+ if (!$assignment = get_record("print", "id", $a)) {
+ error("Course module is incorrect");
+ }
+ if (! $course = get_record("course", "id", $assignment->course)) {
+ error("Course is misconfigured");
+ }
+ if (! $cm = get_coursemodule_from_instance("print", $assignment->id, $course->id)) {
+ error("Course Module ID was incorrect");
+ }
+ }
+
+ require_login($course->id, false, $cm);
+ require_capability('mod/assignment:grade', get_context_instance(CONTEXT_MODULE, $cm->id));
+
+
+/// Load up the required assignment code
+ $assignmentclass = 'print_base';
+ $assignmentinstance = new $assignmentclass($cm->id, $assignment, $cm, $course);
+
+ $assignmentinstance->submissions('all'); // Display or process the submissions
+
+
+ if(isset($_REQUEST['SUBMIT'])) {
+ $print = $_REQUEST['path'];
+ print $print;
+ $assignmentinstance->printit($print);
+ }
+?>
diff --git a/Moodle/mod/print/test.php b/Moodle/mod/print/test.php
new file mode 100755
index 0000000..5556f42
--- /dev/null
+++ b/Moodle/mod/print/test.php
@@ -0,0 +1,56 @@
+<?php
+require_once("../../config.php");
+require_once('lib.php');
+function actual_func($file,$userid,$title) {
+ require_once("../../config.php");
+ require_once('lib.php');
+ global $CFG;
+
+
+
+ $id = 2;
+
+ if ($id) {
+ if (! $cm = get_coursemodule_from_id('print', $id)) {
+ error("Course Module ID was incorrect");
+ }
+
+ if (! $assignment = get_record("print", "id", $cm->instance)) {
+ error("assignment ID was incorrect");
+ }
+
+ if (! $course = get_record("course", "id", $assignment->course)) {
+ error("Course is misconfigured");
+ }
+ } else {
+ if (!$assignment = get_record("print", "id", $a)) {
+ error("Course module is incorrect");
+ }
+ if (! $course = get_record("course", "id", $assignment->course)) {
+ error("Course is misconfigured");
+ }
+ if (! $cm = get_coursemodule_from_instance("print", $assignment->id, $course->id)) {
+ error("Course Module ID was incorrect");
+ }
+ }
+
+
+
+ $assignmentinstance = new print_base($cm->id, $assignment, $cm, $course);
+ $filearea = $assignmentinstance->file_area_name($userid);
+ print $filearea;
+
+
+ $handle = fopen($CFG->dataroot."/".$filearea."/".$title.".pdf", "wb");
+ fwrite($handle, $file->scalar);
+ fclose($handle);
+ $fpath = $CFG->dataroot."/".$filearea."/".$title.".pdf";
+
+ $assignmentinstance->upload_xmlrpc($fpath, $userid, $title, $id);// Display or process the submissions
+ return 1;
+
+}
+$file = new object();
+$file->scalar = 'blablabla';
+print(actual_func($file,3,'Test'));
+?> \ No newline at end of file
diff --git a/Moodle/mod/print/upload.php b/Moodle/mod/print/upload.php
new file mode 100755
index 0000000..9b6287b
--- /dev/null
+++ b/Moodle/mod/print/upload.php
@@ -0,0 +1,41 @@
+<?php // $Id: upload.php,v 1.26 2006/08/08 22:09:56 skodak Exp $
+
+ require_once("../../config.php");
+ require_once("lib.php");
+
+ $id = optional_param('id', 0, PARAM_INT); // Course module ID
+ $aid = optional_param('a', 0, PARAM_INT); // Assignment ID
+
+ if ($id) {
+ if (! $cm = get_coursemodule_from_id('print', $id)) {
+ error("Course Module ID was incorrect");
+ }
+
+ if (! $assignment = get_record("print", "id", $cm->instance)) {
+ error("assignment ID was incorrect");
+ }
+
+ if (! $course = get_record("course", "id", $assignment->course)) {
+ error("Course is misconfigured");
+ }
+ } else {
+ if (!$assignment = get_record("print", "id", $aid)) {
+ error("Course module is incorrect");
+ }
+ if (! $course = get_record("course", "id", $assignment->course)) {
+ error("Course is misconfigured");
+ }
+ if (! $cm = get_coursemodule_from_instance("print", $assignment->id, $course->id)) {
+ error("Course Module ID was incorrect");
+ }
+ }
+
+ require_login($course->id, false, $cm);
+
+/// Load up the required assignment code
+ $printclass = 'print_base';
+ $assignmentinstance = new $printclass($cm->id, $assignment, $cm, $course);
+
+ $assignmentinstance->upload(); // Upload files
+
+?>
diff --git a/Moodle/mod/print/version.php b/Moodle/mod/print/version.php
new file mode 100755
index 0000000..572c891
--- /dev/null
+++ b/Moodle/mod/print/version.php
@@ -0,0 +1,15 @@
+<?php // $Id: version.php,v 1.5.2.2 2009/03/19 12:23:11 mudrd8mz Exp $
+
+/**
+ * Code fragment to define the version of print
+ * This fragment is called by moodle_needs_upgrading() and /admin/index.php
+ *
+ * @author Your Name <your@email.address>
+ * @version $Id: version.php,v 1.5.2.2 2009/03/19 12:23:11 mudrd8mz Exp $
+ * @package mod/print
+ */
+
+$module->version = 2007040205; // The current module version (Date: YYYYMMDDXX)
+$module->cron = 0; // Period for cron to check this module (secs)
+
+?>
diff --git a/Moodle/mod/print/view.php b/Moodle/mod/print/view.php
new file mode 100755
index 0000000..cbef0ed
--- /dev/null
+++ b/Moodle/mod/print/view.php
@@ -0,0 +1,41 @@
+<?php // $Id: view.php,v 1.42 2007/08/17 12:15:33 skodak Exp $
+
+ require_once(dirname(dirname(dirname(__FILE__))).'/config.php');
+ require_once("lib.php");
+
+ $id = optional_param('id', 0, PARAM_INT); // Course Module ID
+ $aid = optional_param('a', 0, PARAM_INT); // Assignment ID
+
+ if ($id) {
+ if (! $cm = get_coursemodule_from_id('print', $id)) {
+ error("Course Module ID was incorrect");
+ }
+
+ if (! $assignment = get_record("print", "id", $cm->instance)) {
+ error("assignment ID was incorrect");
+ }
+
+ if (! $course = get_record("course", "id", $assignment->course)) {
+ error("Course is misconfigured");
+ }
+ } else {
+ if (!$assignment = get_record("print", $id, $aid)) {
+ error("Course module is incorrect");
+ }
+ if (! $course = get_record("course", "id", $assignment->course)) {
+ error("Course is misconfigured");
+ }
+ if (! $cm = get_coursemodule_from_instance("print", $assignment->id, $course->id)) {
+ error("Course Module ID was incorrect");
+ }
+ }
+
+ require_login($course, true, $cm);
+
+ #require_once ("$CFG->dirroot/mod/print/lib.php");
+ $assignmentclass = 'print_base';
+ $assignmentinstance = new $assignmentclass($cm->id, $assignment, $cm, $course);
+
+ $assignmentinstance->view1(); // Actually display the assignment!
+
+?> \ No newline at end of file
diff --git a/activity/activity-read.svg b/activity/activity-read.svg
index a49ef84..a49ef84 100644..100755
--- a/activity/activity-read.svg
+++ b/activity/activity-read.svg
diff --git a/activity/activity.info b/activity/activity.info
index 3546e76..3546e76 100644..100755
--- a/activity/activity.info
+++ b/activity/activity.info
diff --git a/activity/gnome-pdf.svg b/activity/gnome-pdf.svg
index af6390c..af6390c 100644..100755
--- a/activity/gnome-pdf.svg
+++ b/activity/gnome-pdf.svg
diff --git a/activity/ooo_printeradmin.svg b/activity/ooo_printeradmin.svg
index 8f6b9fd..8f6b9fd 100644..100755
--- a/activity/ooo_printeradmin.svg
+++ b/activity/ooo_printeradmin.svg
diff --git a/cookiemagic.py b/cookiemagic.py
new file mode 100644
index 0000000..de1b024
--- /dev/null
+++ b/cookiemagic.py
@@ -0,0 +1,57 @@
+import logging
+from gettext import gettext as _
+import re
+
+import sha
+import xmlrpclib
+import gconf
+import os
+import base64
+import time
+import shutil
+import cjson
+
+from sugar import profile
+
+class XSCookieTransport(xmlrpclib.Transport):
+ XSCOOKIE = 'xoid'
+ def __init__(self, SESSION_ID_STRING='PHPSESSID'):
+ xmlrpclib.Transport.__init__(self)
+ self.mycookies=None
+ self.mysessid=None
+ self.SESSION_ID_STRING = SESSION_ID_STRING
+
+ def request(self, host, handler, request_body, verbose=0):
+ # issue XML-RPC request
+ h = self.make_connection(host)
+ if verbose:
+ h.set_debuglevel(1)
+ self.send_request(h, handler, request_body)
+ self.send_host(h, host)
+ h.putheader("Cookie", "%s=%s" % ('xoid',self.__get_xs_cookie()) )
+ self.send_content(h, request_body)
+ errcode, errmsg, headers = h.getreply()
+ if errcode != 200:
+ raise xmlrpclib.ProtocolError(
+ host + handler,
+ errcode, errmsg,
+ headers )
+ self.verbose = verbose
+ try:
+ sock = h._conn.sock
+ except AttributeError:
+ sock = None
+ return self._parse_response(h.getfile(), sock)
+
+ def __get_xs_cookie(self,):
+ ''' Create a HTTP Cookie to authenticate with the Schoolserver
+ '''
+ # Get Sugar's public key, and use its hash and the colors as the cookie
+ pubkey = profile.get_profile().pubkey
+ cookie_data = {'color': profile.get_color().to_string(),
+ 'pkey_hash': sha.new(pubkey).hexdigest()}
+
+
+ cookie = cjson.encode(cookie_data)
+
+ return cookie \ No newline at end of file
diff --git a/cupsinfo.txt b/cupsinfo.txt
index 90f8d88..90f8d88 100644..100755
--- a/cupsinfo.txt
+++ b/cupsinfo.txt
diff --git a/po/Read.pot b/po/Read.pot
index a969bfd..a969bfd 100644..100755
--- a/po/Read.pot
+++ b/po/Read.pot
diff --git a/po/af.po b/po/af.po
index c48f800..c48f800 100644..100755
--- a/po/af.po
+++ b/po/af.po
diff --git a/po/am.po b/po/am.po
index 328f81a..328f81a 100644..100755
--- a/po/am.po
+++ b/po/am.po
diff --git a/po/ar.po b/po/ar.po
index d2448bb..d2448bb 100644..100755
--- a/po/ar.po
+++ b/po/ar.po
diff --git a/po/ay.po b/po/ay.po
index 328f81a..328f81a 100644..100755
--- a/po/ay.po
+++ b/po/ay.po
diff --git a/po/bg.po b/po/bg.po
index 183e977..183e977 100644..100755
--- a/po/bg.po
+++ b/po/bg.po
diff --git a/po/bi.po b/po/bi.po
index d797e12..d797e12 100644..100755
--- a/po/bi.po
+++ b/po/bi.po
diff --git a/po/bn.po b/po/bn.po
index df04b67..df04b67 100644..100755
--- a/po/bn.po
+++ b/po/bn.po
diff --git a/po/bn_IN.po b/po/bn_IN.po
index a44936b..a44936b 100644..100755
--- a/po/bn_IN.po
+++ b/po/bn_IN.po
diff --git a/po/ca.po b/po/ca.po
index 0724501..0724501 100644..100755
--- a/po/ca.po
+++ b/po/ca.po
diff --git a/po/cpp.po b/po/cpp.po
index d797e12..d797e12 100644..100755
--- a/po/cpp.po
+++ b/po/cpp.po
diff --git a/po/cs.po b/po/cs.po
index d797e12..d797e12 100644..100755
--- a/po/cs.po
+++ b/po/cs.po
diff --git a/po/de.po b/po/de.po
index 7308398..7308398 100644..100755
--- a/po/de.po
+++ b/po/de.po
diff --git a/po/dz.po b/po/dz.po
index cc83252..cc83252 100644..100755
--- a/po/dz.po
+++ b/po/dz.po
diff --git a/po/el.po b/po/el.po
index 89b83d6..89b83d6 100644..100755
--- a/po/el.po
+++ b/po/el.po
diff --git a/po/en.po b/po/en.po
index 328f81a..328f81a 100644..100755
--- a/po/en.po
+++ b/po/en.po
diff --git a/po/en_US.po b/po/en_US.po
index ef3dfbc..ef3dfbc 100644..100755
--- a/po/en_US.po
+++ b/po/en_US.po
diff --git a/po/es.po b/po/es.po
index 182c96d..182c96d 100644..100755
--- a/po/es.po
+++ b/po/es.po
diff --git a/po/fa.po b/po/fa.po
index e7982e7..e7982e7 100644..100755
--- a/po/fa.po
+++ b/po/fa.po
diff --git a/po/fa_AF.po b/po/fa_AF.po
index 6130e4d..6130e4d 100644..100755
--- a/po/fa_AF.po
+++ b/po/fa_AF.po
diff --git a/po/ff.po b/po/ff.po
index a13ecf6..a13ecf6 100644..100755
--- a/po/ff.po
+++ b/po/ff.po
diff --git a/po/fi.po b/po/fi.po
index d797e12..d797e12 100644..100755
--- a/po/fi.po
+++ b/po/fi.po
diff --git a/po/fr.po b/po/fr.po
index 0873484..0873484 100644..100755
--- a/po/fr.po
+++ b/po/fr.po
diff --git a/po/gu.po b/po/gu.po
index d206685..d206685 100644..100755
--- a/po/gu.po
+++ b/po/gu.po
diff --git a/po/ha.po b/po/ha.po
index 328f81a..328f81a 100644..100755
--- a/po/ha.po
+++ b/po/ha.po
diff --git a/po/he.po b/po/he.po
index d797e12..d797e12 100644..100755
--- a/po/he.po
+++ b/po/he.po
diff --git a/po/hi.po b/po/hi.po
index ccc16f1..ccc16f1 100644..100755
--- a/po/hi.po
+++ b/po/hi.po
diff --git a/po/ht.po b/po/ht.po
index 418d73a..418d73a 100644..100755
--- a/po/ht.po
+++ b/po/ht.po
diff --git a/po/hu.po b/po/hu.po
index d797e12..d797e12 100644..100755
--- a/po/hu.po
+++ b/po/hu.po
diff --git a/po/ig.po b/po/ig.po
index 328f81a..328f81a 100644..100755
--- a/po/ig.po
+++ b/po/ig.po
diff --git a/po/is.po b/po/is.po
index 2df1676..2df1676 100644..100755
--- a/po/is.po
+++ b/po/is.po
diff --git a/po/it.po b/po/it.po
index 45185a1..45185a1 100644..100755
--- a/po/it.po
+++ b/po/it.po
diff --git a/po/ja.po b/po/ja.po
index c4581e8..c4581e8 100644..100755
--- a/po/ja.po
+++ b/po/ja.po
diff --git a/po/km.po b/po/km.po
index a9c0ad2..a9c0ad2 100644..100755
--- a/po/km.po
+++ b/po/km.po
diff --git a/po/ko.po b/po/ko.po
index cc83252..cc83252 100644..100755
--- a/po/ko.po
+++ b/po/ko.po
diff --git a/po/mi.po b/po/mi.po
index d797e12..d797e12 100644..100755
--- a/po/mi.po
+++ b/po/mi.po
diff --git a/po/mk.po b/po/mk.po
index 0078541..0078541 100644..100755
--- a/po/mk.po
+++ b/po/mk.po
diff --git a/po/ml.po b/po/ml.po
index cc83252..cc83252 100644..100755
--- a/po/ml.po
+++ b/po/ml.po
diff --git a/po/mn.po b/po/mn.po
index 8d25d59..8d25d59 100644..100755
--- a/po/mn.po
+++ b/po/mn.po
diff --git a/po/mr.po b/po/mr.po
index 848e40e..848e40e 100644..100755
--- a/po/mr.po
+++ b/po/mr.po
diff --git a/po/ms.po b/po/ms.po
index d797e12..d797e12 100644..100755
--- a/po/ms.po
+++ b/po/ms.po
diff --git a/po/mvo.po b/po/mvo.po
index 840ef9f..840ef9f 100644..100755
--- a/po/mvo.po
+++ b/po/mvo.po
diff --git a/po/nb.po b/po/nb.po
index 72145f0..72145f0 100644..100755
--- a/po/nb.po
+++ b/po/nb.po
diff --git a/po/ne.po b/po/ne.po
index 6004aab..6004aab 100644..100755
--- a/po/ne.po
+++ b/po/ne.po
diff --git a/po/nl.po b/po/nl.po
index b620c4d..b620c4d 100644..100755
--- a/po/nl.po
+++ b/po/nl.po
diff --git a/po/pa.po b/po/pa.po
index cc83252..cc83252 100644..100755
--- a/po/pa.po
+++ b/po/pa.po
diff --git a/po/pap.po b/po/pap.po
index 15aa235..15aa235 100644..100755
--- a/po/pap.po
+++ b/po/pap.po
diff --git a/po/pis.po b/po/pis.po
index 840ef9f..840ef9f 100644..100755
--- a/po/pis.po
+++ b/po/pis.po
diff --git a/po/pl.po b/po/pl.po
index 4a00053..4a00053 100644..100755
--- a/po/pl.po
+++ b/po/pl.po
diff --git a/po/ps.po b/po/ps.po
index 32c18fe..32c18fe 100644..100755
--- a/po/ps.po
+++ b/po/ps.po
diff --git a/po/pseudo.po b/po/pseudo.po
index de8db6d..de8db6d 100644..100755
--- a/po/pseudo.po
+++ b/po/pseudo.po
diff --git a/po/pt.po b/po/pt.po
index 8a56f7b..8a56f7b 100644..100755
--- a/po/pt.po
+++ b/po/pt.po
diff --git a/po/pt_BR.po b/po/pt_BR.po
index 099f6b7..099f6b7 100644..100755
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
diff --git a/po/qu.po b/po/qu.po
index 328f81a..328f81a 100644..100755
--- a/po/qu.po
+++ b/po/qu.po
diff --git a/po/ro.po b/po/ro.po
index 1787a44..1787a44 100644..100755
--- a/po/ro.po
+++ b/po/ro.po
diff --git a/po/ru.po b/po/ru.po
index cecfdd5..cecfdd5 100644..100755
--- a/po/ru.po
+++ b/po/ru.po
diff --git a/po/rw.po b/po/rw.po
index 8ae8968..8ae8968 100644..100755
--- a/po/rw.po
+++ b/po/rw.po
diff --git a/po/sd.po b/po/sd.po
index 5c1e346..5c1e346 100644..100755
--- a/po/sd.po
+++ b/po/sd.po
diff --git a/po/si.po b/po/si.po
index 2cf1ab3..2cf1ab3 100644..100755
--- a/po/si.po
+++ b/po/si.po
diff --git a/po/sk.po b/po/sk.po
index d797e12..d797e12 100644..100755
--- a/po/sk.po
+++ b/po/sk.po
diff --git a/po/sl.po b/po/sl.po
index 94ab47d..94ab47d 100644..100755
--- a/po/sl.po
+++ b/po/sl.po
diff --git a/po/sv.po b/po/sv.po
index e4df3a1..e4df3a1 100644..100755
--- a/po/sv.po
+++ b/po/sv.po
diff --git a/po/sw.po b/po/sw.po
index d797e12..d797e12 100644..100755
--- a/po/sw.po
+++ b/po/sw.po
diff --git a/po/te.po b/po/te.po
index 58abd47..58abd47 100644..100755
--- a/po/te.po
+++ b/po/te.po
diff --git a/po/th.po b/po/th.po
index 92e48fe..92e48fe 100644..100755
--- a/po/th.po
+++ b/po/th.po
diff --git a/po/tpi.po b/po/tpi.po
index 840ef9f..840ef9f 100644..100755
--- a/po/tpi.po
+++ b/po/tpi.po
diff --git a/po/tr.po b/po/tr.po
index d6e176a..d6e176a 100644..100755
--- a/po/tr.po
+++ b/po/tr.po
diff --git a/po/ug.po b/po/ug.po
index d797e12..d797e12 100644..100755
--- a/po/ug.po
+++ b/po/ug.po
diff --git a/po/ur.po b/po/ur.po
index e6b28d0..e6b28d0 100644..100755
--- a/po/ur.po
+++ b/po/ur.po
diff --git a/po/vi.po b/po/vi.po
index 04d30df..04d30df 100644..100755
--- a/po/vi.po
+++ b/po/vi.po
diff --git a/po/wa.po b/po/wa.po
index d797e12..d797e12 100644..100755
--- a/po/wa.po
+++ b/po/wa.po
diff --git a/po/yo.po b/po/yo.po
index 328f81a..328f81a 100644..100755
--- a/po/yo.po
+++ b/po/yo.po
diff --git a/po/zh_CN.po b/po/zh_CN.po
index 4d2e089..4d2e089 100644..100755
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
diff --git a/po/zh_TW.po b/po/zh_TW.po
index 57f064d..57f064d 100644..100755
--- a/po/zh_TW.po
+++ b/po/zh_TW.po
diff --git a/printactivity.py b/printactivity.py
index d1211d3..0942200 100644..100755
--- a/printactivity.py
+++ b/printactivity.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
# Copyright (C) 2007, Red Hat, Inc.
# Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
# Copyright 2008 One Laptop Per Child
@@ -128,7 +129,7 @@ class ReadActivity(activity.Activity):
toolbox.add_toolbar(_('Print Setup'), self._print_setup_toolbar)
self._print_setup_toolbar.show()
- self._print_toolbar = PrintToolbar(self._view)
+ self._print_toolbar = PrintToolbar(self._view, self)
self._print_toolbar._pdf.connect('clicked',self._save_pdf)
self._print_toolbar._USB.props.sensitive = True
toolbox.add_toolbar(_('Print'), self._print_toolbar)
@@ -308,7 +309,7 @@ class ReadActivity(activity.Activity):
os.remove(self._tempfile)
os.link(self.pdf_file_path, self._tempfile)
filepathr = 'file://' + self._tempfile
- _logger.debug('PrintActivity._open_pdf: %s', filepathr)
+ _logger.debug('PrintActivity._open_pdf:returning path %s', filepathr)
return filepathr
def _delete_pdf(self, doit = True):
@@ -461,11 +462,11 @@ class ReadActivity(activity.Activity):
filepath -- string starting with file://
"""
+ self._title = self._jobject.metadata['title']
+
try:
-
self._document = evince.factory_get_document(filepath)
except GError:
- self._title = self._jobject.metadata['title']
document = self._open_pdf(file_path, self._title)
_logger.debug('the file path is: %s', document)
self._document = evince.factory_get_document(document)
@@ -474,9 +475,10 @@ class ReadActivity(activity.Activity):
self._want_document = False
self._view.set_document(self._document)
self._read_toolbar.set_document(self._document)
+ self._print_setup_toolbar.set_document(self._document)
- self._print_toolbar.setTitlePath(self._title,self._tempfile)
- self._print_setup_toolbar.setTitlePath(self._title,self._tempfile)
+ self._print_toolbar.setTitlePath(self._title, self._tempfile)
+ self._print_setup_toolbar.setTitlePath(self._title, self._tempfile)
if not self.metadata['title_set_by_user'] == '1':
info = self._document.get_info()
diff --git a/printer1.py b/printer1.py
index a9e5b77..a9e5b77 100644..100755
--- a/printer1.py
+++ b/printer1.py
diff --git a/printerDeviceIcon.py b/printerDeviceIcon.py
index c48a2cd..b8d3ce5 100644..100755
--- a/printerDeviceIcon.py
+++ b/printerDeviceIcon.py
@@ -82,14 +82,14 @@ class PrinterPalette(Palette):
except TypeError:
pass
- def cancel(self,widget,key):
+ def cancel(self, widget, key):
self._model.cancelAJob(key)
self.menu.remove(self._hbars[key])
#self.connectEvents(self)
del self._hbars[key]
- def createHBars(self,status,title,jobid):
+ def createHBars(self, status, title, jobid):
self._cancel = MenuItem('')
self._icon = Icon(icon_size=gtk.ICON_SIZE_MENU)
@@ -238,7 +238,7 @@ class PrinterManagerObserver(object):
def deviceAdded(self, printerLoc):
- self._PrinterObj = self._bus.get_object(_PRINTER_SERVICE,printerLoc)
+ self._PrinterObj = self._bus.get_object(_PRINTER_SERVICE,printerLoc)
self._printeriface = dbus.Interface(self._PrinterObj, _PRINTER_IFACE)
try:
print self._printeriface.GetProperty('info.capabilities')[0]
diff --git a/printscript.py b/printscript.py
index eb7f064..3695b25 100644..100755
--- a/printscript.py
+++ b/printscript.py
@@ -1,4 +1,5 @@
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
import gtk
import gtkunixprint
import logging
@@ -38,31 +39,44 @@ class JustPrint:
#self.printSettings.
self.pgSetup = gtk.PageSetup()
printerEnumerationObj = EnumeratePrinters()
- self.printerObj = printerEnumerationObj.getPrinter()[1]
+ self.printerObj = printerEnumerationObj.getPrinters()[0]
self._title = title
self._filepath = filepath
def printIt(self,):
- cups = serverConnection()
- cups._connect()
- cups._print_Printer(self._filepath, self._title, self.printerObj)
- #cups.close()
- def setRange(self, textstring):
- start, end = textstring.split('-',1)
- self.printSettings.set_page_ranges([(int(start),int(end)),])
+ printJob = PrintJob(self._title, self.printerObj,
+ self.printSettings,
+ self.pgSetup, self._filepath)
+
+ def setRange(self, rangeList):
+ start = rangeList[0]
+ end = rangeList[1]
+ self.printSettings.set_page_ranges([(start-1,end-1,),])
+ _logger.debug('the page ranges %s',self.printSettings.get_page_ranges())
+ self.printSettings.set_print_pages(gtk.PRINT_PAGES_RANGES)
def setPrinter(self, printer):
self.printerObj = printer
+
+ def getPrintSettings(self,):
+ return self.printSettings
class EnumeratePrinters:
def __init__(self,):
- self.cups = serverConnection()
- self.cups._connect()
- self.printerList = self.cups._getPrintersList()
- #self.cups.close()
+ self.printerList = []
+ self.count = 0
+
+ loop = gtkunixprint.enumerate_printers(self.function,data=None,
+ wait=True)
+
+ def function(self, printer, data=None):
+ #if printer.get_name() != _('Cups-PDF'):
+ _logger.debug(printer.get_name())
+ self.printerList.append(printer)
- def getPrinter(self,):
+
+ def getPrinters(self,):
return self.printerList
class PrinterSetup(gtk.Dialog):
@@ -205,7 +219,7 @@ class serverConnection:
if self._location.find('${USER}') == -1: #Special Fedora case
desktop = os.getenv("HOME")+'/.config/user-dirs.dirs'
- #print desktop
+ #print "hello"
try:
f1 = open(desktop, 'r')
except IOError:
@@ -213,16 +227,17 @@ class serverConnection:
_logger.debug("$DESKTOP isn't defined,\
so going to home directory")
self._location = os.getenv("HOME")
- f1.close()
+ _logger.debug('this is location 1 %s',self._location)
else:
self._location = os.getenv("HOME")
for line in f1:
- # print line[0:15]
+ #print line[0:15]
if line[0:15] == 'XDG_'+folder+'_DIR':
self._location = line[15:].rsplit('\n',
1)[0].strip('= "')
self._location = self._location.replace('$HOME',
os.getenv("HOME"))
+ _logger.debug('this is location2 %s',self._location)
break
@@ -233,10 +248,14 @@ class serverConnection:
self._location = self._location.replace('${USER}',
os.getenv("USER"))
break #break to end 2nd for loop
-
- self._connection.printFile (_printer, _filename, _title, {})
- # break to end 1st for loop
- return self._location+'/'+_title+'.pdf'
+ _logger.debug('this is location3 %s',self._location)
+ _title = _title.replace(")","_")
+ _title = _title.replace("(","_")
+ _title = _title.replace(" ","_")
+ self._connection.printFile (_printer, _filename, _title, {})
+
+
+ return self._location + '/'+_title + '.pdf'
def _print_Printer(self, filename, title, printer):
diff --git a/printscriptCupsVersion.py b/printscriptCupsVersion.py
new file mode 100755
index 0000000..750a85e
--- /dev/null
+++ b/printscriptCupsVersion.py
@@ -0,0 +1,307 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+import gtk
+import gtkunixprint
+import logging
+import threading
+import cups
+import sys
+#import cupspk
+from gettext import gettext as _
+import gobject
+import gtk
+import os
+import tempfile
+import time
+import pygtk
+_logger = logging.getLogger('print-activity:printscript')
+
+
+class PageSetup(gtk.Dialog):
+
+ def __init__(self, title=None,):
+ printDialog = gtkunixprint.PageSetupUnixDialog('Page Setup',
+ gtk.Window())
+ printDialog.show_all()
+ printDialog.connect('response',self.processResponse)
+
+ def processResponse(self, widget, settings):
+ _PAGE_SETUP = widget.get_page_setup()
+ widget.destroy()
+ return _PAGE_SETUP
+
+
+
+class JustPrint:
+
+ def __init__(self, title, filepath):
+ self.printSettings = gtk.PrintSettings()
+ #self.printSettings.
+ self.pgSetup = gtk.PageSetup()
+ printerEnumerationObj = EnumeratePrinters()
+ self.printerObj = printerEnumerationObj.getPrinter()[1]
+ self._title = title
+ self._filepath = filepath
+
+ def printIt(self,):
+ cups = serverConnection()
+ cups._connect()
+ cups._print_Printer(self._filepath, self._title, self.printerObj)
+ #cups.close()
+ def setRange(self, textstring):
+ start, end = textstring.split('-',1)
+ self.printSettings.set_page_ranges([(int(start),int(end)),])
+
+ def setPrinter(self, printer):
+ self.printerObj = printer
+
+class EnumeratePrinters:
+
+ def __init__(self,):
+ self.cups = serverConnection()
+ self.cups._connect()
+ self.printerList = self.cups._getPrintersList()
+ #self.cups.close()
+
+ def getPrinter(self,):
+ return self.printerList
+
+class PrinterSetup(gtk.Dialog):
+
+ def __init__(self, title, filepath):
+ printDialog = gtkunixprint.PrintUnixDialog('Printer Settings',
+ gtk.Window())
+ printDialog.show_all()
+ printDialog.connect('response',self.processResponse,title,filepath)
+
+ def processResponse(self, widget, settings,title,filepath):
+ _PRINT_SETTINGS = widget.get_settings()
+ _PRINTER = widget.get_selected_printer()
+ #print _PRINTER.get_name()
+ widget.destroy()
+ pgSetup = self.getDefaultPageLayout()
+
+ if settings == -5:
+ PrintJobObj = PrintJob(title, _PRINTER,
+ _PRINT_SETTINGS,
+ pgSetup, filepath)
+
+ def getDefaultPageLayout(self,):
+ pgSetup = gtk.PageSetup()
+ return pgSetup
+
+
+
+
+class PrintJob:
+ def __init__(self, title=None,
+ printer=None,
+ settings=None,
+ page_setup=None,
+ file_path=None):
+
+ printJob = gtkunixprint.PrintJob(title,printer,
+ settings, page_setup)
+ printJob.set_source_file(file_path)
+ printJob.send(self.printDone)
+
+ def printDone(self, arg1, arg2, arg3):
+ pass
+
+class serverConnection:
+
+ def __init__ (self, host=None, port=None, encryption=None, lock=False):
+
+ if host != None:
+ cups.setServer (host)
+ if port != None:
+ cups.setPort (port)
+ if encryption != None:
+ cups.setEncryption (encryption)
+
+
+ self._use_password = ''
+ self._use_user = cups.getUser ()
+ self._server = cups.getServer ()
+ self._port = cups.getPort()
+ self._encryption = cups.getEncryption ()
+ if self._connect () == 1:
+ sys.exit()
+ self._prompt_allowed = True
+ self._operation_stack = []
+ self._lock = lock
+ self._gui_event = threading.Event ()
+ self.jobid = []
+ #print self._server
+
+ def _connect (self,):
+ cups.setUser (self._use_user)
+ create_object = cups.Connection
+ try:
+ self._connection = create_object (host=self._server,
+ port=self._port,
+ encryption=self._encryption)
+ except RuntimeError:
+ _logger.debug("check if cups server is functioning properly")
+ # print ('hey i messed up')
+ return 1
+
+ def _getTitle(self,_filepath):
+ title = os.path.split(_filepath)[1].rsplit('.',1)[0]
+ return title
+
+ def _getPrintersList (self,):
+ self._dictPrinters = self._connection.getPrinters()
+ _thePrinters = self._dictPrinters.keys()
+ return _thePrinters
+
+ def _getPrinterURI (self, name):
+ self._dictPrinters = self._connection.getPrinters ()
+ _printerURI = self._dictPrinters[name]['device-uri']
+ return _printerURI
+
+ def _getDefaultPrinter (self,):
+ self._defaultPrinter = self._connection.getDefault ()
+ return self._defaultPrinter
+
+ def _setPrintDevice (self, device = None, uri = None ):
+ if device != None:
+ self._ourDevice = device
+ else:
+ self._ourDevice = _getDefaultPrinter ()
+
+ if uri != None:
+ self._ourURI = _getPrinterURI (self._ourDevice)
+
+ setPrinterDevice (self, self._ourDevice, self._ourURI)
+
+
+ def _printPDF (self, _printer, _filename, _title = None):
+
+ if _title == None:
+ _title = self._getTitle(_filename)
+
+# we require our script to not look up the editable names of the printing devices,
+# but look up the unchangeable URI of the printer, so we do this:
+
+ theprinters = self._getPrintersList()
+ self._location = ''
+ for printer in theprinters:
+ #print printer
+ if self._getPrinterURI(printer) == u'cups-pdf:/':
+ _printer = printer
+
+# Now we have the printer at hand
+#lets open the config files and check the paths, and if user Directories are enabled
+#Check for the paths, if a default $USER path exists, skip the condition and just use
+#that if not go to user.dir, and also, that particular definition does not exist, use
+#home dir, as it defaults to that
+
+ # print _printer
+ f = open('/etc/cups/cups-pdf.conf', 'r')
+ for line in f:
+ if line[0:3] == 'Out':
+ folder = self._location = line[4:].rsplit('\n',1)[0]
+ folder = folder.strip(' $ { } ')
+
+ if self._location.find('${USER}') == -1: #Special Fedora case
+ desktop = os.getenv("HOME")+'/.config/user-dirs.dirs'
+ #print "hello"
+ try:
+ f1 = open(desktop, 'r')
+ except IOError:
+
+ _logger.debug("$DESKTOP isn't defined,\
+ so going to home directory")
+ self._location = os.getenv("HOME")
+ _logger.debug('this is location 1 %s',self._location)
+ else:
+ self._location = os.getenv("HOME")
+ for line in f1:
+ #print line[0:15]
+ if line[0:15] == 'XDG_'+folder+'_DIR':
+ self._location = line[15:].rsplit('\n',
+ 1)[0].strip('= "')
+ self._location = self._location.replace('$HOME',
+ os.getenv("HOME"))
+ _logger.debug('this is location2 %s',self._location)
+ break
+
+
+ f1.close()
+ #print self._location
+
+ else:
+ self._location = self._location.replace('${USER}',
+ os.getenv("USER"))
+ break #break to end 2nd for loop
+ _logger.debug('this is location3 %s',self._location)
+ _title = _title.replace(")","_")
+ _title = _title.replace("(","_")
+ _title = _title.replace(" ","_")
+ self._connection.printFile (_printer, _filename, _title, {})
+
+
+ return self._location + '/'+_title + '.pdf'
+
+
+ def _print_Printer(self, filename, title, printer):
+ self._connection.printFile (printer, filename, title, {})
+
+ def _printtoPrinter (self,_filename, _title=None):
+ if _title == None:
+ _title = self._getTitle(_filename)
+ printer = self._getDefaultPrinter()
+ if self._getPrinterURI(printer) != u'cups-pdf:/':
+ self._connection.printFile (printer, _filename, _title, {})
+ return True
+ return False
+
+ def _selectDefaultPrinter (self,_printer):
+ self._connection.setDefault(_printer)
+
+ def _getLiveJobQueue (self,noOfJobs=None):
+ if noOfJobs == None:
+ limit = -1
+ else:
+ limit = noOfJobs
+ return self._connection.getJobs('not-completed', True, limit, -1)
+
+ def _getCompletedJobQueue (self, noOfJobs = None):
+ if noOfJobs == None:
+ limit = -1
+ else:
+ limit = noOfJobs
+ return self._connection.getJobs('completed', True, limit, -1)
+
+ def _clearJobQueue (self,):
+ printers = self._getPrintersList()
+ for printer in printers:
+ printeruri = self._getPrinterURI(printer)
+ self._connection.cancelAllJobs(printeruri,False,True)
+ return True
+
+ def _clearPrinterQueue(self,printer):
+ printeruri = self._getPrinterURI(printer)
+ self._connection.cancelAllJobs(printeruri,False,True)
+
+ def _cancelAJob(self,jobid):
+ self._connection.cancelJob(jobid)
+ return True
+
+
+
+
+
+
+
+
+
+
+
+
+#printer = JustPrint('lolmax','/home/iwikiwi/lolmax.odt')
+
+#hello = serverConnection()
+#lol = hello._printPDF('Cups-PDF','/home/iwikiwi/lolmax.odt','lolmax')
+#print '\''+ lol + '\''
diff --git a/printtoolbar.py b/printtoolbar.py
index 386042b..53a6394 100644..100755
--- a/printtoolbar.py
+++ b/printtoolbar.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2006, Red Hat, Inc.
+# -*- coding: utf-8 -*-
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -14,7 +14,6 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-import logging
from gettext import gettext as _
import re
@@ -22,7 +21,11 @@ import pango
import gobject
import gtk
import evince
+import xmlrpclib
+from cookiemagic import XSCookieTransport
+from sugar.graphics.alert import Alert
+from sugar.graphics.icon import Icon
from sugar.graphics.toolbutton import ToolButton
from sugar.graphics.menuitem import MenuItem
from sugar.graphics import iconentry
@@ -36,13 +39,15 @@ class PrintToolbar(gtk.Toolbar):
__gtype_name__= 'PrintToolbar'
- def __init__(self, evince_view, title=None, tempfile=None):
+ def __init__(self, evince_view, activity, title=None, tempfile=None):
gtk.Toolbar.__init__(self)
self._evince_view = evince_view
+ self._activity = activity
self._document = None
self._title = title
self._path = tempfile
+ self._username = ''
self._pdf = ToolButton('document-save')
self._pdf.set_tooltip(_('save-PDF'))
@@ -52,9 +57,18 @@ class PrintToolbar(gtk.Toolbar):
self._moodle = ToolButton()
self._moodle.set_tooltip(_('Send-Moodle'))
- self._moodle.props.sensitive = False
+ self._moodle.props.sensitive = True
self.insert(self._moodle, -1)
self._moodle.show()
+ self._moodle.connect('clicked', self.xmlrpc,)
+
+ palette = self._moodle.get_palette()
+ menu_item = MenuItem(_('Moodle Username'))
+ menu_item.connect('activate', self.username_textbox)
+ palette.menu.append(menu_item)
+ menu_item.show()
+
+
self._USB = ToolButton('printer')
self._USB.set_tooltip(_('printer'))
@@ -64,9 +78,57 @@ class PrintToolbar(gtk.Toolbar):
self._USB.connect('clicked', self.printing)
+ def username_textbox(self, widget):
+ widget = gtk.Window('Username')
+
+
+
+
+ def xmlrpc(self, widget):
+
+
+ ''' window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+ window.set_size_request(200, 100)
+ window.set_title("Send to Moodle")
+ window.connect("delete_event", lambda w,e: gtk.main_quit())
+ menu = gtk.Menu()
+
+ if username == '':
+ self._stop_alert = Alert()
+ self._stop_alert.props.title = _('Moodle Username not entered')
+ self._stop_alert.props.msg = _('Please Enter your username')
+ ok_icon = Icon(icon_name='dialog-ok')
+ self._stop_alert.add_button(gtk.RESPONSE_OK, _('Ok'), ok_icon)
+ ok_icon.show()
+ self._activity.add_alert(self._stop_alert)
+ self._stop_alert.connect('response', self.__stop_response_cb)
+ self._stop_alert.show()
+ return
+
+ # This is how you get the url to the school server.
+ client = gconf.client_get_default()
+ backup_url = client.get_string('/desktop/sugar/backup_url')
+ if not backup_url:
+ _logger.debug('seed_xs_cookie: Not registered with Schoolserver')
+ return
+
+ jabber_server = client.get_string(
+ '/desktop/sugar/collaboration/jabber_server')
+ '''
+
+ server = xmlrpclib.ServerProxy("http://localhost/~iwikiwi/moodle1/web/mod/print/print_xmlrpc.php", transport=XSCookieTransport())
+ filein = open(self._path, 'rb')
+ contents = filein.read()
+ filein.close()
+ bits = xmlrpclib.Binary(contents)
+ server.send_func(bits,'lol',)
+
+ def __stop_response_cb(self, alert, response_id):
+ self._activity.remove_alert(alert)
+
def printing(self, widget):
justPrint = JustPrint(self._title, self._path)
- justPrint.Printit()
+ justPrint.PrintIt()
def setTitlePath(self, title, path):
self._title = title
@@ -91,26 +153,37 @@ class PrintSetupToolbar(gtk.Toolbar):
total_page_item.add(self._noOfPagesL)
total_page_item.show()
self.insert(total_page_item, -1)
- self._noOfPagesTB = gtk.Entry()
- self._noOfPagesTB.connect("activate", self.TBfunction,
- gtk.RESPONSE_OK)
- self._noOfPagesTB.set_editable(True)
- self._noOfPagesTB.show()
+ self._noOfPages1 = gtk.SpinButton()
+ self._noOfPages1.set_numeric(True)
+ self._noOfPages2 = gtk.SpinButton()
+ self._noOfPages2.set_numeric(True)
+ #self._noOfPages1.connect("value-changed", self.SetPage,
+ # gtk.RESPONSE_OK)
+ #self._noOfPages2.connect("value-changed", self.SetPage,
+ # gtk.RESPONSE_OK)
+
+ #self._noOfPagesTB.set_editable(True)
+ self._noOfPages1.show()
+ self._noOfPages2.show()
total_page_item1 = gtk.ToolItem()
-
- total_page_item1.add(self._noOfPagesTB)
+ total_page_item2 = gtk.ToolItem()
+ total_page_item1.add(self._noOfPages1)
+ total_page_item2.add(self._noOfPages2)
total_page_item1.show()
+ total_page_item2.show()
self.insert(total_page_item1, -1)
+ self.insert(total_page_item2, -1)
+
printerEnumerationObj = EnumeratePrinters()
- printerObjList = printerEnumerationObj.getPrinter()
+ self.printerObjList = printerEnumerationObj.getPrinters()
self._printerComboBox = gtk.combo_box_new_text()
self._printerComboBox.append_text('Printer:')
- for printer in printerObjList:
-
- self._printerComboBox.append_text(printer)
+ for printer in self.printerObjList:
+ self._printerComboBox.append_text(printer.get_name())
self._printerComboBox.connect('changed', self.changed_cb)
+
self._printerComboBox.set_active(0)
self._printerComboBox.show()
total_page_item2 = gtk.ToolItem()
@@ -125,25 +198,40 @@ class PrintSetupToolbar(gtk.Toolbar):
self._USB.show()
self._USB.connect('clicked', self.printing)
+
+ #def SetPage(self,widget):
+ # pass
+
+ def set_document(self, document):
+ self._document = document
+ noOfPages = self._document.get_n_pages()
+ self._noOfPages1.set_range(0, noOfPages)
+ self._noOfPages2.set_range(0, noOfPages)
+ self._noOfPages2.set_value(noOfPages)
+ self.adj1 = gtk.Adjustment(1.0, 1.0, noOfPages, 1.0, 5.0, 0.0)
+ self.adj2 = gtk.Adjustment(1.0, 1.0, noOfPages, 1.0, 5.0, 0.0)
+
+ self._noOfPages1.configure(self.adj1, 0, 0)
+ self._noOfPages2.configure(self.adj2, 0, 0)
- def TBfunction(self, widget, entry):
-
- entry_text = widget.get_text()
- self.justPrint = JustPrint(self._title, self._path)
- self.justPrint.setRange(entry_text)
+
def changed_cb(self, combobox):
model = combobox.get_model()
index = combobox.get_active()
if index:
- self._printerToSet = model[index][0]
- self.justPrint.setPrinter(self._printerToSet)
+ self._printerToSet = self.printerObjList[index-1]
return
def printing(self, widget):
-
+
+ range_params = [self._noOfPages1.get_value_as_int(),
+ self._noOfPages2.get_value_as_int(),]
+ self.justPrint = JustPrint(self._title, self._path)
+ self.justPrint.setRange(range_params)
+ self.justPrint.setPrinter(self._printerToSet)
self.justPrint.printIt()
def setTitlePath(self, title, path):
@@ -225,8 +313,7 @@ class ReadToolbar(gtk.Toolbar):
self.insert(navitem, -1)
navitem.show_all()
-
-
+
def set_document(self, document):
self._document = document
page_cache = self._document.get_page_cache()
diff --git a/test.pcap b/test.pcap
index 809ca89..809ca89 100644..100755
--- a/test.pcap
+++ b/test.pcap
Binary files differ
diff --git a/xmlrpc.txt b/xmlrpc.txt
index 7a68751..7a68751 100644..100755
--- a/xmlrpc.txt
+++ b/xmlrpc.txt