diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5a26031..e6cc039 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,53 +1,33 @@ name: Build on: push: - branches: main + tags: '*' jobs: - release-on-push: + prepare-data: + name: Prepare Data runs-on: ubuntu-latest - outputs: - ver: ${{ steps.release.outputs.version }} - tag: ${{ steps.release.outputs.tag_name }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + outputs: + tag: ${{ steps.prepare.outputs.SOURCE_TAG }} steps: - - id: release - uses: rymndhng/release-on-push-action@master - with: - bump_version_scheme: norelease - - - name: Check Output Parameters + - id: prepare + name: Prepare environment variables run: | - echo "Got tag name ${{ steps.release.outputs.tag_name }}" - echo "Got release version ${{ steps.release.outputs.version }}" - - docker-dh: - name: Push to Docker Hub - needs: [release-on-push] + echo ::set-output name=SOURCE_NAME::${GITHUB_REF#refs/*/} + echo ::set-output name=SOURCE_BRANCH::${GITHUB_REF#refs/heads/} + echo ::set-output name=SOURCE_TAG::${GITHUB_REF#refs/tags/} + + build: + name: GitHub Package Registry runs-on: ubuntu-latest + needs: [prepare-data] steps: - uses: actions/checkout@v2 - - name: Login to DockerHub Registry - run: echo ${{ secrets.DOCKERHUB_PASSWORD }} | docker login -u ${{ secrets.DOCKERHUB_USERNAME }} --password-stdin - - name: Build image for Docker Hub - run: docker build . --file Dockerfile --build-arg VERSION=${{ needs.release-on-push.outputs.ver }} --tag luketainton/hesk-docker:${{ needs.release-on-push.outputs.tag }} --tag luketainton/hesk-docker:latest - - name: Push image to Docker Hub - run: | - docker push luketainton/hesk-docker:${{ needs.release-on-push.outputs.tag }} && - docker push luketainton/hesk-docker:latest - - docker-ghr: - name: Push to GitHub Package Registry - needs: [release-on-push] - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Login to DockerHub Registry - run: echo ${{ secrets.GITHUB_TOKEN }} | docker login https://docker.pkg.github.com -u luketainton --password-stdin + - name: Login to GitHub Package Registry + run: echo ${{ secrets.PAT }} | docker login ghcr.io -u luketainton --password-stdin - name: Build image for GitHub Package Registry - run: docker build . --file Dockerfile --build-arg VERSION=${{ needs.release-on-push.outputs.ver }} --tag docker.pkg.github.com/luketainton/hesk-docker/hesk-docker:latest --tag docker.pkg.github.com/luketainton/hesk-docker/hesk-docker:${{ needs.release-on-push.outputs.tag }} + run: docker build . --file Dockerfile --tag ghcr.io/luketainton/hesk:${{ needs.prepare-data.outputs.tag }} --tag ghcr.io/luketainton/hesk:latest - name: Push image to GitHub Package Registry run: | - docker push docker.pkg.github.com/luketainton/hesk-docker/hesk-docker:${{ needs.release-on-push.outputs.tag }} && - docker push docker.pkg.github.com/luketainton/hesk-docker/hesk-docker:latest + docker push ghcr.io/luketainton/hesk:latest + docker push ghcr.io/luketainton/hesk:${{ needs.prepare-data.outputs.tag }} \ No newline at end of file diff --git a/hesk/admin/admin_main.php b/hesk/admin/admin_main.php index 2e33985..32a37cb 100644 --- a/hesk/admin/admin_main.php +++ b/hesk/admin/admin_main.php @@ -50,27 +50,6 @@ hesk_handle_messages(); /* Print tickets? */ if (hesk_checkPermission('can_view_tickets',0)) { - if ( ! isset($_SESSION['hide']['ticket_list']) ) - { - // Show 'Tickets' if resolved tickets are shown by default - if (isset($_SESSION['default_list']) && strpos($_SESSION['default_list'], 's3=1') !== false) { - $table_title = $hesklang['tickets']; - } else { - $table_title = $hesklang['open_tickets']; - } - - $header_text = ' -
-

'.$table_title.' (%%HESK_TICKET_COUNT%%)

-
- -   - -
-
- '; - } - /* Reset default settings? */ if ( isset($_GET['reset']) && hesk_token_check() ) { @@ -85,6 +64,7 @@ if (hesk_checkPermission('can_view_tickets',0)) } /* Print the list of tickets */ + $href = 'admin_main.php'; require(HESK_PATH . 'inc/print_tickets.inc.php'); echo " 
"; diff --git a/hesk/admin/admin_reply_ticket.php b/hesk/admin/admin_reply_ticket.php index 3f454ed..18b0e93 100644 --- a/hesk/admin/admin_reply_ticket.php +++ b/hesk/admin/admin_reply_ticket.php @@ -39,6 +39,19 @@ hesk_session_start(); hesk_dbConnect(); hesk_isLoggedIn(); +// Prevent flooding - multiple replies within a few seconds are probably not valid +if ($hesk_settings['flood']) +{ + if (isset($_SESSION['last_reply_timestamp']) && (time() - $_SESSION['last_reply_timestamp']) < $hesk_settings['flood']) + { + hesk_error($hesklang['e_flood']); + } + else + { + $_SESSION['last_reply_timestamp'] = time(); + } +} + /* Check permissions for this feature */ hesk_checkPermission('can_reply_tickets'); @@ -76,6 +89,29 @@ require_once(HESK_PATH . 'inc/statuses.inc.php'); if (strlen($message)) { + $message_html = $message; + + // Handle rich-text tickets + if ($hesk_settings['staff_ticket_formatting'] == 2) { + // Decode the message we encoded earlier + $message_html = hesk_html_entity_decode($message_html); + + // Clean the HTML code and set the plaintext version + require(HESK_PATH . 'inc/htmlpurifier/HeskHTMLPurifier.php'); + require(HESK_PATH . 'inc/html2text/html2text.php'); + $purifier = new HeskHTMLPurifier($hesk_settings['cache_dir']); + $message_html = $purifier->heskPurify($message_html); + + $message = convert_html_to_text($message_html); + $message = fix_newlines($message); + + // Re-encode the message + $message = hesk_htmlspecialchars($message); + } elseif ($hesk_settings['staff_ticket_formatting'] == 0) { + $message_html = hesk_makeURL($message_html); + $message_html = nl2br($message_html); + } + // Save message for later and ignore the rest? if ( isset($_POST['save_reply']) ) { @@ -83,7 +119,7 @@ if (strlen($message)) hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."reply_drafts` WHERE `owner`=".intval($_SESSION['id'])." AND `ticket`=".intval($ticket['id'])); // Save the message draft - hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."reply_drafts` (`owner`, `ticket`, `message`) VALUES (".intval($_SESSION['id']).", ".intval($ticket['id']).", '".hesk_dbEscape($message)."')"); + hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."reply_drafts` (`owner`, `ticket`, `message`, `message_html`) VALUES (".intval($_SESSION['id']).", ".intval($ticket['id']).", '".hesk_dbEscape($message)."', '".hesk_dbEscape($message_html)."')"); /* Set reply submitted message */ $_SESSION['HESK_SUCCESS'] = TRUE; @@ -97,7 +133,7 @@ if (strlen($message)) elseif ($_SESSION['afterreply'] == 2) { /* Get the next open ticket that needs a reply */ - $res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `owner` IN ('0','".intval($_SESSION['id'])."') AND " . hesk_myCategories() . " AND `status` IN ('0','1') ORDER BY `owner` DESC, `priority` ASC LIMIT 1"); + $res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `owner` IN ('0','".intval($_SESSION['id'])."') AND " . hesk_myCategories() . " AND `status` IN ('0','1') AND `id` != ".intval($ticket['id']). " ORDER BY `owner` DESC, `priority` ASC LIMIT 1"); if (hesk_dbNumRows($res) == 1) { @@ -121,6 +157,14 @@ if (strlen($message)) if ( ! $submit_as_customer && ! empty($_POST['signature']) && strlen($_SESSION['signature'])) { $message .= "\n\n" . addslashes($_SESSION['signature']) . "\n"; + + // Make signature links clickable + $signature = hesk_makeURL($_SESSION['signature']); + + // Turn newlines into
tags + $signature = nl2br($signature); + + $message_html .= "

" . addslashes($signature) . "
"; } // Make links clickable @@ -188,11 +232,11 @@ if ($hesk_settings['attachments']['use'] && !empty($attachments)) // Add reply if ($submit_as_customer) { - hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` (`replyto`,`name`,`message`,`dt`,`attachments`) VALUES ('".intval($replyto)."','".hesk_dbEscape(addslashes($ticket['name']))."','".hesk_dbEscape($message."

{$hesklang['creb']} {$_SESSION['name']}")."',NOW(),'".hesk_dbEscape($myattachments)."')"); + hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` (`replyto`,`name`,`message`,`message_html`,`dt`,`attachments`) VALUES ('".intval($replyto)."','".hesk_dbEscape(addslashes($ticket['name']))."','".hesk_dbEscape($message."

{$hesklang['creb']} ".addslashes($_SESSION['name'])."")."','".hesk_dbEscape($message_html."

{$hesklang['creb']} ".addslashes($_SESSION['name'])."")."',NOW(),'".hesk_dbEscape($myattachments)."')"); } else { - hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`staffid`) VALUES ('".intval($replyto)."','".hesk_dbEscape(addslashes($_SESSION['name']))."','".hesk_dbEscape($message)."',NOW(),'".hesk_dbEscape($myattachments)."','".intval($_SESSION['id'])."')"); + hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` (`replyto`,`name`,`message`,`message_html`,`dt`,`attachments`,`staffid`) VALUES ('".intval($replyto)."','".hesk_dbEscape(addslashes($_SESSION['name']))."','".hesk_dbEscape($message)."','".hesk_dbEscape($message_html)."',NOW(),'".hesk_dbEscape($myattachments)."','".intval($_SESSION['id'])."')"); } /* Track ticket status changes for history */ @@ -214,7 +258,7 @@ if ( ! empty($_POST['set_priority']) ) 3 => $hesklang['low'] ); - $revision = sprintf($hesklang['thist8'],hesk_date(),$options[$priority],$_SESSION['name'].' ('.$_SESSION['user'].')'); + $revision = sprintf($hesklang['thist8'],hesk_date(),$options[$priority],addslashes($_SESSION['name']).' ('.$_SESSION['user'].')'); $priority_sql = ",`priority`='$priority', `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') "; } @@ -237,7 +281,7 @@ elseif ($submit_as_customer) if ($ticket['status'] != $new_status) { - $revision = sprintf($hesklang['thist9'],hesk_date(),$hesklang['wait_reply'],$_SESSION['name'].' ('.$_SESSION['user'].')'); + $revision = sprintf($hesklang['thist9'],hesk_date(),$hesklang['wait_reply'],addslashes($_SESSION['name']).' ('.$_SESSION['user'].')'); $sql_status = " , `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') "; } } @@ -274,7 +318,7 @@ else if ($ticket['status'] != $new_status && $new_status != 2) { - $revision = sprintf($hesklang['thist9'],hesk_date(),$data['name'],$_SESSION['name'].' ('.$_SESSION['user'].')'); + $revision = sprintf($hesklang['thist9'],hesk_date(),addslashes($data['name']),addslashes($_SESSION['name']).' ('.$_SESSION['user'].')'); $sql_status .= " , `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') "; } @@ -314,7 +358,7 @@ else if ( ! empty($_POST['assign_self']) && hesk_checkPermission('can_assign_self',0)) { - $revision = sprintf($hesklang['thist2'],hesk_date(),$_SESSION['name'].' ('.$_SESSION['user'].')',$_SESSION['name'].' ('.$_SESSION['user'].')'); + $revision = sprintf($hesklang['thist2'],hesk_date(),addslashes($_SESSION['name']).' ('.$_SESSION['user'].')',addslashes($_SESSION['name']).' ('.$_SESSION['user'].')'); $sql .= " , `owner`=".intval($_SESSION['id']).", `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') "; } @@ -355,6 +399,7 @@ $info = array( 'attachments' => $myattachments, 'dt' => hesk_date($ticket['dt'], true), 'lastchange' => hesk_date($ticket['lastchange'], true), +'due_date' => hesk_format_due_date($ticket['due_date']), 'id' => $ticket['id'], 'language' => $ticket['language'], 'time_worked' => $ticket['time_worked'], diff --git a/hesk/admin/admin_settings_email.php b/hesk/admin/admin_settings_email.php index f821233..5112899 100644 --- a/hesk/admin/admin_settings_email.php +++ b/hesk/admin/admin_settings_email.php @@ -622,6 +622,7 @@ if ($hesk_settings['attachments']['use'] && ! defined('HESK_DEMO') ) +
@@ -726,6 +727,19 @@ if ($hesk_settings['attachments']['use'] && ! defined('HESK_DEMO') ) >
+
+
+ > + + +
+ + + +
+
+
+
@@ -800,13 +814,15 @@ if ($hesk_settings['attachments']['use'] && ! defined('HESK_DEMO') ) var s_imap_user = document.getElementById('i5').value; var s_imap_password = document.getElementById('i6').value; var s_imap_enc = document.getElementById('i4').checked ? 'tls' : (document.getElementById('i9').checked ? 'ssl' : ''); + var s_imap_noval_cert = document.getElementById('i10').checked ? '1' : '0'; var params = "test=imap" + "&s_imap_host_name=" + encodeURIComponent( s_imap_host_name ) + "&s_imap_host_port=" + encodeURIComponent( s_imap_host_port ) + "&s_imap_user=" + encodeURIComponent( s_imap_user ) + "&s_imap_password=" + encodeURIComponent( s_imap_password ) + - "&s_imap_enc=" + encodeURIComponent( s_imap_enc ); + "&s_imap_enc=" + encodeURIComponent( s_imap_enc ) + + "&s_imap_noval_cert=" + encodeURIComponent( s_imap_noval_cert ); xmlHttp=GetXmlHttpObject(); if (xmlHttp==null) diff --git a/hesk/admin/admin_settings_general.php b/hesk/admin/admin_settings_general.php index 794ffb4..636d17c 100644 --- a/hesk/admin/admin_settings_general.php +++ b/hesk/admin/admin_settings_general.php @@ -239,6 +239,27 @@ hesk_handle_messages();
+
+
+ + +
+ + + +
+
+
+
+
+ > + +
+
+ +
+
+

diff --git a/hesk/admin/admin_settings_help_desk.php b/hesk/admin/admin_settings_help_desk.php index 5a7694c..a0fe3f5 100644 --- a/hesk/admin/admin_settings_help_desk.php +++ b/hesk/admin/admin_settings_help_desk.php @@ -159,6 +159,17 @@ if ($hesk_settings['attachments']['use'] && ! defined('HESK_DEMO') ) { } return true; } + + function hesk_generateUrlAccessKey(fID) { + var length = Math.random() * (30 - 20) + 20; + var result = ''; + var characters = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ1234567890-_.'; + var charactersLength = characters.length; + for ( var i = 0; i < length; i++ ) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + $('#' + fID).val(result); + } //-->
@@ -257,6 +268,20 @@ if ($hesk_settings['attachments']['use'] && ! defined('HESK_DEMO') ) { +
+ + + +
@@ -844,6 +869,32 @@ if ($hesk_settings['attachments']['use'] && ! defined('HESK_DEMO') ) {
+ +
+
+ + +
+ + + +
+
+
+
+
+ > + +
+
+ > + +
+
+

@@ -1032,6 +1083,20 @@ if ($hesk_settings['attachments']['use'] && ! defined('HESK_DEMO') ) { +
+ + + +
@@ -1080,6 +1145,29 @@ if ($hesk_settings['attachments']['use'] && ! defined('HESK_DEMO') ) {
+
+ + +
@@ -1100,6 +1188,27 @@ if ($hesk_settings['attachments']['use'] && ! defined('HESK_DEMO') ) {
+
+
+ + +
+
+
+ +
+

diff --git a/hesk/admin/admin_settings_save.php b/hesk/admin/admin_settings_save.php index 08a9a24..bde3610 100644 --- a/hesk/admin/admin_settings_save.php +++ b/hesk/admin/admin_settings_save.php @@ -58,10 +58,10 @@ if ($section === 'GENERAL') { /* --> General settings */ $set['site_title'] = hesk_input( hesk_POST('s_site_title'), $hesklang['err_sname']); $set['site_title'] = str_replace('\\"','"',$set['site_title']); - $set['site_url'] = hesk_input( hesk_POST('s_site_url'), $hesklang['err_surl']); + $set['site_url'] = hesk_validateURL( hesk_POST('s_site_url'), $hesklang['err_surl']); $set['hesk_title'] = hesk_input( hesk_POST('s_hesk_title'), $hesklang['err_htitle']); $set['hesk_title'] = str_replace('\\"','"',$set['hesk_title']); - $set['hesk_url'] = rtrim( hesk_input( hesk_POST('s_hesk_url'), $hesklang['err_hurl']), '/'); + $set['hesk_url'] = rtrim( hesk_validateURL( hesk_POST('s_hesk_url'), $hesklang['err_hurl']), '/'); $set['webmaster_mail'] = hesk_validateEmail( hesk_POST('s_webmaster_mail'), $hesklang['err_wmmail']); $set['noreply_mail'] = hesk_validateEmail( hesk_POST('s_noreply_mail'), $hesklang['err_nomail']); $set['noreply_name'] = hesk_input( hesk_POST('s_noreply_name') ); @@ -75,6 +75,12 @@ if ($section === 'GENERAL') { } else { hesk_error($hesklang['err_site_theme']); } + $set['admin_css'] = empty($_POST['s_admin_css']) ? 0 : 1; + $set['admin_css_url'] = hesk_validateURL( hesk_POST('s_admin_css_url', 'https://www.example.com/hesk-style.css')); + if ($set['admin_css_url'] == '' || $set['admin_css_url'] == 'https://www.example.com/hesk-style.css') { + $set['admin_css'] = 0; + $set['admin_css_url'] = 'https://www.example.com/hesk-style.css'; + } /* --> Language settings */ $set['can_sel_lang'] = empty($_POST['s_can_sel_lang']) ? 0 : 1; @@ -134,6 +140,7 @@ if ($section === 'GENERAL') { $set['print_font_size'] = hesk_checkMinMax( intval( hesk_POST('s_print_font_size') ) , 1, 99, 12); $set['autoclose'] = hesk_checkMinMax( intval( hesk_POST('s_autoclose') ) , 0, 999, 7); $set['max_open'] = hesk_checkMinMax( intval( hesk_POST('s_max_open') ) , 0, 999, 0); + $set['due_soon'] = hesk_checkMinMax( intval( hesk_POST('s_due_soon') ) , 1, 999, 7); $set['new_top'] = empty($_POST['s_new_top']) ? 0 : 1; $set['reply_top'] = empty($_POST['s_reply_top']) ? 0 : 1; $set['hide_replies'] = hesk_checkMinMax( intval( hesk_POST('s_hide_replies') ) , -1, 1, -1); @@ -167,6 +174,11 @@ if ($section === 'GENERAL') { $set['select_cat'] = empty($_POST['s_select_cat']) ? 0 : 1; $set['select_pri'] = empty($_POST['s_select_pri']) ? 0 : 1; $set['cat_show_select'] = hesk_checkMinMax( intval( hesk_POST('s_cat_show_select') ) , 0, 999, 10); + $set['staff_ticket_formatting'] = hesk_checkMinMax( intval( hesk_POST('s_ticket_formatting_staff') ) , 0, 2, 0); + // Temporary until Markdown support + if ($set['staff_ticket_formatting'] == 1) { + $set['staff_ticket_formatting'] = 0; + } /* --> SPAM prevention */ $set['secimg_use'] = empty($_POST['s_secimg_use']) ? 0 : ( hesk_POST('s_secimg_use') == 2 ? 2 : 1); @@ -189,9 +201,14 @@ if ($section === 'GENERAL') { $set['attempt_limit']++; } $set['attempt_banmin'] = hesk_checkMinMax( intval( hesk_POST('s_attempt_banmin') ) , 5, 99999, 60); + $set['flood'] = hesk_checkMinMax( intval( hesk_POST('s_flood') ) , 0, 999, 3); $set['reset_pass'] = empty($_POST['s_reset_pass']) ? 0 : 1; $set['email_view_ticket'] = ($set['require_email'] == 0) ? 0 : (empty($_POST['s_email_view_ticket']) ? 0 : 1); $set['x_frame_opt'] = empty($_POST['s_x_frame_opt']) ? 0 : 1; + $set['samesite'] = hesk_POST('s_samesite', 'Lax'); + if ( ! in_array($set['samesite'], array('Strict', 'Lax', 'None'))) { + $set['samesite'] = 'Lax'; + } $set['force_ssl'] = HESK_SSL && isset($_POST['s_force_ssl']) && $_POST['s_force_ssl'] == 1 ? 1 : 0; // Make sure help desk URL starts with https if forcing SSL @@ -200,6 +217,9 @@ if ($section === 'GENERAL') { $set['hesk_url'] = preg_replace('/^http:/i', 'https:', hesk_getProperty($set, 'hesk_url') ); } + $set['url_key'] = hesk_input( hesk_POST('s_url_key') ); + $set['url_key'] = preg_replace('/[^a-zA-Z0-9_.-]/', '', $set['url_key']); + /* --> Attachments */ $set['attachments']['use'] = empty($_POST['s_attach_use']) ? 0 : 1; if ($set['attachments']['use']) @@ -212,7 +232,7 @@ if ($section === 'GENERAL') { $set['attachments']['max_size'] = hesk_formatUnits($size . ' ' . $unit); $set['attachments']['allowed_types'] = isset($_POST['s_allowed_types']) && ! is_array($_POST['s_allowed_types']) && strlen($_POST['s_allowed_types']) ? explode(',', strtolower( preg_replace('/[^a-zA-Z0-9,]/', '', $_POST['s_allowed_types']) ) ) : array(); - $set['attachments']['allowed_types'] = array_diff($set['attachments']['allowed_types'], array('php', 'php4', 'php3', 'php5', 'phps', 'phtml', 'shtml', 'shtm', 'cgi', 'pl') ); + $set['attachments']['allowed_types'] = array_diff($set['attachments']['allowed_types'], array('php', 'php4', 'php3', 'php5', 'php7', 'php8', 'phps', 'phar', 'phtml', 'shtml', 'shtm', 'cgi', 'pl') ); if (count($set['attachments']['allowed_types'])) { @@ -338,6 +358,7 @@ if ($section === 'GENERAL') { $set['imap_host_port'] = intval( hesk_POST('tmp_imap_host_port', 110) ); $set['imap_enc'] = hesk_POST('tmp_imap_enc'); $set['imap_enc'] = ($set['imap_enc'] == 'ssl' || $set['imap_enc'] == 'tls') ? $set['imap_enc'] : ''; + $set['imap_noval_cert'] = empty($_POST['tmp_imap_noval_cert']) ? 0 : 1; $set['imap_keep'] = empty($_POST['tmp_imap_keep']) ? 0 : 1; $set['imap_user'] = hesk_input( hesk_POST('tmp_imap_user') ); $set['imap_password'] = hesk_input( hesk_POST('tmp_imap_password') ); @@ -472,12 +493,12 @@ if ($section === 'GENERAL') { $set['time_display'] = empty($_POST['s_time_display']) ? 0 : 1; /* --> Other */ - $set['ip_whois'] = hesk_input( hesk_POST('s_ip_whois_url', 'https://whois.domaintools.com/{IP}') ); + $set['ip_whois'] = hesk_validateURL( hesk_POST('s_ip_whois_url', 'https://whois.domaintools.com/{IP}') ); // If no {IP} tag append it to the end if ( strlen($set['ip_whois']) == 0 ) { - $set['ip_whois'] = 'http://whois.domaintools.com/{IP}'; + $set['ip_whois'] = 'https://whois.domaintools.com/{IP}'; } elseif ( strpos($set['ip_whois'], '{IP}') === false ) { @@ -509,6 +530,8 @@ $hesk_settings[\'webmaster_mail\']=\'' . hesk_getProperty($set, 'webmaster_mail' $hesk_settings[\'noreply_mail\']=\'' . hesk_getProperty($set, 'noreply_mail') . '\'; $hesk_settings[\'noreply_name\']=\'' . hesk_getProperty($set, 'noreply_name') . '\'; $hesk_settings[\'site_theme\']=\'' . hesk_getProperty($set, 'site_theme') . '\'; +$hesk_settings[\'admin_css\']=' . hesk_getProperty($set, 'admin_css') . '; +$hesk_settings[\'admin_css_url\']=\'' . hesk_getProperty($set, 'admin_css_url') . '\'; // --> Language settings $hesk_settings[\'can_sel_lang\']=' . hesk_getProperty($set, 'can_sel_lang') . '; @@ -535,6 +558,7 @@ $hesk_settings[\'max_listings\']=' . hesk_getProperty($set, 'max_listings') . '; $hesk_settings[\'print_font_size\']=' . hesk_getProperty($set, 'print_font_size') . '; $hesk_settings[\'autoclose\']=' . hesk_getProperty($set, 'autoclose') . '; $hesk_settings[\'max_open\']=' . hesk_getProperty($set, 'max_open') . '; +$hesk_settings[\'due_soon\']=' . hesk_getProperty($set, 'due_soon') . '; $hesk_settings[\'new_top\']=' . hesk_getProperty($set, 'new_top') . '; $hesk_settings[\'reply_top\']=' . hesk_getProperty($set, 'reply_top') . '; $hesk_settings[\'hide_replies\']=' . hesk_getProperty($set, 'hide_replies') . '; @@ -560,6 +584,7 @@ $hesk_settings[\'short_link\']=' . hesk_getProperty($set, 'short_link') . '; $hesk_settings[\'select_cat\']=' . hesk_getProperty($set, 'select_cat') . '; $hesk_settings[\'select_pri\']=' . hesk_getProperty($set, 'select_pri') . '; $hesk_settings[\'cat_show_select\']=' . hesk_getProperty($set, 'cat_show_select') . '; +$hesk_settings[\'staff_ticket_formatting\']=' . hesk_getProperty($set, 'staff_ticket_formatting') . '; // --> SPAM Prevention $hesk_settings[\'secimg_use\']=' . hesk_getProperty($set, 'secimg_use') . '; @@ -574,10 +599,13 @@ $hesk_settings[\'question_ans\']=\'' . hesk_getProperty($set, 'question_ans') . // --> Security $hesk_settings[\'attempt_limit\']=' . hesk_getProperty($set, 'attempt_limit') . '; $hesk_settings[\'attempt_banmin\']=' . hesk_getProperty($set, 'attempt_banmin') . '; +$hesk_settings[\'flood\']=' . hesk_getProperty($set, 'flood') . '; $hesk_settings[\'reset_pass\']=' . hesk_getProperty($set, 'reset_pass') . '; $hesk_settings[\'email_view_ticket\']=' . hesk_getProperty($set, 'email_view_ticket') . '; $hesk_settings[\'x_frame_opt\']=' . hesk_getProperty($set, 'x_frame_opt') . '; +$hesk_settings[\'samesite\']=\'' . hesk_getProperty($set, 'samesite') . '\'; $hesk_settings[\'force_ssl\']=' . hesk_getProperty($set, 'force_ssl') . '; +$hesk_settings[\'url_key\']=\'' . hesk_getProperty($set, 'url_key') . '\'; // --> Attachments $hesk_settings[\'attachments\']=array ( @@ -640,6 +668,7 @@ $hesk_settings[\'imap_job_wait\']=' . hesk_getProperty($set, 'imap_job_wait') . $hesk_settings[\'imap_host_name\']=\'' . hesk_getProperty($set, 'imap_host_name') . '\'; $hesk_settings[\'imap_host_port\']=' . hesk_getProperty($set, 'imap_host_port') . '; $hesk_settings[\'imap_enc\']=\'' . hesk_getProperty($set, 'imap_enc') . '\'; +$hesk_settings[\'imap_noval_cert\']=' . hesk_getProperty($set, 'imap_noval_cert') . '; $hesk_settings[\'imap_keep\']=' . hesk_getProperty($set, 'imap_keep') . '; $hesk_settings[\'imap_user\']=\'' . hesk_getProperty($set, 'imap_user') . '\'; $hesk_settings[\'imap_password\']=\'' . hesk_getProperty($set, 'imap_password') . '\'; diff --git a/hesk/admin/admin_submit_ticket.php b/hesk/admin/admin_submit_ticket.php index 18a1457..75155ee 100644 --- a/hesk/admin/admin_submit_ticket.php +++ b/hesk/admin/admin_submit_ticket.php @@ -39,6 +39,32 @@ if ( empty($_POST) && ! empty($_SERVER['CONTENT_LENGTH']) ) hesk_error($hesklang['maxpost']); } +// Changing category? Remember data and redirect to category select page +if (hesk_POST('change_category') == 1) +{ + $_SESSION['as_name'] = hesk_POST('name'); + $_SESSION['as_email'] = hesk_POST('email'); + $_SESSION['as_priority'] = hesk_POST('priority'); + $_SESSION['as_subject'] = hesk_POST('subject'); + $_SESSION['as_message'] = hesk_POST('message'); + $_SESSION['as_due_date'] = hesk_POST('due_date'); + $_SESSION['as_owner'] = hesk_POST('owner'); + $_SESSION['as_notify'] = hesk_POST('notify'); + $_SESSION['as_show'] = hesk_POST('show'); + $_SESSION['as_language'] = hesk_POST('as_language'); + + foreach ($hesk_settings['custom_fields'] as $k=>$v) + { + if ($v['use'] && ! in_array($v['type'], array('date', 'email'))) + { + $_SESSION["as_$k"] = ($v['type'] == 'checkbox') ? hesk_POST_array($k) : hesk_POST($k); + } + } + + header('Location: new_ticket.php'); + exit(); +} + $hesk_error_buffer = array(); $tmpvar['name'] = hesk_input( hesk_POST('name') ) or $hesk_error_buffer['name']=$hesklang['enter_your_name']; @@ -214,11 +240,16 @@ foreach ($hesk_settings['custom_fields'] as $k=>$v) } } +$tmpvar['due_date'] = hesk_input(hesk_POST('due_date')); +if ($tmpvar['due_date'] != '' && !preg_match("/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/", $tmpvar['due_date'])) { + $hesk_error_buffer['due_date'] = $hesklang['invalid_due_date']; +} + // Generate tracking ID $tmpvar['trackid'] = hesk_createID(); // Log who submitted ticket -$tmpvar['history'] = sprintf($hesklang['thist7'], hesk_date(), $_SESSION['name'].' ('.$_SESSION['user'].')'); +$tmpvar['history'] = sprintf($hesklang['thist7'], hesk_date(), addslashes($_SESSION['name']).' ('.$_SESSION['user'].')'); $tmpvar['openedby'] = $_SESSION['id']; // Owner @@ -239,7 +270,7 @@ if (hesk_checkPermission('can_assign_others',0)) if ($autoassign_owner) { $tmpvar['owner'] = intval($autoassign_owner['id']); - $tmpvar['history'] .= sprintf($hesklang['thist10'],hesk_date(),$autoassign_owner['name'].' ('.$autoassign_owner['user'].')'); + $tmpvar['history'] .= sprintf($hesklang['thist10'],hesk_date(),addslashes($autoassign_owner['name']).' ('.$autoassign_owner['user'].')'); } else { @@ -254,7 +285,7 @@ if (hesk_checkPermission('can_assign_others',0)) else { // Has the new owner access to the selected category? - $res = hesk_dbQuery("SELECT `name`,`isadmin`,`categories` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`='{$tmpvar['owner']}' LIMIT 1"); + $res = hesk_dbQuery("SELECT `name`,`user`,`isadmin`,`categories` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`='{$tmpvar['owner']}' LIMIT 1"); if (hesk_dbNumRows($res) == 1) { $row = hesk_dbFetchAssoc($res); @@ -267,6 +298,7 @@ if (hesk_checkPermission('can_assign_others',0)) $hesk_error_buffer['owner']=$hesklang['onasc']; } } + $tmpvar['history'] .= sprintf($hesklang['thist2'],hesk_date(),addslashes($row['name']).' ('.$row['user'].')',addslashes($_SESSION['name']).' ('.$_SESSION['user'].')'); } else { @@ -286,6 +318,16 @@ $notify = ! empty($_POST['notify']) ? 1 : 0; // Show ticket after submission? $show = ! empty($_POST['show']) ? 1 : 0; +// Is the ticket language different than current language? +if ($hesk_settings['can_sel_lang']) +{ + $new_lang = hesk_POST('as_language'); + if (isset($hesk_settings['languages'][$new_lang])) + { + $hesklang['LANGUAGE'] = $new_lang; + } +} + // Attachments if ($hesk_settings['attachments']['use']) { @@ -310,14 +352,16 @@ if (count($hesk_error_buffer)!=0) { $_SESSION['iserror'] = array_keys($hesk_error_buffer); - $_SESSION['as_name'] = hesk_POST('name'); - $_SESSION['as_email'] = hesk_POST('email'); + $_SESSION['as_name'] = hesk_POST('name'); + $_SESSION['as_email'] = hesk_POST('email'); $_SESSION['as_priority'] = $tmpvar['priority']; - $_SESSION['as_subject'] = hesk_POST('subject'); - $_SESSION['as_message'] = hesk_POST('message'); + $_SESSION['as_subject'] = hesk_POST('subject'); + $_SESSION['as_message'] = hesk_POST('message'); + $_SESSION['as_due_date'] = hesk_POST('due_date'); $_SESSION['as_owner'] = $tmpvar['owner']; $_SESSION['as_notify'] = $notify; $_SESSION['as_show'] = $show; + $_SESSION['as_language'] = hesk_POST('as_language'); foreach ($hesk_settings['custom_fields'] as $k=>$v) { @@ -353,8 +397,29 @@ if ($hesk_settings['attachments']['use'] && !empty($attachments)) } } -$tmpvar['message']=hesk_makeURL($tmpvar['message']); -$tmpvar['message']=nl2br($tmpvar['message']); +$tmpvar['message_html'] = $tmpvar['message']; + +if ($hesk_settings['staff_ticket_formatting'] == 2) { + // Decode the message we encoded earlier + $tmpvar['message_html'] = hesk_html_entity_decode($tmpvar['message_html']); + + // Clean the HTML code and set the plaintext version + require(HESK_PATH . 'inc/htmlpurifier/HeskHTMLPurifier.php'); + require(HESK_PATH . 'inc/html2text/html2text.php'); + $purifier = new HeskHTMLPurifier($hesk_settings['cache_dir']); + $tmpvar['message_html'] = $purifier->heskPurify($tmpvar['message_html']); + + $tmpvar['message'] = convert_html_to_text($tmpvar['message_html']); + $tmpvar['message'] = fix_newlines($tmpvar['message']); + + // Re-encode the message + $tmpvar['message'] = hesk_htmlspecialchars($tmpvar['message']); +} else { + // `message` already contains a HTML friendly version. May as well just re-use it + $tmpvar['message'] = hesk_makeURL($tmpvar['message']); + $tmpvar['message'] = nl2br($tmpvar['message']); + $tmpvar['message_html'] = $tmpvar['message']; +} // Track who assigned the ticket if ($tmpvar['owner'] > 0) @@ -403,6 +468,8 @@ hesk_cleanSessionVars('as_message'); hesk_cleanSessionVars('as_owner'); hesk_cleanSessionVars('as_notify'); hesk_cleanSessionVars('as_show'); +hesk_cleanSessionVars('as_due_date'); +hesk_cleanSessionVars('as_language'); foreach ($hesk_settings['custom_fields'] as $k=>$v) { hesk_cleanSessionVars("as_$k"); @@ -422,5 +489,6 @@ if ($show) } else { - hesk_process_messages($hesklang['new_ticket_submitted'].'. ' . $hesklang['view_ticket'] . '', 'new_ticket.php', 'SUCCESS'); + $link = hesk_checkPermission('can_view_tickets',0) ? '' . $hesklang['view_ticket'] . '' : ''; + hesk_process_messages($hesklang['new_ticket_submitted'].'. ' . $link, 'new_ticket.php', 'SUCCESS'); } diff --git a/hesk/admin/admin_ticket.php b/hesk/admin/admin_ticket.php index 2f37d35..4cd9457 100644 --- a/hesk/admin/admin_ticket.php +++ b/hesk/admin/admin_ticket.php @@ -13,6 +13,7 @@ define('IN_SCRIPT',1); define('HESK_PATH','../'); +define('CALENDAR',1); /* Get all the required files and functions */ require(HESK_PATH . 'hesk_settings.inc.php'); @@ -61,6 +62,10 @@ define('BACK2TOP',1); if ($hesk_settings['time_display']) { define('TIMEAGO',1); } +if ($hesk_settings['staff_ticket_formatting'] == 2) { + define('WYSIWYG',1); + define('STYLE_CODE',1); +} /* Get ticket info */ $res = hesk_dbQuery("SELECT `t1`.* , `t2`.name AS `repliername` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` AS `t1` LEFT JOIN `".hesk_dbEscape($hesk_settings['db_pfix'])."users` AS `t2` ON `t1`.`replierid` = `t2`.`id` WHERE `trackid`='".hesk_dbEscape($trackingID)."' LIMIT 1"); @@ -91,6 +96,16 @@ else $ticket = hesk_dbFetchAssoc($res); } +// Has this ticket been anonymized? +$ticket['anonymized'] = ( + $ticket['name'] == $hesklang['anon_name'] && + $ticket['email'] == $hesklang['anon_email'] && + $ticket['subject'] == $hesklang['anon_subject'] && + $ticket['message'] == $hesklang['anon_message'] && + $ticket['message_html'] == $hesklang['anon_message'] && + $ticket['ip'] == $hesklang['anon_IP'] + ) ? true : false; + /* Permission to view this ticket? */ if ($ticket['owner'] && $ticket['owner'] != $_SESSION['id'] && ! hesk_checkPermission('can_view_ass_others',0)) { @@ -387,7 +402,7 @@ if (isset($_POST['notemsg']) && hesk_token_check('POST')) /* Notify assigned staff that a note has been added if needed */ if ($ticket['owner'] && $ticket['owner'] != $_SESSION['id']) { - $res = hesk_dbQuery("SELECT `email`, `notify_note` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`='".intval($ticket['owner'])."' LIMIT 1"); + $res = hesk_dbQuery("SELECT `email` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`='".intval($ticket['owner'])."' AND `notify_note`='1' LIMIT 1"); if (hesk_dbNumRows($res) == 1) { @@ -407,6 +422,7 @@ if (isset($_POST['notemsg']) && hesk_token_check('POST')) 'dt' => hesk_date($ticket['dt'], true), 'lastchange' => hesk_date($ticket['lastchange'], true), 'attachments' => $myattachments, + 'due_date' => hesk_format_due_date($ticket['due_date']), 'id' => $ticket['id'], 'time_worked' => $ticket['time_worked'], 'last_reply_by' => $ticket['repliername'], @@ -449,13 +465,46 @@ if ($hesk_settings['time_worked'] && ($can_reply || $can_edit) && isset($_POST[' $time_worked = hesk_getTime($h . ':' . $m . ':' . $s); /* Update database */ - $revision = sprintf($hesklang['thist14'],hesk_date(),$time_worked,$_SESSION['name'].' ('.$_SESSION['user'].')'); + $revision = sprintf($hesklang['thist14'],hesk_date(),$time_worked,addslashes($_SESSION['name']).' ('.$_SESSION['user'].')'); hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `time_worked`='" . hesk_dbEscape($time_worked) . "', `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') WHERE `trackid`='" . hesk_dbEscape($trackingID) . "'"); /* Show ticket */ hesk_process_messages($hesklang['twu'],'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999),'SUCCESS'); } +/* Update due date */ +if (($can_reply || $can_edit) && isset($_POST['action']) && $_POST['action'] == 'due_date' && hesk_token_check('POST')) { + $new_due_date = hesk_POST('new-due-date'); + + // MM/DD/YYYY + if ($new_due_date != '' && !preg_match("/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/", $new_due_date)) { + hesk_process_messages($hesklang['invalid_due_date'], 'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999)); + } + + $sql_overdue_email = ''; + + if ($new_due_date == '') { + $formatted_date = false; + $revision = sprintf($hesklang['thist20'], hesk_date(), addslashes($_SESSION['name']).' ('.$_SESSION['user'].')'); + } else { + $date = new DateTime($new_due_date . 'T00:00:00'); + $formatted_date = $date->format('Y-m-d'); + $revision = sprintf($hesklang['thist19'], hesk_date(), $formatted_date, addslashes($_SESSION['name']).' ('.$_SESSION['user'].')'); + + // If this is a future date, we'll reset the + $current_date = new DateTime(); + if ($date > $current_date) + { + $sql_overdue_email = '`overdue_email_sent`=0,'; + } + } + + hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `due_date` = " . ($formatted_date === false ? 'NULL' : "'".hesk_dbEscape($formatted_date)."'") . ", {$sql_overdue_email} `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') WHERE `trackid`='" . hesk_dbEscape($trackingID) . "' AND (`due_date` IS " . ($formatted_date === false ? 'NOT NULL' : "NULL OR `due_date` != '".hesk_dbEscape($formatted_date)."'") . ")"); + + /* Show ticket */ + hesk_process_messages($hesklang['due_date_updated'],'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999),'SUCCESS'); +} + /* Delete attachment action */ if (isset($_GET['delatt']) && hesk_token_check()) { @@ -499,7 +548,7 @@ if (isset($_GET['delatt']) && hesk_token_check()) hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` WHERE `att_id`='".intval($att_id)."'"); /* Update ticket or reply in the database */ - $revision = sprintf($hesklang['thist12'],hesk_date(),$att['real_name'],$_SESSION['name'].' ('.$_SESSION['user'].')'); + $revision = sprintf($hesklang['thist12'],hesk_date(),$att['real_name'],addslashes($_SESSION['name']).' ('.$_SESSION['user'].')'); if ($reply) { hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` SET `attachments`=REPLACE(`attachments`,'".hesk_dbEscape($att_id.'#'.$att['real_name']).",','') WHERE `id`='".intval($reply)."'"); @@ -933,11 +982,11 @@ $options = array( } } - if ($ticket['message'] != '') + if ($ticket['message_html'] != '') { ?> -
-

+
+

+
+
+ +
+ + + + +
+ +
+ +
+ +
+ @@ -1577,16 +1686,18 @@ function hesk_getAdminButtons($isReply=0,$white=1) } // Resend email notification button - $buttons['more'][] = ' - - - - - '.$hesklang['btn_resend'].' - '; + if (!$ticket['anonymized']) { + $buttons['more'][] = ' + + + + + '.$hesklang['btn_resend'].' + '; + } // Import to knowledgebase button - if (!$isReply && $hesk_settings['kb_enable'] && hesk_checkPermission('can_man_kb',0)) + if (!$isReply && $hesk_settings['kb_enable'] && hesk_checkPermission('can_man_kb',0) && !$ticket['anonymized']) { $buttons['more'][] = ' @@ -1598,7 +1709,7 @@ function hesk_getAdminButtons($isReply=0,$white=1) } // Export ticket - if (!$isReply && $can_export) + if (!$isReply && $can_export && !$ticket['anonymized']) { $buttons['more'][] = ' @@ -1826,8 +1937,8 @@ function hesk_printTicketReplies() { -
-

+
+

-
-

+
+

-
-

+
+

- ",$(e).append(o)},a=document.querySelectorAll("[ripple]"),d=0,s=a.length;d label",function(e){$(e.currentTarget).closest(".dropdown").hasClass("active")?$(e.currentTarget).closest(".dropdown").removeClass("active").find(".dropdown-list").slideUp(150):($(".dropdown").removeClass("active"),$(".dropdown-list").slideUp(150),$(e.currentTarget).closest(".dropdown").addClass("active").find(".dropdown-list").slideDown(150))}),$("body").on("click",".dropdown-list > li",function(e){$(e.currentTarget).hasClass("noclose")||$(e.currentTarget).closest(".dropdown").removeClass("active").find(".dropdown-list").slideUp(150)}),$("body").on("click",".dropdown-select .label",function(e){$(e.currentTarget).closest(".dropdown-select").hasClass("active")?$(e.currentTarget).closest(".dropdown-select").removeClass("active").find(".dropdown-list").slideUp(150):($(".dropdown-select").removeClass("active"),$(".dropdown-list").slideUp(150),$(e.currentTarget).closest(".dropdown-select").addClass("active").find(".dropdown-list").slideDown(150))}),$("body").on("click",".dropdown-list > li",function(e){$(e.currentTarget).hasClass("noclose")||$(e.currentTarget).closest(".dropdown").removeClass("active").find(".dropdown-list").slideUp(150)}),$("body").on("click",".dropdown-select .dropdown-list li",function(e){var t,s;s=$(e.currentTarget).attr("data-option"),t=$(e.currentTarget).closest(".dropdown-select").hasClass("submit-us")?(t=s.length?"Submit as "+$(e.currentTarget).text():$(e.currentTarget).text()).toLowerCase().charAt(0).toUpperCase()+t.toLowerCase().substr(1):$(e.currentTarget).text(),$(e.currentTarget).closest(".dropdown-list").find("li").removeClass("selected"),$(e.currentTarget).addClass("selected"),$(e.currentTarget).closest(".dropdown-select").attr("data-value",s).find(".label span").text(t),$(e.currentTarget).closest(".dropdown-select").removeClass("active"),$(e.currentTarget).closest(".dropdown-list").slideUp(150),$(e.currentTarget).closest(".dropdown-select").find('select option[value="'+s+'"]').prop("selected",!0),$(e.currentTarget).closest(".dropdown-select").find("select").trigger("change")}),$(".ticket__replies_link").click(function(e){$(e.currentTarget).hasClass("visible")?($(e.currentTarget).removeClass("visible"),$(".ticket__replies_list").slideUp(150)):($(".ticket__replies_list").slideDown(150),$(e.currentTarget).addClass("visible"))});var b=[];$('.block--attach input[type="file"]').change(function(e){for(d=0;d
';$(".block--attach-list").append(o),$(".block--attach-list div").each(function(e,t){$(t).attr("data-i",e)})}}),$("body").on("click",".block--attach-list div i",function(e){var t=Number($(e.target).closest("div").attr("data-i"));b.splice(t,1),$(e.currentTarget).closest("div").slideUp(150,function(){$(e.currentTarget).closest("div").remove(),$(".block--attach-list div").each(function(e,t){$(t).attr("data-i",e)})}),console.log(b)}),$(".accordion-title").click(function(e){$(e.currentTarget).closest(".accordion").hasClass("visible")?($(e.currentTarget).closest(".accordion").find(".accordion-body").slideUp(150),$(e.currentTarget).closest(".accordion").removeClass("visible")):($(e.currentTarget).closest(".accordion").find(".accordion-body").slideDown(150),$(e.currentTarget).closest(".accordion").addClass("visible"))}),$.isFunction($.fn.datepicker)&&$(".datepicker").datepicker({language:"en",position:"right bottom",autoClose:!0,onSelect:function(e,t,s){e.length&&s.$el.parent().parent().find(".calendar--value").fadeIn(150).find("span").text(e)},onHide:function(e,t){$(".ticket-create .param.calendar button").removeClass("active")}}),$(".ticket-create .param.calendar button").click(function(e){$(this).addClass("active"),$(this).parent().find(".datepicker").data("datepicker").show()}),$(".ticket-create .param.calendar .close").click(function(e){$(this).parent().parent().find(".calendar--button").find(".datepicker").data("datepicker").clear(),$(".ticket-create .param.calendar .calendar--value").fadeOut(150,function(){$(this).find("span").text("")})}),$('[data-action="create-ticket"]').click(function(e){$("body").addClass("noscroll"),$(".right-bar.ticket-create").fadeIn(150)}),$("body").on("mouseenter",".tooltype",function(e){$(this).find(".tooltype__content").fadeIn(150)}),$("body").on("mouseleave",".tooltype",function(e){$(this).find(".tooltype__content").fadeOut(150)}),$(".tabbed__head_tabs li").click(function(e){var t=$(this).attr("data-link");$(".tabbed__head_tabs li").removeClass("current"),$(this).addClass("current"),$(".tabbed__tabs .tabbed__tabs_tab").removeClass("is-visible"),$(".tabbed__tabs [data-tab="+t+"]").addClass("is-visible")}),$(".btn-toggler").click(function(e){$(this).closest(".params--block").find(".accordion-body").slideToggle(),$(this).toggleClass("is-opened")}),$(".selectize-input input").prop("disabled","disabled")}),window.onload=function(){$("#loader").fadeOut(150)}; \ No newline at end of file +function escapeHtml(e){var t=document.createTextNode(e),e=document.createElement("p");return e.appendChild(t),e.innerHTML}$(document).ready(function(){var e,t,s,o,i,a,r,c,l,d,p,u,f,g,v;for(svg4everybody(),t=function(s,n){var o=void 0;return function(){var e=this,t=arguments;return clearTimeout(o),o=setTimeout(function(){return s.apply(e,t)},n)}},r=function(e){var t=this,s=document.createElement("span"),n=t.offsetWidth,o=(t.getBoundingClientRect(),e.offsetX-n/2),n="top:"+(e.offsetY-n/2)+"px; left: "+o+"px; height: "+n+"px; width: "+n+"px;";return t.rippleContainer.appendChild(s),s.setAttribute("style",n)},e=function(){for(;this.rippleContainer.firstChild;)this.rippleContainer.removeChild(this.rippleContainer.firstChild)},c=function(e){e=e||150,$(".profile__item--notification").removeClass("active").find(".notification-list").slideUp(e),$(".profile__user").removeClass("active").find(".profile__menu").slideUp(e),$(".dropdown, .dropdown-select").removeClass("active"),$(".dropdown-list").slideUp(e,function(){$(this).find(".assign--buttons").show(),$(this).find(".assign--list").hide()}),$(".form__search_type").slideUp(150),$(".form__search_results").slideUp(150)},dropdownSelectRender=function(e){var s,t=$(e).find("select"),n=[];t.find("option").each(function(e,t){n.push({val:$(t).val(),text:$(t).text(),selected:$(t).is(":selected")}),$(t).is(":selected")&&(s=$(t).text())});var o,i='
'+escapeHtml(s)+'
",$(e).append(i)},a=document.querySelectorAll("[ripple]"),d=0,s=a.length;d label",function(e){$(e.currentTarget).closest(".dropdown").hasClass("active")?$(e.currentTarget).closest(".dropdown").removeClass("active").find(".dropdown-list").slideUp(150):($(".dropdown").removeClass("active"),$(".dropdown-list").slideUp(150),$(e.currentTarget).closest(".dropdown").addClass("active").find(".dropdown-list").slideDown(150))}),$("body").on("click",".dropdown-list > li",function(e){$(e.currentTarget).hasClass("noclose")||$(e.currentTarget).closest(".dropdown").removeClass("active").find(".dropdown-list").slideUp(150)}),$("body").on("click",".dropdown-select .label",function(e){$(e.currentTarget).closest(".dropdown-select").hasClass("active")?$(e.currentTarget).closest(".dropdown-select").removeClass("active").find(".dropdown-list").slideUp(150):($(".dropdown-select").removeClass("active"),$(".dropdown-list").slideUp(150),$(e.currentTarget).closest(".dropdown-select").addClass("active").find(".dropdown-list").slideDown(150))}),$("body").on("click",".dropdown-list > li",function(e){$(e.currentTarget).hasClass("noclose")||$(e.currentTarget).closest(".dropdown").removeClass("active").find(".dropdown-list").slideUp(150)}),$("body").on("click",".dropdown-select .dropdown-list li",function(e){var t=$(e.currentTarget).attr("data-option"),s=$(e.currentTarget).closest(".dropdown-select").hasClass("submit-us")?(s=t.length?"Submit as "+$(e.currentTarget).text():$(e.currentTarget).text()).toLowerCase().charAt(0).toUpperCase()+s.toLowerCase().substr(1):$(e.currentTarget).text();$(e.currentTarget).closest(".dropdown-list").find("li").removeClass("selected"),$(e.currentTarget).addClass("selected"),$(e.currentTarget).closest(".dropdown-select").attr("data-value",t).find(".label span").text(s),$(e.currentTarget).closest(".dropdown-select").removeClass("active"),$(e.currentTarget).closest(".dropdown-list").slideUp(150),$(e.currentTarget).closest(".dropdown-select").find('select option[value="'+t+'"]').prop("selected",!0),$(e.currentTarget).closest(".dropdown-select").find("select").trigger("change")}),$(".ticket__replies_link").click(function(e){$(e.currentTarget).hasClass("visible")?($(e.currentTarget).removeClass("visible"),$(".ticket__replies_list").slideUp(150)):($(".ticket__replies_list").slideDown(150),$(e.currentTarget).addClass("visible"))});var b=[];$('.block--attach input[type="file"]').change(function(e){for(d=0;d"+s+t+'';$(".block--attach-list").append(t),$(".block--attach-list div").each(function(e,t){$(t).attr("data-i",e)})}}),$("body").on("click",".block--attach-list div i",function(e){var t=Number($(e.target).closest("div").attr("data-i"));b.splice(t,1),$(e.currentTarget).closest("div").slideUp(150,function(){$(e.currentTarget).closest("div").remove(),$(".block--attach-list div").each(function(e,t){$(t).attr("data-i",e)})}),console.log(b)}),$(".accordion-title").click(function(e){$(e.currentTarget).closest(".accordion").hasClass("visible")?($(e.currentTarget).closest(".accordion").find(".accordion-body").slideUp(150),$(e.currentTarget).closest(".accordion").removeClass("visible")):($(e.currentTarget).closest(".accordion").find(".accordion-body").slideDown(150),$(e.currentTarget).closest(".accordion").addClass("visible"))}),$.isFunction($.fn.datepicker)&&$(".datepicker").datepicker({language:"en",position:"right bottom",autoClose:!0,onSelect:function(e,t,s){e.length&&s.$el.parent().parent().find(".calendar--value").fadeIn(150).find("span").text(e)},onHide:function(e,t){$(".ticket-create .param.calendar button").removeClass("active")}}),$(".ticket-create .param.calendar button").click(function(e){$(this).addClass("active"),$(this).parent().find(".datepicker").data("datepicker").show()}),$(".ticket-create .param.calendar .close").click(function(e){$(this).parent().parent().find(".calendar--button").find(".datepicker").data("datepicker").clear(),$(".ticket-create .param.calendar .calendar--value").fadeOut(150,function(){$(this).find("span").text("")})}),$('[data-action="create-ticket"]').click(function(e){$("body").addClass("noscroll"),$(".right-bar.ticket-create").fadeIn(150)}),$("body").on("mouseenter",".tooltype",function(e){$(this).find(".tooltype__content").fadeIn(150)}),$("body").on("mouseleave",".tooltype",function(e){$(this).find(".tooltype__content").fadeOut(150)}),$(".tabbed__head_tabs li").click(function(e){var t=$(this).attr("data-link");$(".tabbed__head_tabs li").removeClass("current"),$(this).addClass("current"),$(".tabbed__tabs .tabbed__tabs_tab").removeClass("is-visible"),$(".tabbed__tabs [data-tab="+t+"]").addClass("is-visible")}),$(".btn-toggler").click(function(e){$(this).closest(".params--block").find(".accordion-body").slideToggle(),$(this).toggleClass("is-opened")}),$(".selectize-input input").prop("readonly","true")}),window.onload=function(){$("#loader").fadeOut(150)}; \ No newline at end of file diff --git a/hesk/theme/hesk3/customer/js/jquery.modal.min.js b/hesk/theme/hesk3/customer/js/jquery.modal.min.js new file mode 100644 index 0000000..34eecf6 --- /dev/null +++ b/hesk/theme/hesk3/customer/js/jquery.modal.min.js @@ -0,0 +1,5 @@ +/* + A simple jQuery modal (http://github.com/kylefox/jquery-modal) + Version 0.9.2 +*/ +!function(o){"object"==typeof module&&"object"==typeof module.exports?o(require("jquery"),window,document):o(jQuery,window,document)}(function(o,t,i,e){var s=[],l=function(){return s.length?s[s.length-1]:null},n=function(){var o,t=!1;for(o=s.length-1;o>=0;o--)s[o].$blocker&&(s[o].$blocker.toggleClass("current",!t).toggleClass("behind",t),t=!0)};o.modal=function(t,i){var e,n;if(this.$body=o("body"),this.options=o.extend({},o.modal.defaults,i),this.options.doFade=!isNaN(parseInt(this.options.fadeDuration,10)),this.$blocker=null,this.options.closeExisting)for(;o.modal.isActive();)o.modal.close();if(s.push(this),t.is("a"))if(n=t.attr("href"),this.anchor=t,/^#/.test(n)){if(this.$elm=o(n),1!==this.$elm.length)return null;this.$body.append(this.$elm),this.open()}else this.$elm=o("
"),this.$body.append(this.$elm),e=function(o,t){t.elm.remove()},this.showSpinner(),t.trigger(o.modal.AJAX_SEND),o.get(n).done(function(i){if(o.modal.isActive()){t.trigger(o.modal.AJAX_SUCCESS);var s=l();s.$elm.empty().append(i).on(o.modal.CLOSE,e),s.hideSpinner(),s.open(),t.trigger(o.modal.AJAX_COMPLETE)}}).fail(function(){t.trigger(o.modal.AJAX_FAIL);var i=l();i.hideSpinner(),s.pop(),t.trigger(o.modal.AJAX_COMPLETE)});else this.$elm=t,this.anchor=t,this.$body.append(this.$elm),this.open()},o.modal.prototype={constructor:o.modal,open:function(){var t=this;this.block(),this.anchor.blur(),this.options.doFade?setTimeout(function(){t.show()},this.options.fadeDuration*this.options.fadeDelay):this.show(),o(i).off("keydown.modal").on("keydown.modal",function(o){var t=l();27===o.which&&t.options.escapeClose&&t.close()}),this.options.clickClose&&this.$blocker.click(function(t){t.target===this&&o.modal.close()})},close:function(){s.pop(),this.unblock(),this.hide(),o.modal.isActive()||o(i).off("keydown.modal")},block:function(){this.$elm.trigger(o.modal.BEFORE_BLOCK,[this._ctx()]),this.$body.css("overflow","hidden"),this.$blocker=o('
').appendTo(this.$body),n(),this.options.doFade&&this.$blocker.css("opacity",0).animate({opacity:1},this.options.fadeDuration),this.$elm.trigger(o.modal.BLOCK,[this._ctx()])},unblock:function(t){!t&&this.options.doFade?this.$blocker.fadeOut(this.options.fadeDuration,this.unblock.bind(this,!0)):(this.$blocker.children().appendTo(this.$body),this.$blocker.remove(),this.$blocker=null,n(),o.modal.isActive()||this.$body.css("overflow",""))},show:function(){this.$elm.trigger(o.modal.BEFORE_OPEN,[this._ctx()]),this.options.showClose&&(this.closeButton=o(''+this.options.closeText+""),this.$elm.append(this.closeButton)),this.$elm.addClass(this.options.modalClass).appendTo(this.$blocker),this.options.doFade?this.$elm.css({opacity:0,display:"inline-block"}).animate({opacity:1},this.options.fadeDuration):this.$elm.css("display","inline-block"),this.$elm.trigger(o.modal.OPEN,[this._ctx()])},hide:function(){this.$elm.trigger(o.modal.BEFORE_CLOSE,[this._ctx()]),this.closeButton&&this.closeButton.remove();var t=this;this.options.doFade?this.$elm.fadeOut(this.options.fadeDuration,function(){t.$elm.trigger(o.modal.AFTER_CLOSE,[t._ctx()])}):this.$elm.hide(0,function(){t.$elm.trigger(o.modal.AFTER_CLOSE,[t._ctx()])}),this.$elm.trigger(o.modal.CLOSE,[this._ctx()])},showSpinner:function(){this.options.showSpinner&&(this.spinner=this.spinner||o('
').append(this.options.spinnerHtml),this.$body.append(this.spinner),this.spinner.show())},hideSpinner:function(){this.spinner&&this.spinner.remove()},_ctx:function(){return{elm:this.$elm,$elm:this.$elm,$blocker:this.$blocker,options:this.options,$anchor:this.anchor}}},o.modal.close=function(t){if(o.modal.isActive()){t&&t.preventDefault();var i=l();return i.close(),i.$elm}},o.modal.isActive=function(){return s.length>0},o.modal.getCurrent=l,o.modal.defaults={closeExisting:!0,escapeClose:!0,clickClose:!0,closeText:"Close",closeClass:"",modalClass:"modal",blockerClass:"jquery-modal",spinnerHtml:'
',showSpinner:!0,showClose:!0,fadeDuration:null,fadeDelay:1},o.modal.BEFORE_BLOCK="modal:before-block",o.modal.BLOCK="modal:block",o.modal.BEFORE_OPEN="modal:before-open",o.modal.OPEN="modal:open",o.modal.BEFORE_CLOSE="modal:before-close",o.modal.CLOSE="modal:close",o.modal.AFTER_CLOSE="modal:after-close",o.modal.AJAX_SEND="modal:ajax:send",o.modal.AJAX_SUCCESS="modal:ajax:success",o.modal.AJAX_FAIL="modal:ajax:fail",o.modal.AJAX_COMPLETE="modal:ajax:complete",o.fn.modal=function(t){return 1===this.length&&new o.modal(this,t),this},o(i).on("click.modal",'a[rel~="modal:close"]',o.modal.close),o(i).on("click.modal",'a[rel~="modal:open"]',function(t){t.preventDefault(),o(this).modal()})}); diff --git a/hesk/theme/hesk3/customer/view-ticket/form.php b/hesk/theme/hesk3/customer/view-ticket/form.php index 27d69bb..9cd47f0 100644 --- a/hesk/theme/hesk3/customer/view-ticket/form.php +++ b/hesk/theme/hesk3/customer/view-ticket/form.php @@ -4,6 +4,7 @@ global $hesk_settings, $hesklang; * @var string $trackingId * @var string $email * @var boolean $rememberEmail + * @var boolean $displayForgotTrackingIdForm * @var boolean $submittedForgotTrackingIdForm */ @@ -41,6 +42,7 @@ require_once(TEMPLATE_PATH . 'customer/util/alerts.php'); width: 200px; } + @@ -95,7 +97,9 @@ require_once(TEMPLATE_PATH . 'customer/util/alerts.php');

@@ -137,19 +141,24 @@ require_once(TEMPLATE_PATH . 'customer/util/alerts.php'); -
-
+
+ @@ -201,9 +211,18 @@ END LICENSE CODE + diff --git a/hesk/theme/hesk3/customer/view-ticket/view-ticket.php b/hesk/theme/hesk3/customer/view-ticket/view-ticket.php index 0a8ab9f..8301748 100644 --- a/hesk/theme/hesk3/customer/view-ticket/view-ticket.php +++ b/hesk/theme/hesk3/customer/view-ticket/view-ticket.php @@ -41,6 +41,10 @@ require(TEMPLATE_PATH . 'customer/view-ticket/partial/add-reply.php'); + + + + @@ -137,10 +141,10 @@ require(TEMPLATE_PATH . 'customer/view-ticket/partial/add-reply.php');
-
-

+
+

@@ -322,8 +326,8 @@ function displayReplies($replies, $trackingId) {
-
-

+
+

diff --git a/hesk/theme/hesk3/print-ticket.php b/hesk/theme/hesk3/print-ticket.php index d745f41..7077750 100644 --- a/hesk/theme/hesk3/print-ticket.php +++ b/hesk/theme/hesk3/print-ticket.php @@ -80,6 +80,10 @@ if (!defined('IN_SCRIPT')) { : + + : + + : diff --git a/hesk/ticket.php b/hesk/ticket.php index 2774b55..c4fd71b 100644 --- a/hesk/ticket.php +++ b/hesk/ticket.php @@ -34,6 +34,7 @@ $display = 'none'; if ( ! empty($_GET['remind']) ) { $display = 'block'; + $my_email = hesk_emailCleanup( hesk_validateEmail( hesk_GET('e'), 'ERR' , 0) ); print_form(); } @@ -282,6 +283,7 @@ function print_form() 'trackingId' => $trackingID, 'email' => $my_email, 'rememberEmail' => $do_remember, + 'displayForgotTrackingIdForm' => !empty($_GET['forgot']), 'submittedForgotTrackingIdForm' => $display === 'block' ));