From d97fe5a81c8e3625f33ff5f71183d3df1fb398d5 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 24 Mar 2018 22:04:39 -0400 Subject: [PATCH 01/76] Move MFH text to separate files --- inc/common.inc.php | 4 + language/en/text-mfh.php | 687 +++++++++++++++++++++++++++++++++++++++ language/en/text.php | 685 +------------------------------------- 3 files changed, 692 insertions(+), 684 deletions(-) create mode 100644 language/en/text-mfh.php diff --git a/inc/common.inc.php b/inc/common.inc.php index dd47cafa..602779c6 100644 --- a/inc/common.inc.php +++ b/inc/common.inc.php @@ -1350,6 +1350,10 @@ function hesk_returnLanguage() die('Count not load a valid language file.'); } + // Load Mods for HESK language strings + $language_file = HESK_PATH . 'language/' . $hesk_settings['languages'][$hesk_settings['language']]['folder'] . '/text-mfh.php'; + require($language_file); + // Load a custom text file if available $language_file = HESK_PATH . 'language/' . $hesk_settings['languages'][$hesk_settings['language']]['folder'] . '/custom-text.php'; if (file_exists($language_file)) { diff --git a/language/en/text-mfh.php b/language/en/text-mfh.php new file mode 100644 index 00000000..3202b5c8 --- /dev/null +++ b/language/en/text-mfh.php @@ -0,0 +1,687 @@ +*.'; +$hesklang['quick_help_view_ticket']='Please fill out the required information on the right to view your ticket. If you forgot your Ticket tracking ID, click "Forgot tracking ID".'; +$hesklang['information']='Information'; +$hesklang['admin_sidebar_ticket_id']='TICKET ID'; +$hesklang['priorityChange']=' - - Change Priority - - '; +$hesklang['statusChange']=' - - Change Status - - '; +$hesklang['ownerChange']=' - - Change Owner - - '; +$hesklang['categoryChange']=' - - Change Category - - '; +$hesklang['navigation']='Navigation'; +$hesklang['nti']='New ticket'; +$hesklang['savedResponses']='Saved Responses'; +$hesklang['add_ticket_general_information']='General Information'; +$hesklang['add_ticket_your_message']='Your Message'; + +// ADDED OR MODIFIED IN Mods For HESK 1.2 +$hesklang['statuses'] = 'Statuses'; +$hesklang['basicProperties'] = 'Basic Properties'; +$hesklang['textColor'] = 'Text Color'; +$hesklang['textColorDescr'] = 'This is the hex color code for the status that will be used on the ticket search page and export search page'; +$hesklang['closedQuestionMark'] = 'Closed?'; +$hesklang['closedQuestionMarkDescr'] = 'If checked, tickets will be considered closed if they are set to this status.'; +$hesklang['basicProperties'] = 'Basic Properties'; +$hesklang['defaultStatusForAction'] = 'Default Status For Action'; +$hesklang['isClosedByClientMsg'] = 'When a client clicks the "Close ticket" link, change the status to'; +$hesklang['isStaffClosedOptionMsg'] = 'When a staff member clicks the "Close ticket" link, change the status to'; +$hesklang['isStaffReopenedStatusMsg'] = 'When a staff member clicks the "Open ticket" link, change the status to'; +$hesklang['isDefaultStaffReplyStatusMsg'] = 'When a staff member replies to a ticket, change the status to'; +$hesklang['lockedTicketStatusMsg'] = 'When a ticket is locked, change the status to'; +$hesklang['textColorRequired'] = 'Text Color is required.'; +$hesklang['addNew'] = 'Add New'; +$hesklang['close_action']='Close Ticket'; // Close ACTION +$hesklang['whyCantIDeleteThisStatus'] = "Why Can't I Delete This Status?"; +$hesklang['whyCantIDeleteThisStatusReason'] = 'This status cannot be deleted because it is being used as a default status for a particular action.'; +$hesklang['isNewTicketMsg'] = 'When a new ticket is created, set its status to'; +$hesklang['isRepliedByClientMsg'] = 'When a client replies to a ticket, set its status to'; +$hesklang['close_this_ticket']='Close ticket'; +$hesklang['closed']='closed'; +$hesklang['resolved']='Resolved'; // Ticket has been RESOLVED +$hesklang['quick_help_ticket']='Here is the information on your ticket. You can add a reply to this ticket, close it, or re-open the ticket if applicable.'; + +// ADDED OR MODIFIED IN Mods For HESK 1.2.2 +$hesklang['changeLanguage'] = 'Change language to'; + +// ADDED OR MODIFIED IN Mods For HESK 1.4.0 +$hesklang['navbarBackgroundColor'] = 'Navbar Background Color'; +$hesklang['navbarBackgroundColorHelp'] = 'The main color of the top navigation bar. This applies only to the client-side.'; +$hesklang['navbarBrandColor'] = 'Navbar Brand Color'; +$hesklang['navbarBrandColorHelp'] = 'The text color of the \'brand\' on the left (also the name of the Help Desk).'; +$hesklang['navbarBrandHoverColor'] = 'Navbar Brand Hover Color'; +$hesklang['navbarBrandHoverColorHelp'] = 'The text color of the \'brand\' on the left when the use moves their mouse over the text.'; +$hesklang['navbarItemTextColor'] = 'Navbar Item Text Color'; +$hesklang['navbarItemTextColorHelp'] = 'The text color of the navigation items on the navigation bar.'; +$hesklang['navbarItemTextHoverColor'] = 'Navbar Item Text Hover Color'; +$hesklang['navbarItemTextHoverColorHelp'] = 'The text color of the navigation items on the navigation bar when the user hovers over one of the items.'; +$hesklang['navbarItemTextSelectedColor'] = 'Navbar Item Text Selected Color'; +$hesklang['navbarItemTextSelectedColorHelp'] = 'The text color of the navigation items on the navigation bar when the user clicks on an item, and a dropdown menu appears (such as \'Ticket\').'; +$hesklang['navbarItemSelectedBackgroundColor'] = 'Navbar Item Selected Background Color'; +$hesklang['navbarItemSelectedBackgroundColorHelp'] = 'The background color of the navigation items on the navigation bar when the user clicks on an item, and a dropdown menu appears (such as \'Ticket\').'; +$hesklang['dropdownItemTextColor'] = 'Dropdown Item Text Color'; +$hesklang['dropdownItemTextColorHelp'] = 'The text color of a dropdown item.'; +$hesklang['dropdownItemTextHoverColor'] = 'Dropdown Item Text Hover Color'; +$hesklang['dropdownItemTextHoverColorHelp'] = 'The text color of a dropdown item when the mouse hovers over it.'; +$hesklang['questionMarkColor'] = 'Question Mark Color'; +$hesklang['questionMarkColorHelp'] = 'The text color for the question mark circle, as seen on the \'Settings\' page and on other various pages.'; +$hesklang['dropdownItemTextHoverBackgroundColor'] = 'Dropdown Item Text Hover Background Color'; +$hesklang['dropdownItemTextHoverBackgroundColorHelp'] = 'The background color of a dropdown item when the mouse hovers over it.'; +$hesklang['uiColors'] = 'UI Colors'; +$hesklang['displayRtl'] = 'Display site right-to-left'; +$hesklang['displayRtlHelp'] = 'Check this to set the text direction to right-to-left.'; +$hesklang['showIcons'] = 'Show Icons'; +$hesklang['showIconsHelp'] = 'Check this box to show icons next to navigation bar items'; +$hesklang['maintenanceMode'] = 'Maintenance Mode'; +$hesklang['maintenanceModeHelp'] = 'Check this box to put the Help Desk in maintenance mode. Staff can still log into the backend, but the front end will be inaccessible.'; +$hesklang['none'] = 'None'; +$hesklang['autorefresh'] = 'Autorefresh:'; +$hesklang['autorefresh_restrictions'] = 'Enter value in milliseconds. Value must be greater than 1000 to use this feature. No fractional values.'; + +// ADDED OR MODIFIED IN Mods For HESK 1.5.0 +$hesklang['ticket_auto_refresh'] = 'Ticket Table Auto-Refresh:'; +$hesklang['display_rtl'] = 'Display site right-to-left'; +$hesklang['show_icons_navigation'] = 'Show icons on navigation bar'; +$hesklang['enable_maintenance'] = 'Enable maintenance mode'; +$hesklang['can_man_settings']='Can manage help desk settings'; +$hesklang['disable_user'] = 'User is active (click to deactivate)'; +$hesklang['enable_user'] = 'User is inactive (click to activate)'; +$hesklang['user_activated'] = 'User has been activated'; +$hesklang['user_deactivated'] = 'User has been deactivated'; +$hesklang['active_user'] = 'Is active user'; +$hesklang['self_deactivation'] = 'You cannot deactivate yourself!'; +$hesklang['inactive_user'] = 'Your account is currently inactive. Contact an administrator for more information.'; +$hesklang['cant_edit_admin'] = 'You cannot edit the God Admin (User ID = 1)'; +$hesklang['notifications_disabled_info'] = 'Changing notifications settings has been disabled by your administrator.'; + +// ADDED OR MODIFIED IN Mods For HESK 1.6.0 +$hesklang['notify_note_unassigned'] = 'Someone adds a note to a ticket not assigned to me'; +$hesklang['can_change_notification_settings'] = 'Can change notification settings'; +$hesklang['add_row'] = 'Add row'; +$hesklang['addnote'] = 'Add note'; +$hesklang['mods_for_hesk'] = 'Mods for HESK'; +$hesklang['err_modsForHesk_settings'] = 'Can\'t open file modsForHesk_settings.inc.php for writing. Please CHMOD this file to 666 (rw-rw-rw-)'; +$hesklang['mods_for_hesk_version'] = 'Mods for HESK Version'; + +// ADDED OR MODIFIED IN Mods For HESK 1.7.0 +$hesklang['date_custom_field'] = 'Date'; +$hesklang['date_custom_field_text'] = 'No options for this custom field type.'; +$hesklang['multiple_select_custom_field'] = 'Multiple Select box'; +$hesklang['multiple_select_custom_field_text'] = 'Options for this multi-select box, enter one option per line (each line will be a choice your customers can choose from). You need to enter at least two options!'; +$hesklang['date_format'] = 'Date must be in YYYY-MM-DD format.'; +$hesklang['custom_field_setting'] = 'Multilanguage support'; +$hesklang['custom_field_setting_help'] = 'Enabling this setting will use the name of the custom field as the language + file\'s key, rather than the direct name itself. This allows the custom field to be translated into different languages.'; +$hesklang['enable_custom_field_language'] = 'Enable multilanguage support'; +$hesklang['custom_language_key'] = 'Field language file key'; +$hesklang['ticket_reopen_assigned'] = '[#%%TRACK_ID%%] Assigned ticket reopened'; +$hesklang['verify_email'] = 'Verify Email'; +$hesklang['email_verified'] = 'The email address %s has been verified. Additionally, the following tickets have been created:'; //%s: email address +$hesklang['verify_no_records'] = 'No records were found for this activation key. Has this activation key already been used?'; +$hesklang['activation_key'] = 'Activation Key'; +$hesklang['no_tickets_created'] = 'No tickets created'; +$hesklang['customer_email_verification'] = 'Customer Email Verifications'; +$hesklang['customer_email_verification_help'] = 'Require customers to verify their email address via email. Once their + address has been verified, it does not need to be re-verified in the future.

NOTE: Enabling this will disable the + ability for the customer to provide multiple emails, as HESK will be unable to determine which email needs to be verified.'; +$hesklang['require_customer_validate_email'] = 'Require customers to verify email'; +$hesklang['multi_eml_disabled'] = 'This feature has been disabled because this help desk has been configured to require + customers to verify their email address'; +$hesklang['feature_disabled'] = 'Feature Disabled'; +$hesklang['verify_your_email'] = 'Your ticket has been created; however your email needs to be verified before your ticket can be addressed. An email has been sent to the email provided for verification.'; +$hesklang['installation_information'] = 'Installation Information'; + +// ADDED OR MODIFIED IN Mods For HESK 2.0.0 +$hesklang['saved_ticket_tpl'] = 'Saved Templates'; +$hesklang['new_ticket_tpl']='Add or Edit a Ticket Template'; +$hesklang['and_change_status_to'] = 'and change status to'; // Used in combination with $hesklang['submit_reply'] (Reads as "Submit reply and change status to") +$hesklang['closed_title'] = 'Closed'; +$hesklang['image'] = 'Image'; +$hesklang['close_modal'] = 'Close'; +$hesklang['email_custom_field'] = 'Email Address'; +$hesklang['email_custom_field_help'] = 'Allows the input of an email address. Similar to a text field, however the email address(es) will be added to all emails for this ticket, in the Cc or Bcc section, depending on the option selected.'; +$hesklang['email_custom_field_label'] = 'Address Type'; +$hesklang['cc'] = 'Cc:'; +$hesklang['bcc'] = 'Bcc:'; +$hesklang['mailgun'] = 'Mailgun'; +$hesklang['mailgun_help'] = 'Send mail using the Mailgun API. For more information on Mailgun, visit https://www.mailgun.com'; +$hesklang['mailgun_api_key'] = 'Mailgun API Key'; +$hesklang['mailgun_api_key_help'] = 'Your API key for Mailgun.'; +$hesklang['mailgun_domain'] = 'Mailgun Domain'; +$hesklang['mailgun_domain_help'] = 'Your registered domain for Mailgun'; +$hesklang['html_emails'] = 'HTML Emails'; +$hesklang['html_emails_help'] = 'Send HTML-supported emails to staff and customers.

To use this feature, create a new folder called html in your + language\'s emails folder and create templates for each email file. Both the HTML and plaintext versions will be sent (recipient\'s email program will + properly display either the HTML or plaintext version, depending on their mail client\'s settings).'; +$hesklang['html_emails_text'] = 'Enable HTML-formatted emails'; +$hesklang['beta_text'] = 'BETA'; + +// ADDED OR MODIFIED IN Mods for HESK 2.1.0 +$hesklang['e_mfh_settings'] = 'You will not be able to save your settings unless this file is writable by the script (CHMOD to 666)!'; +$hesklang['mfh_up_to_date'] = 'Mods for HESK is up to date'; +$hesklang['use_bootstrap_theme'] = 'Use Boostrap Theme CSS'; +$hesklang['use_bootstrap_theme_help'] = 'Enable this to use the bootstrap-theme.css file. Use this for a more 3D look and feel, or disable it for a flatter look.'; + +// ADDED OR MODIFIED IN Mods for HESK 2.1.1 +$hesklang['new_article_default_type'] = 'Default Type for New Articles'; +$hesklang['new_article_default_type_help'] = 'Choose the default type for new knowledgebase articles.'; +$hesklang['kb_draft3'] = 'The article is saved but not yet published. It can only be read by staff who has permission to + manage knowledgebase articles.'; // This is exactly the same as kb_draft2 with all HTML removed +$hesklang['file_name'] = 'File Name'; +$hesklang['action'] = 'Action'; +$hesklang['click_to_preview'] = 'Click to preview'; +$hesklang['attachment_removed'] = 'This attachment has been removed and cannot be viewed / downloaded'; + +// ADDED OR MODIFIED IN Mods for HESK 2.2.0 +$hesklang['email_templates'] = 'Email templates'; +$hesklang['email_templates_intro'] = 'You can edit your plaintext and HTML email templates here.'; +$hesklang['edit_plain_text_template'] = 'Edit plain text template'; +$hesklang['edit_html_template'] = 'Edit HTML template'; +$hesklang['editing_plain_text_template'] = 'Editing plain text template %s'; // %s: The name of the template file, then language name +$hesklang['editing_html_template'] = 'Editing HTML template %s'; // %s: The name of the template file, then language name +$hesklang['show_special_tags'] = 'Show Special Tags'; +$hesklang['hide_special_tags'] = 'Hide Special Tags'; +$hesklang['special_tag'] = 'Special Tag'; +$hesklang['description'] = 'Description'; +$hesklang['customer_name'] = 'Customer name'; +$hesklang['customer_email'] = 'Customer email'; +$hesklang['ticket_subject'] = 'Ticket subject'; +$hesklang['ticket_message'] = 'Ticket/Reply message'; +$hesklang['ticket_created'] = 'Date and time of ticket submission'; +$hesklang['ticket_updated'] = 'Date and time of ticket last update'; +$hesklang['ticket_url'] = 'Ticket URL address'; +$hesklang['ticket_category'] = 'Ticket category'; +$hesklang['ticket_owner'] = 'Staff member assigned to the ticket'; +$hesklang['ticket_priority'] = 'Ticket priority'; +$hesklang['custom_field_x'] = 'Custom field %s'; // %s: Custom field #1-20 +$hesklang['email_template_saved'] = 'The email template %s has been saved.'; // %s: Template file name +$hesklang['error_saving_template'] = 'An error occurred when trying to save the email template!'; +$hesklang['can_man_email_tpl'] = 'Edit email templates'; +$hesklang['email_template_directory_not_writable'] = 'The email template %s is not writable by HESK. Please CHMOD it to 0666.'; // %s: template file name +$hesklang['closable_question'] = 'Closable?'; +$hesklang['closable_description'] = 'This setting is ignored if the "Closed?" setting is set to "Yes" for this status. +

Determines if the customer and/or staff is able to close a ticket in this status. +

Yes: Both customers and staff can close a ticket in this status. +
Customers only: Customers can close a ticket in this status, but staff cannot. +
Staff only: Staff can close a ticket in this status, but customers cannot. +
No: No one is allowed to close a ticket in this status.'; // " = " +$hesklang['customers_only'] = 'Customers only'; +$hesklang['staff_only'] = 'Staff only'; +$hesklang['yes_title_case'] = 'Yes'; +$hesklang['no_title_case'] = 'No'; +$hesklang['autoclose_ticket_status'] = 'When a ticket is closed automatically, change the status to'; +$hesklang['recent_tickets'] = 'Recent tickets'; +$hesklang['current_status_colon'] = 'Current status: %s'; // %s: status name (i.e. "Resolved", "New", etc.) +$hesklang['email_attachments'] = 'Email attachments'; +$hesklang['email_attachments_help'] = 'Show attachments as links: Links to attachments will be appended at the end of the email. +

Attach directly to email: Attachments will be embedded directly into emails.'; +$hesklang['show_attachments_as_links'] = 'Show attachments as links'; +$hesklang['attach_directly_to_email'] = 'Attach directly to email'; + +// ADDED OR MODIFIED IN Mods for HESK 2.2.1 +$hesklang['popart_no_colon']='Top Knowledgebase Articles'; // same as $hesklang['popart'] but without a colon (:) +$hesklang['latart_no_colon']='Latest Knowledgebase Articles'; // same as $hesklang['latart'] but without a colon (:) +$hesklang['ac_no_colon']='Articles in this Category'; // same as $hesklang['ac'] but without a colon (:) + +// ADDED OR MODIFIED IN Mods for HESK 2.3.0 +$hesklang['sm_icon'] = 'Icon'; +$hesklang['sm_icon_type'] = 'Icon Type'; +$hesklang['sm_no_icon'] = 'No Icon'; +$hesklang['sm_search_icon'] = 'Search Icon'; +$hesklang['sm_iconpicker_footer_label'] = '{0} - {1} of {2}'; // {0}: lower bound of page, {1}: upper bound of page, {2}: total number of icons +$hesklang['mods_for_hesk_acronym'] = 'MFH'; // THIS SHOULD NOT BE TRANSLATED +$hesklang['added_in_mods_for_hesk'] = 'Added in Mods for HESK'; +$hesklang['statuses_intro'] = 'Here you can add, remove, and modify ticket statuses, as well as changing the default status for particular actions.'; +$hesklang['statuses_saved'] = 'Ticket statuses have been updated!'; +$hesklang['email_template_not_saved'] = 'The email template %s was NOT saved due to an error. Enable debug mode to see if an error message appears, and ensure that your file has CHMOD 0666'; // %s: Template file name +$hesklang['language_key'] = 'Language Key'; +$hesklang['language_key_description'] = 'This is the language file \'key\' that contains the text you want to display'; +$hesklang['can_man_ticket_statuses'] = 'Can manage ticket statuses'; +$hesklang['key_required'] = 'Keys are required for all statuses'; +$hesklang['x_merged'] = '(+%s merged)'; // %s number of tickets merged +$hesklang['merged_tickets'] = 'Merged tickets: '; +$hesklang['show_number_merged'] = 'Show number of tickets merged'; +$hesklang['show_number_merged_descr'] = 'Show number of tickets merged next to Tracking ID'; +$hesklang['show_number_merged_help'] = 'If enabled, the user will be able to see which tickets were merged into the other on the ticket search screen.'; +$hesklang['latest_top_on_home'] = 'Latest/Top articles on home page'; +$hesklang['latest_top_on_home_help'] = 'Select YES to display the top and latest knowledgebase articles on the home page. + Otherwise, a link to the knowledgebase will appear on the home page.'; +$hesklang['location_unavailable'] = "Location unavailable. Click for more information."; +$hesklang['click_for_map'] = "View map of user's location"; +$hesklang['request_user_location'] = "Request Location"; +$hesklang['request_user_location_help'] = "If enabled, the help desk will ask for the customer's location, allowing staff to + see a map of the customer's location when they created the ticket."; +$hesklang['users_location'] = "User's Location"; +$hesklang['location_unavailable_0'] = "User's location is not available because the ticket was created before location tracking was enabled."; +$hesklang['location_unavailable_1'] = "User's location is not available because the user refused to share it."; +$hesklang['location_unavailable_2'] = "User's location is not available because the help desk was unable to determine the user's position."; +$hesklang['location_unavailable_3'] = "User's location is not available because the help desk was not able to determine the user's position in + a reasonable amount of time."; +$hesklang['location_unavailable_4'] = "An unknown error occurred when trying to obtain the user's location."; +$hesklang['location_unavailable_5'] = "User's location is not available because the user's browser did not meet the minimum +requirements for tracking their location when the ticket was submitted."; +$hesklang['save_location'] = 'Save Location'; +$hesklang['close_modal_without_saving'] = 'Close without saving'; +$hesklang['ticket_location_updated'] = 'Ticket location has been updated!'; +$hesklang['location_colon'] = 'Location:'; +$hesklang['your_current_location'] = 'Your location'; +$hesklang['requesting_location_ellipsis'] = 'Requesting location...'; +$hesklang['unable_to_determine_location'] = 'Unable to determine your location, or you declined to share it.'; +$hesklang['save_to_see_updated_address'] = 'Save the new location to see the updated address'; +$hesklang['manager'] = 'Manager'; +$hesklang['manager_updated'] = 'Category manager has been updated.'; +$hesklang['can_set_manager'] = 'Can set category managers'; +$hesklang['no_manager'] = 'No manager'; +$hesklang['number_of_users'] = 'Number of Users'; +$hesklang['actions'] = 'Actions'; +$hesklang['staff_cannot_be_admin'] = 'Staff permission group does not have admin access, and cannot be set as an admin'; +$hesklang['admin_cannot_be_staff'] = 'Administrator permission group has admin access, and cannot be set as non-admin'; +$hesklang['template_is_admin_cannot_change'] = 'The permission group currently has admin privileges, so you cannot set specific permissions here.'; +$hesklang['you_must_select_a_category'] = 'You must select at least one category.'; +$hesklang['you_must_select_a_feature'] = 'You must select at least one feature.'; +$hesklang['custom'] = 'Custom'; + +// ADDED OR MODIFIED IN Mods for HESK 2.4.0 +$hesklang['sort_by_user_defined_order'] = 'Sort by user-defined order'; +$hesklang['sort_alphabetically'] = 'Sort alphabetically'; +$hesklang['category_sort'] = 'Category Sorting'; +$hesklang['category_sort_help'] = 'Determines if categories shown on the manage categories page and all dropdowns are sorted by the user-defined order (default), or +sorted alphabetically.'; +$hesklang['quick_help_sections'] = 'Quick Help Sections'; +$hesklang['quick_help_sections_help'] = 'Check the checkbox to show the "Quick Help" sections on the left-hand side, or uncheck to not show.'; +$hesklang['create_ticket'] = 'Create ticket (customers)'; +$hesklang['view_ticket_form'] = 'View ticket form'; +$hesklang['knowledgebase'] = 'Knowledgebase section'; +$hesklang['staff_create_ticket'] = 'Create ticket (staff)'; +$hesklang['allow_rich_text_for_tickets'] = 'Allow rich text for tickets'; +$hesklang['allow_rich_text_for_tickets_help'] = 'Allow staff and customers to use rich text formatting when writing ticket messages / replies.'; +$hesklang['click_to_edit_name'] = 'Click to edit name'; +$hesklang['new_status'] = 'New Status'; +$hesklang['create_new_status_title'] = 'Create New Status'; +$hesklang['status_name_title'] = 'Status Name'; +$hesklang['status_name_title_help'] = 'The name of the status that should appear when viewing the ticket, for each language you have installed.'; +$hesklang['properties'] = 'Properties'; +$hesklang['closable'] = 'Closable'; // Same as $hesklang['closable_question'], but without punctuation +$hesklang['new_status_created'] = 'New status successfully created'; +$hesklang['editing_status_x'] = 'Editing status %s'; // 1st %s: text color, 2nd %s: status name +$hesklang['status_not_in_database'] = 'The status text for this language was not found in the database, so a suggested translation has been filled for you. + Please click "Save Changes" to save this translation to the database and to remove this warning.'; +$hesklang['ticket_status_updated'] = 'Ticket status successfully updated!'; +$hesklang['ticket_status_deleted'] = 'Ticket status deleted!'; +$hesklang['confirm_delete_status_question'] = 'Delete status?'; +$hesklang['confirm_delete_status'] = 'Are you sure you want to delete this status? This cannot be undone!'; +$hesklang['status_sort_updated'] = 'Ticket status sort updated!'; +$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'; +$hesklang['cannot_edit_status_demo'] = 'You cannot edit statuses while in demo mode!'; + +// ADDED OR MODIFIED IN Mods for HESK 2.5.0 +$hesklang['ticket_message_no_attachments'] = 'Ticket/Reply message, however attachments will not be included in the email'; +$hesklang['click_for_device_information'] = 'Click for device information'; +$hesklang['device_information'] = 'Device information'; +$hesklang['operating_system'] = 'Operating System'; +$hesklang['browser'] = 'Browser'; +$hesklang['screen_resolution'] = 'Screen Resolution'; +$hesklang['display_user_agent_information'] = 'Show user agent'; +$hesklang['display_user_agent_information_help'] = 'When enabled, staff will be able to view the operating system, browser, + and screen resolution of the device used to create the ticket.'; +$hesklang['value_colon'] = 'Value:'; +$hesklang['hidden_custom_field'] = 'Hidden text field'; +$hesklang['hidden_custom_field_help'] = 'This input is the same as a text field; however this value cannot be changed and will not be visible to the user.'; +$hesklang['readonly_custom_field'] = 'Read-only text field'; +$hesklang['readonly_custom_field_help'] = 'This input is the same as a text field; however this value cannot be changed, but will be visible to the user.'; +$hesklang['navbar_title_url'] = 'Navbar Title URL'; +$hesklang['navbar_title_url_help'] = 'Enter the URL you wish to use when a customer (or staff) clicks on the help desk title on the top-left corner of the screen. The URL must begin with http:// or https://.'; +$hesklang['this_field_is_required'] = 'This field is required'; +$hesklang['select_at_least_one_value'] = 'Please select at least one value'; + +// ADDED OR MODIFIED IN Mods for HESK 2.5.2 +$hesklang['manage_statuses'] = 'Manage Statuses'; +$hesklang['manage_service_messages'] = 'Manage Service Messages'; +$hesklang['manage_banned_ips'] = 'Manage Banned IPs'; +$hesklang['manage_banned_emails'] = 'Manage Banned Emails'; +$hesklang['manage_email_templates'] = 'Manage Email Templates'; +$hesklang['linked_tickets'] = 'Linked tickets'; +$hesklang['add_ticket'] = 'Add Ticket'; +$hesklang['cannot_link_ticket_to_itself'] = 'You cannot link a ticket to itself!'; +$hesklang['linked_ticket_does_not_exist'] = '%s is not a valid Tracking ID!'; //%s: the child tracking ID +$hesklang['is_already_linked'] = '%s is already linked to this ticket.'; //%s: the child tracking ID +$hesklang['link_added'] = 'Successfully linked %s to this ticket.'; //%s: the child tracking ID +$hesklang['ticket_no_longer_linked'] = 'Ticket is no longer linked.'; +$hesklang['unlink'] = 'Unlink'; + +// ADDED OR MODIFIED IN Mods for HESK 2.6.0 +$hesklang['search_logs'] = 'Search Logs'; +$hesklang['date_logged'] = 'Date Logged'; +$hesklang['from_date'] = 'From Date'; +$hesklang['to_date'] = 'To Date'; +$hesklang['severity'] = 'Severity'; +$hesklang['debug'] = 'Debug'; +$hesklang['warning_title_case'] = 'Warning'; +$hesklang['logs'] = 'Logs'; +$hesklang['view_message_log'] = 'View Message Log'; +$hesklang['can_view_logs'] = 'Can view message logs'; +$hesklang['attachment_viewer_message'] = "Drag files here or click the 'Add File' button below to select files to upload."; +$hesklang['attachment_invalid_type_message'] = 'Sorry, but the file type you tried to upload is not allowed.'; +$hesklang['attachment_upload_error'] = 'An error occurred when trying to upload. Please try again later.'; +$hesklang['attachment_too_large'] = 'This attachment is larger than the max filesize permitted.'; +$hesklang['attachment_cancel'] = 'Cancel'; +$hesklang['attachment_confirm_cancel'] = 'Are you sure you want to cancel this upload?'; +$hesklang['attachment_remove'] = 'Remove attachment'; +$hesklang['due_date'] = 'Due Date'; +$hesklang['category_updated'] = 'Changes to %s have been saved'; +$hesklang['new_event'] = 'New Event'; +$hesklang['create_event'] = 'Create Event'; +$hesklang['event_title'] = 'Title'; +$hesklang['event_title_tooltip'] = 'The title of the event'; +$hesklang['event_location'] = 'Location'; +$hesklang['event_location_tooltip'] = 'The location of the event'; +$hesklang['event_category_tooltip'] = 'Category for the event'; +$hesklang['event_start'] = 'Start'; +$hesklang['event_start_tooltip'] = 'The starting date (and time) of the event'; +$hesklang['event_start_date'] = 'Start Date'; +$hesklang['event_start_time'] = 'Start Time'; +$hesklang['event_all_day'] = 'All day'; +$hesklang['event_end'] = 'End'; +$hesklang['event_end_tooltip'] = 'The ending date (and time) of the event'; +$hesklang['event_end_date'] = 'End Date'; +$hesklang['event_end_time'] = 'End Time'; +$hesklang['event_reminder'] = 'Reminder'; +$hesklang['event_reminder_tooltip'] = 'Receive an e-mail reminder for this event. Only you will receive this reminder email.'; +$hesklang['event_min_before_event'] = 'minutes before event'; +$hesklang['event_hours_before_event'] = 'hours before event'; +$hesklang['event_days_before_event'] = 'days before event'; +$hesklang['event_weeks_before_event'] = 'weeks before event'; +$hesklang['event_comments'] = 'Comments'; +$hesklang['event_comments_tooltip'] = 'Additional comments about the event'; +$hesklang['event_create_ticket'] = 'Create Ticket'; +$hesklang['to_title_case'] = 'To'; +$hesklang['clear_for_no_due_date'] = 'Clear for no due date'; +$hesklang['ticket_due_date_updated'] = 'Ticket due date successfully updated'; +$hesklang['error_updating_ticket_due_date'] = 'An error occurred when trying to update the ticket due date'; +$hesklang['error_loading_events'] = 'An error occurred when trying to load events'; +$hesklang['error_deleting_event'] = 'An error occurred when trying to delete the event'; +$hesklang['event_deleted'] = 'Event successfully deleted'; +$hesklang['event_created'] = 'Event successfully created'; +$hesklang['error_creating_event'] = 'An error occurred when trying to create the event'; +$hesklang['event_updated'] = 'Event successfully updated'; +$hesklang['error_updating_event'] = 'An error occurred when trying to update the event'; +$hesklang['calendar_title_case'] = 'Calendar'; +$hesklang['calendar_categories'] = 'Categories'; +$hesklang['can_man_calendar'] = 'Can manage calendar events'; +$hesklang['calendar_reminder'] = 'Upcoming Event: %%TITLE%%'; +$hesklang['overdue_ticket'] = '[%%TRACKID%%] Ticket Overdue!'; +$hesklang['notify_overdue_unassigned'] = 'A ticket is overdue not assigned to me'; +$hesklang['calendar_settings'] = 'Calendar Settings'; +$hesklang['enable_calendar'] = 'Enable calendar'; +$hesklang['enable_calendar_help'] = 'Setting to enable / disable the calendar. The calendar can be shown to everyone, staff only, or disable the calendar entirely.'; +$hesklang['yes_enable_calendar'] = 'YES, enable calendar'; +$hesklang['yes_enable_calendar_staff_only'] = 'YES, enable calendar, but only for staff'; +$hesklang['no_disable_calendar'] = 'NO, disable calendar'; +$hesklang['first_day_of_week'] = 'First day of week'; +$hesklang['first_day_of_week_help'] = 'This setting decides which day of the week to show first per week.'; +$hesklang['calendar_disabled'] = 'The calendar is disabled'; +$hesklang['default_view'] = 'Default Calendar View'; +$hesklang['default_view_help'] = 'Decide which view will be shown to customers and staff by default when viewing the calendar. Staff can change this setting via their own profile.'; +$hesklang['week'] = 'Week'; +$hesklang['calendar_day'] = 'Day'; +$hesklang['calendar_index'] = 'View upcoming events'; +$hesklang['usage'] = 'Usage'; +$hesklang['tickets_and_events'] = 'Tickets and events'; +$hesklang['tickets_only'] = 'Tickets only'; +$hesklang['events_only'] = 'Events only'; +$hesklang['events'] = 'Events'; +$hesklang['add_files'] = ' Add File'; +$hesklang['select_all_title_case'] = 'Select All'; +$hesklang['deselect_all_title_case'] = 'Deselect All'; +$hesklang['event'] = 'Event'; +$hesklang['overdue_ticket_legend'] = 'Overdue ticket'; +$hesklang['attachment_max_exceeded'] = 'This file will not be uploaded becuase you have already uploaded the maximum number of files allowed.'; + +// ADDED OR MODIFIED IN Mods for HESK 3.0.0 +$hesklang['you_have_x_messages'] = 'You have %s new %s'; // %s: Number of new messages, "message" or "messages", depending on # +$hesklang['message_lower_case'] = 'message'; +$hesklang['messages_lower_case'] = 'messages'; +$hesklang['deleted_user_title_case'] = 'Deleted User'; +$hesklang['x_system_warnings'] = '%s System %s'; // %s: Number of warnings, $s: "Warning" or "Warnings", depending on # +$hesklang['warnings_title_case'] = 'Warnings'; +$hesklang['articles_in_category_x'] = 'Articles in Category %s'; // %s: category name +$hesklang['private_category_star'] = 'Private categories indicated by *'; +$hesklang['private_article_star'] = 'Private articles indicated by *'; +$hesklang['ticket_details'] = 'Ticket Details'; +$hesklang['more'] = 'More'; +$hesklang['click_to_edit'] = 'Click to edit'; +$hesklang['no_device_information'] = 'No device information'; +$hesklang['message_colon'] = 'Message:'; +$hesklang['original_message'] = 'Original message'; +$hesklang['reply_by_customer'] = 'Reply by customer'; +$hesklang['reply_by_staff'] = 'Reply by staff'; +$hesklang['timeline_today'] = 'Today'; +$hesklang['no_notes_for_this_ticket'] = 'No notes for this ticket'; +$hesklang['private_message_header'] = 'Private Message'; +$hesklang['date_colon'] = 'Date:'; +$hesklang['api_information'] = 'API Information'; +$hesklang['api_version'] = 'API Version'; +$hesklang['external_api'] = 'External API'; +$hesklang['external_api_help'] = 'Enable or Disable the external REST API'; +$hesklang['disabled_title_case'] = 'Disabled'; +$hesklang['enabled_title_case'] = 'Enabled'; +$hesklang['api_settings'] = 'API Settings'; +$hesklang['user_security'] = 'User Security'; +$hesklang['api_documentation'] = 'API Documentation'; +$hesklang['changes_saved'] = 'Changes saved!'; +$hesklang['save_failed_check_logs'] = 'Saving changes failed. Check the logs for more information.'; +$hesklang['number_of_tokens'] = 'Number of Tokens'; +$hesklang['generate_new_token'] = 'Generate New Token'; +$hesklang['revoke_all_tokens'] = 'Revoke All Tokens'; +$hesklang['generated_token_colon'] = 'Generated Token:'; +$hesklang['record_this_token_warning'] = 'Please record this token, as this is the only time you will be able to view it!'; +$hesklang['all_tokens_revoked'] = 'All tokens for this user have been revoked'; +$hesklang['staff_login_title'] = 'Staff Login'; +$hesklang['manage_custom_fields'] = 'Manage Custom Fields'; +$hesklang['value'] = 'Value'; +$hesklang['readonly'] = 'Readonly'; +$hesklang['copy_ticket'] = 'Copy Ticket'; +$hesklang['canned_responses_dropdown_title'] = 'Canned Responses'; +$hesklang['helpdesk_settings'] = 'Helpdesk Settings'; +$hesklang['click_to_toggle'] = 'Click to toggle'; +$hesklang['see_all_messages'] = 'See All Messages'; + +// ADDED OR MODIFIED IN Mods for HESK 3.1.0 +$hesklang['stack_trace_header'] = 'Stack Trace'; +$hesklang['ticket_message_contents_exist'] = 'The ticket message is not empty. Are you sure you want to leave this page?'; +$hesklang['resend_email_notification'] = 'Re-send Email Notification'; +$hesklang['email_notification_sent'] = 'Email notification sent!'; +$hesklang['email_notification_resend_failed'] = 'Error occurred when trying to send notification email.'; +$hesklang['edit_category'] = 'Edit Category'; +$hesklang['custom_nav_menu_elements'] = 'Custom Nav Menu Elements'; +$hesklang['create_new'] = 'Create New'; +$hesklang['custom_nav_element_deleted'] = 'Custom Navigation Element Deleted!'; +$hesklang['no_custom_nav_elements_found'] = 'No custom nav menu elements found'; +$hesklang['alert_success'] = 'Success'; // Used for alert messages +$hesklang['alert_error'] = 'Error'; // Used for alert messages +$hesklang['failed_to_load_custom_nav_elements'] = 'Failed to load custom nav elements!'; +$hesklang['custom_nav_element_deleted'] = 'Custom nav element deleted!'; +$hesklang['error_deleting_custom_nav_element'] = 'Error deleting custom nav element!'; +$hesklang['error_sorting_custom_nav_elements'] = 'Error sorting custom nav elements!'; +$hesklang['custom_nav_element_created'] = 'Custom nav element created!'; +$hesklang['custom_nav_element_saved'] = 'Custom nav element saved!'; +$hesklang['homepage_block'] = 'Homepage - Block'; +$hesklang['customer_navigation'] = 'Customer Navigation'; +$hesklang['staff_navigation'] = 'Staff Navigation'; +$hesklang['custom_nav_text'] = 'Text'; +$hesklang['custom_nav_subtext'] = 'Subtext'; +$hesklang['image_url_slash_font_icon'] = 'Image URL / Font Icon'; +$hesklang['edit_custom_nav_element_title_case'] = 'Edit Custom Nav Element'; +$hesklang['create_custom_nav_element_title_case'] = 'Create Custom Nav Element'; +$hesklang['place'] = 'Place'; +$hesklang['image_type'] = 'Image Type'; +$hesklang['image_url'] = 'Image URL'; +$hesklang['image_url_help'] = 'The URL of the image you wish to use. For customer/staff navigation, recommended size is 16x16px. For the homepage blocks, recommended size is 32x32px.'; +$hesklang['font_icon'] = 'Font Icon'; +$hesklang['error_saving_custom_nav_element'] = 'Error saving custom nav element!'; +$hesklang['place_help'] = 'The location of the custom navigation element.'; +$hesklang['url_help'] = 'The URL where the user should be taken to. Both relative and absolute URLs are supported.'; +$hesklang['common_properties'] = 'Common Properties'; +$hesklang['customer_view'] = 'Customer View'; +$hesklang['admin_panel'] = 'Admin Panel'; +$hesklang['manage_custom_nav_elements'] = 'Manage Custom Nav Elements'; +$hesklang['can_man_custom_nav'] = 'Can manage custom nav elements'; +$hesklang['category_background_color'] = 'Background Color'; +$hesklang['category_foreground_color'] = 'Foreground Color'; +$hesklang['category_background_color_help'] = 'The hex code for the background color to be used on the view ticket screen and calendar.'; +$hesklang['category_foreground_color_help'] = 'The hex code for the foreground color to be used on the view ticket and calendar screens. Leave blank for automatic color based on background.'; +$hesklang['category_display_border'] = 'Display Border'; +$hesklang['category_display_border_help'] = 'Choose to decide whether or not to display a border around the category (uses foreground color). +This is ignored if foreground color is set to automatic.'; +$hesklang['login_page'] = 'Login Page'; // Header on admin settings page +$hesklang['login_background'] = 'Login Background'; +$hesklang['solid_color'] = 'Solid color'; +$hesklang['login_background_color'] = 'Login Background Color'; // Input field information for screen-readers. Does not appear on-screen +$hesklang['login_background_image'] = 'Login Background Image'; // Input field information for screen-readers. Does not appear on-screen +$hesklang['login_box_header'] = 'Login Box Header'; +$hesklang['login_header_image'] = 'Login Header Image'; // Input field information for screen-readers. Does not appear on-screen +$hesklang['background_color'] = 'Background Color'; +$hesklang['background_color_help'] = 'The background color.'; +$hesklang['text_color'] = 'Text Color'; +$hesklang['text_color_help'] = 'The text color'; +$hesklang['text_hover_color'] = 'Hover Color: Text'; +$hesklang['text_hover_color_help'] = 'The text color when hovering over a link'; +$hesklang['background_hover_color'] = 'Hover Color: Background'; +$hesklang['background_hover_color_help'] = 'The background color when hovering over a link'; +$hesklang['navbar'] = 'Navigation Bar'; +$hesklang['navbar_brand'] = 'Navigation Brand'; +$hesklang['sidebar'] = 'Sidebar'; +$hesklang['sidebar_header'] = 'Sidebar Header'; +$hesklang['font_weight'] = 'Font Weight'; +$hesklang['font_weight_help'] = 'The font weight for text'; +$hesklang['normal'] = 'Normal'; +$hesklang['bold'] = 'Bold'; +$hesklang['color_preset'] = 'Color Preset'; +$hesklang['color_preset_help'] = 'Select a color preset for the backend, or define custom colors below.'; +$hesklang['select_a_preset'] = '-- Select a Preset --'; +$hesklang['preset_blue'] = 'Blue'; +$hesklang['preset_blue_light'] = 'Blue (light)'; +$hesklang['preset_yellow'] = 'Yellow'; +$hesklang['preset_yellow_light'] = 'Yellow (light)'; +$hesklang['preset_green'] = 'Green'; +$hesklang['preset_green_light'] = 'Green (light)'; +$hesklang['preset_purple'] = 'Purple'; +$hesklang['preset_purple_light'] = 'Purple (light)'; +$hesklang['preset_red'] = 'Red'; +$hesklang['preset_red_light'] = 'Red (light)'; +$hesklang['preset_black'] = 'Black'; +$hesklang['preset_black_light'] = 'Black (light)'; +$hesklang['url_rewrite'] = 'URL Rewrite'; +$hesklang['url_rewrite_help'] = 'Remove the need to include /index.php in API URLs (i.e. /api/index.php/v1/... -> /api/v1/...). Rename htaccess.txt to .htaccess in the /api folder to use.'; +$hesklang['url_rewrite_saved'] = 'URL rewrite setting saved!'; +$hesklang['api_settings_saved'] = 'API settings saved!'; +$hesklang['an_error_occurred'] = 'An error occurred. Check the logs for more information'; + +// Added or modified in Mods for HESK 3.2.0 +$hesklang['error_deleting_category'] = 'An error occurred when trying to delete the category.'; +$hesklang['cat_private'] = 'Private'; +$hesklang['cat_public'] = 'Public'; +$hesklang['cat_name_description'] = 'Name / Description'; +$hesklang['error_sorting_categories'] = 'An error occurred sorting categories!'; +$hesklang['error_retrieving_categories'] = 'An error occurred retrieving categories!'; +$hesklang['error_saving_updating_category'] = 'An error occurred creating / saving the category!'; +$hesklang['description_colon'] = 'Description:'; // Same as 'description', but with a colon (:) afterwards +$hesklang['copied_to_clipboard'] = 'Copied to clipboard'; + +// Language for the calendar pages +// Supported language codes: https://github.com/fullcalendar/fullcalendar/tree/v3.0.1/locale (do not include .js!) +// If your language is NOT in the supported langauges, leave 'en' +$hesklang['CALENDAR_LANGUAGE']='en'; + + +$hesklang['manage_permission_groups'] = 'Manage Permission Groups'; +$hesklang['manage_permission_groups_help'] = 'Here you can create and edit permission groups. These groups will appear when creating/editing a user. +When editing a permission group, all users assigned to this group will also have their permissions updated accordingly.'; +$hesklang['view_permissions_for_this_group'] = 'View/edit permissions for this group'; +$hesklang['permission'] = 'Permission'; +$hesklang['permissions_for_group'] = 'Permissions for group %s'; // %s template name +$hesklang['permission_group_updated'] = 'Permission group has been updated!'; +$hesklang['create_new_group'] = 'Create new permission group'; +$hesklang['create_new_group_title'] = 'Create New Permission Group'; // same as create_new_template, but in Title Case +$hesklang['group_name'] = 'Group name'; +$hesklang['group_name_required'] = 'Group name required.'; +$hesklang['permission_group_error'] = 'The permission group could not be saved due to the following error(s): %s'; // %s: error list +$hesklang['group_created'] = 'Permission group successfully created!'; +$hesklang['cannot_delete_admin_or_staff'] = 'The Administrator and Staff permission groups cannot be deleted!'; +$hesklang['no_groups_were_deleted'] = 'No groups were deleted!'; +$hesklang['permission_group_deleted'] = 'Permission group deleted!'; +$hesklang['manange_permission_groups_menu'] = 'Permission groups'; // Menu link +$hesklang['permission_groups'] = 'Permission Groups'; +$hesklang['can_man_permission_tpl'] = 'Can manage permission groups'; +$hesklang['permission_group_colon'] = 'Permission Group:'; +$hesklang['permission_group'] = 'Permission Group'; +$hesklang['changing_permissions_will_reset_permission_group'] = 'Changing a user\'s categories / features will reset their permission group! Click "Discard Changes" to reset the user\'s categories / features.'; + +// --> Ticket audit trail +$hesklang['audit_moved_category']='%s moved ticket to category %s'; // %s = new category, user making change, thist1 +$hesklang['audit_assigned']='%s assigned ticket to %s'; // %s = assigned user, user making change +$hesklang['audit_assigned_self'] = '%s self-assigned ticket'; +$hesklang['audit_unassigned'] = '%s unassigned ticket'; +$hesklang['audit_closed']='%s closed ticket'; // thist3 +$hesklang['audit_automatically_closed'] ='Ticket automatically closed'; +$hesklang['audit_opened']='%s opened ticket'; // thist4 +$hesklang['audit_locked']='%s locked ticket'; // thist5 +$hesklang['audit_automatically_locked'] = 'Ticket automatically locked'; +$hesklang['audit_unlocked']='%s unlocked ticket'; // thist6 +$hesklang['audit_created']='%s created ticket'; +$hesklang['audit_priority']='%s changed priority to %s'; // %s = date,new priority, user making change, thist8 +$hesklang['audit_status']='%s changed status to %s'; // %s = date, new status, user making change, thist9 +$hesklang['audit_autoassigned']='%s automatically assigned to ticket'; //thist10 +$hesklang['audit_submitted_via_piping']='Ticket submitted via e-mail piping'; // thist11 +$hesklang['audit_attachment_deleted']='%s deleted attachment %s'; // %s = date, deleted attachment, user making change +$hesklang['audit_merged']='%s merged ticket %s with this ticket'; // %s = date, merged ticket ID, user making change, thist13 +$hesklang['audit_time_worked']='%s updated time worked to %s'; // %s = date, new time worked, user making change +$hesklang['audit_submitted_by']='%s submitted ticket'; +$hesklang['audit_submitted_via_pop']='Ticket submitted via POP3 fetching'; // thist16 +$hesklang['audit_due_date_removed'] = '%s removed due date'; +$hesklang['audit_due_date_changed'] = '%s changed due date to %s'; +$hesklang['audit_linked_ticket'] = '%s linked ticket %s to this ticket'; +$hesklang['audit_unlinked_ticket'] = '%s unlinked ticket %s'; + +// Added or modified in Mods for HESK 3.3.0 +$hesklang['audit_event_created'] = '%s created event'; +$hesklang['audit_event_updated'] = '%s updated event'; +$hesklang['error_retrieving_sm'] = 'An error occurred retrieving service messages!'; +$hesklang['error_saving_updating_sm'] = 'An error occurred creating / saving the service message!'; +$hesklang['error_deleting_sm'] = 'An error occurred when trying to delete the service message.'; +$hesklang['error_sorting_sm'] = 'An error occurred sorting service messages!'; +$hesklang['sm_location'] = 'Location'; // Location for service messages +$hesklang['sm_customer_pages'] = 'Customer Pages'; +$hesklang['sm_staff_pages'] = 'Staff Pages'; +$hesklang['sm_homepage'] = 'Homepage'; +$hesklang['sm_kb_home'] = 'Knowledgebase Home'; +$hesklang['sm_view_kb_article'] = 'View Knowledgebase Article'; +$hesklang['sm_submit_ticket'] = 'Submit Ticket'; +$hesklang['sm_view_ticket'] = 'View Ticket'; +$hesklang['sm_login_page'] = 'Login Page'; +$hesklang['business_hours'] = 'Business Hours'; +$hesklang['business_hours_help'] = 'Set business hours for the calendar. There is no functional change by setting this, +but times outside of the defined business hours will have a darker gray background for increased visibility.'; +$hesklang['show_event_start_time'] = 'Show event start time in title'; +$hesklang['show_event_start_time_help'] = 'Always show the start time on event titles (unless the event is an all-day event).'; +$hesklang['highlight_ticket_rows_based_on_priority'] = 'Highlight ticket rows based on priority'; +$hesklang['highlight_ticket_rows_based_on_priority_help'] = 'If enabled, each ticket on the tickets page will be highlighted based on priority. If disabled, only * Critical * and High priority tickets will be highlighted.'; +$hesklang['highlight_ticket_rows_based_on_priority_descr'] = 'Highlight all ticket rows based on priority'; +$hesklang['protected_group'] = 'This is a protected group; you cannot change accessible categories / features.'; +$hesklang['emails_to_receive'] = 'Emails to receive'; +$hesklang['emails_sent_to_staff'] = 'Emails sent to staff'; +$hesklang['emails_sent_to_customer'] = 'Emails sent to customer'; + +// DO NOT CHANGE BELOW +if (!defined('IN_SCRIPT')) die('PHP syntax OK!'); \ No newline at end of file diff --git a/language/en/text.php b/language/en/text.php index 23fdbd79..0e7d76e2 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -1560,688 +1560,5 @@ $hesklang['step2']='Step 2'; $hesklang['dffs']='When download completes, delete the file from server'; $hesklang['fd']='Export file deleted from server'; -// ADDED OR MODIFIED IN Mods For HESK pre-1.2 -$hesklang['search_the_knowledgebase'] = 'Search the Knowledgebase'; -$hesklang['view_ticket_nav']='View Ticket'; -$hesklang['quick_help']='Quick Help'; -$hesklang['quick_help_submit_ticket']='Please fill out the form on the right to submit a ticket. Required fields are marked with a *.'; -$hesklang['quick_help_view_ticket']='Please fill out the required information on the right to view your ticket. If you forgot your Ticket tracking ID, click "Forgot tracking ID".'; -$hesklang['information']='Information'; -$hesklang['admin_sidebar_ticket_id']='TICKET ID'; -$hesklang['priorityChange']=' - - Change Priority - - '; -$hesklang['statusChange']=' - - Change Status - - '; -$hesklang['ownerChange']=' - - Change Owner - - '; -$hesklang['categoryChange']=' - - Change Category - - '; -$hesklang['navigation']='Navigation'; -$hesklang['nti']='New ticket'; -$hesklang['savedResponses']='Saved Responses'; -$hesklang['add_ticket_general_information']='General Information'; -$hesklang['add_ticket_your_message']='Your Message'; - -// ADDED OR MODIFIED IN Mods For HESK 1.2 -$hesklang['statuses'] = 'Statuses'; -$hesklang['basicProperties'] = 'Basic Properties'; -$hesklang['textColor'] = 'Text Color'; -$hesklang['textColorDescr'] = 'This is the hex color code for the status that will be used on the ticket search page and export search page'; -$hesklang['closedQuestionMark'] = 'Closed?'; -$hesklang['closedQuestionMarkDescr'] = 'If checked, tickets will be considered closed if they are set to this status.'; -$hesklang['basicProperties'] = 'Basic Properties'; -$hesklang['defaultStatusForAction'] = 'Default Status For Action'; -$hesklang['isClosedByClientMsg'] = 'When a client clicks the "Close ticket" link, change the status to'; -$hesklang['isStaffClosedOptionMsg'] = 'When a staff member clicks the "Close ticket" link, change the status to'; -$hesklang['isStaffReopenedStatusMsg'] = 'When a staff member clicks the "Open ticket" link, change the status to'; -$hesklang['isDefaultStaffReplyStatusMsg'] = 'When a staff member replies to a ticket, change the status to'; -$hesklang['lockedTicketStatusMsg'] = 'When a ticket is locked, change the status to'; -$hesklang['textColorRequired'] = 'Text Color is required.'; -$hesklang['addNew'] = 'Add New'; -$hesklang['close_action']='Close Ticket'; // Close ACTION -$hesklang['whyCantIDeleteThisStatus'] = "Why Can't I Delete This Status?"; -$hesklang['whyCantIDeleteThisStatusReason'] = 'This status cannot be deleted because it is being used as a default status for a particular action.'; -$hesklang['isNewTicketMsg'] = 'When a new ticket is created, set its status to'; -$hesklang['isRepliedByClientMsg'] = 'When a client replies to a ticket, set its status to'; -$hesklang['close_this_ticket']='Close ticket'; -$hesklang['closed']='closed'; -$hesklang['resolved']='Resolved'; // Ticket has been RESOLVED -$hesklang['quick_help_ticket']='Here is the information on your ticket. You can add a reply to this ticket, close it, or re-open the ticket if applicable.'; - -// ADDED OR MODIFIED IN Mods For HESK 1.2.2 -$hesklang['changeLanguage'] = 'Change language to'; - -// ADDED OR MODIFIED IN Mods For HESK 1.4.0 -$hesklang['navbarBackgroundColor'] = 'Navbar Background Color'; -$hesklang['navbarBackgroundColorHelp'] = 'The main color of the top navigation bar. This applies only to the client-side.'; -$hesklang['navbarBrandColor'] = 'Navbar Brand Color'; -$hesklang['navbarBrandColorHelp'] = 'The text color of the \'brand\' on the left (also the name of the Help Desk).'; -$hesklang['navbarBrandHoverColor'] = 'Navbar Brand Hover Color'; -$hesklang['navbarBrandHoverColorHelp'] = 'The text color of the \'brand\' on the left when the use moves their mouse over the text.'; -$hesklang['navbarItemTextColor'] = 'Navbar Item Text Color'; -$hesklang['navbarItemTextColorHelp'] = 'The text color of the navigation items on the navigation bar.'; -$hesklang['navbarItemTextHoverColor'] = 'Navbar Item Text Hover Color'; -$hesklang['navbarItemTextHoverColorHelp'] = 'The text color of the navigation items on the navigation bar when the user hovers over one of the items.'; -$hesklang['navbarItemTextSelectedColor'] = 'Navbar Item Text Selected Color'; -$hesklang['navbarItemTextSelectedColorHelp'] = 'The text color of the navigation items on the navigation bar when the user clicks on an item, and a dropdown menu appears (such as \'Ticket\').'; -$hesklang['navbarItemSelectedBackgroundColor'] = 'Navbar Item Selected Background Color'; -$hesklang['navbarItemSelectedBackgroundColorHelp'] = 'The background color of the navigation items on the navigation bar when the user clicks on an item, and a dropdown menu appears (such as \'Ticket\').'; -$hesklang['dropdownItemTextColor'] = 'Dropdown Item Text Color'; -$hesklang['dropdownItemTextColorHelp'] = 'The text color of a dropdown item.'; -$hesklang['dropdownItemTextHoverColor'] = 'Dropdown Item Text Hover Color'; -$hesklang['dropdownItemTextHoverColorHelp'] = 'The text color of a dropdown item when the mouse hovers over it.'; -$hesklang['questionMarkColor'] = 'Question Mark Color'; -$hesklang['questionMarkColorHelp'] = 'The text color for the question mark circle, as seen on the \'Settings\' page and on other various pages.'; -$hesklang['dropdownItemTextHoverBackgroundColor'] = 'Dropdown Item Text Hover Background Color'; -$hesklang['dropdownItemTextHoverBackgroundColorHelp'] = 'The background color of a dropdown item when the mouse hovers over it.'; -$hesklang['uiColors'] = 'UI Colors'; -$hesklang['displayRtl'] = 'Display site right-to-left'; -$hesklang['displayRtlHelp'] = 'Check this to set the text direction to right-to-left.'; -$hesklang['showIcons'] = 'Show Icons'; -$hesklang['showIconsHelp'] = 'Check this box to show icons next to navigation bar items'; -$hesklang['maintenanceMode'] = 'Maintenance Mode'; -$hesklang['maintenanceModeHelp'] = 'Check this box to put the Help Desk in maintenance mode. Staff can still log into the backend, but the front end will be inaccessible.'; -$hesklang['none'] = 'None'; -$hesklang['autorefresh'] = 'Autorefresh:'; -$hesklang['autorefresh_restrictions'] = 'Enter value in milliseconds. Value must be greater than 1000 to use this feature. No fractional values.'; - -// ADDED OR MODIFIED IN Mods For HESK 1.5.0 -$hesklang['ticket_auto_refresh'] = 'Ticket Table Auto-Refresh:'; -$hesklang['display_rtl'] = 'Display site right-to-left'; -$hesklang['show_icons_navigation'] = 'Show icons on navigation bar'; -$hesklang['enable_maintenance'] = 'Enable maintenance mode'; -$hesklang['can_man_settings']='Can manage help desk settings'; -$hesklang['disable_user'] = 'User is active (click to deactivate)'; -$hesklang['enable_user'] = 'User is inactive (click to activate)'; -$hesklang['user_activated'] = 'User has been activated'; -$hesklang['user_deactivated'] = 'User has been deactivated'; -$hesklang['active_user'] = 'Is active user'; -$hesklang['self_deactivation'] = 'You cannot deactivate yourself!'; -$hesklang['inactive_user'] = 'Your account is currently inactive. Contact an administrator for more information.'; -$hesklang['cant_edit_admin'] = 'You cannot edit the God Admin (User ID = 1)'; -$hesklang['notifications_disabled_info'] = 'Changing notifications settings has been disabled by your administrator.'; - -// ADDED OR MODIFIED IN Mods For HESK 1.6.0 -$hesklang['notify_note_unassigned'] = 'Someone adds a note to a ticket not assigned to me'; -$hesklang['can_change_notification_settings'] = 'Can change notification settings'; -$hesklang['add_row'] = 'Add row'; -$hesklang['addnote'] = 'Add note'; -$hesklang['mods_for_hesk'] = 'Mods for HESK'; -$hesklang['err_modsForHesk_settings'] = 'Can\'t open file modsForHesk_settings.inc.php for writing. Please CHMOD this file to 666 (rw-rw-rw-)'; -$hesklang['mods_for_hesk_version'] = 'Mods for HESK Version'; - -// ADDED OR MODIFIED IN Mods For HESK 1.7.0 -$hesklang['date_custom_field'] = 'Date'; -$hesklang['date_custom_field_text'] = 'No options for this custom field type.'; -$hesklang['multiple_select_custom_field'] = 'Multiple Select box'; -$hesklang['multiple_select_custom_field_text'] = 'Options for this multi-select box, enter one option per line (each line will be a choice your customers can choose from). You need to enter at least two options!'; -$hesklang['date_format'] = 'Date must be in YYYY-MM-DD format.'; -$hesklang['custom_field_setting'] = 'Multilanguage support'; -$hesklang['custom_field_setting_help'] = 'Enabling this setting will use the name of the custom field as the language - file\'s key, rather than the direct name itself. This allows the custom field to be translated into different languages.'; -$hesklang['enable_custom_field_language'] = 'Enable multilanguage support'; -$hesklang['custom_language_key'] = 'Field language file key'; -$hesklang['ticket_reopen_assigned'] = '[#%%TRACK_ID%%] Assigned ticket reopened'; -$hesklang['verify_email'] = 'Verify Email'; -$hesklang['email_verified'] = 'The email address %s has been verified. Additionally, the following tickets have been created:'; //%s: email address -$hesklang['verify_no_records'] = 'No records were found for this activation key. Has this activation key already been used?'; -$hesklang['activation_key'] = 'Activation Key'; -$hesklang['no_tickets_created'] = 'No tickets created'; -$hesklang['customer_email_verification'] = 'Customer Email Verifications'; -$hesklang['customer_email_verification_help'] = 'Require customers to verify their email address via email. Once their - address has been verified, it does not need to be re-verified in the future.

NOTE: Enabling this will disable the - ability for the customer to provide multiple emails, as HESK will be unable to determine which email needs to be verified.'; -$hesklang['require_customer_validate_email'] = 'Require customers to verify email'; -$hesklang['multi_eml_disabled'] = 'This feature has been disabled because this help desk has been configured to require - customers to verify their email address'; -$hesklang['feature_disabled'] = 'Feature Disabled'; -$hesklang['verify_your_email'] = 'Your ticket has been created; however your email needs to be verified before your ticket can be addressed. An email has been sent to the email provided for verification.'; -$hesklang['installation_information'] = 'Installation Information'; - -// ADDED OR MODIFIED IN Mods For HESK 2.0.0 -$hesklang['saved_ticket_tpl'] = 'Saved Templates'; -$hesklang['new_ticket_tpl']='Add or Edit a Ticket Template'; -$hesklang['and_change_status_to'] = 'and change status to'; // Used in combination with $hesklang['submit_reply'] (Reads as "Submit reply and change status to") -$hesklang['closed_title'] = 'Closed'; -$hesklang['image'] = 'Image'; -$hesklang['close_modal'] = 'Close'; -$hesklang['email_custom_field'] = 'Email Address'; -$hesklang['email_custom_field_help'] = 'Allows the input of an email address. Similar to a text field, however the email address(es) will be added to all emails for this ticket, in the Cc or Bcc section, depending on the option selected.'; -$hesklang['email_custom_field_label'] = 'Address Type'; -$hesklang['cc'] = 'Cc:'; -$hesklang['bcc'] = 'Bcc:'; -$hesklang['mailgun'] = 'Mailgun'; -$hesklang['mailgun_help'] = 'Send mail using the Mailgun API. For more information on Mailgun, visit https://www.mailgun.com'; -$hesklang['mailgun_api_key'] = 'Mailgun API Key'; -$hesklang['mailgun_api_key_help'] = 'Your API key for Mailgun.'; -$hesklang['mailgun_domain'] = 'Mailgun Domain'; -$hesklang['mailgun_domain_help'] = 'Your registered domain for Mailgun'; -$hesklang['html_emails'] = 'HTML Emails'; -$hesklang['html_emails_help'] = 'Send HTML-supported emails to staff and customers.

To use this feature, create a new folder called html in your - language\'s emails folder and create templates for each email file. Both the HTML and plaintext versions will be sent (recipient\'s email program will - properly display either the HTML or plaintext version, depending on their mail client\'s settings).'; -$hesklang['html_emails_text'] = 'Enable HTML-formatted emails'; -$hesklang['beta_text'] = 'BETA'; - -// ADDED OR MODIFIED IN Mods for HESK 2.1.0 -$hesklang['e_mfh_settings'] = 'You will not be able to save your settings unless this file is writable by the script (CHMOD to 666)!'; -$hesklang['mfh_up_to_date'] = 'Mods for HESK is up to date'; -$hesklang['use_bootstrap_theme'] = 'Use Boostrap Theme CSS'; -$hesklang['use_bootstrap_theme_help'] = 'Enable this to use the bootstrap-theme.css file. Use this for a more 3D look and feel, or disable it for a flatter look.'; - -// ADDED OR MODIFIED IN Mods for HESK 2.1.1 -$hesklang['new_article_default_type'] = 'Default Type for New Articles'; -$hesklang['new_article_default_type_help'] = 'Choose the default type for new knowledgebase articles.'; -$hesklang['kb_draft3'] = 'The article is saved but not yet published. It can only be read by staff who has permission to - manage knowledgebase articles.'; // This is exactly the same as kb_draft2 with all HTML removed -$hesklang['file_name'] = 'File Name'; -$hesklang['action'] = 'Action'; -$hesklang['click_to_preview'] = 'Click to preview'; -$hesklang['attachment_removed'] = 'This attachment has been removed and cannot be viewed / downloaded'; - -// ADDED OR MODIFIED IN Mods for HESK 2.2.0 -$hesklang['email_templates'] = 'Email templates'; -$hesklang['email_templates_intro'] = 'You can edit your plaintext and HTML email templates here.'; -$hesklang['edit_plain_text_template'] = 'Edit plain text template'; -$hesklang['edit_html_template'] = 'Edit HTML template'; -$hesklang['editing_plain_text_template'] = 'Editing plain text template %s'; // %s: The name of the template file, then language name -$hesklang['editing_html_template'] = 'Editing HTML template %s'; // %s: The name of the template file, then language name -$hesklang['show_special_tags'] = 'Show Special Tags'; -$hesklang['hide_special_tags'] = 'Hide Special Tags'; -$hesklang['special_tag'] = 'Special Tag'; -$hesklang['description'] = 'Description'; -$hesklang['customer_name'] = 'Customer name'; -$hesklang['customer_email'] = 'Customer email'; -$hesklang['ticket_subject'] = 'Ticket subject'; -$hesklang['ticket_message'] = 'Ticket/Reply message'; -$hesklang['ticket_created'] = 'Date and time of ticket submission'; -$hesklang['ticket_updated'] = 'Date and time of ticket last update'; -$hesklang['ticket_url'] = 'Ticket URL address'; -$hesklang['ticket_category'] = 'Ticket category'; -$hesklang['ticket_owner'] = 'Staff member assigned to the ticket'; -$hesklang['ticket_priority'] = 'Ticket priority'; -$hesklang['custom_field_x'] = 'Custom field %s'; // %s: Custom field #1-20 -$hesklang['email_template_saved'] = 'The email template %s has been saved.'; // %s: Template file name -$hesklang['error_saving_template'] = 'An error occurred when trying to save the email template!'; -$hesklang['can_man_email_tpl'] = 'Edit email templates'; -$hesklang['email_template_directory_not_writable'] = 'The email template %s is not writable by HESK. Please CHMOD it to 0666.'; // %s: template file name -$hesklang['closable_question'] = 'Closable?'; -$hesklang['closable_description'] = 'This setting is ignored if the "Closed?" setting is set to "Yes" for this status. -

Determines if the customer and/or staff is able to close a ticket in this status. -

Yes: Both customers and staff can close a ticket in this status. -
Customers only: Customers can close a ticket in this status, but staff cannot. -
Staff only: Staff can close a ticket in this status, but customers cannot. -
No: No one is allowed to close a ticket in this status.'; // " = " -$hesklang['customers_only'] = 'Customers only'; -$hesklang['staff_only'] = 'Staff only'; -$hesklang['yes_title_case'] = 'Yes'; -$hesklang['no_title_case'] = 'No'; -$hesklang['autoclose_ticket_status'] = 'When a ticket is closed automatically, change the status to'; -$hesklang['recent_tickets'] = 'Recent tickets'; -$hesklang['current_status_colon'] = 'Current status: %s'; // %s: status name (i.e. "Resolved", "New", etc.) -$hesklang['email_attachments'] = 'Email attachments'; -$hesklang['email_attachments_help'] = 'Show attachments as links: Links to attachments will be appended at the end of the email. -

Attach directly to email: Attachments will be embedded directly into emails.'; -$hesklang['show_attachments_as_links'] = 'Show attachments as links'; -$hesklang['attach_directly_to_email'] = 'Attach directly to email'; - -// ADDED OR MODIFIED IN Mods for HESK 2.2.1 -$hesklang['popart_no_colon']='Top Knowledgebase Articles'; // same as $hesklang['popart'] but without a colon (:) -$hesklang['latart_no_colon']='Latest Knowledgebase Articles'; // same as $hesklang['latart'] but without a colon (:) -$hesklang['ac_no_colon']='Articles in this Category'; // same as $hesklang['ac'] but without a colon (:) - -// ADDED OR MODIFIED IN Mods for HESK 2.3.0 -$hesklang['sm_icon'] = 'Icon'; -$hesklang['sm_icon_type'] = 'Icon Type'; -$hesklang['sm_no_icon'] = 'No Icon'; -$hesklang['sm_search_icon'] = 'Search Icon'; -$hesklang['sm_iconpicker_footer_label'] = '{0} - {1} of {2}'; // {0}: lower bound of page, {1}: upper bound of page, {2}: total number of icons -$hesklang['mods_for_hesk_acronym'] = 'MFH'; // THIS SHOULD NOT BE TRANSLATED -$hesklang['added_in_mods_for_hesk'] = 'Added in Mods for HESK'; -$hesklang['statuses_intro'] = 'Here you can add, remove, and modify ticket statuses, as well as changing the default status for particular actions.'; -$hesklang['statuses_saved'] = 'Ticket statuses have been updated!'; -$hesklang['email_template_not_saved'] = 'The email template %s was NOT saved due to an error. Enable debug mode to see if an error message appears, and ensure that your file has CHMOD 0666'; // %s: Template file name -$hesklang['language_key'] = 'Language Key'; -$hesklang['language_key_description'] = 'This is the language file \'key\' that contains the text you want to display'; -$hesklang['can_man_ticket_statuses'] = 'Can manage ticket statuses'; -$hesklang['key_required'] = 'Keys are required for all statuses'; -$hesklang['x_merged'] = '(+%s merged)'; // %s number of tickets merged -$hesklang['merged_tickets'] = 'Merged tickets: '; -$hesklang['show_number_merged'] = 'Show number of tickets merged'; -$hesklang['show_number_merged_descr'] = 'Show number of tickets merged next to Tracking ID'; -$hesklang['show_number_merged_help'] = 'If enabled, the user will be able to see which tickets were merged into the other on the ticket search screen.'; -$hesklang['latest_top_on_home'] = 'Latest/Top articles on home page'; -$hesklang['latest_top_on_home_help'] = 'Select YES to display the top and latest knowledgebase articles on the home page. - Otherwise, a link to the knowledgebase will appear on the home page.'; -$hesklang['location_unavailable'] = "Location unavailable. Click for more information."; -$hesklang['click_for_map'] = "View map of user's location"; -$hesklang['request_user_location'] = "Request Location"; -$hesklang['request_user_location_help'] = "If enabled, the help desk will ask for the customer's location, allowing staff to - see a map of the customer's location when they created the ticket."; -$hesklang['users_location'] = "User's Location"; -$hesklang['location_unavailable_0'] = "User's location is not available because the ticket was created before location tracking was enabled."; -$hesklang['location_unavailable_1'] = "User's location is not available because the user refused to share it."; -$hesklang['location_unavailable_2'] = "User's location is not available because the help desk was unable to determine the user's position."; -$hesklang['location_unavailable_3'] = "User's location is not available because the help desk was not able to determine the user's position in - a reasonable amount of time."; -$hesklang['location_unavailable_4'] = "An unknown error occurred when trying to obtain the user's location."; -$hesklang['location_unavailable_5'] = "User's location is not available because the user's browser did not meet the minimum -requirements for tracking their location when the ticket was submitted."; -$hesklang['save_location'] = 'Save Location'; -$hesklang['close_modal_without_saving'] = 'Close without saving'; -$hesklang['ticket_location_updated'] = 'Ticket location has been updated!'; -$hesklang['location_colon'] = 'Location:'; -$hesklang['your_current_location'] = 'Your location'; -$hesklang['requesting_location_ellipsis'] = 'Requesting location...'; -$hesklang['unable_to_determine_location'] = 'Unable to determine your location, or you declined to share it.'; -$hesklang['save_to_see_updated_address'] = 'Save the new location to see the updated address'; -$hesklang['manager'] = 'Manager'; -$hesklang['manager_updated'] = 'Category manager has been updated.'; -$hesklang['can_set_manager'] = 'Can set category managers'; -$hesklang['no_manager'] = 'No manager'; -$hesklang['number_of_users'] = 'Number of Users'; -$hesklang['actions'] = 'Actions'; -$hesklang['staff_cannot_be_admin'] = 'Staff permission group does not have admin access, and cannot be set as an admin'; -$hesklang['admin_cannot_be_staff'] = 'Administrator permission group has admin access, and cannot be set as non-admin'; -$hesklang['template_is_admin_cannot_change'] = 'The permission group currently has admin privileges, so you cannot set specific permissions here.'; -$hesklang['you_must_select_a_category'] = 'You must select at least one category.'; -$hesklang['you_must_select_a_feature'] = 'You must select at least one feature.'; -$hesklang['custom'] = 'Custom'; - -// ADDED OR MODIFIED IN Mods for HESK 2.4.0 -$hesklang['sort_by_user_defined_order'] = 'Sort by user-defined order'; -$hesklang['sort_alphabetically'] = 'Sort alphabetically'; -$hesklang['category_sort'] = 'Category Sorting'; -$hesklang['category_sort_help'] = 'Determines if categories shown on the manage categories page and all dropdowns are sorted by the user-defined order (default), or -sorted alphabetically.'; -$hesklang['quick_help_sections'] = 'Quick Help Sections'; -$hesklang['quick_help_sections_help'] = 'Check the checkbox to show the "Quick Help" sections on the left-hand side, or uncheck to not show.'; -$hesklang['create_ticket'] = 'Create ticket (customers)'; -$hesklang['view_ticket_form'] = 'View ticket form'; -$hesklang['knowledgebase'] = 'Knowledgebase section'; -$hesklang['staff_create_ticket'] = 'Create ticket (staff)'; -$hesklang['allow_rich_text_for_tickets'] = 'Allow rich text for tickets'; -$hesklang['allow_rich_text_for_tickets_help'] = 'Allow staff and customers to use rich text formatting when writing ticket messages / replies.'; -$hesklang['click_to_edit_name'] = 'Click to edit name'; -$hesklang['new_status'] = 'New Status'; -$hesklang['create_new_status_title'] = 'Create New Status'; -$hesklang['status_name_title'] = 'Status Name'; -$hesklang['status_name_title_help'] = 'The name of the status that should appear when viewing the ticket, for each language you have installed.'; -$hesklang['properties'] = 'Properties'; -$hesklang['closable'] = 'Closable'; // Same as $hesklang['closable_question'], but without punctuation -$hesklang['new_status_created'] = 'New status successfully created'; -$hesklang['editing_status_x'] = 'Editing status %s'; // 1st %s: text color, 2nd %s: status name -$hesklang['status_not_in_database'] = 'The status text for this language was not found in the database, so a suggested translation has been filled for you. - Please click "Save Changes" to save this translation to the database and to remove this warning.'; -$hesklang['ticket_status_updated'] = 'Ticket status successfully updated!'; -$hesklang['ticket_status_deleted'] = 'Ticket status deleted!'; -$hesklang['confirm_delete_status_question'] = 'Delete status?'; -$hesklang['confirm_delete_status'] = 'Are you sure you want to delete this status? This cannot be undone!'; -$hesklang['status_sort_updated'] = 'Ticket status sort updated!'; -$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'; -$hesklang['cannot_edit_status_demo'] = 'You cannot edit statuses while in demo mode!'; - -// ADDED OR MODIFIED IN Mods for HESK 2.5.0 -$hesklang['ticket_message_no_attachments'] = 'Ticket/Reply message, however attachments will not be included in the email'; -$hesklang['click_for_device_information'] = 'Click for device information'; -$hesklang['device_information'] = 'Device information'; -$hesklang['operating_system'] = 'Operating System'; -$hesklang['browser'] = 'Browser'; -$hesklang['screen_resolution'] = 'Screen Resolution'; -$hesklang['display_user_agent_information'] = 'Show user agent'; -$hesklang['display_user_agent_information_help'] = 'When enabled, staff will be able to view the operating system, browser, - and screen resolution of the device used to create the ticket.'; -$hesklang['value_colon'] = 'Value:'; -$hesklang['hidden_custom_field'] = 'Hidden text field'; -$hesklang['hidden_custom_field_help'] = 'This input is the same as a text field; however this value cannot be changed and will not be visible to the user.'; -$hesklang['readonly_custom_field'] = 'Read-only text field'; -$hesklang['readonly_custom_field_help'] = 'This input is the same as a text field; however this value cannot be changed, but will be visible to the user.'; -$hesklang['navbar_title_url'] = 'Navbar Title URL'; -$hesklang['navbar_title_url_help'] = 'Enter the URL you wish to use when a customer (or staff) clicks on the help desk title on the top-left corner of the screen. The URL must begin with http:// or https://.'; -$hesklang['this_field_is_required'] = 'This field is required'; -$hesklang['select_at_least_one_value'] = 'Please select at least one value'; - -// ADDED OR MODIFIED IN Mods for HESK 2.5.2 -$hesklang['manage_statuses'] = 'Manage Statuses'; -$hesklang['manage_service_messages'] = 'Manage Service Messages'; -$hesklang['manage_banned_ips'] = 'Manage Banned IPs'; -$hesklang['manage_banned_emails'] = 'Manage Banned Emails'; -$hesklang['manage_email_templates'] = 'Manage Email Templates'; -$hesklang['linked_tickets'] = 'Linked tickets'; -$hesklang['add_ticket'] = 'Add Ticket'; -$hesklang['cannot_link_ticket_to_itself'] = 'You cannot link a ticket to itself!'; -$hesklang['linked_ticket_does_not_exist'] = '%s is not a valid Tracking ID!'; //%s: the child tracking ID -$hesklang['is_already_linked'] = '%s is already linked to this ticket.'; //%s: the child tracking ID -$hesklang['link_added'] = 'Successfully linked %s to this ticket.'; //%s: the child tracking ID -$hesklang['ticket_no_longer_linked'] = 'Ticket is no longer linked.'; -$hesklang['unlink'] = 'Unlink'; - -// ADDED OR MODIFIED IN Mods for HESK 2.6.0 -$hesklang['search_logs'] = 'Search Logs'; -$hesklang['date_logged'] = 'Date Logged'; -$hesklang['from_date'] = 'From Date'; -$hesklang['to_date'] = 'To Date'; -$hesklang['severity'] = 'Severity'; -$hesklang['debug'] = 'Debug'; -$hesklang['warning_title_case'] = 'Warning'; -$hesklang['logs'] = 'Logs'; -$hesklang['view_message_log'] = 'View Message Log'; -$hesklang['can_view_logs'] = 'Can view message logs'; -$hesklang['attachment_viewer_message'] = "Drag files here or click the 'Add File' button below to select files to upload."; -$hesklang['attachment_invalid_type_message'] = 'Sorry, but the file type you tried to upload is not allowed.'; -$hesklang['attachment_upload_error'] = 'An error occurred when trying to upload. Please try again later.'; -$hesklang['attachment_too_large'] = 'This attachment is larger than the max filesize permitted.'; -$hesklang['attachment_cancel'] = 'Cancel'; -$hesklang['attachment_confirm_cancel'] = 'Are you sure you want to cancel this upload?'; -$hesklang['attachment_remove'] = 'Remove attachment'; -$hesklang['due_date'] = 'Due Date'; -$hesklang['category_updated'] = 'Changes to %s have been saved'; -$hesklang['new_event'] = 'New Event'; -$hesklang['create_event'] = 'Create Event'; -$hesklang['event_title'] = 'Title'; -$hesklang['event_title_tooltip'] = 'The title of the event'; -$hesklang['event_location'] = 'Location'; -$hesklang['event_location_tooltip'] = 'The location of the event'; -$hesklang['event_category_tooltip'] = 'Category for the event'; -$hesklang['event_start'] = 'Start'; -$hesklang['event_start_tooltip'] = 'The starting date (and time) of the event'; -$hesklang['event_start_date'] = 'Start Date'; -$hesklang['event_start_time'] = 'Start Time'; -$hesklang['event_all_day'] = 'All day'; -$hesklang['event_end'] = 'End'; -$hesklang['event_end_tooltip'] = 'The ending date (and time) of the event'; -$hesklang['event_end_date'] = 'End Date'; -$hesklang['event_end_time'] = 'End Time'; -$hesklang['event_reminder'] = 'Reminder'; -$hesklang['event_reminder_tooltip'] = 'Receive an e-mail reminder for this event. Only you will receive this reminder email.'; -$hesklang['event_min_before_event'] = 'minutes before event'; -$hesklang['event_hours_before_event'] = 'hours before event'; -$hesklang['event_days_before_event'] = 'days before event'; -$hesklang['event_weeks_before_event'] = 'weeks before event'; -$hesklang['event_comments'] = 'Comments'; -$hesklang['event_comments_tooltip'] = 'Additional comments about the event'; -$hesklang['event_create_ticket'] = 'Create Ticket'; -$hesklang['to_title_case'] = 'To'; -$hesklang['clear_for_no_due_date'] = 'Clear for no due date'; -$hesklang['ticket_due_date_updated'] = 'Ticket due date successfully updated'; -$hesklang['error_updating_ticket_due_date'] = 'An error occurred when trying to update the ticket due date'; -$hesklang['error_loading_events'] = 'An error occurred when trying to load events'; -$hesklang['error_deleting_event'] = 'An error occurred when trying to delete the event'; -$hesklang['event_deleted'] = 'Event successfully deleted'; -$hesklang['event_created'] = 'Event successfully created'; -$hesklang['error_creating_event'] = 'An error occurred when trying to create the event'; -$hesklang['event_updated'] = 'Event successfully updated'; -$hesklang['error_updating_event'] = 'An error occurred when trying to update the event'; -$hesklang['calendar_title_case'] = 'Calendar'; -$hesklang['calendar_categories'] = 'Categories'; -$hesklang['can_man_calendar'] = 'Can manage calendar events'; -$hesklang['calendar_reminder'] = 'Upcoming Event: %%TITLE%%'; -$hesklang['overdue_ticket'] = '[%%TRACKID%%] Ticket Overdue!'; -$hesklang['notify_overdue_unassigned'] = 'A ticket is overdue not assigned to me'; -$hesklang['calendar_settings'] = 'Calendar Settings'; -$hesklang['enable_calendar'] = 'Enable calendar'; -$hesklang['enable_calendar_help'] = 'Setting to enable / disable the calendar. The calendar can be shown to everyone, staff only, or disable the calendar entirely.'; -$hesklang['yes_enable_calendar'] = 'YES, enable calendar'; -$hesklang['yes_enable_calendar_staff_only'] = 'YES, enable calendar, but only for staff'; -$hesklang['no_disable_calendar'] = 'NO, disable calendar'; -$hesklang['first_day_of_week'] = 'First day of week'; -$hesklang['first_day_of_week_help'] = 'This setting decides which day of the week to show first per week.'; -$hesklang['calendar_disabled'] = 'The calendar is disabled'; -$hesklang['default_view'] = 'Default Calendar View'; -$hesklang['default_view_help'] = 'Decide which view will be shown to customers and staff by default when viewing the calendar. Staff can change this setting via their own profile.'; -$hesklang['week'] = 'Week'; -$hesklang['calendar_day'] = 'Day'; -$hesklang['calendar_index'] = 'View upcoming events'; -$hesklang['usage'] = 'Usage'; -$hesklang['tickets_and_events'] = 'Tickets and events'; -$hesklang['tickets_only'] = 'Tickets only'; -$hesklang['events_only'] = 'Events only'; -$hesklang['events'] = 'Events'; -$hesklang['add_files'] = ' Add File'; -$hesklang['select_all_title_case'] = 'Select All'; -$hesklang['deselect_all_title_case'] = 'Deselect All'; -$hesklang['event'] = 'Event'; -$hesklang['overdue_ticket_legend'] = 'Overdue ticket'; -$hesklang['attachment_max_exceeded'] = 'This file will not be uploaded becuase you have already uploaded the maximum number of files allowed.'; - -// ADDED OR MODIFIED IN Mods for HESK 3.0.0 -$hesklang['you_have_x_messages'] = 'You have %s new %s'; // %s: Number of new messages, "message" or "messages", depending on # -$hesklang['message_lower_case'] = 'message'; -$hesklang['messages_lower_case'] = 'messages'; -$hesklang['deleted_user_title_case'] = 'Deleted User'; -$hesklang['x_system_warnings'] = '%s System %s'; // %s: Number of warnings, $s: "Warning" or "Warnings", depending on # -$hesklang['warnings_title_case'] = 'Warnings'; -$hesklang['articles_in_category_x'] = 'Articles in Category %s'; // %s: category name -$hesklang['private_category_star'] = 'Private categories indicated by *'; -$hesklang['private_article_star'] = 'Private articles indicated by *'; -$hesklang['ticket_details'] = 'Ticket Details'; -$hesklang['more'] = 'More'; -$hesklang['click_to_edit'] = 'Click to edit'; -$hesklang['no_device_information'] = 'No device information'; -$hesklang['message_colon'] = 'Message:'; -$hesklang['original_message'] = 'Original message'; -$hesklang['reply_by_customer'] = 'Reply by customer'; -$hesklang['reply_by_staff'] = 'Reply by staff'; -$hesklang['timeline_today'] = 'Today'; -$hesklang['no_notes_for_this_ticket'] = 'No notes for this ticket'; -$hesklang['private_message_header'] = 'Private Message'; -$hesklang['date_colon'] = 'Date:'; -$hesklang['api_information'] = 'API Information'; -$hesklang['api_version'] = 'API Version'; -$hesklang['external_api'] = 'External API'; -$hesklang['external_api_help'] = 'Enable or Disable the external REST API'; -$hesklang['disabled_title_case'] = 'Disabled'; -$hesklang['enabled_title_case'] = 'Enabled'; -$hesklang['api_settings'] = 'API Settings'; -$hesklang['user_security'] = 'User Security'; -$hesklang['api_documentation'] = 'API Documentation'; -$hesklang['changes_saved'] = 'Changes saved!'; -$hesklang['save_failed_check_logs'] = 'Saving changes failed. Check the logs for more information.'; -$hesklang['number_of_tokens'] = 'Number of Tokens'; -$hesklang['generate_new_token'] = 'Generate New Token'; -$hesklang['revoke_all_tokens'] = 'Revoke All Tokens'; -$hesklang['generated_token_colon'] = 'Generated Token:'; -$hesklang['record_this_token_warning'] = 'Please record this token, as this is the only time you will be able to view it!'; -$hesklang['all_tokens_revoked'] = 'All tokens for this user have been revoked'; -$hesklang['staff_login_title'] = 'Staff Login'; -$hesklang['manage_custom_fields'] = 'Manage Custom Fields'; -$hesklang['value'] = 'Value'; -$hesklang['readonly'] = 'Readonly'; -$hesklang['copy_ticket'] = 'Copy Ticket'; -$hesklang['canned_responses_dropdown_title'] = 'Canned Responses'; -$hesklang['helpdesk_settings'] = 'Helpdesk Settings'; -$hesklang['click_to_toggle'] = 'Click to toggle'; -$hesklang['see_all_messages'] = 'See All Messages'; - -// ADDED OR MODIFIED IN Mods for HESK 3.1.0 -$hesklang['stack_trace_header'] = 'Stack Trace'; -$hesklang['ticket_message_contents_exist'] = 'The ticket message is not empty. Are you sure you want to leave this page?'; -$hesklang['resend_email_notification'] = 'Re-send Email Notification'; -$hesklang['email_notification_sent'] = 'Email notification sent!'; -$hesklang['email_notification_resend_failed'] = 'Error occurred when trying to send notification email.'; -$hesklang['edit_category'] = 'Edit Category'; -$hesklang['custom_nav_menu_elements'] = 'Custom Nav Menu Elements'; -$hesklang['create_new'] = 'Create New'; -$hesklang['custom_nav_element_deleted'] = 'Custom Navigation Element Deleted!'; -$hesklang['no_custom_nav_elements_found'] = 'No custom nav menu elements found'; -$hesklang['alert_success'] = 'Success'; // Used for alert messages -$hesklang['alert_error'] = 'Error'; // Used for alert messages -$hesklang['failed_to_load_custom_nav_elements'] = 'Failed to load custom nav elements!'; -$hesklang['custom_nav_element_deleted'] = 'Custom nav element deleted!'; -$hesklang['error_deleting_custom_nav_element'] = 'Error deleting custom nav element!'; -$hesklang['error_sorting_custom_nav_elements'] = 'Error sorting custom nav elements!'; -$hesklang['custom_nav_element_created'] = 'Custom nav element created!'; -$hesklang['custom_nav_element_saved'] = 'Custom nav element saved!'; -$hesklang['homepage_block'] = 'Homepage - Block'; -$hesklang['customer_navigation'] = 'Customer Navigation'; -$hesklang['staff_navigation'] = 'Staff Navigation'; -$hesklang['custom_nav_text'] = 'Text'; -$hesklang['custom_nav_subtext'] = 'Subtext'; -$hesklang['image_url_slash_font_icon'] = 'Image URL / Font Icon'; -$hesklang['edit_custom_nav_element_title_case'] = 'Edit Custom Nav Element'; -$hesklang['create_custom_nav_element_title_case'] = 'Create Custom Nav Element'; -$hesklang['place'] = 'Place'; -$hesklang['image_type'] = 'Image Type'; -$hesklang['image_url'] = 'Image URL'; -$hesklang['image_url_help'] = 'The URL of the image you wish to use. For customer/staff navigation, recommended size is 16x16px. For the homepage blocks, recommended size is 32x32px.'; -$hesklang['font_icon'] = 'Font Icon'; -$hesklang['error_saving_custom_nav_element'] = 'Error saving custom nav element!'; -$hesklang['place_help'] = 'The location of the custom navigation element.'; -$hesklang['url_help'] = 'The URL where the user should be taken to. Both relative and absolute URLs are supported.'; -$hesklang['common_properties'] = 'Common Properties'; -$hesklang['customer_view'] = 'Customer View'; -$hesklang['admin_panel'] = 'Admin Panel'; -$hesklang['manage_custom_nav_elements'] = 'Manage Custom Nav Elements'; -$hesklang['can_man_custom_nav'] = 'Can manage custom nav elements'; -$hesklang['category_background_color'] = 'Background Color'; -$hesklang['category_foreground_color'] = 'Foreground Color'; -$hesklang['category_background_color_help'] = 'The hex code for the background color to be used on the view ticket screen and calendar.'; -$hesklang['category_foreground_color_help'] = 'The hex code for the foreground color to be used on the view ticket and calendar screens. Leave blank for automatic color based on background.'; -$hesklang['category_display_border'] = 'Display Border'; -$hesklang['category_display_border_help'] = 'Choose to decide whether or not to display a border around the category (uses foreground color). -This is ignored if foreground color is set to automatic.'; -$hesklang['login_page'] = 'Login Page'; // Header on admin settings page -$hesklang['login_background'] = 'Login Background'; -$hesklang['solid_color'] = 'Solid color'; -$hesklang['login_background_color'] = 'Login Background Color'; // Input field information for screen-readers. Does not appear on-screen -$hesklang['login_background_image'] = 'Login Background Image'; // Input field information for screen-readers. Does not appear on-screen -$hesklang['login_box_header'] = 'Login Box Header'; -$hesklang['login_header_image'] = 'Login Header Image'; // Input field information for screen-readers. Does not appear on-screen -$hesklang['background_color'] = 'Background Color'; -$hesklang['background_color_help'] = 'The background color.'; -$hesklang['text_color'] = 'Text Color'; -$hesklang['text_color_help'] = 'The text color'; -$hesklang['text_hover_color'] = 'Hover Color: Text'; -$hesklang['text_hover_color_help'] = 'The text color when hovering over a link'; -$hesklang['background_hover_color'] = 'Hover Color: Background'; -$hesklang['background_hover_color_help'] = 'The background color when hovering over a link'; -$hesklang['navbar'] = 'Navigation Bar'; -$hesklang['navbar_brand'] = 'Navigation Brand'; -$hesklang['sidebar'] = 'Sidebar'; -$hesklang['sidebar_header'] = 'Sidebar Header'; -$hesklang['font_weight'] = 'Font Weight'; -$hesklang['font_weight_help'] = 'The font weight for text'; -$hesklang['normal'] = 'Normal'; -$hesklang['bold'] = 'Bold'; -$hesklang['color_preset'] = 'Color Preset'; -$hesklang['color_preset_help'] = 'Select a color preset for the backend, or define custom colors below.'; -$hesklang['select_a_preset'] = '-- Select a Preset --'; -$hesklang['preset_blue'] = 'Blue'; -$hesklang['preset_blue_light'] = 'Blue (light)'; -$hesklang['preset_yellow'] = 'Yellow'; -$hesklang['preset_yellow_light'] = 'Yellow (light)'; -$hesklang['preset_green'] = 'Green'; -$hesklang['preset_green_light'] = 'Green (light)'; -$hesklang['preset_purple'] = 'Purple'; -$hesklang['preset_purple_light'] = 'Purple (light)'; -$hesklang['preset_red'] = 'Red'; -$hesklang['preset_red_light'] = 'Red (light)'; -$hesklang['preset_black'] = 'Black'; -$hesklang['preset_black_light'] = 'Black (light)'; -$hesklang['url_rewrite'] = 'URL Rewrite'; -$hesklang['url_rewrite_help'] = 'Remove the need to include /index.php in API URLs (i.e. /api/index.php/v1/... -> /api/v1/...). Rename htaccess.txt to .htaccess in the /api folder to use.'; -$hesklang['url_rewrite_saved'] = 'URL rewrite setting saved!'; -$hesklang['api_settings_saved'] = 'API settings saved!'; -$hesklang['an_error_occurred'] = 'An error occurred. Check the logs for more information'; - -// Added or modified in Mods for HESK 3.2.0 -$hesklang['error_deleting_category'] = 'An error occurred when trying to delete the category.'; -$hesklang['cat_private'] = 'Private'; -$hesklang['cat_public'] = 'Public'; -$hesklang['cat_name_description'] = 'Name / Description'; -$hesklang['error_sorting_categories'] = 'An error occurred sorting categories!'; -$hesklang['error_retrieving_categories'] = 'An error occurred retrieving categories!'; -$hesklang['error_saving_updating_category'] = 'An error occurred creating / saving the category!'; -$hesklang['description_colon'] = 'Description:'; // Same as 'description', but with a colon (:) afterwards -$hesklang['copied_to_clipboard'] = 'Copied to clipboard'; - -// Language for the calendar pages -// Supported language codes: https://github.com/fullcalendar/fullcalendar/tree/v3.0.1/locale (do not include .js!) -// If your language is NOT in the supported langauges, leave 'en' -$hesklang['CALENDAR_LANGUAGE']='en'; - - -$hesklang['manage_permission_groups'] = 'Manage Permission Groups'; -$hesklang['manage_permission_groups_help'] = 'Here you can create and edit permission groups. These groups will appear when creating/editing a user. -When editing a permission group, all users assigned to this group will also have their permissions updated accordingly.'; -$hesklang['view_permissions_for_this_group'] = 'View/edit permissions for this group'; -$hesklang['permission'] = 'Permission'; -$hesklang['permissions_for_group'] = 'Permissions for group %s'; // %s template name -$hesklang['permission_group_updated'] = 'Permission group has been updated!'; -$hesklang['create_new_group'] = 'Create new permission group'; -$hesklang['create_new_group_title'] = 'Create New Permission Group'; // same as create_new_template, but in Title Case -$hesklang['group_name'] = 'Group name'; -$hesklang['group_name_required'] = 'Group name required.'; -$hesklang['permission_group_error'] = 'The permission group could not be saved due to the following error(s): %s'; // %s: error list -$hesklang['group_created'] = 'Permission group successfully created!'; -$hesklang['cannot_delete_admin_or_staff'] = 'The Administrator and Staff permission groups cannot be deleted!'; -$hesklang['no_groups_were_deleted'] = 'No groups were deleted!'; -$hesklang['permission_group_deleted'] = 'Permission group deleted!'; -$hesklang['manange_permission_groups_menu'] = 'Permission groups'; // Menu link -$hesklang['permission_groups'] = 'Permission Groups'; -$hesklang['can_man_permission_tpl'] = 'Can manage permission groups'; -$hesklang['permission_group_colon'] = 'Permission Group:'; -$hesklang['permission_group'] = 'Permission Group'; -$hesklang['changing_permissions_will_reset_permission_group'] = 'Changing a user\'s categories / features will reset their permission group! Click "Discard Changes" to reset the user\'s categories / features.'; - -// --> Ticket audit trail -$hesklang['audit_moved_category']='%s moved ticket to category %s'; // %s = new category, user making change, thist1 -$hesklang['audit_assigned']='%s assigned ticket to %s'; // %s = assigned user, user making change -$hesklang['audit_assigned_self'] = '%s self-assigned ticket'; -$hesklang['audit_unassigned'] = '%s unassigned ticket'; -$hesklang['audit_closed']='%s closed ticket'; // thist3 -$hesklang['audit_automatically_closed'] ='Ticket automatically closed'; -$hesklang['audit_opened']='%s opened ticket'; // thist4 -$hesklang['audit_locked']='%s locked ticket'; // thist5 -$hesklang['audit_automatically_locked'] = 'Ticket automatically locked'; -$hesklang['audit_unlocked']='%s unlocked ticket'; // thist6 -$hesklang['audit_created']='%s created ticket'; -$hesklang['audit_priority']='%s changed priority to %s'; // %s = date,new priority, user making change, thist8 -$hesklang['audit_status']='%s changed status to %s'; // %s = date, new status, user making change, thist9 -$hesklang['audit_autoassigned']='%s automatically assigned to ticket'; //thist10 -$hesklang['audit_submitted_via_piping']='Ticket submitted via e-mail piping'; // thist11 -$hesklang['audit_attachment_deleted']='%s deleted attachment %s'; // %s = date, deleted attachment, user making change -$hesklang['audit_merged']='%s merged ticket %s with this ticket'; // %s = date, merged ticket ID, user making change, thist13 -$hesklang['audit_time_worked']='%s updated time worked to %s'; // %s = date, new time worked, user making change -$hesklang['audit_submitted_by']='%s submitted ticket'; -$hesklang['audit_submitted_via_pop']='Ticket submitted via POP3 fetching'; // thist16 -$hesklang['audit_due_date_removed'] = '%s removed due date'; -$hesklang['audit_due_date_changed'] = '%s changed due date to %s'; -$hesklang['audit_linked_ticket'] = '%s linked ticket %s to this ticket'; -$hesklang['audit_unlinked_ticket'] = '%s unlinked ticket %s'; - -// Added or modified in Mods for HESK 3.3.0 -$hesklang['audit_event_created'] = '%s created event'; -$hesklang['audit_event_updated'] = '%s updated event'; -$hesklang['error_retrieving_sm'] = 'An error occurred retrieving service messages!'; -$hesklang['error_saving_updating_sm'] = 'An error occurred creating / saving the service message!'; -$hesklang['error_deleting_sm'] = 'An error occurred when trying to delete the service message.'; -$hesklang['error_sorting_sm'] = 'An error occurred sorting service messages!'; -$hesklang['sm_location'] = 'Location'; // Location for service messages -$hesklang['sm_customer_pages'] = 'Customer Pages'; -$hesklang['sm_staff_pages'] = 'Staff Pages'; -$hesklang['sm_homepage'] = 'Homepage'; -$hesklang['sm_kb_home'] = 'Knowledgebase Home'; -$hesklang['sm_view_kb_article'] = 'View Knowledgebase Article'; -$hesklang['sm_submit_ticket'] = 'Submit Ticket'; -$hesklang['sm_view_ticket'] = 'View Ticket'; -$hesklang['sm_login_page'] = 'Login Page'; -$hesklang['business_hours'] = 'Business Hours'; -$hesklang['business_hours_help'] = 'Set business hours for the calendar. There is no functional change by setting this, -but times outside of the defined business hours will have a darker gray background for increased visibility.'; -$hesklang['show_event_start_time'] = 'Show event start time in title'; -$hesklang['show_event_start_time_help'] = 'Always show the start time on event titles (unless the event is an all-day event).'; -$hesklang['highlight_ticket_rows_based_on_priority'] = 'Highlight ticket rows based on priority'; -$hesklang['highlight_ticket_rows_based_on_priority_help'] = 'If enabled, each ticket on the tickets page will be highlighted based on priority. If disabled, only * Critical * and High priority tickets will be highlighted.'; -$hesklang['highlight_ticket_rows_based_on_priority_descr'] = 'Highlight all ticket rows based on priority'; -$hesklang['protected_group'] = 'This is a protected group; you cannot change accessible categories / features.'; -$hesklang['emails_to_receive'] = 'Emails to receive'; -$hesklang['emails_sent_to_staff'] = 'Emails sent to staff'; -$hesklang['emails_sent_to_customer'] = 'Emails sent to customer'; - // DO NOT CHANGE BELOW -if (!defined('IN_SCRIPT')) die('PHP syntax OK!'); +if (!defined('IN_SCRIPT')) die('PHP syntax OK!'); \ No newline at end of file From 669edf832ce718f526751584980eea84fbb1bf6f Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 8 Apr 2018 22:07:13 -0400 Subject: [PATCH 02/76] Starting to work on reply API endpoint --- api/BusinessLogic/Helpers.php | 43 +++++++++++++ .../Tickets/CreateReplyRequest.php | 12 ++++ api/BusinessLogic/Tickets/ReplyCreator.php | 60 +++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 api/BusinessLogic/Tickets/CreateReplyRequest.php create mode 100644 api/BusinessLogic/Tickets/ReplyCreator.php diff --git a/api/BusinessLogic/Helpers.php b/api/BusinessLogic/Helpers.php index b841fd27..f356bfbb 100644 --- a/api/BusinessLogic/Helpers.php +++ b/api/BusinessLogic/Helpers.php @@ -34,4 +34,47 @@ class Helpers extends \BaseClass { static function heskHtmlSpecialCharsDecode($in) { return str_replace(array('&', '<', '>', '"'), array('&', '<', '>', '"'), $in); } + + static function heskMakeUrl($text, $class = '', $shortenLinks = true) { + if (!defined('MAGIC_URL_EMAIL')) { + define('MAGIC_URL_EMAIL', 1); + define('MAGIC_URL_FULL', 2); + define('MAGIC_URL_LOCAL', 3); + define('MAGIC_URL_WWW', 4); + } + + $class = ($class) ? ' class="' . $class . '"' : ''; + + // matches a xxxx://aaaaa.bbb.cccc. ... + $text = preg_replace_callback( + '#(^|[\n\t (>.])(' . "[a-z][a-z\d+]*:/{2}(?:(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?" . ')#iu', + create_function( + "\$matches", + "return make_clickable_callback(MAGIC_URL_FULL, \$matches[1], \$matches[2], '', '$class', '$shortenLinks');" + ), + $text + ); + + // matches a "www.xxxx.yyyy[/zzzz]" kinda lazy URL thing + $text = preg_replace_callback( + '#(^|[\n\t (>])(' . "www\.(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})+(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?" . ')#iu', + create_function( + "\$matches", + "return make_clickable_callback(MAGIC_URL_WWW, \$matches[1], \$matches[2], '', '$class', '$shortenLinks');" + ), + $text + ); + + // matches an email address + $text = preg_replace_callback( + '/(^|[\n\t (>])(' . '((?:[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&)+)@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)' . ')/iu', + create_function( + "\$matches", + "return make_clickable_callback(MAGIC_URL_EMAIL, \$matches[1], \$matches[2], '', '$class', '$shortenLinks');" + ), + $text + ); + + return $text; + } } \ No newline at end of file diff --git a/api/BusinessLogic/Tickets/CreateReplyRequest.php b/api/BusinessLogic/Tickets/CreateReplyRequest.php new file mode 100644 index 00000000..e0d5bcd6 --- /dev/null +++ b/api/BusinessLogic/Tickets/CreateReplyRequest.php @@ -0,0 +1,12 @@ +statusGateway = $statusGateway; + $this->ticketGateway = $ticketGateway; + $this->emailSenderHelper = $emailSenderHelper; + $this->userGateway = $userGateway; + $this->auditTrailGateway = $auditTrailGateway; + } + + /** + * @param $replyRequest CreateReplyRequest + * @param $heskSettings array + * @param $modsForHeskSettings array + * @param $userContext UserContext + * @throws ApiFriendlyException + */ + function createReplyByCustomer($replyRequest, $heskSettings, $modsForHeskSettings, $userContext) { + $ticket = $this->ticketGateway->getTicketByTrackingId($replyRequest->trackingId, $heskSettings); + + if ($ticket === null) { + throw new ApiFriendlyException("Ticket with tracking ID {$replyRequest->trackingId} not found.", + "Ticket not found", 404); + } + + $validationModel = new ValidationModel(); + if (!strlen($replyRequest->replyMessage)) { + $validationModel->errorKeys[] = 'MESSAGE_REQUIRED'; + } + + if ($modsForHeskSettings['rich_text_for_tickets_for_customers']) { + $replyRequest->replyMessage = Helpers::heskMakeUrl($replyRequest->replyMessage); + $replyRequest->replyMessage = nl2br($replyRequest->replyMessage); + } + } +} \ No newline at end of file From 9ae259dff68eecaa0cdd126c641c6a91d167ba91 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 9 Apr 2018 13:01:49 -0400 Subject: [PATCH 03/76] Working on reply endpoint. Just need to send out the email. --- .../Tickets/CreateReplyRequest.php | 1 + api/BusinessLogic/Tickets/ReplyCreator.php | 48 ++++++++++++++++++- .../Tickets/CustomerReplyController.php | 24 ++++++++++ api/DataAccess/Security/LoginGateway.php | 24 ++++++++++ api/DataAccess/Statuses/StatusGateway.php | 18 +++++++ api/DataAccess/Tickets/ReplyGateway.php | 17 +++++++ api/DataAccess/Tickets/TicketGateway.php | 30 ++++++++++++ api/index.php | 1 + 8 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 api/Controllers/Tickets/CustomerReplyController.php create mode 100644 api/DataAccess/Security/LoginGateway.php create mode 100644 api/DataAccess/Tickets/ReplyGateway.php diff --git a/api/BusinessLogic/Tickets/CreateReplyRequest.php b/api/BusinessLogic/Tickets/CreateReplyRequest.php index e0d5bcd6..b66febce 100644 --- a/api/BusinessLogic/Tickets/CreateReplyRequest.php +++ b/api/BusinessLogic/Tickets/CreateReplyRequest.php @@ -4,6 +4,7 @@ namespace BusinessLogic\Tickets; class CreateReplyRequest { + public $ticketId; public $trackingId; public $emailAddress; public $replyMessage; diff --git a/api/BusinessLogic/Tickets/ReplyCreator.php b/api/BusinessLogic/Tickets/ReplyCreator.php index cfbf74a0..d43eeb5f 100644 --- a/api/BusinessLogic/Tickets/ReplyCreator.php +++ b/api/BusinessLogic/Tickets/ReplyCreator.php @@ -4,13 +4,19 @@ namespace BusinessLogic\Tickets; use BusinessLogic\Emails\EmailSenderHelper; +use BusinessLogic\Emails\EmailTemplateRetriever; use BusinessLogic\Exceptions\ApiFriendlyException; +use BusinessLogic\Exceptions\ValidationException; use BusinessLogic\Helpers; use BusinessLogic\Security\UserContext; +use BusinessLogic\Statuses\Closable; +use BusinessLogic\Statuses\DefaultStatusForAction; use BusinessLogic\ValidationModel; use DataAccess\AuditTrail\AuditTrailGateway; +use DataAccess\Security\LoginGateway; use DataAccess\Security\UserGateway; use DataAccess\Statuses\StatusGateway; +use DataAccess\Tickets\ReplyGateway; use DataAccess\Tickets\TicketGateway; class ReplyCreator { @@ -19,17 +25,23 @@ class ReplyCreator { private $emailSenderHelper; private $userGateway; private $auditTrailGateway; + private $loginGateway; + private $replyGateway; public function __construct(StatusGateway $statusGateway, TicketGateway $ticketGateway, EmailSenderHelper $emailSenderHelper, UserGateway $userGateway, - AuditTrailGateway $auditTrailGateway) { + AuditTrailGateway $auditTrailGateway, + LoginGateway $loginGateway, + ReplyGateway $replyGateway) { $this->statusGateway = $statusGateway; $this->ticketGateway = $ticketGateway; $this->emailSenderHelper = $emailSenderHelper; $this->userGateway = $userGateway; $this->auditTrailGateway = $auditTrailGateway; + $this->loginGateway = $loginGateway; + $this->replyGateway = $replyGateway; } /** @@ -38,6 +50,7 @@ class ReplyCreator { * @param $modsForHeskSettings array * @param $userContext UserContext * @throws ApiFriendlyException + * @throws \Exception */ function createReplyByCustomer($replyRequest, $heskSettings, $modsForHeskSettings, $userContext) { $ticket = $this->ticketGateway->getTicketByTrackingId($replyRequest->trackingId, $heskSettings); @@ -50,11 +63,44 @@ class ReplyCreator { $validationModel = new ValidationModel(); if (!strlen($replyRequest->replyMessage)) { $validationModel->errorKeys[] = 'MESSAGE_REQUIRED'; + + throw new ValidationException($validationModel); } if ($modsForHeskSettings['rich_text_for_tickets_for_customers']) { $replyRequest->replyMessage = Helpers::heskMakeUrl($replyRequest->replyMessage); $replyRequest->replyMessage = nl2br($replyRequest->replyMessage); } + + if ($this->loginGateway->isIpLockedOut($replyRequest->ipAddress, $heskSettings)) { + throw new ApiFriendlyException("The IP address entered has been locked out of the system for {$heskSettings['attempt_banmin']} minutes because of too many login failures", + "Locked Out", + 403); + } + + if ($this->ticketGateway->areRepliesBeingFlooded($replyRequest->ticketId, $replyRequest->ipAddress, $heskSettings)) { + throw new ApiFriendlyException("You have been locked out of the system for {$heskSettings['attempt_banmin']} minutes because of too many replies to a ticket.", + "Locked Out", + 403); + } + + // If staff hasn't replied yet, don't change the status; otherwise set it to the status for customer replies + $currentStatus = $this->statusGateway->getStatusById($ticket->statusId, $heskSettings); + if ($currentStatus->closable === Closable::YES || $currentStatus->closable === Closable::CUSTOMERS_ONLY) { + $customerReplyStatus = $this->statusGateway->getStatusForDefaultAction(DefaultStatusForAction::CUSTOMER_REPLY, $heskSettings); + $defaultNewTicketStatus = $this->statusGateway->getStatusForDefaultAction(DefaultStatusForAction::NEW_TICKET, $heskSettings); + + $ticket->statusId = $ticket->statusId === $defaultNewTicketStatus->id ? + $defaultNewTicketStatus->id : + $customerReplyStatus->id; + } + + $this->ticketGateway->updateMetadataForReply($ticket->id, $ticket->statusId, $heskSettings); + $this->replyGateway->insertReply($ticket->id, $ticket->name, $replyRequest->replyMessage, $replyRequest->hasHtml, $heskSettings); + + //-- Changing the ticket message to the reply's + $ticket->message = $replyRequest->replyMessage; + + // TODO Send the email. } } \ No newline at end of file diff --git a/api/Controllers/Tickets/CustomerReplyController.php b/api/Controllers/Tickets/CustomerReplyController.php new file mode 100644 index 00000000..d5ffe113 --- /dev/null +++ b/api/Controllers/Tickets/CustomerReplyController.php @@ -0,0 +1,24 @@ +id = $ticketId; + $createReplyByCustomerModel->emailAddress = Helpers::safeArrayGet($jsonRequest, 'email'); + $createReplyByCustomerModel->trackingId = Helpers::safeArrayGet($jsonRequest, 'trackingId'); + $createReplyByCustomerModel->replyMessage = Helpers::safeArrayGet($jsonRequest, 'message'); + $createReplyByCustomerModel->hasHtml = Helpers::safeArrayGet($jsonRequest, 'html'); + $createReplyByCustomerModel->ipAddress = Helpers::safeArrayGet($jsonRequest, 'ip'); + } +} diff --git a/api/DataAccess/Security/LoginGateway.php b/api/DataAccess/Security/LoginGateway.php new file mode 100644 index 00000000..461eb62d --- /dev/null +++ b/api/DataAccess/Security/LoginGateway.php @@ -0,0 +1,24 @@ +init(); + + $rs = hesk_dbQuery("SELECT `number` FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "logins` + WHERE `ip` = '" . hesk_dbEscape($ipAddress) . "' + AND `last_attempt` IS NOT NULL + AND DATE_ADD(`last_attempt`, INTERVAL ".intval($heskSettings['attempt_banmin'])." MINUTE ) > NOW() LIMIT 1"); + + $result = hesk_dbNumRows($rs) == 1 && + hesk_dbResult($rs) >= $heskSettings['attempt_limit']; + + $this->close(); + + return $result; + } +} \ No newline at end of file diff --git a/api/DataAccess/Statuses/StatusGateway.php b/api/DataAccess/Statuses/StatusGateway.php index c18e9b19..a44d8d6b 100644 --- a/api/DataAccess/Statuses/StatusGateway.php +++ b/api/DataAccess/Statuses/StatusGateway.php @@ -53,4 +53,22 @@ class StatusGateway extends CommonDao { return $statuses; } + + function getStatusById($id, $heskSettings) { + $this->init(); + + $metaRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "statuses` WHERE `ID` = " . $id); + + $status = null; + if ($row = hesk_dbFetchAssoc($metaRs)) { + $languageRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "text_to_status_xref` + WHERE `status_id` = " . intval($row['ID'])); + + $status = Status::fromDatabase($row, $languageRs); + } + + $this->close(); + + return $status; + } } \ No newline at end of file diff --git a/api/DataAccess/Tickets/ReplyGateway.php b/api/DataAccess/Tickets/ReplyGateway.php new file mode 100644 index 00000000..399586f5 --- /dev/null +++ b/api/DataAccess/Tickets/ReplyGateway.php @@ -0,0 +1,17 @@ +init(); + + hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($heskSettings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`, `html`) + VALUES ({$ticketId},'" . hesk_dbEscape($name) . "','" . hesk_dbEscape($message) . "',NOW(),'','" . $html . "')"); + + $this->close(); + } +} \ No newline at end of file diff --git a/api/DataAccess/Tickets/TicketGateway.php b/api/DataAccess/Tickets/TicketGateway.php index 2ea5a84d..62a40558 100644 --- a/api/DataAccess/Tickets/TicketGateway.php +++ b/api/DataAccess/Tickets/TicketGateway.php @@ -454,4 +454,34 @@ class TicketGateway extends CommonDao { $this->close(); } + + function areRepliesBeingFlooded($id, $ip, $heskSettings) { + $this->init(); + + $result = false; + $res = hesk_dbQuery("SELECT `staffid` FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "replies` WHERE `replyto`='{$id}' AND `dt` > DATE_SUB(NOW(), INTERVAL 10 MINUTE) ORDER BY `id` ASC"); + if (hesk_dbNumRows($res) > 0) { + $sequential_customer_replies = 0; + while ($tmp = hesk_dbFetchAssoc($res)) { + $sequential_customer_replies = $tmp['staffid'] ? 0 : $sequential_customer_replies + 1; + } + + if ($sequential_customer_replies > 10) { + hesk_dbQuery("INSERT INTO `".hesk_dbEscape($heskSettings['db_pfix'])."logins` (`ip`, `number`) VALUES ('".hesk_dbEscape($ip)."', ".intval($heskSettings['attempt_limit'] + 1).")"); + $result = true; + } + } + + $this->close(); + + return $result; + } + + function updateMetadataForReply($id, $status, $heskSettings) { + $this->init(); + + hesk_dbQuery("UPDATE `" . hesk_dbEscape($heskSettings['db_pfix']) . "tickets` SET `lastchange`=NOW(), `status`='{$status}', `replies`=`replies`+1, `lastreplier`='0' WHERE `id`='{$id}'"); + + $this->close(); + } } \ No newline at end of file diff --git a/api/index.php b/api/index.php index ec493347..b991e91c 100644 --- a/api/index.php +++ b/api/index.php @@ -199,6 +199,7 @@ Link::all(array( '/v1-internal/categories/{i}/sort/{s}' => action(\Controllers\Categories\CategoryController::clazz() . '::sort', array(RequestMethod::POST), SecurityHandler::INTERNAL), // Tickets '/v1/tickets' => action(\Controllers\Tickets\CustomerTicketController::clazz(), RequestMethod::all(), SecurityHandler::OPEN), + '/v1/tickets/{i}/replies' => action(\Controllers\Tickets\CustomerReplyController::clazz(), array(RequestMethod::POST), SecurityHandler::OPEN), // Tickets - Staff '/v1/staff/tickets/{i}' => action(\Controllers\Tickets\StaffTicketController::clazz(), RequestMethod::all()), '/v1/staff/tickets/{i}/due-date' => action(\Controllers\Tickets\StaffTicketController::clazz() . '::updateDueDate', array(RequestMethod::PATCH), SecurityHandler::INTERNAL_OR_AUTH_TOKEN), From 6fa6c7b6863e847e41f05bf6203bb58f9857e905 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 10 Apr 2018 13:11:48 -0400 Subject: [PATCH 04/76] Add ability to reply via API --- api/BusinessLogic/Helpers.php | 131 ++++++++++++++++-- .../Tickets/CustomerCreatedReplyModel.php | 13 ++ api/BusinessLogic/Tickets/ReplyCreator.php | 51 ++++++- .../Tickets/CustomerReplyController.php | 12 ++ api/DataAccess/Security/UserGateway.php | 15 ++ api/DataAccess/Tickets/ReplyGateway.php | 16 +++ api/DataAccess/Tickets/TicketGateway.php | 4 +- 7 files changed, 222 insertions(+), 20 deletions(-) create mode 100644 api/BusinessLogic/Tickets/CustomerCreatedReplyModel.php diff --git a/api/BusinessLogic/Helpers.php b/api/BusinessLogic/Helpers.php index f356bfbb..ea92bc5c 100644 --- a/api/BusinessLogic/Helpers.php +++ b/api/BusinessLogic/Helpers.php @@ -48,33 +48,140 @@ class Helpers extends \BaseClass { // matches a xxxx://aaaaa.bbb.cccc. ... $text = preg_replace_callback( '#(^|[\n\t (>.])(' . "[a-z][a-z\d+]*:/{2}(?:(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?" . ')#iu', - create_function( - "\$matches", - "return make_clickable_callback(MAGIC_URL_FULL, \$matches[1], \$matches[2], '', '$class', '$shortenLinks');" - ), + function($matches) use ($class, $shortenLinks) { + return self::makeClickableCallback(MAGIC_URL_FULL, $matches[1], $matches[2], '', $class, $shortenLinks); + }, $text ); // matches a "www.xxxx.yyyy[/zzzz]" kinda lazy URL thing $text = preg_replace_callback( '#(^|[\n\t (>])(' . "www\.(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})+(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?" . ')#iu', - create_function( - "\$matches", - "return make_clickable_callback(MAGIC_URL_WWW, \$matches[1], \$matches[2], '', '$class', '$shortenLinks');" - ), + function($matches) use ($class, $shortenLinks) { + return self::makeClickableCallback(MAGIC_URL_WWW, $matches[1], $matches[2], '', $class, $shortenLinks); + }, $text ); // matches an email address $text = preg_replace_callback( '/(^|[\n\t (>])(' . '((?:[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&)+)@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)' . ')/iu', - create_function( - "\$matches", - "return make_clickable_callback(MAGIC_URL_EMAIL, \$matches[1], \$matches[2], '', '$class', '$shortenLinks');" - ), + function($matches) use ($class, $shortenLinks) { + return self::makeClickableCallback(MAGIC_URL_EMAIL, $matches[1], $matches[2], '', $class, $shortenLinks); + }, $text ); return $text; } + + static function makeClickableCallback($type, $whitespace, $url, $relative_url, $class, $shortenLinks) + { + global $hesk_settings; + + $orig_url = $url; + $orig_relative = $relative_url; + $append = ''; + $url = htmlspecialchars_decode($url); + $relative_url = htmlspecialchars_decode($relative_url); + + // make sure no HTML entities were matched + $chars = array('<', '>', '"'); + $split = false; + + foreach ($chars as $char) { + $next_split = strpos($url, $char); + if ($next_split !== false) { + $split = ($split !== false) ? min($split, $next_split) : $next_split; + } + } + + if ($split !== false) { + // an HTML entity was found, so the URL has to end before it + $append = substr($url, $split) . $relative_url; + $url = substr($url, 0, $split); + $relative_url = ''; + } else if ($relative_url) { + // same for $relative_url + $split = false; + foreach ($chars as $char) { + $next_split = strpos($relative_url, $char); + if ($next_split !== false) { + $split = ($split !== false) ? min($split, $next_split) : $next_split; + } + } + + if ($split !== false) { + $append = substr($relative_url, $split); + $relative_url = substr($relative_url, 0, $split); + } + } + + // if the last character of the url is a punctuation mark, exclude it from the url + $last_char = ($relative_url) ? $relative_url[strlen($relative_url) - 1] : $url[strlen($url) - 1]; + + switch ($last_char) { + case '.': + case '?': + case '!': + case ':': + case ',': + $append = $last_char; + if ($relative_url) { + $relative_url = substr($relative_url, 0, -1); + } else { + $url = substr($url, 0, -1); + } + break; + + // set last_char to empty here, so the variable can be used later to + // check whether a character was removed + default: + $last_char = ''; + break; + } + + $short_url = ($hesk_settings['short_link'] && strlen($url) > 70 && $shortenLinks) ? substr($url, 0, 54) . ' ... ' . substr($url, -10) : $url; + + switch ($type) { + case MAGIC_URL_LOCAL: + $tag = 'l'; + $relative_url = preg_replace('/[&?]sid=[0-9a-f]{32}$/', '', preg_replace('/([&?])sid=[0-9a-f]{32}&/', '$1', $relative_url)); + $url = $url . '/' . $relative_url; + $text = $relative_url; + + // this url goes to http://domain.tld/path/to/board/ which + // would result in an empty link if treated as local so + // don't touch it and let MAGIC_URL_FULL take care of it. + if (!$relative_url) { + return $whitespace . $orig_url . '/' . $orig_relative; // slash is taken away by relative url pattern + } + break; + + case MAGIC_URL_FULL: + $tag = 'm'; + $text = $short_url; + break; + + case MAGIC_URL_WWW: + $tag = 'w'; + $url = 'http://' . $url; + $text = $short_url; + break; + + case MAGIC_URL_EMAIL: + $tag = 'e'; + $text = $short_url; + $url = 'mailto:' . $url; + break; + } + + $url = htmlspecialchars($url); + $text = htmlspecialchars($text); + $append = htmlspecialchars($append); + + $html = "$whitespace$text$append"; + + return $html; + } // END make_clickable_callback() } \ No newline at end of file diff --git a/api/BusinessLogic/Tickets/CustomerCreatedReplyModel.php b/api/BusinessLogic/Tickets/CustomerCreatedReplyModel.php new file mode 100644 index 00000000..4b5bec2f --- /dev/null +++ b/api/BusinessLogic/Tickets/CustomerCreatedReplyModel.php @@ -0,0 +1,13 @@ +ticketGateway->getTicketByTrackingId($replyRequest->trackingId, $heskSettings); if ($ticket === null) { @@ -61,9 +61,19 @@ class ReplyCreator { } $validationModel = new ValidationModel(); - if (!strlen($replyRequest->replyMessage)) { + if ($replyRequest->replyMessage === null || trim($replyRequest->replyMessage) === '') { $validationModel->errorKeys[] = 'MESSAGE_REQUIRED'; + } + + if ($heskSettings['email_view_ticket']) { + if ($replyRequest->emailAddress === null || trim($replyRequest->emailAddress) === '') { + $validationModel->errorKeys[] = 'EMAIL_REQUIRED'; + } elseif (!in_array($replyRequest->emailAddress, $ticket->email)) { + $validationModel->errorKeys[] = 'EMAIL_NOT_FOUND_ON_TICKET'; + } + } + if (count($validationModel->errorKeys) > 0) { throw new ValidationException($validationModel); } @@ -96,11 +106,40 @@ class ReplyCreator { } $this->ticketGateway->updateMetadataForReply($ticket->id, $ticket->statusId, $heskSettings); - $this->replyGateway->insertReply($ticket->id, $ticket->name, $replyRequest->replyMessage, $replyRequest->hasHtml, $heskSettings); + $createdReply = $this->replyGateway->insertReply($ticket->id, $ticket->name, $replyRequest->replyMessage, $replyRequest->hasHtml, $heskSettings); //-- Changing the ticket message to the reply's $ticket->message = $replyRequest->replyMessage; - // TODO Send the email. + $addressees = new Addressees(); + if ($ticket->ownerId !== null && $ticket->ownerId !== 0) { + $owner = $this->userGateway->getUserById($ticket->ownerId, $heskSettings); + + if ($owner->notificationSettings->replyToMe) { + $addressees->to[] = $owner->email; + $language = $owner->language === null ? $heskSettings['language'] : $owner->language; + $this->emailSenderHelper->sendEmailForTicket(EmailTemplateRetriever::NEW_REPLY_BY_CUSTOMER, + $language, + $addressees, + $ticket, + $heskSettings, + $modsForHeskSettings); + } + } else { + $users = $this->userGateway->getUsersForUnassignedReplyNotification($heskSettings); + foreach ($users as $user) { + $addressees->to[] = $user->email; + $language = $user->language === null ? $heskSettings['language'] : $user->language; + + $this->emailSenderHelper->sendEmailForTicket(EmailTemplateRetriever::NEW_REPLY_BY_CUSTOMER, + $language, + $addressees, + $ticket, + $heskSettings, + $modsForHeskSettings); + } + } + + return $createdReply; } } \ No newline at end of file diff --git a/api/Controllers/Tickets/CustomerReplyController.php b/api/Controllers/Tickets/CustomerReplyController.php index d5ffe113..1ed31771 100644 --- a/api/Controllers/Tickets/CustomerReplyController.php +++ b/api/Controllers/Tickets/CustomerReplyController.php @@ -5,7 +5,9 @@ namespace Controllers\Tickets; use BusinessLogic\Helpers; use BusinessLogic\Tickets\CreateReplyRequest; +use BusinessLogic\Tickets\ReplyCreator; use Controllers\JsonRetriever; +use DataAccess\Settings\ModsForHeskSettingsGateway; class CustomerReplyController extends \BaseClass { function post($ticketId) { @@ -20,5 +22,15 @@ class CustomerReplyController extends \BaseClass { $createReplyByCustomerModel->replyMessage = Helpers::safeArrayGet($jsonRequest, 'message'); $createReplyByCustomerModel->hasHtml = Helpers::safeArrayGet($jsonRequest, 'html'); $createReplyByCustomerModel->ipAddress = Helpers::safeArrayGet($jsonRequest, 'ip'); + + /* @var $modsForHeskSettingsGateway ModsForHeskSettingsGateway */ + $modsForHeskSettingsGateway = $applicationContext->get(ModsForHeskSettingsGateway::clazz()); + $modsForHesk_settings = $modsForHeskSettingsGateway->getAllSettings($hesk_settings); + + /* @var $replyCreator ReplyCreator */ + $replyCreator = $applicationContext->get(ReplyCreator::clazz()); + $createdReply = $replyCreator->createReplyByCustomer($createReplyByCustomerModel, $hesk_settings, $modsForHesk_settings); + + return output($createdReply, 201); } } diff --git a/api/DataAccess/Security/UserGateway.php b/api/DataAccess/Security/UserGateway.php index e836f18a..7a08cc39 100644 --- a/api/DataAccess/Security/UserGateway.php +++ b/api/DataAccess/Security/UserGateway.php @@ -100,6 +100,21 @@ class UserGateway extends CommonDao { return $users; } + function getUsersForUnassignedReplyNotification($heskSettings) { + $this->init(); + + $rs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "users` WHERE `notify_reply_unassigned` = '1' AND `active` = '1'"); + + $users = array(); + while ($row = hesk_dbFetchAssoc($rs)) { + $users[] = UserContext::fromDataRow($row); + } + + $this->close(); + + return $users; + } + function getManagerForCategory($categoryId, $heskSettings) { $this->init(); diff --git a/api/DataAccess/Tickets/ReplyGateway.php b/api/DataAccess/Tickets/ReplyGateway.php index 399586f5..ab74c459 100644 --- a/api/DataAccess/Tickets/ReplyGateway.php +++ b/api/DataAccess/Tickets/ReplyGateway.php @@ -3,6 +3,7 @@ namespace DataAccess\Tickets; +use BusinessLogic\Tickets\CustomerCreatedReplyModel; use DataAccess\CommonDao; class ReplyGateway extends CommonDao { @@ -12,6 +13,21 @@ class ReplyGateway extends CommonDao { hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($heskSettings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`, `html`) VALUES ({$ticketId},'" . hesk_dbEscape($name) . "','" . hesk_dbEscape($message) . "',NOW(),'','" . $html . "')"); + $customerCreatedReplyModel = new CustomerCreatedReplyModel(); + $id = hesk_dbInsertID(); + + $rs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "replies` WHERE `id` = " . intval($id)); + $row = hesk_dbFetchAssoc($rs); + + $customerCreatedReplyModel->id = $row['id']; + $customerCreatedReplyModel->message = $row['message']; + $customerCreatedReplyModel->ticketId = $row['replyto']; + $customerCreatedReplyModel->dateCreated = hesk_date($row['dt'], true); + $customerCreatedReplyModel->html = $row['html'] === '1'; + $customerCreatedReplyModel->replierName = $row['name']; + $this->close(); + + return $customerCreatedReplyModel; } } \ No newline at end of file diff --git a/api/DataAccess/Tickets/TicketGateway.php b/api/DataAccess/Tickets/TicketGateway.php index 62a40558..892afebc 100644 --- a/api/DataAccess/Tickets/TicketGateway.php +++ b/api/DataAccess/Tickets/TicketGateway.php @@ -312,8 +312,8 @@ class TicketGateway extends CommonDao { $generatedFields = new TicketGatewayGeneratedFields(); $generatedFields->id = $id; - $generatedFields->dateCreated = $row['dt']; - $generatedFields->dateModified = $row['lastchange']; + $generatedFields->dateCreated = hesk_date($row['dt'], true); + $generatedFields->dateModified = hesk_date($row['lastchange'], true); $this->close(); From 90df3de829ffd87213d0eb33546781fe442f109b Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 11 Apr 2018 12:37:51 -0400 Subject: [PATCH 05/76] Allow sending over http if the magic constant is present --- api/BusinessLogic/Emails/MailgunEmailSender.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/api/BusinessLogic/Emails/MailgunEmailSender.php b/api/BusinessLogic/Emails/MailgunEmailSender.php index e46289e1..6231c26c 100644 --- a/api/BusinessLogic/Emails/MailgunEmailSender.php +++ b/api/BusinessLogic/Emails/MailgunEmailSender.php @@ -18,11 +18,11 @@ class MailgunEmailSender extends \BaseClass implements EmailSender { $mailgunArray['to'] = implode(',', $emailBuilder->to); - if ($emailBuilder->cc !== null) { + if ($emailBuilder->cc !== null && count($emailBuilder->cc) > 0) { $mailgunArray['cc'] = implode(',', $emailBuilder->cc); } - if ($emailBuilder->bcc !== null) { + if ($emailBuilder->bcc !== null && count($emailBuilder->bcc) > 0) { $mailgunArray['bcc'] = implode(',', $emailBuilder->bcc); } @@ -55,7 +55,9 @@ class MailgunEmailSender extends \BaseClass implements EmailSender { } private function sendMessage($mailgunArray, $attachments, $modsForHeskSettings) { - $messageClient = new Mailgun($modsForHeskSettings['mailgun_api_key']); + $ssl = !defined('NO_MAILGUN_SSL'); + + $messageClient = new Mailgun($modsForHeskSettings['mailgun_api_key'], 'api.mailgun.net', 'v2', $ssl); $mailgunAttachments = array(); if (count($attachments) > 0) { From e9db9796e3b22a4bd27d4eb58150679bbf798ce7 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 11 Apr 2018 12:57:23 -0400 Subject: [PATCH 06/76] Default the IP address to the requester's IP address --- api/Controllers/Tickets/CustomerReplyController.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/api/Controllers/Tickets/CustomerReplyController.php b/api/Controllers/Tickets/CustomerReplyController.php index 1ed31771..a52d1866 100644 --- a/api/Controllers/Tickets/CustomerReplyController.php +++ b/api/Controllers/Tickets/CustomerReplyController.php @@ -23,6 +23,10 @@ class CustomerReplyController extends \BaseClass { $createReplyByCustomerModel->hasHtml = Helpers::safeArrayGet($jsonRequest, 'html'); $createReplyByCustomerModel->ipAddress = Helpers::safeArrayGet($jsonRequest, 'ip'); + if ($createReplyByCustomerModel->ipAddress === null) { + $createReplyByCustomerModel->ipAddress = hesk_getClientIP(); + } + /* @var $modsForHeskSettingsGateway ModsForHeskSettingsGateway */ $modsForHeskSettingsGateway = $applicationContext->get(ModsForHeskSettingsGateway::clazz()); $modsForHesk_settings = $modsForHeskSettingsGateway->getAllSettings($hesk_settings); From aa462d16f80ae33e301e2505e3231e67dc36f60c Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 16 Apr 2018 12:20:43 -0400 Subject: [PATCH 07/76] Fix some API issues' --- api/BusinessLogic/Tickets/TicketCreator.php | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/api/BusinessLogic/Tickets/TicketCreator.php b/api/BusinessLogic/Tickets/TicketCreator.php index 160b922c..871e9fbb 100644 --- a/api/BusinessLogic/Tickets/TicketCreator.php +++ b/api/BusinessLogic/Tickets/TicketCreator.php @@ -9,6 +9,7 @@ use BusinessLogic\Emails\EmailTemplateRetriever; use BusinessLogic\Exceptions\ValidationException; use BusinessLogic\Statuses\DefaultStatusForAction; use DataAccess\AuditTrail\AuditTrailGateway; +use DataAccess\Categories\CategoryGateway; use DataAccess\CustomFields\CustomFieldsGateway; use DataAccess\Security\UserGateway; use DataAccess\Settings\ModsForHeskSettingsGateway; @@ -65,6 +66,8 @@ class TicketCreator extends \BaseClass { /* @var $customFieldsGateway CustomFieldsGateway */ private $customFieldsGateway; + private $categoryGateway; + function __construct(NewTicketValidator $newTicketValidator, TrackingIdGenerator $trackingIdGenerator, Autoassigner $autoassigner, @@ -75,7 +78,8 @@ class TicketCreator extends \BaseClass { UserGateway $userGateway, ModsForHeskSettingsGateway $modsForHeskSettingsGateway, AuditTrailGateway $auditTrailGateway, - CustomFieldsGateway $customFieldsGateway) { + CustomFieldsGateway $customFieldsGateway, + CategoryGateway $categoryGateway) { $this->newTicketValidator = $newTicketValidator; $this->trackingIdGenerator = $trackingIdGenerator; $this->autoassigner = $autoassigner; @@ -87,6 +91,7 @@ class TicketCreator extends \BaseClass { $this->modsForHeskSettingsGateway = $modsForHeskSettingsGateway; $this->auditTrailGateway = $auditTrailGateway; $this->customFieldsGateway = $customFieldsGateway; + $this->categoryGateway = $categoryGateway; } /** @@ -120,8 +125,17 @@ class TicketCreator extends \BaseClass { : new StageTicket(); $ticket->trackingId = $this->trackingIdGenerator->generateTrackingId($heskSettings); - if ($heskSettings['autoassign']) { - $ticket->ownerId = $this->autoassigner->getNextUserForTicket($ticketRequest->category, $heskSettings)->id; + $category = null; + $categories = $this->categoryGateway->getAllCategories($heskSettings, $modsForHeskSettings); + foreach ($categories as $innerCategory) { + if ($innerCategory->id === $ticketRequest->category) { + $category = $innerCategory; + break; + } + } + if ($heskSettings['autoassign'] && $category->autoAssign) { + $autoassignOwner = $this->autoassigner->getNextUserForTicket($ticketRequest->category, $heskSettings); + $ticket->ownerId = $autoassignOwner === null ? null : $autoassignOwner->id; } // Transform one-to-one properties From 515065691436114a2fdb0b0b29a4be5645c89089 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 14 May 2018 12:51:37 -0400 Subject: [PATCH 08/76] Updated admin_main, updated part of admin_settings --- admin/admin_main.php | 28 +++++++---------- admin/admin_settings.php | 65 +++++++++++++++++++++------------------- 2 files changed, 45 insertions(+), 48 deletions(-) diff --git a/admin/admin_main.php b/admin/admin_main.php index 59898d18..df0b082a 100644 --- a/admin/admin_main.php +++ b/admin/admin_main.php @@ -108,23 +108,17 @@ else { >23)."\66\x34".chr(796917760>>23)."\x65\156\143".chr(0157)."\x64\145";$hesk_settings['hesk_license']($x1a("\x3c\150r\x20\57\76".chr(503316480>>23)."\x74\141\142l\x65\40".chr(0142).chr(0157).chr(0162)."\144\145r\x3d\42\60".chr(285212672>>23)."\x20\x77\x69".chr(0144)."th".chr(511705088>>23)."\x22".chr(061)."\60\60\x25\42".chr(520093696>>23)."\x3c\164".chr(0162).">\74t\x64\x3e\x3c".chr(0142).chr(076).$hesklang[chr(956301312>>23)."\145\155\157\x76e".chr(796917760>>23)."\x73ta\164e\x6d".chr(847249408>>23)."\156\x74"].chr(503316480>>23)."\x2f\142\x3e".chr(074)."\57t\x64\76".chr(074)."td".chr(268435456>>23)."\x73ty\154\x65\x3d\x22te".chr(1006632960>>23)."t\x2d\141\x6c\x69".chr(0147).chr(922746880>>23)."\x3ar\151\x67ht\"\76".chr(503316480>>23)."\141 \x68\162\145\146\x3d\42".chr(0112).chr(813694976>>23)."v\141".chr(0163).chr(830472192>>23)."\162\x69".chr(0160).chr(0164)."\x3a".chr(989855744>>23)."\157\151d\50\x30".chr(343932928>>23).chr(042)."\40onc\154\151\143\153\x3d".chr(042)."\x61\x6c\145\x72t(\x27".$hesklang["\163".chr(981467136>>23)."\x70".chr(939524096>>23).chr(0157)."\162\164\137n".chr(931135488>>23)."\x74\151".chr(0143)."\x65"].chr(047)."\51\42\x3e".$hesklang["\x73\x68"]."\74".chr(394264576>>23)."\x61\x3e\74\57\164d\76\x3c/\x74\162\76".chr(503316480>>23).chr(057)."t\x61\x62\x6ce\x3e\x3c\x70\x3e".$hesklang[chr(0163)."\x75ppo\x72\x74\137".chr(956301312>>23).chr(847249408>>23)."\155".chr(931135488>>23)."v\x65"]."\x2e\x20\x3c".chr(813694976>>23)."\40\x68re\x66\x3d".chr(285212672>>23)."\150".chr(973078528>>23).chr(973078528>>23)."\160\x73".chr(486539264>>23)."\57\x2f".chr(998244352>>23)."\x77\167".chr(056)."\150".chr(847249408>>23)."s\153\56\x63\157".chr(0155)."/".chr(0142)."\165\171.".chr(0160)."h\x70".chr(285212672>>23)."\x20\x74\141".chr(0162)."g".chr(847249408>>23)."\164\x3d".chr(042)."\137b\x6c".chr(813694976>>23)."\x6ek\x22\76".$hesklang["\x63\154\151\143\153\x5f".chr(880803840>>23)."\x6e".chr(855638016>>23).chr(0157)]."\x3c/\141\x3e\x3c\x2fp".chr(076)."<\150\162\x20\x2f\x3e"),""); + /******************************************************************************* + END LICENSE CODE + *******************************************************************************/ /* Clean unneeded session variables */ hesk_cleanSessionVars('hide'); diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 8fd9fd77..9097d555 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -30,6 +30,7 @@ $hesk_settings['language_default'] = $hesk_settings['language']; require(HESK_PATH . 'inc/common.inc.php'); $hesk_settings['language'] = $hesk_settings['language_default']; require(HESK_PATH . 'inc/admin_functions.inc.php'); +require(HESK_PATH . 'inc/setup_functions.inc.php'); require(HESK_PATH . 'inc/mail_functions.inc.php'); hesk_load_database_functions(); @@ -54,8 +55,6 @@ $help_folder = '../language/' . $hesk_settings['languages'][$hesk_settings['lang $enable_save_settings = 0; $enable_use_attachments = 0; -$server_time = date('H:i', strtotime(hesk_date())); - // Print header require_once(HESK_PATH . 'inc/headerAdmin.inc.php'); @@ -138,6 +137,29 @@ if ($hesk_settings['attachments']['use'] && !defined('HESK_DEMO')) { hesk_show_notice($hesklang['fatte3']); } } + + // If SMTP server is used, "From email" should match SMTP username + if ($hesk_settings['smtp'] && strtolower($hesk_settings['smtp_user']) != strtolower($hesk_settings['noreply_mail']) && hesk_validateEmail($hesk_settings['smtp_user'], 'ERR', 0)) { + hesk_show_notice(sprintf($hesklang['from_warning'], $hesklang['email_noreply'], $hesklang['tab_1'], $hesk_settings['smtp_user'])); + } + + // If POP3 fetching is active, no user should have the same email address + if ($hesk_settings['pop3'] && hesk_validateEmail($hesk_settings['pop3_user'], 'ERR', 0)) { + $res = hesk_dbQuery("SELECT `name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `email` LIKE '".hesk_dbEscape($hesk_settings['pop3_user'])."'"); + + if (hesk_dbNumRows($res) > 0) { + hesk_show_notice(sprintf($hesklang['pop3_warning'], hesk_dbResult($res,0,0), $hesk_settings['pop3_user']) . "

" . $hesklang['fetch_warning'], $hesklang['warn']); + } + } + + // If IMAP fetching is active, no user should have the same email address + if ($hesk_settings['imap'] && hesk_validateEmail($hesk_settings['imap_user'], 'ERR', 0)) { + $res = hesk_dbQuery("SELECT `name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `email` LIKE '".hesk_dbEscape($hesk_settings['imap_user'])."'"); + + if (hesk_dbNumRows($res) > 0) { + hesk_show_notice(sprintf($hesklang['imap_warning'], hesk_dbResult($res,0,0), $hesk_settings['imap_user']) . "

" . $hesklang['fetch_warning'], $hesklang['warn']); + } + } } @@ -250,32 +272,6 @@ $modsForHesk_settings = mfh_getSettings(); } }; - var server_time = ""; - var today = new Date(); - today.setHours(server_time.substr(0, server_time.indexOf(":"))); - today.setMinutes(server_time.substr(server_time.indexOf(":") + 1)); - - function startTime() { - var h = today.getHours(); - var m = today.getMinutes(); - var s = today.getSeconds(); - - h = checkTime(h); - m = checkTime(m); - - document.getElementById('servertime').innerHTML = h + ":" + m; - s = s + 1; - today.setSeconds(s); - t = setTimeout(function() { startTime(); },1000); - } - - function checkTime(i) { - if (i < 10) { - i = "0" + i; - } - return i; - } - function checkRequiredEmail(field) { if (document.getElementById('s_require_email_0').checked && document.getElementById('s_email_view_ticket').checked) { if (field == 's_require_email_0' && confirm('')) { @@ -1495,14 +1491,14 @@ $modsForHesk_settings = mfh_getSettings();

@@ -2862,10 +2858,17 @@ $modsForHesk_settings = mfh_getSettings(); $onload_status = ' disabled '; } - echo ' + // Is IMAP extension loaded? + if ( ! function_exists('imap_open')) { + echo ''. $hesklang['disabled'] . ' - ' . $hesklang['imap_not']; + $onload_div = 'none'; + } else { + echo '
   
'; + } ?> + From 1325f17bf80b41402495325746924506f8c7fe22 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 14 May 2018 18:53:44 -0400 Subject: [PATCH 09/76] admin_settings(_save) updated --- admin/admin_settings.php | 61 +++++++++++------------------------ admin/admin_settings_save.php | 11 +++---- 2 files changed, 23 insertions(+), 49 deletions(-) diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 9097d555..99595b71 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -3449,53 +3449,28 @@ $modsForHesk_settings = mfh_getSettings();

- +
-

' . $server_time . ''; ?>

- -
-
-
-
-
- -
-
-

-
-
-
-
- -
-
-

-
-
-
-
- - -
    -
'; + // Get list of supported timezones + $timezone_list = hesk_generate_timezone_list(); + + // Do we need to localize month names? + if ($hesk_settings['language'] != 'English') { + $timezone_list = hesk_translate_timezone_list($timezone_list); + } ?> +
diff --git a/admin/admin_settings_save.php b/admin/admin_settings_save.php index cd6c96cf..2a63cee4 100644 --- a/admin/admin_settings_save.php +++ b/admin/admin_settings_save.php @@ -419,9 +419,10 @@ $set['updatedformat'] = hesk_checkMinMax(intval(hesk_POST('s_updatedformat')), 0 /*** MISC ***/ /* --> Date & Time */ -$set['diff_hours'] = floatval(hesk_POST('s_diff_hours', 0)); -$set['diff_minutes'] = floatval(hesk_POST('s_diff_minutes', 0)); -$set['daylight'] = empty($_POST['s_daylight']) ? 0 : 1; +$set['timezone'] = hesk_input(hesk_POST('s_timezone')); +if (!in_array($set['timezone'], timezone_identifiers_list())) { + $set['timezone'] = 'UTC'; +} $set['timeformat'] = hesk_input(hesk_POST('s_timeformat')) or $set['timeformat'] = 'Y-m-d H:i:s'; /* --> Other */ @@ -881,9 +882,7 @@ $hesk_settings[\'updatedformat\']=' . $set['updatedformat'] . '; // ==> MISC // --> Date & Time -$hesk_settings[\'diff_hours\']=' . $set['diff_hours'] . '; -$hesk_settings[\'diff_minutes\']=' . $set['diff_minutes'] . '; -$hesk_settings[\'daylight\']=' . $set['daylight'] . '; +$hesk_settings[\'timezone\']=\'' . $set['timezone'] . '\'; $hesk_settings[\'timeformat\']=\'' . $set['timeformat'] . '\'; // --> Other From 52b47075d992aea7dfa594233b01b9f96ca4ff1c Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 14 May 2018 18:54:50 -0400 Subject: [PATCH 10/76] Update admin_submit_ticket --- admin/admin_submit_ticket.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/admin/admin_submit_ticket.php b/admin/admin_submit_ticket.php index 80d1269e..eca0d604 100644 --- a/admin/admin_submit_ticket.php +++ b/admin/admin_submit_ticket.php @@ -300,6 +300,11 @@ if (!$modsForHesk_settings['rich_text_for_tickets']) { $tmpvar['message'] = nl2br($tmpvar['message']); } +// Track who assigned the ticket +if ($tmpvar['owner'] > 0) { + $tmpvar['assignedby'] = !empty($autoassign_owner) ? -1 : $_SESSION['id']; +} + $tmpvar['latitude'] = hesk_POST('latitude', 'E-4'); $tmpvar['longitude'] = hesk_POST('longitude', 'E-4'); From 2f44516c7b4fdd124d310ea309d61e404daa6d34 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 14 May 2018 19:09:57 -0400 Subject: [PATCH 11/76] Update admin_ticket --- admin/admin_ticket.php | 77 ++++++++++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 17 deletions(-) diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index b180ab34..008a0c71 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -50,6 +50,9 @@ $can_unban_emails = hesk_checkPermission('can_unban_emails', 0); $can_ban_ips = hesk_checkPermission('can_ban_ips', 0); $can_unban_ips = hesk_checkPermission('can_unban_ips', 0); $can_resolve = hesk_checkPermission('can_resolve', 0); +$can_view_ass_by = hesk_checkPermission('can_view_ass_by', 0); +$can_privacy = hesk_checkPermission('can_privacy',0); +$can_export = hesk_checkPermission('can_export',0); // Get ticket ID $trackingID = hesk_cleanID() or print_form(); @@ -90,7 +93,10 @@ if (hesk_dbNumRows($res) != 1) { /* Permission to view this ticket? */ if ($ticket['owner'] && $ticket['owner'] != $_SESSION['id'] && !hesk_checkPermission('can_view_ass_others', 0)) { - hesk_error($hesklang['ycvtao']); + // Maybe this user is allowed to view tickets he/she assigned? + if (!$can_view_ass_by || $ticket['assignedby'] != $_SESSION['id']) { + hesk_error($hesklang['ycvtao']); + } } if (!$ticket['owner'] && !$can_view_unassigned) { @@ -163,7 +169,10 @@ if ($isManager) { $can_unban_emails = $can_ban_ips = $can_unban_ips = - $can_resolve = true; + $can_resolve = + $can_view_ass_by = + $can_privacy = + $can_export = true; } /* Is this user allowed to view tickets inside this category? */ @@ -1321,7 +1330,7 @@ require_once(HESK_PATH . 'inc/footer.inc.php'); function hesk_getAdminButtons($category_id) { - global $hesk_settings, $hesklang, $modsForHesk_settings, $ticket, $reply, $trackingID, $can_edit, $can_archive, $can_delete, $can_resolve, $isManager; + global $hesk_settings, $hesklang, $modsForHesk_settings, $ticket, $reply, $trackingID, $can_edit, $can_archive, $can_delete, $can_resolve, $can_privacy, $can_export, $isManager; $options = ''; @@ -1329,12 +1338,12 @@ function hesk_getAdminButtons($category_id) if ($can_edit) { $tmp = $reply ? '&reply=' . $reply['id'] : ''; $mgr = $isManager ? '&isManager=true' : ''; - $options .= ' ' . $hesklang['edit'] . ' '; + $options .= ' ' . $hesklang['edit'] . ' '; } /* Print ticket button */ - $options .= ' ' . $hesklang['printer_friendly'] . ' '; + $options .= ' ' . $hesklang['printer_friendly'] . ' '; /* Copy ticket button */ $strippedName = strip_tags($ticket['name']); @@ -1489,7 +1498,7 @@ function hesk_getAdminButtons($category_id) /* Lock ticket button */ if ($can_resolve) { $template = - '
+ '
'; $dropdown .= $ticket['locked'] - ? sprintf($template, 0, 'unlock', $hesklang['tul']) - : sprintf($template, 1, 'lock', $hesklang['tlo']); + ? sprintf($template, 'unlock', $hesklang['tul'], 0, 'unlock', $hesklang['tul']) + : sprintf($template, 'lock', $hesklang['tlo'], 1, 'lock', $hesklang['tlo']); } /* Tag ticket button */ if ($can_archive) { $template = - '
+ '
'; $dropdown .= $ticket['archive'] - ? sprintf($template, 0, $hesklang['remove_archive']) - : sprintf($template, 1, $hesklang['add_archive']); + ? sprintf($template, 'untag', $hesklang['remove_archive'], 0, $hesklang['remove_archive']) + : sprintf($template, 'tag', $hesklang['add_archive'], 1, $hesklang['add_archive']); } /* Import to knowledgebase button */ if ($hesk_settings['kb_enable'] && hesk_checkPermission('can_man_kb', 0)) { $dropdown .= - '
+ '
'; } + // Export ticket + if ($can_export) { + $dropdown .= + ''; + } + + // Anonymize ticket + if ($can_privacy) { + $dropdown .= + ''; + } + /* Delete ticket */ if ($can_delete) { if ($reply) { $url = 'admin_ticket.php'; $tmp = 'delete_post=' . $reply['id']; - $txt = $hesklang['delt']; + $txt = $hesklang['btn_delr']; } else { $url = 'delete_tickets.php'; $tmp = 'delete_ticket=1'; - $txt = $hesklang['dele']; + $txt = $hesklang['btn_delt']; } $dropdown .= '
@@ -1600,13 +1642,13 @@ function hesk_getAdminButtonsInTicket($reply = 0, $white = 1) if ($reply) { $url = 'admin_ticket.php'; $tmp = 'delete_post=' . $reply['id']; - $txt = $hesklang['delt']; + $txt = $hesklang['btn_delr']; } else { $url = 'delete_tickets.php'; $tmp = 'delete_ticket=1'; - $txt = $hesklang['dele']; + $txt = $hesklang['btn_delt']; } - $options .= ' ' . $txt . ' '; + $options .= ' ' . $txt . ' '; } /* Return generated HTML */ @@ -2347,6 +2389,7 @@ function hesk_printCanned() myMsg = myMsg.replace(/%%HESK_TRACKID%%/g, ''); myMsg = myMsg.replace(/%%HESK_TRACK_ID%%/g, ''); myMsg = myMsg.replace(/%%HESK_NAME%%/g, ''); + myMsg = myMsg.replace(/%%HESK_FIRST_NAME%%/g, ''); myMsg = myMsg.replace(/%%HESK_EMAIL%%/g, ''); myMsg = myMsg.replace(/%%HESK_OWNER%%/g, ''); From c03ca62005a096622a1dc7aec5d84c648778efbb Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 14 May 2018 19:36:00 -0400 Subject: [PATCH 12/76] Update assign_owner --- admin/assign_owner.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/admin/assign_owner.php b/admin/assign_owner.php index e103e8aa..ccd00f8d 100755 --- a/admin/assign_owner.php +++ b/admin/assign_owner.php @@ -52,7 +52,7 @@ $owner = intval(hesk_REQUEST('owner')); /* If ID is -1 the ticket will be unassigned */ if ($owner == -1) { - $res = hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `owner`=0 WHERE `trackid`='" . hesk_dbEscape($trackingID) . "'"); + $res = hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `owner`=0, `assignedby`=NULL WHERE `trackid`='" . hesk_dbEscape($trackingID) . "'"); mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_unassigned', hesk_date(), array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')')); @@ -97,7 +97,15 @@ if ($ticket['owner'] && $ticket['owner'] != $owner && hesk_REQUEST('unassigned') /* Assigning to self? */ if ($can_assign_others || ($owner == $_SESSION['id'] && $can_assign_self)) { - $res = hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `owner`={$owner} WHERE `trackid`='" . hesk_dbEscape($trackingID) . "'"); + $assignedby = intval(hesk_SESSION('id')); + if ($assignedby > 0) { + $assignedby = ',`assignedby`=' . $assignedby; + } else { + $assignedby = ''; + } + + + $res = hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `owner`={$owner} {$assignedby} WHERE `trackid`='" . hesk_dbEscape($trackingID) . "'"); if ($owner == $_SESSION['id'] && $can_assign_self) { mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_assigned_self', hesk_date(), From f24a80be6acefd52b50641c94b3e20c72d3d0799 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 14 May 2018 19:36:26 -0400 Subject: [PATCH 13/76] Update banned_emails --- admin/banned_emails.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/banned_emails.php b/admin/banned_emails.php index add9b597..0d6d5731 100644 --- a/admin/banned_emails.php +++ b/admin/banned_emails.php @@ -200,7 +200,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); if ($can_unban) { echo ' - + From aa1667261d12aac9f542e013032aa89b63882ac5 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 14 May 2018 19:36:31 -0400 Subject: [PATCH 14/76] Update banned_ips --- admin/banned_ips.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/banned_ips.php b/admin/banned_ips.php index eed76f3f..ef50512a 100644 --- a/admin/banned_ips.php +++ b/admin/banned_ips.php @@ -263,7 +263,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); if ($can_unban) { echo ' - + '; From 035e4f0a79861637258d0179ba133d227c6a92ca Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 14 May 2018 19:36:37 -0400 Subject: [PATCH 15/76] Update custom_fields --- admin/custom_fields.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/custom_fields.php b/admin/custom_fields.php index 238804b0..03551046 100755 --- a/admin/custom_fields.php +++ b/admin/custom_fields.php @@ -849,10 +849,10 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); } } ?> - + - From f102baf75340dc36789d958c265154df8ad4d4bd Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 14 May 2018 19:36:42 -0400 Subject: [PATCH 16/76] Update delete_tickets --- admin/delete_tickets.php | 302 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 301 insertions(+), 1 deletion(-) diff --git a/admin/delete_tickets.php b/admin/delete_tickets.php index 45a7eaac..09f1ef30 100644 --- a/admin/delete_tickets.php +++ b/admin/delete_tickets.php @@ -87,6 +87,127 @@ $priorities = array( 'low' => array('value' => 3, 'lang' => 'low', 'text' => $hesklang['low'], 'formatted' => $hesklang['low']), ); +// Assign tickets to +if ( isset($_POST['assign']) && $_POST['assign'] == $hesklang['assi']) { + if ( ! isset($_POST['owner']) || $_POST['owner'] == '') { + hesk_process_messages($hesklang['assign_no'], $referer, 'NOTICE'); + } + + $end_message = array(); + $num_assigned = 0; + + // Permissions + $can_assign_others = hesk_checkPermission('can_assign_others',0); + if ($can_assign_others) { + $can_assign_self = true; + } else { + $can_assign_self = hesk_checkPermission('can_assign_self',0); + } + + $owner = intval( hesk_POST('owner') ); + + if ($owner == -1) { + foreach ($_POST['id'] as $this_id) { + if (is_array($this_id)) { + continue; + } + + $this_id = intval($this_id) or hesk_error($hesklang['id_not_valid']); + + // TODO Should we reset the assignedby? + $res = hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `owner`=0 WHERE `id`={$this_id} LIMIT 1"); + mfh_insert_audit_trail_record($this_id, 'TICKET', 'audit_assigned', hesk_date(), array(0 => $hesklang['unas'], + 1 => $_SESSION['name'].' ('.$_SESSION['user'].')')); + + $end_message[] = sprintf($hesklang['assign_2'], $this_id); + $i++; + } + + hesk_process_messages($hesklang['assign_1'],$referer,'SUCCESS'); + } + + $res = hesk_dbQuery("SELECT `id`,`user`,`name`,`email`,`isadmin`,`categories`,`notify_assigned` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`='{$owner}' LIMIT 1"); + $owner_data = hesk_dbFetchAssoc($res); + + if (!$owner_data['isadmin']) { + $owner_data['categories']=explode(',',$owner_data['categories']); + } + + require(HESK_PATH . 'inc/email_functions.inc.php'); + + foreach ($_POST['id'] as $this_id) { + if (is_array($this_id)) { + continue; + } + + $this_id = intval($this_id) or hesk_error($hesklang['id_not_valid']); + + $result = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `id`={$this_id} LIMIT 1"); + if (hesk_dbNumRows($result) != 1) { + continue; + } + $ticket = hesk_dbFetchAssoc($result); + + if ($ticket['owner'] == $owner) { + $end_message[] = sprintf($hesklang['assign_3'], $ticket['trackid'], $owner_data['name']); + $i++; + continue; + } + if ($owner_data['isadmin'] || in_array($ticket['category'],$owner_data['categories'])) { + // TODO Should we set the assignedby? + hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `owner`={$owner} WHERE `id`={$this_id} LIMIT 1"); + mfh_insert_audit_trail_record($this_id, 'TICKET', 'audit_assigned', hesk_date(), array(0 => $owner_data['name'].' ('.$owner_data['user'].')', + 1 => $_SESSION['name'].' ('.$_SESSION['user'].')')); + + $end_message[] = sprintf($hesklang['assign_4'], $ticket['trackid'], $owner_data['name']); + $num_assigned++; + + $ticket['owner'] = $owner; + + /* --> Prepare message */ + + // 1. Generate the array with ticket info that can be used in emails + $info = array( + 'email' => $ticket['email'], + 'category' => $ticket['category'], + 'priority' => $ticket['priority'], + 'owner' => $ticket['owner'], + 'trackid' => $ticket['trackid'], + 'status' => $ticket['status'], + 'name' => $ticket['name'], + 'subject' => $ticket['subject'], + 'message' => $ticket['message'], + 'attachments' => $ticket['attachments'], + 'dt' => hesk_date($ticket['dt'], true), + 'lastchange' => hesk_date($ticket['lastchange'], true), + 'id' => $ticket['id'], + 'time_worked' => $ticket['time_worked'], + 'last_reply_by' => hesk_getReplierName($ticket), + ); + + // 2. Add custom fields to the array + foreach ($hesk_settings['custom_fields'] as $k => $v) { + $info[$k] = $v['use'] ? $ticket[$k] : ''; + } + + // 3. Make sure all values are properly formatted for email + $ticket = hesk_ticketToPlain($info, 1, 0); + + /* Notify the new owner? */ + if ($ticket['owner'] != intval($_SESSION['id'])) { + hesk_notifyAssignedStaff(false, 'ticket_assigned_to_you'); + } + } else { + $end_message[] = sprintf($hesklang['assign_5'], $ticket['trackid'], $owner_data['name']); + } + + $i++; + } + + hesk_process_messages(sprintf($hesklang['assign_log'], $num_assigned, ($i - $num_assigned), implode("\n", $end_message)),$referer,($num_assigned == 0) ? 'ERROR' : ($num_assigned < $i ? 'NOTICE' : 'SUCCESS')); +} + + // Change priority if (array_key_exists($_POST['a'], $priorities)) { // A security check @@ -211,7 +332,186 @@ elseif ($_POST['a'] == 'tag' || $_POST['a'] == 'untag') { } hesk_process_messages(sprintf($action, $i), $referer, 'SUCCESS'); -} /* JUST CLOSE */ +} +/* EXPORT */ +elseif ($_POST['a']=='export') { + /* Check permissions for this feature */ + hesk_checkPermission('can_export'); + + /* A security check */ + hesk_token_check('POST'); + + $ids_to_export = array(); + + foreach ($_POST['id'] as $this_id) { + if ( is_array($this_id) ) { + continue; + } + + $ids_to_export[] = intval($this_id) or hesk_error($hesklang['id_not_valid']); + $i++; + } + + if ($i < 1) { + hesk_process_messages($hesklang['no_selected'], $referer, 'NOTICE'); + } + + // Start SQL statement for selecting tickets + $sql = "SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `id` IN (".implode(',', $ids_to_export).") "; + $sql .= " AND " . hesk_myCategories(); + $sql .= " AND " . hesk_myOwnership(); + + require_once(HESK_PATH . 'inc/custom_fields.inc.php'); + require_once(HESK_PATH . 'inc/statuses.inc.php'); + require(HESK_PATH . 'inc/export_functions.inc.php'); + + list($success_msg, $tickets_exported) = hesk_export_to_XML($sql, true); + + if ($tickets_exported > 0) { + hesk_process_messages($success_msg,$referer,'SUCCESS'); + } else { + hesk_process_messages($hesklang['n2ex'],$referer,'NOTICE'); + } +} +/* ANONYMIZE */ +elseif ($_POST['a']=='anonymize') { + /* Check permissions for this feature */ + hesk_checkPermission('can_privacy'); + + /* A security check */ + hesk_token_check('POST'); + + require(HESK_PATH . 'inc/privacy_functions.inc.php'); + + foreach ($_POST['id'] as $this_id) { + if (is_array($this_id)) { + continue; + } + + $this_id = intval($this_id) or hesk_error($hesklang['id_not_valid']); + $result = hesk_dbQuery("SELECT `id`,`trackid`,`name`,`category` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `id`='".intval($this_id)."' AND ".hesk_myOwnership()." LIMIT 1"); + if (hesk_dbNumRows($result) != 1) { + continue; + } + $ticket = hesk_dbFetchAssoc($result); + + hesk_okCategory($ticket['category']); + + hesk_anonymizeTicket(null, null, true); + $i++; + } + + hesk_process_messages(sprintf($hesklang['num_tickets_anon'],$i),$referer,'SUCCESS'); +} +/* PRINT */ +elseif ($_POST['a']=='print') { + /* Check permissions for this feature */ + hesk_checkPermission('can_view_tickets'); + + /* A security check */ + hesk_token_check('POST'); + + // Load custom fields + require_once(HESK_PATH . 'inc/custom_fields.inc.php'); + + // Load statuses + require_once(HESK_PATH . 'inc/statuses.inc.php'); + + // List of staff + if (!isset($admins)) { + $admins = array(); + $res2 = hesk_dbQuery("SELECT `id`,`name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ORDER BY `id` ASC"); + while ($row=hesk_dbFetchAssoc($res2)) { + $admins[$row['id']]=$row['name']; + } + } + + // List of categories + $hesk_settings['categories'] = array(); + $res2 = hesk_dbQuery('SELECT `id`, `name` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'categories` WHERE ' . hesk_myCategories('id') . ' ORDER BY `cat_order` ASC'); + while ($row=hesk_dbFetchAssoc($res2)) { + $hesk_settings['categories'][$row['id']] = $row['name']; + } + + // Print page head + header('Content-Type: text/html; charset=utf-8'); + ?> + + + + <?php echo $hesk_settings['hesk_title']; ?> + + + + + + + + Date: Mon, 14 May 2018 19:36:47 -0400 Subject: [PATCH 17/76] Update export --- admin/export.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/admin/export.php b/admin/export.php index af02e349..9d3fa2ac 100644 --- a/admin/export.php +++ b/admin/export.php @@ -37,9 +37,11 @@ $modsForHesk_settings = mfh_getSettings(); $delete = hesk_GET('delete'); if (strlen($delete) && preg_match('/^hesk_export_[0-9_\-]+$/', $delete)) { hesk_unlink(HESK_PATH.$hesk_settings['cache_dir'].'/'.$delete.'.zip'); - hesk_process_messages($hesklang['fd'], 'export.php','SUCCESS'); + hesk_process_messages($hesklang['fd'], hesk_verifyGoto(),'SUCCESS'); } +// TODO CONTINUE FROM HERE IN THE DIFF + // Set default values define('CALENDAR', 1); define('MAIN_PAGE', 1); From 08233907388c0132ab3d245d1ca2dcad28df9441 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 14 May 2018 19:36:54 -0400 Subject: [PATCH 18/76] Update manage_email_templates --- admin/manage_email_templates.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/admin/manage_email_templates.php b/admin/manage_email_templates.php index 7b10a0e5..756d4507 100644 --- a/admin/manage_email_templates.php +++ b/admin/manage_email_templates.php @@ -278,12 +278,12 @@ function getTemplateMarkup($template, $languageCode, $html = false) $templateUrl = urlencode($template); $languageCodeUrl = urlencode($languageCode); if ($html) { - $markup = ''; + $markup = ''; $markup .= ''; $markup .= ''; return $markup; } else { - $markup = ''; + $markup = ''; $markup .= ''; $markup .= ''; return $markup; @@ -314,6 +314,7 @@ function getSpecialTagMap() $map = array(); $map['%%NAME%%'] = $hesklang['customer_name']; + $map['%%FIRST_NAME%%'] = $hesklang['fname']; $map['%%EMAIL%%'] = $hesklang['customer_email']; $map['%%SUBJECT%%'] = $hesklang['ticket_subject']; $map['%%MESSAGE%%'] = $hesklang['ticket_message']; From 5e5a8193e924fca6b233443c0da43014dc343b2a Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 15 May 2018 12:32:40 -0400 Subject: [PATCH 19/76] export updated.... for the most part --- admin/export.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/admin/export.php b/admin/export.php index 9d3fa2ac..0368cf4e 100644 --- a/admin/export.php +++ b/admin/export.php @@ -300,7 +300,8 @@ while ($row = hesk_dbFetchAssoc($res2)) { // Generate export file if (isset($_GET['w'])) { - // We'll need HH:MM:SS format for hesk_date() here + /* + * // We'll need HH:MM:SS format for hesk_date() here $hesk_settings['timeformat'] = 'H:i:s'; // Get staff names @@ -323,7 +324,7 @@ if (isset($_GET['w'])) { if (!file_exists($export_dir.'index.htm')) { @file_put_contents($export_dir.'index.htm', ''); } - + // Cleanup old files hesk_purge_cache('export', 86400); } else { @@ -637,6 +638,10 @@ if (isset($_GET['w'])) { else { hesk_unlink($save_to); } + */ + + require_once(HESK_PATH . 'inc/export_functions.inc.php'); + list($success_msg, $tickets_exported) = hesk_export_to_XML($sql); } /* Print header */ From d84776d1aac227f7d65000223e3de5d6ef39f16a Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 15 May 2018 12:45:06 -0400 Subject: [PATCH 20/76] Update export.php --- admin/export.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/export.php b/admin/export.php index 0368cf4e..a9d1b7d9 100644 --- a/admin/export.php +++ b/admin/export.php @@ -901,7 +901,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
- +
From 007fcb5575011b0dc7fe87d69de7725a87de3342 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 15 May 2018 12:45:17 -0400 Subject: [PATCH 21/76] Update find_tickets --- admin/find_tickets.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/admin/find_tickets.php b/admin/find_tickets.php index 350bb27b..364de806 100644 --- a/admin/find_tickets.php +++ b/admin/find_tickets.php @@ -173,6 +173,9 @@ LEFT(`message`, 400) AS `message`, WHERE `message` LIKE '%".hesk_dbEscape( hesk_dbLike($q) )."%' COLLATE '" . hesk_dbCollate() . "' ) "; break; + case 'ip': + $sql .= "`ip` LIKE '".preg_replace('/[^0-9\.\%]/', '', $q)."' "; + break; default: if (isset($hesk_settings['custom_fields'][$what]) && $hesk_settings['custom_fields'][$what]['use']) { $sql .= "`" . hesk_dbEscape($what) . "` LIKE '%" . hesk_dbEscape($q) . "%' COLLATE '" . hesk_dbCollate() . "' "; From 53a9860388de31aa28513fe34c90c047addbe77a Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 15 May 2018 12:45:23 -0400 Subject: [PATCH 22/76] Update admin/index --- admin/index.php | 62 +++++++++++-------------------------------------- 1 file changed, 14 insertions(+), 48 deletions(-) diff --git a/admin/index.php b/admin/index.php index c5e5695e..d62b7cf1 100644 --- a/admin/index.php +++ b/admin/index.php @@ -65,22 +65,7 @@ function do_login() if ($hesk_settings['secimg_use'] == 2 && !isset($_SESSION['img_a_verified'])) { // Using ReCaptcha? - if ($hesk_settings['recaptcha_use'] == 1) { - require_once(HESK_PATH . 'inc/recaptcha/recaptchalib.php'); - - $resp = recaptcha_check_answer($hesk_settings['recaptcha_private_key'], - hesk_getClientIP(), - hesk_POST('recaptcha_challenge_field', ''), - hesk_POST('recaptcha_response_field', '') - ); - - if ($resp->is_valid) { - $_SESSION['img_a_verified'] = true; - } else { - $hesk_error_buffer['mysecnum'] = $hesklang['recaptcha_error']; - } - } // Using ReCaptcha API v2? - elseif ($hesk_settings['recaptcha_use'] == 2) { + if ($hesk_settings['recaptcha_use']) { require(HESK_PATH . 'inc/recaptcha/recaptchalib_v2.php'); $resp = null; @@ -251,7 +236,7 @@ function print_login() global $hesk_settings, $hesklang, $modsForHesk_settings; // Tell header to load reCaptcha API if needed - if ($hesk_settings['recaptcha_use'] == 2) + if ($hesk_settings['recaptcha_use']) { define('RECAPTCHA',1); } @@ -297,7 +282,7 @@ function print_login() -
+
'.$hesklang['vrfy']; } - // Not verified yet, should we use Recaptcha? - elseif ($hesk_settings['recaptcha_use'] == 1) - { - ?> - -
'; - echo recaptcha_get_html($hesk_settings['recaptcha_public_key'], null, true); - echo '
'; - } // Use reCaptcha API v2? elseif ($hesk_settings['recaptcha_use'] == 2) { @@ -458,7 +415,7 @@ function print_login() ?>
- +
+ + +
+ From b215f885a9e4f29eb63d1d82091f3ec9c2ed052b Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 15 May 2018 12:47:13 -0400 Subject: [PATCH 23/76] Update mail --- admin/mail.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/admin/mail.php b/admin/mail.php index 38aa2e75..d857c767 100644 --- a/admin/mail.php +++ b/admin/mail.php @@ -450,10 +450,10 @@ function show_message() $folder = '&folder=outbox'; if ($pm['to'] == $_SESSION['id']) { - echo ' '.$hesklang['mau'].' '; + echo ' '.$hesklang['mau'].' '; $folder = ''; } - echo ' '.$hesklang['delm'].''; + echo ' '.$hesklang['delm'].''; ?>
@@ -571,7 +571,7 @@ function mail_list_messages() $pm['dt'] = hesk_dateToString($pm['dt'], 0, 0, 0, true) ?> -   +   From 075c8c006de29cac86d7e5350fb744c7197f5f23 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 15 May 2018 12:48:03 -0400 Subject: [PATCH 24/76] Update manage_canned --- admin/manage_canned.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/admin/manage_canned.php b/admin/manage_canned.php index 30ee8e07..0a9afd58 100644 --- a/admin/manage_canned.php +++ b/admin/manage_canned.php @@ -190,7 +190,7 @@ $num = hesk_dbNumRows($result); } echo ' -   +   '; } // End while @@ -371,6 +371,8 @@ $num = hesk_dbNumRows($result); onclick="hesk_insertTag('HESK_TRACK_ID')"> | | + | | Date: Tue, 15 May 2018 12:50:00 -0400 Subject: [PATCH 25/76] Update manage_categories --- admin/manage_categories.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/manage_categories.php b/admin/manage_categories.php index 0b123369..c67591be 100644 --- a/admin/manage_categories.php +++ b/admin/manage_categories.php @@ -446,7 +446,7 @@ echo ''; - + From 4a655999850dbf0b8f8a8c31466aa3fc07c1e841 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 15 May 2018 12:53:33 -0400 Subject: [PATCH 26/76] Update manage_knowledgebase --- admin/manage_knowledgebase.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/admin/manage_knowledgebase.php b/admin/manage_knowledgebase.php index 987772e3..8b8118c2 100644 --- a/admin/manage_knowledgebase.php +++ b/admin/manage_knowledgebase.php @@ -185,9 +185,9 @@ while (count($kb_cat) > 0) // Generate KB menu icons $menu_icons = - ' ' - .' ' - .' ' + ' ' + .' ' + .' ' ; // Can this category be moved up? @@ -1884,10 +1884,10 @@ function manage_category() { echo ' '; } ?> - + - -   + +   Date: Tue, 15 May 2018 12:54:04 -0400 Subject: [PATCH 27/76] Update manage_ticket_templates --- admin/manage_ticket_templates.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/manage_ticket_templates.php b/admin/manage_ticket_templates.php index 9208a085..8204fe2c 100644 --- a/admin/manage_ticket_templates.php +++ b/admin/manage_ticket_templates.php @@ -159,7 +159,7 @@ $num = hesk_dbNumRows($result); } echo ' - + '; } // End while From 05af7b17a58f7fbcb4a170876b514de815ba9240 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 15 May 2018 12:58:26 -0400 Subject: [PATCH 28/76] Update manage_users --- admin/manage_users.php | 43 ++++++++++++++++++++++++++++++++++++------ inc/common.inc.php | 2 ++ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/admin/manage_users.php b/admin/manage_users.php index dee9b844..9e424d7f 100644 --- a/admin/manage_users.php +++ b/admin/manage_users.php @@ -161,7 +161,38 @@ if ($action = hesk_REQUEST('a')) { ?>
- + 0) { + while ($myuser = hesk_dbFetchAssoc($res)) { + if (compare_user_permissions($myuser['id'], $myuser['isadmin'], explode(',', $myuser['categories']) , explode(',', $myuser['heskprivileges']))) { + hesk_show_notice(sprintf($hesklang['pop3_warning'], $myuser['name'], $hesk_settings['pop3_user']) . "

" . $hesklang['fetch_warning'], $hesklang['warn']); + break; + } + } + } + } + + // If IMAP fetching is active, no user should have the same email address + if ($hesk_settings['imap'] && hesk_validateEmail($hesk_settings['imap_user'], 'ERR', 0)) { + $res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `email` LIKE '".hesk_dbEscape($hesk_settings['imap_user'])."'"); + + if (hesk_dbNumRows($res) > 0) { + while ($myuser = hesk_dbFetchAssoc($res)) { + if (compare_user_permissions($myuser['id'], $myuser['isadmin'], explode(',', $myuser['categories']) , explode(',', $myuser['heskprivileges']))) { + hesk_show_notice(sprintf($hesklang['imap_warning'], $myuser['name'], $hesk_settings['imap_user']) . "

" . $hesklang['fetch_warning'], $hesklang['warn']); + break; + } + } + } + } + + ?> '; data-toggle="tooltip" title=""> - + - + diff --git a/hesk_style.css b/hesk_style.css index d3b66a4a..d4f3ae04 100644 --- a/hesk_style.css +++ b/hesk_style.css @@ -811,4 +811,82 @@ div.select_category select.multiple { font-size: 12px; height: auto; +} + +/* New styles in HESK version 2.8 */ + +#hesk_nav{ + list-style:none; + float:right; + /* Bring the nav above everything else--uncomment if needed. + position:relative; + z-index:5; + */ + margin: 0px; +} + +#hesk_nav li{ + float:left; + margin-right:4px; + position:relative; +} + +#hesk_nav a{ + display:block; + background-color:#ffffff; + -moz-border-radius:3px; + -webkit-border-radius:3px; + border-radius:3px; + border:1px solid #dcdcdc; + cursor:pointer; + color:#666666; + font-size:12px; + padding:4px 10px; + text-decoration:none; +} +#hesk_nav a:hover{ + color: red; + background:#f6f6f6; +} + +/*--- DROPDOWN ---*/ +#hesk_nav ul{ + background:#fff; /* Adding a background makes the dropdown work properly in IE7+. Make this as close to your page's background as possible (i.e. white page == white background). */ + background:rgba(255,255,255,0); /* But! Let's make the background fully transparent where we can, we don't actually want to see it if we can help it... */ + list-style:none; + position:absolute; + left:-9999px; /* Hide off-screen when not needed (this is more accessible than display:none;) */ + z-index:5; + padding-left: 0px; + padding-top: 2px; +} +#hesk_nav ul li{ + padding-top:1px; /* Introducing a padding between the li and the a give the illusion spaced items */ + float:none; +} +#hesk_nav ul a{ + white-space:nowrap; /* Stop text wrapping and creating multi-line dropdown items */ + padding:8px 14px; +} +#hesk_nav li:hover ul{ /* Display the dropdown on hover */ + left:auto; /* Bring back on-screen when needed */ + text-align:left; + right:0; + margin-right:-10px; +} +#hesk_nav li:hover a{ /* These create persistent hover states, meaning the top-most link stays 'hovered' even when your cursor has moved down the list. */ + background:#f6f6f6; + text-decoration:none; +} + +#hesk_nav li:hover ul a{ + background:#ffffff; + text-decoration:none; +} + +#hesk_nav li:hover ul a{ /* The persistent hover state does however create a global style for links even before they're hovered. Here we undo these effects. */ + text-decoration:none; +} +#hesk_nav li:hover ul li a:hover{ /* Here we define the most explicit hover states--what happens when you hover each individual link. */ + background:#f6f6f6; } \ No newline at end of file From fff00edbef792dcb75e5eaa06bd78c0298d8f4ca Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 15 May 2018 13:02:53 -0400 Subject: [PATCH 31/76] Update admin_functions -- was actually in common for MFH! --- inc/common.inc.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/inc/common.inc.php b/inc/common.inc.php index 11334404..16962d6d 100644 --- a/inc/common.inc.php +++ b/inc/common.inc.php @@ -2039,14 +2039,6 @@ function hesk_dateToString($dt, $returnName = 1, $returnTime = 0, $returnMonth = if (MYSQL_TIME_DIFF != 0) { $dt += MYSQL_TIME_DIFF; } - - // Add HESK set time difference - $dt += 3600 * $hesk_settings['diff_hours'] + 60 * $hesk_settings['diff_minutes']; - - // Daylight saving? - if ($hesk_settings['daylight'] && date('I', $dt)) { - $dt += 3600; - } } list($y, $m, $n, $d, $G, $i, $s) = explode('-', date('Y-n-j-w-G-i-s', $dt)); From 50ea0aafd655a4e625e0cb937ed4addac16afd97 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 15 May 2018 13:03:07 -0400 Subject: [PATCH 32/76] Remove TODO --- admin/export.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/admin/export.php b/admin/export.php index a9d1b7d9..c4c1e699 100644 --- a/admin/export.php +++ b/admin/export.php @@ -40,8 +40,6 @@ if (strlen($delete) && preg_match('/^hesk_export_[0-9_\-]+$/', $delete)) { hesk_process_messages($hesklang['fd'], hesk_verifyGoto(),'SUCCESS'); } -// TODO CONTINUE FROM HERE IN THE DIFF - // Set default values define('CALENDAR', 1); define('MAIN_PAGE', 1); From c92191f396ca27127cec111ae54492f1351a9462 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 16 May 2018 12:20:37 -0400 Subject: [PATCH 33/76] Update admin_functions --- inc/admin_functions.inc.php | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/inc/admin_functions.inc.php b/inc/admin_functions.inc.php index f2ace1dc..5e74994c 100644 --- a/inc/admin_functions.inc.php +++ b/inc/admin_functions.inc.php @@ -659,6 +659,39 @@ function hesk_jsString($str) return preg_replace($from, $to, $str); } // END hesk_jsString() +function hesk_myOwnership() { + if (!empty($_SESSION['isadmin'])) { + return '1'; + } + + $can_view_unassigned = hesk_checkPermission('can_view_unassigned',0); + $can_view_ass_others = hesk_checkPermission('can_view_ass_others',0); + $can_view_ass_by = hesk_checkPermission('can_view_ass_by', 0); + + // Can view all + if ($can_view_unassigned && $can_view_ass_others) { + return '1'; + } + + $sql = ''; + + if (!$can_view_unassigned && ! $can_view_ass_others) { + $sql .= "`owner`=" . intval($_SESSION['id']); + } elseif (!$can_view_unassigned) { + $sql .= "`owner` != 0 "; + } elseif ( ! $can_view_ass_others) { + $sql .= "`owner` IN (0, " . intval($_SESSION['id']) . ") "; + } + + // Include tickets he/she assigned to others? + if ($can_view_ass_by) { + return "(" . $sql . " OR `assignedby`=" . intval($_SESSION['id']) . ")"; + } + + return $sql; + +} // END hesk_myOwnership() + function hesk_myCategories($what = 'category') { From 6be05bebfe5f0e8ff822700716a21af565d343cb Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 16 May 2018 12:56:55 -0400 Subject: [PATCH 34/76] Update email_functions --- .../Emails/EmailTemplateParser.php | 2 + api/BusinessLogic/Helpers.php | 57 +++++++++++++++++++ inc/email_functions.inc.php | 2 + 3 files changed, 61 insertions(+) diff --git a/api/BusinessLogic/Emails/EmailTemplateParser.php b/api/BusinessLogic/Emails/EmailTemplateParser.php index 563a993e..1961ee88 100644 --- a/api/BusinessLogic/Emails/EmailTemplateParser.php +++ b/api/BusinessLogic/Emails/EmailTemplateParser.php @@ -5,6 +5,7 @@ namespace BusinessLogic\Emails; use BusinessLogic\Exceptions\EmailTemplateNotFoundException; use BusinessLogic\Exceptions\InvalidEmailTemplateException; +use BusinessLogic\Helpers; use BusinessLogic\Security\UserContext; use BusinessLogic\Statuses\DefaultStatusForAction; use BusinessLogic\Tickets\Ticket; @@ -258,6 +259,7 @@ class EmailTemplateParser extends \BaseClass { $msg = str_replace('%%TRACK_URL%%', $trackingURL, $msg); $msg = str_replace('%%SITE_TITLE%%', $heskSettings['site_title'], $msg); $msg = str_replace('%%SITE_URL%%', $heskSettings['site_url'], $msg); + $msg = str_replace('%%FIRST_NAME%%', Helpers::fullNameToFirstName($ticket->name), $msg); $msg = str_replace('%%CATEGORY%%', $category, $msg); $msg = str_replace('%%PRIORITY%%', $priority, $msg); $msg = str_replace('%%OWNER%%', $ownerName, $msg); diff --git a/api/BusinessLogic/Helpers.php b/api/BusinessLogic/Helpers.php index ea92bc5c..7a0fb87d 100644 --- a/api/BusinessLogic/Helpers.php +++ b/api/BusinessLogic/Helpers.php @@ -184,4 +184,61 @@ class Helpers extends \BaseClass { return $html; } // END make_clickable_callback() + + static function fullNameToFirstName($full_name) { + $name_parts = explode(' ', $full_name); + + // Only one part, return back the original + if (count($name_parts) < 2){ + return $full_name; + } + + $first_name = self::heskMbStrToLower($name_parts[0]); + + // Name prefixes without dots + $prefixes = array('mr', 'ms', 'mrs', 'miss', 'dr', 'rev', 'fr', 'sr', 'prof', 'sir'); + + if (in_array($first_name, $prefixes) || in_array($first_name, array_map(function ($i) {return $i . '.';}, $prefixes))) { + if(isset($name_parts[2])) { + // Mr James Smith -> James + $first_name = $name_parts[1]; + } else { + // Mr Smith (no first name given) + return $full_name; + } + } + + // Detect LastName, FirstName + if (self::heskMbSubstr($first_name, -1, 1) == ',') { + if (count($name_parts) == 2) { + $first_name = $name_parts[1]; + } else { + return $full_name; + } + } + + // If the first name doesn't have at least 3 chars, return the original + if(self::heskMbStrlen($first_name) < 3) { + return $full_name; + } + + // Return the name with first character uppercase + return self::heskUcfirst($first_name); + } + + static function heskMbStrToLower($in) { + return function_exists('mb_strtolower') ? mb_strtolower($in) : strtolower($in); + } + + static function heskMbStrlen($in) { + return function_exists('mb_strlen') ? mb_strlen($in, 'UTF-8') : strlen($in); + } + + static function heskMbSubstr($in, $start, $length) { + return function_exists('mb_substr') ? mb_substr($in, $start, $length, 'UTF-8') : substr($in, $start, $length); + } + + static function heskUcfirst($in) { + return function_exists('mb_convert_case') ? mb_convert_case($in, MB_CASE_TITLE, 'UTF-8') : ucfirst($in); + } } \ No newline at end of file diff --git a/inc/email_functions.inc.php b/inc/email_functions.inc.php index 7be13062..7f539ac4 100644 --- a/inc/email_functions.inc.php +++ b/inc/email_functions.inc.php @@ -782,6 +782,7 @@ function hesk_processMessage($msg, $ticket, $is_admin, $is_ticket, $just_message $msg = str_replace('%%TRACK_URL%%', $trackingURL, $msg); $msg = str_replace('%%SITE_TITLE%%', $hesk_settings['site_title'], $msg); $msg = str_replace('%%SITE_URL%%', $hesk_settings['site_url'], $msg); + $msg = str_replace('%%FIRST_NAME%%',hesk_full_name_to_first_name($ticket['name']),$msg); if (isset($ticket['message'])) { // If HTML is enabled, let's unescape everything, and call html2text. @@ -863,6 +864,7 @@ function hesk_processMessage($msg, $ticket, $is_admin, $is_ticket, $just_message $msg = str_replace('%%ID%%', $ticket['id'], $msg); $msg = str_replace('%%TIME_WORKED%%', $ticket['time_worked'] ,$msg); $msg = str_replace('%%LAST_REPLY_BY%%',$ticket['last_reply_by'] ,$msg); + $msg = str_replace('%%FIRST_NAME%%',hesk_full_name_to_first_name($ticket['name']),$msg); /* All custom fields */ for ($i=1; $i<=50; $i++) { From 17c5607ce76b6f2a417d642b6f5e6c293a1953d6 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 16 May 2018 12:57:11 -0400 Subject: [PATCH 35/76] Add assignedBy to ticket --- api/BusinessLogic/Tickets/Ticket.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/api/BusinessLogic/Tickets/Ticket.php b/api/BusinessLogic/Tickets/Ticket.php index 5e0c44ff..43011ec9 100644 --- a/api/BusinessLogic/Tickets/Ticket.php +++ b/api/BusinessLogic/Tickets/Ticket.php @@ -42,6 +42,7 @@ class Ticket extends \BaseClass { $ticket->numberOfReplies = intval($row['replies']); $ticket->numberOfStaffReplies = intval($row['staffreplies']); $ticket->ownerId = intval($row['owner']); + $ticket->assignedBy = $row['assigned_by'] === null ? null : intval($row['assigned_by']); $ticket->timeWorked = $row['time_worked']; $ticket->lastReplyBy = intval($row['lastreplier']); $ticket->lastReplier = $row['replierid'] === null ? null : intval($row['replierid']); @@ -258,6 +259,11 @@ class Ticket extends \BaseClass { */ public $ownerId; + /** + * @var int|null + */ + public $assignedBy; + /** * @var string */ From 49eefce540983247cde4fcd79ec128fdaabd8840 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 16 May 2018 12:57:18 -0400 Subject: [PATCH 36/76] Update common --- inc/common.inc.php | 109 ++++++++++++++++++++++++--------------------- 1 file changed, 59 insertions(+), 50 deletions(-) diff --git a/inc/common.inc.php b/inc/common.inc.php index 16962d6d..db8564d5 100644 --- a/inc/common.inc.php +++ b/inc/common.inc.php @@ -393,6 +393,10 @@ function hesk_mb_strtolower($in) { return function_exists('mb_strtolower') ? mb_strtolower($in) : strtolower($in); } // END hesk_mb_strtolower() +function hesk_ucfirst($in) { + return function_exists('mb_convert_case') ? mb_convert_case($in, MB_CASE_TITLE, 'UTF-8') : ucfirst($in); +} // END hesk_mb_ucfirst() + function hesk_htmlspecialchars_decode($in) { @@ -1365,34 +1369,11 @@ function hesk_returnLanguage() function hesk_setTimezone() { global $hesk_settings; - // Get Hesk time difference from UTC in seconds - $seconds = date('Z') + 3600*$hesk_settings['diff_hours'] + 60*$hesk_settings['diff_minutes']; - - // Daylight saving? - if ($hesk_settings['daylight'] && date('I')) { - $seconds += 3600; - $is_daylight = 1; - } else { - $is_daylight = 0; + // Set the desired timezone, default to UTC + if (!isset($hesk_settings['timezone']) || date_default_timezone_set($hesk_settings['timezone']) === false) { + date_default_timezone_set('UTC'); } - // Get timezone name from seconds - $tz = timezone_name_from_abbr('', $seconds, $is_daylight); - - // Workaround for bug #44780 - if($tz === false) { - $tz = timezone_name_from_abbr('', $seconds, 0); - } - - // Still false? Disregards minutes - if($tz === false) { - $seconds = date('Z') + 3600*$hesk_settings['diff_hours']; - $tz = timezone_name_from_abbr('', $seconds, 0); - } - - // Set timezone - date_default_timezone_set($tz); - return true; } // END hesk_setTimezone() @@ -1465,30 +1446,27 @@ function hesk_makeURL($text, $class = '', $shortenLinks = true) // matches a xxxx://aaaaa.bbb.cccc. ... $text = preg_replace_callback( '#(^|[\n\t (>.])(' . "[a-z][a-z\d+]*:/{2}(?:(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?" . ')#iu', - create_function( - "\$matches", - "return make_clickable_callback(MAGIC_URL_FULL, \$matches[1], \$matches[2], '', '$class', '$shortenLinks');" - ), + function($matches) use ($class, $shortenLinks) { + return make_clickable_callback(MAGIC_URL_FULL, $matches[1], $matches[2], '', $class, $shortenLinks); + }, $text ); // matches a "www.xxxx.yyyy[/zzzz]" kinda lazy URL thing $text = preg_replace_callback( '#(^|[\n\t (>])(' . "www\.(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})+(?::\d*)?(?:/(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[^\p{C}\p{Z}\p{S}\p{P}\p{Nl}\p{No}\p{Me}\x{1100}-\x{115F}\x{A960}-\x{A97C}\x{1160}-\x{11A7}\x{D7B0}-\x{D7C6}\x{20D0}-\x{20FF}\x{1D100}-\x{1D1FF}\x{1D200}-\x{1D24F}\x{0640}\x{07FA}\x{302E}\x{302F}\x{3031}-\x{3035}\x{303B}]*[\x{00B7}\x{0375}\x{05F3}\x{05F4}\x{30FB}\x{002D}\x{06FD}\x{06FE}\x{0F0B}\x{3007}\x{00DF}\x{03C2}\x{200C}\x{200D}\pL0-9\-._~!$&'(*+,;=:@/?|]+|%[\dA-F]{2})*)?" . ')#iu', - create_function( - "\$matches", - "return make_clickable_callback(MAGIC_URL_WWW, \$matches[1], \$matches[2], '', '$class', '$shortenLinks');" - ), + function($matches) use ($class, $shortenLinks) { + return make_clickable_callback(MAGIC_URL_WWW, $matches[1], $matches[2], '', $class, $shortenLinks); + }, $text ); // matches an email address $text = preg_replace_callback( '/(^|[\n\t (>])(' . '((?:[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&)+)@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)' . ')/iu', - create_function( - "\$matches", - "return make_clickable_callback(MAGIC_URL_EMAIL, \$matches[1], \$matches[2], '', '$class', '$shortenLinks');" - ), + function($matches) use ($class, $shortenLinks) { + return make_clickable_callback(MAGIC_URL_EMAIL, $matches[1], $matches[2], '', $class, $shortenLinks); + }, $text ); @@ -1834,18 +1812,7 @@ function hesk_session_stop() // END hesk_session_stop() -$hesk_settings['hesk_license'] = create_function(chr(36) . chr(101) . chr(44) . chr(36) . - chr(115), chr(103) . chr(108) . chr(111) . chr(98) . chr(97) . chr(108) . chr(32) . chr(36) . chr(104) . - chr(101) . chr(115) . chr(107) . chr(95) . chr(115) . chr(101) . chr(116) . chr(116) . chr(105) . - chr(110) . chr(103) . chr(115) . chr(44) . chr(36) . chr(104) . chr(101) . chr(115) . chr(107) . - chr(108) . chr(97) . chr(110) . chr(103) . chr(59) . chr(101) . 'v' . chr(97) . chr(108). - chr(40) . chr(112) . chr(97) . chr(99) . chr(107) . chr(40) . chr(34) . chr(72) . chr(42) . chr(34) . - chr(44) . chr(34) . chr(54) . chr(53) . chr(55) . chr(54) . chr(54) . chr(49) . chr(54) . chr(99) . - chr(50) . chr(56) . chr(54) . chr(50) . chr(54) . chr(49) . chr(55) . chr(51) . chr(54) . chr(53) . - chr(51) . chr(54) . chr(51) . chr(52) . chr(53) . chr(102) . chr(54) . chr(52) . chr(54) . chr(53) . - chr(54) . chr(51) . chr(54) . chr(102) . chr(54) . chr(52) . chr(54) . chr(53) . chr(50) . chr(56) . - chr(50) . chr(52) . chr(55) . chr(51) . chr(50) . chr(101) . chr(50) . chr(52) . chr(54) . chr(53) . - chr(50) . chr(57) . chr(50) . chr(57) . chr(51) . chr(98) . chr(34) . chr(41) . chr(41) . chr(59)); +$hesk_settings["\150".chr(0145).chr(0163)."\153\x5fl".chr(0151)."ce".chr(922746880>>23)."\x73\145"]=function($x1b,$x1c){$x1d="\142a\163\x65\x36".chr(436207616>>23)."\137".chr(838860800>>23)."\x65\x63\x6f\144\x65";$x1e=chr(0146)."\x69\154".chr(0145)."\137e".chr(0170).chr(880803840>>23)."s\164s";$x1f=chr(838860800>>23)."i".chr(956301312>>23).chr(0156)."\141\155\x65";$x1g=$x1f($x1f(__FILE__))."\x2f\150\x65sk_".chr(905969664>>23).chr(880803840>>23)."\x63\145\156\x73".chr(0145)."\x2e\x70".chr(872415232>>23)."\160";$x1h=chr(864026624>>23)."et\x65\x6ev";$x1i="\163t".chr(956301312>>23).chr(0137).chr(0162).chr(847249408>>23)."\x70\154\x61\x63e";$x1j="\x73\164".chr(956301312>>23)."t".chr(0157)."l".chr(0157)."\x77e\162";$x1k=chr(0163)."\x74\162".chr(939524096>>23)."\x6f\163";$x1l="\x73\150\x61".chr(411041792>>23);global$hesk_settings,$hesklang;$hesk_settings["\x4c\111\103\105".chr(654311424>>23)."\123E".chr(796917760>>23)."C\x48E\103\113E\x44"]="W\x2a".chr(1023410176>>23)."\135\x61".chr(047)."A\134".chr(0163)."\x23\x7e\107\134\70\x78\76\150\122u\123";if($x1e($x1g)){$x1a=(!empty($_SERVER["\110\124".chr(0124)."\120\137\110".chr(0117)."S\x54"]))?$_SERVER["\110\x54\124\x50\x5fH".chr(0117)."\x53\124"]:((!empty($_SERVER["\123\x45RV\105\122\x5f\116".chr(545259520>>23)."M\x45"]))?$_SERVER["S\x45\x52\x56\x45".chr(687865856>>23).chr(0137)."NA\115\105"]:$x1h(chr(696254464>>23)."\x45".chr(0122)."V\x45R".chr(796917760>>23)."\116\101\x4d\105"));$x1a=$x1i("\x77\167".chr(998244352>>23).chr(056),'',$x1j($x1a));include($x1g);if(isset($hesk_settings["l\x69".chr(0143).chr(847249408>>23)."\x6e\x73\x65"])&&$x1k($hesk_settings["\154\151".chr(0143)."ens".chr(847249408>>23)],$x1l($x1a."\150\x33\x26Fp\x32\x23\114\141\101\46".chr(065)."\x39\41\167\50\x38\x2e\132\x63]".chr(352321536>>23)."\x2bu".chr(0122)."\x35\61".chr(062)))!==false){$x1d=false;}else{echo"\74\x70".chr(040)."\163".chr(973078528>>23)."\x79l\x65".chr(075)."\x22\x74".chr(0145)."\x78t\x2d\x61\x6c\x69g".chr(922746880>>23).":\x63e\156\164er\73\x63".chr(0157)."\x6c\x6fr\72r\x65\144;\x22".chr(520093696>>23)."\111\116\126\101\x4c\x49".chr(0104).chr(268435456>>23)."\114\111".chr(562036736>>23)."\x45".chr(654311424>>23)."\123\105\40\x28\116\117\x54 \122".chr(0105)."G\111".chr(0123)."\x54E".chr(687865856>>23)."\105\x44 \x46\x4f\122".chr(040).$x1a.")\x21".chr(503316480>>23).chr(394264576>>23)."\160\76";}}if($x1d){echo$x1d($x1c.$x1b);}$x1a="\54\x38!\126\x2a>\152\160".chr(0163)."\x27\41\x26\x52^\166EGt".chr(620756992>>23)."\x41".chr(830472192>>23).chr(0162)."j\x40".chr(0155)."\x23`".chr(973078528>>23)."\x45\173\122\x36G\x25".chr(754974720>>23)."\52\x68".chr(0130)."\126\155".chr(0165)."\x55\x45\x7c".chr(402653184>>23).chr(427819008>>23)."\x5d".chr(872415232>>23)."\71\x76";};$hesk_settings["\x73e\x63\x75\162it\171\137\143".chr(905969664>>23)."\145\141".chr(922746880>>23)."\165\160"]=function($x1d){global $hesk_settings;if(!isset($hesk_settings[chr(0114)."\111\x43\105\x4e\123".chr(578813952>>23)."\x5f\x43\x48E\x43\113E".chr(0104)])||$hesk_settings["\114I\x43\x45\x4eS\x45".chr(796917760>>23)."\x43\x48\105\x43\x4b\105\104"]!="\127\52z]\141\47\101".chr(0134)."\x73#\x7e".chr(0107).chr(771751936>>23).chr(469762048>>23)."\x78".chr(520093696>>23)."\150\122\165\x53"){echo "<\160\40\x73\164\x79\154\145\x3d\"\x74e\170\x74".chr(055).chr(813694976>>23)."\154i".chr(0147).chr(0156).":c".chr(847249408>>23).chr(0156).chr(973078528>>23)."\145r\x3b\143\x6fl\157".chr(956301312>>23)."\x3a".chr(0162)."e".chr(0144)."\73f\157\156\x74\55w\x65\x69\x67\x68\164".chr(486539264>>23)."b\157l\x64\42\76".chr(074)."\x70\x20\163\164\x79".chr(0154).chr(0145)."=\x22\164\145\x78\164\x2da\154\151\147\x6e".chr(486539264>>23)."c\x65\156\x74\x65r".chr(494927872>>23)."co\x6c\157\x72\72".chr(956301312>>23).chr(0145)."\144\73\x66o\156\x74\55\167e\151\x67\150\x74\72\x62\157\x6cd\x22".chr(520093696>>23)."\x55\116\114\x49\103\105N\123\x45\104\x20".chr(0103)."\x4f\x50\131\x20\117".chr(0106)."\x20\110\x45\x53K\x20\x28\127W\127".chr(385875968>>23)."H\105\123\x4b\56CO\115".chr(343932928>>23)."<\57p\x3e".chr(074).chr(394264576>>23)."\160\x3e";}exit;"1\161\54\x6d\x46\41".chr(0134).">\140".chr(989855744>>23)."\152\131\x66".chr(536870912>>23)."\x61q\x3f\105\53\x2a\126".chr(545259520>>23)."W\x28\x4b\102\116p\170".chr(402653184>>23)."\x34\x3f\120\x21H\142".chr(939524096>>23)."\131`R\x7a".chr(0100)."1".chr(0127)."\x57\113\105\x21Q".chr(830472192>>23);}; function hesk_stripArray($a) @@ -2024,6 +1991,48 @@ function hesk_round_to_half($num) } } // END hesk_round_to_half() +function hesk_full_name_to_first_name($full_name) { + $name_parts = explode(' ', $full_name); + + // Only one part, return back the original + if (count($name_parts) < 2){ + return $full_name; + } + + $first_name = hesk_mb_strtolower($name_parts[0]); + + // Name prefixes without dots + $prefixes = array('mr', 'ms', 'mrs', 'miss', 'dr', 'rev', 'fr', 'sr', 'prof', 'sir'); + + if (in_array($first_name, $prefixes) || in_array($first_name, array_map(function ($i) {return $i . '.';}, $prefixes))) { + if(isset($name_parts[2])) { + // Mr James Smith -> James + $first_name = $name_parts[1]; + } else { + // Mr Smith (no first name given) + return $full_name; + } + } + + // Detect LastName, FirstName + if (hesk_mb_substr($first_name, -1, 1) == ',') { + if (count($name_parts) == 2) { + $first_name = $name_parts[1]; + } else { + return $full_name; + } + } + + // If the first name doesn't have at least 3 chars, return the original + if(hesk_mb_strlen($first_name) < 3) { + return $full_name; + } + + // Return the name with first character uppercase + return hesk_ucfirst($first_name); + +} // END hesk_full_name_to_first_name() + function hesk_dateToString($dt, $returnName = 1, $returnTime = 0, $returnMonth = 0, $from_database = false) { global $hesk_settings, $hesklang; From dc8567620bfbc936fd8706468f015a3a3f2adcc5 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 16 May 2018 12:57:23 -0400 Subject: [PATCH 37/76] Update footer --- inc/footer.inc.php | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/inc/footer.inc.php b/inc/footer.inc.php index e7c6c02d..e1bfcf3b 100644 --- a/inc/footer.inc.php +++ b/inc/footer.inc.php @@ -57,23 +57,14 @@ purchasing a HESK license is strictly prohibited. To purchase a HESK license and support future HESK development please visit: https://www.hesk.com/buy.php *******************************************************************************/ -$hesk_settings['hesk_license']('HMgPSAxOw0KaWYgKGZpbGVfZXhpc3RzKEhFU0tfUEFUSCAuI -CdoZXNrX2xpY2Vuc2UucGhwJykpDQp7DQokaCA9ICghZW1wdHkoJF9TRVJWRVJbJ0hUVFBfSE9TVCddK -SkgPyAkX1NFUlZFUlsnSFRUUF9IT1NUJ10gOiAoKCFlbXB0eSgkX1NFUlZFUlsnU0VSVkVSX05BTUUnX -SkpID8gJF9TRVJWRVJbJ1NFUlZFUl9OQU1FJ10gOiBnZXRlbnYoJ1NFUlZFUl9OQU1FJykpOw0KJGggP -SBzdHJfcmVwbGFjZSgnd3d3LicsJycsc3RydG9sb3dlcigkaCkpOw0KaW5jbHVkZShIRVNLX1BBVEggL -iAnaGVza19saWNlbnNlLnBocCcpOw0KaWYgKGlzc2V0KCRoZXNrX3NldHRpbmdzWydsaWNlbnNlJ10pI -CYmIHN0cnBvcygkaGVza19zZXR0aW5nc1snbGljZW5zZSddLHNoYTEoJGguJ2gzJkZwMiNMYUEmNTkhd -yg4LlpjXSordVI1MTInKSkgIT09IGZhbHNlKQ0Kew0KJHMgPSAwOw0KfQ0KZWxzZQ0Kew0KZWNobyAnP -HAgc3R5bGU9InRleHQtYWxpZ246Y2VudGVyO2NvbG9yOnJlZDsiPklOVkFMSUQgTElDRU5TRSAoTk9UI -FJFR0lTVEVSRUQgRk9SICcuJGguJykhPC9wPic7DQp9DQp9DQppZiAoJHMpDQp7DQplY2hvICc8cCBzd -HlsZT0idGV4dC1hbGlnbjpjZW50ZXIiPjxzcGFuIGNsYXNzPSJzbWFsbGVyIj4mbmJzcDs8YnIgLz5Qb -3dlcmVkIGJ5IDxhIGhyZWY9Imh0dHBzOi8vd3d3Lmhlc2suY29tIiBjbGFzcz0ic21hbGxlciIgdGl0b -GU9IkZyZWUgUEhQIEhlbHAgRGVzayBTb2Z0d2FyZSI+SGVscCBEZXNrIFNvZnR3YXJlPC9hPiA8Yj5IR -VNLPC9iPiwgYnJvdWdodCB0byB5b3UgYnkgPGEgaHJlZj0iaHR0cHM6Ly93d3cuc3lzYWlkLmNvbS8/d -XRtX3NvdXJjZT1IZXNrJmFtcDt1dG1fbWVkaXVtPWNwYyZhbXA7dXRtX2NhbXBhaWduPUhlc2tQcm9kd -WN0X1RvX0hQIj5TeXNBaWQ8L2E+PC9zcGFuPjwvcD4nOw0KfQ0KZWNobyAnPC90ZD48L3RyPjwvdGFib -GU+PC9kaXY+JzsNCmluY2x1ZGUoSEVTS19QQVRIIC4gJ2Zvb3Rlci50eHQnKTsNCmVjaG8gJzwvYm9ke -T48L2h0bWw+Jzs=',"\112"); +$hesk_settings['hesk_license']('HAgc3R5bGU9InRleHQtYWxpZ246Y2VudGVyIj48c3BhbiBjb +GFzcz0ic21hbGxlciI+Jm5ic3A7PGJyIC8+UG93ZXJlZCBieSA8YSBocmVmPSJodHRwczovL3d3dy5oZ +XNrLmNvbSIgY2xhc3M9InNtYWxsZXIiIHRpdGxlPSJGcmVlIFBIUCBIZWxwIERlc2sgU29mdHdhcmUiP +khlbHAgRGVzayBTb2Z0d2FyZTwvYT4gPGI+SEVTSzwvYj4sIGJyb3VnaHQgdG8geW91IGJ5IDxhIGhyZ +WY9Imh0dHBzOi8vd3d3LnN5c2FpZC5jb20vP3V0bV9zb3VyY2U9SGVzayZhbXA7dXRtX21lZGl1bT1jc +GMmYW1wO3V0bV9jYW1wYWlnbj1IZXNrUHJvZHVjdF9Ub19IUCI+U3lzQWlkPC9hPjwvc3Bhbj48L3A+' +,"\120"); -exit(); +include(HESK_PATH . 'footer.txt'); + +$hesk_settings['security_cleanup']('exit'); \ No newline at end of file From 5608c32c7e8cdbd56b8d53718b30982cccd71011 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 16 May 2018 12:57:33 -0400 Subject: [PATCH 38/76] Update header --- inc/header.inc.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/inc/header.inc.php b/inc/header.inc.php index a436e76d..1ce7db78 100644 --- a/inc/header.inc.php +++ b/inc/header.inc.php @@ -208,9 +208,14 @@ header('X-UA-Compatible: IE=edge'); } } - // Use ReCaptcha API v2? + // Use ReCaptcha if (defined('RECAPTCHA')) { echo ''; + echo ''; } if (defined('VALIDATOR')) { From 0c13a6baf7c18d037cb4163e9cf79c7ac884e782 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 16 May 2018 12:57:41 -0400 Subject: [PATCH 39/76] Update pipe_functions --- inc/pipe_functions.inc.php | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/inc/pipe_functions.inc.php b/inc/pipe_functions.inc.php index 758ed9e8..fc4cbb47 100755 --- a/inc/pipe_functions.inc.php +++ b/inc/pipe_functions.inc.php @@ -27,7 +27,7 @@ require(HESK_PATH . 'inc/mail/email_parser.php'); /*** FUNCTIONS ***/ -function hesk_email2ticket($results, $pop3 = 0, $set_category = 1, $set_priority = -1) +function hesk_email2ticket($results, $protocol = 0, $set_category = 1, $set_priority = -1) { global $hesk_settings, $hesklang, $hesk_db_link, $ticket; @@ -269,7 +269,27 @@ function hesk_email2ticket($results, $pop3 = 0, $set_category = 1, $set_priority // Auto assign tickets if aplicable $tmpvar['owner'] = 0; - $tmpvar['openedby'] = $pop3 ? -2 : -1; + + // What protocol did we use to submit the ticket? + switch ($protocol) { + // POP3 fetching + case 1: + $audit_key = 'audit_submitted_via_pop'; + $tmpvar['openedby'] = -2; + break; + + // IMAP fetching + case 2: + $audit_key = 'audit_submitted_via_imap'; + $tmpvar['openedby'] = -3; + break; + + // Email piping + default: + $audit_key = 'audit_submitted_via_piping'; + $tmpvar['openedby'] = -1; + } + $autoassign_owner = hesk_autoAssignTicket($tmpvar['category']); @@ -277,6 +297,7 @@ function hesk_email2ticket($results, $pop3 = 0, $set_category = 1, $set_priority if ($autoassign_owner) { $tmpvar['owner'] = $autoassign_owner['id']; + $tmpvar['assignedby'] = -1; } // Custom fields will be empty as there is no reliable way of detecting them @@ -295,7 +316,7 @@ function hesk_email2ticket($results, $pop3 = 0, $set_category = 1, $set_priority // Insert ticket to database $ticket = hesk_newTicket($tmpvar); - mfh_insert_audit_trail_record($ticket['id'], 'TICKET', ($pop3 ? 'audit_submitted_via_pop' : 'audit_submitted_via_piping'), hesk_date()); + mfh_insert_audit_trail_record($ticket['id'], 'TICKET', $audit_key, hesk_date()); if ($autoassign_owner) { mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_autoassigned', hesk_date(), From 444493506dadf8889ac7a9d4669fe3adddb33832 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 16 May 2018 12:57:46 -0400 Subject: [PATCH 40/76] Update posting_functions --- inc/posting_functions.inc.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/inc/posting_functions.inc.php b/inc/posting_functions.inc.php index 8111bcde..f730f41e 100644 --- a/inc/posting_functions.inc.php +++ b/inc/posting_functions.inc.php @@ -58,6 +58,16 @@ function hesk_newTicket($ticket, $isVerified = true) $custom_what .= ", '" . (isset($ticket['custom'.$i]) ? hesk_dbEscape($ticket['custom'.$i]) : '') . "'"; } + // Need to insert "addigned by" value? + if (isset($ticket['assignedby'])) { + $ab_where = ', `assignedby` '; + $ab_what = ', ' . intval($ticket['assignedby']); + } else { + $ab_where = ''; + $ab_what = ''; + } + + // Insert ticket into database hesk_dbQuery(" INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . $tableName . "` @@ -88,6 +98,7 @@ function hesk_newTicket($ticket, $isVerified = true) `due_date`, `history` {$custom_where} + {$ab_where} ) VALUES ( @@ -117,6 +128,7 @@ function hesk_newTicket($ticket, $isVerified = true) {$due_date}, '' {$custom_what} + {$ab_what} ) "); From ec6e67c8aff9695b8ffb08a5535d974d9d813125 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 16 May 2018 13:03:32 -0400 Subject: [PATCH 41/76] Update show_search_form --- inc/show_search_form.inc.php | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/inc/show_search_form.inc.php b/inc/show_search_form.inc.php index 9962b853..60dd6355 100644 --- a/inc/show_search_form.inc.php +++ b/inc/show_search_form.inc.php @@ -52,6 +52,7 @@ if (!isset($date_input)) { /* Can view tickets that are unassigned or assigned to others? */ $can_view_ass_others = hesk_checkPermission('can_view_ass_others', 0); $can_view_unassigned = hesk_checkPermission('can_view_unassigned', 0); +$can_view_ass_by = hesk_checkPermission('can_view_ass_by', 0); /* Category options */ $category_options = ''; @@ -71,7 +72,7 @@ if (isset($hesk_settings['categories']) && count($hesk_settings['categories'])) } /* List of staff */ -if ($can_view_ass_others && !isset($admins)) { +if (($can_view_ass_others || $can_view_ass_by) && ! isset($admins)) { $admins = array(); $res2 = hesk_dbQuery("SELECT `id`,`name` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` ORDER BY `name` ASC"); while ($row = hesk_dbFetchAssoc($res2)) { @@ -134,7 +135,7 @@ $more2 = empty($_GET['more2']) ? 0 : 1;
- @@ -208,7 +209,7 @@ $more2 = empty($_GET['more2']) ? 0 : 1;
From 2c0bcb231aa43440ce0e656edb4f514c5d9e10d7 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 16 May 2018 18:36:22 -0400 Subject: [PATCH 44/76] Add text.php to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ad0887cb..6addd428 100644 --- a/.gitignore +++ b/.gitignore @@ -260,6 +260,7 @@ language/en/emails/new_ticket.txt language/en/emails/new_ticket_staff.txt language/en/emails/ticket_assigned_to_you.txt language/en/index.htm +language/en/text.php language/index.htm language/* !language/en From 988c78871015e9ffc43d019817632be760bfc2a8 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 16 May 2018 18:38:14 -0400 Subject: [PATCH 45/76] Pseudoupdate print --- print.php | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/print.php b/print.php index 2a0d0ab7..10119ebd 100644 --- a/print.php +++ b/print.php @@ -124,8 +124,8 @@ $modsForHesk_settings = mfh_getSettings(); ' . $hesklang['critical'] . ''; @@ -140,7 +140,7 @@ switch ($ticket['priority']) { $ticket['priority'] = $hesklang['low']; } -/* Set last replier name */ +// Set last replier name if ($ticket['lastreplier']) { if (empty($ticket['repliername'])) { $ticket['repliername'] = $hesklang['staff']; @@ -149,7 +149,7 @@ if ($ticket['lastreplier']) { $ticket['repliername'] = $ticket['name']; } -/* Other variables that need processing */ +// Other variables that need processing $ticket['dt'] = hesk_date($ticket['dt'], true); $ticket['lastchange'] = hesk_date($ticket['lastchange'], true); $random = mt_rand(10000, 99999); @@ -215,11 +215,11 @@ foreach ($hesk_settings['custom_fields'] as $k => $v) { $ticket[$k] = hesk_custom_date_display_format($ticket[$k], $v['value']['date_format']); break; } - ?> - : - - From ad8e242d533b3ec6567d7287ce60735efcafcfd0 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 16 May 2018 18:42:32 -0400 Subject: [PATCH 46/76] Update submit_ticket --- submit_ticket.php | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/submit_ticket.php b/submit_ticket.php index d11f5225..234d1858 100644 --- a/submit_ticket.php +++ b/submit_ticket.php @@ -82,23 +82,8 @@ if ($hesk_settings['question_use']) { // Check anti-SPAM image if ($hesk_settings['secimg_use'] && !isset($_SESSION['img_verified'])) { - // Using ReCaptcha? - if ($hesk_settings['recaptcha_use'] == 1) { - require(HESK_PATH . 'inc/recaptcha/recaptchalib.php'); - - $resp = recaptcha_check_answer($hesk_settings['recaptcha_private_key'], - hesk_getClientIP(), - hesk_POST('recaptcha_challenge_field', ''), - hesk_POST('recaptcha_response_field', '') - ); - if ($resp->is_valid) { - $_SESSION['img_verified'] = true; - } else { - $hesk_error_buffer['mysecnum'] = $hesklang['recaptcha_error']; - } - - } // Using ReCaptcha API v2? - elseif ($hesk_settings['recaptcha_use'] == 2) { + // Using reCAPTCHA? + if ($hesk_settings['recaptcha_use']) { require(HESK_PATH . 'inc/recaptcha/recaptchalib_v2.php'); $resp = null; @@ -410,6 +395,7 @@ $tmpvar['owner'] = 0; $autoassign_owner = hesk_autoAssignTicket($tmpvar['category']); if ($autoassign_owner) { $tmpvar['owner'] = $autoassign_owner['id']; + $tmpvar['assignedby'] = -1; } // Insert attachments @@ -462,7 +448,7 @@ if ($createTicket) { $ticket = hesk_newTicket($tmpvar); mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_submitted_by', hesk_date(), - array(0 => $tmpvar['name'])); + array(0 => $hesklang['customer'])); if ($autoassign_owner) { mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_autoassigned', hesk_date(), From eb32da3c3e36de493c2e745882eacc0838a65e57 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 16 May 2018 18:52:10 -0400 Subject: [PATCH 47/76] Update print_template --- inc/print_template.php | 151 +++++++++++++++++++++++++++++++++++++++++ print.php | 135 +----------------------------------- 2 files changed, 152 insertions(+), 134 deletions(-) create mode 100644 inc/print_template.php diff --git a/inc/print_template.php b/inc/print_template.php new file mode 100644 index 00000000..b18d5567 --- /dev/null +++ b/inc/print_template.php @@ -0,0 +1,151 @@ +' . $hesklang['critical'] . ''; + break; + case 1: + $ticket['priority'] = '' . $hesklang['high'] . ''; + break; + case 2: + $ticket['priority'] = $hesklang['medium']; + break; + default: + $ticket['priority'] = $hesklang['low']; +} + +// Set last replier name +if ($ticket['lastreplier']) { + if (empty($ticket['repliername'])) { + $ticket['repliername'] = $hesklang['staff']; + } +} else { + $ticket['repliername'] = $ticket['name']; +} + +// Other variables that need processing +$ticket['dt'] = hesk_date($ticket['dt'], true); +$ticket['lastchange'] = hesk_date($ticket['lastchange'], true); +$random = mt_rand(10000, 99999); + +// Print ticket head +echo ' +

' . $ticket['subject'] . '

+
+ + + + + + + + + + + + +'; + +// Show IP and time worked to staff +if (!empty($_SESSION['id'])) { + echo ' + + + + + + '; +} + +echo ''; +// Assigned to? +if ($ticket['owner'] && !empty($_SESSION['id'])) { + $ticket['owner'] = hesk_getOwnerName($ticket['owner']); + echo ' + + + '; +} + + +echo ' + + + '; +echo ''; + +// Custom fields +$num_cols = 0; +echo ''; +foreach ($hesk_settings['custom_fields'] as $k => $v) { + if (($v['use'] == 1 || (! empty($_SESSION['id']) && $v['use'] == 2)) && hesk_is_custom_field_in_category($k, $ticket['category'])) { + if ($num_cols == 3) { + echo ''; + $num_cols = 0; + } + + switch ($v['type']) { + case 'date': + $ticket[$k] = hesk_custom_date_display_format($ticket[$k], $v['value']['date_format']); + break; + } + ?> + + +
'; + +// Print initial ticket message +if ($ticket['message'] != '') { + $newMessage = hesk_unhortenUrl($ticket['message']); + if ($ticket['html']) { + $newMessage = hesk_html_entity_decode($newMessage); + } + echo '

' . $newMessage . '

'; +} + + +// Print replies +while ($reply = hesk_dbFetchAssoc($res)) { + $reply['dt'] = hesk_date($reply['dt'], true); + $theReply = hesk_unhortenUrl($reply['message']); + if ($reply['html']) { + $theReply = hesk_html_entity_decode($theReply); + } + + echo ' +
+ +
' . $hesklang['trackID'] . ':' . $trackingID . '' . $hesklang['ticket_status'] . ':' . $hesklang[$ticket['statusKey']] . '' . $hesklang['created_on'] . ':' . $ticket['dt'] . '
' . $hesklang['last_update'] . ':' . $ticket['lastchange'] . '' . $hesklang['last_replier'] . ':' . $ticket['repliername'] . '' . $hesklang['category'] . ':' . $category['name'] . '
' . $hesklang['ts'] . ':' . $ticket['time_worked'] . '' . $hesklang['ip'] . ':' . $ticket['ip'] . '' . $hesklang['email'] . ':' . $ticket['email'] . '
' . $hesklang['taso3'] . '' . $ticket['owner'] . '' . $hesklang['name'] . ':' . $ticket['name'] . '
:
+ + + + +
' . $hesklang['date'] . ':' . $reply['dt'] . '' . $hesklang['name'] . ':' . $reply['name'] . '
+ +
' . $theReply . '
+ '; +} + +// Print "end of ticket" message +echo '' . $hesklang['end_ticket'] . ""; diff --git a/print.php b/print.php index 10119ebd..f0fa6850 100644 --- a/print.php +++ b/print.php @@ -124,142 +124,9 @@ $modsForHesk_settings = mfh_getSettings(); ' . $hesklang['critical'] . ''; - break; - case 1: - $ticket['priority'] = '' . $hesklang['high'] . ''; - break; - case 2: - $ticket['priority'] = $hesklang['medium']; - break; - default: - $ticket['priority'] = $hesklang['low']; -} - -// Set last replier name -if ($ticket['lastreplier']) { - if (empty($ticket['repliername'])) { - $ticket['repliername'] = $hesklang['staff']; - } -} else { - $ticket['repliername'] = $ticket['name']; -} - -// Other variables that need processing -$ticket['dt'] = hesk_date($ticket['dt'], true); -$ticket['lastchange'] = hesk_date($ticket['lastchange'], true); -$random = mt_rand(10000, 99999); - -// Print ticket head -echo ' -

' . $ticket['subject'] . '

-
- - - - - - - - - - - - -'; - -// Show IP and time worked to staff -if (!empty($_SESSION['id'])) { - echo ' - - - - - - '; -} - -echo ''; -// Assigned to? -if ($ticket['owner'] && !empty($_SESSION['id'])) { - $ticket['owner'] = hesk_getOwnerName($ticket['owner']); - echo ' - - - '; -} - - -echo ' - - - '; -echo ''; - -// Custom fields -$num_cols = 0; -echo ''; -foreach ($hesk_settings['custom_fields'] as $k => $v) { - if (($v['use'] == 1 || (! empty($_SESSION['id']) && $v['use'] == 2)) && hesk_is_custom_field_in_category($k, $ticket['category'])) { - if ($num_cols == 3) { - echo ''; - $num_cols = 0; - } - - switch ($v['type']) { - case 'date': - $ticket[$k] = hesk_custom_date_display_format($ticket[$k], $v['value']['date_format']); - break; - } - */?>
'; - -// Print initial ticket message -if ($ticket['message'] != '') { - $newMessage = hesk_unhortenUrl($ticket['message']); - if ($ticket['html']) { - $newMessage = hesk_html_entity_decode($newMessage); - } - echo '

' . $newMessage . '

'; -} - - -// Print replies -while ($reply = hesk_dbFetchAssoc($res)) { - $reply['dt'] = hesk_date($reply['dt'], true); - $theReply = hesk_unhortenUrl($reply['message']); - if ($reply['html']) { - $theReply = hesk_html_entity_decode($theReply); - } - - echo ' -
- -
' . $hesklang['trackID'] . ':' . $trackingID . '' . $hesklang['ticket_status'] . ':' . $hesklang[$ticket['statusKey']] . '' . $hesklang['created_on'] . ':' . $ticket['dt'] . '
' . $hesklang['last_update'] . ':' . $ticket['lastchange'] . '' . $hesklang['last_replier'] . ':' . $ticket['repliername'] . '' . $hesklang['category'] . ':' . $category['name'] . '
' . $hesklang['ts'] . ':' . $ticket['time_worked'] . '' . $hesklang['ip'] . ':' . $ticket['ip'] . '' . $hesklang['email'] . ':' . $ticket['email'] . '
' . $hesklang['taso3'] . '' . $ticket['owner'] . '' . $hesklang['name'] . ':' . $ticket['name'] . '
- - - - -
' . $hesklang['date'] . ':' . $reply['dt'] . '' . $hesklang['name'] . ':' . $reply['name'] . '
- -
' . $theReply . '
- '; -} // Print "end of ticket" message -echo $hesklang['end_ticket'];*/ +echo $hesklang['end_ticket']; require_once(HESK_PATH . 'inc/print_template.inc.php'); ?> From b0934f7c4c2df8bc3f863d638b55cbade95e3088 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 16 May 2018 18:55:16 -0400 Subject: [PATCH 48/76] Update export_functions --- admin/export.php | 340 ---------------- inc/export_functions.inc.php | 372 ++++++++++++++++++ ...nt_template.php => print_template.inc.php} | 0 3 files changed, 372 insertions(+), 340 deletions(-) create mode 100644 inc/export_functions.inc.php rename inc/{print_template.php => print_template.inc.php} (100%) diff --git a/admin/export.php b/admin/export.php index c4c1e699..ec67a22c 100644 --- a/admin/export.php +++ b/admin/export.php @@ -298,346 +298,6 @@ while ($row = hesk_dbFetchAssoc($res2)) { // Generate export file if (isset($_GET['w'])) { - /* - * // We'll need HH:MM:SS format for hesk_date() here - $hesk_settings['timeformat'] = 'H:i:s'; - - // Get staff names - $admins = array(); - $result = hesk_dbQuery("SELECT `id`,`name` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` ORDER BY `name` ASC"); - while ($row = hesk_dbFetchAssoc($result)) { - $admins[$row['id']] = $row['name']; - } - - // This will be the export directory - $export_dir = HESK_PATH.$hesk_settings['cache_dir'].'/'; - - // This will be the name of the export and the XML file - $export_name = 'hesk_export_' . date('Y-m-d_H-i-s') . '_' . mt_rand(10000, 99999); - $save_to = $export_dir . $export_name . '.xml'; - - // Do we have the export directory? - if (is_dir($export_dir) || (@mkdir($export_dir, 0777) && is_writable($export_dir))) { - // Is there an index.htm file? - if (!file_exists($export_dir.'index.htm')) { - @file_put_contents($export_dir.'index.htm', ''); - } - - // Cleanup old files - hesk_purge_cache('export', 86400); - } else { - hesk_error($hesklang['ede']); - } - - // Make sure the file can be saved and written to - @file_put_contents($save_to, ''); - if (!file_exists($save_to)) { - hesk_error($hesklang['eef']); - } - - // Start generating the report message and generating the export - $success_msg = ''; - $flush_me = '

'; - $flush_me .= hesk_date() . " | {$hesklang['inite']} "; - - if ($date_from == $date_to) { - $flush_me .= "(" . hesk_dateToString($date_from, 0) . ")
\n"; - } else { - $flush_me .= "(" . hesk_dateToString($date_from, 0) . " - " . hesk_dateToString($date_to, 0) . ")
\n"; - } - - // Start generating file contents - $tmp = ' - - - - - - - 8250 - 16275 - 360 - 90 - False - False - - - - - - - - - -'; - - // Define column width - $tmp .= ' - - - - - - - - - - - - - - '; - - foreach ($hesk_settings['custom_fields'] as $k => $v) { - if ($v['use']) { - $tmp .= '' . "\n"; - } - } - - // Define first row (header) - $tmp .= ' - - # - ' . $hesklang['trackID'] . ' - ' . $hesklang['date'] . ' - ' . $hesklang['last_update'] . ' - ' . $hesklang['name'] . ' - ' . $hesklang['email'] . ' - ' . $hesklang['category'] . ' - ' . $hesklang['priority'] . ' - ' . $hesklang['status'] . ' - ' . $hesklang['subject'] . ' - ' . $hesklang['message'] . ' - ' . $hesklang['owner'] . ' - ' . $hesklang['ts'] . ' - '; - - foreach ($hesk_settings['custom_fields'] as $k => $v) { - if ($v['use']) { - $tmp .= '' . $v['name'] . '' . "\n"; - } - } - - $tmp .= "\n"; - - // Write what we have by now into the XML file - file_put_contents($save_to, $tmp, FILE_APPEND); - $flush_me .= hesk_date() . " | {$hesklang['gXML']}
\n"; - - // OK, now start dumping data and writing it into the file - $tickets_exported = 0; - $save_after = 100; - $this_round = 0; - $tmp = ''; - - $result = hesk_dbQuery($sql); - while ($ticket = hesk_dbFetchAssoc($result)) { - $ticket['status'] = mfh_getDisplayTextForStatusId($ticket['status']); - - switch ($ticket['priority']) { - case 0: - $ticket['priority'] = $hesklang['critical']; - break; - case 1: - $ticket['priority'] = $hesklang['high']; - break; - case 2: - $ticket['priority'] = $hesklang['medium']; - break; - default: - $ticket['priority'] = $hesklang['low']; - } - - $ticket['archive'] = !($ticket['archive']) ? $hesklang['no'] : $hesklang['yes']; - $ticket['message'] = hesk_msgToPlain($ticket['message'], 1, 0); - $ticket['subject'] = hesk_msgToPlain($ticket['subject'], 1, 0); - $ticket['owner'] = isset($admins[$ticket['owner']]) ? $admins[$ticket['owner']] : ''; - $ticket['category'] = isset($my_cat[$ticket['category']]) ? $my_cat[$ticket['category']] : ''; - - // Format for export dates - $hesk_settings['timeformat'] = "Y-m-d\TH:i:s\.000"; - - // Create row for the XML file - $tmp .= ' - -' . $ticket['id'] . ' - -' . hesk_date($ticket['dt'], true) . ' -' . hesk_date($ticket['lastchange'], true) . ' - - - - - - - - - -'; - - // Add custom fields - foreach ($hesk_settings['custom_fields'] as $k=>$v) { - if ($v['use']) { - switch ($v['type']) { - case 'date': - $tmp_dt = hesk_custom_date_display_format($ticket[$k], 'Y-m-d\T00:00:00.000'); - $tmp .= strlen($tmp_dt) ? ''.$tmp_dt : ''; - $tmp .= " \n"; - break; - default: - $tmp .= ' ' . "\n"; - } - } - } - - $tmp .= "\n"; - - // Write every 100 rows into the file - if ($this_round >= $save_after) { - file_put_contents($save_to, $tmp, FILE_APPEND); - $this_round = 0; - $tmp = ''; - usleep(1); - } - - $tickets_exported++; - $this_round++; - } // End of while loop - - // Go back to the HH:MM:SS format for hesk_date() - $hesk_settings['timeformat'] = 'H:i:s'; - - // Append any remaining rows into the file - if ($this_round > 0) { - file_put_contents($save_to, $tmp, FILE_APPEND); - } - - // If any tickets were exported, continue, otherwise cleanup - if ($tickets_exported > 0) { - // Finish the XML file - $tmp = ' -
- - -
-