golden hour
/home/doctorbruno/public_html/taeionline.com/support/include
⬆️ Go Up
Upload
File/Folder
Size
Actions
.MANIFEST
194.97 KB
Del
OK
.htaccess
14 B
Del
OK
JSON.php
33.13 KB
Del
OK
PasswordHash.php
6.92 KB
Del
OK
Spyc.php
31.74 KB
Del
OK
UniversalClassLoader.php
8.61 KB
Del
OK
ajax.admin.php
7.29 KB
Del
OK
ajax.config.php
4.61 KB
Del
OK
ajax.content.php
9.76 KB
Del
OK
ajax.draft.php
13.03 KB
Del
OK
ajax.email.php
2.33 KB
Del
OK
ajax.export.php
1006 B
Del
OK
ajax.filter.php
874 B
Del
OK
ajax.forms.php
13.84 KB
Del
OK
ajax.i18n.php
5.1 KB
Del
OK
ajax.kbase.php
2.93 KB
Del
OK
ajax.note.php
2.05 KB
Del
OK
ajax.orgs.php
11.73 KB
Del
OK
ajax.plugins.php
2.15 KB
Del
OK
ajax.schedule.php
4.29 KB
Del
OK
ajax.search.php
12.72 KB
Del
OK
ajax.sequence.php
3.2 KB
Del
OK
ajax.staff.php
11.62 KB
Del
OK
ajax.tasks.php
33.87 KB
Del
OK
ajax.thread.php
8.81 KB
Del
OK
ajax.tickets.php
79.7 KB
Del
OK
ajax.tips.php
1.66 KB
Del
OK
ajax.upgrader.php
2.24 KB
Del
OK
ajax.users.php
18.33 KB
Del
OK
api.cron.php
1.06 KB
Del
OK
api.tickets.php
10.36 KB
Del
OK
class.2fa.php
7.76 KB
Del
OK
class.ajax.php
1.45 KB
Del
OK
class.api.php
15.31 KB
Del
OK
class.app.php
1.49 KB
Del
OK
class.attachment.php
6.95 KB
Del
OK
class.auth.php
50.73 KB
Del
OK
class.avatar.php
6.44 KB
Del
OK
class.banlist.php
2.58 KB
Del
OK
class.base32.php
4.07 KB
Del
OK
class.businesshours.php
7.08 KB
Del
OK
class.canned.php
9.05 KB
Del
OK
class.captcha.php
1.73 KB
Del
OK
class.category.php
11.14 KB
Del
OK
class.charset.php
3.41 KB
Del
OK
class.cli.php
9.48 KB
Del
OK
class.client.php
15.39 KB
Del
OK
class.collaborator.php
5.65 KB
Del
OK
class.company.php
2.65 KB
Del
OK
class.config.php
60.36 KB
Del
OK
class.controller.php
1.15 KB
Del
OK
class.cron.php
3.6 KB
Del
OK
class.crypto.php
18.92 KB
Del
OK
class.csrf.php
2.38 KB
Del
OK
class.dept.php
33.21 KB
Del
OK
class.dispatcher.php
7.12 KB
Del
OK
class.draft.php
6.23 KB
Del
OK
class.dynamic_forms.php
64.98 KB
Del
OK
class.email.php
49 KB
Del
OK
class.error.php
1.69 KB
Del
OK
class.export.php
32.92 KB
Del
OK
class.faq.php
15.05 KB
Del
OK
class.file.php
34.59 KB
Del
OK
class.filter.php
31.9 KB
Del
OK
class.filter_action.php
23.67 KB
Del
OK
class.format.php
44.3 KB
Del
OK
class.forms.php
195.58 KB
Del
OK
class.http.php
7.16 KB
Del
OK
class.i18n.php
24.28 KB
Del
OK
class.import.php
6.9 KB
Del
OK
class.json.php
2.71 KB
Del
OK
class.knowledgebase.php
5.8 KB
Del
OK
class.list.php
42 KB
Del
OK
class.lock.php
4.05 KB
Del
OK
class.log.php
1.55 KB
Del
OK
class.mail.php
35.76 KB
Del
OK
class.mailer.php
25.75 KB
Del
OK
class.mailfetch.php
9.72 KB
Del
OK
class.mailparse.php
30.99 KB
Del
OK
class.message.php
6.42 KB
Del
OK
class.migrater.php
5.2 KB
Del
OK
class.misc.php
7.5 KB
Del
OK
class.model.php
2.3 KB
Del
OK
class.nav.php
14.15 KB
Del
OK
class.note.php
2.39 KB
Del
OK
class.oauth2.php
4.04 KB
Del
OK
class.organization.php
22.45 KB
Del
OK
class.orm.php
120.9 KB
Del
OK
class.osticket.php
20.64 KB
Del
OK
class.ostsession.php
21.86 KB
Del
OK
class.page.php
10.59 KB
Del
OK
class.pagenate.php
5.53 KB
Del
OK
class.passwd.php
1.21 KB
Del
OK
class.pdf.php
3.83 KB
Del
OK
class.plugin.php
36.13 KB
Del
OK
class.priority.php
1.81 KB
Del
OK
class.queue.php
103.51 KB
Del
OK
class.report.php
11.76 KB
Del
OK
class.role.php
11.27 KB
Del
OK
class.schedule.php
46.28 KB
Del
OK
class.search.php
61.66 KB
Del
OK
class.sequence.php
7.27 KB
Del
OK
class.session.php
19.25 KB
Del
OK
class.setup.php
3.55 KB
Del
OK
class.signal.php
4.16 KB
Del
OK
class.sla.php
9.11 KB
Del
OK
class.staff.php
60.21 KB
Del
OK
class.task.php
56.21 KB
Del
OK
class.team.php
12.31 KB
Del
OK
class.template.php
23.45 KB
Del
OK
class.thread.php
108.96 KB
Del
OK
class.thread_actions.php
17.08 KB
Del
OK
class.ticket.php
167.39 KB
Del
OK
class.timezone.php
21.94 KB
Del
OK
class.topic.php
20.06 KB
Del
OK
class.translation.php
34.79 KB
Del
OK
class.upgrader.php
13.76 KB
Del
OK
class.user.php
43.4 KB
Del
OK
class.usersession.php
7.55 KB
Del
OK
class.util.php
10.07 KB
Del
OK
class.validator.php
12.94 KB
Del
OK
class.variable.php
11.93 KB
Del
OK
class.xml.php
3.23 KB
Del
OK
class.yaml.php
1.15 KB
Del
OK
cli
-
Del
OK
client
-
Del
OK
config
-
Del
OK
fpdf
-
Del
OK
htmLawed.php
53.53 KB
Del
OK
html2text.php
33.71 KB
Del
OK
i18n
-
Del
OK
index.php
37 B
Del
OK
laminas-mail
-
Del
OK
mpdf
-
Del
OK
mysqli.php
9.55 KB
Del
OK
ost-config.php
5.63 KB
Del
OK
ost-sampleconfig.php
6.24 KB
Del
OK
pear
-
Del
OK
plugins
-
Del
OK
staff
-
Del
OK
tnef_decoder.php
19.82 KB
Del
OK
upgrader
-
Del
OK
Edit: class.export.php
<?php /************************************************************************* class.export.php Exports stuff (details to follow) Jared Hancock <jared@osticket.com> Copyright (c) 2006-2013 osTicket http://www.osticket.com Released under the GNU General Public License WITHOUT ANY WARRANTY. See LICENSE.TXT for details. vim: expandtab sw=4 ts=4 sts=4: **********************************************************************/ class Export { // XXX: This may need to be moved to a print-specific class static $paper_sizes = array( /* @trans */ 'Letter', /* @trans */ 'Legal', 'A4', 'A3', ); static function dumpQuery($sql, $headers, $how='csv', $options=array()) { $exporters = array( 'csv' => 'CsvResultsExporter', 'json' => 'JsonResultsExporter' ); $exp = new $exporters[$how]($sql, $headers, $options); return $exp->dump($options['tmp'] ? true : false); } # XXX: Think about facilitated exporting. For instance, we might have a # TicketExporter, which will know how to formulate or lookup a # format query (SQL), and cooperate with the output process to add # extra (recursive) information. In this funciton, the top-level # SQL is exported, but for something like tickets, we will need to # export attached messages, reponses, and notes, as well as # attachments associated with each, ... static function dumpTickets($sql, $target=array(), $how='csv', $options=array()) { // Add custom fields to the $sql statement $cdata = $fields = array(); foreach (TicketForm::getInstance()->getFields() as $f) { // Ignore core fields if (in_array($f->get('name'), array('priority'))) continue; // Ignore non-data fields elseif (!$f->hasData() || $f->isPresentationOnly()) continue; $name = $f->get('name') ?: 'field_'.$f->get('id'); $key = 'cdata.'.$name; $fields[$key] = $f; $cdata[$key] = $f->getLocal('label'); } if (!is_array($target)) $target = CustomQueue::getExportableFields() + $cdata; // Reset the $sql query $tickets = $sql->models() ->select_related('user', 'user__default_email', 'dept', 'staff', 'team', 'staff', 'cdata', 'topic', 'status', 'cdata__:priority') ->annotate(array( 'collab_count' => TicketThread::objects() ->filter(array('ticket__ticket_id' => new SqlField('ticket_id', 1))) ->aggregate(array('count' => SqlAggregate::COUNT('collaborators__id'))), 'attachment_count' => TicketThread::objects() ->filter(array('ticket__ticket_id' => new SqlField('ticket_id', 1))) ->filter(array('entries__attachments__inline' => 0)) ->aggregate(array('count' => SqlAggregate::COUNT('entries__attachments__id'))), 'reopen_count' => TicketThread::objects() ->filter(array('ticket__ticket_id' => new SqlField('ticket_id', 1))) ->filter(array('events__annulled' => 0, 'events__event_id' => Event::getIdByName('reopened'))) ->aggregate(array('count' => SqlAggregate::COUNT('events__id'))), 'thread_count' => TicketThread::objects() ->filter(array('ticket__ticket_id' => new SqlField('ticket_id', 1))) ->exclude(array('entries__flags__hasbit' => ThreadEntry::FLAG_HIDDEN)) ->aggregate(array('count' => SqlAggregate::COUNT('entries__id'))), )); // Fetch staff information // FIXME: Adjust Staff model so it doesn't do extra queries foreach (Staff::objects() as $S) $S->get('junk'); return self::dumpQuery($tickets, $target, $how, array('modify' => function(&$record, $keys) use ($fields) { foreach ($fields as $k=>$f) { if (($i = array_search($k, $keys)) !== false) { $record[$i] = $f->export($f->to_php($record[$i])); } } return $record; }, 'delimiter' => @$options['delimiter']) ); } static function saveTickets($sql, $fields, $filename, $how='csv', $options=array()) { global $thisstaff; if (!$thisstaff) return null; $sql->filter($thisstaff->getTicketsVisibility()); Http::download($filename, "text/$how"); self::dumpTickets($sql, $fields, $how, $options); exit; } static function dumpTasks($sql, $how='csv') { // Add custom fields to the $sql statement $cdata = $fields = array(); foreach (TaskForm::getInstance()->getFields() as $f) { // Ignore non-data fields if (!$f->hasData() || $f->isPresentationOnly()) continue; $name = $f->get('name') ?: 'field_'.$f->get('id'); $key = 'cdata.'.$name; $fields[$key] = $f; $cdata[$key] = $f->getLocal('label'); } // Reset the $sql query $tasks = $sql->models() ->select_related('dept', 'staff', 'team', 'cdata') ->annotate(array( 'collab_count' => SqlAggregate::COUNT('thread__collaborators'), 'attachment_count' => SqlAggregate::COUNT('thread__entries__attachments'), 'thread_count' => SqlAggregate::COUNT('thread__entries'), )); return self::dumpQuery($tasks, array( 'number' => __('Task Number'), 'created' => __('Date Created'), 'cdata.title' => __('Title'), 'dept::getLocalName' => __('Department'), '::getStatus' => __('Current Status'), 'duedate' => __('Due Date'), 'staff::getName' => __('Agent Assigned'), 'team::getName' => __('Team Assigned'), 'thread_count' => __('Thread Count'), 'attachment_count' => __('Attachment Count'), ) + $cdata, $how, array('modify' => function(&$record, $keys, $obj) use ($fields) { foreach ($fields as $k=>$f) { if (($i = array_search($k, $keys)) !== false) { $record[$i] = $f->export($f->to_php($record[$i])); } } return $record; }) ); } static function saveTasks($sql, $filename, $how='csv') { ob_start(); self::dumpTasks($sql, $how); $stuff = ob_get_contents(); ob_end_clean(); if ($stuff) Http::download($filename, "text/$how", $stuff); return false; } static function saveUsers($sql, $filename, $how='csv') { $exclude = array('name', 'email'); $form = UserForm::getUserForm(); $fields = $form->getExportableFields($exclude, 'cdata.'); $cdata = array_combine(array_keys($fields), array_values(array_map( function ($f) { return $f->getLocal('label'); }, $fields))); $users = $sql->models() ->select_related('org', 'cdata'); ob_start(); echo self::dumpQuery($users, array( 'name' => __('Name'), 'org' => __('Organization'), '::getEmail' => __('Email'), ) + $cdata, $how, array('modify' => function(&$record, $keys, $obj) use ($fields) { foreach ($fields as $k=>$f) { if ($f && ($i = array_search($k, $keys)) !== false) { $record[$i] = $f->export($f->to_php($record[$i])); } } return $record; }) ); $stuff = ob_get_contents(); ob_end_clean(); if ($stuff) Http::download($filename, "text/$how", $stuff); return false; } static function saveOrganizations($sql, $filename, $how='csv') { $exclude = array('name'); $form = OrganizationForm::getDefaultForm(); $fields = $form->getExportableFields($exclude, 'cdata.'); $cdata = array_combine(array_keys($fields), array_values(array_map( function ($f) { return $f->getLocal('label'); }, $fields))); $cdata += array( '::getNumUsers' => 'Users', '::getAccountManager' => 'Account Manager', ); $orgs = $sql->models(); ob_start(); echo self::dumpQuery($orgs, array( 'name' => 'Name', ) + $cdata, $how, array('modify' => function(&$record, $keys, $obj) use ($fields) { foreach ($fields as $k=>$f) { if ($f && ($i = array_search($k, $keys)) !== false) { $record[$i] = $f->export($f->to_php($record[$i])); } } return $record; }) ); $stuff = ob_get_contents(); ob_end_clean(); if ($stuff) Http::download($filename, "text/$how", $stuff); return false; } static function agents($agents, $filename='', $how='csv') { // Filename or stream to export agents to $filename = $filename ?: sprintf('Agents-%s.csv', date('Ymd')); Http::download($filename, "text/$how"); $depts = Dept::getDepartments(null, true, Dept::DISPLAY_DISABLED); echo self::dumpQuery($agents, array( '::getName' => 'Name', '::getUsername' => 'Username', '::getStatus' => 'Status', 'permissions' => 'Permissions', '::getDept' => 'Primary Department', ) + $depts, $how, array('modify' => function(&$record, $keys, $obj) use ($depts) { if (($i = array_search('permissions', $keys))) $record[$i] = implode(",", array_keys($obj->getPermission()->getInfo())); $roles = $obj->getRoles(); foreach ($depts as $k => $v) { if (is_numeric($k) && ($i = array_search($k, $keys)) !== false) { $record[$i] = $roles[$k] ?: ''; } } return $record; }) ); exit; } static function departmentMembers($dept, $agents, $filename='', $how='csv') { $primaryMembers = array(); foreach ($dept->getPrimaryMembers() as $agent) { $primaryMembers[] = $agent->getId(); } // Filename or stream to export depts' agents to $filename = $filename ?: sprintf('%s-%s.csv', $dept->getName(), date('Ymd')); Http::download($filename, "text/$how"); echo self::dumpQuery($agents, array( '::getName' => 'Name', '::getUsername' => 'Username', 2 => 'Access Type', 3 => 'Access Role', ), $how, array('modify' => function(&$record, $keys, $obj) use ($dept, $primaries, $primaryMembers) { $role = $obj->getRole($dept); if (array_search($obj->getId(), $primaryMembers, true) === false) $type = 'Extended'; else { $type = 'Primary'; } $record[2] = $type; $record[3] = $role->name; return $record; }) ); exit; } static function audits($type, ?string $filename, ?string $tableInfo, ?string $object, ?string $how='csv', ?bool $show_viewed=true, ?array $data=array(), CsvExporter $exporter) { $headings = array('Description', 'Timestamp', 'IP'); switch ($type) { case 'audit': $sql = AuditEntry::objects()->filter(array('object_type'=>$data['type'])); if ($data['state'] && $data['state'] != 'All') { $eventId = Event::getIdByName(strtolower($data['state'])); $sql = $sql->filter(array('event_id'=>$eventId)); } if ($data['startDate'] && $data['endDate']) $sql = $sql->filter(array('timestamp__range' => array('"'.$data['startDate'].'"', '"'.$data['endDate'].'"', true))); $sql = $sql->order_by('-timestamp'); $tableInfo = $sql; break; case 'user': $sql = AuditEntry::objects()->filter(array('user_id'=>$object))->order_by('-timestamp'); break; case 'staff': $sql = AuditEntry::objects()->filter(array('staff_id'=>$object))->order_by('-timestamp'); break; case 'ticket': $sql = AuditEntry::objects()->filter(array('object_id'=>$object, 'object_type'=>'T'))->order_by('-timestamp'); break; } if (!$show_viewed) $sql = $sql->filter(Q::not(array('event_id'=>Event::getIdByName('viewed'))))->order_by('-timestamp'); $exporter->write($headings); $row = array(); foreach ($sql as $key => $value) { if (is_object($value)) { $description = AuditEntry::getDescription($value, true); $value = $value->ht; } $row[0] = $description; $row[1] = Format::datetime($value['timestamp']); $row[2] = $value['ip']; $exporter->write($row); } } } /* * Exporter Interface * */ abstract class Exporter { protected $id; // Export ID (random code) protected $fp; // stream: file pointer for $file protected $file; // File name / path for the export protected $fileObj; // FileObject class protected $options; abstract function write($data); abstract function init(); function __construct($options=array()) { $this->id = $options['id'] ?: self::generateId(); if (isset($options['file'])) $this->file = $options['file']; $this->options = $options; $this->open(); } function isAvailable() { return file_exists($this->getFile()); } function isReady() { return ($this->isAvailable() && $this->lock()); } private function open($mode='a+') { if ($this->fp) return $this->fp; try { if (($file=$this->getFile())) { if (!($this->fp=fopen($file, $mode))) throw new Exception(); } else { // We don't have a file create one in temp directory $prefix = Format::filename(Misc::randCode(6)); if (!($temp=tempnam(sys_get_temp_dir(), $prefix)) || !($this->fp=fopen($temp, $mode)) || !($meta=stream_get_meta_data($this->fp))) { throw new Exception(); } // get filename from mera $this->file = $meta['uri']; $this->init(); } } catch(Exception $ex) { @fclose($this->fp); @unlink($temp); throw new Exception(); } return $this->fp; } // Close / unlock the file. function close() { @fclose($this->fp); } function delete() { @unlink($this->getFile()); } function getId() { return $this->id; } function getStream() { return $this->fp; } function getFile() { return $this->file; } function getFilename() { return $this->options['filename'] ?: 'Export'; } function getFileType() { return mime_content_type($this->getFile()); } function getFileSize() { return filesize($this->getFile()); } function getFileObject() { if (!isset($this->fileObj)) { $this->fileObj = new FileObject($this->getFile()); // Set the real filename $this->fileObj->setFilename($this->getFilename()); // Set mime type $this->fileObj->setMimeType($this->getFileType()); } return $this->fileObj; } function getOptions() { return $this->options; } // Check interval in seconds function getInterval() { return @$this->options['interval'] ?: 5; } function lock() { return $this->fp ? flock($this->fp, LOCK_EX | LOCK_NB) : false; } function unlock() { fflush($this->fp); flock($this->fp, LOCK_UN); } // Acknowledge the export and close the session // This is important when the export would be taking a long time or when // it's being emailed out in the background function ack() { // Register the export in the session self::register($this); // Flush response / return export id and check interval Http::flush(201, json_encode(['eid' => $this->getId(), 'interval' => $this->getInterval()])); // Phew... now we're free to do the export session_write_close(); // Release session for other requests ignore_user_abort(1); // Leave us alone bro! @set_time_limit(0); // Useless when safe_mode is on // Ask the queue to export to the exporter } // Finilize the export - unlock the file and close the ponter function finalize($delay=true) { $this->unlock(); $this->close(); // Sleep 3 times the interval to allow time for file download if ($delay) sleep($this->getInterval()*3); } function download($filename=false, $delete=true) { $this->close(); $filename = $filename ?: $this->getFilename(); Http::download($filename, 'application/octet-stream', null, 'attachment'); header('Content-Length: '.$this->getFileSize()); readfile($this->getFile()); // Delete the file if requsted if ($delete) @$this->delete(); exit; } function email(Staff $staff) { global $cfg; if (!file_exists($this->getFile()) || !($file=$this->getFileObject()) || !($email=$cfg->getDefaultEmail())) return false; $mailer = new osTicket\Mail\Mailer($email); $mailer->addFileObject($file); $subject = __("Export"); $body = __("Attached is file containing the export you asked us to send you!"); return $mailer->send(array($staff), $subject, $body); } // Generate an alphanumeric url safe id/code static function generateId($len=6) { $id = substr(str_replace('%', '', urlencode(Misc::randCode($len))), 0, $len); if (isset($_SESSION['Exports'][$id])) return self::generateId($len); return $id; } static function register($exporter, $extra=array()) { if (!$exporter instanceof Exporter) return false; $_SESSION['Exports'][$exporter->getId()] = $exporter->getOptions() + array( 'file' => $exporter->getFile(), 'class' => get_class($exporter)) + $extra ?: $extra; } static function load($id) { if (!isset($_SESSION['Exports'][$id]) || !file_exists($_SESSION['Exports'][$id]['file'])) return null; try { $info = $_SESSION['Exports'][$id]; $class = $info['class']; $exporter = new $class(array('id' => $id) + $info); } catch (Exception $ex) { return null; } return $exporter; } } /* * CsvExporter - expects an open file */ class CsvExporter extends Exporter { protected $mimetype = 'text/csv'; function __construct($options=array()) { try { parent::__construct($options); } catch (Exception $ex) { throw new Exception(); } } function init() { $this->lock(); // Output a UTF-8 BOM (byte order mark) fputs($this->fp, chr(0xEF) . chr(0xBB) . chr(0xBF)); } function getFileType() { return $this->mimetype; } function getDelimiter() { if (isset($this->options['delimiter']) && $this->options['delimiter']) return $this->options['delimiter']; return Internationalization::getCSVDelimiter(); } function escape($data) { return $data; // Escape formula, commands etc. return array_map(function($v) { if (preg_match('/^[=\-+@].*/', $v)) return "'".$v; return $v; }, $data); } function write($data) { fputcsv($this->fp, $this->escape($data), $this->getDelimiter(), "\"", ""); } } /* * Given SQL query export results based on subclass. */ class ResultSetExporter { var $output; function __construct($sql, $headers, $options=array()) { $this->headers = array_values($headers); // Remove limit and offset $sql->limit(null)->offset(null); # TODO: If $filter, add different LIMIT clause to query $this->options = $options; $this->output = $options['output'] ?: fopen('php://output', 'w'); $this->headers = array(); $this->keys = array(); foreach ($headers as $field=>$name) { $this->headers[] = $name; $this->keys[] = $field; } $this->_res = $sql->getIterator(); if ($this->_res instanceof IteratorAggregate) $this->_res = $this->_res->getIterator(); $this->_res->rewind(); } function getHeaders() { return $this->headers; } function next() { if (!$this->_res->valid()) return false; $object = $this->_res->current(); $this->_res->next(); $record = array(); foreach ($this->keys as $field) { list($field, $func) = explode('::', $field); $path = explode('.', $field); $current = $object; // Evaluate dotted ORM path if ($field) { foreach ($path as $P) { if (isset($current->{$P})) $current = $current->{$P}; else { $current = $P; break; } } } // Evalutate :: function call on target current if (($current && $func) && (method_exists($current, $func) || method_exists($current, '__call'))) { $current = $current->{$func}(); } $record[] = (string) $current; } if (isset($this->options['modify']) && is_callable($this->options['modify'])) $record = $this->options['modify']($record, $this->keys, $object); return $record; } function nextArray() { if (!($row = $this->next())) return false; return array_combine($this->keys, $row); } function dump() { # Useful for debug output while ($row=$this->nextArray()) { var_dump($row); //nolint } } } class CsvResultsExporter extends ResultSetExporter { function getDelimiter() { if (isset($this->options['delimiter'])) return $this->options['delimiter']; return Internationalization::getCSVDelimiter(); } function dump($tmp=false) { if (!$this->output) $this->output = fopen('php://output', 'w'); $delimiter = $this->getDelimiter(); // Output a UTF-8 BOM (byte order mark) fputs($this->output, chr(0xEF) . chr(0xBB) . chr(0xBF)); fputcsv($this->output, $this->getHeaders(), $delimiter, "\"", ""); while ($row=$this->next()) fputcsv($this->output, array_map( function($v){ if (preg_match('/^[=\-+@].*/', $v)) return "'".$v; return $v; }, $row), $delimiter, "\"", ""); if (!$tmp) fclose($this->output); } } class JsonResultsExporter extends ResultSetExporter { function dump() { require_once(INCLUDE_DIR.'class.json.php'); $rows = array(); while ($row=$this->nextArray()) { $rows[] = $row; } echo JsonDataEncoder::encode($rows); } } require_once INCLUDE_DIR . 'class.json.php'; require_once INCLUDE_DIR . 'class.migrater.php'; require_once INCLUDE_DIR . 'class.signal.php'; define('OSTICKET_BACKUP_SIGNATURE', 'osTicket-Backup'); define('OSTICKET_BACKUP_VERSION', 'B'); class DatabaseExporter { var $stream; var $options; var $tables = array(CONFIG_TABLE, SYSLOG_TABLE, FILE_TABLE, FILE_CHUNK_TABLE, STAFF_TABLE, DEPT_TABLE, TOPIC_TABLE, STAFF_DEPT_TABLE, TEAM_TABLE, TEAM_MEMBER_TABLE, FAQ_TABLE, FAQ_TOPIC_TABLE, FAQ_CATEGORY_TABLE, DRAFT_TABLE, CANNED_TABLE, TICKET_TABLE, ATTACHMENT_TABLE, THREAD_TABLE, THREAD_ENTRY_TABLE, THREAD_ENTRY_EMAIL_TABLE, THREAD_ENTRY_MERGE_TABLE, LOCK_TABLE, THREAD_EVENT_TABLE, TICKET_PRIORITY_TABLE, EMAIL_TABLE, EMAIL_TEMPLATE_TABLE, EMAIL_TEMPLATE_GRP_TABLE, FILTER_TABLE, FILTER_RULE_TABLE, SLA_TABLE, API_KEY_TABLE, SESSION_TABLE, PAGE_TABLE, FORM_SEC_TABLE, FORM_FIELD_TABLE, LIST_TABLE, LIST_ITEM_TABLE, FORM_ENTRY_TABLE, FORM_ANSWER_TABLE, USER_TABLE, USER_EMAIL_TABLE, PLUGIN_TABLE, THREAD_COLLABORATOR_TABLE, TRANSLATION_TABLE, USER_ACCOUNT_TABLE, ORGANIZATION_TABLE, NOTE_TABLE ); function __construct($stream, $options=array()) { $this->stream = $stream; $this->options = $options; } function write_block($what) { fwrite($this->stream, JsonDataEncoder::encode($what)); fwrite($this->stream, "\n"); } function dump_header() { $header = array( array(OSTICKET_BACKUP_SIGNATURE, OSTICKET_BACKUP_VERSION), array( 'version'=>THIS_VERSION, 'table_prefix'=>TABLE_PREFIX, 'salt'=>SECRET_SALT, 'dbtype'=>DBTYPE, 'streams'=>DatabaseMigrater::getUpgradeStreams( UPGRADE_DIR . 'streams/'), ), ); $this->write_block($header); } function dump($error_stream) { // Allow plugins to change the tables exported Signal::send('export.tables', $this, $this->tables); $this->dump_header(); foreach ($this->tables as $t) { if ($error_stream) $error_stream->write("$t\n"); // Inspect schema $table = array(); $res = db_query("select column_name from information_schema.columns where table_schema=DATABASE() and table_name='$t'"); while (list($field) = db_fetch_row($res)) $table[] = $field; if (!$table) { if ($error_stream) $error_stream->write( sprintf(__("%s: Cannot export table with no fields\n"), $t)); die(); } $this->write_block( array('table', substr($t, strlen(TABLE_PREFIX)), $table)); db_query("select * from $t"); // Dump row data while ($row = db_fetch_row($res)) $this->write_block($row); $this->write_block(array('end-table')); } } function transfer($destination, $query, $callback=false, $options=array()) { $header_out = false; $res = db_query($query, true, false); $i = 0; while ($row = db_fetch_array($res)) { if (is_callable($callback)) $callback($row); if (!$header_out) { $fields = array_keys($row); $this->write_block( array('table', $destination, $fields, $options)); $header_out = true; } $this->write_block(array_values($row)); } $this->write_block(array('end-table')); } function transfer_array($destination, $array, $keys, $options=array()) { $this->write_block( array('table', $destination, $keys, $options)); foreach ($array as $row) { $this->write_block(array_values($row)); } $this->write_block(array('end-table')); } } class TicketZipExporter { var $ticket; var $tmpfiles; function __construct(Ticket $ticket) { $this->ticket = $ticket; $this->tmpfiles = array(); } function addTicket($ticket, $zip, $prefix, $notes=true, $psize=null) { require_once(INCLUDE_DIR.'class.pdf.php'); $pdf_file = $this->tmpfiles[] = tempnam(sys_get_temp_dir(), 'zip'); $pdf = new Ticket2PDF($ticket, $psize, $notes); $pdf->output($pdf_file, 'F'); $zip->addFile($pdf_file, "{$ticket->getNumber()}.pdf"); // Include all the (non-inline) attachments // XXX: Handle attachments with duplicate filenames between entry posts $attachments = Attachment::objects() ->filter([ 'thread_entry__thread' => $ticket->getThread(), 'inline' => 0 ]) ->order_by('thread_entry__created') ->select_related('file'); foreach ($attachments as $att) { $zip->addFromString("{$prefix}/{$att->getFilename()}", $att->getFile()->getData()); } // Include custom fields attachments foreach (DynamicFormEntry::forTicket($ticket->getId()) as $form) { $answers = $form->getAnswers()->filter( array('field__type' => 'files')); foreach ($answers as $answer) { $field = $answer->getField(); foreach ($field->getAttachments() as $a) $zip->addFromString("{$prefix}/{$a->getFilename()}", $a->getFile()->getData()); } } } function addTask($task, $zip, $prefix, $notes=true, $psize=null) { require_once(INCLUDE_DIR.'class.pdf.php'); $pdf_file = $this->tmpfiles[] = tempnam(sys_get_temp_dir(), 'zip'); $pdf = new Task2PDF($task, ['psize' => $psize]); $pdf->output($pdf_file, 'F'); $zip->addFile($pdf_file, "{$prefix}/{$task->getNumber()}.pdf"); // Include all the (non-inline) attachments // XXX: Handle attachments with duplicate filenames between entry posts $attachments = Attachment::objects() ->filter([ 'thread_entry__thread' => $task->getThread(), 'inline' => 0 ]) ->order_by('thread_entry__created') ->select_related('file'); foreach ($attachments as $att) { $zip->addFromString("{$prefix}/{$task->getNumber()}/{$att->getFilename()}", $att->getFile()->getData()); } // Include custom fields attachments foreach (DynamicFormEntry::forTask($task->getId()) as $form) { $answers = $form->getAnswers()->filter( array('field__type' => 'files')); foreach ($answers as $answer) { $field = $answer->getField(); foreach ($field->getAttachments() as $a) $zip->addFromString("{$prefix}/{$task->getNumber()}/{$a->getFilename()}", $a->getFile()->getData()); } } } function download($options = array()) { global $thisstaff; $notes = isset($options['notes']) ? $options['notes'] : false; $tasks = isset($options['tasks']) ? $options['tasks'] : false; // TODO: Use a streaming ZIP library $zipfile = tempnam(sys_get_temp_dir(), 'zip'); try { $zip = new ZipArchive(); if (!$zip->open($zipfile, ZipArchive::CREATE)) return; $prefix = "{$this->ticket->getNumber()}"; // Include a PDF of the ticket thread (with optional notes) if (!$thisstaff || !($psize = $thisstaff->getDefaultPaperSize())) $psize = 'Letter'; $this->addTicket($this->ticket, $zip, $prefix, $notes, $psize); if ($tasks) { foreach ($this->ticket->tasks as $task) $this->addTask($task, $zip, "{$prefix}/tasks", $notes, $psize); } $zip->close(); Http::download("ticket-{$this->ticket->getNumber()}.zip", "application/zip", null, 'attachment'); $fp = fopen($zipfile, 'r'); fpassthru($fp); fclose($fp); } finally { foreach ($this->tmpfiles as $T) @unlink($T); unlink($zipfile); } } }
Save