diff --git a/admin/admin_reply_ticket.php b/admin/admin_reply_ticket.php
index a2b5ba22..0601eacd 100644
--- a/admin/admin_reply_ticket.php
+++ b/admin/admin_reply_ticket.php
@@ -145,10 +145,24 @@ if (strlen($message)) {
if ($hesk_settings['attachments']['use']) {
require(HESK_PATH . 'inc/attachments.inc.php');
$attachments = array();
- for ($i = 1; $i <= $hesk_settings['attachments']['max_number']; $i++) {
- $att = hesk_uploadFile($i);
- if ($att !== false && !empty($att)) {
- $attachments[$i] = $att;
+
+ $use_legacy_attachments = hesk_POST('use-legacy-attachments', 0);
+
+ if ($use_legacy_attachments) {
+ for ($i = 1; $i <= $hesk_settings['attachments']['max_number']; $i++) {
+ $att = hesk_uploadFile($i);
+ if ($att !== false && !empty($att)) {
+ $attachments[$i] = $att;
+ }
+ }
+ } else {
+ // The user used the new drag-and-drop system.
+ $temp_attachment_ids = hesk_POST_array('attachment-ids');
+ foreach ($temp_attachment_ids as $temp_attachment_id) {
+ // Simply get the temp info and move it to the attachments table
+ $temp_attachment = mfh_getTemporaryAttachment($temp_attachment_id);
+ $attachments[] = $temp_attachment;
+ mfh_deleteTemporaryAttachment($temp_attachment_id);
}
}
}
diff --git a/admin/admin_submit_ticket.php b/admin/admin_submit_ticket.php
index ab8e36d1..05937433 100644
--- a/admin/admin_submit_ticket.php
+++ b/admin/admin_submit_ticket.php
@@ -171,10 +171,23 @@ if ($hesk_settings['attachments']['use']) {
$attachments = array();
$trackingID = $tmpvar['trackid'];
- for ($i = 1; $i <= $hesk_settings['attachments']['max_number']; $i++) {
- $att = hesk_uploadFile($i);
- if ($att !== false && !empty($att)) {
- $attachments[$i] = $att;
+ $use_legacy_attachments = hesk_POST('use-legacy-attachments', 0);
+
+ if ($use_legacy_attachments) {
+ for ($i = 1; $i <= $hesk_settings['attachments']['max_number']; $i++) {
+ $att = hesk_uploadFile($i);
+ if ($att !== false && !empty($att)) {
+ $attachments[$i] = $att;
+ }
+ }
+ } else {
+ // The user used the new drag-and-drop system.
+ $temp_attachment_ids = hesk_POST_array('attachment-ids');
+ foreach ($temp_attachment_ids as $temp_attachment_id) {
+ // Simply get the temp info and move it to the attachments table
+ $temp_attachment = mfh_getTemporaryAttachment($temp_attachment_id);
+ $attachments[] = $temp_attachment;
+ mfh_deleteTemporaryAttachment($temp_attachment_id);
}
}
}
diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php
index 941121e2..5975a028 100644
--- a/admin/admin_ticket.php
+++ b/admin/admin_ticket.php
@@ -314,12 +314,27 @@ if (isset($_POST['notemsg']) && hesk_token_check('POST')) {
require(HESK_PATH . 'inc/htmLawed.php');
require(HESK_PATH . 'inc/attachments.inc.php');
$attachments = array();
- for ($i = 1; $i <= $hesk_settings['attachments']['max_number']; $i++) {
- $att = hesk_uploadFile($i);
- if ($att !== false && !empty($att)) {
- $attachments[$i] = $att;
+
+ $use_legacy_attachments = hesk_POST('use-legacy-attachments', 0);
+
+ if ($use_legacy_attachments) {
+ for ($i = 1; $i <= $hesk_settings['attachments']['max_number']; $i++) {
+ $att = hesk_uploadFile($i);
+ if ($att !== false && !empty($att)) {
+ $attachments[$i] = $att;
+ }
+ }
+ } else {
+ // The user used the new drag-and-drop system.
+ $temp_attachment_ids = hesk_POST_array('attachment-ids');
+ foreach ($temp_attachment_ids as $temp_attachment_id) {
+ // Simply get the temp info and move it to the attachments table
+ $temp_attachment = mfh_getTemporaryAttachment($temp_attachment_id);
+ $attachments[] = $temp_attachment;
+ mfh_deleteTemporaryAttachment($temp_attachment_id);
}
}
+
}
$myattachments = '';
@@ -1238,23 +1253,32 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
@@ -1954,14 +1985,29 @@ function new_article()
require_once(HESK_PATH . 'inc/posting_functions.inc.php');
require_once(HESK_PATH . 'inc/attachments.inc.php');
$attachments = array();
- for ($i=1;$i<=3;$i++)
- {
- $att = hesk_uploadFile($i, false);
- if ( ! empty($att))
+
+ $use_legacy_attachments = hesk_POST('use-legacy-attachments', 0);
+
+ if ($use_legacy_attachments) {
+ for ($i=1; $i<=3; $i++)
{
- $attachments[$i] = $att;
+ $att = hesk_uploadFile($i, false);
+ if ( ! empty($att))
+ {
+ $attachments[$i] = $att;
+ }
+ }
+ } else {
+ // The user used the new drag-and-drop system.
+ $temp_attachment_ids = hesk_POST_array('attachment-ids');
+ foreach ($temp_attachment_ids as $temp_attachment_id) {
+ // Simply get the temp info and move it to the attachments table
+ $temp_attachment = mfh_getTemporaryAttachment($temp_attachment_id);
+ $attachments[] = $temp_attachment;
+ mfh_deleteTemporaryAttachment($temp_attachment_id);
}
}
+
$myattachments='';
/* Any errors? */
diff --git a/admin/new_ticket.php b/admin/new_ticket.php
index 74d23344..d3351af9 100644
--- a/admin/new_ticket.php
+++ b/admin/new_ticket.php
@@ -40,6 +40,7 @@ define('AUTOFOCUS', true);
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
+require(HESK_PATH . 'inc/view_attachment_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
@@ -1032,18 +1033,24 @@ if ($hesk_settings['attachments']['use']) {
diff --git a/css/dropzone-basic.min.css b/css/dropzone-basic.min.css
new file mode 100644
index 00000000..5238d5ca
--- /dev/null
+++ b/css/dropzone-basic.min.css
@@ -0,0 +1 @@
+.dropzone,.dropzone *{box-sizing:border-box}.dropzone{position:relative}.dropzone .dz-preview{position:relative;display:inline-block;width:120px;margin:0.5em}.dropzone .dz-preview .dz-progress{display:block;height:15px;border:1px solid #aaa}.dropzone .dz-preview .dz-progress .dz-upload{display:block;height:100%;width:0;background:green}.dropzone .dz-preview .dz-error-message{color:red;display:none}.dropzone .dz-preview.dz-error .dz-error-message,.dropzone .dz-preview.dz-error .dz-error-mark{display:block}.dropzone .dz-preview.dz-success .dz-success-mark{display:block}.dropzone .dz-preview .dz-error-mark,.dropzone .dz-preview .dz-success-mark{position:absolute;display:none;left:30px;top:30px;width:54px;height:58px;left:50%;margin-left:-27px}
diff --git a/css/dropzone.min.css b/css/dropzone.min.css
new file mode 100644
index 00000000..d04515e2
--- /dev/null
+++ b/css/dropzone.min.css
@@ -0,0 +1 @@
+@-webkit-keyframes passing-through{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%, 70%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}100%{opacity:0;-webkit-transform:translateY(-40px);-moz-transform:translateY(-40px);-ms-transform:translateY(-40px);-o-transform:translateY(-40px);transform:translateY(-40px)}}@-moz-keyframes passing-through{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%, 70%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}100%{opacity:0;-webkit-transform:translateY(-40px);-moz-transform:translateY(-40px);-ms-transform:translateY(-40px);-o-transform:translateY(-40px);transform:translateY(-40px)}}@keyframes passing-through{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%, 70%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}100%{opacity:0;-webkit-transform:translateY(-40px);-moz-transform:translateY(-40px);-ms-transform:translateY(-40px);-o-transform:translateY(-40px);transform:translateY(-40px)}}@-webkit-keyframes slide-in{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}}@-moz-keyframes slide-in{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}}@keyframes slide-in{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}}@-webkit-keyframes pulse{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}10%{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}20%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}@-moz-keyframes pulse{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}10%{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}20%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}@keyframes pulse{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}10%{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}20%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}.dropzone,.dropzone *{box-sizing:border-box}.dropzone{min-height:150px;border:2px solid rgba(0,0,0,0.3);background:white;padding:20px 20px}.dropzone.dz-clickable{cursor:pointer}.dropzone.dz-clickable *{cursor:default}.dropzone.dz-clickable .dz-message,.dropzone.dz-clickable .dz-message *{cursor:pointer}.dropzone.dz-started .dz-message{display:none}.dropzone.dz-drag-hover{border-style:solid}.dropzone.dz-drag-hover .dz-message{opacity:0.5}.dropzone .dz-message{text-align:center;margin:2em 0}.dropzone .dz-preview{position:relative;display:inline-block;vertical-align:top;margin:16px;min-height:100px}.dropzone .dz-preview:hover{z-index:1000}.dropzone .dz-preview:hover .dz-details{opacity:1}.dropzone .dz-preview.dz-file-preview .dz-image{border-radius:20px;background:#999;background:linear-gradient(to bottom, #eee, #ddd)}.dropzone .dz-preview.dz-file-preview .dz-details{opacity:1}.dropzone .dz-preview.dz-image-preview{background:white}.dropzone .dz-preview.dz-image-preview .dz-details{-webkit-transition:opacity 0.2s linear;-moz-transition:opacity 0.2s linear;-ms-transition:opacity 0.2s linear;-o-transition:opacity 0.2s linear;transition:opacity 0.2s linear}.dropzone .dz-preview .dz-remove{font-size:14px;text-align:center;display:block;cursor:pointer;border:none}.dropzone .dz-preview .dz-remove:hover{text-decoration:underline}.dropzone .dz-preview:hover .dz-details{opacity:1}.dropzone .dz-preview .dz-details{z-index:20;position:absolute;top:0;left:0;opacity:0;font-size:13px;min-width:100%;max-width:100%;padding:2em 1em;text-align:center;color:rgba(0,0,0,0.9);line-height:150%}.dropzone .dz-preview .dz-details .dz-size{margin-bottom:1em;font-size:16px}.dropzone .dz-preview .dz-details .dz-filename{white-space:nowrap}.dropzone .dz-preview .dz-details .dz-filename:hover span{border:1px solid rgba(200,200,200,0.8);background-color:rgba(255,255,255,0.8)}.dropzone .dz-preview .dz-details .dz-filename:not(:hover){overflow:hidden;text-overflow:ellipsis}.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span{border:1px solid transparent}.dropzone .dz-preview .dz-details .dz-filename span,.dropzone .dz-preview .dz-details .dz-size span{background-color:rgba(255,255,255,0.4);padding:0 0.4em;border-radius:3px}.dropzone .dz-preview:hover .dz-image img{-webkit-transform:scale(1.05, 1.05);-moz-transform:scale(1.05, 1.05);-ms-transform:scale(1.05, 1.05);-o-transform:scale(1.05, 1.05);transform:scale(1.05, 1.05);-webkit-filter:blur(8px);filter:blur(8px)}.dropzone .dz-preview .dz-image{border-radius:20px;overflow:hidden;width:120px;height:120px;position:relative;display:block;z-index:10}.dropzone .dz-preview .dz-image img{display:block}.dropzone .dz-preview.dz-success .dz-success-mark{-webkit-animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);-moz-animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);-ms-animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);-o-animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1)}.dropzone .dz-preview.dz-error .dz-error-mark{opacity:1;-webkit-animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);-moz-animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);-ms-animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);-o-animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1)}.dropzone .dz-preview .dz-success-mark,.dropzone .dz-preview .dz-error-mark{pointer-events:none;opacity:0;z-index:500;position:absolute;display:block;top:50%;left:50%;margin-left:-27px;margin-top:-27px}.dropzone .dz-preview .dz-success-mark svg,.dropzone .dz-preview .dz-error-mark svg{display:block;width:54px;height:54px}.dropzone .dz-preview.dz-processing .dz-progress{opacity:1;-webkit-transition:all 0.2s linear;-moz-transition:all 0.2s linear;-ms-transition:all 0.2s linear;-o-transition:all 0.2s linear;transition:all 0.2s linear}.dropzone .dz-preview.dz-complete .dz-progress{opacity:0;-webkit-transition:opacity 0.4s ease-in;-moz-transition:opacity 0.4s ease-in;-ms-transition:opacity 0.4s ease-in;-o-transition:opacity 0.4s ease-in;transition:opacity 0.4s ease-in}.dropzone .dz-preview:not(.dz-processing) .dz-progress{-webkit-animation:pulse 6s ease infinite;-moz-animation:pulse 6s ease infinite;-ms-animation:pulse 6s ease infinite;-o-animation:pulse 6s ease infinite;animation:pulse 6s ease infinite}.dropzone .dz-preview .dz-progress{opacity:1;z-index:1000;pointer-events:none;position:absolute;height:16px;left:50%;top:50%;margin-top:-8px;width:80px;margin-left:-40px;background:rgba(255,255,255,0.9);-webkit-transform:scale(1);border-radius:8px;overflow:hidden}.dropzone .dz-preview .dz-progress .dz-upload{background:#333;background:linear-gradient(to bottom, #666, #444);position:absolute;top:0;left:0;bottom:0;width:0;-webkit-transition:width 300ms ease-in-out;-moz-transition:width 300ms ease-in-out;-ms-transition:width 300ms ease-in-out;-o-transition:width 300ms ease-in-out;transition:width 300ms ease-in-out}.dropzone .dz-preview.dz-error .dz-error-message{display:block}.dropzone .dz-preview.dz-error:hover .dz-error-message{opacity:1;pointer-events:auto}.dropzone .dz-preview .dz-error-message{pointer-events:none;z-index:1000;position:absolute;display:block;display:none;opacity:0;-webkit-transition:opacity 0.3s ease;-moz-transition:opacity 0.3s ease;-ms-transition:opacity 0.3s ease;-o-transition:opacity 0.3s ease;transition:opacity 0.3s ease;border-radius:8px;font-size:13px;top:130px;left:-10px;width:140px;background:#be2626;background:linear-gradient(to bottom, #be2626, #a92222);padding:0.5em 1.2em;color:white}.dropzone .dz-preview .dz-error-message:after{content:'';position:absolute;top:-6px;left:64px;width:0;height:0;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #be2626}
diff --git a/inc/attachments.inc.php b/inc/attachments.inc.php
index 001ec25b..bde3ba93 100644
--- a/inc/attachments.inc.php
+++ b/inc/attachments.inc.php
@@ -40,13 +40,23 @@ function hesk_uploadFile($i, $isTicket = true)
{
global $hesk_settings, $hesklang, $trackingID, $hesk_error_buffer, $modsForHesk_settings;
+ $single_file = $i == -1;
/* Return if name is empty */
- if (empty($_FILES['attachment']['name'][$i])) {
+ $name = $single_file
+ ? $_FILES['attachment']['name']
+ : $_FILES['attachment']['name'][$i];
+
+ if (empty($name)) {
return '';
}
+
/* Parse the name */
- $file_realname = hesk_cleanFileName($_FILES['attachment']['name'][$i]);
+ if ($single_file) {
+ $file_realname = hesk_cleanFileName($_FILES['attachment']['name']);
+ } else {
+ $file_realname = hesk_cleanFileName($_FILES['attachment']['name'][$i]);
+ }
/* Check file extension */
$ext = strtolower(strrchr($file_realname, "."));
@@ -55,10 +65,13 @@ function hesk_uploadFile($i, $isTicket = true)
}
/* Check file size */
- if ($_FILES['attachment']['size'][$i] > $hesk_settings['attachments']['max_size']) {
+ $size = $single_file
+ ? $_FILES['attachment']['size']
+ : $_FILES['attachment']['size'][$i];
+ if ($size > $hesk_settings['attachments']['max_size']) {
return hesk_fileError(sprintf($hesklang['file_too_large'], $file_realname));
} else {
- $file_size = $_FILES['attachment']['size'][$i];
+ $file_size = $size;
}
/* Generate a random file name */
@@ -68,11 +81,8 @@ function hesk_uploadFile($i, $isTicket = true)
$tmp .= $useChars{mt_rand(0, 29)};
}
- if (defined('KB')) {
- $file_name = substr(md5($tmp . $file_realname), 0, 200) . $ext;
- } else {
- $file_name = substr($trackingID . '_' . md5($tmp . $file_realname), 0, 200) . $ext;
- }
+
+ $file_name = substr(md5($tmp . $file_realname), 0, 200) . $ext;
// Does the temporary file exist? If not, probably server-side configuration limits have been reached
// Uncomment this for debugging purposes
@@ -88,7 +98,10 @@ function hesk_uploadFile($i, $isTicket = true)
if (!$isTicket) {
$directory = $modsForHesk_settings['kb_attach_dir'];
}
- if (!move_uploaded_file($_FILES['attachment']['tmp_name'][$i], dirname(dirname(__FILE__)) . '/' . $directory . '/' . $file_name)) {
+ $file_to_move = $single_file
+ ? $_FILES['attachment']['tmp_name']
+ : $_FILES['attachment']['tmp_name'][$i];
+ if (!move_uploaded_file($file_to_move, dirname(dirname(__FILE__)) . '/' . $directory . '/' . $file_name)) {
return hesk_fileError($hesklang['cannot_move_tmp']);
}
@@ -130,3 +143,29 @@ function hesk_removeAttachments($attachments, $isTicket)
return true;
} // End hesk_removeAttachments()
+
+
+function mfh_getTemporaryAttachment($id) {
+ global $hesk_settings;
+
+ $rs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "temp_attachment` WHERE `id` = " . intval($id));
+ if (hesk_dbNumRows($rs) == 0) {
+ return NULL;
+ }
+ $row = hesk_dbFetchAssoc($rs);
+
+ $info = array(
+ 'saved_name' => $row['saved_name'],
+ 'real_name' => $row['file_name'],
+ 'size' => $row['size']
+ );
+
+ return $info;
+}
+
+
+function mfh_deleteTemporaryAttachment($id) {
+ global $hesk_settings;
+
+ hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "temp_attachment` WHERE `id` = ".intval($id));
+}
\ No newline at end of file
diff --git a/inc/common.inc.php b/inc/common.inc.php
index 99ed0bd7..58ef87ba 100644
--- a/inc/common.inc.php
+++ b/inc/common.inc.php
@@ -1836,4 +1836,11 @@ function mfh_log_warning($location, $message, $user) {
function mfh_log_error($location, $message, $user) {
mfh_log($location, $message, 3, $user);
+}
+
+function mfh_bytesToUnits($size) {
+ $bytes_in_megabyte = 1048576;
+ $quotient = $size / $bytes_in_megabyte;
+
+ return intval($quotient);
}
\ No newline at end of file
diff --git a/inc/header.inc.php b/inc/header.inc.php
index 9d5e67eb..406dad64 100644
--- a/inc/header.inc.php
+++ b/inc/header.inc.php
@@ -99,9 +99,12 @@ if (is_dir(HESK_PATH . 'install')) {
+
+
+
+