mirror of
https://github.com/opensupports/opensupports.git
synced 2025-07-28 08:14:25 +02:00
commit
8e6d28fff8
@ -1,6 +1,6 @@
|
|||||||

|

|
||||||
|
|
||||||
[](https://travis-ci.org/opensupports/opensupports) v4.1.0
|
[](https://travis-ci.org/opensupports/opensupports) v4.1.1
|
||||||
|
|
||||||
OpenSupports is an open source ticket system built primarly with PHP and ReactJS.
|
OpenSupports is an open source ticket system built primarly with PHP and ReactJS.
|
||||||
Please, visit our website for more information: [http://www.opensupports.com/](http://www.opensupports.com/)
|
Please, visit our website for more information: [http://www.opensupports.com/](http://www.opensupports.com/)
|
||||||
@ -77,7 +77,7 @@ Just as there is the `gulp dev` task for development, there is also a `gulp prod
|
|||||||
4. Run the MySQL server
|
4. Run the MySQL server
|
||||||
|
|
||||||
`sudo /etc/init.d/mysql start`
|
`sudo /etc/init.d/mysql start`
|
||||||
|
|
||||||
##### BACKEND API RUBY TESTING
|
##### BACKEND API RUBY TESTING
|
||||||
|
|
||||||
1. Install ruby `sudo apt-get install ruby-full`
|
1. Install ruby `sudo apt-get install ruby-full`
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "OpenSupports",
|
"name": "OpenSupports",
|
||||||
"version": "4.1.0",
|
"version": "4.1.1",
|
||||||
"author": "Ivan Diaz <contact@opensupports.com>",
|
"author": "Ivan Diaz <contact@opensupports.com>",
|
||||||
"description": "Open source ticket system made with PHP and ReactJS",
|
"description": "Open source ticket system made with PHP and ReactJS",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -83,9 +83,10 @@ class InitSettingsController extends Controller {
|
|||||||
'registration' => !!Controller::request('registration'),
|
'registration' => !!Controller::request('registration'),
|
||||||
'user-system-enabled' => !!Controller::request('user-system-enabled'),
|
'user-system-enabled' => !!Controller::request('user-system-enabled'),
|
||||||
'last-stat-day' => date('YmdHi', strtotime(' -12 day ')),
|
'last-stat-day' => date('YmdHi', strtotime(' -12 day ')),
|
||||||
'ticket-gap' => Hashing::generateRandomPrime(1000000, 9999999),
|
'ticket-gap' => Hashing::generateRandomPrime(100000, 999999),
|
||||||
'file-gap' => Hashing::generateRandomPrime(1000000, 9999999),
|
'ticket-first-number' => Hashing::generateRandomNumber(100000, 999999),
|
||||||
'file-first-number' => Hashing::generateRandomNumber(1000000, 9999999),
|
'file-gap' => Hashing::generateRandomPrime(100000, 999999),
|
||||||
|
'file-first-number' => Hashing::generateRandomNumber(100000, 999999),
|
||||||
'file-quantity' => 0,
|
'file-quantity' => 0,
|
||||||
'session-prefix' => 'opensupports-'.Hashing::generateRandomToken().'_'
|
'session-prefix' => 'opensupports-'.Hashing::generateRandomToken().'_'
|
||||||
]);
|
]);
|
||||||
|
@ -26,8 +26,4 @@ class LinearCongruentialGenerator {
|
|||||||
|
|
||||||
return ($this->first - $this->min + $offset * $this->gap) % ($this->max - $this->min + 1) + $this->min;
|
return ($this->first - $this->min + $offset * $this->gap) % ($this->max - $this->min + 1) + $this->min;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function generateFirst() {
|
|
||||||
return Hashing::generateRandomNumber($this->min, $this->max);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -36,10 +36,10 @@ class MailSender {
|
|||||||
public function setTemplate($type, $config) {
|
public function setTemplate($type, $config) {
|
||||||
$mailTemplate = MailTemplate::getTemplate($type);
|
$mailTemplate = MailTemplate::getTemplate($type);
|
||||||
$compiledMailContent = $mailTemplate->compile($config);
|
$compiledMailContent = $mailTemplate->compile($config);
|
||||||
|
|
||||||
$this->mailOptions = array_merge($this->mailOptions, $compiledMailContent);
|
$this->mailOptions = array_merge($this->mailOptions, $compiledMailContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function send() {
|
public function send() {
|
||||||
$mailerInstance = $this->getMailerInstance();
|
$mailerInstance = $this->getMailerInstance();
|
||||||
|
|
||||||
@ -49,6 +49,7 @@ class MailSender {
|
|||||||
throw new Exception('Mail sending data not available');
|
throw new Exception('Mail sending data not available');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$mailerInstance->ClearAllRecipients();
|
||||||
$mailerInstance->addAddress($this->mailOptions['to']);
|
$mailerInstance->addAddress($this->mailOptions['to']);
|
||||||
$mailerInstance->Subject = $this->mailOptions['subject'];
|
$mailerInstance->Subject = $this->mailOptions['subject'];
|
||||||
$mailerInstance->Body = $this->mailOptions['body'];
|
$mailerInstance->Body = $this->mailOptions['body'];
|
||||||
@ -88,4 +89,4 @@ class MailSender {
|
|||||||
|
|
||||||
return $this->mailerInstance;
|
return $this->mailerInstance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,10 +78,10 @@ class Ticket extends DataStore {
|
|||||||
$ticketQuantity = Ticket::count();
|
$ticketQuantity = Ticket::count();
|
||||||
|
|
||||||
if ($ticketQuantity === 0) {
|
if ($ticketQuantity === 0) {
|
||||||
$ticketNumber = $linearCongruentialGenerator->generateFirst();
|
$ticketNumber = Setting::getSetting('ticket-first-number')->value;
|
||||||
} else {
|
} else {
|
||||||
$linearCongruentialGenerator->setGap(Setting::getSetting('ticket-gap')->value);
|
$linearCongruentialGenerator->setGap(Setting::getSetting('ticket-gap')->value);
|
||||||
$linearCongruentialGenerator->setFirst(Ticket::getTicket(1)->ticketNumber);
|
$linearCongruentialGenerator->setFirst(Setting::getSetting('ticket-first-number')->value);
|
||||||
|
|
||||||
$ticketNumber = $linearCongruentialGenerator->generate($ticketQuantity);
|
$ticketNumber = $linearCongruentialGenerator->generate($ticketQuantity);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ class LinearCongruentialGeneratorTest extends TestCase {
|
|||||||
$linearCongruentialGenerator = new LinearCongruentialGenerator();
|
$linearCongruentialGenerator = new LinearCongruentialGenerator();
|
||||||
$linearCongruentialGenerator->setRange($min, $max);
|
$linearCongruentialGenerator->setRange($min, $max);
|
||||||
$linearCongruentialGenerator->setGap(Hashing::generateRandomPrime($min, $max));
|
$linearCongruentialGenerator->setGap(Hashing::generateRandomPrime($min, $max));
|
||||||
$linearCongruentialGenerator->setFirst($linearCongruentialGenerator->generateFirst());
|
$linearCongruentialGenerator->setFirst(Hashing::generateRandomNumber($min, $max));
|
||||||
|
|
||||||
$used = [];
|
$used = [];
|
||||||
|
|
||||||
|
4
version_upgrades/4.1.0/4.1.0.php
Normal file
4
version_upgrades/4.1.0/4.1.0.php
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?php
|
||||||
|
require_once '../mysql_connect.php';
|
||||||
|
|
||||||
|
$mysql->query(file_get_contents('./4.1.0.sql'));
|
100
version_upgrades/4.1.1/4.1.1.php
Normal file
100
version_upgrades/4.1.1/4.1.1.php
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
<?php
|
||||||
|
require_once '../mysql_connect.php';
|
||||||
|
|
||||||
|
require_once './libs/Hashing.php';
|
||||||
|
require_once './libs/LinearCongruentialGenerator.php';
|
||||||
|
require_once './libs/MailSender.php';
|
||||||
|
|
||||||
|
$ticketGap = Hashing::generateRandomPrime(1000000, 9999999);
|
||||||
|
$fileGap = Hashing::generateRandomPrime(1000000, 9999999);
|
||||||
|
$ticketFirstNumber = Hashing::generateRandomNumber(1000000, 9999999);
|
||||||
|
$fileFirstNumber = Hashing::generateRandomNumber(1000000, 9999999);
|
||||||
|
|
||||||
|
$mysql->query("UPDATE setting SET value='$ticketGap' WHERE name='ticket-gap'");
|
||||||
|
$mysql->query("UPDATE setting SET value='$fileGap' WHERE name='file-gap'");
|
||||||
|
$mysql->query("UPDATE setting SET value='$ticketFirstNumber' WHERE name='ticket-first-number'");
|
||||||
|
$mysql->query("UPDATE setting SET value='$fileFirstNumber' WHERE name='file-first-number'");
|
||||||
|
|
||||||
|
$smtpHost = $mysql->query("SELECT value FROM setting WHERE name='smtp-host'")->fetch_array(MYSQLI_ASSOC)['value'];
|
||||||
|
$smtpPort = $mysql->query("SELECT value FROM setting WHERE name='smtp-port'")->fetch_array(MYSQLI_ASSOC)['value'];
|
||||||
|
$smtpUser = $mysql->query("SELECT value FROM setting WHERE name='smtp-user'")->fetch_array(MYSQLI_ASSOC)['value'];
|
||||||
|
$smtpPassword = $mysql->query("SELECT value FROM setting WHERE name='smtp-pass'")->fetch_array(MYSQLI_ASSOC)['value'];
|
||||||
|
$noReplyEmail = $mysql->query("SELECT value FROM setting WHERE name='no-reply-email'")->fetch_array(MYSQLI_ASSOC)['value'];
|
||||||
|
$userSystemEnabled = $mysql->query("SELECT value FROM setting WHERE name='user-system-enabled'")->fetch_array(MYSQLI_ASSOC)['value'];
|
||||||
|
$url = $mysql->query("SELECT value FROM setting WHERE name='url'")->fetch_array(MYSQLI_ASSOC)['value'];
|
||||||
|
|
||||||
|
$mailSender = MailSender::getInstance();
|
||||||
|
$mailSender->setConnectionSettings(
|
||||||
|
$smtpHost, $smtpPort, $smtpUser, $smtpPassword, $noReplyEmail
|
||||||
|
);
|
||||||
|
|
||||||
|
function compileString($string, $config) {
|
||||||
|
$compiledString = $string;
|
||||||
|
|
||||||
|
foreach ($config as $configName => $configValue) {
|
||||||
|
$compiledString = str_replace("{{{$configName}}}", $configValue, $compiledString);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $compiledString;
|
||||||
|
}
|
||||||
|
|
||||||
|
$migrationMail = file_get_contents('./libs/migration-mail.html');
|
||||||
|
|
||||||
|
if($tickets = $mysql->query("SELECT * FROM ticket ORDER BY id ASC")) {
|
||||||
|
$linearCongruentialGenerator = new LinearCongruentialGenerator();
|
||||||
|
$linearCongruentialGenerator->setGap($ticketGap);
|
||||||
|
$linearCongruentialGenerator->setFirst($ticketFirstNumber);
|
||||||
|
$offset = 0;
|
||||||
|
$emails = [];
|
||||||
|
|
||||||
|
while($ticket = $tickets->fetch_assoc()) {
|
||||||
|
$ticketId = $ticket['id'];
|
||||||
|
$ticketNumber = $linearCongruentialGenerator->generate($offset);
|
||||||
|
|
||||||
|
$mysql->query("UPDATE ticket SET ticket_number='$ticketNumber' WHERE id='$ticketId'");
|
||||||
|
|
||||||
|
if(array_key_exists('author_email', $ticket) && $ticket['author_email']) {
|
||||||
|
if(!array_key_exists($ticket['author_email'], $emails)) {
|
||||||
|
$emails[$ticket['author_email']] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
array_push(
|
||||||
|
$emails[$ticket['author_email']],
|
||||||
|
[
|
||||||
|
'old_number' => $ticket['ticket_number'],
|
||||||
|
'new_number' => $ticketNumber,
|
||||||
|
'title' => $ticket['title']
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$offset++;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($emails as $email => $emailTickets) {
|
||||||
|
$ticketString = '';
|
||||||
|
|
||||||
|
foreach($emailTickets as $ticket) {
|
||||||
|
$ticketString .= '<p>';
|
||||||
|
$ticketString .= $ticket['old_number'];
|
||||||
|
$ticketString .= ' => ';
|
||||||
|
$ticketString .= $ticket['new_number'];
|
||||||
|
$ticketString .= ' ';
|
||||||
|
$ticketString .= htmlentities($ticket['title']);
|
||||||
|
$ticketString .= '</p>';
|
||||||
|
$ticketString .= PHP_EOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
$mailSender->setMailContent([
|
||||||
|
'to' => $email,
|
||||||
|
'subject' => 'Tickets have been updated',
|
||||||
|
'body' => compileString($migrationMail, [
|
||||||
|
'url' => $url,
|
||||||
|
'email' => $email,
|
||||||
|
'tickets' => $ticketString,
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
|
||||||
|
$mailSender->send();
|
||||||
|
}
|
||||||
|
}
|
44
version_upgrades/4.1.1/libs/Hashing.php
Normal file
44
version_upgrades/4.1.1/libs/Hashing.php
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
class Hashing {
|
||||||
|
public static function hashPassword($password) {
|
||||||
|
return password_hash($password, PASSWORD_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function verifyPassword($password, $hash) {
|
||||||
|
return password_verify($password, $hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function generateRandomToken() {
|
||||||
|
return md5(uniqid(rand()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function generateRandomNumber($min, $max) {
|
||||||
|
return rand($min, $max);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function generateRandomPrime($min, $max) {
|
||||||
|
$number = Hashing::generateRandomNumber($min, $max);
|
||||||
|
|
||||||
|
while(!Hashing::isPrime($number)) {
|
||||||
|
$number = Hashing::generateRandomNumber($min, $max);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function isPrime($number) {
|
||||||
|
$sqrt = sqrt($number);
|
||||||
|
$prime = true;
|
||||||
|
|
||||||
|
if($number <= 1) return false;
|
||||||
|
|
||||||
|
for($i = 2; $i <= $sqrt; $i++) {
|
||||||
|
if($number % $i === 0) {
|
||||||
|
$prime = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $prime;
|
||||||
|
}
|
||||||
|
}
|
29
version_upgrades/4.1.1/libs/LinearCongruentialGenerator.php
Normal file
29
version_upgrades/4.1.1/libs/LinearCongruentialGenerator.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
class LinearCongruentialGenerator {
|
||||||
|
private $gap;
|
||||||
|
private $first;
|
||||||
|
private $min = 100000;
|
||||||
|
private $max = 999999;
|
||||||
|
|
||||||
|
public function setRange($min, $max) {
|
||||||
|
$this->min = $min;
|
||||||
|
$this->max = $max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setGap($gap) {
|
||||||
|
if(!Hashing::isPrime($gap)) throw new Exception('LinearCongruentialGenerator: gap must be prime');
|
||||||
|
|
||||||
|
$this->gap = $gap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setFirst($first) {
|
||||||
|
$this->first = $first;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generate($offset) {
|
||||||
|
if(!$this->first) throw new Exception('LinearCongruentialGenerator: first is not set');
|
||||||
|
if(!$this->gap) throw new Exception('LinearCongruentialGenerator: gap is not set');
|
||||||
|
|
||||||
|
return ($this->first - $this->min + $offset * $this->gap) % ($this->max - $this->min + 1) + $this->min;
|
||||||
|
}
|
||||||
|
}
|
83
version_upgrades/4.1.1/libs/MailSender.php
Normal file
83
version_upgrades/4.1.1/libs/MailSender.php
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
<?php
|
||||||
|
require_once '../../server/vendor/autoload.php';
|
||||||
|
|
||||||
|
class MailSender {
|
||||||
|
|
||||||
|
private $mailOptions = [];
|
||||||
|
private $mailerInstance;
|
||||||
|
private static $instance = NULL;
|
||||||
|
|
||||||
|
public static function getInstance() {
|
||||||
|
if(MailSender::$instance === NULL) {
|
||||||
|
MailSender::$instance = new MailSender();
|
||||||
|
}
|
||||||
|
|
||||||
|
return MailSender::$instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function __construct() {}
|
||||||
|
|
||||||
|
public function setConnectionSettings($host, $port, $user, $pass, $noReplyEmail) {
|
||||||
|
$this->mailOptions['from'] = $noReplyEmail;
|
||||||
|
$this->mailOptions['fromName'] = 'OpenSupports';
|
||||||
|
|
||||||
|
$this->mailOptions['smtp-host'] = $host;
|
||||||
|
$this->mailOptions['smtp-port'] = $port;
|
||||||
|
$this->mailOptions['smtp-user'] = $user;
|
||||||
|
$this->mailOptions['smtp-pass'] = $pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setMailContent($mailContent) {
|
||||||
|
$this->mailOptions = array_merge($this->mailOptions, $mailContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function send() {
|
||||||
|
$mailerInstance = $this->getMailerInstance();
|
||||||
|
|
||||||
|
if( !array_key_exists('to', $this->mailOptions) ||
|
||||||
|
!array_key_exists('subject', $this->mailOptions) ||
|
||||||
|
!array_key_exists('body', $this->mailOptions) ) {
|
||||||
|
throw new Exception('Mail sending data not available');
|
||||||
|
}
|
||||||
|
|
||||||
|
$mailerInstance->ClearAllRecipients();
|
||||||
|
$mailerInstance->addAddress($this->mailOptions['to']);
|
||||||
|
$mailerInstance->Subject = $this->mailOptions['subject'];
|
||||||
|
$mailerInstance->Body = $this->mailOptions['body'];
|
||||||
|
$mailerInstance->isHTML(true);
|
||||||
|
|
||||||
|
if ($this->isConnected()) {
|
||||||
|
$mailerInstance->send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isConnected() {
|
||||||
|
return $this->getMailerInstance()->smtpConnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getMailerInstance() {
|
||||||
|
if(!($this->mailerInstance instanceof PHPMailer)) {
|
||||||
|
$this->mailerInstance = new PHPMailer();
|
||||||
|
|
||||||
|
$this->mailerInstance->From = $this->mailOptions['from'];
|
||||||
|
$this->mailerInstance->FromName = $this->mailOptions['fromName'];
|
||||||
|
|
||||||
|
$this->mailerInstance->isSMTP();
|
||||||
|
$this->mailerInstance->SMTPAuth = true;
|
||||||
|
$this->mailerInstance->Host = $this->mailOptions['smtp-host'];
|
||||||
|
$this->mailerInstance->Port = $this->mailOptions['smtp-port'];
|
||||||
|
$this->mailerInstance->Username = $this->mailOptions['smtp-user'];
|
||||||
|
$this->mailerInstance->Password = $this->mailOptions['smtp-pass'];
|
||||||
|
$this->mailerInstance->Timeout = 1000;
|
||||||
|
$this->mailerInstance->SMTPOptions = [
|
||||||
|
'ssl' => [
|
||||||
|
'verify_peer' => false,
|
||||||
|
'verify_peer_name' => false,
|
||||||
|
'allow_self_signed' => true
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->mailerInstance;
|
||||||
|
}
|
||||||
|
}
|
384
version_upgrades/4.1.1/libs/migration-mail.html
Normal file
384
version_upgrades/4.1.1/libs/migration-mail.html
Normal file
@ -0,0 +1,384 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>Support Center</title>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
/* Take care of image borders and formatting, client hacks */
|
||||||
|
img { max-width: 600px; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic;}
|
||||||
|
a img { border: none; }
|
||||||
|
table { border-collapse: collapse !important;}
|
||||||
|
#outlook a { padding:0; }
|
||||||
|
.ReadMsgBody { width: 100%; }
|
||||||
|
.ExternalClass { width: 100%; }
|
||||||
|
.backgroundTable { margin: 0 auto; padding: 0; width: 100% !important; }
|
||||||
|
table td { border-collapse: collapse; }
|
||||||
|
.ExternalClass * { line-height: 115%; }
|
||||||
|
.container-for-gmail-android { min-width: 600px; }
|
||||||
|
|
||||||
|
|
||||||
|
/* General styling */
|
||||||
|
* {
|
||||||
|
font-family: Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-webkit-text-size-adjust: none;
|
||||||
|
width: 100% !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
height: 100%;
|
||||||
|
color: #676767;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
font-family: Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #777777;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #676767;
|
||||||
|
text-decoration: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pull-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pull-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-lg,
|
||||||
|
.header-md,
|
||||||
|
.header-sm {
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: normal;
|
||||||
|
padding: 35px 0 0;
|
||||||
|
color: #4d4d4d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-md {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-sm {
|
||||||
|
padding: 5px 0;
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-padding {
|
||||||
|
padding: 20px 0 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-header-padding-right {
|
||||||
|
width: 290px;
|
||||||
|
text-align: right;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-header-padding-left {
|
||||||
|
width: 290px;
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.free-text {
|
||||||
|
width: 100% !important;
|
||||||
|
padding: 10px 60px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block-rounded {
|
||||||
|
border-radius: 5px;
|
||||||
|
border: 1px solid #e5e5e5;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
padding: 55px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-block {
|
||||||
|
padding: 0 20px;
|
||||||
|
width: 260px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mini-block-container {
|
||||||
|
padding: 30px 50px;
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mini-block {
|
||||||
|
background-color: #ffffff;
|
||||||
|
width: 498px;
|
||||||
|
border: 1px solid #cccccc;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 60px 75px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block-rounded {
|
||||||
|
width: 260px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-img {
|
||||||
|
width: 258px;
|
||||||
|
border-radius: 5px 5px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.force-width-img {
|
||||||
|
width: 480px;
|
||||||
|
height: 1px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.force-width-full {
|
||||||
|
width: 600px;
|
||||||
|
height: 1px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-img img {
|
||||||
|
width: 82px;
|
||||||
|
border-radius: 5px;
|
||||||
|
border: 1px solid #cccccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-img {
|
||||||
|
width: 92px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-msg {
|
||||||
|
width: 236px;
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: left;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-block {
|
||||||
|
padding: 10px 0;
|
||||||
|
border: 1px solid #cccccc;
|
||||||
|
color: #4d4d4d;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 17px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.force-width-gmail {
|
||||||
|
min-width:600px;
|
||||||
|
height: 0px !important;
|
||||||
|
line-height: 1px !important;
|
||||||
|
font-size: 1px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-width {
|
||||||
|
width: 228px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style type="text/css" media="screen">
|
||||||
|
@import url(http://fonts.googleapis.com/css?family=Oxygen:400,700);
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style type="text/css" media="screen">
|
||||||
|
@media screen {
|
||||||
|
/* Thanks Outlook 2013! */
|
||||||
|
* {
|
||||||
|
font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style type="text/css" media="only screen and (max-width: 480px)">
|
||||||
|
/* Mobile styles */
|
||||||
|
@media only screen and (max-width: 480px) {
|
||||||
|
|
||||||
|
table[class*="container-for-gmail-android"] {
|
||||||
|
min-width: 290px !important;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table[class="w320"] {
|
||||||
|
width: 320px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
img[class="force-width-gmail"] {
|
||||||
|
display: none !important;
|
||||||
|
width: 0 !important;
|
||||||
|
height: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
a[class="button-width"],
|
||||||
|
a[class="button-mobile"] {
|
||||||
|
width: 248px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class*="mobile-header-padding-left"] {
|
||||||
|
width: 160px !important;
|
||||||
|
padding-left: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class*="mobile-header-padding-right"] {
|
||||||
|
width: 160px !important;
|
||||||
|
padding-right: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="header-lg"] {
|
||||||
|
font-size: 24px !important;
|
||||||
|
padding-bottom: 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="header-md"] {
|
||||||
|
font-size: 18px !important;
|
||||||
|
padding-bottom: 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="content-padding"] {
|
||||||
|
padding: 5px 0 30px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="button"] {
|
||||||
|
padding: 15px 0 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class*="free-text"] {
|
||||||
|
padding: 10px 18px 30px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
img[class="force-width-img"],
|
||||||
|
img[class="force-width-full"] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="info-block"] {
|
||||||
|
display: block !important;
|
||||||
|
width: 280px !important;
|
||||||
|
padding-bottom: 40px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="info-img"],
|
||||||
|
img[class="info-img"] {
|
||||||
|
width: 278px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="mini-block-container"] {
|
||||||
|
padding: 8px 20px !important;
|
||||||
|
width: 280px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="mini-block"] {
|
||||||
|
padding: 20px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="user-img"] {
|
||||||
|
display: block !important;
|
||||||
|
text-align: center !important;
|
||||||
|
width: 100% !important;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td[class="user-msg"] {
|
||||||
|
display: block !important;
|
||||||
|
padding-bottom: 20px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#f7f7f7">
|
||||||
|
<table align="center" cellpadding="0" cellspacing="0" class="container-for-gmail-android" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td align="left" valign="top" width="100%" style="background-color: #ffffff;">
|
||||||
|
<center>
|
||||||
|
<table cellspacing="0" cellpadding="0" width="100%" bgcolor="#ffffff" style="border-bottom: 1px solid #cccccc">
|
||||||
|
<tr>
|
||||||
|
<td width="100%" height="80" valign="top" style="text-align: center; vertical-align:middle;">
|
||||||
|
<center>
|
||||||
|
<table cellpadding="0" cellspacing="0" width="600" class="w320">
|
||||||
|
<tr>
|
||||||
|
<td style="vertical-align: middle;">
|
||||||
|
<a href="http://www.opensupports.com/" target="_blank"><img height="47" src="http://opensupports.com/logo.png" alt="logo"></a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</center>
|
||||||
|
<!--[if gte mso 9]>
|
||||||
|
</v:textbox>
|
||||||
|
</v:rect>
|
||||||
|
<![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top" width="100%" style="background-color: #f7f7f7;" class="content-padding">
|
||||||
|
<center>
|
||||||
|
<table cellspacing="0" cellpadding="0" width="600" class="w320">
|
||||||
|
<tr>
|
||||||
|
<td class="header-lg">
|
||||||
|
Ticket numbers updated
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="free-text">
|
||||||
|
Hello, {{email}}. Due maintenance reasons, the following tickets have changed its number.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="mini-block-container">
|
||||||
|
<table cellspacing="0" cellpadding="0" width="100%" style="border-collapse:separate !important;">
|
||||||
|
<tr>
|
||||||
|
<td class="mini-block">
|
||||||
|
<table cellpadding="0" cellspacing="0" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td style="padding-bottom: 30px;">
|
||||||
|
{{tickets}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="button">
|
||||||
|
<div><!--[if mso]>
|
||||||
|
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{url}}/check-ticket/" style="height:45px;v-text-anchor:middle;width:155px;" arcsize="15%" strokecolor="#ffffff" fillcolor="#ff6f6f">
|
||||||
|
<w:anchorlock/>
|
||||||
|
<center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">Check Ticket</center>
|
||||||
|
</v:roundrect>
|
||||||
|
<![endif]--><a class="button-mobile" target="_blank" href="{{url}}/check-ticket/"
|
||||||
|
style="background-color:#ff6f6f;border-radius:5px;color:#ffffff;display:inline-block;font-family:'Cabin', Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;line-height:45px;text-align:center;text-decoration:none;width:155px;-webkit-text-size-adjust:none;mso-hide:all;">Check Tickets</a></div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" valign="top" width="100%" style="background-color: #ffffff; border-top: 1px solid #e5e5e5; border-bottom: 1px solid #e5e5e5; height: 100px;">
|
||||||
|
<center>
|
||||||
|
<table cellspacing="0" cellpadding="0" width="600" class="w320">
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 25px 0 25px">
|
||||||
|
<strong>OpenSupports</strong><br />
|
||||||
|
Open source ticket system<br />
|
||||||
|
www.opensupports.com<br /><br />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
13
version_upgrades/mysql_connect.php
Normal file
13
version_upgrades/mysql_connect.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$mysql_host = getenv('MYSQL_HOST');
|
||||||
|
$mysql_user = getenv('MYSQL_USER');
|
||||||
|
$mysql_password = getenv('MYSQL_PASSWORD');
|
||||||
|
$mysql_db = getenv('MYSQL_DB');
|
||||||
|
|
||||||
|
$mysql = new mysqli($mysql_host, $mysql_user, $mysql_password, $mysql_db);
|
||||||
|
|
||||||
|
if (mysqli_connect_errno()) {
|
||||||
|
printf("Connect failed: %s\n", mysqli_connect_error());
|
||||||
|
exit();
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user