Browse Source

Getting started on new ticket validator

tags/3.1.0
Mike Koch 2 years ago
parent
commit
d1ae2a8009

+ 15
- 0
api/businesslogic/ValidationModel.php View File

@@ -0,0 +1,15 @@
<?php

class ValidationModel {
/**
* @var array
*/
public $errorKeys;

public $valid;

function __construct() {
$errorKeys = [];
$valid = true;
}
}

+ 119
- 0
api/businesslogic/email_validators.php View File

@@ -0,0 +1,119 @@
<?php

/**
* @param string $address - the email address
* @param array $multiple_emails - true if HESK (or custom field) supports multiple emails
* @param bool $return_emails (def. true): return the email address(es). Otherwise a boolean is returned
*
* @return mixed|null|string - array if multiple valid emails, null if no email and not required, string if valid email
*/
function hesk_validateEmail($address, $multiple_emails, $return_emails = true) {
/* Allow multiple emails to be used? */
if ($multiple_emails) {
/* Make sure the format is correct */
$address = preg_replace('/\s/', '', $address);
$address = str_replace(';', ',', $address);

/* Check if addresses are valid */
$all = explode(',', $address);
foreach ($all as $k => $v) {
if (!hesk_isValidEmail($v)) {
unset($all[$k]);
}
}

/* If at least one is found return the value */
if (count($all)) {
if ($return_emails) {
return implode(',', $all);
}

return true;
} elseif (!$return_emails) {
return false;
}
} else {
/* Make sure people don't try to enter multiple addresses */
$address = str_replace(strstr($address, ','), '', $address);
$address = str_replace(strstr($address, ';'), '', $address);
$address = trim($address);

/* Valid address? */
if (hesk_isValidEmail($address)) {
if ($return_emails) {
return $address;
}

return true;
}
}

if ($return_emails) {
return null;
}

return true;
} // END hesk_validateEmail()

/**
* @param $email
* @return bool
*/
function hesk_isValidEmail($email) {
/* Check for header injection attempts */
if (preg_match("/\r|\n|%0a|%0d/i", $email)) {
return false;
}

/* Does it contain an @? */
$atIndex = strrpos($email, "@");
if ($atIndex === false) {
return false;
}

/* Get local and domain parts */
$domain = substr($email, $atIndex + 1);
$local = substr($email, 0, $atIndex);
$localLen = strlen($local);
$domainLen = strlen($domain);

/* Check local part length */
if ($localLen < 1 || $localLen > 64) {
return false;
}

/* Check domain part length */
if ($domainLen < 1 || $domainLen > 254) {
return false;
}

/* Local part mustn't start or end with a dot */
if ($local[0] == '.' || $local[$localLen - 1] == '.') {
return false;
}

/* Local part mustn't have two consecutive dots*/
if (strpos($local, '..') !== false) {
return false;
}

/* Check domain part characters */
if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)) {
return false;
}

/* Domain part mustn't have two consecutive dots */
if (strpos($domain, '..') !== false) {
return false;
}

/* Character not valid in local part unless local part is quoted */
if (!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\", "", $local))) /* " */ {
if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\", "", $local))) /* " */ {
return false;
}
}

/* All tests passed, email seems to be OK */
return true;
} // END hesk_isValidEmail()

+ 42
- 0
api/businesslogic/ticket/CreateTicketForCustomerModel.php View File

@@ -0,0 +1,42 @@
<?php

class CreateTicketForCustomerModel {
// Metadata
/**
* @var string
*/
public $name;

/**
* @var string
*/
public $email;

/**
* @var integer
*/
public $priority;

/**
* @var integer
*/
public $category;

// Message
/**
* @var string
*/
public $subject;

/**
* @var string
*/
public $message;

/**
* @var array
*/
public $customFields;

public $location;
}

+ 93
- 0
api/businesslogic/ticket/ticket_creator.php View File

@@ -0,0 +1,93 @@
<?php

/**
* @param $ticket_request CreateTicketForCustomerModel
*/
function create_ticket_for_customer($ticket_request, $hesk_settings, $modsForHesk_settings) {
validate($ticket_request, false, $hesk_settings, $modsForHesk_settings);
}

/**
* @param $ticket_request CreateTicketForCustomerModel
* @param $staff bool
* @return ValidationModel If errorKeys is empty, validation successful. Otherwise invalid ticket
*/
function validate($ticket_request, $staff, $hesk_settings, $modsForHesk_settings) {
require_once('../email_validators.php');
//require_once('../category/retriever.php');
//require_once('../bans/retriever.php');

$TICKET_PRIORITY_CRITICAL = 0;

$validationModel = new ValidationModel();

if ($ticket_request->name === NULL || $ticket_request->name == '') {
$validationModel->errorKeys[] = 'NO_NAME';
}

if (hesk_validateEmail($ticket_request->email, $hesk_settings['multi_eml'], false)) {
$validationModel->errorKeys[] = 'INVALID_OR_MISSING_EMAIL';
}

if (intval($ticket_request->category) === 0) {
// TODO add support for invalid category ID
$validationModel->errorKeys[] = 'NO_CATEGORY';
}

// Don't allow critical priority tickets
if ($hesk_settings['cust_urgency'] && intval($ticket_request->priority) === $TICKET_PRIORITY_CRITICAL) {
$validationModel->errorKeys[] = 'CRITICAL_PRIORITY_FORBIDDEN';
}

if ($hesk_settings['require_subject'] === 1 &&
($ticket_request->subject === NULL || $ticket_request->subject === '')) {
$validationModel->errorKeys[] = 'SUBJECT_REQUIRED';
}

if ($hesk_settings['require_message'] === 1 &&
($ticket_request->message === NULL || $ticket_request->message === '')) {
$validationModel->errorKeys[] = 'MESSAGE_REQUIRED';
}

foreach ($hesk_settings['custom_fields'] as $key => $value) {
// TODO Only check categories that apply to this custom field
if ($value['use'] == 1 && hesk_is_custom_field_in_category($key, intval($ticket_request->category))) {
$custom_field_value = $ticket_request->customFields[$key];
if (empty($custom_field_value)) {
$validationModel->errorKeys[] = 'CUSTOM_FIELD_' . $key . '_INVALID::NO_VALUE';
continue;
}
switch($v['type']) {
case 'date':
if (!preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/", $custom_field_value)) {
$validationModel->errorKeys[] = 'CUSTOM_FIELD_' . $key . '_INVALID::INVALID_DATE';
} else {
// Actually validate based on range
$date = strtotime($custom_field_value . ' t00:00:00');
$dmin = strlen($value['value']['dmin']) ? strtotime($value['value']['dmin'] . ' t00:00:00') : false;
$dmax = strlen($value['value']['dmax']) ? strtotime($value['value']['dmax'] . ' t00:00:00') : false;

if ($dmin && $dmin > $date) {
$validationModel->errorKeys[] = 'CUSTOM_FIELD_' . $key . '_INVALID::DATE_BEFORE_MIN::MIN-' . $dmin . '::ENTERED-' . $date;
} elseif ($dmax && $dmax < $date) {
$validationModel->errorKeys[] = 'CUSTOM_FIELD_' . $key . '_INVALID::DATE_AFTER_MAX::MAX-' . $dmax . '::ENTERED-' . $date;
}
}
break;
case 'email':
if (!hesk_validateEmail($custom_field_value, $value['value']['multiple'], false)) {
$validationModel->errorKeys[] = 'CUSTOM_FIELD_' . $key . '_INVALID::INVALID_OR_MISSING_EMAIL';
}
break;
}
}
}

// TODO Check bans (email only; don't check IP on REST requests as they'll most likely be sent via servers)
// TODO submit_ticket.php:320-322

// TODO Check if we're at the max number of tickets
// TODO submit_ticket.php:325-334

return $validationModel;
}

+ 3
- 0
api/loader.php View File

@@ -0,0 +1,3 @@
<?php
// The loader is responsible for loading all necessary PHP classes to run the API. No more need to import everything
// manually.

+ 0
- 1
api/ticket/index.php View File

@@ -3,7 +3,6 @@ define('IN_SCRIPT', 1);
define('HESK_PATH', '../../');
define('API_PATH', '../');
require_once(HESK_PATH . 'hesk_settings.inc.php');
require_once(HESK_PATH . 'inc/common.inc.php');
require_once(API_PATH . 'core/headers.php');
require_once(API_PATH . 'core/output.php');
require_once(API_PATH . 'businesslogic/ticket_retriever.php');

Loading…
Cancel
Save