Compare commits
56 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7960e242cb | ||
|
|
a394f7cd6f | ||
|
|
7b3800bf36 | ||
|
|
8a348a6924 | ||
|
|
87249490f5 | ||
|
|
74b13887cd | ||
|
|
ecb26c0aff | ||
|
|
882c0aa6c0 | ||
|
|
22c0fac001 | ||
|
|
bdfece3569 | ||
|
|
e9bfc44b3c | ||
|
|
ab7fd654fa | ||
|
|
c9577e6136 | ||
|
|
f5d8a21dd2 | ||
|
|
e5ada3280a | ||
|
|
3561bee579 | ||
|
|
78c87c02ee | ||
|
|
cbd6117cea | ||
|
|
9ffff0efcd | ||
|
|
346222c5a0 | ||
|
|
7a7ee45864 | ||
|
|
3b84d4caf3 | ||
|
|
ab88c98f02 | ||
|
|
1fd4dbe1a1 | ||
|
|
66e04a6ab6 | ||
|
|
bf3879500f | ||
|
|
be93b908a4 | ||
|
|
17bd5c55d1 | ||
|
|
481c83ef6c | ||
|
|
6bc8ce4a23 | ||
|
|
24e957569b | ||
|
|
4e98dec006 | ||
|
|
38437db08c | ||
|
|
e2889f66a3 | ||
|
|
a470033a49 | ||
|
|
5241efcb79 | ||
|
|
5773711003 | ||
|
|
19053c7726 | ||
|
|
7a51bdc7b5 | ||
|
|
58fe8e47f5 | ||
|
|
3da10a8471 | ||
|
|
caa7a8ff3a | ||
|
|
064c71f43e | ||
|
|
45bf1633f9 | ||
|
|
e5794fd10b | ||
|
|
e9a17b16ed | ||
|
|
9aaee36e8f | ||
|
|
733edeb648 | ||
|
|
c33fb6f107 | ||
|
|
315859f89e | ||
|
|
6b7ed3d3e5 | ||
|
|
17ae48d4cc | ||
|
|
9d11a7c49c | ||
|
|
2ffe69c21b | ||
|
|
c9bbb7a6a8 | ||
|
|
c933754581 |
76
WHATSNEW.md
76
WHATSNEW.md
@@ -1,3 +1,79 @@
|
||||
osTicket v1.8.8
|
||||
===============
|
||||
### Improvements
|
||||
* Fix handling of some Redmond-specific character set encoding names (#1698)
|
||||
* Delete collaborators when deleting tickets (#1709)
|
||||
* Fix regression preventing auto-responses for staff new tickets (#1712)
|
||||
* Fix missing icon for "add new filter", thanks @Chefkeks (#1735)
|
||||
|
||||
### Performance and Security
|
||||
* Fix generation of random data on Windows® platforms (#1672)
|
||||
* Fix possible DoS and brute force on login pages (#1727)
|
||||
|
||||
osTicket v1.8.7
|
||||
===============
|
||||
### Improvements
|
||||
* Consider auto response checkbox and department setting for new ticket by
|
||||
staff (#1509)
|
||||
* Properly handle alert and auto response flags from API (#1435), thanks
|
||||
@stevepacker
|
||||
* Do not reopen tickets for automated responses (#1529)
|
||||
* Display FAQ article consistently on client portal (#1553)
|
||||
* Avoid wrapping password reset URLs on text emails (#1558)
|
||||
* Forbid disabling the only active administrator (#1569)
|
||||
* Searching for tickets searches to midnight of the end date (#1572),
|
||||
thanks @grintor
|
||||
* Fix rejection of tickets by filter, even if a previous matching filter
|
||||
would stop on match (#1644)
|
||||
* Fix matching of `User / Email Address` in ticket filters (#1644)
|
||||
* Skip team assignment alert on new ticket if assigned to an agent
|
||||
(fddb3c7)
|
||||
* Fix release of ticket lock when navigating away from ticket view (#1552)
|
||||
|
||||
### Performance and Security
|
||||
* Fix possible XSS vulnerability in sortable table view pages (#1639)
|
||||
|
||||
osTicket v1.8.6
|
||||
===============
|
||||
### Enhancements
|
||||
* Add new ost-config.php setting, `MAIL_EOL` which permanently defeats the
|
||||
newline corruption on outgoing email via the PHP `mail()` function
|
||||
(#1248)
|
||||
|
||||
### Improvements
|
||||
* Fix sorting by ticket number if using sequential numbers
|
||||
* Fix threading if HTML is enabled and QR is disabled (#1197)
|
||||
* Export ticket `created` date (#1201)
|
||||
* Fix duplicate email where a collaborator would receive a confirmation
|
||||
for his own message (#1235)
|
||||
* Fix multi-line display of checkbox descriptions (#1160)
|
||||
* Fix API validation failure for custom list selections (#1238)
|
||||
* Fix crash adding a new user with a selection field custom data
|
||||
* Fix failed user identification from email headers if `References` header
|
||||
is sorted differently be mail client (#1263)
|
||||
* Fix deletion of inline images on pages if draft was not saved (#1288)
|
||||
* Fix corruption of custom date time fields on client portal if using non
|
||||
US date format (#1320)
|
||||
* Fix corruption of email mailbox if improperly encoded as ISO-8859-1
|
||||
without RFC 2047 charset hint (#1332)
|
||||
* Fix occasional MySQL Commands OOS error from ORM (#1334)
|
||||
* Dashboard statistics should use 'period' as the date limiter (#1345)
|
||||
|
||||
### Performance and Security
|
||||
* Fix XSS vulnerability in email template management (#1162, #1163)
|
||||
|
||||
osTicket v1.8.5
|
||||
===============
|
||||
### Improvements
|
||||
* Fix missing `%{recipient}` variable used in canned reply (filters) (#1047)
|
||||
* Fix `%{ticket.close_date}` variable in email message templates (#1090)
|
||||
* Fix premature session expiration (#1111)
|
||||
* Correctly handle custom data for help topics (#1105)
|
||||
* Avoid system alert notices bouncing and creating tickets (#1115)
|
||||
|
||||
### Performance and Security
|
||||
* Fix XSS vulnerability in user name (#1108, #1131)
|
||||
|
||||
osTicket v1.8.4
|
||||
===============
|
||||
### Improvements
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Customizng Your Theme
|
||||
Customizing Your Theme
|
||||
====
|
||||
|
||||
When modifying the default theme, it is recommended that you do not
|
||||
|
||||
@@ -166,6 +166,9 @@ class TicketsAjaxAPI extends AjaxController {
|
||||
//dates
|
||||
$startTime =($req['startDate'] && (strlen($req['startDate'])>=8))?strtotime($req['startDate']):0;
|
||||
$endTime =($req['endDate'] && (strlen($req['endDate'])>=8))?strtotime($req['endDate']):0;
|
||||
if ($endTime)
|
||||
// $endTime should be the last second of the day, not the first like $startTime
|
||||
$endTime += (60 * 60 * 24) - 1;
|
||||
if( ($startTime && $startTime>time()) or ($startTime>$endTime && $endTime>0))
|
||||
$startTime=$endTime=0;
|
||||
|
||||
@@ -389,15 +392,15 @@ class TicketsAjaxAPI extends AjaxController {
|
||||
if ($user) {
|
||||
if ($user->getId() == $ticket->getOwnerId())
|
||||
$errors['err'] = sprintf('Ticket owner, %s, is a collaborator by default!',
|
||||
$user->getName());
|
||||
Format::htmlchars($user->getName()));
|
||||
elseif (($c=$ticket->addCollaborator($user,
|
||||
array('isactive'=>1), $errors))) {
|
||||
$note = Format::htmlchars(sprintf('%s <%s> added as a collaborator',
|
||||
$c->getName(), $c->getEmail()));
|
||||
Format::htmlchars($c->getName()), $c->getEmail()));
|
||||
$ticket->logNote('New Collaborator Added', $note,
|
||||
$thisstaff, false);
|
||||
$info = array('msg' => sprintf('%s added as a collaborator',
|
||||
$c->getName()));
|
||||
Format::htmlchars($c->getName())));
|
||||
return self::_collaborators($ticket, $info);
|
||||
}
|
||||
}
|
||||
@@ -426,7 +429,7 @@ class TicketsAjaxAPI extends AjaxController {
|
||||
return self::_collaborator($c ,$user->getForms($_POST), $errors);
|
||||
|
||||
$info = array('msg' => sprintf('%s updated successfully',
|
||||
$c->getName()));
|
||||
Format::htmlchars($c->getName())));
|
||||
|
||||
return self::_collaborators($ticket, $info);
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ class UsersAjaxAPI extends AjaxController {
|
||||
Http::response(404, 'Unknown user');
|
||||
|
||||
$info = array(
|
||||
'title' => sprintf('Update %s', $user->getName())
|
||||
'title' => sprintf('Update %s', Format::htmlchars($user->getName()))
|
||||
);
|
||||
$forms = $user->getForms();
|
||||
|
||||
|
||||
@@ -115,18 +115,20 @@ class TicketApiController extends ApiController {
|
||||
function createTicket($data) {
|
||||
|
||||
# Pull off some meta-data
|
||||
$alert = $data['alert'] ? $data['alert'] : true;
|
||||
$autorespond = $data['autorespond'] ? $data['autorespond'] : true;
|
||||
$data['source'] = $data['source'] ? $data['source'] : 'API';
|
||||
$alert = array_key_exists('alert', $data) ? $data['alert'] : true;
|
||||
$autorespond = array_key_exists('autorespond', $data) ? $data['autorespond'] : true;
|
||||
$data['source'] = array_key_exists('source', $data) ? $data['source'] : 'API';
|
||||
|
||||
# Create the ticket with the data (attempt to anyway)
|
||||
$errors = array();
|
||||
|
||||
if ($topic=Topic::lookup($data['topicId'])) {
|
||||
if ($form=DynamicForm::lookup($topic->ht['form_id'])) {
|
||||
$form = $form->instanciate();
|
||||
if (!$form->isValid())
|
||||
$errors += $form->errors();
|
||||
if ($topic_form = $topic->getForm()) {
|
||||
$TF = $topic_form->getForm($data);
|
||||
$topic_form = $topic_form->instanciate();
|
||||
$topic_form->setSource($data);
|
||||
if (!$TF->isValid())
|
||||
$errors = array_merge($errors, $TF->errors());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,9 +148,9 @@ class TicketApiController extends ApiController {
|
||||
}
|
||||
|
||||
# Save dynamic form
|
||||
if (isset($form)) {
|
||||
$form->setTicketId($ticket->getId());
|
||||
$form->save();
|
||||
if (isset($topic_form)) {
|
||||
$topic_form->setTicketId($ticket->getId());
|
||||
$topic_form->save();
|
||||
}
|
||||
|
||||
return $ticket;
|
||||
|
||||
@@ -343,7 +343,7 @@ class ApiXmlDataParser extends XmlDataParser {
|
||||
unset($value[":text"]);
|
||||
}
|
||||
if (isset($value['encoding']))
|
||||
$value['body'] = Format::utf8encode($value['body'], $value['encoding']);
|
||||
$value['body'] = Charset::utf8($value['body'], $value['encoding']);
|
||||
|
||||
if (!strcasecmp($value['type'], 'text/html'))
|
||||
$value = new HtmlThreadBody($value['body']);
|
||||
|
||||
75
include/class.charset.php
Normal file
75
include/class.charset.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/*********************************************************************
|
||||
class.charset.php
|
||||
|
||||
Charset util class
|
||||
|
||||
Copyright (c) 2015 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 Charset {
|
||||
|
||||
const UTF8 = 'utf-8';
|
||||
|
||||
// Cleanup invalid charsets
|
||||
// Thanks in part to https://github.com/mikel/mail/commit/88457e
|
||||
static function normalize($charset) {
|
||||
|
||||
$match = array();
|
||||
switch (true) {
|
||||
// Windows charsets - force correct format
|
||||
case preg_match('`^Windows-?(\d+)$`', $charset, $match):
|
||||
return 'Windows-'.$match[1];
|
||||
// ks_c_5601-1987: Korean alias for cp949
|
||||
case preg_match('`^ks_c_5601-1987`', $charset):
|
||||
return 'cp949';
|
||||
// Incorrect, bogus, ambiguous or empty charsets
|
||||
// ISO-8859-1 is assumed
|
||||
case preg_match('`^(default|x-user-defined|iso|us-ascii)`', $charset):
|
||||
case preg_match('`^\s*$`', $charset):
|
||||
return 'ISO-8859-1';
|
||||
}
|
||||
|
||||
// Hmmmm
|
||||
return $charset;
|
||||
}
|
||||
|
||||
// Translate characters ($text) from one encoding ($from) to another ($to)
|
||||
static function transcode($text, $from, $to) {
|
||||
|
||||
//Try auto-detecting charset/encoding
|
||||
if (!$from && function_exists('mb_detect_encoding'))
|
||||
$from = mb_detect_encoding($text);
|
||||
|
||||
// Normalize bogus or ambiguous charsets
|
||||
$from = self::normalize(trim($from));
|
||||
$to = self::normalize(trim($to));
|
||||
|
||||
$original = $text;
|
||||
if (function_exists('iconv'))
|
||||
$text = iconv($from, $to.'//IGNORE', $text);
|
||||
elseif (function_exists('mb_convert_encoding'))
|
||||
$text = mb_convert_encoding($text, $to, $from);
|
||||
elseif (!strcasecmp($to, 'utf-8')
|
||||
&& function_exists('utf8_encode')
|
||||
&& !strcasecmp($from, 'ISO-8859-1'))
|
||||
$text = utf8_encode($text);
|
||||
|
||||
// If $text is false, then we have a (likely) invalid charset, use
|
||||
// the original text and assume 8-bit (latin-1 / iso-8859-1)
|
||||
// encoding
|
||||
return (!$text && $original) ? $original : $text;
|
||||
}
|
||||
|
||||
//Wrapper for utf-8 transcoding.
|
||||
function utf8($text, $charset=null) {
|
||||
return self::transcode($text, $charset, self::UTF8);
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -37,9 +37,13 @@ abstract class TicketUser {
|
||||
$tag = substr($name, 3);
|
||||
switch (strtolower($tag)) {
|
||||
case 'ticket_link':
|
||||
return sprintf('%s/view.php?auth=%s',
|
||||
return sprintf('%s/view.php?%s',
|
||||
$cfg->getBaseUrl(),
|
||||
urlencode($this->getAuthToken()));
|
||||
Http::build_query(
|
||||
array('auth' => $this->getAuthToken()),
|
||||
false
|
||||
)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -129,8 +133,7 @@ abstract class TicketUser {
|
||||
}
|
||||
|
||||
function isOwner() {
|
||||
return ($this->user
|
||||
&& $this->user->getId() == $this->getTicket()->getOwnerId());
|
||||
return $this instanceof TicketOwner;
|
||||
}
|
||||
|
||||
abstract function getTicketId();
|
||||
|
||||
@@ -53,12 +53,15 @@ Class CSRF {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
function rotate() {
|
||||
$this->csrf['token'] = sha1(session_id().Crypto::random(16).SECRET_SALT);
|
||||
$this->csrf['time'] = time();
|
||||
}
|
||||
|
||||
function getToken() {
|
||||
|
||||
if(!$this->csrf['token'] || $this->isExpired()) {
|
||||
|
||||
$this->csrf['token'] = sha1(session_id().Crypto::random(16).SECRET_SALT);
|
||||
$this->csrf['time'] = time();
|
||||
if (!$this->csrf['token'] || $this->isExpired()) {
|
||||
$this->rotate();
|
||||
} else {
|
||||
//Reset the timer
|
||||
$this->csrf['time'] = time();
|
||||
|
||||
@@ -457,6 +457,7 @@ class DynamicFormEntry extends VerySimpleModel {
|
||||
var $_form;
|
||||
var $_errors = false;
|
||||
var $_clean = false;
|
||||
var $_source = null;
|
||||
|
||||
function getAnswers() {
|
||||
if (!isset($this->_values)) {
|
||||
@@ -506,12 +507,21 @@ class DynamicFormEntry extends VerySimpleModel {
|
||||
function getFields() {
|
||||
if (!isset($this->_fields)) {
|
||||
$this->_fields = array();
|
||||
foreach ($this->getAnswers() as $a)
|
||||
$this->_fields[] = $a->getField();
|
||||
foreach ($this->getAnswers() as $a) {
|
||||
$T = $this->_fields[] = $a->getField();
|
||||
$T->setForm($this);
|
||||
}
|
||||
}
|
||||
return $this->_fields;
|
||||
}
|
||||
|
||||
function getSource() {
|
||||
return $this->_source ?: (isset($this->id) ? false : $_POST);
|
||||
}
|
||||
function setSource($source) {
|
||||
$this->_source = $source;
|
||||
}
|
||||
|
||||
function getField($name) {
|
||||
|
||||
foreach ($this->getFields() as $field)
|
||||
@@ -631,8 +641,8 @@ class DynamicFormEntry extends VerySimpleModel {
|
||||
if (count($this->dirty))
|
||||
$this->set('updated', new SqlFunction('NOW'));
|
||||
parent::save();
|
||||
foreach ($this->getAnswers() as $a) {
|
||||
$field = $a->getField();
|
||||
foreach ($this->getFields() as $field) {
|
||||
$a = $field->getAnswer();
|
||||
if ($this->object_type == 'U'
|
||||
&& in_array($field->get('name'), array('name','email')))
|
||||
continue;
|
||||
@@ -894,15 +904,20 @@ class SelectionField extends FormField {
|
||||
function parse($value) {
|
||||
$config = $this->getConfiguration();
|
||||
if (is_int($value))
|
||||
return $this->to_php($this->getWidget()->getEnteredValue(), (int) $value);
|
||||
$val = $this->to_php($this->getWidget()->getEnteredValue(), (int) $value);
|
||||
elseif (!$config['typeahead'])
|
||||
return $this->to_php(null, (int) $value);
|
||||
else
|
||||
return $this->to_php($value);
|
||||
$val = $this->to_php(null, (int) $value);
|
||||
if (!$val)
|
||||
$val = $this->to_php($value);
|
||||
return $val;
|
||||
}
|
||||
|
||||
function to_php($value, $id=false) {
|
||||
if ($id && is_int($id))
|
||||
if ($value === null && $id === null)
|
||||
return null;
|
||||
if ($value instanceof DynamicListItem)
|
||||
$item = $value;
|
||||
elseif ($id && is_int($id))
|
||||
$item = DynamicListItem::lookup($id);
|
||||
# Attempt item lookup by name too
|
||||
if (!$item || ($value !== null && $value != $item->get('value'))) {
|
||||
|
||||
@@ -57,8 +57,8 @@ class Export {
|
||||
$sql = str_replace(' FROM ', ',' . implode(',', $select) . ' FROM ', $sql);
|
||||
return self::dumpQuery($sql,
|
||||
array(
|
||||
'number' => 'Ticket Number',
|
||||
'created' => 'Date',
|
||||
'number' => 'Ticket Number',
|
||||
'ticket_created' => 'Date',
|
||||
'subject' => 'Subject',
|
||||
'name' => 'From',
|
||||
'email' => 'From Email',
|
||||
|
||||
@@ -180,9 +180,7 @@ class FAQ {
|
||||
|
||||
// Inline images (attached to the draft)
|
||||
$this->attachments->deleteInlines();
|
||||
if (isset($vars['draft_id']) && $vars['draft_id'])
|
||||
if ($draft = Draft::lookup($vars['draft_id']))
|
||||
$this->attachments->upload($draft->getAttachmentIds(), true);
|
||||
$this->attachments->upload(Draft::getAttachmentIds($vars['answer']));
|
||||
|
||||
$this->reload();
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ class Filter {
|
||||
}
|
||||
|
||||
function stopOnMatch() {
|
||||
return ($this->ht['stop_on_match']);
|
||||
return ($this->ht['stop_onmatch']);
|
||||
}
|
||||
|
||||
function matchAllRules() {
|
||||
@@ -716,7 +716,7 @@ class TicketFilter {
|
||||
$res = $this->getAllActive();
|
||||
if($res) {
|
||||
while (list($id) = db_fetch_row($res))
|
||||
array_push($this->filters, new Filter($id));
|
||||
$this->filters[] = new Filter($id);
|
||||
}
|
||||
|
||||
return $this->filters;
|
||||
@@ -742,36 +742,25 @@ class TicketFilter {
|
||||
|
||||
return $this->short_list;
|
||||
}
|
||||
/**
|
||||
* Determine if the filters that match the received vars indicate that
|
||||
* the email should be rejected
|
||||
*
|
||||
* Returns FALSE if the email should be acceptable. If the email should
|
||||
* be rejected, the first filter that matches and has reject ticket set is
|
||||
* returned.
|
||||
*/
|
||||
function shouldReject() {
|
||||
foreach ($this->getMatchingFilterList() as $filter) {
|
||||
# Set reject if this filter indicates that the email should
|
||||
# be blocked; however, don't unset $reject, because if it
|
||||
# was set by another rule that did not set stopOnMatch(), we
|
||||
# should still honor its configuration
|
||||
if ($filter->rejectOnMatch()) return $filter;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Determine if any filters match the received email, and if so, apply
|
||||
* actions defined in those filters to the ticket-to-be-created.
|
||||
*
|
||||
* Throws:
|
||||
* RejectedException if the email should not be acceptable. If the email
|
||||
* should be rejected, the first filter that matches and has reject
|
||||
* ticket set is returned.
|
||||
*/
|
||||
function apply(&$ticket) {
|
||||
foreach ($this->getMatchingFilterList() as $filter) {
|
||||
if ($filter->rejectOnMatch())
|
||||
throw new RejectedException($filter);
|
||||
$filter->apply($ticket, $this->vars);
|
||||
if ($filter->stopOnMatch()) break;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ function getAllActive() {
|
||||
function getAllActive() {
|
||||
|
||||
$sql='SELECT id FROM '.FILTER_TABLE
|
||||
.' WHERE isactive=1 '
|
||||
@@ -927,6 +916,19 @@ class TicketFilter {
|
||||
}
|
||||
}
|
||||
|
||||
class RejectedException extends Exception {
|
||||
var $filter;
|
||||
|
||||
function __construct(Filter $filter) {
|
||||
parent::__construct('Ticket rejected by a filter');
|
||||
$this->filter = $filter;
|
||||
}
|
||||
|
||||
function getRejectingFilter() {
|
||||
return $this->filter;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function: endsWith
|
||||
*
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
vim: expandtab sw=4 ts=4 sts=4:
|
||||
**********************************************************************/
|
||||
|
||||
include_once INCLUDE_DIR.'class.charset.php';
|
||||
|
||||
class Format {
|
||||
|
||||
@@ -30,52 +31,19 @@ class Format {
|
||||
return round(($bytes/1048576),1).' mb';
|
||||
}
|
||||
|
||||
/* encode text into desired encoding - taking into accout charset when available. */
|
||||
function encode($text, $charset=null, $encoding='utf-8') {
|
||||
|
||||
//Try auto-detecting charset/encoding
|
||||
if (!$charset && function_exists('mb_detect_encoding'))
|
||||
$charset = mb_detect_encoding($text);
|
||||
|
||||
// Cleanup - incorrect, bogus, or ambiguous charsets
|
||||
// ISO-8859-1 is assumed for empty charset.
|
||||
if (!$charset || in_array(strtolower(trim($charset)),
|
||||
array('default','x-user-defined','iso','us-ascii')))
|
||||
$charset = 'ISO-8859-1';
|
||||
|
||||
$original = $text;
|
||||
if (function_exists('iconv'))
|
||||
$text = iconv($charset, $encoding.'//IGNORE', $text);
|
||||
elseif (function_exists('mb_convert_encoding'))
|
||||
$text = mb_convert_encoding($text, $encoding, $charset);
|
||||
elseif (!strcasecmp($encoding, 'utf-8')
|
||||
&& function_exists('utf8_encode')
|
||||
&& !strcasecmp($charset, 'ISO-8859-1'))
|
||||
$text = utf8_encode($text);
|
||||
|
||||
// If $text is false, then we have a (likely) invalid charset, use
|
||||
// the original text and assume 8-bit (latin-1 / iso-8859-1)
|
||||
// encoding
|
||||
return (!$text && $original) ? $original : $text;
|
||||
}
|
||||
|
||||
//Wrapper for utf-8 encoding.
|
||||
function utf8encode($text, $charset=null) {
|
||||
return Format::encode($text, $charset, 'utf-8');
|
||||
}
|
||||
|
||||
function mimedecode($text, $encoding='UTF-8') {
|
||||
|
||||
if(function_exists('imap_mime_header_decode')
|
||||
&& ($parts = imap_mime_header_decode($text))) {
|
||||
$str ='';
|
||||
foreach ($parts as $part)
|
||||
$str.= Format::encode($part->text, $part->charset, $encoding);
|
||||
$str.= Charset::transcode($part->text, $part->charset, $encoding);
|
||||
|
||||
$text = $str;
|
||||
} elseif(function_exists('iconv_mime_decode')) {
|
||||
} elseif($text[0] == '=' && function_exists('iconv_mime_decode')) {
|
||||
$text = iconv_mime_decode($text, 0, $encoding);
|
||||
} elseif(!strcasecmp($encoding, 'utf-8') && function_exists('imap_utf8')) {
|
||||
} elseif(!strcasecmp($encoding, 'utf-8')
|
||||
&& function_exists('imap_utf8')) {
|
||||
$text = imap_utf8($text);
|
||||
}
|
||||
|
||||
@@ -94,7 +62,7 @@ class Format {
|
||||
$filename, $match))
|
||||
// XXX: Currently we don't care about the language component.
|
||||
// The encoding hint is sufficient.
|
||||
return self::utf8encode(urldecode($match[3]), $match[1]);
|
||||
return Charset::utf8(urldecode($match[3]), $match[1]);
|
||||
else
|
||||
return $filename;
|
||||
}
|
||||
@@ -186,7 +154,7 @@ class Format {
|
||||
$s = str_replace('"','', $s);
|
||||
}
|
||||
if ($styles)
|
||||
$attributes['style'] = Format::htmlencode(implode(';', $styles));
|
||||
$attributes['style'] = Format::htmlchars(implode(';', $styles));
|
||||
else
|
||||
unset($attributes['style']);
|
||||
}
|
||||
@@ -243,18 +211,23 @@ class Format {
|
||||
return $striptags?Format::striptags($text, false):$text;
|
||||
}
|
||||
|
||||
function htmlchars($var) {
|
||||
return Format::htmlencode($var);
|
||||
}
|
||||
function htmlchars($var, $sanitize = false) {
|
||||
|
||||
if (is_array($var))
|
||||
return array_map(array('Format', 'htmlchars'), $var);
|
||||
|
||||
if ($sanitize)
|
||||
$var = Format::sanitize($var);
|
||||
|
||||
function htmlencode($var) {
|
||||
$flags = ENT_COMPAT;
|
||||
if (phpversion() >= '5.4.0')
|
||||
$flags |= ENT_HTML401;
|
||||
|
||||
return is_array($var)
|
||||
? array_map(array('Format','htmlencode'), $var)
|
||||
: htmlentities($var, $flags, 'UTF-8');
|
||||
try {
|
||||
return htmlspecialchars( (string) $var, $flags, 'UTF-8', false);
|
||||
} catch(Exception $e) {
|
||||
return $var;
|
||||
}
|
||||
}
|
||||
|
||||
function htmldecode($var) {
|
||||
@@ -266,11 +239,11 @@ class Format {
|
||||
if (phpversion() >= '5.4.0')
|
||||
$flags |= ENT_HTML401;
|
||||
|
||||
return html_entity_decode($var, $flags, 'UTF-8');
|
||||
return htmlspecialchars_decode($var, $flags);
|
||||
}
|
||||
|
||||
function input($var) {
|
||||
return Format::htmlencode($var);
|
||||
return Format::htmlchars($var);
|
||||
}
|
||||
|
||||
//Format text for display..
|
||||
@@ -529,7 +502,7 @@ class Format {
|
||||
$contents = base64_decode($contents);
|
||||
}
|
||||
if ($output_encoding && $charset)
|
||||
$contents = Format::encode($contents, $charset, $output_encoding);
|
||||
$contents = Charset::transcode($contents, $charset, $output_encoding);
|
||||
|
||||
return array(
|
||||
'data' => $contents,
|
||||
|
||||
@@ -588,6 +588,18 @@ class TextareaField extends FormField {
|
||||
else
|
||||
return nl2br(Format::htmlchars($value));
|
||||
}
|
||||
|
||||
function export($value) {
|
||||
return (!$value) ? $value : Format::html2text($value);
|
||||
}
|
||||
|
||||
function parse($value) {
|
||||
$config = $this->getConfiguration();
|
||||
if ($config['html'])
|
||||
return Format::sanitize($value);
|
||||
else
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
class PhoneField extends FormField {
|
||||
@@ -634,7 +646,9 @@ class PhoneField extends FormField {
|
||||
function parse($value) {
|
||||
// NOTE: Value may have a legitimate 'X' to separate the number and
|
||||
// extension parts. Don't remove the 'X'
|
||||
return preg_replace('/[^\dX]/', '', $value);
|
||||
$val = preg_replace('/[^\dX]/', '', $value);
|
||||
// Pass completely-incorrect string for validation error
|
||||
return $val ?: $value;
|
||||
}
|
||||
|
||||
function toString($value) {
|
||||
@@ -997,8 +1011,10 @@ class TextareaWidget extends Widget {
|
||||
$cols = "cols=\"{$config['cols']}\"";
|
||||
if (isset($config['length']) && $config['length'])
|
||||
$maxlength = "maxlength=\"{$config['length']}\"";
|
||||
if (isset($config['html']) && $config['html'])
|
||||
if (isset($config['html']) && $config['html']) {
|
||||
$class = 'class="richtext no-bar small"';
|
||||
$this->value = Format::viewableImages($this->value);
|
||||
}
|
||||
?>
|
||||
<span style="display:inline-block;width:100%">
|
||||
<textarea <?php echo $rows." ".$cols." ".$maxlength." ".$class
|
||||
@@ -1092,13 +1108,13 @@ class CheckboxWidget extends Widget {
|
||||
function render() {
|
||||
$config = $this->field->getConfiguration();
|
||||
?>
|
||||
<input type="checkbox" name="<?php echo $this->name; ?>[]" <?php
|
||||
<input style="vertical-align:top;" type="checkbox" name="<?php echo $this->name; ?>[]" <?php
|
||||
if ($this->value) echo 'checked="checked"'; ?> value="<?php
|
||||
echo $this->field->get('id'); ?>"/>
|
||||
<?php
|
||||
if ($config['desc']) { ?>
|
||||
<em style="display:inline-block"><?php
|
||||
echo Format::htmlchars($config['desc']); ?></em>
|
||||
echo Format::viewableImages($config['desc']); ?></em>
|
||||
<?php }
|
||||
}
|
||||
|
||||
|
||||
@@ -111,5 +111,10 @@ class Http {
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
static function build_query($vars, $encode=true, $separator='&') {
|
||||
return http_build_query(
|
||||
($encode ? Format::htmlchars($vars) : $vars), '', $separator);
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -25,11 +25,12 @@ class Mailer {
|
||||
|
||||
var $ht = array();
|
||||
var $attachments = array();
|
||||
var $options = array();
|
||||
|
||||
var $smtp = array();
|
||||
var $eol="\n";
|
||||
|
||||
function Mailer($email=null, $options=null) {
|
||||
function Mailer($email=null, array $options=array()) {
|
||||
global $cfg;
|
||||
|
||||
if(is_object($email) && $email->isSMTPEnabled() && ($info=$email->getSMTPInfo())) { //is SMTP enabled for the current email?
|
||||
@@ -46,6 +47,7 @@ class Mailer {
|
||||
|
||||
$this->email = $email;
|
||||
$this->attachments = array();
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
function getEOL() {
|
||||
@@ -114,7 +116,12 @@ class Mailer {
|
||||
'X-Mailer' =>'osTicket Mailer',
|
||||
);
|
||||
|
||||
if ($this->getEmail() instanceof Email)
|
||||
// Add in the options passed to the constructor
|
||||
$options = ($options ?: array()) + $this->options;
|
||||
|
||||
if (isset($options['nobounce']) && $options['nobounce'])
|
||||
$headers['Return-Path'] = '<>';
|
||||
elseif ($this->getEmail() instanceof Email)
|
||||
$headers['Return-Path'] = $this->getEmail()->getEmail();
|
||||
|
||||
//Bulk.
|
||||
@@ -148,6 +155,13 @@ class Mailer {
|
||||
}
|
||||
}
|
||||
|
||||
// Use Mail_mime default initially
|
||||
$eol = null;
|
||||
|
||||
// MAIL_EOL setting can be defined in `ost-config.php`
|
||||
if (defined('MAIL_EOL') && is_string(MAIL_EOL)) {
|
||||
$eol = MAIL_EOL;
|
||||
}
|
||||
// The Suhosin patch will muck up the line endings in some
|
||||
// cases
|
||||
//
|
||||
@@ -155,12 +169,12 @@ class Mailer {
|
||||
// https://github.com/osTicket/osTicket-1.8/issues/202
|
||||
// http://pear.php.net/bugs/bug.php?id=12032
|
||||
// http://us2.php.net/manual/en/function.mail.php#97680
|
||||
if ((extension_loaded('suhosin') || defined("SUHOSIN_PATCH"))
|
||||
&& !$this->getSMTPInfo())
|
||||
$mime = new Mail_mime("\n");
|
||||
else
|
||||
// Use defaults
|
||||
$mime = new Mail_mime();
|
||||
elseif ((extension_loaded('suhosin') || defined("SUHOSIN_PATCH"))
|
||||
&& !$this->getSMTPInfo()
|
||||
) {
|
||||
$eol = "\n";
|
||||
}
|
||||
$mime = new Mail_mime($eol);
|
||||
|
||||
// If the message is not explicitly declared to be a text message,
|
||||
// then assume that it needs html processing to create a valid text
|
||||
@@ -169,10 +183,12 @@ class Mailer {
|
||||
$mid_token = (isset($options['thread']))
|
||||
? $options['thread']->asMessageId($to) : '';
|
||||
if (!(isset($options['text']) && $options['text'])) {
|
||||
if ($cfg && $cfg->stripQuotedReply() && ($tag=$cfg->getReplySeparator())
|
||||
$tag = '';
|
||||
if ($cfg && $cfg->stripQuotedReply()
|
||||
&& (!isset($options['reply-tag']) || $options['reply-tag']))
|
||||
$message = "<div style=\"display:none\"
|
||||
data-mid=\"$mid_token\">$tag<br/><br/></div>$message";
|
||||
$tag = $cfg->getReplySeparator() . '<br/><br/>';
|
||||
$message = "<div style=\"display:none\"
|
||||
data-mid=\"$mid_token\">$tag</div>$message";
|
||||
// Make sure nothing unsafe has creeped into the message
|
||||
$message = Format::safe_html($message); //XXX??
|
||||
$txtbody = rtrim(Format::html2text($message, 90, false))
|
||||
@@ -287,7 +303,7 @@ class Mailer {
|
||||
//Emails using native php mail function - if DB connection doesn't exist.
|
||||
//Don't use this function if you can help it.
|
||||
function sendmail($to, $subject, $message, $from) {
|
||||
$mailer = new Mailer();
|
||||
$mailer = new Mailer(null, array('notice'=>true, 'nobounce'=>true));
|
||||
$mailer->setFromAddress($from);
|
||||
return $mailer->send($to, $subject, $message);
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@ class MailFetcher {
|
||||
|
||||
//Convert text to desired encoding..defaults to utf8
|
||||
function mime_encode($text, $charset=null, $encoding='utf-8') { //Thank in part to afterburner
|
||||
return Format::encode($text, $charset, $encoding);
|
||||
return Charset::transcode($text, $charset, $encoding);
|
||||
}
|
||||
|
||||
function mailbox_encode($mailbox) {
|
||||
@@ -241,7 +241,7 @@ class MailFetcher {
|
||||
if (function_exists('mb_detect_encoding'))
|
||||
if (($src_enc = mb_detect_encoding($text))
|
||||
&& (strcasecmp($src_enc, 'ASCII') !== 0))
|
||||
return Format::encode($text, $src_enc, $encoding);
|
||||
return Charset::transcode($text, $src_enc, $encoding);
|
||||
|
||||
// Handle ASCII text and RFC-2047 encoding
|
||||
$str = '';
|
||||
|
||||
@@ -320,7 +320,7 @@ class Mail_Parse {
|
||||
$content = $struct->body;
|
||||
//Encode to desired encoding - ONLY if charset is known??
|
||||
if (isset($struct->ctype_parameters['charset']))
|
||||
$content = Format::encode($content,
|
||||
$content = Charset::transcode($content,
|
||||
$struct->ctype_parameters['charset'], $this->charset);
|
||||
|
||||
return $content;
|
||||
@@ -343,7 +343,7 @@ class Mail_Parse {
|
||||
|
||||
|
||||
function mime_encode($text, $charset=null, $encoding='utf-8') {
|
||||
return Format::encode($text, $charset, $encoding);
|
||||
return Charset::transcode($text, $charset, $encoding);
|
||||
}
|
||||
|
||||
function getAttachments($part=null){
|
||||
@@ -498,12 +498,18 @@ class Mail_Parse {
|
||||
|
||||
$parsed = Mail_RFC822::parseAddressList($address, null, null,false);
|
||||
|
||||
if(PEAR::isError($parsed))
|
||||
if (PEAR::isError($parsed))
|
||||
return array();
|
||||
|
||||
// Decode name and mailbox
|
||||
foreach ($parsed as $p) {
|
||||
$p->personal = Format::mimedecode($p->personal, $this->charset);
|
||||
// Some mail clients may send ISO-8859-1 strings without proper encoding.
|
||||
// Also, handle the more sane case where the mailbox is properly encoded
|
||||
// against RFC2047
|
||||
$p->mailbox = Format::mimedecode($p->mailbox, $this->charset);
|
||||
}
|
||||
|
||||
return $parsed;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,14 +15,30 @@
|
||||
**********************************************************************/
|
||||
class Misc {
|
||||
|
||||
function randCode($count=8, $chars=false) {
|
||||
$chars = $chars ? $chars
|
||||
: 'abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.';
|
||||
$data = '';
|
||||
$m = strlen($chars) - 1;
|
||||
for ($i=0; $i < $count; $i++)
|
||||
$data .= $chars[mt_rand(0,$m)];
|
||||
return $data;
|
||||
function randCode($len=8, $chars=false) {
|
||||
$chars = $chars ?: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_=';
|
||||
|
||||
// Determine the number of bits we need
|
||||
$char_count = strlen($chars);
|
||||
$bits_per_char = ceil(log($char_count, 2));
|
||||
$bytes = ceil(4 * $len / floor(32 / $bits_per_char));
|
||||
// Pad to 4 byte boundary
|
||||
$bytes += (4 - ($bytes % 4)) % 4;
|
||||
|
||||
// Fetch some random data blocks
|
||||
$data = Crypto::random($bytes);
|
||||
|
||||
$mask = (1 << $bits_per_char) - 1;
|
||||
$loops = (int) (32 / $bits_per_char);
|
||||
$output = '';
|
||||
$ints = unpack('V*', $data);
|
||||
foreach ($ints as $int) {
|
||||
for ($i = $loops; $i > 0; $i--) {
|
||||
$output .= $chars[($int & $mask) % $char_count];
|
||||
$int >>= $bits_per_char;
|
||||
}
|
||||
}
|
||||
return substr($output, 0, $len);
|
||||
}
|
||||
|
||||
function __rand_seed($value=0) {
|
||||
|
||||
@@ -885,14 +885,20 @@ class MysqlExecutor {
|
||||
}
|
||||
|
||||
function _prepare() {
|
||||
$this->execute();
|
||||
$this->_setup_output();
|
||||
}
|
||||
|
||||
function execute() {
|
||||
if (!($this->stmt = db_prepare($this->sql)))
|
||||
throw new Exception('Unable to prepare query: '.db_error()
|
||||
.' '.$this->sql);
|
||||
if (count($this->params))
|
||||
$this->_bind($this->params);
|
||||
$this->stmt->execute();
|
||||
$this->_setup_output();
|
||||
$this->stmt->store_result();
|
||||
if (!$this->stmt->execute() || ! $this->stmt->store_result()) {
|
||||
throw new Exception('Unable to execute query: ' . $this->stmt->error);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function _bind($params) {
|
||||
|
||||
@@ -240,7 +240,7 @@ class osTicket {
|
||||
$email=$this->getConfig()->getDefaultEmail(); //will take the default email.
|
||||
|
||||
if($email) {
|
||||
$email->sendAlert($to, $subject, $message, null, array('text'=>true));
|
||||
$email->sendAlert($to, $subject, $message, null, array('text'=>true, 'reply-tag'=>false));
|
||||
} else {//no luck - try the system mail.
|
||||
Mailer::sendmail($to, $subject, $message, sprintf('"osTicket Alerts"<%s>',$to));
|
||||
}
|
||||
|
||||
@@ -22,9 +22,7 @@ class osTicketSession {
|
||||
var $id = '';
|
||||
|
||||
function osTicketSession($ttl=0){
|
||||
$this->ttl =$ttl?$ttl:get_cfg_var('session.gc_maxlifetime');
|
||||
if(!$this->ttl)
|
||||
$this->ttl=SESSION_TTL;
|
||||
$this->ttl = $ttl ?: ini_get('session.gc_maxlifetime') ?: SESSION_TTL;
|
||||
|
||||
// Set osTicket specific session name.
|
||||
session_name('OSTSESSID');
|
||||
@@ -32,6 +30,9 @@ class osTicketSession {
|
||||
// Forced cleanup on shutdown
|
||||
register_shutdown_function('session_write_close');
|
||||
|
||||
// Set session cleanup time to match TTL
|
||||
ini_set('session.gc_maxlifetime', $ttl);
|
||||
|
||||
if (OsticketConfig::getDBVersion())
|
||||
return session_start();
|
||||
|
||||
@@ -48,7 +49,7 @@ class osTicketSession {
|
||||
// Remote port specification, as it will make an invalid domain
|
||||
list($domain) = explode(':', $_SERVER['HTTP_HOST']);
|
||||
|
||||
session_set_cookie_params(86400, ROOT_PATH, $domain,
|
||||
session_set_cookie_params($ttl, ROOT_PATH, $domain,
|
||||
osTicket::is_https());
|
||||
|
||||
//Set handlers.
|
||||
|
||||
@@ -37,14 +37,19 @@ class PageNate {
|
||||
}
|
||||
$this->setURL($url);
|
||||
}
|
||||
function setURL($url='',$vars=''){
|
||||
if($url){
|
||||
if(strpos($url,'?')===false)
|
||||
$url=$url.'?';
|
||||
}else{
|
||||
$url=THISPAGE.'?';
|
||||
|
||||
function setURL($url='',$vars='') {
|
||||
if ($url) {
|
||||
if (strpos($url, '?')===false)
|
||||
$url .= '?';
|
||||
} else {
|
||||
$url = THISPAGE.'?';
|
||||
}
|
||||
$this->url=$url.$vars;
|
||||
|
||||
if ($vars && is_array($vars))
|
||||
$vars = Http::build_query($vars);
|
||||
|
||||
$this->url = $url.$vars;
|
||||
}
|
||||
|
||||
function getStart() {
|
||||
|
||||
@@ -845,6 +845,19 @@ class Staff extends AuthenticatedUser {
|
||||
if(!$vars['timezone_id'])
|
||||
$errors['timezone_id']='Time zone required';
|
||||
|
||||
// Ensure we will still have an administrator with access
|
||||
if ($vars['isadmin'] !== '1' || $vars['isactive'] !== '1') {
|
||||
$sql = 'select count(*), max(staff_id) from '.STAFF_TABLE
|
||||
.' WHERE isadmin=1 and isactive=1';
|
||||
if (($res = db_query($sql))
|
||||
&& (list($count, $sid) = db_fetch_row($res))) {
|
||||
if ($count == 1 && $sid == $id) {
|
||||
$errors['isadmin'] =
|
||||
'Cowardly refusing to remove or lock out the only active administrator';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($errors) return false;
|
||||
|
||||
|
||||
|
||||
@@ -197,10 +197,18 @@ class Thread {
|
||||
return false;
|
||||
|
||||
$this->deleteAttachments();
|
||||
$this->removeCollaborators();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function removeCollaborators() {
|
||||
$sql='DELETE FROM '.TICKET_COLLABORATOR_TABLE
|
||||
.' WHERE ticket_id='.db_input($this->getTicketId());
|
||||
|
||||
return (db_query($sql) && db_affected_rows());
|
||||
}
|
||||
|
||||
/* static */
|
||||
function lookup($ticket) {
|
||||
|
||||
@@ -347,14 +355,14 @@ Class ThreadEntry {
|
||||
return $this->ht['@headers'];
|
||||
}
|
||||
|
||||
function getEmailReferences() {
|
||||
if (!isset($this->_references)) {
|
||||
$headers = self::getEmailHeaderArray();
|
||||
if (isset($headers['References']) && $headers['References'])
|
||||
$this->_references = $headers['References']." ";
|
||||
$this->_references .= $this->getEmailMessageId();
|
||||
}
|
||||
return $this->_references;
|
||||
function getEmailReferences($include_mid=true) {
|
||||
$references = '';
|
||||
$headers = self::getEmailHeaderArray();
|
||||
if (isset($headers['References']) && $headers['References'])
|
||||
$references = $headers['References']." ";
|
||||
if ($include_mid)
|
||||
$references .= $this->getEmailMessageId();
|
||||
return $references;
|
||||
}
|
||||
|
||||
function getTaggedEmailReferences($prefix, $refId) {
|
||||
@@ -364,7 +372,7 @@ Class ThreadEntry {
|
||||
$mid = substr_replace($this->getEmailMessageId(),
|
||||
$ref, strpos($this->getEmailMessageId(), '@'), 0);
|
||||
|
||||
return sprintf('%s %s', $this->getEmailReferences(), $mid);
|
||||
return sprintf('%s %s', $this->getEmailReferences(false), $mid);
|
||||
}
|
||||
|
||||
function getEmailReferencesForUser($user) {
|
||||
@@ -418,11 +426,11 @@ Class ThreadEntry {
|
||||
if (!($ticket = $this->getTicket()))
|
||||
return null;
|
||||
|
||||
if ($ticket->getOwnerId() == $ticket->getUserId())
|
||||
if ($ticket->getOwnerId() == $this->getUserId())
|
||||
$this->user = new TicketOwner(
|
||||
User::lookup($this->getUserId()), $ticket);
|
||||
else
|
||||
$this->user = Collborator::lookup(array(
|
||||
$this->user = Collaborator::lookup(array(
|
||||
'userId'=>$this->getUserId(), 'ticketId'=>$this->getTicketId()));
|
||||
}
|
||||
|
||||
@@ -834,7 +842,7 @@ Class ThreadEntry {
|
||||
return ThreadEntry::lookup($id);
|
||||
}
|
||||
|
||||
foreach (array('mid', 'in-reply-to', 'references') as $header) {
|
||||
foreach (array('in-reply-to', 'references') as $header) {
|
||||
$matches = array();
|
||||
if (!isset($mailinfo[$header]) || !$mailinfo[$header])
|
||||
continue;
|
||||
@@ -848,6 +856,7 @@ Class ThreadEntry {
|
||||
// (parent) on the far right.
|
||||
// @see rfc 1036, section 2.2.5
|
||||
// @see http://www.jwz.org/doc/threading.html
|
||||
$thread = null;
|
||||
foreach (array_reverse($matches[0]) as $mid) {
|
||||
//Try to determine if it's a reply to a tagged email.
|
||||
$ref = null;
|
||||
@@ -858,20 +867,29 @@ Class ThreadEntry {
|
||||
}
|
||||
$res = db_query(sprintf($search, db_input($mid)));
|
||||
while (list($id) = db_fetch_row($res)) {
|
||||
if (!($t = ThreadEntry::lookup($id))) continue;
|
||||
|
||||
//We found a match - see if we can ID the user.
|
||||
if (!($t = ThreadEntry::lookup($id)))
|
||||
continue;
|
||||
// Capture the first match thread item
|
||||
if (!$thread)
|
||||
$thread = $t;
|
||||
// We found a match - see if we can ID the user.
|
||||
// XXX: Check access of ref is enough?
|
||||
if ($ref && ($uid = $t->getUIDFromEmailReference($ref))) {
|
||||
if ($ref[0] =='s') //staff
|
||||
$mailinfo['staffId'] = $uid;
|
||||
else //user or collaborator.
|
||||
else // user or collaborator.
|
||||
$mailinfo['userId'] = $uid;
|
||||
}
|
||||
|
||||
return $t;
|
||||
// Best possible case — found the thread and the
|
||||
// user
|
||||
return $t;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Second best case — found a thread but couldn't identify the
|
||||
// user from the header. Return the first thread entry matched
|
||||
if ($thread)
|
||||
return $thread;
|
||||
}
|
||||
|
||||
// Search for ticket by the [#123456] in the subject line
|
||||
|
||||
@@ -1035,7 +1035,7 @@ class Ticket {
|
||||
$options = array('inreplyto' => $entry->getEmailMessageId(),
|
||||
'thread' => $entry);
|
||||
foreach ($recipients as $recipient) {
|
||||
if ($uid == $recipient->getId()) continue;
|
||||
if ($uid == $recipient->getUserId()) continue;
|
||||
$options['references'] = $entry->getEmailReferencesForUser($recipient);
|
||||
$notice = $this->replaceVars($msg, array('recipient' => $recipient));
|
||||
$email->send($recipient->getEmail(), $notice['subj'], $notice['body'], $attachments,
|
||||
@@ -1069,7 +1069,11 @@ class Ticket {
|
||||
}
|
||||
|
||||
// Reopen if closed.
|
||||
if($this->isClosed()) $this->reopen();
|
||||
// We're also checking autorespond flag because we don't want to
|
||||
// reopen closed tickets on auto-reply from end user. This is not to
|
||||
// confused with autorespond on new message setting
|
||||
if ($autorespond && $this->isClosed())
|
||||
$this->reopen();
|
||||
|
||||
/********** double check auto-response ************/
|
||||
if (!($user = $message->getUser()))
|
||||
@@ -1267,10 +1271,10 @@ class Ticket {
|
||||
|
||||
return $duedate;
|
||||
break;
|
||||
case 'close_date';
|
||||
case 'close_date':
|
||||
$closedate ='';
|
||||
if($this->isClosed())
|
||||
$duedate = Format::date(
|
||||
$closedate = Format::date(
|
||||
$cfg->getDateTimeFormat(),
|
||||
Misc::db2gmtime($this->getCloseDate()),
|
||||
$cfg->getTZOffset(),
|
||||
@@ -1675,7 +1679,11 @@ class Ticket {
|
||||
$signature='';
|
||||
|
||||
$msg = $this->replaceVars($msg->asArray(),
|
||||
array('response' => $response, 'signature' => $signature));
|
||||
array(
|
||||
'response' => $response,
|
||||
'signature' => $signature,
|
||||
'recipient' => $this->getOwner(),
|
||||
));
|
||||
|
||||
$attachments =($cfg->emailAttachments() && $files)?$response->getAttachments():array();
|
||||
$options = array(
|
||||
@@ -2160,7 +2168,8 @@ class Ticket {
|
||||
*
|
||||
* $autorespond and $alertstaff overrides config settings...
|
||||
*/
|
||||
function create($vars, &$errors, $origin, $autorespond=true, $alertstaff=true) {
|
||||
static function create($vars, &$errors, $origin, $autorespond=true,
|
||||
$alertstaff=true) {
|
||||
global $ost, $cfg, $thisclient, $_FILES;
|
||||
|
||||
// Don't enforce form validation for email
|
||||
@@ -2247,22 +2256,6 @@ class Ticket {
|
||||
}
|
||||
}
|
||||
|
||||
//Init ticket filters...
|
||||
$ticket_filter = new TicketFilter($origin, $vars);
|
||||
// Make sure email contents should not be rejected
|
||||
if($ticket_filter
|
||||
&& ($filter=$ticket_filter->shouldReject())) {
|
||||
$errors = array(
|
||||
'errno' => 403,
|
||||
'err' => "This help desk is for use by authorized users
|
||||
only");
|
||||
$ost->logWarning('Ticket denied',
|
||||
sprintf('Ticket rejected ( %s) by filter "%s"',
|
||||
$vars['email'], $filter->getName()), true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
$id=0;
|
||||
$fields=array();
|
||||
$fields['message'] = array('type'=>'*', 'required'=>1, 'error'=>'Message required');
|
||||
@@ -2301,7 +2294,21 @@ class Ticket {
|
||||
if (!$errors) {
|
||||
|
||||
# Perform ticket filter actions on the new ticket arguments
|
||||
if ($ticket_filter) $ticket_filter->apply($vars);
|
||||
try {
|
||||
// Init ticket filters...
|
||||
$ticket_filter = new TicketFilter($origin, $vars);
|
||||
$ticket_filter->apply($vars);
|
||||
}
|
||||
catch (RejectedException $ex) {
|
||||
$errors = array(
|
||||
'errno' => 403,
|
||||
'err' => "This help desk is for use by authorized users only");
|
||||
$ost->logWarning('Ticket denied',
|
||||
sprintf('Ticket rejected ( %s) by filter "%s"',
|
||||
$vars['email'], $ex->getRejectingFilter()->getName()), true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Allow vars to be changed in ticket filter and applied to the user
|
||||
// account created or detected
|
||||
@@ -2423,7 +2430,8 @@ class Ticket {
|
||||
if ($vars['staffId'])
|
||||
$ticket->assignToStaff($vars['staffId'], 'Auto Assignment');
|
||||
if ($vars['teamId'])
|
||||
$ticket->assignToTeam($vars['teamId'], 'Auto Assignment');
|
||||
$ticket->assignToTeam($vars['teamId'], 'Auto Assignment',
|
||||
!$vars['staffId']);
|
||||
}
|
||||
|
||||
/********** double check auto-response ************/
|
||||
@@ -2494,7 +2502,8 @@ class Ticket {
|
||||
if (!$thisstaff->canAssignTickets())
|
||||
unset($vars['assignId']);
|
||||
|
||||
if(!($ticket=Ticket::create($vars, $errors, 'staff', false)))
|
||||
$create_vars = $vars;
|
||||
if(!($ticket=Ticket::create($create_vars, $errors, 'staff', false)))
|
||||
return false;
|
||||
|
||||
$vars['msgId']=$ticket->getLastMsgId();
|
||||
|
||||
@@ -145,7 +145,7 @@ class User extends UserModel {
|
||||
|
||||
$info = array(
|
||||
'id' => $this->getId(),
|
||||
'name' => (string) $this->getName(),
|
||||
'name' => Format::htmlchars($this->getName()),
|
||||
'email' => (string) $this->getEmail(),
|
||||
'phone' => (string) $this->getPhoneNumber());
|
||||
|
||||
@@ -187,7 +187,7 @@ class User extends UserModel {
|
||||
$this->_entries[] = $g;
|
||||
}
|
||||
}
|
||||
return $this->_entries;
|
||||
return $this->_entries ?: array();
|
||||
}
|
||||
|
||||
function getForms($data=null) {
|
||||
|
||||
@@ -14,9 +14,9 @@ $category=$faq->getCategory();
|
||||
</div>
|
||||
<div style="float:right;text-align:right;padding-top:5px;padding-right:5px;"></div>
|
||||
<div class="clear"></div>
|
||||
<p>
|
||||
<div class="thread-body">
|
||||
<?php echo Format::safe_html($faq->getAnswerWithImages()); ?>
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
<?php
|
||||
if($faq->getNumAttachments()) { ?>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
if(!defined('OSTCLIENTINC') || !is_object($thisclient) || !$thisclient->isValid() || !$cfg->showRelatedTickets()) die('Access Denied');
|
||||
|
||||
$qstr='&'; //Query string collector
|
||||
$qs = array();
|
||||
$status=null;
|
||||
if(isset($_REQUEST['status'])) { //Query string status has nothing to do with the real status used below.
|
||||
$qstr.='status='.urlencode($_REQUEST['status']);
|
||||
$qs += array('status' => $_REQUEST['status']);
|
||||
//Status we are actually going to use on the query...making sure it is clean!
|
||||
switch(strtolower($_REQUEST['status'])) {
|
||||
case 'open':
|
||||
@@ -64,7 +64,7 @@ if($status){
|
||||
|
||||
$search=($_REQUEST['a']=='search' && $_REQUEST['q']);
|
||||
if($search) {
|
||||
$qstr.='&a='.urlencode($_REQUEST['a']).'&q='.urlencode($_REQUEST['q']);
|
||||
$qs += array('a' => $_REQUEST['a'], 'q' => $_REQUEST['q']);
|
||||
if(is_numeric($_REQUEST['q'])) {
|
||||
$qwhere.=" AND ticket.`number` LIKE '$queryterm%'";
|
||||
} else {//Deep search!
|
||||
@@ -83,7 +83,9 @@ if($search) {
|
||||
$total=db_count('SELECT count(DISTINCT ticket.ticket_id) '.$qfrom.' '.$qwhere);
|
||||
$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
|
||||
$pageNav=new Pagenate($total, $page, PAGE_LIMIT);
|
||||
$pageNav->setURL('tickets.php',$qstr.'&sort='.urlencode($_REQUEST['sort']).'&order='.urlencode($_REQUEST['order']));
|
||||
$qstr = '&'. Http::build_query($qs);
|
||||
$qs += array('sort' => $_REQUEST['sort'], 'order' => $_REQUEST['order']);
|
||||
$pageNav->setURL('tickets.php', $qs);
|
||||
|
||||
//more stuff...
|
||||
$qselect.=' ,count(attach_id) as attachments ';
|
||||
|
||||
@@ -448,6 +448,11 @@ class HtmlAElement extends HtmlInlineElement {
|
||||
$href = substr($href, 7);
|
||||
$output = (($href != $output) ? "$href " : '') . "<$output>";
|
||||
} elseif (mb_strwidth($href) > $width / 2) {
|
||||
if (mb_strwidth($output) > $width / 2) {
|
||||
// Parse URL and use relative path part
|
||||
if ($PU = parse_url($output))
|
||||
$output = $PU['host'] . $PU['path'];
|
||||
}
|
||||
if ($href != $output)
|
||||
$id = $this->getRoot()->addFootnote($output, $href);
|
||||
$output = "[$output][$id]";
|
||||
|
||||
@@ -16,19 +16,6 @@
|
||||
$Id: $
|
||||
**********************************************************************/
|
||||
|
||||
/**
|
||||
* If you have a strange HTTP server configuration and osTicket cannot
|
||||
* discover the URL path of where your osTicket is installed, define
|
||||
* ROOT_PATH here.
|
||||
*
|
||||
* The ROOT_PATH is the part of the URL used to access your osTicket
|
||||
* helpdesk before the '/scp' part and after the hostname. For instance, for
|
||||
* http://mycompany.com/support', the ROOT_PATH should be '/support/'
|
||||
*
|
||||
* ROOT_PATH *must* end with a forward-slash!
|
||||
*/
|
||||
# define('ROOT_PATH', '/support/');
|
||||
|
||||
#Disable direct access.
|
||||
if(!strcasecmp(basename($_SERVER['SCRIPT_NAME']),basename(__FILE__)) || !defined('INCLUDE_DIR'))
|
||||
die('kwaheri rafiki!');
|
||||
@@ -48,13 +35,19 @@ define('SECRET_SALT','%CONFIG-SIRI');
|
||||
#Default admin email. Used only on db connection issues and related alerts.
|
||||
define('ADMIN_EMAIL','%ADMIN-EMAIL');
|
||||
|
||||
#Mysql Login info
|
||||
# Database Options
|
||||
# ---------------------------------------------------
|
||||
# Mysql Login info
|
||||
define('DBTYPE','mysql');
|
||||
define('DBHOST','%CONFIG-DBHOST');
|
||||
define('DBNAME','%CONFIG-DBNAME');
|
||||
define('DBUSER','%CONFIG-DBUSER');
|
||||
define('DBPASS','%CONFIG-DBPASS');
|
||||
|
||||
# Table prefix
|
||||
define('TABLE_PREFIX','%CONFIG-PREFIX');
|
||||
|
||||
#
|
||||
# SSL Options
|
||||
# ---------------------------------------------------
|
||||
# SSL options for MySQL can be enabled by adding a certificate allowed by
|
||||
@@ -75,7 +68,42 @@ define('DBPASS','%CONFIG-DBPASS');
|
||||
# define('DBSSLCERT','/path/to/client.crt');
|
||||
# define('DBSSLKEY','/path/to/client.key');
|
||||
|
||||
#Table prefix
|
||||
define('TABLE_PREFIX','%CONFIG-PREFIX');
|
||||
#
|
||||
# Mail Options
|
||||
# ---------------------------------------------------
|
||||
# Option: MAIL_EOL (default: \r\n)
|
||||
#
|
||||
# Some mail setups do not handle emails with \r\n (CRLF) line endings for
|
||||
# headers and base64 and quoted-response encoded bodies. This is an error
|
||||
# and a violation of the internet mail RFCs. However, because this is also
|
||||
# outside the control of both osTicket development and many server
|
||||
# administrators, this option can be adjusted for your setup. Many folks who
|
||||
# experience blank or garbled email from osTicket can adjust this setting to
|
||||
# use "\n" (LF) instead of the CRLF default.
|
||||
#
|
||||
# References:
|
||||
# http://www.faqs.org/rfcs/rfc2822.html
|
||||
# https://github.com/osTicket/osTicket-1.8/issues/202
|
||||
# https://github.com/osTicket/osTicket-1.8/issues/700
|
||||
# https://github.com/osTicket/osTicket-1.8/issues/759
|
||||
# https://github.com/osTicket/osTicket-1.8/issues/1217
|
||||
|
||||
# define(MAIL_EOL, "\n");
|
||||
|
||||
#
|
||||
# HTTP Server Options
|
||||
# ---------------------------------------------------
|
||||
# Option: ROOT_PATH (default: <auto detect>, fallback: /)
|
||||
#
|
||||
# If you have a strange HTTP server configuration and osTicket cannot
|
||||
# discover the URL path of where your osTicket is installed, define
|
||||
# ROOT_PATH here.
|
||||
#
|
||||
# The ROOT_PATH is the part of the URL used to access your osTicket
|
||||
# helpdesk before the '/scp' part and after the hostname. For instance, for
|
||||
# http://mycompany.com/support', the ROOT_PATH should be '/support/'
|
||||
#
|
||||
# ROOT_PATH *must* end with a forward-slash!
|
||||
|
||||
# define('ROOT_PATH', '/support/');
|
||||
?>
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
$info=array();
|
||||
$qstr='';
|
||||
$info=$qs = array();
|
||||
|
||||
if($api && $_REQUEST['a']!='add'){
|
||||
$title='Update API Key';
|
||||
$action='update';
|
||||
$submit_text='Save Changes';
|
||||
$info=$api->getHashtable();
|
||||
$qstr.='&id='.$api->getId();
|
||||
$qs += array('id' => $api->getId());
|
||||
}else {
|
||||
$title='Add New API Key';
|
||||
$action='add';
|
||||
$submit_text='Add Key';
|
||||
$info['isactive']=isset($info['isactive'])?$info['isactive']:1;
|
||||
$qstr.='&a='.urlencode($_REQUEST['a']);
|
||||
$qs += array('a' => $_REQUEST['a']);
|
||||
}
|
||||
$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
?>
|
||||
<form action="apikeys.php?<?php echo $qstr; ?>" method="post" id="save">
|
||||
<form action="apikeys.php?<?php echo Http::build_query($qs); ?>" method="post" id="save">
|
||||
<?php csrf_token(); ?>
|
||||
<input type="hidden" name="do" value="<?php echo $action; ?>">
|
||||
<input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
|
||||
$qstr='';
|
||||
$qs = array();
|
||||
$sql='SELECT * FROM '.API_KEY_TABLE.' WHERE 1';
|
||||
$sortOptions=array('key'=>'apikey','status'=>'isactive','ip'=>'ipaddr','date'=>'created','created'=>'created','updated'=>'updated');
|
||||
$orderWays=array('DESC'=>'DESC','ASC'=>'ASC');
|
||||
@@ -27,9 +27,11 @@ $order_by="$order_column $order ";
|
||||
$total=db_count('SELECT count(*) FROM '.API_KEY_TABLE.' ');
|
||||
$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
|
||||
$pageNav=new Pagenate($total,$page,PAGE_LIMIT);
|
||||
$pageNav->setURL('apikeys.php',$qstr.'&sort='.urlencode($_REQUEST['sort']).'&order='.urlencode($_REQUEST['order']));
|
||||
//Ok..lets roll...create the actual query
|
||||
$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$qstr = '&'. Http::build_query($qs);
|
||||
$qs += array('sort' => $_REQUEST['sort'], 'order' => $_REQUEST['order']);
|
||||
$pageNav->setURL('apikeys.php', $qs);
|
||||
|
||||
$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$query="$sql ORDER BY $order_by LIMIT ".$pageNav->getStart().",".$pageNav->getLimit();
|
||||
$res=db_query($query);
|
||||
if($res && ($num=db_num_rows($res)))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin() || !$filter) die('Access Denied');
|
||||
|
||||
$qstr='';
|
||||
$qs = array();
|
||||
$select='SELECT rule.* ';
|
||||
$from='FROM '.FILTER_RULE_TABLE.' rule ';
|
||||
$where='WHERE rule.filter_id='.db_input($filter->getId());
|
||||
@@ -41,8 +41,10 @@ $order_by="$order_column $order ";
|
||||
$total=db_count('SELECT count(DISTINCT rule.id) '.$from.' '.$where);
|
||||
$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
|
||||
$pageNav=new Pagenate($total, $page, PAGE_LIMIT);
|
||||
$pageNav->setURL('banlist.php',$qstr.'&sort='.urlencode($_REQUEST['sort']).'&order='.urlencode($_REQUEST['order']));
|
||||
$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$qstr = '&'. Http::build_query($qs);
|
||||
$qs += array('sort' => $_REQUEST['sort'], 'order' => $_REQUEST['order']);
|
||||
$pageNav->setURL('banlist.php', $qs);
|
||||
$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$query="$select $from $where ORDER BY $order_by LIMIT ".$pageNav->getStart().",".$pageNav->getLimit();
|
||||
//echo $query;
|
||||
?>
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
|
||||
$info=array();
|
||||
$qstr='';
|
||||
$info=$qs= array();
|
||||
if($rule && $_REQUEST['a']!='add'){
|
||||
$title='Update Ban Rule';
|
||||
$action='update';
|
||||
$submit_text='Update';
|
||||
$info=$rule->getInfo();
|
||||
$info['id']=$rule->getId();
|
||||
$qstr.='&id='.$rule->getId();
|
||||
$qs += array('id' => $rule->getId());
|
||||
}else {
|
||||
$title='Add New Email Address to Ban List';
|
||||
$action='add';
|
||||
$submit_text='Add';
|
||||
$info['isactive']=isset($info['isactive'])?$info['isactive']:1;
|
||||
$qstr.='&a='.urlencode($_REQUEST['a']);
|
||||
$qs += array('a' => $_REQUEST['a']);
|
||||
}
|
||||
|
||||
$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
?>
|
||||
<form action="banlist.php?<?php echo $qstr; ?>" method="post" id="save">
|
||||
<form action="banlist.php?<?php echo Http::build_query($qs); ?>" method="post" id="save">
|
||||
<?php csrf_token(); ?>
|
||||
<input type="hidden" name="do" value="<?php echo $action; ?>">
|
||||
<input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>">
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
<?php
|
||||
if(!defined('OSTSCPINC') || !$thisstaff) die('Access Denied');
|
||||
$info=array();
|
||||
$qstr='';
|
||||
$info=$qs = array();
|
||||
if($canned && $_REQUEST['a']!='add'){
|
||||
$title='Update Canned Response';
|
||||
$action='update';
|
||||
$submit_text='Save Changes';
|
||||
$info=$canned->getInfo();
|
||||
$info['id']=$canned->getId();
|
||||
$qstr.='&id='.$canned->getId();
|
||||
$qs += array('id' => $canned->getId());
|
||||
// Replace cid: scheme with downloadable URL for inline images
|
||||
$info['response'] = $canned->getResponseWithImages();
|
||||
$info['notes'] = Format::viewableImages($info['notes']);
|
||||
@@ -17,12 +16,12 @@ if($canned && $_REQUEST['a']!='add'){
|
||||
$action='create';
|
||||
$submit_text='Add Response';
|
||||
$info['isenabled']=isset($info['isenabled'])?$info['isenabled']:1;
|
||||
$qstr.='&a='.$_REQUEST['a'];
|
||||
$qs += array('a' => $_REQUEST['a']);
|
||||
}
|
||||
$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
|
||||
?>
|
||||
<form action="canned.php?<?php echo $qstr; ?>" method="post" id="save" enctype="multipart/form-data">
|
||||
<form action="canned.php?<?php echo Http::build_query($qs); ?>" method="post" id="save" enctype="multipart/form-data">
|
||||
<?php csrf_token(); ?>
|
||||
<input type="hidden" name="do" value="<?php echo $action; ?>">
|
||||
<input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
if(!defined('OSTSCPINC') || !$thisstaff) die('Access Denied');
|
||||
|
||||
$qstr='';
|
||||
$qs = array();
|
||||
$sql='SELECT canned.*, count(attach.file_id) as files, dept.dept_name as department '.
|
||||
' FROM '.CANNED_TABLE.' canned '.
|
||||
' LEFT JOIN '.DEPT_TABLE.' dept ON (dept.dept_id=canned.dept_id) '.
|
||||
@@ -36,9 +36,11 @@ $order_by="$order_column $order ";
|
||||
$total=db_count('SELECT count(*) FROM '.CANNED_TABLE.' canned ');
|
||||
$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
|
||||
$pageNav=new Pagenate($total, $page, PAGE_LIMIT);
|
||||
$pageNav->setURL('canned.php',$qstr.'&sort='.urlencode($_REQUEST['sort']).'&order='.urlencode($_REQUEST['order']));
|
||||
$qstr = '&'. Http::build_query($qs);
|
||||
$qs += array('sort' => $_REQUEST['sort'], 'order' => $_REQUEST['order']);
|
||||
$pageNav->setURL('canned.php', $qs);
|
||||
//Ok..lets roll...create the actual query
|
||||
$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$qstr .= '&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$query="$sql GROUP BY canned.canned_id ORDER BY $order_by LIMIT ".$pageNav->getStart().",".$pageNav->getLimit();
|
||||
$res=db_query($query);
|
||||
if($res && ($num=db_num_rows($res)))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
if(!defined('OSTSCPINC') || !$thisstaff) die('Access Denied');
|
||||
|
||||
$qstr='';
|
||||
$qs = array();
|
||||
$sql='SELECT cat.category_id, cat.name, cat.ispublic, cat.updated, count(faq.faq_id) as faqs '.
|
||||
' FROM '.FAQ_CATEGORY_TABLE.' cat '.
|
||||
' LEFT JOIN '.FAQ_TABLE.' faq ON (faq.category_id=cat.category_id) ';
|
||||
@@ -30,8 +30,9 @@ $order_by="$order_column $order ";
|
||||
$total=db_count('SELECT count(*) FROM '.FAQ_CATEGORY_TABLE.' cat ');
|
||||
$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
|
||||
$pageNav=new Pagenate($total, $page, PAGE_LIMIT);
|
||||
$pageNav->setURL('categories.php',$qstr.'&sort='.urlencode($_REQUEST['sort']).'&order='.urlencode($_REQUEST['order']));
|
||||
$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$qs += array('sort' => $_REQUEST['sort'], 'order' => $_REQUEST['order']);
|
||||
$pageNav->setURL('categories.php', $qs);
|
||||
$qstr = '&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$query="$sql GROUP BY cat.category_id ORDER BY $order_by LIMIT ".$pageNav->getStart().",".$pageNav->getLimit();
|
||||
$res=db_query($query);
|
||||
if($res && ($num=db_num_rows($res)))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
if(!defined('OSTSCPINC') || !$thisstaff || !$thisstaff->canManageFAQ()) die('Access Denied');
|
||||
$info=array();
|
||||
$qstr='';
|
||||
$qs = array();
|
||||
if($category && $_REQUEST['a']!='add'){
|
||||
$title='Update Category: '.$category->getName();
|
||||
$action='update';
|
||||
@@ -9,17 +9,17 @@ if($category && $_REQUEST['a']!='add'){
|
||||
$info=$category->getHashtable();
|
||||
$info['id']=$category->getId();
|
||||
$info['notes'] = Format::viewableImages($category->getNotes());
|
||||
$qstr.='&id='.$category->getId();
|
||||
$qs += array('id' => $category->getId());
|
||||
}else {
|
||||
$title='Add New Category';
|
||||
$action='create';
|
||||
$submit_text='Add';
|
||||
$qstr.='&a='.$_REQUEST['a'];
|
||||
$qs += array('a' => $_REQUEST['a']);
|
||||
}
|
||||
$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
|
||||
?>
|
||||
<form action="categories.php?<?php echo $qstr; ?>" method="post" id="save">
|
||||
<form action="categories.php?<?php echo Http::build_query($qs); ?>" method="post" id="save">
|
||||
<?php csrf_token(); ?>
|
||||
<input type="hidden" name="do" value="<?php echo $action; ?>">
|
||||
<input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>">
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
$info=array();
|
||||
$qstr='';
|
||||
$info = $qs = array();
|
||||
if($dept && $_REQUEST['a']!='add') {
|
||||
//Editing Department.
|
||||
$title='Update Department';
|
||||
@@ -10,8 +9,7 @@ if($dept && $_REQUEST['a']!='add') {
|
||||
$info=$dept->getInfo();
|
||||
$info['id']=$dept->getId();
|
||||
$info['groups'] = $dept->getAllowedGroups();
|
||||
|
||||
$qstr.='&id='.$dept->getId();
|
||||
$qs += array('id' => $dept->getId());
|
||||
} else {
|
||||
$title='Add New Department';
|
||||
$action='create';
|
||||
@@ -22,11 +20,11 @@ if($dept && $_REQUEST['a']!='add') {
|
||||
if (!isset($info['group_membership']))
|
||||
$info['group_membership'] = 1;
|
||||
|
||||
$qstr.='&a='.$_REQUEST['a'];
|
||||
$qs += array('a' => $_REQUEST['a']);
|
||||
}
|
||||
$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
?>
|
||||
<form action="departments.php?<?php echo $qstr; ?>" method="post" id="save">
|
||||
<form action="departments.php?<?php echo Http::build_query($qs); ?>" method="post" id="save">
|
||||
<?php csrf_token(); ?>
|
||||
<input type="hidden" name="do" value="<?php echo $action; ?>">
|
||||
<input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
|
||||
$qstr='';
|
||||
$qs = array();
|
||||
$sql='SELECT dept.dept_id,dept_name,email.email_id,email.email,email.name as email_name,ispublic,count(staff.staff_id) as users '.
|
||||
',CONCAT_WS(" ",mgr.firstname,mgr.lastname) as manager,mgr.staff_id as manager_id,dept.created,dept.updated FROM '.DEPT_TABLE.' dept '.
|
||||
' LEFT JOIN '.STAFF_TABLE.' mgr ON dept.manager_id=mgr.staff_id '.
|
||||
@@ -30,7 +30,8 @@ $x=$sort.'_sort';
|
||||
$$x=' class="'.strtolower($order).'" ';
|
||||
$order_by="$order_column $order ";
|
||||
|
||||
$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$qs += array('order' => ($order=='DESC' ? 'ASC' : 'DESC'));
|
||||
$qstr = '&'. Http::build_query($qs);
|
||||
|
||||
$query="$sql GROUP BY dept.dept_id ORDER BY $order_by";
|
||||
$res=db_query($query);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
if(!defined('OSTSTAFFINC') || !$thisstaff || !$thisstaff->isStaff()) die('Access Denied');
|
||||
$qstr='';
|
||||
$qs = array();
|
||||
$select='SELECT staff.*,CONCAT_WS(" ",firstname,lastname) as name,dept.dept_name as dept ';
|
||||
$from='FROM '.STAFF_TABLE.' staff '.
|
||||
'LEFT JOIN '.DEPT_TABLE.' dept ON(staff.dept_id=dept.dept_id) ';
|
||||
@@ -25,7 +25,7 @@ if($_REQUEST['q']) {
|
||||
|
||||
if($_REQUEST['did'] && is_numeric($_REQUEST['did'])) {
|
||||
$where.=' AND staff.dept_id='.db_input($_REQUEST['did']);
|
||||
$qstr.='&did='.urlencode($_REQUEST['did']);
|
||||
$qs += array('did' => $_REQUEST['did']);
|
||||
}
|
||||
|
||||
$sortOptions=array('name'=>'staff.firstname,staff.lastname','email'=>'staff.email','dept'=>'dept.dept_name',
|
||||
@@ -54,9 +54,11 @@ $order_by="$order_column $order ";
|
||||
$total=db_count('SELECT count(DISTINCT staff.staff_id) '.$from.' '.$where);
|
||||
$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
|
||||
$pageNav=new Pagenate($total, $page, PAGE_LIMIT);
|
||||
$pageNav->setURL('directory.php',$qstr.'&sort='.urlencode($_REQUEST['sort']).'&order='.urlencode($_REQUEST['order']));
|
||||
$qstr = '&'. Http::build_query($qs);
|
||||
$qs += array('sort' => $_REQUEST['sort'], 'order' => $_REQUEST['order']);
|
||||
$pageNav->setURL('directory.php', $qs);
|
||||
//Ok..lets roll...create the actual query
|
||||
$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$qstr.='&order='.($order=='DESC' ? 'ASC' : 'DESC');
|
||||
$query="$select $from $where GROUP BY staff.staff_id ORDER BY $order_by LIMIT ".$pageNav->getStart().",".$pageNav->getLimit();
|
||||
//echo $query;
|
||||
?>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
$info=array();
|
||||
if($form && $_REQUEST['a']!='add') {
|
||||
$title = 'Update custom form section';
|
||||
$title = 'Update form section';
|
||||
$action = 'update';
|
||||
$url = "?id=".urlencode($_REQUEST['id']);
|
||||
$submit_text='Save Changes';
|
||||
@@ -23,14 +23,14 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
<input type="hidden" name="do" value="<?php echo $action; ?>">
|
||||
<input type="hidden" name="a" value="<?php echo $action; ?>">
|
||||
<input type="hidden" name="id" value="<?php echo $info['id']; ?>">
|
||||
<h2>Custom Form</h2>
|
||||
<h2><?php echo $form ? Format::htmlchars($form->getTitle()) : 'Custom Form'; ?></h2>
|
||||
<table class="form_table" width="940" border="0" cellspacing="0" cellpadding="2">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="2">
|
||||
<h4><?php echo $title; ?></h4>
|
||||
<em>Custom forms are used to allow custom data to be
|
||||
associated with tickets</em>
|
||||
<em>Forms are used to allow for collection of custom
|
||||
data</em>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@@ -59,7 +59,7 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
$page = ($_GET['p'] && is_numeric($_GET['p'])) ? $_GET['p'] : 1;
|
||||
$count = $list->getItemCount();
|
||||
$pageNav = new Pagenate($count, $page, PAGE_LIMIT);
|
||||
$pageNav->setURL('dynamic-list.php', 'id='.urlencode($_REQUEST['id']));
|
||||
$pageNav->setURL('dynamic-list.php', array('id' => $list->getId()));
|
||||
$showing=$pageNav->showing().' list items';
|
||||
?>
|
||||
<?php }
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
$info=array();
|
||||
$qstr='';
|
||||
$info = $qs = array();
|
||||
if($email && $_REQUEST['a']!='add'){
|
||||
$title='Update Email';
|
||||
$action='update';
|
||||
@@ -17,7 +16,7 @@ if($email && $_REQUEST['a']!='add'){
|
||||
if($info['userpass'])
|
||||
$passwdtxt='To change password enter new password above.';
|
||||
|
||||
$qstr.='&id='.$email->getId();
|
||||
$qs += array('id' => $email->getId());
|
||||
}else {
|
||||
$title='Add New Email';
|
||||
$action='create';
|
||||
@@ -25,12 +24,12 @@ if($email && $_REQUEST['a']!='add'){
|
||||
$info['ispublic']=isset($info['ispublic'])?$info['ispublic']:1;
|
||||
$info['ticket_auto_response']=isset($info['ticket_auto_response'])?$info['ticket_auto_response']:1;
|
||||
$info['message_auto_response']=isset($info['message_auto_response'])?$info['message_auto_response']:1;
|
||||
$qstr.='&a='.$_REQUEST['a'];
|
||||
$qs += array('a' => $_REQUEST['a']);
|
||||
}
|
||||
$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
?>
|
||||
<h2>Email Address</h2>
|
||||
<form action="emails.php?<?php echo $qstr; ?>" method="post" id="save">
|
||||
<form action="emails.php?<?php echo Http::build_query($qs); ?>" method="post" id="save">
|
||||
<?php csrf_token(); ?>
|
||||
<input type="hidden" name="do" value="<?php echo $action; ?>">
|
||||
<input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
|
||||
$qstr='';
|
||||
$qs = array();
|
||||
$sql='SELECT email.*,dept.dept_name as department,priority_desc as priority '.
|
||||
' FROM '.EMAIL_TABLE.' email '.
|
||||
' LEFT JOIN '.DEPT_TABLE.' dept ON (dept.dept_id=email.dept_id) '.
|
||||
@@ -31,9 +31,9 @@ $order_by="$order_column $order ";
|
||||
$total=db_count('SELECT count(*) FROM '.EMAIL_TABLE.' email ');
|
||||
$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
|
||||
$pageNav=new Pagenate($total, $page, PAGE_LIMIT);
|
||||
$pageNav->setURL('emails.php',$qstr.'&sort='.urlencode($_REQUEST['sort']).'&order='.urlencode($_REQUEST['order']));
|
||||
//Ok..lets roll...create the actual query
|
||||
$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$qs += array('sort' => $_REQUEST['sort'], 'order' => $_REQUEST['order']);
|
||||
$pageNav->setURL('emails.php', $qs);
|
||||
$qstr = '&order='.($order=='DESC' ? 'ASC' : 'DESC');
|
||||
$query="$sql GROUP BY email.email_id ORDER BY $order_by LIMIT ".$pageNav->getStart().",".$pageNav->getLimit();
|
||||
$res=db_query($query);
|
||||
if($res && ($num=db_num_rows($res)))
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
if(!defined('OSTSCPINC') || !$thisstaff || !$thisstaff->canManageFAQ()) die('Access Denied');
|
||||
$info=array();
|
||||
$qstr='';
|
||||
$info = $qs = array();
|
||||
if($faq){
|
||||
$title='Update FAQ: '.$faq->getQuestion();
|
||||
$action='update';
|
||||
@@ -11,18 +10,19 @@ if($faq){
|
||||
$info['topics']=$faq->getHelpTopicsIds();
|
||||
$info['answer']=Format::viewableImages($faq->getAnswer());
|
||||
$info['notes']=Format::viewableImages($faq->getNotes());
|
||||
$qstr='id='.$faq->getId();
|
||||
$qs += array('id' => $faq->getId());
|
||||
}else {
|
||||
$title='Add New FAQ';
|
||||
$action='create';
|
||||
$submit_text='Add FAQ';
|
||||
if($category) {
|
||||
$qstr='cid='.$category->getId();
|
||||
$qs += array('cid' => $category->getId());
|
||||
$info['category_id']=$category->getId();
|
||||
}
|
||||
}
|
||||
//TODO: Add attachment support.
|
||||
$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
$qstr = Http::build_query($qs);
|
||||
?>
|
||||
<form action="faq.php?<?php echo $qstr; ?>" method="post" id="save" enctype="multipart/form-data">
|
||||
<?php csrf_token(); ?>
|
||||
|
||||
@@ -4,25 +4,24 @@ if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access
|
||||
$matches=Filter::getSupportedMatches();
|
||||
$match_types=Filter::getSupportedMatchTypes();
|
||||
|
||||
$info=array();
|
||||
$qstr='';
|
||||
$info = $qs = array();
|
||||
if($filter && $_REQUEST['a']!='add'){
|
||||
$title='Update Filter';
|
||||
$action='update';
|
||||
$submit_text='Save Changes';
|
||||
$info=array_merge($filter->getInfo(),$filter->getFlatRules());
|
||||
$info['id']=$filter->getId();
|
||||
$qstr.='&id='.$filter->getId();
|
||||
$qs += array('id' => $filter->getId());
|
||||
}else {
|
||||
$title='Add New Filter';
|
||||
$action='add';
|
||||
$submit_text='Add Filter';
|
||||
$info['isactive']=isset($info['isactive'])?$info['isactive']:0;
|
||||
$qstr.='&a='.urlencode($_REQUEST['a']);
|
||||
$qs += array('a' => $_REQUEST['a']);
|
||||
}
|
||||
$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
?>
|
||||
<form action="filters.php?<?php echo $qstr; ?>" method="post" id="save">
|
||||
<form action="filters.php?<?php echo Http::build_query($qs); ?>" method="post" id="save">
|
||||
<?php csrf_token(); ?>
|
||||
<input type="hidden" name="do" value="<?php echo $action; ?>">
|
||||
<input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
$targets = Filter::getTargets();
|
||||
$qstr='';
|
||||
$qs = array();
|
||||
$sql='SELECT filter.*,count(rule.id) as rules '.
|
||||
'FROM '.FILTER_TABLE.' filter '.
|
||||
'LEFT JOIN '.FILTER_RULE_TABLE.' rule ON(rule.filter_id=filter.id) '.
|
||||
@@ -31,9 +31,10 @@ $order_by="$order_column $order ";
|
||||
$total=db_count('SELECT count(*) FROM '.FILTER_TABLE.' filter ');
|
||||
$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
|
||||
$pageNav=new Pagenate($total, $page, PAGE_LIMIT);
|
||||
$pageNav->setURL('filters.php',$qstr.'&sort='.urlencode($_REQUEST['sort']).'&order='.urlencode($_REQUEST['order']));
|
||||
//Ok..lets roll...create the actual query
|
||||
$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$qstr = '&'. Http::build_query($qs);
|
||||
$qs += array('sort' => $_REQUEST['sort'], 'order' => $_REQUEST['order']);
|
||||
$pageNav->setURL('filters.php', $qs);
|
||||
$qstr.='&order='.($order=='DESC' ? 'ASC' : 'DESC');
|
||||
$query="$sql ORDER BY $order_by LIMIT ".$pageNav->getStart().",".$pageNav->getLimit();
|
||||
$res=db_query($query);
|
||||
if($res && ($num=db_num_rows($res)))
|
||||
@@ -47,7 +48,7 @@ else
|
||||
<h2>Ticket Filters</h2>
|
||||
</div>
|
||||
<div style="float:right;text-align:right;padding-top:5px;padding-right:5px;">
|
||||
<b><a href="filters.php?a=add" class="Icon newEmailFilter">Add New Filter</a></b></div>
|
||||
<b><a href="filters.php?a=add" class="Icon newTicketFilter">Add New Filter</a></b></div>
|
||||
<div class="clear"></div>
|
||||
<form action="filters.php" method="POST" name="filters">
|
||||
<?php csrf_token(); ?>
|
||||
@@ -57,7 +58,7 @@ else
|
||||
<caption><?php echo $showing; ?></caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="7"> </th>
|
||||
<th width="7"> </th>
|
||||
<th width="320"><a <?php echo $name_sort; ?> href="filters.php?<?php echo $qstr; ?>&sort=name">Name</a></th>
|
||||
<th width="80"><a <?php echo $status_sort; ?> href="filters.php?<?php echo $qstr; ?>&sort=status">Status</a></th>
|
||||
<th width="80" style="text-align:center;"><a <?php echo $order_sort; ?> href="filters.php?<?php echo $qstr; ?>&sort=order">Order</a></th>
|
||||
@@ -79,7 +80,7 @@ else
|
||||
?>
|
||||
<tr id="<?php echo $row['id']; ?>">
|
||||
<td width=7px>
|
||||
<input type="checkbox" class="ckb" name="ids[]" value="<?php echo $row['id']; ?>"
|
||||
<input type="checkbox" class="ckb" name="ids[]" value="<?php echo $row['id']; ?>"
|
||||
<?php echo $sel?'checked="checked"':''; ?>>
|
||||
</td>
|
||||
<td> <a href="filters.php?id=<?php echo $row['id']; ?>"><?php echo Format::htmlchars($row['name']); ?></a></td>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
$info=array();
|
||||
$qstr='';
|
||||
$info = $qs = array();
|
||||
if($group && $_REQUEST['a']!='add'){
|
||||
$title='Update Group';
|
||||
$action='update';
|
||||
@@ -9,18 +8,18 @@ if($group && $_REQUEST['a']!='add'){
|
||||
$info=$group->getInfo();
|
||||
$info['id']=$group->getId();
|
||||
$info['depts']=$group->getDepartments();
|
||||
$qstr.='&id='.$group->getId();
|
||||
$qs += array('id' => $group->getId());
|
||||
}else {
|
||||
$title='Add New Group';
|
||||
$action='create';
|
||||
$submit_text='Create Group';
|
||||
$info['isactive']=isset($info['isactive'])?$info['isactive']:1;
|
||||
$info['can_create_tickets']=isset($info['can_create_tickets'])?$info['can_create_tickets']:1;
|
||||
$qstr.='&a='.$_REQUEST['a'];
|
||||
$qs += array('a' => $_REQUEST['a']);
|
||||
}
|
||||
$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
?>
|
||||
<form action="groups.php?<?php echo $qstr; ?>" method="post" id="save" name="group">
|
||||
<form action="groups.php?<?php echo Http::build_query($qs); ?>" method="post" id="save" name="group">
|
||||
<?php csrf_token(); ?>
|
||||
<input type="hidden" name="do" value="<?php echo $action; ?>">
|
||||
<input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>">
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
|
||||
$qstr='';
|
||||
|
||||
$qs = array();
|
||||
$sql='SELECT grp.*,count(DISTINCT staff.staff_id) as users, count(DISTINCT dept.dept_id) as depts '
|
||||
.' FROM '.GROUP_TABLE.' grp '
|
||||
.' LEFT JOIN '.STAFF_TABLE.' staff ON(staff.group_id=grp.group_id) '
|
||||
@@ -30,7 +29,7 @@ $x=$sort.'_sort';
|
||||
$$x=' class="'.strtolower($order).'" ';
|
||||
$order_by="$order_column $order ";
|
||||
|
||||
$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$qs += array('order' => ($order=='DESC' ? 'ASC' : 'DESC'));
|
||||
$query="$sql GROUP BY grp.group_id ORDER BY $order_by";
|
||||
$res=db_query($query);
|
||||
if($res && ($num=db_num_rows($res)))
|
||||
@@ -38,6 +37,9 @@ if($res && ($num=db_num_rows($res)))
|
||||
else
|
||||
$showing='No groups found!';
|
||||
|
||||
|
||||
$qstr = '&'.Http::build_query($qs);
|
||||
|
||||
?>
|
||||
<div style="width:700px;padding-top:5px; float:left;">
|
||||
<h2>User Groups</h2>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
$info=array();
|
||||
$qstr='';
|
||||
$info = $qs = array();
|
||||
if($topic && $_REQUEST['a']!='add') {
|
||||
$title='Update Help Topic';
|
||||
$action='update';
|
||||
@@ -9,18 +8,18 @@ if($topic && $_REQUEST['a']!='add') {
|
||||
$info=$topic->getInfo();
|
||||
$info['id']=$topic->getId();
|
||||
$info['pid']=$topic->getPid();
|
||||
$qstr.='&id='.$topic->getId();
|
||||
$qs += array('id' => $topic->getId());
|
||||
} else {
|
||||
$title='Add New Help Topic';
|
||||
$action='create';
|
||||
$submit_text='Add Topic';
|
||||
$info['isactive']=isset($info['isactive'])?$info['isactive']:1;
|
||||
$info['ispublic']=isset($info['ispublic'])?$info['ispublic']:1;
|
||||
$qstr.='&a='.$_REQUEST['a'];
|
||||
$qs += array('a' => $_REQUEST['a']);
|
||||
}
|
||||
$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
?>
|
||||
<form action="helptopics.php?<?php echo $qstr; ?>" method="post" id="save">
|
||||
<form action="helptopics.php?<?php echo Http::build_query($qs); ?>" method="post" id="save">
|
||||
<?php csrf_token(); ?>
|
||||
<input type="hidden" name="do" value="<?php echo $action; ?>">
|
||||
<input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>">
|
||||
|
||||
@@ -6,8 +6,7 @@ $pageTypes = array(
|
||||
'thank-you' => 'Thank you page',
|
||||
'other' => 'Other',
|
||||
);
|
||||
$info=array();
|
||||
$qstr='';
|
||||
$info = $qs = array();
|
||||
if($page && $_REQUEST['a']!='add'){
|
||||
$title='Update Page';
|
||||
$action='update';
|
||||
@@ -16,17 +15,17 @@ if($page && $_REQUEST['a']!='add'){
|
||||
$info['body'] = Format::viewableImages($page->getBody());
|
||||
$info['notes'] = Format::viewableImages($info['notes']);
|
||||
$slug = Format::slugify($info['name']);
|
||||
$qstr.='&id='.$page->getId();
|
||||
$qs += array('id' => $page->getId());
|
||||
}else {
|
||||
$title='Add New Page';
|
||||
$action='add';
|
||||
$submit_text='Add Page';
|
||||
$info['isactive']=isset($info['isactive'])?$info['isactive']:0;
|
||||
$qstr.='&a='.urlencode($_REQUEST['a']);
|
||||
$qs += array('a' => $_REQUEST['a']);
|
||||
}
|
||||
$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
?>
|
||||
<form action="pages.php?<?php echo $qstr; ?>" method="post" id="save">
|
||||
<form action="pages.php?<?php echo Http::build_query($qs); ?>" method="post" id="save">
|
||||
<?php csrf_token(); ?>
|
||||
<input type="hidden" name="do" value="<?php echo $action; ?>">
|
||||
<input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
|
||||
$qstr='';
|
||||
$qs = array();
|
||||
$sql='SELECT page.id, page.isactive, page.name, page.created, page.updated, '
|
||||
.'page.type, count(topic.topic_id) as topics '
|
||||
.' FROM '.PAGE_TABLE.' page '
|
||||
@@ -36,9 +36,11 @@ $order_by="$order_column $order ";
|
||||
$total=db_count('SELECT count(*) FROM '.PAGE_TABLE.' page ');
|
||||
$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
|
||||
$pageNav=new Pagenate($total, $page, PAGE_LIMIT);
|
||||
$pageNav->setURL('pages.php',$qstr.'&sort='.urlencode($_REQUEST['sort']).'&order='.urlencode($_REQUEST['order']));
|
||||
$qstr = '&'. Http::build_query($qs);
|
||||
$qs += array('sort' => $_REQUEST['sort'], 'order' => $_REQUEST['order']);
|
||||
$pageNav->setURL('pages.php', $qs);
|
||||
//Ok..lets roll...create the actual query
|
||||
$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$qstr .= '&order='.($order=='DESC' ? 'ASC' : 'DESC');
|
||||
$query="$sql GROUP BY page.id ORDER BY $order_by LIMIT ".$pageNav->getStart().",".$pageNav->getLimit();
|
||||
$res=db_query($query);
|
||||
if($res && ($num=db_num_rows($res)))
|
||||
|
||||
@@ -12,10 +12,11 @@ if($plugin && $_REQUEST['a']!='add') {
|
||||
$submit_text='Save Changes';
|
||||
$info = $plugin->ht;
|
||||
}
|
||||
$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
|
||||
$info = Format::htmlchars(($errors && $_POST) ? $_POST : $info);
|
||||
?>
|
||||
|
||||
<form action="?id=<?php echo urlencode($_REQUEST['id']); ?>" method="post" id="save">
|
||||
<form action="?<?php echo Http::build_query(array('id' => $_REQUEST['id'])); ?>" method="post" id="save">
|
||||
<?php csrf_token(); ?>
|
||||
<input type="hidden" name="do" value="<?php echo $action; ?>">
|
||||
<input type="hidden" name="id" value="<?php echo $info['id']; ?>">
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
$info=array();
|
||||
$qstr='';
|
||||
$info = $qs = array();
|
||||
if($sla && $_REQUEST['a']!='add'){
|
||||
$title='Update SLA Plan';
|
||||
$action='update';
|
||||
$submit_text='Save Changes';
|
||||
$info=$sla->getInfo();
|
||||
$info['id']=$sla->getId();
|
||||
$qstr.='&id='.$sla->getId();
|
||||
$qs += array('id' => $sla->getId());
|
||||
}else {
|
||||
$title='Add New SLA Plan';
|
||||
$action='add';
|
||||
@@ -16,11 +15,11 @@ if($sla && $_REQUEST['a']!='add'){
|
||||
$info['isactive']=isset($info['isactive'])?$info['isactive']:1;
|
||||
$info['enable_priority_escalation']=isset($info['enable_priority_escalation'])?$info['enable_priority_escalation']:1;
|
||||
$info['disable_overdue_alerts']=isset($info['disable_overdue_alerts'])?$info['disable_overdue_alerts']:0;
|
||||
$qstr.='&a='.urlencode($_REQUEST['a']);
|
||||
$qs += array('a' => $_REQUEST['a']);
|
||||
}
|
||||
$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
?>
|
||||
<form action="slas.php?<?php echo $qstr; ?>" method="post" id="save">
|
||||
<form action="slas.php?<?php echo Http::build_query($qs); ?>" method="post" id="save">
|
||||
<?php csrf_token(); ?>
|
||||
<input type="hidden" name="do" value="<?php echo $action; ?>">
|
||||
<input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
|
||||
$qstr='';
|
||||
$qs = array();
|
||||
$sql='SELECT * FROM '.SLA_TABLE.' sla WHERE 1';
|
||||
$sortOptions=array('name'=>'sla.name','status'=>'sla.isactive','period'=>'sla.grace_period','date'=>'sla.created','updated'=>'sla.updated');
|
||||
$orderWays=array('DESC'=>'DESC','ASC'=>'ASC');
|
||||
@@ -27,9 +27,12 @@ $order_by="$order_column $order ";
|
||||
$total=db_count('SELECT count(*) FROM '.SLA_TABLE.' sla ');
|
||||
$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
|
||||
$pageNav=new Pagenate($total, $page, PAGE_LIMIT);
|
||||
$pageNav->setURL('slas.php',$qstr.'&sort='.urlencode($_REQUEST['sort']).'&order='.urlencode($_REQUEST['order']));
|
||||
$qstr = '&'. Http::build_query($qs);
|
||||
$qs += array('sort' => $_REQUEST['sort'], 'order' => $_REQUEST['order']);
|
||||
|
||||
$pageNav->setURL('slas.php', $qs);
|
||||
//Ok..lets roll...create the actual query
|
||||
$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$qstr .= '&order='.($order=='DESC' ? 'ASC' : 'DESC');
|
||||
$query="$sql ORDER BY $order_by LIMIT ".$pageNav->getStart().",".$pageNav->getLimit();
|
||||
$res=db_query($query);
|
||||
if($res && ($num=db_num_rows($res)))
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
|
||||
$info=array();
|
||||
$qstr='';
|
||||
$info = $qs = array();
|
||||
if($staff && $_REQUEST['a']!='add'){
|
||||
//Editing Department.
|
||||
$title='Update Staff';
|
||||
@@ -12,7 +11,7 @@ if($staff && $_REQUEST['a']!='add'){
|
||||
$info=$staff->getInfo();
|
||||
$info['id']=$staff->getId();
|
||||
$info['teams'] = $staff->getTeams();
|
||||
$qstr.='&id='.$staff->getId();
|
||||
$qs += array('id' => $staff->getId());
|
||||
}else {
|
||||
$title='Add New Staff';
|
||||
$action='create';
|
||||
@@ -23,11 +22,11 @@ if($staff && $_REQUEST['a']!='add'){
|
||||
$info['isactive']=1;
|
||||
$info['isvisible']=1;
|
||||
$info['isadmin']=0;
|
||||
$qstr.='&a=add';
|
||||
$qs += array('a' => 'add');
|
||||
}
|
||||
$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
?>
|
||||
<form action="staff.php?<?php echo $qstr; ?>" method="post" id="save" autocomplete="off">
|
||||
<form action="staff.php?<?php echo Http::build_query($qs); ?>" method="post" id="save" autocomplete="off">
|
||||
<?php csrf_token(); ?>
|
||||
<input type="hidden" name="do" value="<?php echo $action; ?>">
|
||||
<input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
$qstr='';
|
||||
$qs = array();
|
||||
$select='SELECT staff.*,CONCAT_WS(" ",firstname,lastname) as name, grp.group_name, dept.dept_name as dept,count(m.team_id) as teams ';
|
||||
$from='FROM '.STAFF_TABLE.' staff '.
|
||||
'LEFT JOIN '.GROUP_TABLE.' grp ON(staff.group_id=grp.group_id) '.
|
||||
@@ -10,17 +10,17 @@ $where='WHERE 1 ';
|
||||
|
||||
if($_REQUEST['did'] && is_numeric($_REQUEST['did'])) {
|
||||
$where.=' AND staff.dept_id='.db_input($_REQUEST['did']);
|
||||
$qstr.='&did='.urlencode($_REQUEST['did']);
|
||||
$qs += array('did' => $_REQUEST['did']);
|
||||
}
|
||||
|
||||
if($_REQUEST['gid'] && is_numeric($_REQUEST['gid'])) {
|
||||
$where.=' AND staff.group_id='.db_input($_REQUEST['gid']);
|
||||
$qstr.='&gid='.urlencode($_REQUEST['gid']);
|
||||
$qs += array('gid' => $_REQUEST['gid']);
|
||||
}
|
||||
|
||||
if($_REQUEST['tid'] && is_numeric($_REQUEST['tid'])) {
|
||||
$where.=' AND m.team_id='.db_input($_REQUEST['tid']);
|
||||
$qstr.='&tid='.urlencode($_REQUEST['tid']);
|
||||
$qs += array('tid' => $_REQUEST['tid']);
|
||||
}
|
||||
|
||||
$sortOptions=array('name'=>'staff.firstname,staff.lastname','username'=>'staff.username','status'=>'isactive',
|
||||
@@ -48,9 +48,11 @@ $order_by="$order_column $order ";
|
||||
$total=db_count('SELECT count(DISTINCT staff.staff_id) '.$from.' '.$where);
|
||||
$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
|
||||
$pageNav=new Pagenate($total,$page,PAGE_LIMIT);
|
||||
$pageNav->setURL('staff.php',$qstr.'&sort='.urlencode($_REQUEST['sort']).'&order='.urlencode($_REQUEST['order']));
|
||||
//Ok..lets roll...create the actual query
|
||||
$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$qstr = '&'. Http::build_query($qs);
|
||||
$qs += array('sort' => $_REQUEST['sort'], 'order' => $_REQUEST['order']);
|
||||
|
||||
$pageNav->setURL('staff.php', $qs);
|
||||
$qstr .= '&order='.($order=='DESC' ? 'ASC' : 'DESC');
|
||||
$query="$select $from $where GROUP BY staff.staff_id ORDER BY $order_by LIMIT ".$pageNav->getStart().",".$pageNav->getLimit();
|
||||
//echo $query;
|
||||
?>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
|
||||
$qstr='';
|
||||
$qs = array();
|
||||
if($_REQUEST['type']) {
|
||||
$qstr.='&type='.urlencode($_REQUEST['type']);
|
||||
$qs += array('type' => $_REQUEST['type']);
|
||||
}
|
||||
$type=null;
|
||||
switch(strtolower($_REQUEST['type'])){
|
||||
@@ -38,11 +38,11 @@ if( ($startTime && $startTime>time()) or ($startTime>$endTime && $endTime>0)){
|
||||
}else{
|
||||
if($startTime){
|
||||
$qwhere.=' AND created>=FROM_UNIXTIME('.$startTime.')';
|
||||
$qstr.='&startDate='.urlencode($_REQUEST['startDate']);
|
||||
$qs += array('startDate' => $_REQUEST['startDate']);
|
||||
}
|
||||
if($endTime){
|
||||
$qwhere.=' AND created<=FROM_UNIXTIME('.$endTime.')';
|
||||
$qstr.='&endDate='.urlencode($_REQUEST['endDate']);
|
||||
$qs += array('endDate' => $_REQUEST['endDate']);
|
||||
}
|
||||
}
|
||||
$sortOptions=array('id'=>'log.log_id', 'title'=>'log.title','type'=>'log_type','ip'=>'log.ip_address'
|
||||
@@ -73,8 +73,9 @@ $total=db_count("SELECT count(*) $qfrom $qwhere");
|
||||
$page = ($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
|
||||
//pagenate
|
||||
$pageNav=new Pagenate($total, $page, PAGE_LIMIT);
|
||||
$pageNav->setURL('logs.php',$qstr);
|
||||
$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$pageNav->setURL('logs.php',$qs);
|
||||
$qs += array('order' => ($order=='DESC' ? 'ASC' : 'DESC'));
|
||||
$qstr = '&'. Http::build_query($qs);
|
||||
$query="$qselect $qfrom $qwhere ORDER BY $order_by LIMIT ".$pageNav->getStart().",".$pageNav->getLimit();
|
||||
$res=db_query($query);
|
||||
if($res && ($num=db_num_rows($res)))
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
$info=array();
|
||||
$qstr='';
|
||||
$info = $qs = array();
|
||||
if($team && $_REQUEST['a']!='add'){
|
||||
//Editing Team
|
||||
$title='Update Team';
|
||||
@@ -9,18 +8,18 @@ if($team && $_REQUEST['a']!='add'){
|
||||
$submit_text='Save Changes';
|
||||
$info=$team->getInfo();
|
||||
$info['id']=$team->getId();
|
||||
$qstr.='&id='.$team->getId();
|
||||
$qs += array('id' => $team->getId());
|
||||
}else {
|
||||
$title='Add New Team';
|
||||
$action='create';
|
||||
$submit_text='Create Team';
|
||||
$info['isenabled']=1;
|
||||
$info['noalerts']=0;
|
||||
$qstr.='&a='.$_REQUEST['a'];
|
||||
$qs += array('a' => $_REQUEST['a']);
|
||||
}
|
||||
$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
?>
|
||||
<form action="teams.php?<?php echo $qstr; ?>" method="post" id="save">
|
||||
<form action="teams.php?<?php echo Http::build_query($qs); ?>" method="post" id="save">
|
||||
<?php csrf_token(); ?>
|
||||
<input type="hidden" name="do" value="<?php echo $action; ?>">
|
||||
<input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
|
||||
$qstr='';
|
||||
$qs = array();
|
||||
$sql='SELECT team.*,count(m.staff_id) as members,CONCAT_WS(" ",lead.firstname,lead.lastname) as team_lead '.
|
||||
' FROM '.TEAM_TABLE.' team '.
|
||||
' LEFT JOIN '.TEAM_MEMBER_TABLE.' m ON(m.team_id=team.team_id) '.
|
||||
@@ -28,7 +28,8 @@ $x=$sort.'_sort';
|
||||
$$x=' class="'.strtolower($order).'" ';
|
||||
$order_by="$order_column $order ";
|
||||
|
||||
$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$qs += array('order' => ($order=='DESC' ? 'ASC' : 'DESC'));
|
||||
$qstr = '&'. Http::build_query($qs);
|
||||
|
||||
$query="$sql GROUP BY team.team_id ORDER BY $order_by";
|
||||
$res=db_query($query);
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
|
||||
$info=array();
|
||||
$qstr='';
|
||||
$info = $qs = array();
|
||||
if($template && $_REQUEST['a']!='add'){
|
||||
$title='Update Template';
|
||||
$action='update';
|
||||
$submit_text='Save Changes';
|
||||
$info=$template->getInfo();
|
||||
$info['tpl_id']=$template->getId();
|
||||
$qstr.='&tpl_id='.$template->getId();
|
||||
$qs += array('tpl_id' => $template->getId());
|
||||
}else {
|
||||
$title='Add New Template';
|
||||
$action='add';
|
||||
$submit_text='Add Template';
|
||||
$info['isactive']=isset($info['isactive'])?$info['isactive']:0;
|
||||
$info['lang_id'] = $cfg->getSystemLanguage();
|
||||
$qstr.='&a='.urlencode($_REQUEST['a']);
|
||||
$qs += array('a' => $_REQUEST['a']);
|
||||
}
|
||||
$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
?>
|
||||
<form action="templates.php?<?php echo $qstr; ?>" method="post" id="save">
|
||||
<form action="templates.php?<?php echo Http::build_query($qs); ?>" method="post" id="save">
|
||||
<?php csrf_token(); ?>
|
||||
<input type="hidden" name="do" value="<?php echo $action; ?>">
|
||||
<input type="hidden" name="a" value="<?php echo Format::htmlchars($_REQUEST['a']); ?>">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
if(!defined('OSTADMININC') || !$thisstaff->isAdmin()) die('Access Denied');
|
||||
|
||||
$qstr='';
|
||||
$qs = array();
|
||||
$sql='SELECT tpl.*,count(dept.tpl_id) as depts '.
|
||||
'FROM '.EMAIL_TEMPLATE_GRP_TABLE.' tpl '.
|
||||
'LEFT JOIN '.DEPT_TABLE.' dept USING(tpl_id) '.
|
||||
@@ -30,9 +30,10 @@ $order_by="$order_column $order ";
|
||||
$total=db_count('SELECT count(*) FROM '.EMAIL_TEMPLATE_GRP_TABLE.' tpl ');
|
||||
$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
|
||||
$pageNav=new Pagenate($total, $page, PAGE_LIMIT);
|
||||
$pageNav->setURL('templates.php',$qstr.'&sort='.urlencode($_REQUEST['sort']).'&order='.urlencode($_REQUEST['order']));
|
||||
//Ok..lets roll...create the actual query
|
||||
$qstr.='&order='.($order=='DESC'?'ASC':'DESC');
|
||||
$qstr = '&'. Http::build_query($qs);
|
||||
$qs += array('sort' => $_REQUEST['sort'], 'order' => $_REQUEST['order']);
|
||||
$pageNav->setURL('templates.php', $qs);
|
||||
$qstr .= '&order='.($order=='DESC' ? 'ASC' : 'DESC');
|
||||
$query="$sql GROUP BY tpl.tpl_id ORDER BY $order_by LIMIT ".$pageNav->getStart().",".$pageNav->getLimit();
|
||||
$res=db_query($query);
|
||||
if($res && ($num=db_num_rows($res)))
|
||||
|
||||
@@ -8,7 +8,7 @@ if (($users=$ticket->getCollaborators())) {?>
|
||||
echo sprintf('<tr><td %s><i class="icon-%s"></i> %s <em><%s></em></td></tr>',
|
||||
($user->isActive()? '' : 'class="faded"'),
|
||||
($user->isActive()? 'comments' : 'comment-alt'),
|
||||
$user->getName(),
|
||||
Format::htmlchars($user->getName()),
|
||||
$user->getEmail());
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -27,7 +27,7 @@ if(($users=$ticket->getCollaborators())) {?>
|
||||
$user->getId(),
|
||||
$checked,
|
||||
$user->getId(),
|
||||
$user->getName(),
|
||||
Format::htmlchars($user->getName()),
|
||||
$user->getEmail(),
|
||||
$user->getId(),
|
||||
$user->getId());
|
||||
|
||||
@@ -40,7 +40,7 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
|
||||
});
|
||||
return false;
|
||||
"><i class="icon-user"></i>
|
||||
<span id="user-name"><?php echo $user->getName(); ?></span>
|
||||
<span id="user-name"><?php echo Format::htmlchars($user->getName()); ?></span>
|
||||
<<span id="user-email"><?php echo $user->getEmail(); ?></span>>
|
||||
</a>
|
||||
<a class="action-button" style="float:none;overflow:inherit" href="#"
|
||||
|
||||
@@ -438,7 +438,9 @@ $tcount+= $ticket->getNumNotes();
|
||||
<td>
|
||||
<?php
|
||||
# XXX: Add user-to-name and user-to-email HTML ID#s
|
||||
$to =sprintf('%s <%s>', $ticket->getName(), $ticket->getReplyToEmail());
|
||||
$to =sprintf('%s <%s>',
|
||||
Format::htmlchars($ticket->getName()),
|
||||
$ticket->getReplyToEmail());
|
||||
$emailReply = (!isset($info['emailreply']) || $info['emailreply']);
|
||||
?>
|
||||
<select id="emailreply" name="emailreply">
|
||||
@@ -1017,5 +1019,12 @@ $(function() {
|
||||
}
|
||||
});
|
||||
});
|
||||
<?php
|
||||
// Set the lock if one exists
|
||||
if ($lock) { ?>
|
||||
autoLock.setLock({
|
||||
id:<?php echo $lock->getId(); ?>,
|
||||
time: <?php echo $cfg->getLockTime(); ?>}, 'acquire');
|
||||
<?php } ?>
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?php
|
||||
if(!defined('OSTSCPINC') || !$thisstaff || !@$thisstaff->isStaff()) die('Access Denied');
|
||||
|
||||
$qstr='&'; //Query string collector
|
||||
$qs= array(); //Query string collector
|
||||
if($_REQUEST['status']) { //Query string status has nothing to do with the real status used below; gets overloaded.
|
||||
$qstr.='status='.urlencode($_REQUEST['status']);
|
||||
$qs += array('status' => $_REQUEST['status']);
|
||||
}
|
||||
|
||||
//See if this is a search
|
||||
@@ -81,7 +81,7 @@ if($status) {
|
||||
if (isset($_REQUEST['uid']) && $_REQUEST['uid']) {
|
||||
$qwhere .= ' AND (ticket.user_id='.db_input($_REQUEST['uid'])
|
||||
.' OR collab.user_id='.db_input($_REQUEST['uid']).') ';
|
||||
$qstr .= '&uid='.urlencode($_REQUEST['uid']);
|
||||
$qs += array('uid' => $_REQUEST['uid']);
|
||||
}
|
||||
|
||||
//Queues: Overloaded sub-statuses - you've got to just have faith!
|
||||
@@ -110,12 +110,10 @@ if($staffId && ($staffId==$thisstaff->getId())) { //My tickets
|
||||
//Search?? Somebody...get me some coffee
|
||||
$deep_search=false;
|
||||
if($search):
|
||||
$qstr.='&a='.urlencode($_REQUEST['a']);
|
||||
$qstr.='&t='.urlencode($_REQUEST['t']);
|
||||
|
||||
$qs += array('a' => $_REQUEST['a'], 't' => $_REQUEST['t']);
|
||||
//query
|
||||
if($searchTerm){
|
||||
$qstr.='&query='.urlencode($searchTerm);
|
||||
$qs += array('query' => $searchTerm);
|
||||
$queryterm=db_real_escape($searchTerm,false); //escape the term ONLY...no quotes.
|
||||
if (is_numeric($searchTerm)) {
|
||||
$qwhere.=" AND ticket.`number` LIKE '$queryterm%'";
|
||||
@@ -141,12 +139,12 @@ if($search):
|
||||
endif;
|
||||
|
||||
if ($_REQUEST['advsid'] && isset($_SESSION['adv_'.$_REQUEST['advsid']])) {
|
||||
$qstr.='advsid='.$_REQUEST['advsid'];
|
||||
$qs += array('advsid' => $_REQUEST['advsid']);
|
||||
$qwhere .= ' AND ticket.ticket_id IN ('. implode(',',
|
||||
db_input($_SESSION['adv_'.$_REQUEST['advsid']])).')';
|
||||
}
|
||||
|
||||
$sortOptions=array('date'=>'effective_date','ID'=>'ticket.`number`',
|
||||
$sortOptions=array('date'=>'effective_date','ID'=>'ticket.`number`*1',
|
||||
'pri'=>'pri.priority_urgency','name'=>'user.name','subj'=>'cdata.subject',
|
||||
'status'=>'ticket.status','assignee'=>'assigned','staff'=>'staff',
|
||||
'dept'=>'dept.dept_name');
|
||||
@@ -196,7 +194,7 @@ $x=$sort.'_sort';
|
||||
$$x=' class="'.strtolower($order).'" ';
|
||||
|
||||
if($_GET['limit'])
|
||||
$qstr.='&limit='.urlencode($_GET['limit']);
|
||||
$qs += array('limit' => $_GET['limit']);
|
||||
|
||||
$qselect ='SELECT ticket.ticket_id,tlock.lock_id,ticket.`number`,ticket.dept_id,ticket.staff_id,ticket.team_id '
|
||||
.' ,user.name'
|
||||
@@ -225,12 +223,15 @@ $total=db_count("SELECT count(DISTINCT ticket.ticket_id) $qfrom $sjoin $qwhere")
|
||||
$pagelimit=($_GET['limit'] && is_numeric($_GET['limit']))?$_GET['limit']:PAGE_LIMIT;
|
||||
$page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
|
||||
$pageNav=new Pagenate($total,$page,$pagelimit);
|
||||
$pageNav->setURL('tickets.php',$qstr.'&sort='.urlencode($_REQUEST['sort']).'&order='.urlencode($_REQUEST['order']));
|
||||
|
||||
$qstr = '&'.http::build_query($qs);
|
||||
$qs += array('sort' => $_REQUEST['sort'], 'order' => $_REQUEST['order']);
|
||||
$pageNav->setURL('tickets.php', $qs);
|
||||
|
||||
//ADD attachment,priorities, lock and other crap
|
||||
$qselect.=' ,IF(ticket.duedate IS NULL,IF(sla.id IS NULL, NULL, DATE_ADD(ticket.created, INTERVAL sla.grace_period HOUR)), ticket.duedate) as duedate '
|
||||
.' ,CAST(GREATEST(IFNULL(ticket.lastmessage, 0), IFNULL(ticket.closed, 0), IFNULL(ticket.reopened, 0), ticket.created) as datetime) as effective_date '
|
||||
.' ,CONCAT_WS(" ", staff.firstname, staff.lastname) as staff, team.name as team '
|
||||
.' ,ticket.created as ticket_created, CONCAT_WS(" ", staff.firstname, staff.lastname) as staff, team.name as team '
|
||||
.' ,IF(staff.staff_id IS NULL,team.name,CONCAT_WS(" ", staff.lastname, staff.firstname)) as assigned '
|
||||
.' ,IF(ptopic.topic_pid IS NULL, topic.topic, CONCAT_WS(" / ", ptopic.topic, topic.topic)) as helptopic '
|
||||
.' ,cdata.priority_id, cdata.subject, pri.priority_desc, pri.priority_color';
|
||||
@@ -295,7 +296,9 @@ if ($results) {
|
||||
<input type="hidden" name="a" value="search">
|
||||
<table>
|
||||
<tr>
|
||||
<td><input type="text" id="basic-ticket-search" name="query" size=30 value="<?php echo Format::htmlchars($_REQUEST['query']); ?>"
|
||||
<td><input type="text" id="basic-ticket-search" name="query"
|
||||
size=30 value="<?php echo Format::htmlchars($_REQUEST['query'],
|
||||
true); ?>"
|
||||
autocomplete="off" autocorrect="off" autocapitalize="off"></td>
|
||||
<td><input type="submit" name="basic_search" class="button" value="Search"></td>
|
||||
<td> <a href="" id="go-advanced">[advanced]</a></td>
|
||||
@@ -311,7 +314,8 @@ if ($results) {
|
||||
<a class="refresh" href="<?php echo Format::htmlchars($_SERVER['REQUEST_URI']); ?>">Refresh</a>
|
||||
<input type="hidden" name="a" value="mass_process" >
|
||||
<input type="hidden" name="do" id="action" value="" >
|
||||
<input type="hidden" name="status" value="<?php echo Format::htmlchars($_REQUEST['status']); ?>" >
|
||||
<input type="hidden" name="status" value="<?php echo
|
||||
Format::htmlchars($_REQUEST['status'], true); ?>" >
|
||||
<table class="list" border="0" cellspacing="1" cellpadding="2" width="940">
|
||||
<caption><?php echo $showing; ?> <?php echo $results_type; ?></caption>
|
||||
<thead>
|
||||
@@ -424,7 +428,8 @@ if ($results) {
|
||||
echo '<i class="icon-fixed-width icon-paperclip"></i> ';
|
||||
?>
|
||||
</td>
|
||||
<td nowrap> <?php echo Format::truncate($row['name'],22,strpos($row['name'],'@')); ?> </td>
|
||||
<td nowrap> <?php echo Format::htmlchars(
|
||||
Format::truncate($row['name'], 22, strpos($row['name'], '@'))); ?> </td>
|
||||
<?php
|
||||
if($search && !$status){
|
||||
$displaystatus=ucfirst($row['status']);
|
||||
@@ -465,8 +470,10 @@ if ($results) {
|
||||
<?php
|
||||
if($num>0){ //if we actually had any tickets returned.
|
||||
echo '<div> Page:'.$pageNav->getPageLinks().' ';
|
||||
echo '<a class="export-csv" href="?a=export&h='
|
||||
.$hash.'&status='.$_REQUEST['status'] .'">Export</a></div>';
|
||||
echo sprintf('<a class="export-csv" href="?%s">Export</a></div>',
|
||||
Http::build_query(array(
|
||||
'a' => 'export', 'h' => $hash,
|
||||
'status' => $_REQUEST['status'])));
|
||||
?>
|
||||
<?php
|
||||
if($thisstaff->canManageTickets()) { ?>
|
||||
|
||||
@@ -76,7 +76,7 @@ $tpl=$msgtemplates[$selected];
|
||||
<form action="templates.php?id=<?php echo $id; ?>&a=manage" method="post" id="save">
|
||||
<?php csrf_token(); ?>
|
||||
<?php foreach ($extras as $k=>$v) { ?>
|
||||
<input type="hidden" name="<?php echo $k; ?>" value="<?php echo $v; ?>" />
|
||||
<input type="hidden" name="<?php echo $k; ?>" value="<?php echo Format::htmlchars($v); ?>" />
|
||||
<?php } ?>
|
||||
<input type="hidden" name="id" value="<?php echo $id; ?>">
|
||||
<input type="hidden" name="a" value="manage">
|
||||
@@ -105,7 +105,7 @@ $tpl=$msgtemplates[$selected];
|
||||
</div>
|
||||
<input type="hidden" name="draft_id" value=""/>
|
||||
<textarea name="body" cols="21" rows="16" style="width:98%;" wrap="soft"
|
||||
class="richtext draft" data-draft-namespace="tpl.<?php echo $selected; ?>"
|
||||
class="richtext draft" data-draft-namespace="tpl.<?php echo Format::htmlchars($selected); ?>"
|
||||
data-draft-object-id="<?php echo $tpl_id; ?>"><?php echo $info['body']; ?></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -341,7 +341,7 @@ class TnefAttributeStreamReader extends TnefStreamReader {
|
||||
/* Read and truncate to length. */
|
||||
$text = substr($this->_getx($datalen), 0, $length);
|
||||
if ($type == self::TypeUnicode) {
|
||||
$text = Format::encode($text, 'ucs2');
|
||||
$text = Charset::utf8($text, 'ucs2');
|
||||
}
|
||||
|
||||
return $text;
|
||||
@@ -543,7 +543,7 @@ class TnefMessage extends AbstractTnefObject {
|
||||
|
||||
// Transcode it
|
||||
if ($encoding && $charset)
|
||||
$body = Format::encode($body, $charset, $encoding);
|
||||
$body = Charset::transcode($body, $charset, $encoding);
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
@@ -214,3 +214,16 @@ showImagesInline = function(urls, thread_id) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(document).on('submit', 'form', function() {
|
||||
// Reformat dates
|
||||
$('.dp', $(this)).each(function(i, e) {
|
||||
var $e = $(e),
|
||||
d = $e.datepicker('getDate');
|
||||
if (!d) return;
|
||||
var day = ('0'+d.getDate()).substr(-2),
|
||||
month = ('0'+(d.getMonth()+1)).substr(-2),
|
||||
year = d.getFullYear();
|
||||
$e.val(year+'-'+month+'-'+day);
|
||||
});
|
||||
});
|
||||
|
||||
14
login.php
14
login.php
@@ -25,7 +25,19 @@ require_once(INCLUDE_DIR.'class.client.php');
|
||||
require_once(INCLUDE_DIR.'class.ticket.php');
|
||||
|
||||
$inc = 'login.inc.php';
|
||||
|
||||
// Check the CSRF token, and ensure that future requests will have to use a
|
||||
// different CSRF token. This will help ward off both parallel and serial
|
||||
// brute force attacks, because new tokens will have to be requested for
|
||||
// each attempt.
|
||||
if ($_POST) {
|
||||
// Check CSRF token
|
||||
if (!$ost->checkCSRFToken())
|
||||
Http::response(400, __('Valid CSRF Token Required'));
|
||||
|
||||
// Rotate the CSRF token (original cannot be reused)
|
||||
$ost->getCSRF()->rotate();
|
||||
|
||||
if (!$_POST['lticket'] || !Validator::is_email($_POST['lemail']))
|
||||
$errors['err'] = 'Valid email address and ticket number required';
|
||||
elseif (($user = UserAuthenticationBackend::process($_POST['lemail'],
|
||||
@@ -34,7 +46,7 @@ if ($_POST) {
|
||||
// force attempts (which doesn't buy much since the link is emailed)
|
||||
$user->sendAccessLink();
|
||||
$msg = sprintf("%s - access link sent to your email!",
|
||||
$user->getName()->getFirst());
|
||||
Format::htmlchars($user->getName()->getFirst()));
|
||||
$_POST = null;
|
||||
} elseif(!$errors['err']) {
|
||||
$errors['err'] = 'Invalid email or ticket number - try again!';
|
||||
|
||||
8
open.php
8
open.php
@@ -31,11 +31,13 @@ if($_POST):
|
||||
|
||||
$form = false;
|
||||
if ($topic = Topic::lookup($vars['topicId'])) {
|
||||
if ($form = DynamicForm::lookup($topic->ht['form_id'])) {
|
||||
if ($form = $topic->getForm()) {
|
||||
$TF = $form->getForm($vars);
|
||||
$form = $form->instanciate();
|
||||
$form->setSource($vars);
|
||||
// Don't require internal fields (they're not shown)
|
||||
if (!$form->isValid(function($f) { return !$f->get('private'); }))
|
||||
$errors += $form->errors();
|
||||
if (!$TF->isValid(function($f) { return !$f->get('private'); }))
|
||||
$errors = array_merge($errors, $TF->errors());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
method: 'GET',
|
||||
dataType: 'json',
|
||||
url: 'ajax.php/report/overview/table',
|
||||
data: {group: group, start: start, stop: stop},
|
||||
data: {group: group, start: start, period: stop},
|
||||
success: function(json) {
|
||||
var q = $('<table>').attr({'class':'table table-condensed table-striped'}),
|
||||
h = $('<tr>').appendTo($('<thead>').appendTo(q)),
|
||||
|
||||
@@ -15,6 +15,20 @@
|
||||
**********************************************************************/
|
||||
var autoLock = {
|
||||
|
||||
// Defaults
|
||||
lockId: 0,
|
||||
timerId: 0,
|
||||
lasteventTime: 0,
|
||||
lastattemptTime: 0,
|
||||
acquireTime: 0,
|
||||
renewTime: 0,
|
||||
renewFreq: 0, //renewal frequency in seconds...based on returned lock time.
|
||||
time: 0,
|
||||
lockAttempts: 0, //Consecutive lock attempt errors
|
||||
maxattempts: 2, //Maximum failed lock attempts before giving up.
|
||||
warn: true,
|
||||
retry: true,
|
||||
|
||||
addEvent: function(elm, evType, fn, useCapture) {
|
||||
if(elm.addEventListener) {
|
||||
elm.addEventListener(evType, fn, useCapture);
|
||||
@@ -108,18 +122,6 @@ var autoLock = {
|
||||
void(autoLock.tid=parseInt($(':input[name=id]',fObj).val()));
|
||||
void(autoLock.lockTime=parseInt($(':input[name=locktime]',fObj).val()));
|
||||
|
||||
autoLock.lockId=0;
|
||||
autoLock.timerId=0;
|
||||
autoLock.lasteventTime=0;
|
||||
autoLock.lastattemptTime=0;
|
||||
autoLock.acquireTime=0;
|
||||
autoLock.renewTime=0;
|
||||
autoLock.renewFreq=0; //renewal frequency in seconds...based on returned lock time.
|
||||
autoLock.time=0;
|
||||
autoLock.lockAttempts=0; //Consecutive lock attempt errors
|
||||
autoLock.maxattempts=2; //Maximum failed lock attempts before giving up.
|
||||
autoLock.warn=true;
|
||||
autoLock.retry=true;
|
||||
autoLock.watchDocument();
|
||||
autoLock.resetTimer();
|
||||
autoLock.addEvent(window,'unload',autoLock.releaseLock,true); //Release lock regardless of any activity.
|
||||
|
||||
@@ -25,6 +25,16 @@ $msg = $msg?$msg:'Authentication Required';
|
||||
$dest=($dest && (!strstr($dest,'login.php') && !strstr($dest,'ajax.php')))?$dest:'index.php';
|
||||
$show_reset = false;
|
||||
if($_POST) {
|
||||
// Check the CSRF token, and ensure that future requests will have to
|
||||
// use a different CSRF token. This will help ward off both parallel and
|
||||
// serial brute force attacks, because new tokens will have to be
|
||||
// requested for each attempt.
|
||||
if (!$ost->checkCSRFToken())
|
||||
Http::response(400, __('Valid CSRF Token Required'));
|
||||
|
||||
// Rotate the CSRF token (original cannot be reused)
|
||||
$ost->getCSRF()->rotate();
|
||||
|
||||
// Lookup support backends for this staff
|
||||
$username = trim($_POST['userid']);
|
||||
if ($user = StaffAuthenticationBackend::process($username,
|
||||
|
||||
@@ -27,11 +27,9 @@ if($_POST) {
|
||||
$_REQUEST['a'] = null;
|
||||
$msg='Page added successfully';
|
||||
// Attach inline attachments from the editor
|
||||
if (isset($_POST['draft_id'])
|
||||
&& ($draft = Draft::lookup($_POST['draft_id']))
|
||||
&& ($page = Page::lookup($pageId)))
|
||||
if ($page = Page::lookup($pageId))
|
||||
$page->attachments->upload(
|
||||
$draft->getAttachmentIds($_POST['response']), true);
|
||||
Draft::getAttachmentIds($_POST['body']), true);
|
||||
Draft::deleteForNamespace('page');
|
||||
} elseif(!$errors['err'])
|
||||
$errors['err'] = 'Unable to add page. Try again!';
|
||||
@@ -43,13 +41,10 @@ if($_POST) {
|
||||
$msg='Page updated successfully';
|
||||
$_REQUEST['a']=null; //Go back to view
|
||||
// Attach inline attachments from the editor
|
||||
if (isset($_POST['draft_id'])
|
||||
&& ($draft = Draft::lookup($_POST['draft_id']))) {
|
||||
$page->attachments->deleteInlines();
|
||||
$page->attachments->upload(
|
||||
$draft->getAttachmentIds($_POST['response']),
|
||||
true);
|
||||
}
|
||||
$page->attachments->deleteInlines();
|
||||
$page->attachments->upload(
|
||||
Draft::getAttachmentIds($_POST['body']),
|
||||
true);
|
||||
Draft::deleteForNamespace('page.'.$page->getId());
|
||||
} elseif(!$errors['err'])
|
||||
$errors['err'] = 'Unable to update page. Try again!';
|
||||
|
||||
@@ -198,9 +198,11 @@ if($_POST && !$errors):
|
||||
case 'edit':
|
||||
case 'update':
|
||||
$forms=DynamicFormEntry::forTicket($ticket->getId());
|
||||
foreach ($forms as $form)
|
||||
foreach ($forms as $form) {
|
||||
$form->setSource($_POST);
|
||||
if (!$form->isValid())
|
||||
$errors = array_merge($errors, $form->errors());
|
||||
}
|
||||
if(!$ticket || !$thisstaff->canEditTickets())
|
||||
$errors['err']='Permission Denied. You are not allowed to edit tickets';
|
||||
elseif($ticket->update($_POST,$errors)) {
|
||||
@@ -343,7 +345,7 @@ if($_POST && !$errors):
|
||||
} elseif (!$_POST['user_id'] || !($user=User::lookup($_POST['user_id']))) {
|
||||
$errors['err'] = 'Unknown user selected!';
|
||||
} elseif ($ticket->changeOwner($user)) {
|
||||
$msg = 'Ticket ownership changed to '.$user->getName();
|
||||
$msg = 'Ticket ownership changed to ' . Format::htmlchars($user->getName());
|
||||
} else {
|
||||
$errors['err'] = 'Unable to change tiket ownership. Try again';
|
||||
}
|
||||
@@ -472,10 +474,12 @@ if($_POST && !$errors):
|
||||
case 'open':
|
||||
$ticket=null;
|
||||
if ($topic=Topic::lookup($_POST['topicId'])) {
|
||||
if ($form = DynamicForm::lookup($topic->ht['form_id'])) {
|
||||
if ($form = $topic->getForm()) {
|
||||
$TF = $form->getForm($_POST);
|
||||
$form = $form->instanciate();
|
||||
if (!$form->getForm()->isValid())
|
||||
$errors = array_merge($errors, $form->getForm()->errors());
|
||||
$form->setSource($_POST);
|
||||
if (!$TF->isValid())
|
||||
$errors = array_merge($errors, $TF->errors());
|
||||
}
|
||||
}
|
||||
if(!$thisstaff || !$thisstaff->canCreateTickets()) {
|
||||
|
||||
@@ -10,7 +10,7 @@ $url=URL;
|
||||
<h2>Config file permission:</h2>
|
||||
Change permission of ost-config.php to remove write access as shown below.
|
||||
<ul>
|
||||
<li><b>CLI</b>:<br><i>chmod 0664 include/ost-config.php</i></li>
|
||||
<li><b>CLI</b>:<br><i>chmod 0644 include/ost-config.php</i></li>
|
||||
<li><b>FTP</b>:<br>Using WS_FTP this would be right hand clicking on the file, selecting chmod, and then remove write access</li>
|
||||
<li><b>Cpanel</b>:<br>Click on the file, select change permission, and then remove write access.</li>
|
||||
</ul>
|
||||
|
||||
@@ -39,9 +39,11 @@ if($_POST && is_object($ticket) && $ticket->getId()):
|
||||
$errors['err']='Access Denied. Client updates are currently disabled';
|
||||
else {
|
||||
$forms=DynamicFormEntry::forTicket($ticket->getId());
|
||||
foreach ($forms as $form)
|
||||
foreach ($forms as $form) {
|
||||
$form->setSource($_POST);
|
||||
if (!$form->isValid())
|
||||
$errors = array_merge($errors, $form->errors());
|
||||
}
|
||||
}
|
||||
if (!$errors) {
|
||||
foreach ($forms as $f) $f->save();
|
||||
|
||||
Reference in New Issue
Block a user