Merge pull request #301 from mkoch227/attachment-improvements

Attachment improvements, phase one
merge-requests/2/head
Mike Koch 9 years ago
commit 25dd548e35

2
.gitignore vendored

@ -11,7 +11,6 @@ docs/docs_style.css
docs/index.html
docs/quick-guide.html
docs/step-by-step-guide.html
download_attachment.php
file_limits.php
footer.txt
header.txt
@ -147,7 +146,6 @@ img/unlock.png
img/vertical.jpg
img/view.png
inc/assignment_search.inc.php
inc/attachments.inc.php
inc/calendar/img/cal.gif
inc/calendar/img/next_mon.gif
inc/calendar/img/next_year.gif

@ -697,9 +697,9 @@ if ( defined('HESK_DEMO') )
</div>
</div>
<div class="form-group">
<label for="s_attach_dir" class="col-sm-3 control-label"><?php echo $hesklang['atf']; ?> <a href="Javascript:void(0)" onclick="Javascript:hesk_window('<?php echo $help_folder; ?>helpdesk.html#62','400','500')"><i class="fa fa-question-circle settingsquestionmark"></i></a></label>
<label for="s_attach_dir" class="col-sm-3 control-label"><?php echo $hesklang['ticket_attach_dir']; ?> <a href="Javascript:void(0)" onclick="Javascript:hesk_window('<?php echo $help_folder; ?>helpdesk.html#62','400','500')"><i class="fa fa-question-circle settingsquestionmark"></i></a></label>
<div class="col-sm-9">
<input type="text" class="form-control" placeholder="<?php echo htmlspecialchars($hesklang['atf']); ?>" name="s_attach_dir" size="40" maxlength="255" value="<?php echo $hesk_settings['attach_dir']; ?>" />
<input type="text" class="form-control" placeholder="<?php echo htmlspecialchars($hesklang['ticket_attach_dir']); ?>" name="s_attach_dir" size="40" maxlength="255" value="<?php echo $hesk_settings['attach_dir']; ?>" />
</div>
</div>
<div class="form-group">
@ -1287,6 +1287,21 @@ if ( defined('HESK_DEMO') )
?>
</div>
</div>
<div class="form-group">
<label for="kb_attach_dir" class="col-sm-4 control-label">
<span class="label label-primary"
data-toggle="tooltip"
title="<?php echo $hesklang['added_in_mods_for_hesk']; ?>"><?php echo $hesklang['mods_for_hesk_acronym']; ?></span>
<?php echo $hesklang['kb_attach_dir']; ?>
<i class="fa fa-question-circle settingsquestionmark" data-toggle="htmlpopover"
title="<?php echo $hesklang['kb_attach_dir']; ?>"
data-content="<?php echo $hesklang['kb_attach_dir_help']; ?>"></i>
</label>
<div class="col-sm-8">
<input type="text" class="form-control" placeholder="<?php echo htmlspecialchars($hesklang['kb_attach_dir']); ?>" name="kb_attach_dir" size="40" maxlength="255" value="<?php echo $modsForHesk_settings['kb_attach_dir']; ?>">
</div>
</div>
<div class="form-group">
<label for="knowledgebase-visibility-setting" class="col-sm-4 col-xs-12 control-label">
<span class="label label-primary"

@ -518,6 +518,7 @@ $set['request_location'] = empty($_POST['request_location']) ? 0 : 1;
$set['category_order_column'] = empty($_POST['category_order_column']) ? 'cat_order' : 'name';
$set['rich_text_for_tickets'] = empty($_POST['rich_text_for_tickets']) ? 0 : 1;
$set['statuses_order_column'] = empty($_POST['statuses_order_column']) ? 'sort' : 'name';
$set['kb_attach_dir'] = hesk_POST('kb_attach_dir', 'attachments');
if ($set['customer-email-verification-required'])
{
@ -592,7 +593,10 @@ $modsForHesk_settings[\'category_order_column\'] = \''.$set['category_order_colu
$modsForHesk_settings[\'rich_text_for_tickets\'] = '.$set['rich_text_for_tickets'].';
//-- Column to sort statuses by. Can be either \'sort\' or \'name\'
$modsForHesk_settings[\'statuses_order_column\'] = \''.$set['statuses_order_column'].'\';';
$modsForHesk_settings[\'statuses_order_column\'] = \''.$set['statuses_order_column'].'\';
//-- Directory to store knowledgebase articles in.
$modsForHesk_settings[\'kb_attach_dir\'] = \''.$set['kb_attach_dir'].'\';';
// Write the file
if ( ! file_put_contents(HESK_PATH . 'modsForHesk_settings.inc.php', $modsForHesk_file_content) )

@ -42,6 +42,7 @@ require(HESK_PATH . 'modsForHesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/status_functions.inc.php');
require(HESK_PATH . 'inc/view_attachment_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
@ -1430,7 +1431,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
}
}
/* Attachments */
hesk_listAttachments($ticket['attachments']);
mfh_listAttachments($ticket['attachments'], 0, true);
// Show suggested KB articles
if ($hesk_settings['kb_enable'] && $hesk_settings['kb_recommendanswers'] && strlen($ticket['articles']) )
@ -1504,154 +1505,6 @@ require_once(HESK_PATH . 'inc/footer.inc.php');
/*** START FUNCTIONS ***/
function hesk_listAttachments($attachments='', $reply=0, $white=1)
{
global $hesk_settings, $hesklang, $trackingID, $can_edit, $can_delete;
/* Attachments disabled or not available */
if ( ! $hesk_settings['attachments']['use'] || ! strlen($attachments) )
{
return false;
}
/* List attachments */
echo '<p><b>'.$hesklang['attachments'].':</b></p><br />';
$att=explode(',',substr($attachments, 0, -1));
echo '<div class="table-responsive">';
echo '<table class="table table-striped attachment-table">';
echo '<thead><tr><th>&nbsp;</th><th>'.$hesklang['file_name'].'</th><th>'.$hesklang['action'].'</th></tr></thead>';
echo '<tbody>';
foreach ($att as $myatt)
{
list($att_id, $att_name) = explode('#', $myatt);
$fileparts = pathinfo($att_name);
$fontAwesomeIcon = hesk_getFontAwesomeIconForFileExtension($fileparts['extension']);
echo '
<tr>
<td>';
//-- File is an image
if ($fontAwesomeIcon == 'fa fa-file-image-o') {
//-- Get the actual image location and display a thumbnail. It will be linked to a modal to view a larger size.
$path = hesk_getSavedNameUrlForAttachment($att_id);
if ($path == '') {
echo '<i class="fa fa-ban fa-4x" data-toggle="tooltip" title="'.$hesklang['attachment_removed'].'"></i>';
} else {
echo '<span data-toggle="tooltip" title="'.$hesklang['click_to_preview'].'">
<img src="'.$path.'" alt="'.$hesklang['image'].'" data-toggle="modal" data-target="#modal-attachment-'.$att_id.'">
</span>';
echo '<div class="modal fade" id="modal-attachment-'.$att_id.'" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="myModalLabel">'.$att_name.'</h4>
</div>
<div class="modal-body">
<img class="img-responsive" src="'.$path.'" alt="'.$hesklang['image'].'">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">'.$hesklang['close_modal'].'</button>
<a href="../download_attachment.php?att_id='.$att_id.'&amp;track='.$trackingID.'" class="btn btn-success">'.$hesklang['dnl'].'</a>
</div>
</div>
</div>
</div>';
}
} else {
//-- Display the FontAwesome icon in the panel's body
echo '<i class="'.$fontAwesomeIcon.' fa-4x"></i>';
}
echo'
</td>
<td>
<p>'.$att_name.'</p>
</td>
<td>
<div class="btn-group">';
/* Can edit and delete tickets? */
if ($can_edit && $can_delete)
{
echo '<a class="btn btn-danger" href="admin_ticket.php?delatt='.$att_id.'&amp;reply='.$reply.'&amp;track='.$trackingID.'&amp;Refresh='.mt_rand(10000,99999).'&amp;token='.hesk_token_echo(0).'" onclick="return hesk_confirmExecute(\''.hesk_makeJsString($hesklang['pda']).'\');" data-toggle="tooltip" data-placement="top" data-original-title="'.$hesklang['delete'].'"><i class="fa fa-times"></i></a> ';
}
echo '<a class="btn btn-success" href="../download_attachment.php?att_id='.$att_id.'&amp;track='.$trackingID.'"
data-toggle="tooltip" data-placement="top" data-original-title="'.$hesklang['dnl'].'">
<i class="fa fa-arrow-down"></i>
</a>';
echo '</div>
</td>
</tr>
';
}
echo '</tbody></table></div>';
return true;
} // End hesk_listAttachments()
function hesk_getSavedNameUrlForAttachment($att_id)
{
global $hesk_settings;
//-- Call the DB for the attachment
$nameRS = hesk_dbQuery("SELECT `saved_name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` WHERE `att_id` = ".hesk_dbEscape($att_id));
$name = hesk_dbFetchAssoc($nameRS);
$realpath = '../'.$hesk_settings['attach_dir'] . '/' . $name['saved_name'];
return !file_exists($realpath) ? '' : $realpath;
}
function hesk_getFontAwesomeIconForFileExtension($fileExtension)
{
$imageExtensions = array('jpg','jpeg','png','bmp','gif');
//-- Word, Excel, and PPT file extensions: http://en.wikipedia.org/wiki/List_of_Microsoft_Office_filename_extensions
$wordFileExtensions = array('doc','docx','dotm','dot','docm','docb');
$excelFileExtensions = array('xls','xlt','xlm','xlsx','xlsm','xltx','xltm');
$pptFileExtensions = array('ppt','pot','pps','pptx','pptm','potx','potm','ppsx','ppsm','sldx','sldm');
//-- File archive extensions: http://en.wikipedia.org/wiki/List_of_archive_formats
$archiveFileExtensions = array('tar','gz','zip','rar','7z','bz2','lz','lzma','tgz','tbz2','zipx');
//-- Audio file extensions: http://en.wikipedia.org/wiki/Audio_file_format#List_of_formats
$audioFileExtensions = array('3gp','act','aiff','aac','amr','au','awb','dct','dss','dvf','flac','gsm','iklax','ivs','m4a','m4p','mmf','mp3','mpc','msv','ogg','oga','opus','ra','rm','raw','tta','vox','wav','wma','wv');
//-- Video file extensions: http://en.wikipedia.org/wiki/Video_file_format#List_of_video_file_formats
$videoFileExtensions = array('webm','mkv','flv','drc','mng','avi','mov','qt','wmv','yuv','rm','rmvb','asf','mp4','m4p','m4v','mpg','mp2','mpeg','mpe','mpv','m2v','svi','3gp','3g2','mxf','roq','nsv');
//-- The only one I know of :D
$pdfFileExtensions = array('pdf');
$textFileExtensions = array('txt');
$icon = 'fa fa-file-';
$fileExtension = strtolower($fileExtension);
if (in_array($fileExtension, $imageExtensions)) {
$icon.='image-o';
} elseif (in_array($fileExtension, $wordFileExtensions)) {
$icon.='word-o';
} elseif (in_array($fileExtension, $excelFileExtensions)) {
$icon.='excel-o';
} elseif (in_array($fileExtension, $pptFileExtensions)) {
$icon.='powerpoint-o';
} elseif (in_array($fileExtension, $archiveFileExtensions)) {
$icon.='archive-o';
} elseif (in_array($fileExtension, $audioFileExtensions)) {
$icon.='audio-o';
} elseif (in_array($fileExtension, $videoFileExtensions)) {
$icon.='video-o';
} elseif (in_array($fileExtension, $pdfFileExtensions)) {
$icon.='pdf-o';
} elseif (in_array($fileExtension, $textFileExtensions)) {
$icon.='text-o';
} else {
$icon.='o';
}
return $icon;
}
function hesk_getAdminButtons($reply=0,$white=1)
{
global $hesk_settings, $hesklang, $ticket, $reply, $trackingID, $can_edit, $can_archive, $can_delete, $isManager;
@ -1851,7 +1704,7 @@ function hesk_printTicketReplies() {
} ?></p>
</div>
<div class="ticketMessageTop pushMargin">
<?php hesk_listAttachments($reply['attachments'],$reply['id']);
<?php mfh_listAttachments($reply['attachments'],$reply['id'],true);
/* Staff rating */
if ($hesk_settings['rating'] && $reply['staffid'])
{

@ -37,6 +37,7 @@ define('HESK_PATH','../');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'modsForHesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
hesk_load_database_functions();
@ -1113,7 +1114,7 @@ function save_article()
$attachments = array();
for ($i=1;$i<=3;$i++)
{
$att = hesk_uploadFile($i);
$att = hesk_uploadFile($i, false);
if ( ! empty($att))
{
$attachments[$i] = $att;
@ -1922,7 +1923,7 @@ function new_article()
$attachments = array();
for ($i=1;$i<=3;$i++)
{
$att = hesk_uploadFile($i);
$att = hesk_uploadFile($i, false);
if ( ! empty($att))
{
$attachments[$i] = $att;

@ -0,0 +1,189 @@
<?php
/*******************************************************************************
* Title: Help Desk Software HESK
* Version: 2.6.4 from 22nd June 2015
* Author: Klemen Stirn
* Website: http://www.hesk.com
********************************************************************************
* COPYRIGHT AND TRADEMARK NOTICE
* Copyright 2005-2015 Klemen Stirn. All Rights Reserved.
* HESK is a registered trademark of Klemen Stirn.
* The HESK may be used and modified free of charge by anyone
* AS LONG AS COPYRIGHT NOTICES AND ALL THE COMMENTS REMAIN INTACT.
* By using this code you agree to indemnify Klemen Stirn from any
* liability that might arise from it's use.
* Selling the code for this program, in part or full, without prior
* written consent is expressly forbidden.
* Using this code, in part or full, to create derivate work,
* new scripts or products is expressly forbidden. Obtain permission
* before redistributing this software over the Internet or in
* any other medium. In all cases copyright and header must remain intact.
* This Copyright is in full effect in any country that has International
* Trade Agreements with the United States of America or
* with the European Union.
* Removing any of the copyright notices without purchasing a license
* is expressly forbidden. To remove HESK copyright notice you must purchase
* a license for this script. For more information on how to obtain
* a license please visit the page below:
* https://www.hesk.com/buy.php
*******************************************************************************/
define('IN_SCRIPT',1);
define('HESK_PATH','./');
// Get all the required files and functions
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'modsForHesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
hesk_load_database_functions();
hesk_session_start();
// Are we in maintenance mode? (check customers only)
if ( empty($SESSION['id']) )
{
hesk_check_maintenance();
}
// Knowledgebase attachments
if ( isset($_GET['kb_att']) )
{
// Attachment ID
$att_id = intval( hesk_GET('kb_att') ) or hesk_error($hesklang['id_not_valid']);
// Connect to database
hesk_dbConnect();
// Get attachment info
$res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_attachments` WHERE `att_id`='{$att_id}' LIMIT 1");
if (hesk_dbNumRows($res) != 1)
{
hesk_error($hesklang['id_not_valid'].' (att_id)');
}
$file = hesk_dbFetchAssoc($res);
// Is this person allowed access to this attachment?
$res = hesk_dbQuery("SELECT `t1`.`type` as `cat_type`, `t2`.`type` as `art_type`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_articles` AS `t2`
JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_categories` AS `t1`
ON `t2`.`catid` = `t1`.`id`
WHERE (`t2`.`attachments` LIKE '{$att_id}#%' OR `t2`.`attachments` LIKE '%,{$att_id}#%' )
LIMIT 1");
// If no attachment found, throw an error
if (hesk_dbNumRows($res) != 1)
{
hesk_error($hesklang['id_not_valid'].' (no_art)');
}
$row = hesk_dbFetchAssoc($res);
// Private or draft article or category?
if ($row['cat_type'] || $row['art_type'])
{
if ( empty($_SESSION['id']) )
{
// This is a staff-only attachment
hesk_error($hesklang['attpri']);
}
elseif ($row['art_type'] == 2)
{
// Need permission to manage KB to access draft attachments
require(HESK_PATH . 'inc/admin_functions.inc.php');
hesk_checkPermission('can_man_kb');
}
}
}
// Ticket attachments
else
{
// Attachmend ID and ticket tracking ID
$att_id = intval( hesk_GET('att_id', 0) ) or die($hesklang['id_not_valid']);
$tic_id = hesk_cleanID() or die("$hesklang[int_error]: $hesklang[no_trackID]");
// Connect to database
hesk_dbConnect();
// Get attachment info
$res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` WHERE `att_id`='{$att_id}' LIMIT 1");
if (hesk_dbNumRows($res) != 1)
{
hesk_error($hesklang['id_not_valid'].' (att_id)');
}
$file = hesk_dbFetchAssoc($res);
// Is ticket ID valid for this attachment?
if ($file['ticket_id'] != $tic_id)
{
hesk_error($hesklang['trackID_not_found']);
}
// Verify email address match if needed
if ( empty($_SESSION['id']) )
{
hesk_verifyEmailMatch($tic_id);
// Only staff may download attachments to notes
if ($file['type'])
{
hesk_error($hesklang['perm_deny']);
}
}
// Update the download count
}
// Path of the file on the server
$realpath = $hesk_settings['attach_dir'] . '/' . $file['saved_name'];
if (isset($_GET['kb_att'])) {
$realpath = $modsForHesk_settings['kb_attach_dir'] . '/' . $file['saved_name'];
}
// Perhaps the file has been deleted?
if ( ! file_exists($realpath))
{
hesk_error($hesklang['attdel']);
}
// Update the download count
if ( isset($_GET['kb_att']) ) {
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_attachments` SET `download_count` = `download_count` + 1 WHERE `att_id` = '{$att_id}'");
} else {
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` SET `download_count` = `download_count` + 1 WHERE `att_id` = '{$att_id}'");
}
// Send the file as an attachment to prevent malicious code from executing
header("Pragma: "); # To fix a bug in IE when running https
header("Cache-Control: "); # To fix a bug in IE when running https
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Length: ' . $file['size']);
header('Content-Disposition: attachment; filename=' . $file['real_name']);
// For larger files use chunks, smaller ones can be read all at once
$chunksize = 1048576; // = 1024 * 1024 (1 Mb)
if ($file['size'] > $chunksize)
{
$handle = fopen($realpath, 'rb');
$buffer = '';
while ( ! feof($handle))
{
set_time_limit(300);
$buffer = fread($handle, $chunksize);
echo $buffer;
flush();
}
fclose($handle);
}
else
{
readfile($realpath);
}
exit();
?>

@ -0,0 +1,142 @@
<?php
/*******************************************************************************
* Title: Help Desk Software HESK
* Version: 2.6.4 from 22nd June 2015
* Author: Klemen Stirn
* Website: http://www.hesk.com
********************************************************************************
* COPYRIGHT AND TRADEMARK NOTICE
* Copyright 2005-2015 Klemen Stirn. All Rights Reserved.
* HESK is a registered trademark of Klemen Stirn.
* The HESK may be used and modified free of charge by anyone
* AS LONG AS COPYRIGHT NOTICES AND ALL THE COMMENTS REMAIN INTACT.
* By using this code you agree to indemnify Klemen Stirn from any
* liability that might arise from it's use.
* Selling the code for this program, in part or full, without prior
* written consent is expressly forbidden.
* Using this code, in part or full, to create derivate work,
* new scripts or products is expressly forbidden. Obtain permission
* before redistributing this software over the Internet or in
* any other medium. In all cases copyright and header must remain intact.
* This Copyright is in full effect in any country that has International
* Trade Agreements with the United States of America or
* with the European Union.
* Removing any of the copyright notices without purchasing a license
* is expressly forbidden. To remove HESK copyright notice you must purchase
* a license for this script. For more information on how to obtain
* a license please visit the page below:
* https://www.hesk.com/buy.php
*******************************************************************************/
/* Check if this is a valid include */
if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
/***************************
Function hesk_uploadFiles()
***************************/
function hesk_uploadFile($i, $isTicket = true)
{
global $hesk_settings, $hesklang, $trackingID, $hesk_error_buffer, $modsForHesk_settings;
/* Return if name is empty */
if (empty($_FILES['attachment']['name'][$i])) {return '';}
/* Parse the name */
$file_realname = hesk_cleanFileName($_FILES['attachment']['name'][$i]);
/* Check file extension */
$ext = strtolower(strrchr($file_realname, "."));
if ( ! in_array($ext,$hesk_settings['attachments']['allowed_types']))
{
return hesk_fileError(sprintf($hesklang['type_not_allowed'], $ext, $file_realname));
}
/* Check file size */
if ($_FILES['attachment']['size'][$i] > $hesk_settings['attachments']['max_size'])
{
return hesk_fileError(sprintf($hesklang['file_too_large'], $file_realname));
}
else
{
$file_size = $_FILES['attachment']['size'][$i];
}
/* Generate a random file name */
$useChars='AEUYBDGHJLMNPQRSTVWXZ123456789';
$tmp = uniqid();
for($j=1;$j<10;$j++)
{
$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;
}
// Does the temporary file exist? If not, probably server-side configuration limits have been reached
// Uncomment this for debugging purposes
/*
if ( ! file_exists($_FILES['attachment']['tmp_name'][$i]) )
{
return hesk_fileError($hesklang['fnuscphp']);
}
*/
/* If upload was successful let's create the headers */
$directory = $hesk_settings['attach_dir'];
if (!$isTicket) {
$directory = $modsForHesk_settings['kb_attach_dir'];
}
if ( ! move_uploaded_file($_FILES['attachment']['tmp_name'][$i], dirname(dirname(__FILE__)).'/'.$directory.'/'.$file_name))
{
return hesk_fileError($hesklang['cannot_move_tmp']);
}
$info = array(
'saved_name'=> $file_name,
'real_name' => $file_realname,
'size' => $file_size
);
return $info;
} // End hesk_uploadFile()
function hesk_fileError($error)
{
global $hesk_settings, $hesklang, $trackingID;
global $hesk_error_buffer;
$hesk_error_buffer['attachments'] = $error;
return false;
} // End hesk_fileError()
function hesk_removeAttachments($attachments, $isTicket)
{
global $hesk_settings, $hesklang, $modsForHesk_settings;
$directory = $hesk_settings['attach_dir'];
if (!$isTicket) {
$directory = $modsForHesk_settings['kb_attach_dir'];
}
$hesk_settings['server_path'] = dirname(dirname(__FILE__)).'/'.$directory.'/';
foreach ($attachments as $myatt)
{
hesk_unlink($hesk_settings['server_path'].$myatt['saved_name']);
}
return true;
} // End hesk_removeAttachments()

@ -1972,4 +1972,13 @@ function mfh_getDisplayTextForStatusId($statusId) {
// Fallback to the language key
return $hesklang[$statusRec['Key']];
}
}
function mfh_getNumberOfDownloadsForAttachment($att_id, $table='attachments')
{
global $hesk_settings;
$res = hesk_dbQuery('SELECT `download_count` FROM `'.hesk_dbEscape($hesk_settings['db_pfix'].$table)."` WHERE `att_id` = ".intval($att_id));
$rec = hesk_dbFetchAssoc($res);
return $rec['download_count'];
}

@ -0,0 +1,162 @@
<?php
function mfh_listAttachments($attachments='', $reply=0, $is_staff)
{
global $hesk_settings, $hesklang, $trackingID, $can_edit, $can_delete;
/* Attachments disabled or not available */
if ( ! $hesk_settings['attachments']['use'] || ! strlen($attachments) )
{
return false;
}
/* List attachments */
echo '<p><b>'.$hesklang['attachments'].':</b></p><br />';
$att=explode(',',substr($attachments, 0, -1));
echo '<div class="table-responsive">';
echo '<table class="table table-striped attachment-table">';
echo '<thead>
<tr>
<th>&nbsp;</th>
<th>' . $hesklang['file_name'] . '</th>';
if ($is_staff) {
echo '<th>'.$hesklang['download_count'].'</th>';
}
echo '<th>'.$hesklang['action'].'</th>
</tr>
</thead>';
echo '<tbody>';
foreach ($att as $myatt)
{
list($att_id, $att_name) = explode('#', $myatt);
$fileparts = pathinfo($att_name);
$fontAwesomeIcon = mfh_getFontAwesomeIconForFileExtension($fileparts['extension']);
echo '
<tr>
<td>';
//-- File is an image
if ($fontAwesomeIcon == 'fa fa-file-image-o') {
//-- Get the actual image location and display a thumbnail. It will be linked to a modal to view a larger size.
$path = mfh_getSavedNameUrlForAttachment($att_id, $is_staff);
if ($path == '') {
echo '<i class="fa fa-ban fa-4x" data-toggle="tooltip" title="'.$hesklang['attachment_removed'].'"></i>';
} else {
echo '<span data-toggle="tooltip" title="'.$hesklang['click_to_preview'].'">
<img src="'.$path.'" alt="'.$hesklang['image'].'" data-toggle="modal" data-target="#modal-attachment-'.$att_id.'">
</span>';
echo '<div class="modal fade" id="modal-attachment-'.$att_id.'" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="myModalLabel">'.$att_name.'</h4>
</div>
<div class="modal-body">
<img class="img-responsive" src="'.$path.'" alt="'.$hesklang['image'].'">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">'.$hesklang['close_modal'].'</button>
<a href="../download_attachment.php?att_id='.$att_id.'&amp;track='.$trackingID.'" class="btn btn-success">'.$hesklang['dnl'].'</a>
</div>
</div>
</div>
</div>';
}
} else {
//-- Display the FontAwesome icon in the panel's body
echo '<i class="'.$fontAwesomeIcon.' fa-4x"></i>';
}
echo'
</td>
<td>
<p>'.$att_name.'</p>
</td>';
if ($is_staff) {
echo '<td>'.mfh_getNumberOfDownloadsForAttachment($att_id).'</td>';
}
echo '<td>
<div class="btn-group">';
/* Can edit and delete tickets? */
if ($is_staff && $can_edit && $can_delete)
{
echo '<a class="btn btn-danger" href="admin_ticket.php?delatt='.$att_id.'&amp;reply='.$reply.'&amp;track='.$trackingID.'&amp;Refresh='.mt_rand(10000,99999).'&amp;token='.hesk_token_echo(0).'" onclick="return hesk_confirmExecute(\''.hesk_makeJsString($hesklang['pda']).'\');" data-toggle="tooltip" data-placement="top" data-original-title="'.$hesklang['delete'].'"><i class="fa fa-times"></i></a> ';
}
echo '<a class="btn btn-success" href="../download_attachment.php?att_id='.$att_id.'&amp;track='.$trackingID.'"
data-toggle="tooltip" data-placement="top" data-original-title="'.$hesklang['dnl'].'">
<i class="fa fa-arrow-down"></i>
</a>';
echo '</div>
</td>
</tr>
';
}
echo '</tbody></table></div>';
return true;
} // End hesk_listAttachments()
function mfh_getSavedNameUrlForAttachment($att_id, $is_staff)
{
global $hesk_settings;
//-- Call the DB for the attachment
$nameRS = hesk_dbQuery("SELECT `saved_name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` WHERE `att_id` = ".hesk_dbEscape($att_id));
$name = hesk_dbFetchAssoc($nameRS);
if ($is_staff) {
$realpath = '../'.$hesk_settings['attach_dir'] . '/' . $name['saved_name'];
} else {
$realpath = $hesk_settings['attach_dir'] . '/' . $name['saved_name'];
}
return !file_exists($realpath) ? '' : $realpath;
}
function mfh_getFontAwesomeIconForFileExtension($fileExtension)
{
$imageExtensions = array('jpg','jpeg','png','bmp','gif');
//-- Word, Excel, and PPT file extensions: http://en.wikipedia.org/wiki/List_of_Microsoft_Office_filename_extensions
$wordFileExtensions = array('doc','docx','dotm','dot','docm','docb');
$excelFileExtensions = array('xls','xlt','xlm','xlsx','xlsm','xltx','xltm');
$pptFileExtensions = array('ppt','pot','pps','pptx','pptm','potx','potm','ppsx','ppsm','sldx','sldm');
//-- File archive extensions: http://en.wikipedia.org/wiki/List_of_archive_formats
$archiveFileExtensions = array('tar','gz','zip','rar','7z','bz2','lz','lzma','tgz','tbz2','zipx');
//-- Audio file extensions: http://en.wikipedia.org/wiki/Audio_file_format#List_of_formats
$audioFileExtensions = array('3gp','act','aiff','aac','amr','au','awb','dct','dss','dvf','flac','gsm','iklax','ivs','m4a','m4p','mmf','mp3','mpc','msv','ogg','oga','opus','ra','rm','raw','tta','vox','wav','wma','wv');
//-- Video file extensions: http://en.wikipedia.org/wiki/Video_file_format#List_of_video_file_formats
$videoFileExtensions = array('webm','mkv','flv','drc','mng','avi','mov','qt','wmv','yuv','rm','rmvb','asf','mp4','m4p','m4v','mpg','mp2','mpeg','mpe','mpv','m2v','svi','3gp','3g2','mxf','roq','nsv');
//-- The only one I know of :D
$pdfFileExtensions = array('pdf');
$textFileExtensions = array('txt');
$icon = 'fa fa-file-';
$fileExtension = strtolower($fileExtension);
if (in_array($fileExtension, $imageExtensions)) {
$icon.='image-o';
} elseif (in_array($fileExtension, $wordFileExtensions)) {
$icon.='word-o';
} elseif (in_array($fileExtension, $excelFileExtensions)) {
$icon.='excel-o';
} elseif (in_array($fileExtension, $pptFileExtensions)) {
$icon.='powerpoint-o';
} elseif (in_array($fileExtension, $archiveFileExtensions)) {
$icon.='archive-o';
} elseif (in_array($fileExtension, $audioFileExtensions)) {
$icon.='audio-o';
} elseif (in_array($fileExtension, $videoFileExtensions)) {
$icon.='video-o';
} elseif (in_array($fileExtension, $pdfFileExtensions)) {
$icon.='pdf-o';
} elseif (in_array($fileExtension, $textFileExtensions)) {
$icon.='text-o';
} else {
$icon.='o';
}
return $icon;
}

@ -2,7 +2,6 @@
define('IN_SCRIPT', 1);
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
echo $hesklang['yes'];
function executeQuery($sql) {
global $hesk_last_query;
@ -557,6 +556,8 @@ function execute240Scripts() {
global $hesk_settings;
hesk_dbConnect();
// Setup quick help sections
executeQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."quick_help_sections` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`location` VARCHAR(100) NOT NULL,
@ -572,6 +573,7 @@ function execute240Scripts() {
executeQuery("INSERT INTO `hesk_quick_help_sections` (`location`, `show`)
VALUES ('knowledgebase', '1')");
// Setup status improvement tables
executeQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."text_to_status_xref` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`language` VARCHAR(200) NOT NULL,
@ -586,6 +588,12 @@ function execute240Scripts() {
WHERE `id`='".intval($myStatus['ID'])."' LIMIT 1");
$i += 10;
}
// Process attachment improvement tables
executeQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` ADD COLUMN `download_count` INT NOT NULL DEFAULT 0");
executeQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_attachments` ADD COLUMN `download_count` INT NOT NULL DEFAULT 0");
executeQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."settings` SET `Value` = '2.4.0' WHERE `Key` = 'modsForHeskVersion'");
}
function initializeXrefTable() {
@ -607,6 +615,8 @@ function initializeXrefTable() {
}
function execute240FileUpdate() {
global $hesk_settings;
$file = file_get_contents(HESK_PATH . 'modsForHesk_settings.inc.php');
//-- Only add the additional settings if they aren't already there.
@ -624,6 +634,13 @@ $modsForHesk_settings[\'category_order_column\'] = \'cat_order\';';
//-- Setting for using rich-text editor for tickets. 0 = Disable, 1 = Enable
$modsForHesk_settings[\'rich_text_for_tickets\'] = 0;';
}
if (strpos($file, '$modsForHesk_settings[\'kb_attach_dir\']') === false)
{
$file .= '
//-- Directory to store knowledgebase articles in.
$modsForHesk_settings[\'kb_attach_dir\'] = \''.$hesk_settings['attach_dir'].'\';';
}
return file_put_contents(HESK_PATH.'modsForHesk_settings.inc.php', $file);
}

@ -53,6 +53,11 @@ $hesklang['status_sort'] = 'Status Sorting';
$hesklang['status_sort_help'] = 'Determines if statuses shown on the manage statuses page and all dropdowns are sorted by the user-defined order (default), or sorted alphabetically.';
$hesklang['cannot_delete_status_tickets'] = 'This status cannot be deleted because there are tickets set to this status.';
$hesklang['default_statuses_updated'] = 'Default statuses have been updated!';
$hesklang['download_count'] = 'Download Count';
$hesklang['kb_attach_dir'] = 'Knowledgebase attachments folder';
$hesklang['kb_attach_dir_help'] = 'Name of the folder, where knowledgebase attachments will be stored.<br><br>The folder needs to exist within the main HESK folder and be writable by PHP. On most systems names are CaSe SeNSiTiVe.
<br><br>Allowed chars (other will be removed): a-z A-Z 0-9 _ -';
$hesklang['ticket_attach_dir'] = 'Ticket attachments folder';
// ADDED OR MODIFIED IN Mods for HESK 2.3.0
$hesklang['sm_icon'] = 'Icon';

@ -55,4 +55,7 @@ $modsForHesk_settings['category_order_column'] = 'cat_order';
$modsForHesk_settings['rich_text_for_tickets'] = 0;
//-- Column to sort statuses by. Can be either 'sort' or 'name'
$modsForHesk_settings['statuses_order_column'] = 'sort';
$modsForHesk_settings['statuses_order_column'] = 'sort';
//-- Directory to store knowledgebase articles in.
$modsForHesk_settings['kb_attach_dir'] = 'attachments';

@ -40,6 +40,7 @@ define('WYSIWYG',1);
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/view_attachment_functions.inc.php');
// Are we in maintenance mode?
hesk_check_maintenance();
@ -407,7 +408,7 @@ if (!$show['show']) {
}
}
/* Attachments */
hesk_listAttachments($ticket['attachments'], $i);
mfh_listAttachments($ticket['attachments'], $i, false);
?>
</div>
</div>
@ -726,7 +727,7 @@ function hesk_printCustomerTicketReplies()
<div class="message"><?php echo hesk_html_entity_decode($reply['message']); ?></div>
</div>
<div class="ticketMessageTop">
<?php hesk_listAttachments($reply['attachments'],$i);?>
<?php mfh_listAttachments($reply['attachments'],$i,false);?>
</div>
</div>
</div>
@ -738,37 +739,6 @@ function hesk_printCustomerTicketReplies()
} // End hesk_printCustomerTicketReplies()
function hesk_listAttachments($attachments='', $white=1)
{
global $hesk_settings, $hesklang, $trackingID;
/* Attachments disabled or not available */
if ( ! $hesk_settings['attachments']['use'] || ! strlen($attachments) )
{
return false;
}
/* Style and mousover/mousout */
$tmp = $white ? 'White' : 'Blue';
$style = 'class="option'.$tmp.'OFF" onmouseover="this.className=\'option'.$tmp.'ON\'" onmouseout="this.className=\'option'.$tmp.'OFF\'"';
/* List attachments */
echo '<p><b>'.$hesklang['attachments'].':</b><br />';
$att=explode(',',substr($attachments, 0, -1));
foreach ($att as $myatt)
{
list($att_id, $att_name) = explode('#', $myatt);
echo '
<a href="download_attachment.php?att_id='.$att_id.'&amp;track='.$trackingID.$hesk_settings['e_query'].'"><img src="img/clip.png" width="16" height="16" alt="'.$hesklang['dnl'].' '.$att_name.'" title="'.$hesklang['dnl'].' '.$att_name.'" '.$style.' /></a>
<a href="download_attachment.php?att_id='.$att_id.'&amp;track='.$trackingID.$hesk_settings['e_query'].'">'.$att_name.'</a><br />
';
}
echo '</p>';
return true;
} // End hesk_listAttachments()
function hesk_getCustomerButtons($white=1)
{

Loading…
Cancel
Save