diff --git a/.gitignore b/.gitignore index 7b12609a..e4ef0e68 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 5e578079..a9d235b6 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -697,9 +697,9 @@ if ( defined('HESK_DEMO') )
- +
- +
@@ -1287,6 +1287,21 @@ if ( defined('HESK_DEMO') ) ?>
+ +
+ +
+ +
+
- $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(); +?> diff --git a/inc/attachments.inc.php b/inc/attachments.inc.php new file mode 100644 index 00000000..8a56797a --- /dev/null +++ b/inc/attachments.inc.php @@ -0,0 +1,142 @@ + $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() diff --git a/inc/common.inc.php b/inc/common.inc.php index 5a6a7074..1c43e76f 100644 --- a/inc/common.inc.php +++ b/inc/common.inc.php @@ -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']; } \ No newline at end of file diff --git a/inc/view_attachment_functions.inc.php b/inc/view_attachment_functions.inc.php new file mode 100644 index 00000000..39dee973 --- /dev/null +++ b/inc/view_attachment_functions.inc.php @@ -0,0 +1,162 @@ +'.$hesklang['attachments'].':


'; + $att=explode(',',substr($attachments, 0, -1)); + echo '
'; + echo ''; + echo ' + + + '; + if ($is_staff) { + echo ''; + } + echo ' + + '; + echo ''; + foreach ($att as $myatt) + { + + list($att_id, $att_name) = explode('#', $myatt); + $fileparts = pathinfo($att_name); + $fontAwesomeIcon = mfh_getFontAwesomeIconForFileExtension($fileparts['extension']); + echo ' + + + '; + if ($is_staff) { + echo ''; + } + echo ' + + '; + } + echo '
 ' . $hesklang['file_name'] . ''.$hesklang['download_count'].''.$hesklang['action'].'
'; + //-- 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 ''; + } else { + echo ' + '.$hesklang['image'].' + '; + echo ''; + } + } else { + //-- Display the FontAwesome icon in the panel's body + echo ''; + } + echo' + +

'.$att_name.'

+
'.mfh_getNumberOfDownloadsForAttachment($att_id).' +
'; + /* Can edit and delete tickets? */ + if ($is_staff && $can_edit && $can_delete) + { + echo ' '; + } + echo ' + + '; + echo '
+
'; + + 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; +} \ No newline at end of file diff --git a/install/mods-for-hesk/sql/installSql.php b/install/mods-for-hesk/sql/installSql.php index 53405010..76cdb845 100644 --- a/install/mods-for-hesk/sql/installSql.php +++ b/install/mods-for-hesk/sql/installSql.php @@ -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); } \ No newline at end of file diff --git a/language/en/text.php b/language/en/text.php index f193e14c..b225a82f 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -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.

The folder needs to exist within the main HESK folder and be writable by PHP. On most systems names are CaSe SeNSiTiVe. +

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'; diff --git a/modsForHesk_settings.inc.php b/modsForHesk_settings.inc.php index ca271ed5..6e152745 100644 --- a/modsForHesk_settings.inc.php +++ b/modsForHesk_settings.inc.php @@ -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'; \ No newline at end of file +$modsForHesk_settings['statuses_order_column'] = 'sort'; + +//-- Directory to store knowledgebase articles in. +$modsForHesk_settings['kb_attach_dir'] = 'attachments'; \ No newline at end of file diff --git a/ticket.php b/ticket.php index ff9412c4..bc1e34c2 100644 --- a/ticket.php +++ b/ticket.php @@ -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); ?>
@@ -726,7 +727,7 @@ function hesk_printCustomerTicketReplies()
- +
@@ -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 '

'.$hesklang['attachments'].':
'; - $att=explode(',',substr($attachments, 0, -1)); - foreach ($att as $myatt) - { - list($att_id, $att_name) = explode('#', $myatt); - - echo ' - '.$hesklang['dnl'].' '.$att_name.' - '.$att_name.'
- '; - } - echo '

'; - - return true; -} // End hesk_listAttachments() - function hesk_getCustomerButtons($white=1) {