--- /dev/null
+<?php
+/**
+ * The Hylax script to compose a new fax.
+ *
+ * $Horde: incubator/hylax/compose.php,v 1.12 2009/06/10 17:33:26 slusarz Exp $
+ *
+ * Copyright 2005-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author Joel Vandal <joel@scopserv.com>
+ */
+
+@define('HYLAX_BASE', dirname(__FILE__));
+require_once HYLAX_BASE . '/lib/base.php';
+require_once 'Horde/Form.php';
+require_once 'Horde/Form/Renderer.php';
+require_once 'Horde/Form/Action.php';
+require_once 'Horde/Template.php';
+
+/* Load Cover Page templates */
+require HYLAX_BASE . '/config/covers.php';
+
+/* Get Cover Page template name */
+$covers = array();
+foreach ($_covers as $id => $cover) {
+ $covers[$id] = $cover['name'];
+}
+
+$tpl = Horde_Util::getFormData('template', 'default');
+if (empty($_covers[$tpl])) {
+ Horde::fatal(_("The requested Cover Page does not exist."), __FILE__, __LINE__);
+}
+
+/* Load Form Actions */
+$action = Horde_Form_Action::factory('submit');
+
+/* Create Form */
+$vars = Horde_Variables::getDefaultVariables();
+$form = new Horde_Form($vars, _("Compose a new Fax"), 'compose');
+$form->setButtons(_("Send"));
+$form->appendButtons(_("Preview"));
+
+/* Cover Page section */
+$form->addVariable(_("Cover Page"), 'fromhdr', 'header', false);
+$form->addVariable(_("Template"), 'template', 'enum', true, false, null, array($covers));
+$form->addVariable(_("Fax Number"), 'faxnum', 'text', true);
+$form->addVariable(_("Name"), 'name', 'text', false);
+$form->addVariable(_("Company"), 'company', 'text', false);
+$form->addVariable(_("Subject"), 'subject', 'text', false, false, null, array(false, 60));
+$form->addVariable(_("Comment"), 'comment', 'longtext', false, false, null, array(4, 80));
+
+/* Set up template. */
+$template = new Horde_Template();
+$template->set('form', '');
+$template->set('menu', Hylax::getMenu('string'));
+$template->set('notify', Horde_Util::bufferOutput(array($notification, 'notify'), array('listeners' => 'status')));
+
+require HYLAX_TEMPLATES . '/common-header.inc';
+echo $template->fetch(HYLAX_TEMPLATES . '/compose/compose.html');
+
+$renderer = new Horde_Form_Renderer();
+$form->renderActive($renderer, $vars, Horde::selfURL(), 'post');
+
+require $registry->get('templates', 'horde') . '/common-footer.inc';
--- /dev/null
+conf.php
+conf.bak.php
+covers.php
+prefs.php
--- /dev/null
+Deny from all
--- /dev/null
+<?xml version="1.0"?>
+<!-- $Horde: incubator/hylax/config/conf.xml,v 1.5 2005/06/18 01:38:51 jvandal Exp $ -->
+<configuration>
+ <configtab name="fax" desc="Fax Driver Settings">
+ <configsection name="fax">
+ <configheader>Fax Driver Settings</configheader>
+ <configswitch name="driver" desc="What Fax driver should we use?">hylafax
+ <case name="hylafax" desc="Hylafax">
+ <configsection name="params">
+ <configstring name="base_path" desc="Where are located Hylafax binaries?">/usr/sbin</configstring>
+ </configsection>
+ <configstring name="faxrcvd" desc="Where is located the 'faxrcvd' binary?">/var/spool/hylafax/bin</configstring>
+ <configstring name="print" required="false" desc="What is the 'print' command?"></configstring>
+ </case>
+ <case name="spandsp" desc="Asterisk w/ SpanDSP">
+ <configsection name="params">
+ <configstring name="channel" desc="What outbound channel to use for sending faxes?">Zap/g1</configstring>
+ <configinteger name="maxretries" desc="Number of times to retry if the channel is busy or unavailable">0</configinteger>
+ <configinteger name="retrytime" desc="Time between retries?">60</configinteger>
+ <configinteger name="waittime" desc="How long to wait for an answer (seconds) ?">20</configinteger>
+ <configstring name="outgoing" desc="Where is located the Asterisk Outgoing spool directory?">/var/spool/asterisk/outgoing</configstring>
+ </configsection>
+ </case>
+ </configswitch>
+ </configsection>
+ </configtab>
+ <configtab name="storage" desc="Storage Driver Settings">
+ <configsection name="storage">
+ <configheader>Storage Driver Settings</configheader>
+ <configswitch name="driver" desc="What storage driver should we use?">sql
+ <case name="sql" desc="SQL">
+ <configsection name="params">
+ <configsql switchname="driverconfig"/>
+ </configsection>
+ </case>
+ </configswitch>
+ </configsection>
+ </configtab>
+
+ <configtab name="cups" desc="CUPS Settings">
+ <configsection name="cups">
+ <configheader>CUPS Settings</configheader>
+ <configstring name="www_user" desc="What is the name of the user?">faxuser</configstring>
+ <configstring name="backend_dir" desc="Where is the CUPS backend directory?">/usr/lib/cups/backend</configstring>
+ <configstring name="ppd_dir" desc="Where is the CUPS PPD (Model) directory?">/usr/share/cups/model</configstring>
+ </configsection>
+ </configtab>
+</configuration>
--- /dev/null
+<?php
+/**
+ * $Horde: incubator/hylax/config/covers.php.dist,v 1.1 2005/07/09 20:56:18 jvandal Exp $
+ *
+ * This file defines the templates used to generate Cover Page.
+ *
+ */
+
+$_covers['default'] = array(
+ 'name' => _("Default Cover Page"),
+ 'template' => '<table>
+<tr>
+ <th>From</th>
+ <th>To</th>
+ <th>Date</th>
+</tr>
+
+<loop:faxes>
+<tr>
+ <td><tag:faxes.from_name /></td>
+ <td><tag:faxes.to_name /></td>
+ <td><tag:faxes.date_created /></td>
+</tr>
+</loop:faxes>
+
+</table>'
+);
--- /dev/null
+<?php
+/**
+ * $Horde: incubator/hylax/config/prefs.php.dist,v 1.1 2005/07/09 20:56:18 jvandal Exp $
+ *
+ * See horde/config/prefs.php for documentation on the structure of this file.
+ */
+
+$prefGroups['display'] = array(
+ 'column' => _("Other Options"),
+ 'label' => _("Display Options"),
+ 'desc' => _("Change display options such as how search results are sorted."),
+ 'members' => array('hylax_default_view')
+);
+
+// default view
+$_prefs['hylax_default_view'] = array(
+ 'value' => 'summary',
+ 'locked' => false,
+ 'shared' => false,
+ 'type' => 'enum',
+ 'enum' => array('summmary' => _("Summary"),
+ 'folder' => _("Folders"),
+ 'compose' => _("Compose")),
+ 'desc' => _("Select the view to display after login:")
+);
--- /dev/null
+
+Hylafax
+=======
+
+- In the /var/spool/fax/etc/hosts.hfaxd file add something like the following line or lines:
+ localhost:faxuser
+ 127.0.0.1:faxuser
+
+- Add the following group to your /etc/group file:
+ groupadd -g 60002 faxuser
+
+- Make sure the apache user is part of the faxuser group:
+ faxuser:x:60002:apache
+
+
+SpanDSP w/ Asterisk
+===================
+
+- Add the following line in your /etc/asterisk/extensions.conf
+
+[macro-faxreceive]
+exten => s,1,SetVar(FAXFILE=/var/spool/asterisk/fax/${CALLEDFAX}/${UNIQUEID})
+exten => s,2,rxfax(${FAXFILE}.tif)
+
+[fax]
+exten => 5551212,1,Macro(faxreceive)
+exten => h,1,System(/var/www/horde/hylax/scripts/spandsp/faxrcvd "${FAXFILE}" "${CALLERIDNUM}" "${CALLEDFAX}")
+
+[default]
+
+exten => 5551212,1,SetVar(CALLEDFAX=${EXTEN})
+exten => 5551212,2,Answer
+exten => 5551212,3,Goto(fax,${EXTEN},1)
+
+
--- /dev/null
+$Horde: incubator/hylax/docs/TODO,v 1.1 2005/06/14 03:58:28 jvandal Exp $
+
+- Integrate SpanDSP fax driver with Asterisk
+
+- Ability to create new covers and faxes
--- /dev/null
+<?php
+/**
+ * The Hylax script to show a summary view.
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * $Horde: incubator/hylax/folder.php,v 1.7 2009/06/10 05:24:17 slusarz Exp $
+ */
+@define('HYLAX_BASE', dirname(__FILE__));
+require_once HYLAX_BASE . '/lib/base.php';
+
+$folder = strtolower(Horde_Util::getFormData('folder', 'inbox'));
+$path = Horde_Util::getFormData('path');
+$base_folders = Hylax::getBaseFolders();
+
+/* Get the list of faxes in folder. */
+$folder_list = $hylax_storage->listFaxes($folder);
+
+/* Set up URLs which will be used in the list. */
+$view_url = Horde::applicationUrl('view.php');
+$view_img = Horde::img('view.gif', _("View"), 'align="middle"');
+
+$download_url = Horde_Util::addParameter($view_url, 'action', 'download');
+$download_img = Horde::img('download.gif', _("Download"), 'align="middle"', $GLOBALS['registry']->getImageDir('horde'));
+
+$edit_url = Horde::applicationUrl('edit.php');
+$edit_label = ($folder == 'pending') ? _("Edit") : _("Resend");
+$edit_img = Horde::img('edit.gif', $edit_label, 'align="middle"', $GLOBALS['registry']->getImageDir('horde'));
+
+$del_url = Horde::applicationUrl('delete.php');
+$del_img = Horde::img('delete-small.gif', _("Delete"), 'align="middle"', $GLOBALS['registry']->getImageDir('horde'));
+
+$params = array('folder' => $folder, 'path' => $path);
+$warn_img = Horde::img('alerts/warning.gif', _("Warning"), 'align="middle"', $GLOBALS['registry']->getImageDir('horde'));
+$send_url = Horde::applicationUrl('send.php');
+
+$print_url = Horde::applicationUrl('print.php');
+$print_img = Horde::img('print.gif', _("Print"), 'align="middle"', $GLOBALS['registry']->getImageDir('horde'));
+
+/* Loop through list and set up items. */
+$i = 0;
+foreach ($folder_list as $key => $value) {
+ $params['fax_id'] = $value['fax_id'];
+
+ /* View. */
+ $url = Horde_Util::addParameter($view_url, $params);
+ $folder_list[$key]['actions'][] = Horde::link($url, _("View")) . $view_img . '</a>';
+
+ /* Download. */
+ $url = Horde_Util::addParameter($download_url, $params);
+ $folder_list[$key]['actions'][] = Horde::link($url, _("Download")) . $download_img . '</a>';
+
+ /* Delete. */
+ // $url = Horde_Util::addParameter($del_url, $params);
+ // $folder_list[$key]['actions'][] = Horde::link($url, _("Delete")) . $del_img . '</a>';
+
+ /* Print. */
+ $url = Horde_Util::addParameter($print_url, $params);
+ $url = Horde_Util::addParameter($url, 'url', Horde::selfUrl(true));
+ $folder_list[$key]['actions'][] = Horde::link($url, _("Print")) . $print_img . '</a>';
+ $folder_list[$key]['alt_count'] = $i;
+ $i = $i ? 0 : 1;
+
+ /* Format date. */
+ $folder_list[$key]['fax_created'] = strftime('%d/%m/%Y %H:%M', $value['fax_created']);
+
+ if (empty($value['fax_number']) && $value['fax_type'] != 0) {
+ $url = Horde_Util::addParameter($send_url, 'fax_id', $value['fax_id']);
+ $folder_list[$key]['fax_number'] = $warn_img . ' ' . Horde::link($url, _("Insert Number")) . _("Insert Number") . '</a>';
+ } elseif (empty($value['fax_number']) && $value['fax_type'] == 0) {
+ $folder_list[$key]['fax_number'] = _("unknown");
+ }
+ $folder_list[$key]['fax_status'] = $gateway->getStatus($value['job_id']);
+}
+
+/* Set up actions. */
+$actions = array();
+foreach ($base_folders as $key => $value) {
+ if ($folder != $key) {
+ $url = Horde_Util::addParameter(Horde::applicationUrl('folder.php'), 'folder', $key);
+ $actions[] = Horde::link($url) . $value . '</a>';
+ } else {
+ $actions[] = $value;
+ }
+}
+
+/* Set up template. */
+$template = &new Horde_Template();
+if ($folder == 'archive') {
+ $template->set('folder_name', $path);
+} else {
+ $template->set('folder_name', $base_folders[$folder]);
+}
+$template->set('folder', $folder_list, true);
+$template->set('actions', $actions);
+$template->set('menu', Hylax::getMenu('string'));
+$template->set('notify', Horde_Util::bufferOutput(array($notification, 'notify'), array('listeners' => 'status')));
+
+require HYLAX_TEMPLATES . '/common-header.inc';
+echo $template->fetch(HYLAX_TEMPLATES . '/folder/folder.html');
+require $registry->get('templates', 'horde') . '/common-footer.inc';
--- /dev/null
+<?php
+/**
+ * The Hylax script to show a fax view.
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * $Horde: incubator/hylax/img.php,v 1.4 2009/06/10 05:24:17 slusarz Exp $
+ */
+
+@define('AUTH_HANDLER', true);
+@define('HYLAX_BASE', dirname(__FILE__));
+require_once HYLAX_BASE . '/lib/base.php';
+
+$fax_id = Horde_Util::getFormData('fax_id');
+$page = Horde_Util::getFormData('page');
+$preview = Horde_Util::getFormData('preview');
+
+/* Set up the cache object. */
+require_once 'Horde/Cache.php';
+$cache = &Horde_Cache::singleton($conf['cache']['driver'], Horde::getDriverConfig('cache', $conf['cache']['driver']));
+if (is_a($cache, 'PEAR_Error')) {
+ Horde::fatal($cache, __FILE__, __LINE__);
+}
+
+/* Call the get the image data using cache. */
+$id = $fax_id . '_' . $page . ($preview ? '_p' : '');
+$image = $cache->getOutput($id, "Hylax::getImage('$fax_id', '$page', '$preview');", 86400);
+
+header('Content-type: image/png');
+echo $image;
--- /dev/null
+<?php
+/**
+ * $Horde: incubator/hylax/index.php,v 1.12 2009/01/06 17:50:48 jan Exp $
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author Marko Djukic <marko@oblo.com>
+ */
+
+@define('HYLAX_BASE', dirname(__FILE__));
+$hylax_configured = (is_readable(HYLAX_BASE . '/config/conf.php') &&
+ is_readable(HYLAX_BASE . '/config/prefs.php') &&
+ is_readable(HYLAX_BASE . '/config/covers.php'));
+
+if (!$hylax_configured) {
+ require HYLAX_BASE . '/../lib/Test.php';
+ Horde_Test::configFilesMissing('Hylax', HYLAX_BASE,
+ array('conf.php', 'prefs.php'),
+ array('covers.php' => 'This file defines the templates for Cover Sheets.'));
+}
+
+require HYLAX_BASE . '/folder.php';
--- /dev/null
+Deny from all
--- /dev/null
+<?php
+/**
+ * Hylax_Driver Class
+ *
+ * $Horde: incubator/hylax/lib/Driver.php,v 1.13 2009/01/06 17:50:48 jan Exp $
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author Marko Djukic <marko@oblo.com>
+ * @package Hylax
+ */
+class Hylax_Driver {
+
+ var $_params;
+
+ function Hylax_Driver($params)
+ {
+ global $conf;
+
+ $this->_params = $params;
+ }
+
+ function getFolder($folder, $path = null)
+ {
+ return $this->_getFolder($folder, $path);
+ }
+
+ /**
+ * Attempts to return a concrete Hylax_Driver instance based on $driver.
+ *
+ * @param string $driver The type of concrete Hylax_Driver subclass to
+ * return.
+ * @param array $params A hash containing any additional configuration or
+ * connection parameters a subclass might need.
+ *
+ * @return Hylax_Driver The newly created concrete Hylax_Driver
+ * instance, or false on error.
+ */
+ function &factory($driver = null, $params = null)
+ {
+ if (is_null($driver)) {
+ $driver = $GLOBALS['conf']['fax']['driver'];
+ }
+
+ $driver = basename($driver);
+
+ include_once dirname(__FILE__) . '/Driver/' . $driver . '.php';
+ $class = 'Hylax_Driver_' . $driver;
+ if (class_exists($class)) {
+ $hylax = &new $class($params);
+ return $hylax;
+ } else {
+ Horde::fatal(PEAR::raiseError(sprintf(_("No such backend \"%s\" found"), $driver)), __FILE__, __LINE__);
+ }
+ }
+
+ /**
+ * Attempts to return a reference to a concrete Hylax_Driver instance
+ * based on $driver. It will only create a new instance if no
+ * Hylax_Driver instance with the same parameters currently exists.
+ *
+ * This should be used if multiple storage sources are required.
+ *
+ * This method must be invoked as: $var = &Hylax_Driver::singleton()
+ *
+ * @param string $driver The type of concrete Hylax_Driver subclass to
+ * return.
+ * @param array $params A hash containing any additional configuration or
+ * connection parameters a subclass might need.
+ *
+ * @return mixed The created concrete Hylax_Driver instance, or false on
+ * error.
+ */
+ function &singleton($driver = null, $params = null)
+ {
+ static $instances;
+
+ if (is_null($driver)) {
+ $driver = $GLOBALS['conf']['fax']['driver'];
+ }
+
+ if (!isset($instances)) {
+ $instances = array();
+ }
+ $signature = serialize(array($driver, $params));
+
+ if (!isset($instances[$signature])) {
+ $instances[$signature] = &Hylax_Driver::factory($driver, $params);
+ }
+ return $instances[$signature];
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Hylax_Driver_hylafax Class
+ *
+ * $Horde: incubator/hylax/lib/Driver/hylafax.php,v 1.17 2009/01/06 17:50:48 jan Exp $
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author Marko Djukic <marko@oblo.com>
+ * @package Hylax
+ */
+class Hylax_Driver_hylafax extends Hylax_Driver {
+
+ var $_states = array();
+ var $_stat_cols = array();
+ var $_cmd = array();
+
+ function Hylax_Driver_hylafax($params)
+ {
+ parent::Hylax_Driver($params);
+
+ $this->_states = Hylax::getStates();
+ $this->_stat_cols = Hylax::getStatCols();
+ $this->_cmd = array('sendfax' => '/usr/bin/sendfax');
+ }
+
+ function send($number, $data, $time = null)
+ {
+ $command = sprintf('%s -n -d %s',
+ $this->_cmd['sendfax'],
+ $number);
+ $descriptorspec = array(0 => array("pipe", "r"),
+ 1 => array("pipe", "w"),
+ 2 => array("pipe", "w"));
+
+ /* Set up the process. */
+ $process = proc_open($command, $descriptorspec, $pipes);
+ if (is_resource($process)) {
+ fwrite($pipes[0], $data);
+ fclose($pipes[0]);
+
+ $output = '';
+ while (!feof($pipes[1])) {
+ $output .= fgets($pipes[1], 1024);
+ }
+ fclose($pipes[1]);
+
+ proc_close($process);
+ }
+
+ /* Regex match the job id from the output. */
+ preg_match('/request id is (\d+)/', $output, $matches);
+ if (isset($matches[1])) {
+ return $matches[1];
+ }
+ return PEAR::raiseError(sprintf(_("Could not send fax. %s"), $output));
+ }
+
+ function numFaxesIn()
+ {
+ //$inbox = $this->getInbox();
+ //return count($inbox);
+ }
+
+ function numFaxesOut()
+ {
+ //$outbox = $this->getOutbox();
+ //return count($outbox);
+ }
+
+ function getInbox()
+ {
+ return $this->_getFolder('inbox');
+ }
+
+ function _getFolder($folder, $path = null)
+ {
+ switch ($folder) {
+ case 'inbox':
+ return $this->_parseFaxStat($this->_exec('faxstat -r'));
+ break;
+
+ case 'outbox':
+ return $this->_parseFaxStat($this->_exec('faxstat -s'));
+ break;
+
+ case 'sent':
+ return $this->_parseFaxStat($this->_exec('faxstat -d'));
+ break;
+
+ case 'archive':
+ //return $GLOBALS['storage']->getFolder($path);
+ break;
+ }
+ }
+
+ function getJob($job_id, $folder, $path = null)
+ {
+ global $conf;
+
+ $job = array();
+
+ switch ($folder) {
+ case 'inbox':
+ break;
+
+ case 'outbox':
+ $filename = '/var/spool/fax/sendq/q' . $job_id;
+ $job = $this->_getParseSendJob($filename);
+ break;
+
+ case 'sent':
+ $filename = '/var/spool/fax/doneq/q' . $job_id;
+ $job = $this->_getParseSendJob($filename);
+ break;
+
+ case 'archive':
+ //return $GLOBALS['storage']->getFolder($path);
+ break;
+ }
+
+ $job['thumbs'] = $this->getThumbs($job_id, 'docq/' . $job['postscript'], true);
+
+ return $job;
+ }
+
+ function getStatus($job_id)
+ {
+ static $send_q = array();
+ static $done_q = array();
+ if (empty($send_q)) {
+ exec('/usr/bin/faxstat -s', $output);
+ $iMax = count($output);
+ for ($i = 4; $i < $iMax; $i++) {
+ $send_q[] = $output[$i];
+ }
+ }
+ if (empty($done_q)) {
+ exec('/usr/bin/faxstat -d', $output);
+ $iMax = count($output);
+ for ($i = 4; $i < $iMax; $i++) {
+ $done_q[] = $output[$i];
+ }
+ }
+
+ /* Check the queues. */
+ foreach ($send_q as $line) {
+ if ((int)substr($line, 0, 4) == $job_id) {
+ return _("Sending");
+ }
+ }
+ foreach ($done_q as $line) {
+ if ((int)substr($line, 0, 4) == $job_id) {
+ return substr($line, 51);
+ }
+ }
+ return '';
+ }
+
+ function _getParseSendJob($filename)
+ {
+ $job = array();
+ $job_file = file_get_contents($filename);
+ $job_file = explode("\n", $job_file);
+ foreach ($job_file as $line) {
+ if (empty($line)) {
+ continue;
+ }
+ list($key, $value) = explode(':', $line, 2);
+ if ($key == 'postscript') {
+ $job[$key] = basename($value);
+ } else {
+ $job[$key] = $value;
+ }
+ }
+ return $job;
+ }
+
+ function getThumbs($job_id, $ps)
+ {
+ if ($this->_vfs->exists(HYLAX_VFS_PATH, $job_id)) {
+ /* Return thumb image list. */
+ $images = $this->_vfs->listFolder(HYLAX_VFS_PATH . '/' . $job_id, 'doc.png');
+ if (!empty($images)) {
+ return array_keys($images);
+ }
+ }
+ $images = $this->imagesToVFS($job_id, $ps);
+ return array_keys($images);
+ }
+
+ function imagesToVFS($job_id, $ps)
+ {
+ global $conf;
+
+ $this->_vfs->autoCreatePath(HYLAX_VFS_PATH . '/' . $job_id);
+
+ $ps = '/var/spool/fax/' . $ps;
+ $vfs_path = $conf['vfs']['params']['vfsroot'] . '/' . HYLAX_VFS_PATH;
+ /* Do thumbs. */
+ $cmd = sprintf('convert -geometry 25%% %s %s/%s/thumb.png', $ps, $vfs_path, $job_id);
+ $result = $this->_exec($cmd);
+ /* Do full images. */
+ $cmd = sprintf('convert %s %s/%s/doc.png', $ps, $vfs_path, $job_id);
+ $result = $this->_exec($cmd);
+
+ /* Return thumb image list. */
+ return $this->_vfs->listFolder(HYLAX_VFS_PATH . '/' . $job_id, 'doc.png');
+ }
+
+ function _exec($cmd, $input = '')
+ {
+ $spec = array(//0 => array('pipe', 'r'),
+ 1 => array('pipe', 'w'),
+ 2 => array('file', '/tmp/error-output.txt', 'a')
+ );
+ $proc = proc_open($this->_params['base_path'] . $cmd, $spec, $pipes);
+ //fwrite($pipes[0], $input);
+ //@fclose($pipes[0]);
+ while (!feof($pipes[1])) {
+ $result[] = trim(fgets($pipes[1], 1024));
+ }
+ @fclose($pipes[1]);
+ @fclose($pipes[2]);
+ proc_close($proc);
+
+ if (empty($result[(count($result) - 1)])) {
+ unset($result[(count($result) - 1)]);
+ }
+
+ return $result;
+ }
+
+ function _parseFaxStat($result)
+ {
+ $out = array();
+ $i = 0;
+ foreach ($result as $line) {
+ /* Job ID number expected as first char. */
+ if (!empty($line) && is_numeric($line[0])) {
+ $values = explode('|', $line);
+ foreach ($this->_stat_cols as $j => $key) {
+ $out[$i][$key] = $values[$j];
+ }
+ $out[$i]['state'] = $this->_states[$out[$i]['state']];
+ }
+ $i++;
+ }
+ return $out;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Hylax_Driver_spandsp Class
+ *
+ * $Horde: incubator/hylax/lib/Driver/spandsp.php,v 1.14 2009/01/06 17:50:48 jan Exp $
+ *
+ * Copyright 2005-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * @author Joel Vandal <joel@scopserv.com>
+ * @package Hylax
+ */
+class Hylax_Driver_spandsp extends Hylax_Driver {
+
+ var $_states = array();
+ var $_stat_cols = array();
+ var $_cmd = array();
+
+ function Hylax_Driver_spandsp($params)
+ {
+ parent::Hylax_Driver($params);
+
+ $this->_states = Hylax::getStates();
+ $this->_stat_cols = Hylax::getStatCols();
+ }
+
+ function send($number, $data, $time = null)
+ {
+ /* Create a temporary file. */
+ $filename = sprintf("%s.fax", Horde::getTempFile('hylax'));
+ $fh = fopen($filename, "w");
+ fwrite($fh, $data);
+ fclose($fh);
+
+ return $this->createCallFile($filename);
+ }
+
+ function createCallFile($filename)
+ {
+ global $conf;
+
+ /* Create outgoing call */
+ $data = sprintf("Channel: %s/%s\n", $conf['fax']['params']['channel'], $number);
+ $data .= sprintf("MaxRetries: %d\n", $conf['fax']['params']['maxretries']);
+ $data .= sprintf("RetryTime: %d\n", $conf['fax']['params']['retrytime']);
+ $data .= sprintf("WaitTime: %d\n", $conf['fax']['params']['waittime']);
+ $data .= sprintf("Application: %s\n", 'txfax');
+ $data .= sprintf("Data: %s|caller\n", $filename);
+
+ $outfile = sprintf("%s/%s.call", $conf['fax']['params']['outgoing'], md5(microtime()));
+ if ($fh = fopen($outfile, "w")) {
+ fwrite($fh, $data);
+ fclose($fh);
+ return true;
+ }
+
+ return PEAR::raiseError(sprintf(_("Could not send fax. %s"), $output));
+ }
+
+ function numFaxesIn()
+ {
+ //$inbox = $this->getInbox();
+ //return count($inbox);
+ }
+
+ function numFaxesOut()
+ {
+ //$outbox = $this->getOutbox();
+ //return count($outbox);
+ }
+
+ function getInbox()
+ {
+ // return $this->_getFolder('inbox');
+ }
+
+ function _getFolder($folder, $path = null)
+ {
+ switch ($folder) {
+ case 'inbox':
+ // return $this->_parseFaxStat($this->_exec('faxstat -r'));
+ break;
+
+ case 'outbox':
+ // return $this->_parseFaxStat($this->_exec('faxstat -s'));
+ break;
+
+ case 'sent':
+ // return $this->_parseFaxStat($this->_exec('faxstat -d'));
+ break;
+
+ case 'archive':
+ //return $GLOBALS['storage']->getFolder($path);
+ break;
+ }
+ }
+
+ function getJob($job_id, $folder, $path = null)
+ {
+ global $conf;
+
+ $job = array();
+
+ switch ($folder) {
+ case 'inbox':
+ break;
+
+ case 'outbox':
+ // $filename = '/var/spool/fax/sendq/q' . $job_id;
+ // $job = $this->_getParseSendJob($filename);
+ break;
+
+ case 'sent':
+ // $filename = '/var/spool/fax/doneq/q' . $job_id;
+ // $job = $this->_getParseSendJob($filename);
+ break;
+
+ case 'archive':
+ //return $GLOBALS['storage']->getFolder($path);
+ break;
+ }
+
+ // $job['thumbs'] = $this->getThumbs($job_id, 'docq/' . $job['postscript'], true);
+
+ return $job;
+ }
+
+ function getStatus($job_id)
+ {
+ return null;
+ }
+
+ function getThumbs($job_id, $ps)
+ {
+ if ($this->_vfs->exists(HYLAX_VFS_PATH, $job_id)) {
+ /* Return thumb image list. */
+ $images = $this->_vfs->listFolder(HYLAX_VFS_PATH . '/' . $job_id, 'doc.png');
+ if (!empty($images)) {
+ return array_keys($images);
+ }
+ }
+ $images = $this->imagesToVFS($job_id, $ps);
+ return array_keys($images);
+ }
+
+ function imagesToVFS($job_id, $ps)
+ {
+ global $conf;
+
+ $this->_vfs->autoCreatePath(HYLAX_VFS_PATH . '/' . $job_id);
+
+ $ps = '/var/spool/fax/' . $ps;
+ $vfs_path = $conf['vfs']['params']['vfsroot'] . '/' . HYLAX_VFS_PATH;
+ /* Do thumbs. */
+ $cmd = sprintf('convert -geometry 25%% %s %s/%s/thumb.png', $ps, $vfs_path, $job_id);
+ $result = $this->_exec($cmd);
+ /* Do full images. */
+ $cmd = sprintf('convert %s %s/%s/doc.png', $ps, $vfs_path, $job_id);
+ $result = $this->_exec($cmd);
+
+ /* Return thumb image list. */
+ return $this->_vfs->listFolder(HYLAX_VFS_PATH . '/' . $job_id, 'doc.png');
+ }
+
+ function _exec($cmd, $input = '')
+ {
+ $spec = array(//0 => array('pipe', 'r'),
+ 1 => array('pipe', 'w'),
+ 2 => array('file', '/tmp/error-output.txt', 'a')
+ );
+ $proc = proc_open($this->_params['base_path'] . $cmd, $spec, $pipes);
+ //fwrite($pipes[0], $input);
+ //@fclose($pipes[0]);
+ while (!feof($pipes[1])) {
+ $result[] = trim(fgets($pipes[1], 1024));
+ }
+ @fclose($pipes[1]);
+ @fclose($pipes[2]);
+ proc_close($proc);
+
+ if (empty($result[(count($result) - 1)])) {
+ unset($result[(count($result) - 1)]);
+ }
+
+ return $result;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The Hylax:: class providing some support functions to the Hylax
+ * module.
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * $Horde: incubator/hylax/lib/Hylax.php,v 1.17 2009/06/10 06:07:33 slusarz Exp $
+ *
+ * @author Marko Djukic <marko@oblo.com>
+ * @package Hylax
+ */
+class Hylax {
+
+ function getBaseFolders()
+ {
+ return array('inbox' => _("Inbox"),
+ 'outbox' => _("Outbox"));
+ //'sent' => _("Sent"),
+ //'pending' => _("Pending"));
+ }
+
+ function getStates()
+ {
+ return array('D' => _("Done"),
+ 'F' => _("Failed"),
+ 'S' => _("Sending"),
+ 'W' => _("Waiting"));
+ }
+
+ function getStatCols()
+ {
+ return array('job_id', 'time', 'state', 'owner', 'number', 'pages', 'tot_pages', 'dials', 'duration', 'status');
+ }
+
+ function getVFSPath($folder)
+ {
+ return '.horde/fax/' . $folder;
+ }
+
+ function getImage($fax_id, $page, $preview = false)
+ {
+ $data = $GLOBALS['hylax_storage']->getFaxData($fax_id);
+
+ /* Get the image. */
+ require_once HYLAX_BASE . '/lib/Image.php';
+ $image = &new Hylax_Image();
+ $image->loadData($data);
+ $image->getImage($page, $preview);
+ }
+
+ function getPDF($fax_id)
+ {
+ $data = $GLOBALS['hylax_storage']->getFaxData($fax_id);
+
+ /* Get the pdf. */
+ require_once HYLAX_BASE . '/lib/Image.php';
+ $image = &new Hylax_Image();
+ $image->loadData($data);
+ $image->getPDF();
+ }
+
+ function printFax($fax_id)
+ {
+ $data = $GLOBALS['hylax_storage']->getFaxData($fax_id);
+
+ $command = $GLOBALS['conf']['fax']['print'];
+ $descriptorspec = array(0 => array("pipe", "r"),
+ 1 => array("pipe", "w"),
+ 2 => array("pipe", "w"));
+
+ /* Set up the process. */
+ $process = proc_open($command, $descriptorspec, $pipes);
+ if (!is_resource($process)) {
+ return PEAR::raiseError('fail');
+ }
+
+ fwrite($pipes[0], $data);
+ fclose($pipes[0]);
+
+ $output = '';
+ while (!feof($pipes[1])) {
+ $output .= fgets($pipes[1], 1024);
+ }
+ fclose($pipes[1]);
+
+ $stderr = '';
+ while (!feof($pipes[2])) {
+ $stderr .= fgets($pipes[2], 1024);
+ }
+ fclose($pipes[2]);
+
+ proc_close($process);
+
+ if ($stderr) {
+ return PEAR::raiseError($stderr);
+ }
+
+ return true;
+ }
+
+ function getPages($fax_id, $num_pages)
+ {
+ $pages = array();
+ $params = array('fax_id' => $fax_id,
+ 'preview' => 1);
+
+ /* Set the params for the popup to view the full size pages. */
+ Horde::addScriptFile('popup.js', 'horde');
+ $popup_w = 620;
+ $popup_h = 860;
+
+ for ($i = 0; $i < $num_pages; $i++) {
+ $params['page'] = $i;
+ $url = Horde_Util::addParameter('img.php', $params);
+ $img = Horde::img($url, sprintf(_("View page %s"), $i+1), '', $GLOBALS['registry']->get('webroot'));
+
+ $full_url = Horde::applicationUrl(Horde_Util::addParameter('img.php', array('fax_id' => $fax_id, 'page' => $i)));
+
+ $pages[] = Horde::link('', sprintf(_("View page %s"), $i+1), '', '', "popup('$full_url', $popup_w, $popup_h); return false;") . $img . '</a>';
+ }
+ return $pages;
+ }
+
+ function getMenu($returnType = 'object')
+ {
+ global $registry;
+
+ $menu = new Horde_Menu();
+
+ $menu->addArray(array('url' => Horde::applicationUrl('summary.php'),
+ 'text' => _("Summary"),
+ 'icon' => 'fax.png',
+ 'icon_path' => $registry->getImageDir()));
+
+ $menu->addArray(array('url' => Horde::applicationUrl('folder.php'),
+ 'text' => _("Folders"),
+ 'icon' => 'folder.png',
+ 'icon_path' => $registry->getImageDir()));
+
+ $menu->addArray(array('url' => Horde::applicationUrl('compose.php'),
+ 'text' => _("Compose"),
+ 'icon' => 'compose.png',
+ 'icon_path' => $registry->getImageDir()));
+
+ if ($returnType == 'object') {
+ return $menu;
+ } else {
+ return $menu->render();
+ }
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Hylax_Image Class
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * $Horde: incubator/hylax/lib/Image.php,v 1.14 2009/06/10 05:24:18 slusarz Exp $
+ *
+ * @author Marko Djukic <marko@oblo.com>
+ * @package Hylax
+ */
+class Hylax_Image {
+
+ var $_data;
+ var $_cmd;
+ var $_pages = array();
+
+ /**
+ * Constructor
+ *
+ * @param array $params Any parameters needed for this image driver.
+ */
+ function Hylax_Image()
+ {
+ $this->_cmd = array('identify' => '/usr/bin/identify',
+ 'convert' => '/usr/bin/convert',
+ 'ps2pdf' => '/usr/bin/ps2pdf14');
+ }
+
+ function loadData($data)
+ {
+ $this->_data = $data;
+ }
+
+ function getDimensions()
+ {
+ $tmp_file = Horde_Util::getTempFile('fax', true, '/tmp');
+ Horde::logMessage('Created temp file:' . Horde_Util::bufferOutput('var_dump', $tmp_file) . ':', __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ $fp = fopen($tmp_file, 'w');
+ fwrite($fp, $this->_data);
+ fclose($fp);
+
+ /* Run a ImageMagick identify command on the file to get the details. */
+ $command = sprintf('%s %s', $this->_cmd['identify'], $tmp_file);
+ Horde::logMessage('External command call by Hylax_Image::getDimensions(): :' . $command . ':', __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ exec($command, $output, $retval);
+
+ $init = strlen($tmp_file);
+
+ /* Figure out the dimensions from the output. */
+ Horde::logMessage('External command output by Hylax_Image::getDimensions(): ' . serialize($output), __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ foreach ($output as $key => $line) {
+ if (substr($line, 0, $init) != $tmp_file) {
+ continue;
+ }
+ $info = explode(' ', $line);
+ $dims = explode('+', $info[2]);
+ list($width, $height) = explode('x', $dims[0]);
+ $this->_pages[$key]['width'] = $width;
+ $this->_pages[$key]['height'] = $height;
+ }
+ }
+
+ function getNumPages()
+ {
+ if (empty($this->_pages)) {
+ $this->getDimensions();
+ }
+
+ return count($this->_pages);
+ }
+
+ function getImage($page, $preview = false)
+ {
+ $tmp_file = Horde_Util::getTempFile('fax', true, '/tmp');
+ $fp = fopen($tmp_file, 'wb');
+ fwrite($fp, $this->_data);
+ fclose($fp);
+
+ /* Set resize based on whether preview or not. */
+ $resize = ($preview) ? ' -resize 140x200!' : ' -resize 595x842!';
+
+ $tmp_file_out = Horde_Util::getTempFile('fax_preview', true, '/tmp');
+ /* Convert the page from the postscript file to PNG. */
+ $command = sprintf('%s%s %s[%s] png:%s',
+ $this->_cmd['convert'],
+ $resize,
+ $tmp_file,
+ $page,
+ $tmp_file_out);
+ Horde::logMessage('Executing command: ' . $command, __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ exec($command);
+ echo file_get_contents($tmp_file_out);
+ }
+
+ function getPDF()
+ {
+ $tmp_file = Horde_Util::getTempFile('fax', true, '/tmp');
+ $fp = fopen($tmp_file, 'wb');
+ fwrite($fp, $this->_data);
+ fclose($fp);
+
+ /* Convert the page from the postscript file to PDF. */
+ $command = sprintf('%s %s -', $this->_cmd['ps2pdf'], $tmp_file);
+ Horde::logMessage('Executing command: ' . $command, __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ passthru($command);
+ }
+
+ /**
+ * Attempts to return a concrete Hylax_Image instance based on $driver.
+ *
+ * @param string $driver The type of concrete Hylax_Image subclass to
+ * return.
+ * @param array $params A hash containing any additional configuration or
+ * connection parameters a subclass might need.
+ *
+ * @return Hylax_Image The newly created concrete Hylax_Image instance, or
+ * false on an error.
+ */
+ function &factory($driver, $params = array())
+ {
+ $driver = basename($driver);
+ include_once dirname(__FILE__) . '/Image/' . $driver . '.php';
+ $class = 'Hylax_Image_' . $driver;
+ if (class_exists($class)) {
+ $image = &new $class($params);
+ return $image;
+ } else {
+ Horde::fatal(PEAR::raiseError(sprintf(_("No such backend \"%s\" found"), $driver)), __FILE__, __LINE__);
+ }
+ }
+
+ /**
+ * Attempts to return a reference to a concrete Hylax_Image instance based
+ * on $driver.
+ *
+ * It will only create a new instance if no Hylax_Image instance with the
+ * same parameters currently exists.
+ *
+ * This should be used if multiple image sources are required.
+ *
+ * This method must be invoked as: $var = &Hylax_Image::singleton()
+ *
+ * @param string $driver The type of concrete Hylax_Image subclass to
+ * return.
+ * @param array $params A hash containing any additional configuration or
+ * connection parameters a subclass might need.
+ *
+ * @return mixed The created concrete Hylax_Image instance, or false on
+ * error.
+ */
+ function &singleton($driver, $params = array())
+ {
+ static $instances;
+
+ if (!isset($instances)) {
+ $instances = array();
+ }
+
+ $signature = serialize(array($driver, $params));
+ if (!isset($instances[$signature])) {
+ $instances[$signature] = &Hylax_Image::factory($driver, $params);
+ }
+
+ return $instances[$signature];
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * This class provides attributes methods for any existing SQL class.
+ *
+ * $Horde: incubator/hylax/lib/SQL/Attributes.php,v 1.5 2009/01/06 17:50:49 jan Exp $
+ *
+ * Copyright 1999-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ * @since Horde 2.2
+ * @package Hylax
+ */
+class Hylax_SQL_Attributes {
+
+ /**
+ * The PEAR::DB object to run queries with.
+ *
+ * @var DB
+ */
+ var $_db;
+
+ /**
+ * Parameters to use when generating queries:
+ * id_column - The primary id column to use in joins.
+ * primary_table - The main table name.
+ * attribute_table - The table that the attributes are stored in.
+ *
+ * @var array
+ */
+ var $_params = array();
+
+ /**
+ * The number of copies of the attributes table that we need to join on in
+ * the current query.
+ *
+ * @var integer
+ */
+ var $_table_count = 1;
+
+ /**
+ * Constructor.
+ *
+ * @param DB $dbh A PEAR::DB object.
+ * @param array $params The id column, table names, etc.
+ */
+ function Hylax_SQL_Attributes($dbh, $params)
+ {
+ $this->_db = $dbh;
+ $this->_params = $params;
+ }
+
+ /**
+ * Returns all attributes for a given id or multiple ids.
+ *
+ * @param integer | array $id The id to fetch or an array of ids.
+ *
+ * @return array A hash of attributes, or a multi-level hash
+ * of ids => their attributes.
+ */
+ function getAttributes($id)
+ {
+ if (is_array($id)) {
+ $query = sprintf('SELECT %1$s, attribute_name as name, attribute_key as "key", attribute_value as value FROM %2$s WHERE %1$s IN (%3$s)',
+ $this->_params['id_column'],
+ $this->_params['attribute_table'],
+ implode(', ', $id));
+
+ Horde::logMessage('SQL Query by Hylax_SQL_Attributes::getAttributes(): ' . $query, __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ $rows = $this->_db->getAll($query, DB_FETCHMODE_ASSOC);
+ if (is_a($rows, 'PEAR_Error')) {
+ return $rows;
+ }
+
+ $id_column = $this->_params['id_column'];
+ $data = array();
+ foreach ($rows as $row) {
+ if (empty($data[$row[$id_column]])) {
+ $data[$row[$id_column]] = array();
+ }
+ $data[$row[$id_column]][] = array('name' => $row['name'],
+ 'key' => $row['key'],
+ 'value' => $row['value']);
+ }
+ return $data;
+ } else {
+ $query = sprintf('SELECT %1$s, attribute_name as name, attribute_key as "key", attribute_value as value FROM %2$s WHERE %1$s = %3$s',
+ $this->_params['id_column'],
+ $this->_params['attribute_table'],
+ (int)$id);
+ Horde::logMessage('SQL Query by Hylax_SQL_Attributes::getAttributes(): ' . $query, __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ return $this->_db->getAll($query, DB_FETCHMODE_ASSOC);
+ }
+ }
+
+ /**
+ * Return a set of ids based on a set of attribute criteria.
+ *
+ * @param array $criteria The array of criteria. Example:
+ * $criteria['OR'] = array(
+ * array('field' => 'name',
+ * 'op' => '=',
+ * 'test' => 'foo'),
+ * array('field' => 'name',
+ * 'op' => '=',
+ * 'test' => 'bar'));
+ * This would return all ids for which the field
+ * attribute_name is either 'foo' or 'bar'.
+ */
+ function getByAttributes($criteria)
+ {
+ if (!count($criteria)) {
+ return array();
+ }
+
+ /* Build the query. */
+ $this->_table_count = 1;
+ $query = '';
+ foreach ($criteria as $key => $vals) {
+ if ($key == 'OR' || $key == 'AND') {
+ if (!empty($query)) {
+ $query .= ' ' . $key . ' ';
+ }
+ $query .= '(' . $this->_buildAttributeQuery($key, $vals) . ')';
+ }
+ }
+
+ /* Build the FROM/JOIN clauses. */
+ $joins = array();
+ $pairs = array();
+ for ($i = 1; $i <= $this->_table_count; $i++) {
+ $joins[] = sprintf('LEFT JOIN %1$s a%2$s ON a%2$s.%3$s = m.%3$s',
+ $this->_params['attribute_table'],
+ $i,
+ $this->_params['id_column']);
+
+ $pairs[] = 'AND a1.attribute_name = a' . $i . '.attribute_name';
+ }
+ $joins = implode(' ', $joins);
+ $pairs = implode(' ', $pairs);
+
+ $query = sprintf('SELECT DISTINCT a1.%s FROM %s m %s WHERE %s %s',
+ $this->_params['id_column'],
+ $this->_params['primary_table'],
+ $joins,
+ $query,
+ $pairs);
+
+ Horde::logMessage('SQL Query by Hylax_SQL_Attributes::getByAttributes(): ' . $query, __FILE__, __LINE__, PEAR_LOG_DEBUG);
+
+ return $this->_db->getCol($query);
+ }
+
+ /**
+ * Given a new attribute set and an id, insert each into the DB. If
+ * anything fails in here, rollback the transaction, return the relevant
+ * error and bail out.
+ *
+ * @param integer $id The id of the record for which attributes are
+ * being inserted.
+ * @param array $attributes An hash containing the attributes.
+ */
+ function insertAttributes($id, $attributes)
+ {
+ foreach ($attributes as $attr) {
+ $query = 'INSERT INTO ' . $this->_params['attribute_table'] .
+ ' (' . $this->_params['id_column'] . ', attribute_name,' .
+ ' attribute_key, attribute_value) VALUES (?, ?, ?, ?)';
+ $values = array((int)$id,
+ $attr['name'],
+ $attr['key'],
+ $attr['value']);
+
+ Horde::logMessage('SQL Query by Hylax_SQL_Attributes::insertAttributes(): ' . $query, __FILE__, __LINE__, PEAR_LOG_DEBUG);
+
+ $result = $this->_db->query($query, $values);
+ if (is_a($result, 'PEAR_Error')) {
+ $this->_db->rollback();
+ $this->_db->autoCommit(true);
+ return $result;
+ }
+ }
+
+ /* Commit the transaction, and turn autocommit back on. */
+ $result = $this->_db->commit();
+ $this->_db->autoCommit(true);
+ }
+
+ /**
+ * Given an id, delete all attributes for that id from the
+ * attributes table.
+ *
+ * @param integer $id The id of the record for which attributes are being
+ * deleted.
+ */
+ function deleteAttributes($id)
+ {
+ /* Delete attributes. */
+ $query = sprintf('DELETE FROM %s WHERE %s = %s',
+ $this->_params['attribute_table'],
+ $this->_params['id_column'],
+ (int)$id);
+
+ Horde::logMessage('SQL Query by Hylax_SQL_Attributes::deleteAttributes(): ' . $query, __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ $result = $this->_db->query($query);
+ if (is_a($result, 'PEAR_Error')) {
+ return $result;
+ }
+
+ return true;
+ }
+
+ /**
+ * Given an id, update all attributes for that id in the attributes table
+ * with the new attributes.
+ *
+ * @param integer $id The id of the record for which attributes are
+ * being deleted.
+ * @param array $attributes An hash containing the attributes.
+ */
+ function updateAttributes($id, $attributes)
+ {
+ /* Delete the old attributes. */
+ $result = $this->deleteAttributes($id);
+ if (is_a($result, 'PEAR_Error')) {
+ return $result;
+ }
+
+ /* Insert the new attribute set. */
+ $result = $this->insertAttributes($id, $attributes);
+ return $result;
+ }
+
+ /**
+ * Build a piece of an attribute query.
+ *
+ * @param string $glue The glue to join the criteria (OR/AND).
+ * @param array $criteria The array of criteria.
+ * @param boolean $join Should we join on a clean attributes table?
+ *
+ * @return string An SQL fragment.
+ */
+ function _buildAttributeQuery($glue, $criteria, $join = false)
+ {
+ require_once 'Horde/SQL.php';
+
+ /* Initialize the clause that we're building. */
+ $clause = '';
+
+ /* Get the table alias to use for this set of criteria. */
+ if ($join) {
+ $alias = $this->_getAlias(true);
+ } else {
+ $alias = $this->_getAlias();
+ }
+
+ foreach ($criteria as $key => $vals) {
+ if (!empty($vals['OR']) || !empty($vals['AND'])) {
+ if (!empty($clause)) {
+ $clause .= ' ' . $glue . ' ';
+ }
+ $clause .= '(' . $this->_buildAttributeQuery($glue, $vals) . ')';
+ } elseif (!empty($vals['JOIN'])) {
+ if (!empty($clause)) {
+ $clause .= ' ' . $glue . ' ';
+ }
+ $clause .= $this->_buildAttributeQuery($glue, $vals['JOIN'], true);
+ } else {
+ if (isset($vals['field'])) {
+ if (!empty($clause)) {
+ $clause .= ' ' . $glue . ' ';
+ }
+ $clause .= Horde_SQL::buildClause($this->_db, $alias . '.attribute_' . $vals['field'], $vals['op'], $vals['test']);
+ } else {
+ foreach ($vals as $test) {
+ if (!empty($clause)) {
+ $clause .= ' ' . $key . ' ';
+ }
+ $clause .= Horde_SQL::buildClause($this->_db, $alias . '.attribute_' . $test['field'], $test['op'], $test['test']);
+ }
+ }
+ }
+ }
+
+ return $clause;
+ }
+
+ /**
+ * Get an alias to an attributes table, incrementing it if
+ * necessary.
+ *
+ * @param boolean $increment Increment the alias count? Defaults to false.
+ */
+ function _getAlias($increment = false)
+ {
+ static $seen = array();
+
+ if ($increment && !empty($seen[$this->_table_count])) {
+ $this->_table_count++;
+ }
+
+ $seen[$this->_table_count] = true;
+ return 'a' . $this->_table_count;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Hylax_Storage Class
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * $Horde: incubator/hylax/lib/Storage.php,v 1.16 2009/01/06 17:50:48 jan Exp $
+ *
+ * @author Marko Djukic <marko@oblo.com>
+ * @package Hylax
+ */
+class Hylax_Storage {
+
+ /**
+ * A hash containing any parameters for the current storage driver.
+ *
+ * @var array
+ */
+ var $_params = array();
+
+ /**
+ * @var VFS
+ */
+ var $_vfs;
+
+ /**
+ * Constructor
+ *
+ * @param array $params Any parameters needed for this storage driver.
+ */
+ function Hylax_Storage($params)
+ {
+ global $conf;
+
+ $this->_params = $params;
+
+ /* Set up the VFS storage. */
+ if (!isset($conf['vfs']['type'])) {
+ Horde::fatal(_("You must configure a VFS backend to use Hylax."), __FILE__, __LINE__);
+ }
+ $vfs_driver = $conf['vfs']['type'];
+ $vfs_params = Horde::getDriverConfig('vfs', $vfs_driver);
+ require_once 'VFS.php';
+ $this->_vfs = &VFS::singleton($vfs_driver, $vfs_params);
+ }
+
+ function saveFaxData($data, $type = '.ps')
+ {
+ /* Get the next ID. */
+ $fax_id = $this->newFaxId();
+ if (is_a($fax_id, 'PEAR_Error')) {
+ return $fax_id;
+ }
+
+ /* Save data to VFS backend. */
+ $path = Hylax::getVFSPath($fax_id);
+ $file = $fax_id . $type;
+ $saved = $this->_vfs->writeData($path, $file, $data, true);
+ if (is_a($saved, 'PEAR_Error')) {
+ Horde::logMessage('Could not save fax file to VFS: ' . $saved->getMessage(), __FILE__, __LINE__, PEAR_LOG_ERR);
+ return $saved;
+ }
+ return $fax_id;
+ }
+
+ function createFax($info, $fix_owner = false)
+ {
+ /* In case this is just a fax creation without yet a number assigned
+ * create an empty number. */
+ if (!isset($info['fax_number'])) {
+ $info['fax_number'] = '';
+ }
+
+ /* Set the folder. */
+ $info['fax_folder'] = ($info['fax_type']) ? 'outbox' : 'inbox';
+
+ /* Set timestamp. */
+ if (empty($info['fax_created'])) {
+ $info['fax_created'] = time();
+ }
+
+ $data = $this->getFaxData($info['fax_id']);
+ if (is_a($data, 'PEAR_Error')) {
+ Horde::logMessage('Could not get fax data: ' . $data->getMessage(), __FILE__, __LINE__, PEAR_LOG_ERR);
+ return $data;
+ }
+
+ /* Create a fax image object. */
+ require_once HYLAX_BASE . '/lib/Image.php';
+ $image = &new Hylax_Image();
+ $image->loadData($data);
+ if (empty($info['fax_pages'])) {
+ $info['fax_pages'] = $image->getNumPages();
+ }
+
+ /* Save to backend. */
+ $result = $this->_createFax($info);
+ if (is_a($result, 'PEAR_Error')) {
+ return $result;
+ }
+ global $conf;
+ foreach ($conf['fax']['notify'] as $rec) {
+ mail($rec, _("New fax from: ") . $info['fax_number'], '',
+ 'From: '. $conf['fax']['notifyfrom']);
+ }
+ return true;
+ }
+
+ function getFaxData($fax_id)
+ {
+ $path = Hylax::getVFSPath($fax_id);
+ $file = $fax_id . '.ps';
+ $data = $this->_vfs->read($path, $file);
+ if (is_a($data, 'PEAR_Error')) {
+ Horde::logMessage(sprintf("%s '%s/%s'.", $data->getMessage(), $path, $file), __FILE__, __LINE__, PEAR_LOG_ERR);
+ }
+ return $data;
+ }
+
+ function listFaxes($folder)
+ {
+ return $this->_listFaxes($folder);
+ }
+
+ function send($fax_id, $number)
+ {
+ global $conf, $gateway;
+
+ $this->_setFaxNumber($fax_id, $number);
+
+ $data = $this->getFaxData($fax_id);
+
+ $job_id = $gateway->send($number, $data);
+
+ $this->_setJobId($fax_id, $job_id);
+ }
+
+ /**
+ * Attempts to return a concrete Hylax_Storage instance based on $driver.
+ *
+ * @param string $driver The type of concrete Hylax_Storage subclass to
+ * return.
+ * @param array $params A hash containing any additional configuration or
+ * connection parameters a subclass might need.
+ *
+ * @return Hylax_Storage The newly created concrete Hylax_Storage
+ * instance, or false on error.
+ */
+ function &factory($driver, $params = array())
+ {
+ $driver = basename($driver);
+ include_once dirname(__FILE__) . '/Storage/' . $driver . '.php';
+ $class = 'Hylax_Storage_' . $driver;
+ if (class_exists($class)) {
+ $storage = &new $class($params);
+ return $storage;
+ } else {
+ Horde::fatal(PEAR::raiseError(sprintf(_("No such backend \"%s\" found"), $driver)), __FILE__, __LINE__);
+ }
+ }
+
+ /**
+ * Attempts to return a reference to a concrete Hylax_Storage instance
+ * based on $driver.
+ *
+ * It will only create a new instance if no Hylax_Storage instance with the
+ * same parameters currently exists.
+ *
+ * This should be used if multiple storage sources are required.
+ *
+ * This method must be invoked as: $var = &Hylax_Storage::singleton()
+ *
+ * @param string $driver The type of concrete Hylax_Storage subclass to
+ * return.
+ * @param array $params A hash containing any additional configuration or
+ * connection parameters a subclass might need.
+ *
+ * @return mixed The created concrete Hylax_Storage instance, or false on
+ * error.
+ */
+ function &singleton($driver, $params = array())
+ {
+ static $instances;
+
+ if (!isset($instances)) {
+ $instances = array();
+ }
+
+ $signature = serialize(array($driver, $params));
+ if (!isset($instances[$signature])) {
+ $instances[$signature] = &Hylax_Storage::factory($driver, $params);
+ }
+
+ return $instances[$signature];
+ }
+
+}
--- /dev/null
+<?php
+
+require_once HYLAX_BASE . '/lib/SQL/Attributes.php';
+
+/**
+ * Hylax_Storage_sql Class
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * $Horde: incubator/hylax/lib/Storage/sql.php,v 1.21 2009/07/08 18:29:13 slusarz Exp $
+ *
+ * @author Marko Djukic <marko@oblo.com>
+ * @package Hylax
+ */
+class Hylax_Storage_sql extends Hylax_Storage {
+
+ /**
+ * Handle for the database connection.
+ *
+ * @var DB
+ */
+ var $_db;
+
+ /**
+ * @var Hylax_SQL_Attributes
+ */
+ var $_attributes;
+
+ function Hylax_Storage_sql($params)
+ {
+ parent::Hylax_Storage($params);
+ $this->initialise();
+
+ /* Set up the storage attributes object in the $_attributes var. */
+ $attrib_params = array('primary_table' => 'hylax_faxes',
+ 'attribute_table' => 'hylax_fax_attributes',
+ 'id_column' => 'fax_id');
+ $this->_attributes = new Hylax_SQL_Attributes($this->_db, $attrib_params);
+ }
+
+ function newFaxId()
+ {
+ $id = $this->_db->nextId('hylax_faxes');
+ if (is_a($id, 'PEAR_Error')) {
+ Horde::logMessage('Could not generate new fax id. %s' . $id->getMessage(), __FILE__, __LINE__, PEAR_LOG_ERR);
+ } else {
+ Horde::logMessage('Generated new fax id: ' . $id, __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ }
+ return $id;
+ }
+
+ function _createFax(&$info)
+ {
+ /* Save to SQL. */
+ $sql = 'INSERT INTO hylax_faxes (fax_id, fax_type, fax_user, fax_number, fax_pages, fax_created, fax_folder) VALUES (?, ?, ?, ?, ?, ?, ?)';
+ $values = array($info['fax_id'],
+ (int)$info['fax_type'],
+ $info['fax_user'],
+ $info['fax_number'],
+ $info['fax_pages'],
+ $info['fax_created'],
+ $info['fax_folder']);
+ Horde::logMessage('SQL Query by Hylax_Storage_sql::_createFax(): ' . $sql, __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ $result = $this->_db->query($sql, $values);
+ if (is_a($result, 'PEAR_Error')) {
+ Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
+ }
+ return $result;
+ }
+
+ function _listFaxes($folder)
+ {
+ $sql = 'SELECT * FROM hylax_faxes WHERE fax_folder = ?';
+ $values = array($folder);
+ $faxes = $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC);
+ return $faxes;
+ }
+
+ function getFax($fax_id)
+ {
+ $sql = 'SELECT * FROM hylax_faxes WHERE fax_id = ?';
+ $values = array($fax_id);
+ $fax = $this->_db->getRow($sql, $values, DB_FETCHMODE_ASSOC);
+ if (empty($fax)) {
+ return PEAR::raiseError(_("No such fax found."));
+ }
+ return $fax;
+ }
+
+ function getFaxFolder($fax_id)
+ {
+ $sql = 'SELECT fax_folder FROM hylax_faxes WHERE fax_id = ?';
+ $values = array($fax_id);
+ $fax_folder = $this->_db->getOne($sql, $values);
+ if (empty($fax_folder)) {
+ return PEAR::raiseError(_("No such fax found."));
+ }
+ return $fax_folder;
+ }
+
+ function _setFaxNumber($fax_id, $number)
+ {
+ $sql = 'UPDATE hylax_faxes SET fax_number = ? WHERE fax_id = ?';
+ $values = array($number, (int)$fax_id);
+ return $this->_db->query($sql, $values);
+ }
+
+ function _setJobId($fax_id, $job_id)
+ {
+ $sql = 'UPDATE hylax_faxes SET job_id = ? WHERE fax_id = ?';
+ $values = array((int)$job_id, (int)$fax_id);
+ return $this->_db->query($sql, $values);
+ }
+
+ function _getFolder($folder, $path = null)
+ {
+ switch ($folder) {
+ case 'inbox':
+ //return $this->_parseFaxStat($this->_exec('faxstat -r'));
+ break;
+
+ case 'outbox':
+ return $this->_parseFaxStat($this->_exec('faxstat -s'));
+ break;
+
+ case 'archive':
+ //return $GLOBALS['storage']->getFolder($path);
+ break;
+ }
+ }
+
+ /**
+ * Fetches a list of available gateways.
+ *
+ * @return array An array of the available gateways.
+ */
+ function getGateways()
+ {
+ /* Get the gateways. */
+ $sql = 'SELECT * FROM swoosh_gateways';
+ Horde::logMessage('SQL Query by Hylax_Storage_sql::_getGateways(): ' . $sql, __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ $result = $this->_db->getAll($sql, DB_FETCHMODE_ASSOC);
+ if (is_a($result, 'PEAR_Error')) {
+ Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Fetches a gateway from the backend.
+ *
+ * @param int $gateway_id The gateway id to fetch.
+ *
+ * @return array An array containing the gateway settings and parameters.
+ */
+ function &getGateway($gateway_id)
+ {
+ /* Get the gateways. */
+ $sql = 'SELECT * FROM swoosh_gateways WHERE gateway_id = ?';
+ $values = array((int)$gateway_id);
+ Horde::logMessage('SQL Query by Hylax_Storage_sql::getGateway(): ' . $sql, __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ $gateway = $this->_db->getRow($sql, $values, DB_FETCHMODE_ASSOC);
+ if (is_a($gateway, 'PEAR_Error')) {
+ Horde::logMessage($gateway, __FILE__, __LINE__, PEAR_LOG_ERR);
+ return $gateway;
+ }
+
+ /* Unserialize the gateway params. */
+ require_once 'Horde/Serialize.php';
+ $gateway['gateway_params'] = Horde_Serialize::unserialize($gateway['gateway_params'], Horde_Serialize::UTF7_BASIC);
+
+ /* Unserialize the gateway send params. */
+ $gateway['gateway_sendparams'] = Horde_Serialize::unserialize($gateway['gateway_sendparams'], Horde_Serialize::UTF7_BASIC);
+
+ return $gateway;
+ }
+
+ /**
+ * Saves a gateway to the backend.
+ *
+ * @param array $info The gateway settings to be saved passed by reference
+ * as an array.
+ *
+ * @return mixed Gateway id on success or a PEAR error on failure.
+ */
+ function saveGateway(&$info)
+ {
+ if (empty($info['gateway_id'])) {
+ /* No existing gateway id, so new gateway and get next id. */
+ $info['gateway_id'] = $this->_db->nextId('swoosh_gateways');
+ if (is_a($info['gateway_id'], 'PEAR_Error')) {
+ Horde::logMessage($info['gateway_id'], __FILE__, __LINE__, PEAR_LOG_ERR);
+ return $info['gateway_id'];
+ }
+ $sql = 'INSERT INTO swoosh_gateways (gateway_id, gateway_driver, gateway_name, gateway_params, gateway_sendparams) VALUES (?, ?, ?, ?, ?)';
+ $values = array();
+ } else {
+ /* Existing gateway id, so editing an existing gateway. */
+ $sql_sprintf = 'UPDATE swoosh_gateways SET gateway_id = ?, gateway_driver = ?, gateway_name = ?, gateway_params = ?, gateway_sendparams = ? WHERE gateway_id = ?';
+ $values = array((int)$info['gateway_id']);
+ }
+
+ /* Serialize the gateway params. */
+ require_once 'Horde/Serialize.php';
+ if (!empty($info['gateway_params'])) {
+ $info['gateway_params'] = Horde_Serialize::serialize($info['gateway_params'], Horde_Serialize::UTF7_BASIC);
+ } else {
+ $info['gateway_params'] = 'NULL';
+ }
+
+ /* Serialize the gateway send params. */
+ if (!empty($info['gateway_sendparams'])) {
+ $info['gateway_sendparams'] = Horde_Serialize::serialize($info['gateway_sendparams'], Horde_Serialize::UTF7_BASIC);
+ } else {
+ $info['gateway_sendparams'] = 'NULL';
+ }
+
+ /* Put together the sql statement. */
+ array_unshift($values,
+ (int)$info['gateway_id'],
+ $info['gateway_driver'],
+ $info['gateway_name'],
+ $info['gateway_params'],
+ $info['gateway_sendparams']);
+ Horde::logMessage('SQL Query by Hylax_Storage_sql::saveGateway(): ' . $sql, __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ $result = $this->_db->query($sql, $values);
+ if (is_a($result, 'PEAR_Error')) {
+ Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
+ return $result;
+ }
+
+ return $info['gateway_id'];
+ }
+
+ /**
+ * Deletes a gateway from the backend.
+ *
+ * @param int $gateway_id The gateway id of the gateway to delete.
+ *
+ * @return mixed True on success or a PEAR error on failure.
+ */
+ function deleteGateway($gateway_id)
+ {
+ $sql = 'DELETE FROM swoosh_gateways WHERE gateway_id = ?';
+ $values = array((int)$gateway_id);
+ Horde::logMessage('SQL Query by Hylax_Storage_sql::deleteGateway(): ' . $sql, __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ $result = $this->_db->query($sql, $values);
+ if (is_a($result, 'PEAR_Error')) {
+ Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Saves a message to the backend.
+ *
+ * @param integer $gateway_id The id of the gateway used to send this
+ * message.
+ * @param string $message_text The text of the message.
+ * @param string $message_params Any send params used for this message.
+ * @param string $message_batch_id If batch sending is used, the batch id
+ * of this message.
+ *
+ * @return mixed True on success or PEAR Error on failure.
+ */
+ function saveMessage($gateway_id, $message_text, $message_params, $message_batch_id = null)
+ {
+ $message_id = $this->_db->nextId('swoosh_messages');
+ if (is_a($message_id, 'PEAR_Error')) {
+ Horde::logMessage($message_id, __FILE__, __LINE__, PEAR_LOG_ERR);
+ return $message_id;
+ }
+
+ /* Serialize the message params. */
+ require_once 'Horde/Serialize.php';
+ $message_params = Horde_Serialize::serialize($message_params, Horde_Serialize::UTF7_BASIC);
+
+ $sql = 'INSERT INTO swoosh_messages (message_id, user_uid, gateway_id, message_batch_id, message_text, message_params, message_submitted) VALUES (?, ?, ?, ?, ?, ?, ?)';
+ $values = array((int)$message_id,
+ Horde_Auth::getAuth(),
+ (int)$gateway_id,
+ is_null($message_batch_id) ? 'NULL' : (int)$message_batch_id,
+ $message_text,
+ $message_params,
+ (int)time());
+ $result = $this->_db->query($sql, $values);
+ if (is_a($result, 'PEAR_Error')) {
+ Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
+ return $result;
+ }
+
+ return $message_id;
+ }
+
+ /**
+ * Saves an individual send to the backend. This will be one instance of
+ * a message being sent to a recipient.
+ *
+ * @param int $message_id The message id.
+ * @param string $remote_id The text of the message.
+ * @param string $recipient Any send params used for this
+ * @param string $error Any send params used for this
+ *
+ * @return mixed The send id on success or PEAR Error on failure.
+ */
+ function saveSend($message_id, $remote_id, $recipient, $error)
+ {
+ $send_id = $this->_db->nextId('swoosh_sends');
+ if (is_a($send_id, 'PEAR_Error')) {
+ Horde::logMessage($send_id, __FILE__, __LINE__, PEAR_LOG_ERR);
+ return $send_id;
+ }
+ $sql = 'INSERT INTO swoosh_sends (send_id, message_id, send_remote_id, send_recipient, send_status) VALUES (?, ?, ?, ?, ?)';
+ $values = array($send_id,
+ $message_id,
+ (is_null($remote_id) ? 'NULL' : $remote_id),
+ $recipient,
+ (is_null($error) ? 'NULL' : $error));
+ $result = $this->_db->query($sql, $values);
+ if (is_a($result, 'PEAR_Error')) {
+ Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
+ return $result;
+ }
+
+ return $send_id;
+ }
+
+ /**
+ * Gets all the messages for the current user.
+ *
+ * @access private
+ *
+ * @return mixed The array of messages on success or PEAR Error on failure.
+ */
+ function _getMessages()
+ {
+ $sql = 'SELECT * FROM swoosh_messages WHERE user_uid = ?';
+ $values = array(Horde_Auth::getAuth());
+ Horde::logMessage('SQL Query by Hylax_Storage_sql::_getMessages(): ' . $sql, __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ $result = $this->_db->getAssoc($sql, false, $values, DB_FETCHMODE_ASSOC);
+ if (is_a($result, 'PEAR_Error')) {
+ Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Fetches all sends for one or more message ids.
+ *
+ * @access private
+ * @param int|array $message_id The message id(s).
+ *
+ * @return mixed The send id on success or PEAR Error on failure.
+ */
+ function _getSends($message_ids)
+ {
+ if (!is_array($message_ids)) {
+ $message_ids = array($message_ids);
+ }
+
+ $sql = 'SELECT message_id, swoosh_sends.* FROM swoosh_sends' .
+ ' WHERE message_id IN (' . str_repeat('?, ', count($message_ids) - 1) . '?)';
+ $values = $message_ids;
+ Horde::logMessage('SQL Query by Hylax_Storage_sql::_getSends(): ' . $sql, __FILE__, __LINE__, PEAR_LOG_DEBUG);
+ $result = $this->_db->getAssoc($sql, false, $values, DB_FETCHMODE_ASSOC, true);
+ if (is_a($result, 'PEAR_Error')) {
+ Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
+ }
+
+ return $result;
+ }
+
+ function initialise()
+ {
+ global $registry;
+
+ Horde::assertDriverConfig($this->_params, 'sql',
+ array('phptype'));
+
+ if (!isset($this->_params['database'])) {
+ $this->_params['database'] = '';
+ }
+ if (!isset($this->_params['username'])) {
+ $this->_params['username'] = '';
+ }
+ if (!isset($this->_params['hostspec'])) {
+ $this->_params['hostspec'] = '';
+ }
+
+ /* Connect to the SQL server using the supplied parameters. */
+ require_once 'DB.php';
+ $this->_db = &DB::connect($this->_params,
+ array('persistent' => !empty($this->_params['persistent'])));
+ if (is_a($this->_db, 'PEAR_Error')) {
+ Horde::fatal($this->_db, __FILE__, __LINE__);
+ }
+
+ // Set DB portability options
+ switch ($this->_db->phptype) {
+ case 'mssql':
+ $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS | DB_PORTABILITY_RTRIM);
+ break;
+ default:
+ $this->_db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS);
+ }
+
+ return true;
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * Hylax base inclusion file.
+ *
+ * This file brings in all of the dependencies that every Hylax script will
+ * need, and sets up objects that all scripts use.
+ *
+ * Copyright 2003-2009 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * $Horde: incubator/hylax/lib/base.php,v 1.16 2009/07/13 20:05:46 slusarz Exp $
+ */
+
+// Check for a prior definition of HORDE_BASE (perhaps by an
+// auto_prepend_file definition for site customization).
+if (!defined('HORDE_BASE')) {
+ @define('HORDE_BASE', dirname(__FILE__) . '/../..');
+}
+
+// Load the Horde Framework core, and set up inclusion paths.
+require_once HORDE_BASE . '/lib/core.php';
+
+// Registry.
+$registry = Horde_Registry::singleton();
+try {
+ $registry->pushApp('hylax', !defined('AUTH_HANDLER'));
+} catch (Horde_Exception $e) {
+ if ($e->getCode() == 'permission_denied') {
+ Horde::authenticationFailureRedirect();
+ }
+ Horde::fatal($e, __FILE__, __LINE__, false);
+}
+
+$conf = &$GLOBALS['conf'];
+@define('HYLAX_TEMPLATES', $registry->get('templates'));
+
+/* Notification system. */
+$notification = &Horde_Notification::singleton();
+$notification->attach('status');
+
+/* Find the base file path of Hylax. */
+@define('HYLAX_BASE', dirname(__FILE__) . '/..');
+
+/* Hylax base libraries. */
+require_once HYLAX_BASE . '/lib/Hylax.php';
+require_once HYLAX_BASE . '/lib/Driver.php';
+require_once HYLAX_BASE . '/lib/Storage.php';
+
+/* Hylax Driver */
+$gateway = &Hylax_Driver::singleton($conf['fax']['driver'], $conf['fax']['params']);
+
+/* Hylax storage driver. */
+$hylax_storage = &Hylax_Storage::singleton('sql', $conf['sql']);
+
+/* Start compression, if requested. */
+Horde::compressOutput();
--- /dev/null
+<?php define('HYLAX_VERSION', '0.1-cvs') ?>
--- /dev/null
+<?php
+/**
+ * The Hylax script to show a fax view.
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * $Horde: incubator/hylax/print.php,v 1.5 2009/06/10 05:24:17 slusarz Exp $
+ */
+
+@define('HYLAX_BASE', dirname(__FILE__));
+require_once HYLAX_BASE . '/lib/base.php';
+
+$fax_id = Horde_Util::getFormData('fax_id');
+$url = Horde_Util::getFormData('url', 'folder.php');
+$print = Hylax::printFax($fax_id);
+if (is_a($print, 'PEAR_Error')) {
+ $notification->push(sprintf(_("Could not print fax ID \"%s\". %s"), $fax_id, $print->getMessage()), 'horde.error');
+} else {
+ $notification->push(sprintf(_("Printed fax ID \"%s\"."), $fax_id), 'horde.success');
+}
+
+/* Redirect back. */
+$url = Horde::applicationUrl($url, true);
+header('Location: ' . $url);
+exit;
--- /dev/null
+Deny from all
--- /dev/null
+# This is a hylafax configuration file to override the server one.
+JobFmt: "%j|%a|%o|%e|%P|%D|%z|%s"
--- /dev/null
+#!/bin/bash
+# This should go into the /usr/lib/cups/backend directory to allow the fax to
+# be set up as a regular printer for cups.
+
+SCRIPT_DIR="__SCRIPT_DIR__"
+
+# Nothing to see below.
+DATA_SCRIPT="fax_save_data.php"
+FAX_SCRIPT="fax_create.php"
+FAX_USER=$2
+DATA=$6
+
+# Called with no arguments, we list the provided HylaFAX backend
+# (serial devices are irrelevant here).
+if [ $# -eq 0 ]; then
+ echo "direct hylafax:/local \"Unknown\" \"Local HylaFAX server\""
+ exit 0
+fi
+
+# Call using sudo so that VFS creates correctly owned directories for web use.
+if [ -n $DATA ]; then
+ # The spool filename has been passed, cat the contents to the data script.
+ FAX_ID=`cat $DATA|sudo -u __WWW_USER__ $SCRIPT_DIR/$DATA_SCRIPT`
+else
+ # No spool filename, use what comes through on STDIN.
+ FAX_ID=`sudo -u __WWW_USER__ $SCRIPT_DIR/$DATA_SCRIPT`
+fi
+
+# Call the fax creation script to create a stub in the DB for this new data.
+$SCRIPT_DIR/$FAX_SCRIPT $FAX_ID $FAX_USER
--- /dev/null
+*PPD-Adobe: "4.3"
+*FormatVersion: "4.3"
+*FileVersion: "1.0"
+*LanguageVersion: English
+*LanguageEncoding: ISOLatin1
+*PCFileName: "HYLAFAX.PPD"
+*Manufacturer: "HylaFAX"
+*Product: "HylaFAX"
+*cupsFax: True
+*cupsFilter: "application/vnd.cups-postscript 0 -"
+*cupsVersion: 1.1
+*cupsManualCopies: True
+*ModelName: "HylaFAX"
+*ShortNickName: "HylaFAX"
+*NickName: "HylaFAX"
+*PSVersion: "(3010.000) 550"
+*LanguageLevel: "3"
+*ColorDevice: False
+*FaxSupport: Base
+*FileSystem: False
+*Throughput: "1"
+*TTRasterizer: Type42
+*LandscapeOrientation: Plus90
+*VariablePaperSize: False
+
+*OpenUI *Resolution/Fax Resolution: PickOne
+*OrderDependency: 10 AnySetup *Resolution
+*DefaultResolution: 204x196dpi
+*Resolution 204x196dpi/204×196 dpi (high resolution): ""
+*Resolution 204x98dpi/204×98 dpi (low resolution): ""
+*CloseUI: *Resolution
+
+*OpenUI *PageSize/Media Size: PickOne
+*OrderDependency: 0 AnySetup *PageSize
+*DefaultPageSize: A4
+*PageSize A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageSize Letter/US Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageSize Legal/US Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+*CloseUI: *PageSize
+
+*DefaultPageRegion: A4
+*PageRegion A4/A4: "<</PageSize[595 842]/ImagingBBox null>>setpagedevice"
+*PageRegion Letter/US Letter: "<</PageSize[612 792]/ImagingBBox null>>setpagedevice"
+*PageRegion Legal/US Legal: "<</PageSize[612 1008]/ImagingBBox null>>setpagedevice"
+
+*DefaultImageableArea: A4
+
+*DefaultPaperDimension: A4
+*PaperDimension A4: "595 842"
+*PaperDimension Letter: "612 792"
+*PaperDimension Legal: "612 1008"
+
+*OpenUI *Dial/Dial Method: PickOne
+*OrderDependency: 30 AnySetup *Dial
+*DefaultDial: JobName
+*Dial JobName/Job Name: ""
+*Dial Manually/Manually: ""
+*Dial Option/Option (obsolete): ""
+*CloseUI: *Dial
+
+*DefaultFont: Courier
+*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
+*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
+*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
+*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
+*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
+*Font Bookman-Light: Standard "(001.004S)" Standard ROM
+*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
+*Font Courier: Standard "(002.004S)" Standard ROM
+*Font Courier-Bold: Standard "(002.004S)" Standard ROM
+*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
+*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
+*Font Helvetica: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
+*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
+*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
+*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
+*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
+*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
+*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
+*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
+*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
+*Font Symbol: Special "(001.007S)" Special ROM
+*Font Times-Bold: Standard "(001.007S)" Standard ROM
+*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
+*Font Times-Italic: Standard "(001.007S)" Standard ROM
+*Font Times-Roman: Standard "(001.007S)" Standard ROM
+*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
+
+*% What follows is a pseudo-Foomatic driver to enable graphical
+*% specification of the phone number. Only the phone number is listed
+*% as option. It won't be used by Foomatic anyway.
+*%
+*% COMDATA #$VAR1 = {
+*% COMDATA # 'args_byname' => {
+*% COMDATA # 'phone' => {
+*% COMDATA # 'name' => 'phone',
+*% COMDATA # 'type' => 'string',
+*% COMDATA # 'comment' => 'Target Fax Number',
+*% COMDATA # 'default' => ''
+*% COMDATA # }
+*% COMDATA # },
+*% COMDATA # 'model' => 'HylaFaxmodem',
+*% COMDATA # 'comment' => 'HylaFaxmodem driver',
+*% COMDATA # 'make' => 'HylaFaxmodem',
+*% COMDATA # 'color' => '0'
+*% COMDATA #};
+
--- /dev/null
+#!/usr/bin/php
+<?php
+/**
+ * $Horde: incubator/hylax/scripts/fax_create.php,v 1.4 2009/06/10 19:57:57 slusarz Exp $
+ */
+
+// No need for auth.
+@define('AUTH_HANDLER', true);
+
+// Find the base file paths.
+@define('HORDE_BASE', dirname(__FILE__) . '/../..');
+@define('HYLAX_BASE', dirname(__FILE__) . '/..');
+
+// Do CLI checks and environment setup first.
+require_once HYLAX_BASE . '/lib/base.php';
+require_once 'Console/Getopt.php';
+
+// Make sure no one runs this from the web.
+if (!Horde_Cli::runningFromCLI()) {
+ exit("Must be run from the command line\n");
+}
+
+/* Load the CLI environment - make sure there's no time limit, init
+ * some variables, etc. */
+$cli = &new Horde_Cli();
+$cli->init();
+
+/* Create the fax information array. Set fax_type to 1 for outgoing. */
+$info = array('fax_type' => 1);
+
+/* Get the arguments. The third argument is the user submitting the job, used
+ * to differentiate jobs between users.*/
+$args = Console_Getopt::readPHPArgv();
+if (isset($args[1])) {
+ $info['fax_id'] = $args[1];
+}
+if (isset($args[2])) {
+ $info['fax_user'] = $args[2];
+}
+Horde::logMessage(sprintf('Creating fax ID %s for user %s.', $info['fax_id'], $info['fax_user']), __FILE__, __LINE__, PEAR_LOG_DEBUG);
+
+$hylax_storage->createFax($info, true);
--- /dev/null
+#!/usr/bin/php
+<?php
+/**
+ * $Horde: incubator/hylax/scripts/fax_create_recv.php,v 1.4 2009/06/10 19:57:57 slusarz Exp $
+ */
+
+// No need for auth.
+@define('AUTH_HANDLER', true);
+
+// Find the base file paths.
+@define('HORDE_BASE', dirname(__FILE__) . '/../..');
+@define('HYLAX_BASE', dirname(__FILE__) . '/..');
+
+// Do CLI checks and environment setup first.
+require_once HYLAX_BASE . '/lib/base.php';
+require_once 'Console/Getopt.php';
+
+// Make sure no one runs this from the web.
+if (!Horde_Cli::runningFromCLI()) {
+ exit("Must be run from the command line\n");
+}
+
+/* Load the CLI environment - make sure there's no time limit, init some
+ * variables, etc. */
+$cli = &new Horde_Cli();
+$cli->init();
+
+/* Create the fax information array. Set fax_type to 0 for incoming. */
+$info = array('fax_type' => 0,
+ 'fax_user' => '');
+
+/* Get the arguments. The first argument is the filename from which the job ID
+ * is obtained, in the format 'recvq/faxNNNNN.tif'. */
+$args = Console_Getopt::readPHPArgv();
+if (isset($args[1])) {
+ $info['fax_id'] = $args[1];
+}
+if (isset($args[2])) {
+ $file = $args[2];
+ $info['job_id'] = (int)substr($file, 9, -4);
+}
+
+$fax_info = $cli->readStdin();
+$fax_info = explode("\n", $fax_info);
+foreach ($fax_info as $line) {
+ $line = trim($line);
+ if (preg_match('/Pages: (\d+)/', $line, $matches)) {
+ $info['fax_pages'] = $matches[1];
+ } elseif (preg_match('/Sender: (.+)/', $line, $matches)) {
+ $info['fax_number'] = $matches[1];
+ } elseif (preg_match('/Received: (\d{4}):(\d{2}):(\d{2}) (\d{2}):(\d{2}):(\d{2})/', $line, $d)) {
+ $time = mktime($d[4], $d[5], $d[6], $d[2], $d[3], $d[1]);
+ $info['fax_created'] = $time;
+ }
+}
+
+$t = $hylax_storage->createFax($info, true);
+var_dump($t);
--- /dev/null
+#!/usr/bin/php
+<?php
+/**
+ * $Horde: incubator/hylax/scripts/fax_save_data.php,v 1.4 2009/06/10 19:57:57 slusarz Exp $
+ */
+
+// No need for auth.
+@define('AUTH_HANDLER', true);
+
+// Find the base file paths.
+@define('HORDE_BASE', dirname(__FILE__) . '/../..');
+@define('HYLAX_BASE', dirname(__FILE__) . '/..');
+
+// Do CLI checks and environment setup first.
+require_once HYLAX_BASE . '/lib/base.php';
+require_once 'Console/Getopt.php';
+
+// Make sure no one runs this from the web.
+if (!Horde_Cli::runningFromCLI()) {
+ exit("Must be run from the command line\n");
+}
+
+/* Load the CLI environment - make sure there's no time limit, init some
+ * variables, etc. */
+$cli = &new Horde_Cli();
+$cli->init();
+
+/* Store the raw fax postscript data. */
+$data = $cli->readStdin();
+if (empty($data)) {
+ Horde::logMessage('No print data received from standard input. Exiting fax submission.', __FILE__, __LINE__, PEAR_LOG_ERR);
+ exit;
+}
+
+$fax_id = $hylax_storage->saveFaxData($data);
+if (is_a($fax_id, 'PEAR_Error')) {
+ echo '0';
+}
+echo $fax_id;
--- /dev/null
+#!/usr/bin/php
+<?php
+/**
+ * $Horde: incubator/hylax/scripts/fax_save_recv_data.php,v 1.4 2009/06/10 19:57:57 slusarz Exp $
+ */
+
+// No need for auth.
+@define('AUTH_HANDLER', true);
+
+// Find the base file paths.
+@define('HORDE_BASE', dirname(__FILE__) . '/../..');
+@define('HYLAX_BASE', dirname(__FILE__) . '/..');
+
+// Do CLI checks and environment setup first.
+require_once HYLAX_BASE . '/lib/base.php';
+require_once 'Console/Getopt.php';
+
+// Make sure no one runs this from the web.
+if (!Horde_Cli::runningFromCLI()) {
+ exit("Must be run from the command line\n");
+}
+
+/* Load the CLI environment - make sure there's no time limit, init some
+ * variables, etc. */
+$cli = &new Horde_Cli();
+$cli->init();
+
+/* Get the arguments. The first argument is the filename from which the job ID
+ * is obtained, in the format 'recvq/faxNNNNN.tif'. */
+$args = Console_Getopt::readPHPArgv();
+if (isset($args[1])) {
+ $file = $args[1];
+ $job_id = (int)substr($file, 9, -4);
+}
+
+/* Store the raw fax postscript data. */
+$data = $cli->readStdin();
+if (empty($data)) {
+ Horde::logMessage('No print data received from standard input. Exiting fax submission.', __FILE__, __LINE__, PEAR_LOG_ERR);
+ exit;
+}
+
+/* Get the file and store into VFS. */
+$fax_id = $hylax_storage->saveFaxData($data, '.ps');
+if (is_a($fax_id, 'PEAR_Error')) {
+ echo '0';
+ exit;
+}
+Horde::logMessage(sprintf('Creating fax ID %s for received fax.', $fax_id), __FILE__, __LINE__, PEAR_LOG_DEBUG);
+echo $fax_id;
--- /dev/null
+#! /bin/sh
+
+#
+# faxrcvd file devID commID error-msg
+#
+if [ $# -lt 4 ]; then
+ echo "Usage: $0 file devID commID error-msg CIDNumber CIDName "
+ exit 1
+fi
+
+#test -f etc/setup.cache || {
+# SPOOL=`pwd`
+# cat<<EOF
+#
+#FATAL ERROR: $SPOOL/etc/setup.cache is missing!
+#
+#The file $SPOOL/etc/setup.cache is not present. This
+#probably means the machine has not been setup using the faxsetup(8C)
+#command. Read the documentation on setting up HylaFAX before you
+#startup a server system.
+#
+#EOF
+# exit 1
+#}
+#. etc/setup.cache
+
+
+SCRIPT_DIR="__SCRIPT_DIR__"
+
+# Nothing to see below.
+DATA_SCRIPT="fax_save_recv_data.php"
+FAX_SCRIPT="fax_create_recv.php"
+FAX_USER=$2
+
+
+FILE="/var/spool/fax/$1"
+
+if [ -f $FILE ]; then
+ FAX_ID=`tiff2ps -a2 $FILE | sudo -u __WWW_USER__ $SCRIPT_DIR/$DATA_SCRIPT $1`
+ /usr/sbin/faxinfo $FILE | sudo -u __WWW_USER__ $SCRIPT_DIR/$FAX_SCRIPT $FAX_ID $1
+fi
--- /dev/null
+#!/usr/bin/php
+<?php
+/**
+ * $Horde: incubator/hylax/scripts/install_cups_drivers.php,v 1.3 2009/06/10 19:57:57 slusarz Exp $
+ */
+
+// No need for auth.
+@define('AUTH_HANDLER', true);
+
+// Find the base file paths.
+@define('HORDE_BASE', dirname(__FILE__) . '/../..');
+@define('HYLAX_BASE', dirname(__FILE__) . '/..');
+
+// Do CLI checks and environment setup first.
+require_once HYLAX_BASE . '/lib/base.php';
+
+// Make sure no one runs this from the web.
+if (!Horde_Cli::runningFromCLI()) {
+ exit("Must be run from the command line\n");
+}
+
+Horde_Cli::init();
+
+/* The CUPS backend file. */
+$hylafax_backend = file_get_contents(HYLAX_BASE . '/scripts/cups/hylafax');
+$path = realpath(HYLAX_BASE . '/scripts');
+$hylafax_backend = preg_replace('/__SCRIPT_DIR__/', $path, $hylafax_backend);
+$hylafax_backend = preg_replace('/__WWW_USER__/', $conf['cups']['www_user'], $hylafax_backend);
+$fp = fopen($conf['cups']['backend_dir'] . '/hylafax', 'w');
+fwrite($fp, $hylafax_backend);
+fclose($fp);
+chmod($conf['cups']['backend_dir'] . '/hylafax', 0755);
+
+/* The PPD model file. */
+$hylafax_ppd = file_get_contents(HYLAX_BASE . '/scripts/cups/hylafax.ppd');
+$fp = fopen($conf['cups']['ppd_dir'] . '/hylafax.ppd', 'w');
+fwrite($fp, $hylafax_ppd);
+fclose($fp);
+chmod($conf['cups']['ppd_dir'] . '/hylafax.ppd', 0644);
+
+/* The faxrcvd script. */
+if (!file_exists($conf['hylafax']['faxrcvd'] . '/faxrcvd.orig')) {
+ $orig_faxrcvd = file_get_contents($conf['hylafax']['faxrcvd'] . '/faxrcvd');
+ $fp = fopen($conf['hylafax']['faxrcvd'] . '/faxrcvd.orig', 'w');
+ fwrite($fp, $orig_faxrcvd);
+ fclose($fp);
+}
+$faxrcvd = file_get_contents(HYLAX_BASE . '/scripts/hylafax/faxrcvd');
+$faxrcvd = preg_replace('/__SCRIPT_DIR__/', $path, $faxrcvd);
+$faxrcvd = preg_replace('/__WWW_USER__/', $conf['cups']['www_user'], $faxrcvd);
+$fp = fopen($conf['hylafax']['faxrcvd'] . '/faxrcvd', 'w');
+fwrite($fp, $faxrcvd);
+fclose($fp);
+chmod($conf['hylafax']['faxrcvd'] . '/faxrcvd', 0755);
--- /dev/null
+#!/bin/bash
+
+#
+# faxrcvd faxfile callerID calledFax
+#
+if [ $# -lt 2 ]; then
+ echo "Usage: $0 file callerId calledFax"
+ exit 1
+fi
+
+SCRIPT_DIR="__SCRIPT_DIR__"
+
+# Nothing to see below.
+DATA_SCRIPT="fax_save_recv_data.php"
+FAX_SCRIPT="fax_create_recv.php"
+
+FAXFILE=$1
+FAXSENDER=$2
+RECIPIENT=$3
+
+FAX_ID=`tiff2ps -a2 $FAXFILE | sudo -u __WWW_USER__ $SCRIPT_DIR/$DATA_SCRIPT $FAXFILE`
+
+DATETIME=`date +"%Y:%M:%d %T"`
+PAGES=$(tiffinfo $FILE | grep "Page")
+
+echo "Sender: $FAXSENDER" > ${FAXFILE}.txt
+echo "Pages: $PAGES" >> ${FAXFILE}.txt
+echo "Received: $DATETIME" >> ${FAXFILE}.txt
+
+cat ${FAXFILE}.txt | sudo -u __WWW_USER__ $SCRIPT_DIR/$FAX_SCRIPT $FAX_ID $FAXFILE
+rm -rf ${FAXFILE}.txt
+
--- /dev/null
+-- $Horde: incubator/hylax/scripts/sql/fax.mssql.sql,v 1.1 2006/12/13 04:30:49 chuck Exp $
+
+CREATE TABLE hylax_faxes (
+ fax_id INT NOT NULL DEFAULT 0,
+ job_id INT DEFAULT NULL,
+ fax_type SMALLINT(1) NOT NULL,
+ fax_user VARCHAR(255) NOT NULL DEFAULT '',
+ fax_number VARCHAR(255) NOT NULL DEFAULT '',
+ fax_pages INT NOT NULL DEFAULT 0,
+ fax_created INT NOT NULL DEFAULT 0,
+ fax_status VARCHAR(255) NOT NULL DEFAULT '',
+ fax_folder VARCHAR(255) NOT NULL DEFAULT '',
+
+ PRIMARY KEY (fax_id)
+);
+
+CREATE INDEX hylax_faxes_fax_id_idx ON hylax_faxes (fax_id);
+
+
+CREATE TABLE hylax_fax_attributes (
+ fax_id VARCHAR(255) NOT NULL default '',
+ attribute_name VARCHAR(255) NOT NULL default '',
+ attribute_key VARCHAR(255) NOT NULL default '',
+ attribute_value VARCHAR(MAX)
+);
+
+CREATE INDEX fax_attribute_idx ON hylax_fax_attributes (fax_id);
+CREATE INDEX fax_attribute_name_idx ON hylax_fax_attributes (attribute_name);
+CREATE INDEX fax_attribute_key_idx ON hylax_fax_attributes (attribute_key);
--- /dev/null
+-- $Horde: incubator/hylax/scripts/sql/fax.sql,v 1.1 2006/12/13 04:30:49 chuck Exp $
+
+CREATE TABLE hylax_faxes (
+ fax_id INT NOT NULL DEFAULT 0,
+ job_id INT DEFAULT NULL,
+ fax_type SMALLINT(1) NOT NULL,
+ fax_user VARCHAR(255) NOT NULL DEFAULT '',
+ fax_number VARCHAR(255) NOT NULL DEFAULT '',
+ fax_pages INT NOT NULL DEFAULT 0,
+ fax_created INT NOT NULL DEFAULT 0,
+ fax_status VARCHAR(255) NOT NULL DEFAULT '',
+ fax_folder VARCHAR(255) NOT NULL DEFAULT '',
+
+ PRIMARY KEY (fax_id)
+);
+
+CREATE INDEX hylax_faxes_fax_id_idx ON hylax_faxes (fax_id);
+
+
+CREATE TABLE hylax_fax_attributes (
+ fax_id VARCHAR(255) NOT NULL default '',
+ attribute_name VARCHAR(255) NOT NULL default '',
+ attribute_key VARCHAR(255) NOT NULL default '',
+ attribute_value TEXT
+);
+
+CREATE INDEX fax_attribute_idx ON hylax_fax_attributes (fax_id);
+CREATE INDEX fax_attribute_name_idx ON hylax_fax_attributes (attribute_name);
+CREATE INDEX fax_attribute_key_idx ON hylax_fax_attributes (attribute_key);
--- /dev/null
+<?php
+/**
+ * The Hylax script to show a fax view.
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * $Horde: incubator/hylax/send.php,v 1.8 2009/06/10 17:33:26 slusarz Exp $
+ */
+
+@define('HYLAX_BASE', dirname(__FILE__));
+require_once HYLAX_BASE . '/lib/base.php';
+require_once 'Horde/Form.php';
+
+$fax_id = Horde_Util::getFormData('fax_id');
+$folder = strtolower(Horde_Util::getFormData('folder'));
+$path = Horde_Util::getFormData('path');
+$base_folders = Hylax::getBaseFolders();
+
+$vars = Horde_Variables::getDefaultVariables();
+$fax_id = $vars->get('fax_id');
+$url = $vars->get('url', 'folder.php');
+
+$fax = $hylax_storage->getFax($fax_id);
+if (is_a($fax, 'PEAR_Error')) {
+ $notification->push(sprintf(_("Could not open fax ID \"%s\". %s"), $fax_id, $fax->getMessage()), 'horde.error');
+ $url = Horde::applicationUrl($url, true);
+ header('Location: ' . $url);
+ exit;
+} elseif (!empty($fax['fax_number'])) {
+ $notification->push(sprintf(_("Fax ID \"%s\" already has a fax number set."), $fax_id), 'horde.error');
+ $url = Horde::applicationUrl($url, true);
+ header('Location: ' . $url);
+ exit;
+}
+
+$title = _("Send Fax");
+
+/* Set up the form. */
+$form = new Horde_Form($vars, $title);
+$form->setButtons(_("Send"), true);
+$form->addHidden('', 'url', 'text', false);
+$form->addHidden('', 'fax_id', 'int', false);
+$form->addVariable(_("Fax destination"), 'fax_number', 'text', true, false, null, array('/^\d+$/'));
+
+if ($form->validate($vars)) {
+ $form->getInfo($vars, $info);
+ $send = $hylax_storage->send($info['fax_id'], $info['fax_number']);
+ if (is_a($send, 'PEAR_Error')) {
+ $notification->push(sprintf(_("Could not send fax ID \"%s\". %s"), $info['fax_id'], $send->getMessage()), 'horde.error');
+ } else {
+ $notification->push(sprintf(_("Fax ID \"%s\" submitted successfully."), $info['fax_id']), 'horde.success');
+ }
+ $url = Horde::applicationUrl($url, true);
+ header('Location: ' . $url);
+ exit;
+}
+
+/* Get the preview pages. */
+$pages = Hylax::getPages($fax_id, $fax['fax_pages']);
+
+/* Render the form. */
+require_once 'Horde/Form/Renderer.php';
+$renderer = new Horde_Form_Renderer();
+$send_form = Horde_Util::bufferOutput(array($form, 'renderActive'), $renderer, $vars, 'send.php', 'post');
+
+/* Set up template. */
+$template = new Horde_Template();
+$template->set('form', $send_form);
+$template->set('pages', $pages);
+$template->set('menu', $menu->getMenu());
+$template->set('notify', Horde_Util::bufferOutput(array($notification, 'notify'), array('listeners' => 'status')));
+
+require HYLAX_TEMPLATES . '/common-header.inc';
+echo $template->fetch(HYLAX_TEMPLATES . '/fax/fax.html');
+require $registry->get('templates', 'horde') . '/common-footer.inc';
--- /dev/null
+<?php
+/**
+ * The Hylax script to show a summary view.
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * $Horde: incubator/hylax/summary.php,v 1.6 2009/06/10 05:24:17 slusarz Exp $
+ */
+
+@define('HYLAX_BASE', dirname(__FILE__));
+require_once HYLAX_BASE . '/lib/base.php';
+
+$fmt_inbox = array();
+$inbox = $gateway->getInbox();
+foreach ($inbox as $item) {
+ $fmt_inbox[] = array('owner' => $item[2]);
+}
+
+$fmt_outbox = array();
+//$outbox = $fax->getOutbox();
+foreach ($outbox as $item) {
+ $fmt_outbox[] = array(//'time' => $item
+ 'owner' => $item[2],
+ );
+}
+
+/* Set up actions. */
+$template = &new Horde_Template();
+$template->set('in_faxes', $gateway->numFaxesIn());
+$template->set('out_faxes', $gateway->numFaxesOut());
+$template->set('inbox', $fmt_inbox, true);
+$template->set('outbox', $fmt_outbox, true);
+$template->set('menu', Hylax::getMenu('string'));
+$template->set('notify', Horde_Util::bufferOutput(array($notification, 'notify'), array('listeners' => 'status')));
+
+require HYLAX_TEMPLATES . '/common-header.inc';
+echo $template->fetch(HYLAX_TEMPLATES . '/summary/summary.html');
+require $registry->get('templates', 'horde') . '/common-footer.inc';
--- /dev/null
+Deny from all
--- /dev/null
+<?php
+if (isset($language)) {
+ header('Content-type: text/html; charset=' . Horde_Nls::getCharset());
+ header('Vary: Accept-Language');
+}
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd">
+<!-- Hylax: Copyright 2003-2009 The Horde Project. Hylax is under a Horde license. -->
+<!-- Horde Project: http://www.horde.org/ | Hylax: http://www.horde.org/hylax/ -->
+<!-- Horde Licenses: http://www.horde.org/licenses/ -->
+<?php echo !empty($language) ? '<html lang="' . strtr($language, '_', '-') . '">' : '<html>' ?>
+<head>
+<?php
+
+$page_title = $GLOBALS['registry']->get('name');
+if (!empty($title)) $page_title .= ' :: ' . $title;
+if (!empty($refresh_time) && ($refresh_time > 0) && !empty($refresh_url)) {
+ echo "<meta http-equiv=\"refresh\" content=\"$refresh_time;url=$refresh_url\">\n";
+}
+
+Horde::includeScriptFiles();
+
+?>
+<title><?php echo htmlspecialchars($page_title) ?></title>
+<link href="<?php echo $GLOBALS['registry']->getImageDir()?>/favicon.ico" rel="SHORTCUT ICON" />
+<?php Horde::includeStylesheetFiles() ?>
+</head>
+
+<body<?php if ($bc = Horde_Util::nonInputVar('bodyClass')) echo ' class="' . $bc . '"' ?><?php if ($bi = Horde_Util::nonInputVar('bodyId')) echo ' id="' . $bi . '"'; ?>>
--- /dev/null
+<div id="menu">
+ <tag:menu />
+</div>
+<br />
+
+<tag:notify />
--- /dev/null
+<div id="menu">
+ <tag:menu />
+</div>
+<br />
+
+<tag:notify />
+
+<tag:form />
+<br />
+<table width="100%" border="0" cellpadding="2" cellspacing="1">
+ <tr class="smallheader" align="center">
+ <td>
+ <gettext>Pages</gettext>
+ </td>
+ </tr><tr>
+ <td class="previewpages">
+ <loop:pages><tag:pages />
+</loop:pages>
+ </td>
+ </tr>
+</table>
--- /dev/null
+<div id="menu">
+ <tag:menu />
+</div>
+<br />
+
+<tag:notify />
+
+<table width="100%" border="0" cellpadding="2" cellspacing="0">
+ <tr class="header">
+ <td class="header">
+ <gettext>Folder:</gettext> <tag:folder_name />
+ </td><td align="right">
+ <loop:actions><divider:actions> | </divider:actions><tag:actions /></loop:actions>
+ </td>
+ </tr>
+</table>
+<br />
+<table width="100%" border="0" cellpadding="2" cellspacing="1">
+ <tr class="smallheader" align="center">
+ <td width="%1">
+
+ </td><td>
+ <gettext>Date</gettext>
+ </td><td>
+ <gettext>Number</gettext>
+ </td><td>
+ <gettext>Owner</gettext>
+ </td><td>
+ <gettext>Pages</gettext>
+ </td><td>
+ <gettext>Status</gettext>
+ </td>
+ </tr>
+ <if:folder>
+ <loop:folder>
+ <tr class="item<tag:folder.alt_count />" onmouseover="className='selected-hi';" onmouseout="className='item<tag:folder.alt_count />';">
+ <td nowrap="nowrap">
+ <loop:folder.actions><tag:folder.actions /> </loop:folder.actions>
+ </td><td>
+ <tag:folder.fax_created />
+ </td><td>
+ <tag:folder.fax_number />
+ </td><td>
+ <tag:folder.fax_user />
+ </td><td align="center">
+ <tag:folder.fax_pages />
+ </td><td>
+ <tag:folder.fax_status />
+ </td>
+ </tr>
+ </loop:folder>
+ <else:folder>
+ <tr>
+ <td colspan="9" align="center" class="item">
+ <gettext>No entries</gettext>
+ </td>
+ </tr>
+ </else:folder>
+ </if:folder>
+</table>
--- /dev/null
+<div id="menu">
+ <tag:menu />
+</div>
+<br />
+
+<tag:notify />
+
+<table width="100%" border="0" cellpadding="2" cellspacing="0">
+ <tr class="header">
+ <td class="header">
+ <gettext>Summary</gettext>
+ </td>
+ </tr>
+</table>
+<br />
+<table width="100%" border="0" cellpadding="2" cellspacing="0">
+ <tr>
+ <td class="smallheader" width="50%">
+ <gettext>New faxes</gettext> <strong><tag:in_faxes /></strong>
+ </td><td class="smallheader" width="50%">
+ <gettext>Faxes waiting to be sent</gettext> <strong><tag:out_faxes /></strong>
+ </td>
+ </tr><tr>
+ <td>
+ <if:inbox>
+ <table width="100%" border="0" cellpadding="2" cellspacing="1">
+ <loop:inbox>
+ <tr>
+ <td>
+ </td><td>
+ <tag:inbox.owner />
+ </td>
+ </tr>
+ </loop:inbox>
+ </table>
+ </if:inbox>
+ </td><td>
+ <if:outbox>
+ <table width="100%" border="0" cellpadding="2" cellspacing="1">
+ <loop:outbox>
+ <tr class="item">
+ <td>
+ </td><td>
+ <tag:outbox.owner />
+ </td>
+ </tr>
+ </loop:outbox>
+ </table>
+ </if:outbox>
+ </td>
+ </tr>
+</table>
--- /dev/null
+<div id="menu">
+ <tag:menu />
+</div>
+<br />
+
+<tag:notify />
+
+<table width="100%" border="0" cellpadding="2" cellspacing="0">
+ <tr class="header">
+ <td class="header">
+ <gettext>Number:</gettext> <tag:number />
+ </td><td align="right">
+ <loop:actions><divider:actions> | </divider:actions><tag:actions /></loop:actions>
+ </td>
+ </tr>
+</table>
+<br />
+<table width="100%" border="0" cellpadding="2" cellspacing="1">
+ <tr class="smallheader" align="center">
+ <td>
+ <gettext>Pages</gettext>
+ </td>
+ </tr><tr>
+ <td>
+ <loop:pages><tag:pages.preview /></loop:pages>
+ </td>
+ </tr>
+</table>
--- /dev/null
+<?php
+/**
+ * The Hylax script to show a fax view.
+ *
+ * See the enclosed file COPYING for license information (GPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
+ *
+ * $Horde: incubator/hylax/view.php,v 1.7 2009/06/10 05:24:18 slusarz Exp $
+ */
+
+@define('HYLAX_BASE', dirname(__FILE__));
+require_once HYLAX_BASE . '/lib/base.php';
+
+$fax_id = Horde_Util::getFormData('fax_id');
+$url = Horde_Util::getFormData('url');
+$folder = strtolower(Horde_Util::getFormData('folder'));
+$path = Horde_Util::getFormData('path');
+$base_folders = Hylax::getBaseFolders();
+
+if (Horde_Util::getFormData('action') == 'download') {
+ $filename = sprintf('fax%05d.pdf', $fax_id);
+ $browser->downloadHeaders($filename);
+ Hylax::getPDF($fax_id);
+ exit;
+}
+
+$fax = $hylax_storage->getFax($fax_id);
+if (is_a($fax, 'PEAR_Error')) {
+ $notification->push(sprintf(_("Could not open fax ID \"%s\". %s"), $fax_id, $fax->getMessage()), 'horde.error');
+ if (empty($url)) {
+ $url = Horde::applicationUrl('folder.php', true);
+ }
+ header('Location: ' . $url);
+ exit;
+}
+
+$title = _("View Fax");
+
+/* Get the preview pages. */
+$pages = Hylax::getPages($fax_id, $fax['fax_pages']);
+
+/* Set up template. */
+$template = &new Horde_Template();
+$template->set('form', '');
+$template->set('pages', $pages);
+$template->set('menu', Hylax::getMenu('string'));
+$template->set('notify', Horde_Util::bufferOutput(array($notification, 'notify'), array('listeners' => 'status')));
+
+require HYLAX_TEMPLATES . '/common-header.inc';
+echo $template->fetch(HYLAX_TEMPLATES . '/fax/fax.html');
+require $registry->get('templates', 'horde') . '/common-footer.inc';