Compare commits

...

2235 Commits

Author SHA1 Message Date
6fcd22b533 Update to 2018.2.0 2019-01-26 01:12:54 -07:00
Mike Koch
fb81b23f6b
Update installer 2018-07-22 21:16:25 -04:00
Mike Koch
5f58ecb77f
Update installer 2018-07-22 21:16:24 -04:00
Mike Koch
ff9b7ceb9c Merge branch '648-no-cdns' into 'master'
Resolve "Don't Rely On External CDNs"

See merge request mike-koch/Mods-for-HESK!109
2018-07-21 02:07:01 +00:00
Mike Koch
983250665c
#648 Update leaflet to 0.7.7, don't use external CDN 2018-07-20 22:05:46 -04:00
Mike Koch
6205642cdb
#648 Update FontAwesome to 4.7, don't use external CDN 2018-07-20 21:58:18 -04:00
Mike Koch
b41021f567 Merge branch '651-due-date-permissions' into 'master'
Resolve "Problem: Users Cannot Change Ticket Due Date Without "Can Edit Tickets Permission""

See merge request mike-koch/Mods-for-HESK!108
2018-07-20 16:56:39 +00:00
Mike Koch
1de92c0d26
#651 Add 'can_change_due_date' permission 2018-07-20 12:55:54 -04:00
Mike Koch
510544f4ba Merge branch '647-fix-code-on-show-tickets' into 'master'
Resolve "'Show Tickets' on the Admin Panel results in Code View."

See merge request mike-koch/Mods-for-HESK!107
2018-07-19 01:53:47 +00:00
Mike Koch
6180d5d30c
#647 Don't try to show license on show_tickets 2018-07-18 21:53:05 -04:00
Mike Koch
11d6213208 Merge branch '641-invis-recaptcha' into 'master'
Resolve "Invisible Recapcha is not working"

See merge request mike-koch/Mods-for-HESK!106
2018-07-19 01:42:53 +00:00
Mike Koch
c4a9368a7b
#641 Fix invisible recaptcha 2018-07-18 21:39:33 -04:00
Mike Koch
823874e0a1 Merge branch '640-email-required' into 'master'
Resolve "Email required issue"

See merge request mike-koch/Mods-for-HESK!105
2018-07-18 01:38:32 +00:00
Mike Koch
7fc3fb042d
#640 Remove unnecessary subtext, fix required email issue 2018-07-17 21:37:42 -04:00
Mike Koch
a1fc11cd93 Merge branch '644-remove-help-files' into 'master'
Resolve "help/misc.html not updated"

See merge request mike-koch/Mods-for-HESK!104
2018-07-11 01:46:18 +00:00
Mike Koch
66fdd15616
Delete help files 2018-07-10 21:45:47 -04:00
Mike Koch
781e3b0434 Merge branch '644-remove-help-files' into 'master'
Resolve "help/misc.html not updated"

See merge request mike-koch/Mods-for-HESK!103
2018-07-11 01:37:20 +00:00
Mike Koch
12a5b57fab
#644 Remove help files from source control 2018-07-10 21:35:43 -04:00
Mike Koch
179df881c1 Merge branch 'hesk-2-8-2' into 'master'
HESK 2.8.2 Update

See merge request mike-koch/Mods-for-HESK!101
2018-07-09 16:52:39 +00:00
Mike Koch
9260af4734 Merge branch '642-fix-email-headers' into 'master'
Resolve "Mail header sent in a mail body"

Closes #642

See merge request mike-koch/Mods-for-HESK!102
2018-07-09 16:52:16 +00:00
Mike Koch
7efb6fc11e
Fixes #642 fix email headers 2018-07-09 12:50:09 -04:00
Mike Koch
9ee7e3e31b
Fix array designation for 5.3 2018-07-09 12:32:20 -04:00
Mike Koch
205035fa0c
Update build #, version # 2018-07-09 12:28:55 -04:00
Mike Koch
f39dbdfd87
Update footer for HESK 2.8.2 2018-07-09 12:16:40 -04:00
Mike Koch
c11a9d3a80
Update email_functions 2018-07-08 22:01:01 -04:00
Mike Koch
4418a36ccf
Update admin_functions and common from HESK 2.8.2 2018-07-08 21:58:07 -04:00
Mike Koch
e3d4fc89dc
Add migration for service message languages 2018-07-08 21:55:53 -04:00
Mike Koch
748ae25fc2
Update installer 2018-05-19 23:10:26 -04:00
Mike Koch
27e3729fcf
Update installer 2018-05-19 23:05:33 -04:00
Mike Koch
4e01fa7971
Work on installer, fix a couple reply API bugs 2018-05-19 22:30:34 -04:00
Mike Koch
16b1e7c491 Merge branch '3-4-0' into 'master'
2018.1.0 Update

See merge request mike-koch/Mods-for-HESK!100
2018-05-20 01:58:08 +00:00
Mike Koch
fccfde3414
Slight manage_users ui update 2018-05-19 20:59:30 -04:00
Mike Koch
3458f240b7
Users who can handle cats can see all of them on the edit user/perm group pages 2018-05-19 20:30:31 -04:00
Mike Koch
7a3d2f20a9
Actually skip the tests 2018-05-19 12:11:44 -04:00
Mike Koch
d15d4bf8d1
Update MFH version check URI 2018-05-19 10:51:18 -04:00
Mike Koch
d4a48c6c73
Fix admin visibility of tickets on calendar, included assignedByMe to filer 2018-05-19 10:50:57 -04:00
Mike Koch
26de217fef
Change 'Ticket History' to 'Audit Log' 2018-05-18 23:21:30 -04:00
Mike Koch
4d71bf45ad
Skip tests I'm too lazy to fix right now 2018-05-18 23:18:40 -04:00
Mike Koch
4c54ec677c
Fixing tests, round two 2018-05-18 20:46:46 -04:00
Mike Koch
1fffac8b8c
Fix tests I hope 2018-05-18 20:35:30 -04:00
Mike Koch
0c04660f3f
Reset color options on modal after saving 2018-05-18 20:33:29 -04:00
Mike Koch
0bb182220a
Fix new ticket validation via API 2018-05-18 20:28:33 -04:00
Mike Koch
a292d0dd30
Fix category existence when creating new ticket via API 2018-05-18 20:17:56 -04:00
Mike Koch
ea8b89ac04
Fix dates being inserted into the audit trail 2018-05-18 20:14:55 -04:00
Mike Koch
bc6299e5cf
Fix update due date link, manager check, change due date btn visibility 2018-05-18 19:48:24 -04:00
Mike Koch
83e2ec500a
Fix permission group dropdown not matching checkboxes 2018-05-18 18:52:17 -04:00
Mike Koch
ba733a2619
Don't blow up when a service message's user is deleted 2018-05-18 18:37:43 -04:00
Mike Koch
1ca4780d82 Merge branch 'hesk-2-8-0-update' into '3-4-0'
HESK 2.8.0/2.8.1 Update

See merge request mike-koch/Mods-for-HESK!99
2018-05-18 16:51:05 +00:00
Mike Koch
c133b11bf6
HESK 2.8.1 update 2018-05-18 12:42:25 -04:00
Mike Koch
a1fcc93f4e
Fix missing categories on admin_main export 2018-05-17 20:08:59 -04:00
Mike Koch
3ef8494b2a
Fixed print page, fixed flipped audit replacement values' 2018-05-17 20:01:02 -04:00
Mike Koch
b5374b9e6e
Fix LAST_REPLY_BY description 2018-05-17 19:10:34 -04:00
Mike Koch
b5890e1f59
Add IMAP fetching audit trail record 2018-05-17 19:08:22 -04:00
Mike Koch
2e9f040519
Properly set assignedby, fix hesk_notifyAssignedStaff, fix audit trail 2018-05-17 19:06:30 -04:00
Mike Koch
f02af695b8
privacy_functions modified to work with MfH 2018-05-17 18:57:21 -04:00
Mike Koch
6cad99e6c3
Updated pages for 2.8.0 2018-05-17 18:21:14 -04:00
Mike Koch
d2096f366e
Changes and fixes' 2018-05-17 00:08:34 -04:00
Mike Koch
db6e971ccc
Language, settings, ticket list updates 2018-05-16 22:02:41 -04:00
Mike Koch
c5804612ae
update gitignore 2018-05-16 21:44:02 -04:00
Mike Koch
aed9fda0aa
Initial commit of these 3 files for now 2018-05-16 19:02:29 -04:00
Mike Koch
b0934f7c4c
Update export_functions 2018-05-16 18:55:16 -04:00
Mike Koch
eb32da3c3e
Update print_template 2018-05-16 18:52:10 -04:00
Mike Koch
ad8e242d53
Update submit_ticket 2018-05-16 18:42:32 -04:00
Mike Koch
988c788710
Pseudoupdate print 2018-05-16 18:38:14 -04:00
Mike Koch
2c0bcb231a
Add text.php to gitignore 2018-05-16 18:36:22 -04:00
Mike Koch
9d1f2cbfdf
Update index 2018-05-16 18:35:00 -04:00
Mike Koch
32a2cde309
Update ticket_list 2018-05-16 18:15:42 -04:00
Mike Koch
ec6e67c8af
Update show_search_form 2018-05-16 13:03:32 -04:00
Mike Koch
444493506d
Update posting_functions 2018-05-16 12:57:46 -04:00
Mike Koch
0c13a6baf7
Update pipe_functions 2018-05-16 12:57:41 -04:00
Mike Koch
5608c32c7e
Update header 2018-05-16 12:57:33 -04:00
Mike Koch
dc8567620b
Update footer 2018-05-16 12:57:23 -04:00
Mike Koch
49eefce540
Update common 2018-05-16 12:57:18 -04:00
Mike Koch
17c5607ce7
Add assignedBy to ticket 2018-05-16 12:57:11 -04:00
Mike Koch
6be05bebfe
Update email_functions 2018-05-16 12:56:55 -04:00
Mike Koch
c92191f396
Update admin_functions 2018-05-16 12:20:37 -04:00
Mike Koch
50ea0aafd6
Remove TODO 2018-05-15 13:03:07 -04:00
Mike Koch
fff00edbef
Update admin_functions -- was actually in common for MFH! 2018-05-15 13:02:53 -04:00
Mike Koch
b5af789662
Update service_messages, hesk_style 2018-05-15 13:02:04 -04:00
Mike Koch
c380ea0bc5
Update password 2018-05-15 13:00:21 -04:00
Mike Koch
05af7b17a5
Update manage_users 2018-05-15 12:58:26 -04:00
Mike Koch
ef4ab7a2ea
Update manage_ticket_templates 2018-05-15 12:54:04 -04:00
Mike Koch
4a65599985
Update manage_knowledgebase 2018-05-15 12:53:33 -04:00
Mike Koch
682e39fe5d
Update manage_categories 2018-05-15 12:50:00 -04:00
Mike Koch
075c8c006d
Update manage_canned 2018-05-15 12:48:03 -04:00
Mike Koch
b215f885a9
Update mail 2018-05-15 12:47:13 -04:00
Mike Koch
53a9860388
Update admin/index 2018-05-15 12:45:23 -04:00
Mike Koch
007fcb5575
Update find_tickets 2018-05-15 12:45:17 -04:00
Mike Koch
d84776d1aa
Update export.php 2018-05-15 12:45:06 -04:00
Mike Koch
5e5a8193e9
export updated.... for the most part 2018-05-15 12:32:40 -04:00
Mike Koch
0823390738
Update manage_email_templates 2018-05-14 19:36:54 -04:00
Mike Koch
be0a8e52ca
Update export 2018-05-14 19:36:47 -04:00
Mike Koch
f102baf753
Update delete_tickets 2018-05-14 19:36:42 -04:00
Mike Koch
035e4f0a79
Update custom_fields 2018-05-14 19:36:37 -04:00
Mike Koch
aa1667261d
Update banned_ips 2018-05-14 19:36:31 -04:00
Mike Koch
f24a80be6a
Update banned_emails 2018-05-14 19:36:26 -04:00
Mike Koch
c03ca62005
Update assign_owner 2018-05-14 19:36:00 -04:00
Mike Koch
2f44516c7b
Update admin_ticket 2018-05-14 19:09:57 -04:00
Mike Koch
52b47075d9
Update admin_submit_ticket 2018-05-14 18:54:50 -04:00
Mike Koch
1325f17bf8
admin_settings(_save) updated 2018-05-14 18:53:44 -04:00
Mike Koch
5150656914
Updated admin_main, updated part of admin_settings 2018-05-14 12:51:37 -04:00
Mike Koch
874cd36bd0 Merge branch '619-create-ticket-api-issues' into '3-4-0'
Resolve "Issue with API submitting New Ticket"

See merge request mike-koch/Mods-for-HESK!98
2018-04-16 16:21:31 +00:00
Mike Koch
aa462d16f8
Fix some API issues' 2018-04-16 12:20:43 -04:00
Mike Koch
4a73524c32 Merge branch '340-post-customer-reply' into '3-4-0'
Add Customer Reply POST API Endpoint

See merge request mike-koch/Mods-for-HESK!97
2018-04-16 16:15:07 +00:00
Mike Koch
e9db9796e3
Default the IP address to the requester's IP address 2018-04-11 12:57:23 -04:00
Mike Koch
90df3de829
Allow sending over http if the magic constant is present 2018-04-11 12:37:51 -04:00
Mike Koch
6fa6c7b686
Add ability to reply via API 2018-04-10 13:11:48 -04:00
Mike Koch
9ae259dff6
Working on reply endpoint. Just need to send out the email. 2018-04-09 13:01:49 -04:00
Mike Koch
669edf832c
Starting to work on reply API endpoint 2018-04-08 22:07:13 -04:00
Mike Koch
d97fe5a81c
Move MFH text to separate files 2018-03-24 22:04:39 -04:00
Mike Koch
e88bb3565d Merge branch 'bug-fixes' into 'master'
3.3.1 Update

See merge request mike-koch/Mods-for-HESK!96
2018-03-23 16:58:24 +00:00
Mike Koch
306c2d370a
Add update migration 2018-03-23 12:52:30 -04:00
Mike Koch
b3245aa38d
Update build 2018-03-23 12:48:55 -04:00
Mike Koch
ed04663d08
Fix changing ticket due date 2018-03-22 22:09:17 -04:00
Mike Koch
352b3a9f37
Fix issue with category auto-assign 2018-03-22 21:54:55 -04:00
Mike Koch
f290fd7519
Update TinyMCE version 2018-03-22 21:44:43 -04:00
Mike Koch
56eeaea61e
Fix non-contentified strings 2018-03-22 21:43:29 -04:00
Mike Koch
34895de5bc
Business hours should be hidden 2018-03-22 21:42:00 -04:00
1017b64913 Pull 3.3.0 from upstream 2018-03-19 21:59:22 -06:00
100c22eb78 CSS adjustments 2018-03-19 21:46:37 -06:00
Mike Koch
62c1661f04
Add missing migration 2018-03-02 19:38:11 -05:00
Mike Koch
d7ae1f0101
Fix migration 2018-03-02 19:12:50 -05:00
Mike Koch
6b0854a273
Fix validator 2018-03-02 18:53:36 -05:00
Mike Koch
3dd897f732
Update build 2018-03-02 12:47:26 -05:00
Mike Koch
e56ef4d608 Merge branch '3-3-0' into 'master'
Mods for HESK 3.3.0 Update

Closes #599

See merge request mike-koch/Mods-for-HESK!95
2018-03-02 17:44:19 +00:00
Mike Koch
37156a8ac7
Add update migration 2018-03-02 12:43:50 -05:00
Mike Koch
7fe96fda96
Update install files 2018-03-02 12:43:33 -05:00
Mike Koch
9d874e10a5 Merge branch 'master' into '3-3-0'
# Conflicts:
#   api/BusinessLogic/Emails/BasicEmailSender.php
#   install/migrations/core.php
2018-03-02 17:41:56 +00:00
Mike Koch
318462164d
Default status translation to english if it doesn't exist 2018-03-02 12:34:11 -05:00
Mike Koch
af5ba09d38
Default to english if status name is not found for the given language 2018-03-02 12:25:37 -05:00
Mike Koch
34b32761ce
Fix tests... again 2018-03-01 20:12:56 -05:00
Mike Koch
7350c5105d
Fix tesets 2018-03-01 20:07:03 -05:00
Mike Koch
fea2d7b3c1 Merge branch 'hesk-2-7-6-update' into '3-3-0'
HESK 2.7.6 Update

See merge request mike-koch/Mods-for-HESK!94
2018-03-02 00:55:08 +00:00
Mike Koch
f11353c41b
CI should use 7.2 for testing, add 7.2 to validation 2018-02-28 21:54:29 -05:00
Mike Koch
8bad3ed188
Update HESK version in install_functions 2018-02-28 21:49:04 -05:00
Mike Koch
f40df54772
Update rest of files to HESK 2.7.6 2018-02-28 21:45:03 -05:00
Mike Koch
155b6c5926
Update a bunch of files for HESK 2.7.6 2018-02-28 21:21:47 -05:00
Mike Koch
559f2d7011 Merge branch '520-email-custom-field' into '3-3-0'
Resolve "cc/bcc Email Custom Fields Not Being Appended To Sent Emails"

See merge request mike-koch/Mods-for-HESK!93
2018-02-20 03:02:35 +00:00
Mike Koch
275a1691d1
cc/bcc fields work properly in api 2018-02-19 22:01:42 -05:00
Mike Koch
81b27ddb2e
Add cc/bcc to rest API, re-enable in email_functions 2018-02-19 13:03:34 -05:00
Mike Koch
904202488d
Add an 'emails to receive' option for email custom fields 2018-02-19 12:40:12 -05:00
Mike Koch
2b089f3907
Minor UI changes 2018-02-11 22:07:12 -05:00
Mike Koch
35ed664dfd
Only allow users to modify permissions that they have access to 2018-02-11 22:00:44 -05:00
Mike Koch
48b28fc3cd
Only modify permissions the user has access to 2018-02-07 22:03:55 -05:00
Mike Koch
4bd4eec53d
Starting on fixing permission group creation/edit abilities 2018-02-06 22:04:16 -05:00
Mike Koch
71bb5af435
Working on permission issues w/permission groups 2018-02-04 22:10:40 -05:00
Mike Koch
ff6ec13df4 Merge branch 'improve-db-validator' into '3-3-0'
Improve db validator

See merge request mike-koch/Mods-for-HESK!91
2018-02-05 02:17:13 +00:00
Mike Koch
22ecc4804e
Improve the validator 2018-02-04 21:16:18 -05:00
Mike Koch
5696968f25
Working on improving the validator 2018-02-03 22:16:00 -05:00
Mike Koch
d383bc0c00
Fix issue where 3.0.0 beta/rc 1 could not update 2018-02-02 22:18:43 -05:00
Mike Koch
90dc2d691a
Deactivated some migrations as they're no longer needed.... might break some new installs 2018-02-02 22:05:23 -05:00
Mike Koch
5865cb722d
Fix custom field description for select fields 2018-02-02 21:57:33 -05:00
Mike Koch
dd0edef2ba
Fixes #599 Only show active users in PMs 2018-02-02 21:28:15 -05:00
Mike Koch
400c216869
Small UI change, change 'Home' to 'Tickets' 2018-02-01 22:02:51 -05:00
Mike Koch
f2001ec446
Add back button to login page 2018-02-01 21:43:01 -05:00
Mike Koch
d2cb5ad251 Merge branch 'attachment-download-size' into '3-3-0'
Show attachment size in attachment info

See merge request mike-koch/Mods-for-HESK!90
2018-02-02 02:29:05 +00:00
Mike Koch
2ffa6c130c
Show attachment size in attachment info 2018-02-01 21:27:34 -05:00
Mike Koch
98a033798f Merge branch 'add-due-date-to-ticket-home' into '3-3-0'
Show due date on ticket home page

See merge request mike-koch/Mods-for-HESK!89
2018-02-02 01:08:58 +00:00
Mike Koch
4e2b21ae60
Show due date on ticket home page 2018-01-31 22:04:11 -05:00
Mike Koch
a57befcc69 Merge branch '608-ticket-rows' into '3-3-0'
Resolve "Add Setting to Highlight Tickets by Priority"

See merge request mike-koch/Mods-for-HESK!88
2018-01-31 18:00:01 +00:00
Mike Koch
c4f080184c
Add setting to highlight all ticket rows based on priority 2018-01-31 12:54:31 -05:00
Mike Koch
1978948f4a Merge branch 'more-cal-improvements' into '3-3-0'
Moar Calendar Improvements

See merge request mike-koch/Mods-for-HESK!87
2018-01-31 03:29:10 +00:00
Mike Koch
af45726fe6
Add ability to hide start time 2018-01-30 22:24:12 -05:00
Mike Koch
df780f4546
Add business-hours API endpoint 2018-01-30 21:24:33 -05:00
Mike Koch
09b371036a
Business hours can be added to the calendar 2018-01-29 22:12:00 -05:00
Mike Koch
7c884582a2
Working on adding business hours to the calendar 2018-01-28 22:05:09 -05:00
Mike Koch
cfabdb950d Merge branch '357-calendar-planning-phase-two' into '3-3-0'
Resolve "Calendar Planning, Phase Two"

See merge request mike-koch/Mods-for-HESK!86
2018-01-29 01:50:21 +00:00
Mike Koch
f53065f7f6 Merge branch '3-3-0' into '357-calendar-planning-phase-two'
# Conflicts:
#   api/BusinessLogic/Security/UserContext.php
#   api/BusinessLogic/Security/UserPrivilege.php
#   api/index.php
#   language/en/text.php
2018-01-29 01:46:16 +00:00
Mike Koch
624267fe45
Audit trail now displays for users who can manage calendar 2018-01-25 22:07:28 -05:00
Mike Koch
401e335e5f
Adding history to modal 2018-01-24 22:00:10 -05:00
Mike Koch
ad63bcac02
Fixed a couple issues with the audit trail changes 2018-01-24 13:01:23 -05:00
Mike Koch
1a66485d48
Working on adding audit trail to events 2018-01-23 22:14:25 -05:00
Mike Koch
770a01a970
Add status to ticket popover on calendar 2018-01-21 22:03:54 -05:00
Mike Koch
78cb2de9b6
Going to use rrule.js instead 2018-01-19 22:17:15 -05:00
Mike Koch
4959ccb815
Add php-rrule for recurring event parsing 2018-01-18 22:02:48 -05:00
Mike Koch
4c2432a35b
Moved all calendar API logic to the api folder 2018-01-09 12:37:29 -05:00
Mike Koch
3d73b9a4b2
All main staff calendar endpoints moved 2018-01-07 22:02:43 -05:00
Mike Koch
c4b79a722c
More calendar tweaks 2018-01-03 13:04:23 -05:00
Mike Koch
0514965040
Update due date mostly done... just need to fix the buildEvent function 2018-01-02 13:05:10 -05:00
Mike Koch
bd5b3e1322
Working on moving the update ticket due date endpoint 2018-01-01 21:39:01 -05:00
Mike Koch
86f1fb3ca2
Slowly working on moving more API endpoints 2017-12-27 22:00:30 -05:00
Mike Koch
c805fd8eab
Working on new update event endpoint 2017-12-23 22:04:52 -05:00
Mike Koch
9eab1525ef
Getting started on moving the update event endpoint 2017-12-21 22:10:45 -05:00
Mike Koch
814523ba6e
getEventsForStaff endpoint appears to be working 2017-12-17 22:05:32 -05:00
Mike Koch
13161696ae
Working on refactoring the calendar API 2017-12-10 22:01:18 -05:00
Mike Koch
354bb91234 Merge branch '3-2-5' into 'master'
3.2.5

See merge request mike-koch/Mods-for-HESK!85
2017-12-07 02:44:58 +00:00
Mike Koch
05b913c53a
Fix issue in PHP 5.3 2017-12-06 21:39:08 -05:00
Mike Koch
5ee4ed5864
revert meeee 2017-12-06 21:37:42 -05:00
Mike Koch
d4b3c9acc9
Update build 2017-12-06 12:53:55 -05:00
Mike Koch
95342815e2
Update installer 2017-12-06 12:52:02 -05:00
Mike Koch
f35fb7b207 Merge branch 'fix-headers' into '3-2-5'
Fix headers

See merge request mike-koch/Mods-for-HESK!84
2017-12-06 17:48:47 +00:00
Mike Koch
6177bc1794 Merge branch '595-fix-basic-email-sender' into '3-2-5'
Fix BasicEmailSender

See merge request mike-koch/Mods-for-HESK!83
2017-12-06 17:48:34 +00:00
Mike Koch
878b2aa096
Fix headers 2017-12-06 12:45:44 -05:00
Mike Koch
8ee6e1a55f
Can't concatenate an array to a string 2017-12-06 12:18:17 -05:00
Mike Koch
d2ee60e053 Merge branch '301-service-messages' into '3-3-0'
Service Messages Improvements

See merge request mike-koch/Mods-for-HESK!82
2017-12-04 18:07:26 +00:00
Mike Koch
39e61b85c4
Fixed some issues with the service messages endpoints: 2017-12-04 12:56:09 -05:00
Mike Koch
0a2e37320a
Working on adding controller security 2017-12-01 12:56:23 -05:00
Mike Koch
f70c3635a9
Working on moving the calendar API 2017-11-29 21:58:30 -05:00
Mike Koch
8050e10c30
Merge remote-tracking branch 'origin/master' into 357-calendar-planning-phase-two 2017-11-29 21:30:04 -05:00
Mike Koch
3e8085110f
Service messages now appear in their proper locations 2017-11-28 13:03:06 -05:00
Mike Koch
2faac6be1a
Fixed type not being stored, working on display locations 2017-11-27 13:00:35 -05:00
Mike Koch
902f3edcf6
Only show locations that are active 2017-11-27 12:51:34 -05:00
Mike Koch
3bff7fd30b
Contentified some strings 2017-11-27 12:22:41 -05:00
Mike Koch
665db7a4d8
Merge branch 'master' into 301-service-messages 2017-11-27 12:09:03 -05:00
Mike Koch
a7546419a4
Update version number 2017-11-25 21:53:47 -05:00
Mike Koch
8d30a041fe Merge branch 'hesk-2-7-4' into 'master'
HESK 2.7.5

See merge request mike-koch/Mods-for-HESK!81
2017-11-26 02:47:49 +00:00
Mike Koch
dd99ebdb0e
Fix input-group-addon CSS issue 2017-11-25 21:46:19 -05:00
Mike Koch
03e7f62684
Change verbiage 2017-11-25 21:42:23 -05:00
Mike Koch
d092a49bab
Fix sorting of ticket events 2017-11-25 21:40:27 -05:00
Mike Koch
2390af6393
Update HESK verison to 2.7.5 2017-11-25 21:14:15 -05:00
Mike Koch
8b263f66a3
Fix some email sending, updat edit_post maxlengths 2017-11-21 12:58:04 -05:00
Mike Koch
3203eed8aa
Use NOW() for reply dates 2017-11-21 12:29:54 -05:00
Mike Koch
a7742614df
Update pages for HESK 2.7.4 2017-11-20 22:16:46 -05:00
Mike Koch
15b971412b Merge branch '3-2-3' into 'master'
3.2.3

See merge request mike-koch/Mods-for-HESK!80
2017-11-20 17:38:11 +00:00
Mike Koch
f8ab89946d
Update version 2017-11-20 12:37:48 -05:00
Mike Koch
70435cee62
Fix storing dates when format is not MySQL-friendly 2017-11-20 12:36:04 -05:00
Mike Koch
fefe1e23a4 Merge branch 'patch-1' into '3-2-3'
Fix usage of CC and BCC fields in mail header.

See merge request mike-koch/Mods-for-HESK!78
2017-11-20 12:57:53 +00:00
Mike Koch
477d55d8bf Merge branch '591-edit-and-delete-replies' into '3-2-3'
Fix edit/delete reply buttons

See merge request mike-koch/Mods-for-HESK!79
2017-11-20 12:48:40 +00:00
Mike Koch
eac23907e7
Fix edit/delete reply buttons 2017-11-20 07:46:07 -05:00
Jozef
eeb5ada610 Fix usage of CC and BCC fields in mail header. 2017-11-20 11:00:25 +00:00
Mike Koch
36295d1861
Add language property to service messages 2017-11-19 22:16:45 -05:00
Mike Koch
3e82065fa4
Working on adding a language option to service messages 2017-11-18 22:05:11 -05:00
Mike Koch
6a763593ee
Locations can be added to service messages 2017-11-17 22:27:55 -05:00
Mike Koch
d04b40c925
Start working on adding locations to service messages 2017-11-15 22:02:55 -05:00
Mike Koch
f5ff322c33
Remove sweetalert, use a tooltip instead 2017-11-15 21:27:45 -05:00
Mike Koch
ac5f9309c8
Starting to introduce sweetalert 2017-11-15 13:05:41 -05:00
Mike Koch
79e34ce8cc
Service messages now use the API 2017-11-15 12:55:16 -05:00
Mike Koch
3e7f000630
All operations except for preview are working 2017-11-14 13:04:20 -05:00
Mike Koch
d897fa2a4b
More progress' 2017-11-13 22:13:55 -05:00
Mike Koch
a8abfcd4a1
More progress on service messages 2017-11-13 13:07:19 -05:00
Mike Koch
c00d5641e4
Service messages page can now retrieve service messages via AJAX 2017-11-12 22:22:28 -05:00
Mike Koch
6bef518ffa
Add more endpoints for service messages 2017-11-11 22:16:25 -05:00
Mike Koch
311a48487d
Add POST service-messages endpoint 2017-11-11 16:33:43 -05:00
Mike Koch
d305ccf9b3
Add POST endpoint for creating service messages 2017-11-09 22:02:26 -05:00
Mike Koch
c985f80452
Working on moving service messages to an API endpoint 2017-11-09 13:04:10 -05:00
Mike Koch
fd4732d978
Add helper method for boolval 2017-11-08 21:36:46 -05:00
Mike Koch
945e548ef7
Revert to an older mailgun PHP library 2017-11-08 21:12:05 -05:00
Mike Koch
18128ff263
Update mailgun-php 2017-11-08 20:48:05 -05:00
Mike Koch
70793cdfae
Update installer 2017-11-07 21:58:44 -05:00
Mike Koch
30dcb113ae
Modify link to handle servers with odd configurations 2017-11-07 21:48:38 -05:00
Mike Koch
443d4ac1f3
Update some composer dependencies 2017-11-07 09:26:16 -05:00
Mike Koch
88964a73eb
Only skip phpunit for now 2017-11-06 12:38:48 -05:00
Mike Koch
fcaee13ba3
Add missing CSS, update installer 2017-11-05 20:32:25 -05:00
Mike Koch
fab521ff7c Merge branch 'patch-1' into 'master'
Fixed calendar problem (not showing)

See merge request mike-koch/Mods-for-HESK!76
2017-11-06 01:24:59 +00:00
Mike Koch
7c139a8d0c Merge branch 'fix-customer-calendar' into 'master'
Fix customer calendar

See merge request mike-koch/Mods-for-HESK!77
2017-11-06 01:19:40 +00:00
Mike Koch
5d8fa97aa2
update build # 2017-11-05 17:33:19 -05:00
Mike Koch
f3c0c191db
Add bootstrap-select to header 2017-11-05 17:33:02 -05:00
Jan Teunis
046636c40a Fixed calendar problem (not showing)
Added bootstrap-select.js and cleaned up tabs
2017-11-05 22:25:37 +00:00
Mike Koch
c241338fbe
Couple small QoL changes 2017-11-05 12:00:41 -05:00
Mike Koch
d62370b069
Revert "Modify build config"
This reverts commit 05617a3b56a905ceea16713d6cc5eb489631b325.
2017-11-04 22:17:47 -04:00
Mike Koch
ca728839ac Merge branch '3-2-0' into 'master'
3.2.0 Update

See merge request mike-koch/Mods-for-HESK!75
2017-11-05 01:51:11 +00:00
Mike Koch
05617a3b56
Modify build config 2017-11-03 21:50:09 -04:00
Mike Koch
b77e2e6459
Merge branch '417-installer-improvements' into 3-2-0 2017-11-03 21:45:05 -04:00
Mike Koch
2d9c383ddd
Remove some unneeded logs 2017-11-03 21:44:06 -04:00
Mike Koch
59fa5c2698 Merge branch '417-installer-improvements' into '3-2-0'
New Installer

See merge request mike-koch/Mods-for-HESK!73
2017-11-04 01:43:24 +00:00
Mike Koch
308f7431e7
Fixing some down migrations 2017-11-01 22:01:28 -04:00
Mike Koch
86a76fc460
Fix one of the migrations 2017-11-01 21:55:35 -04:00
Mike Koch
4e6bbdfed6
Fix migrations 2017-11-01 21:52:17 -04:00
Mike Koch
61fcfc83b0
Value is a string 2017-11-01 12:55:44 -04:00
Mike Koch
f41fe487fa
Finished converting migrations. Need to test. 2017-11-01 12:52:47 -04:00
Mike Koch
9b7af18f6a
Some more changes 2017-11-01 12:29:51 -04:00
Mike Koch
f6df4fda7e
Finished up 3.0.0 refactoring 2017-10-31 17:31:03 -04:00
Mike Koch
17d5d9efcf Merge branch '3-2-0' into '3-2-0'
Entered correct update url on the admin settings page

See merge request mike-koch/Mods-for-HESK!74
2017-10-31 12:14:55 +00:00
Mike Koch
fed59f988f
Refactored some more migrations 2017-10-31 08:11:37 -04:00
Mike Koch
62d9f31d14
Some more changes 2017-10-30 22:02:28 -04:00
Justin
1862b6beb3 Entered correct update url on admin settings 2017-10-30 18:05:57 +01:00
Mike Koch
311697693f
Splitting up migrations.... partway done 2017-10-30 13:02:36 -04:00
Mike Koch
bc752ff2c3
Don't show anonymous usage checkbox for now
Not ready to go yet
2017-10-27 12:54:14 -04:00
Mike Koch
02492dac52
Add a HESK version mismatch check 2017-10-27 12:40:11 -04:00
Mike Koch
647955fdf0
Delete unused files 2017-10-27 12:26:47 -04:00
Mike Koch
78ae5cebff
Switch from dev to stable 2017-10-25 21:50:55 -04:00
Mike Koch
a01efb8f92
Trying to fix doctrine/annotations 2017-10-25 21:48:03 -04:00
Mike Koch
3fde3df882
Remove caching implementation 2017-10-25 12:42:50 -04:00
Mike Koch
f2cfe967ee
Some minor changes 2017-10-21 13:39:17 -04:00
Mike Koch
9839e8916e
small change 2017-10-20 22:17:56 -04:00
Mike Koch
109a4fa25f
Uninstaller works 2017-10-20 13:07:01 -04:00
Mike Koch
e98213ad4c
Uninstaller seems to be working... I think :P 2017-10-19 22:07:46 -04:00
Mike Koch
7aa7526a17
Working on the uninstaller 2017-10-18 22:00:00 -04:00
Mike Koch
60ac53fe94
Change key 2017-10-18 13:03:11 -04:00
Mike Koch
0df87dde57
Fix some migrations, add new ones to keep track of migration number 2017-10-18 13:02:48 -04:00
Mike Koch
8b7f0ace3a
Fixed error logger 2017-10-17 21:48:58 -04:00
Mike Koch
d35cf4d358
Fix some migrations 2017-10-16 22:02:04 -04:00
Mike Koch
cae76032d1
I *think* the rollback feature is working? 2017-10-16 20:39:16 -04:00
Mike Koch
f5907bf476
Some changes 2017-10-16 13:08:53 -04:00
Mike Koch
78559de051
Trying to get downgrades working properly 2017-10-15 21:23:56 -04:00
Mike Koch
d19c53e99a
Fixed some installer issues... migration 24 looks broken though 2017-10-13 22:10:44 -04:00
Mike Koch
537cbe92f3
Fix .gitlab-ci.yml 2017-10-13 13:02:25 -04:00
Mike Koch
5235461791
Re-enable the migrations 2017-10-12 22:13:18 -04:00
Mike Koch
97e4f4ae4f
Overall UX/UI complete. Need to test the actual migrations 2017-10-12 22:11:51 -04:00
Mike Koch
d007792f3a
Remove var_dump 2017-10-12 13:10:01 -04:00
Mike Koch
cdd4c83e4f
Add a new step for complete 2017-10-12 13:07:50 -04:00
Mike Koch
0cd0337a39
Added initial migration numbers, fixed some UI issues 2017-10-12 13:04:59 -04:00
Mike Koch
72428be04b
Debugging some stuff 2017-10-11 22:00:53 -04:00
Mike Koch
e3cfdda60b
Modified the installer a little bit 2017-10-10 22:00:40 -04:00
Mike Koch
219bc18cc6
Still need to test this.... 2017-10-04 22:03:39 -04:00
Mike Koch
62c059b384
Finished rewriting all of the migrations 2017-10-04 13:07:12 -04:00
Mike Koch
2c8a4ad86e
Migrated some more SQL changes 2017-10-03 22:05:35 -04:00
Mike Koch
d29ec0374e
Transferred some more migrations 2017-10-03 13:17:12 -04:00
Mike Koch
c99f75c908
Converted several other migrations 2017-10-02 22:02:26 -04:00
Mike Koch
f54c9bbd03
More migrations 2017-10-02 08:09:22 -04:00
Mike Koch
92713506e6
Working on creating the migrations 2017-10-01 22:03:09 -04:00
Mike Koch
6ea38bc90b
Got the basic migration framework working 2017-09-29 13:07:11 -04:00
Mike Koch
dbf9baca75
Getting started on the AJAX portion 2017-09-29 08:13:24 -04:00
Mike Koch
5aeb90852b
Add progress bar for installer...still need to write the actual migrations 2017-09-28 13:04:22 -04:00
Mike Koch
8b0fe2cdaf
Start at -1 as the last installed migration # for new installs 2017-09-28 08:18:42 -04:00
Mike Koch
8aac741b6f
Added logic to get the starting migration number 2017-09-28 08:17:45 -04:00
Mike Koch
43264318c4
Some progress 2017-09-27 22:01:34 -04:00
Mike Koch
23fc8ef6d5
Landing page looks good, moved database-validation 2017-09-27 13:00:20 -04:00
Mike Koch
69f2cf4b4c
Working on an updated installer 2017-09-26 22:08:14 -04:00
Mike Koch
e56943d659 Merge branch '200-new-audit-trail' into '3-2-0'
Resolve "Move Audit Trail to separate table"

See merge request mike-koch/Mods-for-HESK!72
2017-09-27 01:25:42 +00:00
Mike Koch
3485a5b7db
Fix tests 2017-09-26 21:19:17 -04:00
Mike Koch
60decb3cfa
Fixed ticket creation stuff 2017-09-26 13:08:17 -04:00
Mike Koch
7e6a5b2ba5
Working on audit for API, trying to fix email issues 2017-09-25 21:50:11 -04:00
Mike Koch
c6f4e4ce3e
New audit trail records are returned in the API response 2017-09-25 08:14:12 -04:00
Mike Koch
0670d74c1e
Pretty much wrapped up with the new ticket history 2017-09-24 22:07:49 -04:00
Mike Koch
44ab918292
Make sure ticket is updated before adding audit record to make sure it appears in the right order 2017-09-23 22:02:29 -04:00
Mike Koch
0ac67766ee
New audit trail now appears on the ticket page 2017-09-22 22:24:27 -04:00
Mike Koch
953747d90d
Update composer lockfile 2017-09-22 18:29:14 -04:00
Mike Koch
62bda38b91
Slowly started on displaying the new audit trail 2017-09-22 13:07:35 -04:00
Mike Koch
db99d2219e
Updated the rest of the audit trails 2017-09-22 12:50:04 -04:00
Mike Koch
939f470666
Updated some more audit trails 2017-09-22 08:08:16 -04:00
Mike Koch
05ede52ce5
Add priority.php 2017-09-22 08:02:43 -04:00
Mike Koch
d5589cc1c2
Some more audit trail fixes 2017-09-22 08:01:53 -04:00
Mike Koch
4ac430bc19
Replace several audit trail spots 2017-09-21 22:12:55 -04:00
Mike Koch
b95876e6a1
Add new audit trail entries for admin_reply_ticket 2017-09-20 08:10:51 -04:00
Mike Koch
35f03ee26e
Getting started with new audit trail entries 2017-09-19 22:03:39 -04:00
Mike Koch
7b8ae3a1d8
The audit table should support multiple types 2017-09-19 17:21:07 -04:00
Mike Koch
ca3bfcde1c
Add missing column 2017-09-19 12:56:27 -04:00
Mike Koch
523fe43b91
Create new tables, add new language strings 2017-09-19 12:49:00 -04:00
Mike Koch
764fefb25a Merge branch '510-custom-field-descriptions' into '3-2-0'
Resolve "Add function to add custom description or explanation of the custom fields for customers."

See merge request mike-koch/Mods-for-HESK!71
2017-09-19 16:28:18 +00:00
Mike Koch
9ed88a1e02
Updated priority colors on customer side 2017-09-19 12:27:32 -04:00
Mike Koch
46721d4212
Add custom field descriptions to customer submit ticket 2017-09-19 12:22:42 -04:00
Mike Koch
111dbb30b9
Add custom field descriptions to edit post 2017-09-19 12:17:33 -04:00
Mike Koch
d01135ac1b
Add custom field descriptions to admin create ticket page 2017-09-19 12:15:38 -04:00
Mike Koch
d06e80056a
Clear descriptions when deleting custom field 2017-09-19 08:05:16 -04:00
Mike Koch
ce8ff6efe5
Custom field descriptions can be saved 2017-09-19 08:04:23 -04:00
Mike Koch
745ecd42aa
Getting started adding custom field descriptions 2017-09-18 22:04:50 -04:00
Mike Koch
fedb26fd43 Merge branch 'bring-back-managers' into '3-2-0'
Bring back managers

See merge request mike-koch/Mods-for-HESK!70
2017-09-19 01:18:22 +00:00
Mike Koch
6d632be7b8
Managers are back in action 2017-09-18 21:13:48 -04:00
Mike Koch
79f41a7652
Permission groups seem to be good to go? 2017-09-18 13:04:26 -04:00
Mike Koch
056b02522e
Working on permission template -> group conversion 2017-09-17 22:07:01 -04:00
Mike Koch
4d9eeeb1d0
More manager stuff 2017-09-14 22:00:57 -04:00
Mike Koch
477b780805
Re-added all manager-related code 2017-09-13 21:27:02 -04:00
Mike Koch
a3709c187b Merge branch '354-priority-tweaks' into '3-2-0'
Resolve "Ticket Priority Improvements"

See merge request !69
2017-09-13 13:56:02 +00:00
Mike Koch
3c0148ddc2
Add bootstrap-select to all dropdowns in green, change background on ticket list 2017-09-12 22:04:10 -04:00
Mike Koch
8de106cbb2
Starting to use bootstrap-select on admin_ticket to improve dropdowns 2017-09-12 13:02:58 -04:00
Mike Koch
9ae189430d
Localize calendar pages 2017-09-12 12:32:30 -04:00
Mike Koch
ea0a612e4f
Trying to fix the PHP linter 2017-09-11 21:34:16 -04:00
Mike Koch
41cbdadb72
More PHP 5.4/5.3 fixes 2017-09-11 21:17:34 -04:00
Mike Koch
016a50878d
Add a BaseClass/BaseException for 5.4 compatibility 2017-09-11 21:03:03 -04:00
Mike Koch
3c4018ace3
Add validation steps for PHP 5.4 and 5.3 2017-09-11 12:56:18 -04:00
Mike Koch
37d730dfdc
Fix a syntax error in PHP 5.5 2017-09-11 12:55:56 -04:00
Mike Koch
0f902f683c
More CI fixes 2017-09-11 12:48:34 -04:00
Mike Koch
02ccb65b27
More changes 2017-09-11 12:46:26 -04:00
Mike Koch
3b0c8ad3a6
More CI changes 2017-09-11 12:43:20 -04:00
Mike Koch
560197eebe
Testing some gitlab ci changes 2017-09-11 12:35:59 -04:00
Mike Koch
0dcac4f324 Merge branch '457-category-descriptions' into '3-2-0'
Add Description to Categories

See merge request !68
2017-09-11 02:07:25 +00:00
Mike Koch
3ed01ba92f
Fix tests 2017-09-10 21:44:49 -04:00
Mike Koch
dd699b7165
Try fixing .gitlabci.yml 2017-09-09 22:06:47 -04:00
Mike Koch
5b7c2f7ec7
Remove all manager usages 2017-09-09 22:03:42 -04:00
Mike Koch
c8e2128c4c
Switch to mike-koch/PHP-DI 2017-09-09 21:29:40 -04:00
Mike Koch
be42fe04fb
Use a proper DI system 2017-09-09 21:24:05 -04:00
Mike Koch
7ca00fecbe
Add strongly typed constructor args on BusinessLogic layer 2017-09-07 20:31:57 -04:00
Mike Koch
f700addda5
Update composer for php-di 2017-09-06 12:56:44 -04:00
Mike Koch
5caac8452e
Don't allow category 1 to be deleted 2017-09-06 07:54:33 -04:00
Mike Koch
02d965e2d9
Localized some stuff, add descriptions to create ticket pages 2017-09-05 22:20:57 -04:00
Mike Koch
45726bd388
Categories can be sorted 2017-09-05 13:06:56 -04:00
Mike Koch
25fde2aa65
Add description 2017-09-01 22:20:12 -04:00
Mike Koch
29f1eb3503
Fixed up editing/creating 2017-09-01 22:08:40 -04:00
Mike Koch
2238a52c40
Add generate link modal 2017-09-01 21:54:37 -04:00
Mike Koch
499b604cc3
Some more changes 2017-08-31 22:09:56 -04:00
Mike Koch
8a2c03a587
Make visibility a column 2017-08-31 13:02:30 -04:00
Mike Koch
24cdb08449
Categories can be created, modify modal 2017-08-30 22:03:51 -04:00
Mike Koch
f7272e8549
Categories can now be edited via the page 2017-08-29 22:19:17 -04:00
Mike Koch
136ca3f206
Fix banned icon for private categories 2017-08-25 18:01:48 -04:00
Mike Koch
a1a870ed34
Adding some more JS goodness. Still need to include autoassign/type into the modal 2017-08-24 22:06:48 -04:00
Mike Koch
aa307e6b15 Some more category changes 2017-08-23 22:00:30 -04:00
Mike Koch
60301f4aab Hide the up arrow for the top-most element 2017-08-22 22:06:42 -04:00
Mike Koch
7fb7a8bec4 Table being loaded. Need to handle proper name display though 2017-08-22 22:03:11 -04:00
Mike Koch
38cea82821 More work on manage categories page 2017-08-21 22:11:30 -04:00
Mike Koch
d76cc27e8e Add number of tickets to category 2017-08-21 21:25:54 -04:00
Mike Koch
c86788e7fd Getting started on manage categories page changes, fixed API config issue 2017-08-21 13:01:39 -04:00
Mike Koch
9582689f2a Categories can be deleted, fixed request methods 2017-08-21 12:54:31 -04:00
Mike Koch
dd690decb2 Editing categories possible, add security check 2017-08-20 21:53:02 -04:00
Mike Koch
7d2479d5b6 Categories can be created 2017-08-20 15:47:30 -04:00
Mike Koch
8f52400aea Change column name 2017-08-20 11:47:35 -04:00
Mike Koch
1185785dbd Should be able to create categories now... 2017-08-18 08:15:50 -04:00
Mike Koch
f7d03f66cd Making more progress on category API endpoint 2017-08-17 22:03:33 -04:00
Mike Koch
05f79ecfa9 Merge remote-tracking branch 'origin/master' into 457-category-descriptions 2017-08-14 21:06:06 -04:00
Mike Koch
b6ab6a806e Fix demo mode for API 2017-08-13 20:55:05 -04:00
Mike Koch
3ec2419086 Fix API URL 2017-08-13 20:43:33 -04:00
Mike Koch
6b5a55226b Update build number 2017-08-13 13:56:43 -04:00
Mike Koch
7aae9c62af Merge branch '3-1-1' into 'master'
3.1.1

See merge request !65
2017-08-13 17:43:22 +00:00
Mike Koch
260600a7f6 Will this work? 2017-08-13 13:40:29 -04:00
Mike Koch
326ccaa6be Sometimes a weird commit fixes the CI build 2017-08-13 13:40:18 -04:00
Mike Koch
c60d2ed866 Update installer 2017-08-12 21:57:41 -04:00
Mike Koch
9bffcfdf6a Merge branch '577-ie-fix' into '3-1-1'
Fix document type on IE intranet pages

See merge request !67
2017-08-13 01:43:59 +00:00
Mike Koch
65576d5c43 Fix document type on IE intranet pages 2017-08-12 21:41:41 -04:00
Mike Koch
efbf38ca33 Merge branch '575-update-checking' into '3-1-1'
Version checks are now asynchronous

See merge request !66
2017-08-11 01:54:33 +00:00
Mike Koch
73b3a01bc0 Version checks are now asynchronous 2017-08-10 21:51:59 -04:00
Mike Koch
84f491bd40 Don't fail resending email when there is no owner 2017-07-30 15:05:53 -04:00
Mike Koch
ed6df71041 Merge branch '572-fix-autotls-issue' into '3-1-1'
Disable AutoTLS for PHPMailer

See merge request !64
2017-07-30 18:54:00 +00:00
Mike Koch
4db151de66 Disable AutoTLS for PHPMailer 2017-07-30 14:52:03 -04:00
f209266260 Enable Summernote for ticket replies 2017-07-29 20:14:53 -06:00
932056f731 Change Forgot Ticket ID UI to a Bootstrap panel 2017-07-29 20:09:42 -06:00
4178703f2b Merge branch 'captcheck' of Netsyms/Mods-for-HESK-Netsyms into master 2017-07-29 20:01:32 -06:00
7cc69878ca Make ticket submit success message into a Bootstrap panel 2017-07-29 20:00:37 -06:00
Mike Koch
68308b02a5 Some sort of progress on category endpoint 2017-07-29 21:57:29 -04:00
297d7f3cfd Add captcheck captcha option 2017-07-29 19:54:47 -06:00
Mike Koch
37bd252041 Merge branch 'bootstrap-theme-disable-fix' into '3-1-1'
Fix bootstrap-theme not disabling on Firefox

See merge request !63
2017-07-30 01:44:12 +00:00
5de09b851b Merge branch 'bootswatch' of Netsyms/Mods-for-HESK-Netsyms into master 2017-07-29 19:24:29 -06:00
daf748b173 Fix stupid mistake 2017-07-29 19:23:50 -06:00
e91f6842ab Swap == for != 2017-07-30 01:21:26 +00:00
d5a9d225f2 Fix bootstrap-theme not disabling on Firefox 2017-07-30 01:15:27 +00:00
c994b0099e Merge branch 'bootswatch' of Netsyms/Mods-for-HESK-Netsyms into master 2017-07-29 19:06:55 -06:00
932ebd1821 Fix typo 2017-07-29 19:05:11 -06:00
a5ae672b9f Add Bootswatch theme picker, Fix bug where the bootstrap theme can't be disabled 2017-07-29 19:00:33 -06:00
234d28a8b8 Merge branch 'summernote' of Netsyms/Mods-for-HESK-Netsyms into master 2017-07-29 18:04:40 -06:00
4baa85a8c5 Replace TinyMCE with Summernote, round 1 2017-07-29 17:45:49 -06:00
4351cf46b7 Add 'js/summernote.js' 2017-07-29 17:00:45 -06:00
d520df6886 Add 'css/summernote.css' 2017-07-29 16:59:10 -06:00
19d5ab9f06 Replace TinyMCE loader code with Summernote 2017-07-29 16:56:53 -06:00
Mike Koch
e8c029186e Don't allow non-GET requests in demo mode 2017-06-28 13:07:10 -04:00
Mike Koch
991c5cb87c Make phpunit a dev dependency 2017-06-27 21:06:17 -04:00
Mike Koch
454013fd98 Use X-HTTP-Method-Override for all MfH pages 2017-06-27 21:02:38 -04:00
Mike Koch
3aea482c3c Add support for X-HTTP-Method-Override header 2017-06-27 08:08:40 -04:00
Mike Koch
a4836f1142 Fixing inline attachments 2017-06-26 12:48:11 -04:00
Mike Koch
1ed740b7fa Update .gitlab-ci.yml 2017-06-26 12:17:57 +00:00
Mike Koch
40724c3503 Fix API paths for manage custom nav elements 2017-06-26 07:52:36 -04:00
Mike Koch
7fe647c3ab Internal API can't be disabled 2017-06-26 07:51:07 -04:00
Mike Koch
81a5b6633c Can't name version number dynamically 2017-06-25 22:07:40 -04:00
Mike Koch
a2b44cd288 Change the name of the zip 2017-06-25 21:13:31 -04:00
Mike Koch
7213f77254 Try setting the variable 2017-06-25 21:03:12 -04:00
Mike Koch
46b3a54369 Run phpunit in the right directory 2017-06-25 20:14:05 -04:00
Mike Koch
277c1b5359 Fix config 2017-06-25 17:00:21 -04:00
Mike Koch
a49c156007 Fix up the build steps 2017-06-25 16:58:40 -04:00
Mike Koch
a559ee24df Make before_script global 2017-06-25 16:52:21 -04:00
Mike Koch
65a9353c93 Fix stages? 2017-06-25 16:50:02 -04:00
Mike Koch
9b4929a4c7 Fixing things? 2017-06-25 16:48:35 -04:00
Mike Koch
543d07cfaf Try renaming the steps 2017-06-25 16:46:39 -04:00
Mike Koch
be903af3a4 Trying to figure out how to build a proper pipeline graph 2017-06-25 16:45:30 -04:00
Mike Koch
abf632b3da Add a deploy step and see if it can see what the test step does 2017-06-25 16:42:49 -04:00
Mike Koch
db204335e6 Can I rename this? 2017-06-25 16:40:59 -04:00
Mike Koch
8997c258a6 Commit. 2017-06-25 16:36:41 -04:00
Mike Koch
bd73cc2f7c Commit. 2017-06-25 16:35:13 -04:00
Mike Koch
5969deb49c Again. 2017-06-25 16:33:22 -04:00
Mike Koch
60c824a7c2 Third try 2017-06-25 16:28:56 -04:00
Mike Koch
663caccf7a Fix image name 2017-06-25 16:27:37 -04:00
Mike Koch
2b4d50d469 Try using a composer image 2017-06-25 16:26:54 -04:00
Mike Koch
7f73a9c61b Remove wget install 2017-06-25 16:24:44 -04:00
Mike Koch
c79e019594 Trying things 2017-06-25 16:23:47 -04:00
Mike Koch
4b21758506 Looks like wget needs to be installed manually 2017-06-25 16:16:47 -04:00
Mike Koch
5a908d6b61 Try building a zip of the release 2017-06-25 16:10:09 -04:00
Mike Koch
cc900a16da Make it var_dump 2017-06-24 22:15:25 -04:00
Mike Koch
033a23eaca Trying to get started on gitlab ci 2017-06-24 22:13:00 -04:00
Mike Koch
bfb8956df2 Update gitlab-ci.yml 2017-06-24 21:49:32 -04:00
Mike Koch
603d68a7b3 Trying to see how artifacts work 2017-06-24 21:46:41 -04:00
Mike Koch
3ca6b1a435 Add a URL rewrite setting for the API. Not using it in code yet... might not even do that lol 2017-06-24 16:04:19 -04:00
Mike Koch
a47773cf98 Testing manual execution 2017-06-23 18:38:57 +00:00
Mike Koch
ef34c5bcb1 Skip the weird failing test 2017-06-22 22:13:41 -04:00
Mike Koch
97d8f0df2e Fix tests... again 2017-06-22 22:09:14 -04:00
Mike Koch
7300b5bd5f Fix tests, remove ls from ci config 2017-06-22 22:06:00 -04:00
Mike Koch
2efa603474 Fix phpunit.xml 2017-06-22 21:57:05 -04:00
Mike Koch
8cdc01f3cb Fix phpunit.xml 2017-06-22 21:55:18 -04:00
Mike Koch
634f8b3aca Update PHPUnit XML 2017-06-22 21:52:15 -04:00
Mike Koch
c52bd054d6 more debugging 2017-06-22 21:48:22 -04:00
Mike Koch
28027ae58b More changes 2017-06-22 21:46:46 -04:00
Mike Koch
0c7856b388 Trying to get CI tests to run 2017-06-22 21:45:01 -04:00
Mike Koch
99ad9ecd63 Add .gitlab-ci.yml 2017-06-22 21:37:56 -04:00
Mike Koch
535e48225d Merge branch '3-1-0' into 'master'
3.1.0 Update

Closes #535, #428, #397, #565, #549, #561, #562, #560, #531, #395, #405, #456, #353, #551, #559, #557, #556, #524, #523, #527, #528, #525, #339, and #522

See merge request !62
2017-06-23 01:24:26 +00:00
Mike Koch
ef481b3192 Fixed some JS files 2017-06-22 21:21:38 -04:00
Mike Koch
77c5c3d872 Fix nav element API path 2017-06-22 12:53:08 -04:00
Mike Koch
65110bd1b4 Update database-validation.php 2017-06-22 12:04:29 +00:00
Mike Koch
1234f858e5 Update build.php 2017-06-22 12:04:12 +00:00
Mike Koch
0caf4e740e Fix color issues on calendar page 2017-06-21 22:07:21 -04:00
Mike Koch
a219883117 Fix colors on new category panel 2017-06-21 21:56:02 -04:00
Mike Koch
9a5738eb1c Use relative URLs for attachment handling 2017-06-20 22:00:54 -04:00
Mike Koch
4a49c8c510 Make all AJAX calls relative 2017-06-20 08:04:07 -04:00
Mike Koch
13d7b70ac5 Fix regex, query order, and black preset text colors 2017-06-19 22:13:34 -04:00
Mike Koch
f9b09fbde6 Only get custom nav elements if not in maint mode and the table exists 2017-06-19 20:47:00 -04:00
Mike Koch
f5933e8bfa update installer, fix colorpicker presets 2017-06-18 22:03:35 -04:00
Mike Koch
c39e4462e8 Add nav element for API settings 2017-06-18 21:31:48 -04:00
Mike Koch
f6283a4c13 Fix the API settings page, update validator, fix sidebar text hover 2017-06-18 21:21:26 -04:00
Mike Koch
34358be637 Add dirty forms check on add reply form 2017-06-17 22:02:03 -04:00
Mike Koch
45c1291711 More color changes 2017-06-16 22:42:12 -04:00
Mike Koch
550d7f5d3c Staff UI colors working 2017-06-16 21:18:22 -04:00
Mike Koch
f860e98018 Most of the user-defined colors are properly working 2017-06-16 13:09:59 -04:00
Mike Koch
cebcefe7e2 Actually save the settings 2017-06-15 22:06:13 -04:00
Mike Koch
69b78d0829 JS updated for presets 2017-06-13 22:14:00 -04:00
Mike Koch
3a7db2f7ca Small change 2017-06-13 12:59:49 -04:00
Mike Koch
f07358cb4a Set the right form names 2017-06-12 21:51:11 -04:00
Mike Koch
7d6f3828fd Fixed some SQL and used proper settings names 2017-06-12 08:21:28 -04:00
Mike Koch
daca2e6273 More work on admin UI colors 2017-06-11 22:04:19 -04:00
Mike Koch
9f0fd7c657 Working on custom staff panel color schemes 2017-06-10 22:29:29 -04:00
Mike Koch
88de2df3c0 Remove trailing PHP tags 2017-06-10 12:12:15 -04:00
Mike Koch
858e14ee8c Remove RTL support 2017-06-10 12:09:04 -04:00
Mike Koch
01570e856c Login header image is working 2017-06-10 12:06:14 -04:00
Mike Koch
55a1d3d5ad Working on adding a login header image 2017-06-09 22:39:00 -04:00
Mike Koch
57f9fdec63 Saving properly works, login page updated 2017-06-08 22:39:45 -04:00
Mike Koch
3a8d69b061 Only update image if changed 2017-06-08 13:10:12 -04:00
Mike Koch
e48022b533 Login background can be uploaded 2017-06-08 13:07:08 -04:00
Mike Koch
65c7c15c74 more work on login background 2017-06-07 21:58:47 -04:00
Mike Koch
31265e7696 Working on saving the login backdrop 2017-06-06 22:02:46 -04:00
Mike Koch
22789540ec Form is pretty much done for login background 2017-06-06 13:02:53 -04:00
Mike Koch
fb2861ea21 Add options for image url or background color 2017-06-05 22:03:08 -04:00
Mike Koch
0956496b99 Getting started on adding login background customizations 2017-06-01 12:56:36 -04:00
Mike Koch
33ab18e826 Update CategoryGateway 2017-06-01 12:45:56 -04:00
Mike Koch
fe898a7a1c Merge branch '397-fine-tuned-category-colors' into '3-1-0'
Resolve "Color Buttons Calendar Categories"

See merge request !61
2017-06-01 16:40:30 +00:00
Mike Koch
5960afd237 Update the database validator 2017-06-01 12:38:03 -04:00
Mike Koch
028be8d187 Calendar pages properly use new category colors 2017-06-01 12:26:54 -04:00
Mike Koch
ac0df60a3e Category colors are properly saved, calendar pages updated 2017-05-31 22:05:24 -04:00
Mike Koch
523b80fb4c Update the form for the new fields 2017-05-30 22:05:20 -04:00
Mike Koch
a043dced97 Getting started on enhanced color changes 2017-05-30 13:02:39 -04:00
Mike Koch
21d00049ba Fix URL 2017-05-29 22:03:46 -04:00
Mike Koch
ad4724ed69 Styling for items that can now be viewed inline 2017-05-29 21:58:50 -04:00
Mike Koch
3b0874db49 Add nav menu element for custom nav elements and security value 2017-05-29 21:39:58 -04:00
Mike Koch
873498e20e Move MFH language strings to end of file for i18n building 2017-05-29 21:01:09 -04:00
Mike Koch
3c5722c6d7 Getting started on inline attachment viewing 2017-05-23 22:14:32 -04:00
Mike Koch
8e22dd10a8 Replace fancybox with magnific popup (licensing) 2017-05-23 21:43:46 -04:00
Mike Koch
1a873cd377 Update calendar.php 2017-05-23 13:55:59 +00:00
Mike Koch
8d8d99e103 Remove erronous var_dump 2017-05-22 22:03:39 -04:00
Mike Koch
2990eadd07 Replace old HESK headers with current ones 2017-05-22 22:02:02 -04:00
Mike Koch
06b23e5459 Localized missing keys 2017-05-22 21:56:43 -04:00
Mike Koch
29d72b9c0e Fix custom fields on manage email templates 2017-05-22 21:46:15 -04:00
Mike Koch
6ec7058094 Replace jGrowl with Toastr' 2017-05-22 21:43:45 -04:00
Mike Koch
09c650d487 Merge branch '395-custom-blocks-to-database' into '3-1-0'
Move Custom Blocks/Nav Elements to Database

See merge request !60
2017-05-22 18:15:10 +00:00
Mike Koch
f96095ad42 Add back name attribute 2017-05-22 13:13:10 -04:00
Mike Koch
b82293d96d Custom nav elements now working on proper pages 2017-05-22 13:10:26 -04:00
Mike Koch
99c229fae7 Add toastr, fix several things regarding custom nav elements 2017-05-21 22:26:36 -04:00
Mike Koch
ab5840babe Sorting is now possible 2017-05-21 12:03:05 -04:00
Mike Koch
11f9266f10 Properly handle saving/getting URLs 2017-05-20 22:12:08 -04:00
Mike Koch
add02b208d Add endpoints for re-ordering elements, add arrows to page 2017-05-19 22:08:50 -04:00
Mike Koch
25922d99f3 Separate each type, add a sort value to reorder them 2017-05-19 12:52:47 -04:00
Mike Koch
5cdd216cdb Elements can be deleted, add overlay during AJAX operations 2017-05-18 22:10:10 -04:00
Mike Koch
8682bd236e New elements can be created, existing elements can be edited 2017-05-17 22:03:05 -04:00
Mike Koch
a139c7d351 Working on save functionality 2017-05-16 13:00:41 -04:00
Mike Koch
0418ff76ad Some more changes.... these are fantastic commit messages! 2017-05-15 22:04:32 -04:00
Mike Koch
0eab3f1622 Modal working 2017-05-15 12:58:34 -04:00
Mike Koch
944552aba2 Slowly working on the edit nav item modal 2017-05-14 22:09:05 -04:00
Mike Koch
6b05ee31ab Working on incorporating the API into the page 2017-05-12 13:11:28 -04:00
Mike Koch
6e72662a1b Wrote the custom nav element api 2017-05-11 22:00:51 -04:00
Mike Koch
d06d168850 Finished up retrieving custom nav elements 2017-05-09 22:00:01 -04:00
Mike Koch
01eaab29d5 Merge pull request #481 from zpetr/master
Unexpected [ bug fix
2017-05-09 08:13:39 -04:00
Mike Koch
3df5324732 Getting more work done on custom navigation 2017-05-08 21:56:30 -04:00
Mike Koch
8db64d903d Getting started on custom nav elements 2017-05-06 22:17:22 -04:00
zpetr
c883a7b1d4 Unexpected [ bug fix
PHP Parse error:  syntax error, unexpected '[', expecting ')'
2017-05-06 23:28:17 +02:00
Mike Koch
ca681cdb5b Merge branch '531-attachment-preview-link' into '3-1-0'
Replace modal with lightbox for viewing images

See merge request !59
2017-05-06 20:28:43 +00:00
Mike Koch
dd68103be6 Replace modal with lightbox for viewing images 2017-05-06 16:27:12 -04:00
Mike Koch
75eb078565 Merge branch '405-header-color-tips' into '3-1-0'
Popover header now matches category color

See merge request !58
2017-05-06 02:10:45 +00:00
Mike Koch
2845a734ef Popover header now matches category color 2017-05-05 22:09:02 -04:00
Mike Koch
a95936a490 Fix some language keys 2017-05-05 21:41:26 -04:00
Mike Koch
4deedc73b4 Resend response properly working 2017-05-04 21:37:50 -04:00
Mike Koch
e086322332 Working on adding the resend button to the actual ticket page 2017-05-04 13:07:17 -04:00
Mike Koch
6b89174901 Merge branch '353-ability-to-resend-response' into '3-1-0'
Add Ability To Resend Response

See merge request !57
2017-05-04 16:15:12 +00:00
Mike Koch
cb9590c189 Add Ability To Resend Response 2017-05-04 16:15:11 +00:00
Mike Koch
99ce0d2b52 Merge branch '551-warn-if-message-filled-when-closing-tab' into '3-1-0'
Display warning on tab close if message contents are not empty

See merge request !56
2017-05-03 01:42:41 +00:00
Mike Koch
77089c79ec Display warning on tab close if message contents are not empty 2017-05-02 21:41:19 -04:00
Mike Koch
e21c26689a Merge branch 'api-rewrite' into '3-1-0'
BETA API v1

See merge request !55
2017-05-02 16:14:39 +00:00
Mike Koch
ef9cbf98b0 Improve POST ticket 2017-05-01 22:05:21 -04:00
Mike Koch
0a2d94e05b Add a basic endpoint to get a ticket for staff 2017-05-01 21:20:59 -04:00
Mike Koch
39c5886880 Some changes to improve overall UX 2017-04-30 22:02:34 -04:00
Mike Koch
ee4ba00fe9 Add endpoint for retrieving helpdesk settings 2017-04-28 22:15:59 -04:00
Mike Koch
7494efb8ca Getting started on settings retrieval 2017-04-28 13:08:25 -04:00
Mike Koch
fd41a589fe Add a status controller to retrieve statuses 2017-04-28 13:03:25 -04:00
Mike Koch
167d6c76ac Basic ticket info can now be edited 2017-04-28 12:36:48 -04:00
Mike Koch
c26db92799 Add edit ticket endpoint 2017-04-27 22:04:28 -04:00
Mike Koch
7b49508b11 Send verification email if needed, return 202 if ticket needs to be verified 2017-04-25 22:06:10 -04:00
Mike Koch
215bcca079 Can now get ticket by ID 2017-04-24 22:11:28 -04:00
Mike Koch
54cb77b136 Getting started on retrieving ticket customer-side 2017-04-24 13:07:11 -04:00
Mike Koch
b03312f73c Fixed a couple issues with deleting tickets 2017-04-23 22:08:48 -04:00
Mike Koch
2ff27e197b Add ability to delete ticket 2017-04-23 12:00:05 -04:00
Mike Koch
2131df0cd9 Working on deleting tickets... a bit more complicated than I initially thought 2017-04-15 22:38:46 -04:00
Mike Koch
d67485af13 Ticket attachments can be deleted 2017-04-12 22:00:56 -04:00
Mike Koch
df503face9 Merge remote-tracking branch 'remotes/origin/master' into api-rewrite
# Conflicts:
#	build.php
#	install/install_functions.inc.php
#	install/mods-for-hesk/ajax/install-database-ajax.php
#	install/mods-for-hesk/installModsForHesk.php
#	install/mods-for-hesk/js/version-scripts.js
#	install/mods-for-hesk/modsForHesk.php
#	install/mods-for-hesk/sql/installSql.php
#	knowledgebase.php
2017-04-12 19:58:30 -04:00
Mike Koch
fe6b4b1c48 Update installer / build number 2017-04-12 19:36:23 -04:00
Mike Koch
b64aa60fa0 Fix white screen on knowledgebase 2017-04-12 17:12:37 -04:00
Mike Koch
1bdb16ed64 Update database/database_mysqli for api,internal-api,cron 2017-04-11 21:49:43 -04:00
Mike Koch
3cdcc411a4 Fix pulling attachments, file checking 2017-04-11 21:44:57 -04:00
Mike Koch
027ff8f029 Update installer the right way 2017-04-11 20:58:36 -04:00
Mike Koch
bed05b0592 Fix version 2017-04-11 20:58:36 -04:00
Mike Koch
8bba31b0e2 Fix missing +s 2017-04-11 20:58:36 -04:00
Mike Koch
7a8f960bc0 Fix installer 2017-04-11 20:58:35 -04:00
Mike Koch
925ad5f538 #544 Rest of the 2.7.3 updates 2017-04-11 20:58:35 -04:00
Mike Koch
f4dbffa7e4 #544 Start updating to HESK 2.7.3 2017-04-11 20:58:34 -04:00
Mike Koch
c606be50ef Output attachment contents 2017-04-11 12:39:09 -04:00
Mike Koch
95606d1f0a Update installer the right way 2017-04-11 12:13:59 -04:00
Mike Koch
3556dd9618 Fix version 2017-04-11 08:19:09 -04:00
Mike Koch
877c85575f Fix missing +s 2017-04-11 08:15:39 -04:00
Mike Koch
b266fe6e4f Fix installer 2017-04-11 08:09:59 -04:00
Mike Koch
f4a42dae1b Merge branch '3-0-6' into 'master'
3.0.6 Update

See merge request !54
2017-04-11 01:55:44 +00:00
Mike Koch
e4c8d5b653 Merge branch '544-hesk-2-7-3-update' into '3-0-6'
Resolve "Update to HESK 2.7.3"

See merge request !53
2017-04-11 01:34:11 +00:00
Mike Koch
7277b5e4a2 #544 Rest of the 2.7.3 updates 2017-04-10 21:32:29 -04:00
Mike Koch
c3bad92656 #544 Start updating to HESK 2.7.3 2017-04-10 13:04:11 -04:00
Mike Koch
d461059cf0 Wrapped up retrieving ticket attachments 2017-04-09 22:14:38 -04:00
Mike Koch
e54d5278ac More work, forgot to include security when creating attachment 2017-04-05 22:13:37 -04:00
Mike Koch
c58867577f Attachments should be retrievable 2017-04-05 21:56:13 -04:00
Mike Koch
3cec244e15 Getting started on attachment retrieval 2017-04-04 22:57:21 -04:00
Mike Koch
999cb74865 Merge remote-tracking branch 'remotes/origin/master' into api-rewrite 2017-04-04 22:31:11 -04:00
Mike Koch
d90d09b9ce Update installer 2017-04-04 12:26:30 -04:00
Mike Koch
10c7f00881 Fix audit trail when changing status 2017-04-04 12:16:42 -04:00
Mike Koch
47152eb7fb Fix hesk_POST 2017-04-04 12:11:17 -04:00
Mike Koch
6dbda6f653 Fix installation issues 2017-04-03 22:32:32 -04:00
Mike Koch
2b051ef97b Merge branch '3-0-4' into 'master'
3.0.4 Update

Closes #537, #516, #517, #521, #463, #504, #508, #519, #507, and #509

See merge request !50
2017-04-04 02:23:01 +00:00
Mike Koch
8b886737b8 Change 'More' dropdown to a modal 2017-04-03 22:21:58 -04:00
Mike Koch
44ab6fc1e9 Start moving the 'more' section to a modal 2017-04-03 13:07:47 -04:00
Mike Koch
85458aa975 Fixes #516 Add autolink plugin to auto-generate URL when entering in messages 2017-04-02 21:15:34 -04:00
Mike Koch
672a061f28 Merge branch '517-checkbox-edit-issues' into '3-0-4'
Fixes #517 Use consistent <br /> tag for checkboxes

See merge request !52
2017-04-03 00:50:04 +00:00
Mike Koch
f28dc0f500 Fixes #517 Use consistent <br /> tag for checkboxes 2017-04-02 20:49:20 -04:00
Mike Koch
3bc61705b1 Merge branch '521-html-entities-when-merging' into '3-0-4'
Fix HTML Entities When Merging Tickets

See merge request !51
2017-04-03 00:36:29 +00:00
Mike Koch
f8ede2240a Fixes #521 copy over html flags when merging tickets 2017-04-02 20:35:05 -04:00
Mike Koch
0b0d046d04 Update installer 2017-03-29 22:11:01 -04:00
Mike Koch
20b7643657 Merge branch '573-sql-fixes' into '3-0-4'
Fix some potention SQL injection vulns

See merge request !49
2017-03-29 01:58:32 +00:00
Mike Koch
59ebafdf81 Fix some potention SQL injection vulns 2017-03-28 21:56:49 -04:00
Mike Koch
60c5be549c Merge branch '463-suggest-kb-rich-text' into '3-0-4'
Fixes #463 Support suggested KB articles when rich text is enabled

See merge request !48
2017-03-29 01:22:22 +00:00
Mike Koch
55c6f4d093 Fixes #463 Support suggested KB articles when rich text is enabled 2017-03-28 21:21:17 -04:00
Mike Koch
48f5ad1810 Merge branch '503-align-message-to-custom-fields' into '3-0-4'
#503 tweak message format, also fix some missing changes for the calendar fix

See merge request !47
2017-03-28 01:53:30 +00:00
Mike Koch
80b6ef4c9b #503 tweak message format, also fix some missing changes for the calendar fix 2017-03-27 21:52:34 -04:00
Mike Koch
3a89bfeca1 Merge branch '504-custom-field-default-value' into '3-0-4'
Fixes #504 set readonly field names different to prevent incorrect values

See merge request !46
2017-03-28 01:45:44 +00:00
Mike Koch
7a723f5250 Fixes #504 set readonly field names different to prevent incorrect values 2017-03-27 21:43:14 -04:00
Mike Koch
0e04e44e1f Merge branch '508-calendar-select-deselect' into '3-0-4'
Fixes #508 Update category visibility after loading events

See merge request !45
2017-03-28 01:00:20 +00:00
Mike Koch
938bb20c3f Fixes #508 Update category visibility after loading events 2017-03-27 20:59:13 -04:00
Mike Koch
97a96b5947 UserToTicketChecker now checks for category managers 2017-03-25 16:36:47 -04:00
Mike Koch
37149ec831 Working on user ticket security checker 2017-03-22 22:07:14 -04:00
Mike Koch
5112a6a13b Make the endpoint only for ticket message attachments, not replies 2017-03-22 12:54:43 -04:00
Mike Koch
0556d07a56 Attachments can now be uploaded for a ticket. Still need to handle updating the reply's property 2017-03-21 22:11:19 -04:00
Mike Koch
8d484f62ea Mostly done with attachment uploading 2017-03-20 22:16:35 -04:00
Mike Koch
4fd6595ded Handle building the attachment and saving it to the FS 2017-03-18 22:13:08 -04:00
Mike Koch
ffd3ac2edf Working on some validation tests 2017-03-17 22:05:51 -04:00
Mike Koch
8378d35149 Start working on attachments API. Fix .gitignore 2017-03-15 22:07:17 -04:00
Mike Koch
f40eaf1a23 Fix tests 2017-03-12 21:24:49 -04:00
Mike Koch
cc880a15fc Show stack traces on the message log page 2017-03-12 20:57:36 -04:00
Mike Koch
f15cb63d32 Logging has been implemented for exceptions 2017-03-12 20:50:54 -04:00
Mike Koch
6af93506f1 Properly handle if the API is disabled 2017-03-12 15:58:17 -04:00
Mike Koch
d0475b22c1 Add UserPrivilege enum, provide better 404 information 2017-03-12 15:37:23 -04:00
Mike Koch
25929d82f4 Fixed some email issues 2017-03-12 01:06:50 -05:00
Mike Koch
ccbe2cd580 MFH Settings being loaded, emails being sent out 2017-03-12 00:44:50 -05:00
Mike Koch
06a38e9383 Autoassign logic is finished 2017-03-11 23:43:50 -05:00
Mike Koch
af789a7060 Working on autoassign rewrite logic 2017-03-10 22:06:32 -05:00
Mike Koch
ad2c96c667 Update composer.json and ApplicationContext 2017-03-09 21:55:32 -05:00
Mike Koch
64428872df Created an entity for user 2017-03-08 21:49:30 -05:00
Mike Koch
abdc734833 Merge branch '506-customer-reply-form-location' into '3-0-4'
Put ticket reply form in the right place

See merge request !44
2017-03-07 17:55:31 +00:00
Mike Koch
5a1b4552ce Put ticket reply form in the right place 2017-03-07 12:54:20 -05:00
Mike Koch
488a86cbac Merge branch '519-fix-status-key-on-emails' into '3-0-4'
Fixes #519 Pull from bridge table for status name

See merge request !43
2017-03-07 02:59:14 +00:00
Mike Koch
9325d819c7 Fixes #519 Pull from bridge table for status name 2017-03-06 21:58:07 -05:00
Mike Koch
01c56da52c Working on adding Spot ORM 2017-03-06 21:44:38 -05:00
Mike Koch
2201f188bd Some changes 2017-03-05 22:03:11 -05:00
Mike Koch
672d089b20 Working on more email stuff 2017-03-04 21:59:55 -05:00
Mike Koch
2a6766c10e Pretty much done with the EmailSenderHelper 2017-03-04 00:43:08 -05:00
Mike Koch
e7eeac9f34 Working on more email sender stuff 2017-03-03 22:05:41 -05:00
Mike Koch
9832ca58ba Some refactoring to the email stuff 2017-03-02 22:05:28 -05:00
Mike Koch
36f8de957a Able to parse email templates.... I hope 2017-02-28 22:03:08 -05:00
Mike Koch
c3e70309bc Some more changes 2017-02-27 21:24:24 -05:00
Mike Koch
41123e987b Some more API changes 2017-02-26 21:52:12 -05:00
Mike Koch
0ceaafc0ec Changes 2017-02-24 22:01:54 -05:00
Mike Koch
9b2aa355b9 Little progress, but still something 2017-02-23 22:04:56 -05:00
Mike Koch
5550565615 Merge branch 'DarekTw-patch-1' into 3-0-4 2017-02-23 08:08:19 -05:00
Mike Koch
c3e6fd5b35 Merge branch 'patch-1' of https://github.com/DarekTw/Mods-for-HESK into DarekTw-patch-1 2017-02-23 08:07:53 -05:00
Mike Koch
b53e9aafd7 Getting started on email retrieval/parsing 2017-02-22 22:02:24 -05:00
Mike Koch
4c7449ea3e Properly handle tickets that need validation. Added comments for next steps 2017-02-20 22:07:39 -05:00
Mike Koch
c1638aeb98 First steps in supporting email validation 2017-02-20 13:05:41 -05:00
Mike Koch
08d7347f00 Small tweaks 2017-02-19 22:04:47 -05:00
Mike Koch
54baa4d6ba Created email senders and integration tests for these senders 2017-02-19 22:02:10 -05:00
Mike Koch
2a145bfa3e SMTP emails working with EmailSender...haven't tested attaching things though 2017-02-18 22:11:45 -05:00
Mike Koch
b4dcbc9846 Getting started on email sender for customer ticket creation 2017-02-16 22:04:59 -05:00
Mike Koch
ca499d5eac Basic ticket creator appears to be working. Still need to handle email 2017-02-16 21:46:47 -05:00
Mike Koch
c8485c0fa3 Working on a status gateway to get the ticket's default status 2017-02-15 22:01:15 -05:00
Mike Koch
31ced3f572 Add somre more fields 2017-02-14 22:03:46 -05:00
Mike Koch
1b6cca8ddf Create ticket endpoint now working, but needs some changes 2017-02-14 12:45:02 -05:00
Mike Koch
1cb4209be2 Working more on create ticket endpoint 2017-02-13 22:34:15 -05:00
Mike Koch
843528252b Getting started on POST for ticket controller 2017-02-13 13:02:40 -05:00
Mike Koch
dc0c8a351b I think I finished the ticket creator 2017-02-13 12:52:43 -05:00
Mike Koch
489f191a13 Majority of create ticket logic done. Just need to add attachments(?) and retriever SQL-specific fields 2017-02-12 22:10:42 -05:00
Mike Koch
1a8a989e87 Moved validation logic to its own class, working on createTicket tests 2017-02-12 01:38:12 -05:00
Mike Koch
044faa77f6 TicketGateway can now insert tickets 2017-02-12 00:50:30 -05:00
Mike Koch
65b10bae3c TrackingIdGenerator working. Stubbed out todo list for rest of creating ticket 2017-02-11 22:07:10 -05:00
Mike Koch
7e966b93a5 Intermediate commit 2017-02-11 16:42:40 -05:00
Mike Koch
ee3a425c59 Remove unnecessary comment 2017-02-11 16:27:39 -05:00
Mike Koch
44239ed459 Start working on TrackingIdGenerator 2017-02-11 16:24:08 -05:00
DarekTw
dd0119602b Fixed unclosed <div> 2017-02-11 16:12:42 +01:00
Mike Koch
6f87dfc149 Small fix on validation model 2017-02-10 22:10:39 -05:00
Mike Koch
d476f86c8c Finished validation tests for create ticket 2017-02-10 22:09:46 -05:00
Mike Koch
bc9bb698c5 Add some more validation tests for dates 2017-02-10 13:05:40 -05:00
Mike Koch
e44baa99c2 Refactored custom field validator, re-enabled test 2017-02-09 12:57:28 -05:00
Mike Koch
e22d318b92 More tests for TicketCreator. Need to refactor some custom field logic 2017-02-07 22:16:15 -05:00
Mike Koch
44e45852d0 Merge branch '507-missing-new-event-button' into '3-0-4'
Add back missing create event button

See merge request !42
2017-02-07 18:02:39 +00:00
Mike Koch
d7a25b7c7a Fixes #507 Add back missing create event button 2017-02-07 13:01:28 -05:00
Mike Koch
4e438d9fd3 Merge branch '509-fix-reply-with-rich-text' into '3-0-4'
Allow customers to respond using rich text

See merge request !41
2017-02-07 17:42:12 +00:00
Mike Koch
cecd302957 Fixes #509 Allow customers to respond using rich text 2017-02-07 12:39:29 -05:00
Mike Koch
b76e2afac1 More work on ticket creator tests 2017-02-06 22:13:16 -05:00
Mike Koch
98cbd6e4dd Working on TicketCreator tests 2017-02-05 22:12:18 -05:00
Mike Koch
176b786279 Move ban test, work on TicketValidators test 2017-02-03 22:08:44 -05:00
Mike Koch
bbdb03d103 Testing is working! 2017-02-02 22:30:41 -05:00
Mike Koch
2b792cff72 Fix exception handler for E_NOTICE 2017-02-02 21:22:04 -05:00
Mike Koch
a702d157cd Delete unused DAOs, fix some replace errors 2017-02-02 20:21:25 -05:00
Mike Koch
ad43c420bb Use PSR-4 standard for classloading 2017-02-01 22:04:52 -05:00
Mike Koch
2b0d2bb9cc Send all enabled custom fields 2017-02-01 21:03:05 -05:00
Mike Koch
a2c98a5a26 Ticket stuff slowly taking shape 2017-01-31 22:26:46 -05:00
Mike Koch
a4af2e668f More work on ticket stuff 2017-01-30 22:10:14 -05:00
Mike Koch
8968be1ffd More work on exception handling and user context building 2017-01-28 22:35:42 -05:00
Mike Koch
e68ecf50c6 Moved some more stuff to new structure 2017-01-28 01:41:29 -05:00
Mike Koch
2ef67de718 Added proper DI and autoloading to make things simpler for the actual logic' 2017-01-28 01:28:53 -05:00
Mike Koch
ecbd2fd94a Fixed some folder structures and worked on ban retrieval 2017-01-27 22:26:28 -05:00
Mike Koch
e1176ec4ee Getting started on ticket endpoint... again 2017-01-26 22:00:45 -05:00
Mike Koch
fc38673b7d Some temporary error handling 2017-01-25 21:55:13 -05:00
Mike Koch
dc07f5e757 Move link to the api folder 2017-01-25 21:27:39 -05:00
Mike Koch
ba0a035d88 Update CONTRIBUTING.md 2017-01-25 20:52:59 +00:00
Mike Koch
6721c558af Update CONTRIBUTING.md 2017-01-25 20:52:20 +00:00
Mike Koch
aff8dadd27 Category Controller is working 2017-01-21 22:09:29 -05:00
Mike Koch
93431e9a98 Build the user context based on hashed token 2017-01-21 16:34:03 -05:00
Mike Koch
17f6bb770d UserContextBuilder mostly done 2017-01-20 21:50:58 -05:00
Mike Koch
96120bc744 Working on user context 2017-01-20 07:19:39 -05:00
Mike Koch
c184469219 Able to hit a controller through link 2017-01-18 21:56:12 -05:00
Mike Koch
d9000c12c7 More routing changes 2017-01-18 17:22:24 -05:00
Mike Koch
5e21877efc Add Link for simple API routing 2017-01-17 22:12:45 -05:00
Mike Koch
b7cbca03a7 Getting started on routing 2017-01-17 22:08:48 -05:00
Mike Koch
f9845624d4 More API changes 2017-01-17 21:58:57 -05:00
Mike Koch
403b87bbda Bunch of stuff 2017-01-16 22:21:11 -05:00
Mike Koch
4942fdbfda Use __DIR__ to make importing easier and only when required 2017-01-14 22:00:27 -05:00
Mike Koch
d1ae2a8009 Getting started on new ticket validator 2017-01-11 21:55:22 -05:00
Mike Koch
273feb676c Forgot to update installModsForHesk 2017-01-07 21:26:03 -05:00
Mike Koch
80e69f3ef0 Bump to 3.0.3 2017-01-07 20:49:44 -05:00
Mike Koch
2ca6d230e3 Revert back to old install script format 2017-01-07 20:47:53 -05:00
Mike Koch
6924ae0fb7 Merge branch 'bug-fix-field-validation' into 'master'
Fix checkbox validator

See merge request !40
2017-01-07 02:55:44 +00:00
Mike Koch
0215657650 Fix checkbox validator 2017-01-06 21:55:14 -05:00
Mike Koch
24e2607fe3 Merge branch 'bug-fix-stage-tickets-table' into 'master'
Fix Stage Ticket Table

See merge request !39
2017-01-07 02:00:54 +00:00
Mike Koch
a43338a017 Fix columns 2017-01-06 20:59:43 -05:00
Mike Koch
0b44970041 Merge branch '3-0-1' into 'master'
3.0.1 Update

Closes #488, #489, #490, #494, #496, #497, and #499

See merge request !38
2017-01-05 04:18:41 +00:00
Mike Koch
8ef0ed6a29 Add reCAPTCHA scripts when required 2017-01-04 21:49:02 -05:00
Mike Koch
f63f141177 Improve database validation 2017-01-03 22:16:04 -05:00
Mike Koch
92b4f8e4d0 Update version, tweak login CSS to perform better on mobile 2017-01-03 22:02:23 -05:00
Mike Koch
9e4ec347cf Show full-size notice with 0 messages to fill in space 2017-01-03 21:42:52 -05:00
Mike Koch
6a42560c0c Merge branch '497-update-to-hesk-2-7-2' into '3-0-1'
Update to HESK 2.7.2

See merge request !37
2017-01-03 17:07:29 +00:00
Mike Koch
7ee6f353aa Merge branch '496-fix-uninstaller' into '3-0-1'
Fix Uninstaller SQL

See merge request !36
2017-01-03 17:06:46 +00:00
Mike Koch
5ae2c1c4a4 Merge branch '494-fix-kb-private' into '3-0-1'
Fix Knowledgebase UI for Staff

See merge request !35
2017-01-03 17:06:04 +00:00
Mike Koch
628031a11e Merge branch '490-ticket-sidebar-color-scheme' into '3-0-1'
Fix sidebar text color w/light scheme

See merge request !33
2017-01-03 17:05:24 +00:00
Mike Koch
3557d5a97f Merge branch '489-canned-responses-not-showing' into '3-0-1'
Load canned responses before displaying reply form

See merge request !32
2017-01-03 17:05:01 +00:00
Mike Koch
d5dce1f931 Merge branch '488-admin-color-dropdown' into '3-0-1'
Fix admin color scheme dropdown

See merge request !31
2017-01-03 17:04:45 +00:00
Mike Koch
081fcf779c Update to HESK 2.7.2 2017-01-02 16:42:41 -05:00
Mike Koch
27a1efafcf Fix unintall SQL 2017-01-02 16:26:10 -05:00
Mike Koch
030b62389e Fix knowledgebase for staff 2017-01-02 16:24:33 -05:00
Mike Koch
6b0e7f17bb Merge branch '493-users-online-rewrite' into '3-0-1'
Resolve "Can't see users"

See merge request !34
2017-01-02 21:09:43 +00:00
Mike Koch
660c28e2f8 Move users online to top navbar 2017-01-02 16:03:20 -05:00
Mike Koch
910e753314 Add users_online to repo 2017-01-02 15:33:02 -05:00
Mike Koch
b58cfda4c8 Set color darker when using a light theme 2017-01-02 13:16:07 -05:00
Mike Koch
2050174cd7 Load canned reponses before displaying reply form 2017-01-02 12:44:52 -05:00
Mike Koch
788fb3462c Fix admin color scheme dropdown 2017-01-02 12:38:48 -05:00
Mike Koch
93c7ddc528 Fix date format on original ticket message 2016-12-31 23:38:51 -05:00
Mike Koch
93fb2e63f2 Translate text 2016-12-31 23:23:19 -05:00
Mike Koch
d3dfd7f326 Change note color scheme, fix add note button 2016-12-31 23:20:19 -05:00
Mike Koch
76d47a6f64 Update installer for 3.0.0 2016-12-31 22:01:18 -05:00
Mike Koch
177af6b0ec Fixes #485 Preserve all preferences when disabled 2016-12-29 13:04:44 -05:00
Mike Koch
76dab03bc3 Properly show dropdown for limited access users 2016-12-29 12:57:24 -05:00
Mike Koch
3f7a57fd66 Some CSS tweaks 2016-12-13 21:37:32 -05:00
Mike Koch
03814ea2a3 Add list week view to calendar 2016-11-30 22:26:11 -05:00
Mike Koch
7fe7fa5450 Bump version to 3.0.0 RC 1 2016-11-30 21:58:24 -05:00
Mike Koch
63e969c0b6 Fix powered by when tickets > 1, fix copy ticket 2016-11-30 21:49:15 -05:00
Mike Koch
ba8d35d762 Move add note to inline section instead of modal 2016-11-30 21:25:10 -05:00
Mike Koch
c6a2f7fcff Fix undefined index when submitting ticket as customer 2016-11-30 13:21:03 -05:00
Mike Koch
ce73cb109a Fix new ticket not showing up with 0 results, fix powered by visibility 2016-11-30 13:18:41 -05:00
Mike Koch
6a4a1ec56c Remove useless 'from' 2016-11-30 13:10:53 -05:00
Mike Koch
c9fc8ef28f Don't stop if a query fails. 2016-11-30 13:01:38 -05:00
Mike Koch
ed87d6fc87 Clicking the top of the box should collapse it 2016-11-30 12:51:50 -05:00
Mike Koch
c3c13e6291 Fix email template link 2016-11-30 08:42:39 -05:00
Mike Koch
7316538105 Add settings links to sidebar 2016-11-29 22:36:02 -05:00
Mike Koch
05072814b6 Mail uses sidebar 2016-11-29 13:06:35 -05:00
Mike Koch
b3634857c8 Actually display the text 2016-11-29 12:57:56 -05:00
Mike Koch
43d1c07a30 Contentify 'see all messages' 2016-11-29 12:57:39 -05:00
Mike Koch
996d73502d Add toggle tooltip 2016-11-29 12:56:09 -05:00
Mike Koch
45b3f88783 Calendar uses new sidebar 2016-11-29 00:36:35 -05:00
Mike Koch
2d2d8379cf Move the content-wrapper after the sidebar 2016-11-28 22:03:01 -05:00
Mike Koch
2cca514966 Add slimscroll to allow sidebar to scroll independently 2016-11-28 17:36:04 -05:00
Mike Koch
c6c3650026 Moved all sidebar stuff back to sidebar, moved email and IP back to original message 2016-11-28 17:33:05 -05:00
Mike Koch
f4da37bdcf Moved everything that used to be on the sidebar to the side 2016-11-28 16:56:28 -05:00
Mike Koch
94a9d59740 Starting to put ticket info on the sidebar 2016-11-27 22:15:37 -05:00
Mike Koch
d55e19c5d6 Moved content-wrapper to actual pages 2016-11-27 22:01:32 -05:00
Mike Koch
916ce2d244 Slight change to how the header reacts 2016-11-27 18:30:11 -05:00
Mike Koch
937f91f352 Got a basic layout with top bar only working. Need to handle each page now 2016-11-27 01:35:08 -05:00
Mike Koch
a89fc9b20f More progress on top navbar 2016-11-26 22:22:50 -05:00
Mike Koch
61cd534f7f Getting started on top navbar 2016-11-25 22:09:28 -05:00
Mike Koch
50d8493448 Renamed created ticket for same contact, moved close/open to main list of options 2016-11-25 21:51:16 -05:00
Mike Koch
a604982818 Fix audit log 2016-11-25 17:09:47 -05:00
Mike Koch
654a2be8ab Change submit reply + change status to dropup to prevent overflow issues 2016-11-25 17:04:42 -05:00
Mike Koch
c21dd2ec72 Fix replying to ticket on customer side 2016-11-25 16:57:10 -05:00
Mike Koch
87275b80cb Fix some install SQL and properly 500 on error 2016-11-25 15:59:43 -05:00
Mike Koch
53403e2345 Remove custom field IDs and fix placeholder encoding 2016-11-23 22:15:02 -05:00
Mike Koch
182f7f32ca Fix MFH verison check 2016-11-23 22:07:46 -05:00
Mike Koch
f6a52c11ba Don't use the on the index page 2016-11-23 22:02:49 -05:00
Mike Koch
e9fdb0e132 Fix missing slashes in calendar events 2016-11-23 22:02:37 -05:00
Mike Koch
598ef29eb8 Remove leftover calendar panel 2016-11-23 21:51:02 -05:00
Mike Koch
cd8588ecd4 Fix footer for licensed users 2016-11-23 21:48:53 -05:00
Mike Koch
f310039d89 Tweak notes color scheme 2016-11-22 22:02:44 -05:00
Mike Koch
18ffa18383 Changed look of message boxes 2016-11-22 21:49:52 -05:00
Mike Koch
1f82c83668 Moved new ticket button, changed priority icons 2016-11-22 21:42:45 -05:00
Mike Koch
753c1f2bd2 Fix query to improve performance 2016-11-22 21:03:36 -05:00
Mike Koch
63e5e74b12 Udpate to FC 3, add jQuery 2 2016-11-22 15:47:10 -05:00
Mike Koch
e7dd7a479a Update the other scripts for all-day 2016-11-22 13:06:54 -05:00
Mike Koch
a43108404d Fix all day event rendering for events 2016-11-22 12:58:18 -05:00
Mike Koch
6eb97cd7c8 Merge branch 'hesk-2-7-0-final-update' into 'master'
HESK 2.7.0 Final Changes

See merge request !30
2016-11-19 16:55:34 +00:00
Mike Koch
49e385e730 Replace ->num_rows with hesk_dbNumRows() 2016-11-18 22:03:10 -05:00
Mike Koch
34faefaf98 Bump version to stable for now 2016-11-18 22:00:39 -05:00
Mike Koch
9f3db36b71 Update modsForHesk.php 2016-11-19 01:57:24 +00:00
Mike Koch
b1b16fe381 HESK 2.7.0 RC1 -> Final changes 2016-11-18 12:57:17 -05:00
Mike Koch
38d56f195f Merge branch '3-0-0' into 'master'
3.0.0 Update

See merge request !29
2016-11-18 02:40:33 +00:00
Mike Koch
c5aff8b9db Merge remote-tracking branch 'origin/master' into 3-0-0 2016-11-17 21:12:54 -05:00
Mike Koch
bb1e62af82 Mark this update as beta 1 2016-11-17 21:12:41 -05:00
Mike Koch
ea0336688f Use test version check for MFH as well 2016-11-17 21:07:07 -05:00
Mike Koch
f290ad51eb Fix 'from' on email header 2016-11-17 20:57:50 -05:00
Mike Koch
852f2d8da7 Fix CSS class 2016-11-17 20:33:07 -05:00
Mike Koch
db790749ac Update build.php 2016-11-17 13:04:41 +00:00
Mike Koch
5ca17fb9e9 Updated installer. Still need to test actual install script 2016-11-16 22:06:36 -05:00
Mike Koch
ea75c7d1f4 Remove random 2.7.0 scripts 2016-11-16 21:23:11 -05:00
Mike Koch
7d83f10370 Update license headers 2016-11-16 21:16:25 -05:00
Mike Koch
642adb4a75 Merge branch 'hesk-2-7-0-update' into '3-0-0'
HESK 2.7.0 Update

See merge request !28
2016-11-17 01:51:08 +00:00
Mike Koch
74beb8d6bc Add admin color scheme setting 2016-11-16 20:46:14 -05:00
Mike Koch
aba103bb49 Use YYYY-MM-DD for ticket date, restyle find_tickets 2016-11-16 16:48:45 -05:00
Mike Koch
988f0e9a0f Export uses YYYY-MM-DD 2016-11-16 16:32:07 -05:00
Mike Koch
f559979b33 Change reports to BS datepicker and YYYY-MM-DD 2016-11-16 16:08:59 -05:00
Mike Koch
af106175d8 Change system warning text 2016-11-16 15:59:40 -05:00
Mike Koch
c560fc74dd Remove extra ' from map modal 2016-11-16 15:56:47 -05:00
Mike Koch
267afc8c21 Add validation to edit post 2016-11-16 13:21:26 -05:00
Mike Koch
eeadeb543d Don't show header items during maintenance mode 2016-11-15 22:00:05 -05:00
Mike Koch
e6ff8672cf Don't show home and ticket tabs when helpdesk in KB-only mode 2016-11-15 21:50:30 -05:00
Mike Koch
165121abc0 Restyled edit user page 2016-11-15 12:58:47 -05:00
Mike Koch
1bf3a24f48 Fix styling for autoreload, remove autorefresh code 2016-11-15 12:53:33 -05:00
Mike Koch
8dfcdaa0f0 Handle changing language on view ticket page 2016-11-15 12:46:34 -05:00
Mike Koch
a186ef7eed Add require owner field on settings page 2016-11-15 12:34:31 -05:00
Mike Koch
99b88ed0b3 Fix breadcrumb on admin create ticket 2016-11-15 12:31:01 -05:00
Mike Koch
8c596538e2 Fix 'Click to view ticket' when submitting ticket 2016-11-15 12:29:05 -05:00
Mike Koch
011072f4b7 Fix footer, don't show box around 'Powered by' message 2016-11-15 12:18:02 -05:00
Mike Koch
8bc2d95474 Add validator fields to custom fields 2016-11-14 22:02:12 -05:00
Mike Koch
31b3aeabf8 Fix multilang custom fields, add validators to CF on admin new ticket 2016-11-14 15:52:39 -05:00
Mike Koch
e35dc66756 RC1 changes 2016-11-12 22:43:09 -05:00
Mike Koch
abedb2269a Styling fix for autorefresh 2016-11-12 12:28:05 -05:00
Mike Koch
9b2c6d08be Fix autorefresh 2016-11-11 23:05:36 -05:00
Mike Koch
9532ab3ee7 Edit post restyled, fixes to admin_ticket 2016-11-10 21:56:39 -05:00
Mike Koch
a35ceb213d Fix saving settings 2016-11-09 13:21:16 -05:00
Mike Koch
f176f2238f Restyled select ticket category for new ticket 2016-11-08 20:56:48 -05:00
Mike Koch
59cc8498cf More custom field fixes 2016-11-08 13:09:54 -05:00
Mike Koch
61f6e0eb98 Fixed custom fields on new ticket 2016-11-08 12:53:19 -05:00
Mike Koch
9f7a152941 Add RC1 files to gitignore 2016-11-08 12:28:30 -05:00
Mike Koch
49b8b44413 Use YYYY-MM-DD regex due to datepicker switch 2016-11-07 17:41:35 -05:00
Mike Koch
df46cc7579 Some tweaks to the database validation 2016-11-06 22:10:25 -05:00
Mike Koch
44f62052f2 Add a database validator 2016-11-06 22:00:56 -05:00
Mike Koch
ea8aac8d64 Working on re-converting custom fields 2016-11-04 22:00:37 -04:00
Mike Koch
7524d58218 Starting on fixing custom fields 2016-11-01 13:04:16 -04:00
Mike Koch
944f304bd9 Add cc/bcc support for email 2016-11-01 12:59:19 -04:00
Mike Koch
4c55e50c04 Add readonly to manage custom fields 2016-10-31 21:56:54 -04:00
Mike Koch
f2774badf1 Add custom field header to tools pages 2016-10-31 21:05:02 -04:00
Mike Koch
47d32be2b8 Custom fields page uses new UI 2016-10-31 20:57:13 -04:00
Mike Koch
a11d2c95bb Update .gitignore 2016-10-27 20:51:20 -04:00
Mike Koch
9295cf4e14 Rest of b3 updates 2016-10-26 13:42:42 -04:00
Mike Koch
f883aff904 Several beta 3 updates 2016-10-26 13:31:21 -04:00
Mike Koch
4910e25b0a Update settings 2016-10-26 13:24:11 -04:00
Mike Koch
9fcec93b0c Update ticket 2016-10-26 13:19:49 -04:00
Mike Koch
3fe649d14b Changes 2016-10-26 13:11:13 -04:00
Mike Koch
3a690ace8e Update suggest_email 2016-10-25 13:11:41 -04:00
Mike Koch
9ca1bcffb1 Update submit_ticket 2016-10-25 13:08:37 -04:00
Mike Koch
1224ea8d23 Update print and reply_ticket 2016-10-25 12:38:34 -04:00
Mike Koch
7d7e1bd1c4 Update knowledgebase 2016-10-25 12:32:36 -04:00
Mike Koch
4ec37a5079 Update profile_functions 2016-10-24 15:20:16 -04:00
Mike Koch
f54e02fd14 Update print_tickets 2016-10-24 13:35:55 -04:00
Mike Koch
7f0a1628aa Update posting_functions 2016-10-24 13:33:34 -04:00
Mike Koch
fb0503b89b Update pipe_functions 2016-10-23 22:01:37 -04:00
Mike Koch
5e2239a017 Remove LIMIT 1 fro madmin_functions 2016-10-23 22:00:12 -04:00
Mike Koch
bb2d69ca01 Update header 2016-10-23 21:58:34 -04:00
Mike Koch
007feed56c Update email_functions 2016-10-23 21:45:52 -04:00
Mike Koch
76ea4caaa9 Update common 2016-10-22 21:58:43 -04:00
Mike Koch
34cf3106d0 Update admin_functions 2016-10-22 21:45:41 -04:00
Mike Koch
a960a09892 Update hesk_style 2016-10-22 21:42:22 -04:00
Mike Koch
b5955502e5 Update hesk_javascript 2016-10-22 21:39:11 -04:00
Mike Koch
26c2b10d4b Update change_status 2016-10-18 22:01:33 -04:00
Mike Koch
27ded2f593 Update show_tickets 2016-10-18 21:57:33 -04:00
Mike Koch
4394a96090 Update service messages 2016-10-18 21:56:19 -04:00
Mike Koch
f446cac055 Update profile 2016-10-18 21:47:59 -04:00
Mike Koch
792b0c8445 Delete options.php 2016-10-18 21:35:25 -04:00
Mike Koch
b41928ee83 Update new ticket. Probably broken right now but it's something 2016-10-18 21:35:04 -04:00
Mike Koch
0beabedf81 Getting started on admin_ticket 2016-10-17 22:09:51 -04:00
Mike Koch
41c858aa9b Update move category 2016-10-12 21:29:44 -04:00
Mike Koch
e9632e5764 Update manage_users 2016-10-12 21:25:36 -04:00
Mike Koch
c3c4a584f9 Update ticket tpls 2016-10-12 13:36:22 -04:00
Mike Koch
64f1f99705 Update manage kb 2016-10-12 13:34:27 -04:00
Mike Koch
16841d9d5a Update canned and categories 2016-10-12 13:29:50 -04:00
Mike Koch
db960b2c26 Update lock and mail 2016-10-12 13:26:28 -04:00
Mike Koch
7770b58673 Update private KB 2016-10-12 13:24:31 -04:00
Mike Koch
e1204b78c2 Update admin index 2016-10-12 13:21:24 -04:00
Mike Koch
2db83782c0 Update find_tickets 2016-10-12 13:20:30 -04:00
Mike Koch
67e5d805dc Update export 2016-10-12 13:19:12 -04:00
Mike Koch
c679fc66e2 Update edit_post
NOTE: Need to re-add MFH-specific custom fields (multiselect only I think...)
2016-10-11 22:01:20 -04:00
Mike Koch
86a2e0e52e Update delete_tickets 2016-10-11 21:48:55 -04:00
Mike Koch
416412a313 Update change_status 2016-10-11 21:47:16 -04:00
Mike Koch
0f9d9be6e9 Update banned ips 2016-10-09 21:37:48 -04:00
Mike Koch
324866f3c3 update banned emails 2016-10-09 21:35:32 -04:00
Mike Koch
695aae6cd9 Update assign_owner 2016-10-09 21:26:32 -04:00
Mike Koch
6c5c9f0591 Finish updating admin_ticket 2016-10-09 21:18:24 -04:00
Mike Koch
fd7d9e902b Still working on admin ticket. Continue on line 1772 of the diff 2016-10-08 22:02:15 -04:00
Mike Koch
df5ec2281d Some more changes 2016-10-05 17:53:23 -04:00
Mike Koch
cacad60c53 Update admin_submit_ticket 2016-10-05 13:29:06 -04:00
Mike Koch
ef8b282f0c Update admin_settings_save 2016-10-05 13:10:47 -04:00
Mike Koch
5094ce5200 Finished settings page updates 2016-10-05 13:03:38 -04:00
Mike Koch
444f05486f Moved more settings, removed custom fields from settings 2016-10-04 22:08:07 -04:00
Mike Koch
2713647d40 Add HESK 2.7.0 language keys 2016-10-04 20:56:36 -04:00
Mike Koch
7ec6a2b0fb Some settings have been migrated. Missing several language keys 2016-10-03 22:02:07 -04:00
Mike Koch
8e0236b2b4 Some changes to admin/admin_reply 2016-10-03 20:44:42 -04:00
Mike Koch
ccb8931157 Merge branch 'new-staff-page' into '3-0-0'
New staff page



See merge request !27
2016-10-02 15:32:22 +00:00
Mike Koch
d4da338b82 Merge remote-tracking branch 'remotes/origin/3-0-0' into new-staff-page 2016-10-02 11:22:49 -04:00
Mike Koch
0c77843ea7 Slight changes, fix lockout vuln 2016-09-30 21:28:26 -04:00
Mike Koch
5c53ce7991 Redid password reset screen 2016-09-29 22:00:31 -04:00
Mike Koch
2b0b67d2a0 Login screen redone 2016-09-29 21:51:49 -04:00
Mike Koch
4ff6a97a26 Redo edit note UI 2016-09-27 22:07:38 -04:00
Mike Koch
10b293d0d3 API settings page redone, contentified 2016-09-27 22:04:05 -04:00
Mike Koch
f23ca3598e Create ticket page uses new UI 2016-09-27 13:08:31 -04:00
Mike Koch
6d6fe67c53 Mail uses new UI 2016-09-27 12:41:29 -04:00
Mike Koch
8b14ef19cd View ticket and edit post on admin-side restyled 2016-09-25 21:34:19 -04:00
Mike Koch
03765bb798 Added clock to bottom, changed icons for reply vs cust reply 2016-09-23 22:14:39 -04:00
Mike Koch
ee979cf15b Starting on timeline 2016-09-20 13:08:08 -04:00
Mike Koch
f1e106bf48 More work on admin_ticket 2016-09-20 07:59:05 -04:00
Mike Koch
b2f1ff3419 More admin ticket changes 2016-09-18 21:58:16 -04:00
Mike Koch
3eb1cdaffb More admin ticket changes 2016-09-17 21:42:25 -04:00
Mike Koch
e3d2052912 Still working on admin ticket 2016-09-15 22:06:22 -04:00
Mike Koch
12aca461ad Move close/open ticket and create new for contact to dropdown 2016-09-15 13:06:51 -04:00
Mike Koch
579509ef59 Working on admin ticket restyling 2016-09-14 22:09:56 -04:00
Mike Koch
e2c144d8ed Start working on ticket screen 2016-09-11 22:14:15 -04:00
Mike Koch
822c35f2ce Private KB follows new UI 2016-09-11 21:50:20 -04:00
Mike Koch
e62e6233a6 FA doesn't need to be multiplied by 10 2016-09-11 19:23:43 -04:00
Mike Koch
44f90c595a manage_kb uses new style 2016-09-11 19:11:59 -04:00
Mike Koch
d1145b0e98 Fix settings feedback, style add KB article 2016-09-09 22:11:52 -04:00
Mike Koch
155925dc13 Merge branch 'use-correct-ticket-message-editor-when-editing' into '2-7-0'
Use correct ticket editor when editing ticket/reply



See merge request !26
2016-09-07 14:09:51 +00:00
Mike Koch
8a0f99760e Working on new UI for knowledgebase 2016-09-06 13:01:12 -04:00
Mike Koch
8441b5ecc9 Profile uses new UI 2016-09-05 16:59:47 -04:00
Mike Koch
46be4939c1 Settings page uses new UI 2016-09-05 15:13:56 -04:00
Mike Koch
d70e9fc350 #451 Use correct ticket editor when editing ticket/reply 2016-09-02 08:02:36 -04:00
Mike Koch
baf90b7a5d Updated tools to new UI, starting on admin_settings 2016-08-23 12:56:11 -04:00
Mike Koch
bd15f925bc Add minimize button to export box 2016-08-16 22:02:03 -04:00
Mike Koch
d173ee35e9 Update export UI 2016-08-16 21:25:43 -04:00
Mike Koch
8e9ab82391 Getting started on export page 2016-08-15 22:01:32 -04:00
Mike Koch
f1d4a69f61 Reports use new UI 2016-08-15 16:49:56 -04:00
Mike Koch
af8af9b241 Calendar uses new UI 2016-08-15 16:35:41 -04:00
Mike Koch
eed0a8b2d7 Move footer to new one 2016-08-15 15:49:31 -04:00
Mike Koch
42c49c688c Collapse add use, ticket tpl uses new UI 2016-08-15 15:37:41 -04:00
Mike Koch
34e58519f2 Canned responses uses new UI 2016-08-12 21:56:15 -04:00
Mike Koch
774d775c11 Manage categories uses new UI 2016-08-11 22:01:41 -04:00
Mike Koch
e865412b5f Moved header stuff to old file names, working on permission templates 2016-08-11 13:06:12 -04:00
Mike Koch
1337090964 Merge remote-tracking branch 'origin/master' into new-staff-page 2016-08-11 13:05:39 -04:00
Mike Koch
98f2bf0531 Update .gitignore to ignore htmlpurifier 2016-08-11 00:08:00 -04:00
Mike Koch
91a159344c Merge branch '2-6-4' into 'master'
2.6.4 Update

Closes #448, #449

See merge request !25
2016-08-11 04:04:54 +00:00
Mike Koch
84e560e6ba Update installer 2016-08-11 00:03:06 -04:00
Mike Koch
e0e748c5d8 Fixes #448 Set correct lock status, dont show open/close link to clients when ticket is locked 2016-08-10 23:57:37 -04:00
Mike Koch
ef19dcb9b5 Update version headers 2016-08-10 23:36:20 -04:00
Mike Koch
6ee6fcaaab Update ticket 2016-08-10 23:34:45 -04:00
Mike Koch
0c3aee0bcc Update show_search_form 2016-08-10 23:34:15 -04:00
Mike Koch
a8f8310c63 Update common 2016-08-10 23:31:55 -04:00
Mike Koch
5e9c3a4a13 Update admin_functions 2016-08-10 23:28:52 -04:00
Mike Koch
b580995f08 Update service_messages 2016-08-10 23:25:40 -04:00
Mike Koch
55ee82d385 Update manage_knowledgebase 2016-08-10 23:23:46 -04:00
Mike Koch
1b68a892a5 Updat knowledgebase_private 2016-08-10 23:22:10 -04:00
Mike Koch
d2d913f033 Update admin index.php 2016-08-10 23:21:12 -04:00
Mike Koch
ede399c609 Update export.php 2016-08-10 23:20:05 -04:00
Mike Koch
6612be3626 Update admin_settings.php 2016-08-10 23:18:38 -04:00
Mike Koch
c755cbd061 Starting on manage users 2016-08-09 22:17:22 -04:00
Mike Koch
42bb2fc807 Search tickets now uses new UI 2016-08-09 22:05:30 -04:00
Mike Koch
5bb175933a admin_main now uses new styling 2016-08-09 12:59:22 -04:00
Mike Koch
8c01a46738 More work on ticket table 2016-08-08 22:06:29 -04:00
Mike Koch
93dac37532 Finished up search filter... I think 2016-08-08 13:10:31 -04:00
Mike Koch
601da6de92 More work on the get_tickets function 2016-08-07 22:02:23 -04:00
Mike Koch
e251d586f9 Starting to work on ticket search 2016-08-04 12:58:33 -04:00
Mike Koch
5ce782d893 Start working on refactoring ticket table logic 2016-08-02 12:37:06 -04:00
Mike Koch
f82d8e95d7 Linkify messages, remove dead code 2016-08-01 12:58:57 -04:00
Mike Koch
1e8505ee22 Finished sidebar, added system warnings to top 2016-08-01 12:53:25 -04:00
Mike Koch
98747a3c04 More UI changes 2016-07-31 22:07:40 -04:00
Mike Koch
a43e7ec479 More admin page changes 2016-07-29 22:12:14 -04:00
Mike Koch
e57f2e34c2 More progress on the new staff dashboard 2016-07-29 13:07:05 -04:00
Mike Koch
6b8fe5848d Getting started on a new backend look and feel 2016-07-28 22:29:39 -04:00
Mike Koch
2b0e8002fc Merge branch '2-6-3' into 'master'
2.6.3



See merge request !24
2016-07-25 02:07:38 +00:00
Mike Koch
56c2547659 Update build.php 2016-07-25 02:01:55 +00:00
Mike Koch
262e0b5fc7 Update installer 2016-07-24 22:00:47 -04:00
Mike Koch
85861897a5 Fix calendar reminder cron job 2016-07-24 21:58:24 -04:00
Mike Koch
64bd766249 Remove margin on blockquotes in messages 2016-07-24 21:51:01 -04:00
Mike Koch
31921ba521 #440 Notifications and autoassign are enums, not ints 2016-07-24 21:44:44 -04:00
Mike Koch
25be223030 #443 Fix typo 2016-07-24 21:39:36 -04:00
Mike Koch
0838e1de49 Fix some API doc stuff 2016-07-21 22:17:06 -04:00
Mike Koch
405b5942b6 #439 Fix events that span multiple months 2016-07-21 22:06:33 -04:00
Mike Koch
c2e511b71a Add comments to popover for staff 2016-07-17 16:49:36 -04:00
Mike Koch
4428870c4b Merge branch '2-6-2' into 'master'
2.6.2 Update

Closes #437, #436, #433.

See merge request !23
2016-07-17 20:32:14 +00:00
Mike Koch
e8e49b3d4c Update installer 2016-07-17 16:23:21 -04:00
Mike Koch
5706563879 Fixes #433 fix undefined 'as_message' 2016-07-17 16:17:46 -04:00
Mike Koch
eeaf56d3b7 Add comments to customer calendar 2016-07-17 16:13:40 -04:00
Mike Koch
da0fe09fc7 Fixes #436 Add missing columns to stage_tickets table 2016-07-17 16:02:34 -04:00
Mike Koch
e138f73ce9 Merge branch 'patch-1' into 'master'
Update array instantiation syntax to support PHP 5.3.X



See merge request !22
2016-06-26 15:25:49 +00:00
Cody Mize
cd53a5812e Update array instantiation syntax to support PHP 5.3.X 2016-06-25 21:51:42 -04:00
Mike Koch
e5e6f35e97 Update install_functions.inc.php 2016-06-21 12:30:28 +00:00
Mike Koch
6388e6e1cc Update installer 2016-06-19 22:04:49 -04:00
Mike Koch
33051e513e Add 'Message' tag next to message box 2016-06-19 21:59:17 -04:00
Mike Koch
520995111b Add FullCalendar languages, choose language based on HESK language 2016-06-19 21:44:31 -04:00
Mike Koch
22a8132953 Fixes #431 localize calendar header text 2016-06-19 21:23:19 -04:00
Mike Koch
0b1036586d Update README.md 2016-06-18 04:51:20 +00:00
Mike Koch
19e50192de Update README.md 2016-06-18 04:50:55 +00:00
Mike Koch
8a718c48f3 Update cors.php 2016-06-15 01:25:41 +00:00
Mike Koch
574e80b892 Installer improvements 2016-06-13 12:48:19 -04:00
Mike Koch
61fc65a4ac Installer UI tweak 2016-06-13 12:24:21 -04:00
Mike Koch
ecb2bf1e64 Adding a couple queries in advance for 2.7.0 2016-06-13 12:18:07 -04:00
Mike Koch
181f50ded4 Update uninstall scripts 2016-06-12 21:01:10 -04:00
Mike Koch
06be7db327 Add universal CORS restriction 2016-06-11 22:11:05 -04:00
Mike Koch
ab9281d029 Merge branch '402-localize-select-deselect-all' into '2-6-0'
Localize Select/Deselect all

Closes #402

See merge request !18
2016-06-12 01:46:52 +00:00
Mike Koch
22a6ed1820 Localize Select/Deselect all 2016-06-11 21:45:07 -04:00
Mike Koch
38aeb64407 Use red background for overdue tickets 2016-06-09 12:58:53 -04:00
Mike Koch
df57eaaa9a Testing out a red icon for overdue... not sure about it though 2016-06-07 13:11:18 -04:00
Mike Koch
e05e03ef2c Only touch the DB for mailgun if enabled 2016-06-07 12:24:36 -04:00
Mike Koch
8047920fb1 #415 Convert BIT columns to INT 2016-06-07 12:19:56 -04:00
Mike Koch
252d317e79 #414 Replace ->fetch_assoc() with hesk_dbFetchAssoc() 2016-06-07 12:16:17 -04:00
Mike Koch
8885516922 #411 Add primary key to settings table 2016-06-07 12:11:25 -04:00
Mike Koch
75ecd7d579 Better UX for max files exceeded 2016-06-06 13:03:12 -04:00
Mike Koch
5418f834fe Remove unnecessary logs 2016-06-06 12:44:35 -04:00
Mike Koch
dd5c5a90d3 Fix file upload when multiple files are selected at once 2016-06-06 12:37:59 -04:00
Mike Koch
4a86d9ddbb Convert FROM_UNIXTIME to UTC before querying 2016-06-03 11:56:03 +00:00
Mike Koch
a9a820219e #407 Fix file limits 2016-06-01 13:03:10 -04:00
Mike Koch
ed0d107712 #406 fix legend language string 2016-06-01 12:58:43 -04:00
Mike Koch
40e2b6dad3 Add legend indicating each event icon 2016-05-31 12:55:40 -04:00
Mike Koch
c5b3bc0190 Fix several PhpStorm warnings 2016-05-31 12:37:18 -04:00
Mike Koch
075fcf3125 Display notice when event is overdue 2016-05-31 12:33:42 -04:00
Mike Koch
aeb59d6722 Remove tracking ID from title, show icon instead 2016-05-30 22:05:52 -04:00
Mike Koch
cc11a481f5 More calendar fixes 2016-05-30 15:45:45 -04:00
Mike Koch
097bded91a Added owner and priority... still need to update the other pages 2016-05-29 19:05:28 -04:00
Mike Koch
e01b7457fa #379 Another tweak to the category display 2016-05-29 15:18:38 -04:00
Mike Koch
e663b9605f Get started on ticket popover. Still a couple TODO items 2016-05-29 02:03:53 -04:00
Mike Koch
0fdc62734c #379 Tweak calendar catgory display to prevent overflow issues 2016-05-29 01:13:24 -04:00
Mike Koch
f8f9372ccb #381 Make select/deselect buttons smaller 2016-05-26 12:36:09 -04:00
Mike Koch
9aebf467d0 Merge branch 'fix-manage-statuses' into '2-6-0'
Fix on creating a new status

You were unable to create a new status because the page would reload itself when the modal appeared.

The problem was that the button was triggering the post's form. Adding type="button" to the button class, it will not.

See merge request !17
2016-05-26 16:17:51 +00:00
Santiago
915d434d9c Fix on creating a new status
You were unable to create a new status because the page would reload itself when the modal appeared.

The problem was that the button was triggering the post's form. Adding type="button" to the button class, it will not.
2016-05-26 16:05:52 +00:00
Mike Koch
c5a87a84a5 Typo fix 2016-05-23 21:53:08 -04:00
Mike Koch
cc175ad376 Use hesk_date instead of NOW(), fix tickets on calendar 2016-05-23 21:49:02 -04:00
Mike Koch
1153e6f229 Fix accepted files 2016-05-23 21:49:02 -04:00
Mike Koch
c563745498 Merge branch 'add-select-deselect-all-for-calendar' into '2-6-0'
Add select/deselect all buttons for calendar categories



See merge request !16
2016-05-23 16:49:46 +00:00
Mike Koch
d334c33d31 #381 Add select/deselect all buttons for calendar categories 2016-05-23 12:47:50 -04:00
Mike Koch
9d8305442a #394 Remove alter table warning from install page 2016-05-18 12:59:48 -04:00
Mike Koch
47c7322a0c #380/#383 Respect category sort property 2016-05-18 12:58:49 -04:00
Mike Koch
60d3a17ad3 Change CSS selector to prevent sttyling issues 2016-05-14 22:15:34 -04:00
Mike Koch
dc1e5e490f Fix overflowing image on attachment viewer 2016-05-14 21:59:14 -04:00
Mike Koch
4a9e613f0a Fix dropzone layout on notes 2016-05-14 21:54:15 -04:00
Mike Koch
70d622dc0e Fix double file-submission 2016-05-12 21:44:06 -04:00
Mike Koch
bf2b875b80 Fix markup for new_ticket 2016-05-11 14:41:33 -04:00
Mike Koch
d4cad22526 Make sure & doesn't become &amp; when editing a category 2016-05-10 13:02:43 -04:00
Mike Koch
441a8e537e Merge branch '375-improve-file-upload' into '2-6-0'
Improve File Uploadsd

Closes #375

See merge request !15
2016-05-10 16:55:32 +00:00
Mike Koch
41bbeaf97f Use the new button layout on all dropzones 2016-05-10 12:53:25 -04:00
Mike Koch
be6659b183 Disable button when max attachments reached 2016-05-07 21:58:41 -04:00
Mike Koch
18ffc0b657 Properly overflow text if the name is too long 2016-05-06 22:34:01 -04:00
Mike Koch
fcf54ac9ca Several attachment changes
- Use an "Add File" button at the bottom of the dropzone instead of clicking directly on the dropzone
- Adjust layout to hopefully fix issue with long file names (haven't tested yet)
- Show percentage in percentage bar
- Fix issue where percentage bar would still animate even after upload finished
2016-05-06 22:22:41 -04:00
Mike Koch
243d72d602 Disable submit buttons until uploads complete 2016-05-06 12:41:49 -04:00
Mike Koch
f9ec18ce5f Fix drag-and-drop for attachments 2016-05-06 12:28:05 -04:00
Mike Koch
580a662ce0 Fix gray line when customer didn't reply appears 2016-05-05 20:31:45 -04:00
Mike Koch
946ebfdaee Small JS and calendar fix 2016-05-05 12:59:50 -04:00
Mike Koch
4136013097 Update installer' 2016-05-05 12:13:33 -04:00
Mike Koch
ca25034f37 Make the public API opt-in since the settings page is hidden 2016-05-05 12:07:35 -04:00
Mike Koch
65452902bb Merge remote-tracking branch 'origin/master' into 2-6-0
Conflicts:
	admin/manage_knowledgebase.php
	inc/header.inc.php
	inc/headerAdmin.inc.php
	install/mods-for-hesk/sql/installSql.php
2016-05-04 23:42:53 -04:00
Mike Koch
7628820b94 Merge branch 'prelease-changes' into '2-6-0'
Prelease changes



See merge request !14
2016-05-05 01:44:02 +00:00
Mike Koch
760e71f35c Remove useless .val 2016-05-04 21:42:32 -04:00
Mike Koch
44236101e1 Add some tooltips, fix color on textbox 2016-05-04 21:39:41 -04:00
Mike Koch
bedc61c74f Only send overdue notices for open tickets 2016-05-04 20:58:16 -04:00
Mike Koch
514dae4c57 Merge branch '355-api-security' into '2-6-0'
Improve API Security

Closes #355

See merge request !13
2016-05-02 21:17:03 +00:00
Mike Koch
c77e53fa9e Secure the internal API 2016-05-02 17:14:18 -04:00
Mike Koch
b9faaf2325 Finish up securing API endpoints 2016-05-02 16:48:39 -04:00
Mike Koch
cb6103319e Secure ticket endpoint, add new properties to JSON 2016-05-01 22:18:35 -04:00
Mike Koch
26007af59f Merge branch '367-add-colorpicker' into '2-6-0'
Add Colorpicker

Closes #367

See merge request !12
2016-05-01 01:28:41 +00:00
Mike Koch
b224181067 Contentify non-translated strings 2016-04-30 21:26:14 -04:00
Mike Koch
51720f17a8 Add colorpicker for categories and statuses 2016-04-30 21:17:30 -04:00
Mike Koch
0dad89d7b5 Merge branch '366-add-semicolor-to-email-separator' into '2-6-0'
Replace semicolons with commas for multiple emails

Closes #366

See merge request !11
2016-04-30 04:44:18 +00:00
Mike Koch
047f36c92c Replace semicolons with commas for multiple emails 2016-04-30 00:42:56 -04:00
Mike Koch
adbb1b9ee7 Merge branch 'bug-fix-rich-text-message-query-param' into '2-6-0'
Fix Message Input When Rich Text is Enabled



See merge request !10
2016-04-30 04:28:40 +00:00
Mike Koch
00e40bd02d #356 Add message to rich text editor when passed in via session or get 2016-04-30 00:27:24 -04:00
Mike Koch
21561f5a4f Merge branch '365-missing-bottom-border' into '2-6-0'
Fix missing bottom border

Closes #365

See merge request !9
2016-04-29 15:37:02 +00:00
Mike Koch
1e485a1585 Remove commented out code 2016-04-27 21:59:50 -04:00
Mike Koch
a9fefd393d Fix missing bottom border on ticket replies 2016-04-27 21:59:29 -04:00
Mike Koch
603d8233a7 Merge branch '370-fix-date-time-on-ticket' into '2-6-0'
Fix time for created/updated on ticket header

Closes #370

See merge request !8
2016-04-28 01:52:43 +00:00
Mike Koch
5a8db97739 Fix time for created/updated on ticket header 2016-04-27 21:48:53 -04:00
Mike Koch
7f131eaca7 Merge branch '352-bug-fix-canned-response-replaces-message' into '2-6-0'
Fix canned responses 'Add to Bottom'

Closes #352

See merge request !7
2016-04-28 01:30:53 +00:00
Mike Koch
ee87ec50e0 Fix canned responses 'Add to Bottom' 2016-04-27 21:23:25 -04:00
Mike Koch
aa65ca99dd Merge branch '368-fix-status-on-piping' into '2-6-0'
Fix Status on Piping

Closes #368

See merge request !6
2016-04-27 01:57:46 +00:00
Mike Koch
e9dfaa3460 Add blank due date when piping in a ticket 2016-04-26 21:56:30 -04:00
Mike Koch
32bcb9ddfe I think this should work, still needto test 2016-04-26 13:41:09 -04:00
Mike Koch
7f1fb6dbb4 Merge branch '361-fix-install-for-mysql-5.7' into '2-6-0'
Remove invalid keyword in MySQL 5.7

Closes #361

See merge request !5
2016-04-26 17:20:41 +00:00
Mike Koch
d5c4b39790 Remove invalid keyword in MySQL 5.7 2016-04-26 13:19:22 -04:00
Mike Koch
512227697d Merge branch '362-fix-unsecure-content-over-https' into '2-6-0'
Return map tiles over https

Closes #362

See merge request !4
2016-04-26 17:17:00 +00:00
Mike Koch
bdbf5c9e49 #362 Return map tiles over https 2016-04-26 13:14:55 -04:00
Mike Koch
f03b532dee Merge branch '363-bug-fix-email-validation' into '2-6-0'
Fix email validation on Banned Emails

Closes #363

See merge request !3
2016-04-26 16:51:45 +00:00
Mike Koch
825cc9e644 Closes #363 fix email validation 2016-04-26 12:49:12 -04:00
Mike Koch
78b1c9933b Merge branch 'calendar-planning' into '2-6-0'
Calendar planning

Adds the calendar planning module to MFH.

See merge request !1
2016-04-26 16:43:22 +00:00
Mike Koch
99ba705338 Fix syntax error 2016-04-26 12:40:17 -04:00
Mike Koch
471110f312 Use in_array instead of strpos 2016-04-26 12:39:43 -04:00
Mike Koch
50e4861d39 Some calendar fixes 2016-04-26 08:59:54 -04:00
Mike Koch
a801a64f93 Calendar is finished... I think. 2016-04-25 21:56:52 -04:00
Mike Koch
7f4f5fff23 Add saving of settings 2016-04-25 14:00:52 -04:00
Mike Koch
1d079a5336 Start working on settings 2016-04-24 22:15:07 -04:00
Mike Koch
a860ba5d40 Add due date on create ticket screen 2016-04-24 15:26:38 -04:00
Mike Koch
3707fc52b5 Reset email flag when the due date changes 2016-04-23 22:18:00 -04:00
Mike Koch
23040e1745 Add null check for ownerless tickets 2016-04-23 22:08:38 -04:00
Mike Koch
a47068c83b Add support for emails for users who want emails sent for overdue tickets not assigned to them 2016-04-23 22:07:51 -04:00
Mike Koch
dd0481b452 Add notification for overdue tickets not assigned to me 2016-04-21 22:05:45 -04:00
Mike Koch
9c93b739b3 Add cron database functions file 2016-04-20 21:44:13 -04:00
Mike Koch
263a5804c8 Basic overdue ticket alerts working 2016-04-20 18:38:52 -04:00
Mike Koch
38dd4ee7c9 Update README 2016-04-18 21:14:45 -04:00
Mike Koch
62d04bf6e6 Fix install scripts 2016-04-18 19:37:53 -04:00
Mike Koch
ba8a89a3c3 Update installer 2016-04-18 19:35:14 -04:00
Mike Koch
c3bb97eead Merge branch 'hesk-2-6-7-update' into 'master'
Hesk 2.6.7 update



See merge request !2
2016-04-18 23:15:24 +00:00
Mike Koch
f564bd47cc Merge remote-tracking branch 'origin/master' into hesk-2-6-7-update 2016-04-18 19:14:37 -04:00
Mike Koch
7cbd197284 Update headers 2016-04-18 18:57:07 -04:00
Mike Koch
7ef6d6215a Update ticket 2016-04-18 18:54:37 -04:00
Mike Koch
ea41b8e747 Update reply_ticket 2016-04-18 18:41:09 -04:00
Mike Koch
1e894e904e Update print 2016-04-18 18:38:19 -04:00
Mike Koch
451c3dfbf5 Update common 2016-04-18 18:34:50 -04:00
Mike Koch
f8fa90d85b Update change_status 2016-04-18 18:34:46 -04:00
Mike Koch
f7bd3374aa Update mail.php 2016-04-18 18:27:27 -04:00
Mike Koch
a989911864 Add readonly option and security group 2016-04-15 21:39:39 -04:00
Mike Koch
fe78f743d1 Moved all content strings into the language file 2016-04-15 12:50:56 -04:00
Mike Koch
472911d05a Contentified JS language 2016-04-13 22:00:24 -04:00
Mike Koch
a4a92882b1 Some due date fixes and language file transfers 2016-04-13 21:43:23 -04:00
Mike Koch
2355d0b883 Add sample language field to use for JS language keys 2016-04-12 13:29:39 -04:00
Mike Koch
e252038b55 Fix saving ticket due dates. Still need to contentify 2016-04-12 13:27:03 -04:00
Mike Koch
1d4b6ee6f7 Contentified majority of the calendar pages. Need to do JS though 2016-03-31 09:57:17 -04:00
Mike Koch
8756200fee Calendar cron job now working 2016-03-31 09:00:39 -04:00
Mike Koch
033dd8e4fb Getting started on the email stuff 2016-03-30 22:02:16 -04:00
Mike Koch
b4e238ee41 Update jGrowl 2016-03-30 20:26:35 -04:00
Mike Koch
2aad4b8826 Respond to resizing events on the week/day view 2016-03-30 15:16:18 -04:00
Mike Koch
0b24713a60 Fix reminder dropdowns when editing 2016-03-30 15:12:14 -04:00
Mike Koch
c35e0159db Fix updating reminders 2016-03-29 22:12:39 -04:00
Mike Koch
29ff273d78 SQL now properly works 2016-03-29 21:58:33 -04:00
Mike Koch
2863fb82e2 Remove reminder_time column, as the cron job uses SQL to calculate the time 2016-03-29 13:44:57 -04:00
Mike Koch
2006c3ca70 Getting started on the cron job 2016-03-28 21:55:34 -04:00
Mike Koch
7331396776 Add a couple columns to the install SQL 2016-03-28 21:55:34 -04:00
Mike Koch
7f07e73192 Fix background gray count conditional 2016-03-16 03:16:21 +00:00
Mike Koch
7155e18903 Fix SQL for public end 2016-03-10 22:04:08 -05:00
Mike Koch
5ada01e09d Return reminder information and display on edit modal 2016-03-10 21:56:52 -05:00
Mike Koch
fe42a83100 Remove console.log 2016-03-09 22:01:10 -05:00
Mike Koch
e7107996eb #189 Display public events on the calendar 2016-03-09 21:59:24 -05:00
Mike Koch
8e51429dce #189 Start working on customer-side calendar 2016-03-08 22:20:06 -05:00
Mike Koch
914fb0ff9c #189 Allow categories to be both tickets/events, events, or tickets 2016-03-06 22:01:22 -05:00
Mike Koch
1cdcc34d71 Add 'usage' for categories 2016-03-03 22:12:08 -05:00
Mike Koch
80687f3bed Reset category and reminder values when showing the create modal 2016-03-03 00:05:40 -05:00
Mike Koch
ce46f3d4a1 #189 Add create event button to calendar header 2016-03-02 21:59:39 -05:00
Mike Koch
7639bf3dd7 #189 Store user's id when creating reminder 2016-02-22 19:07:10 -05:00
Mike Koch
31a69cebe9 Getting started on reminders 2016-02-20 22:22:27 -05:00
Mike Koch
1df4e7775a A bunch of calendar fixes 2016-02-18 13:28:00 -05:00
Mike Koch
4a09d508b8 Add ability to show/hide categories on the calendar view 2016-02-17 22:03:33 -05:00
Mike Koch
33cb1723ee Display category colors on calendar 2016-02-15 22:14:24 -05:00
Mike Koch
d74b07b455 Add category colors, overall category UX improvements 2016-02-15 21:11:50 -05:00
Mike Koch
0743f63982 more work on category colors 2016-02-14 22:25:55 -05:00
Mike Koch
2fa0858fab Add 'Click to select' on each dropdown. Still need to add validation 2016-02-13 23:29:58 -05:00
Mike Koch
1b7cf24258 Escape the start/end times instead of intval
On 32-bit PHP installations, the start/end times will exceed the max size
of a 32-bit integer, causing the query to always return 0 results.
2016-02-13 23:19:33 -05:00
Mike Koch
5708c63b75 Add category support. Need to honoror 'click to select' though 2016-02-13 22:11:20 -05:00
Mike Koch
b8aa98e98b Update README.me 2016-02-08 18:44:36 +00:00
Mike Koch
427e98eb94 Display overdue tickets in red 2016-02-04 13:44:13 -05:00
Mike Koch
8b0afb84c9 Display tooltip to create a new event after 250ms 2016-02-04 13:35:44 -05:00
Mike Koch
7567fc8ff5 Display popover when hovering over an event 2016-02-04 13:22:43 -05:00
Mike Koch
d8acf87d48 Add jump by year, start working on popovers 2016-02-04 09:09:00 -05:00
Mike Koch
cd0bd1cc39 Merge pull request #473 from mike-koch/mike-koch-patch-1
Fix installer
2016-02-02 21:13:39 -05:00
Mike Koch
1afa0ad639 Fix installer 2016-02-02 21:13:15 -05:00
Mike Koch
3a8e979e7e Merge pull request #472 from mike-koch/update-to-hesk-2-6-6
Update to HESK 2.6.6
2016-02-02 13:28:42 -05:00
Mike Koch
f2ba296eb6 #471 Update installer 2016-02-02 13:22:08 -05:00
Mike Koch
569a1ab6af #471 Update headers to 2.6.6 for all other files 2016-02-02 13:09:41 -05:00
Mike Koch
4500313fd5 #471 Update common to 2.6.6 2016-02-02 13:06:48 -05:00
Mike Koch
c54aeb6fa0 #471 Update download_attachment for 2.6.6 2016-02-02 13:03:02 -05:00
Mike Koch
a4de4886d9 #471 Update knowledgebase for 2.6.6 2016-02-02 13:01:51 -05:00
Mike Koch
e771090e51 Add button to create a ticket based on calendar details 2016-01-28 21:42:56 -05:00
Mike Koch
9138a32533 Add button to create a ticket based on this event 2016-01-28 13:40:27 -05:00
Mike Koch
1c58747db7 Removed the "create ticket on" options
It may cause some weird issues when creating a ticket (who created it, message, custom fields, etc), so pulling this out for now. There will be a way to create a ticket from an already created event via a query string that is passed to the admin_new_ticket page.
2016-01-28 13:22:05 -05:00
Mike Koch
0fecd860e2 Use URL of caller instead of just 'Internal API' 2016-01-28 12:32:06 -05:00
Mike Koch
eed4e4392a Display and update due date from ticket page 2016-01-28 09:07:08 -05:00
Mike Koch
d4840a297a Ticket due dates can be updated via the calendar 2016-01-26 22:21:19 -05:00
Mike Koch
03c47c1ab7 Show tickets with their due dates 2016-01-26 21:55:59 -05:00
Mike Koch
b4bb77f2aa Add due date column to tickets table 2016-01-26 13:28:07 -05:00
Mike Koch
ff5d4a6153 CRUD Operations are complete 2016-01-26 13:13:08 -05:00
Mike Koch
98984ede80 Utilize drag-and-drop of events 2016-01-26 10:54:15 -05:00
Mike Koch
688d330268 Events can now be deleted 2016-01-26 10:26:56 -05:00
Mike Koch
4c5d9416cb Edit modal working. Fixed some other issues 2016-01-26 10:09:46 -05:00
Mike Koch
1173b23838 Show events on calendar, fix all day issue 2016-01-26 08:59:33 -05:00
Mike Koch
1984f73cf2 Feedback, better SQL 2016-01-21 22:19:14 -05:00
Mike Koch
a2c6f10ca8 Events are now displayed on calendar after creation 2016-01-21 13:34:14 -05:00
Mike Koch
6650650e51 Events can now be saved 2016-01-21 13:25:44 -05:00
Mike Koch
6677dce6fd AJAX call is working. haven't actually saved anything yet though 2016-01-19 22:13:13 -05:00
Mike Koch
0973ed421d more changes 2016-01-19 13:19:12 -05:00
Mike Koch
d0d792af3b Add assign to dropdown 2016-01-19 08:49:12 -05:00
Mike Koch
1f866a9cc1 Add create ticket date and tooltips 2016-01-18 22:16:44 -05:00
Mike Koch
6a2ee9cc48 Set some values based on current calendar view, reset modal on click 2016-01-18 12:58:57 -05:00
Mike Koch
f503ec5c0c Remove some default values 2016-01-18 12:58:28 -05:00
Mike Koch
5f2d7c1a66 Some more calendar stuff 2016-01-17 21:59:47 -05:00
Mike Koch
f706333d23 Change default donetext 2016-01-17 11:21:04 -05:00
Mike Koch
6cbe3564a1 Add clockpicker dependency for times 2016-01-16 22:32:58 -05:00
Mike Koch
1cdc673d56 Switching back to DATETIME 2016-01-16 20:04:12 -05:00
Mike Koch
b9a1b7fe6b Add ability to retrieve events. Also change dates to epoch format 2016-01-13 22:08:08 -05:00
Mike Koch
f03d4a1524 Merge pull request #463 from mkoch227/update-status-badge
Update status badge
2016-01-13 18:06:34 -05:00
Mike Koch
d917ef1d92 Update status badge
Switch from stillmaintained.com to a generic shields.io badge until stillmaintained.com returns.
2016-01-13 18:06:24 -05:00
Mike Koch
816a4413e1 #201 A basic calendar is now displayed
Still need to add a cluster of handlers to handle adding events, saving, loading, etc.
2016-01-12 22:06:34 -05:00
Mike Koch
9096e0765e #201 Add necessary dependencies 2016-01-12 21:45:34 -05:00
Mike Koch
5dcce6436e #201 Add comment field 2016-01-12 21:36:36 -05:00
Mike Koch
57593a36db #201 Add table for calendar events 2016-01-12 21:31:59 -05:00
Mike Koch
67a6819cd2 Merge pull request #461 from mkoch227/2-5-3
2.5.3 Update
2016-01-09 21:41:31 -05:00
Mike Koch
4d4c29e0ae Update installer 2016-01-09 21:38:25 -05:00
Mike Koch
df80fb9037 Merge pull request #460 from mkoch227/bug-fix-notify-skip-spam
Fix Notify New Spam Setting
2016-01-09 21:25:16 -05:00
Mike Koch
ae0db735a0 Fixes #456 Use the correct checkbox name 2016-01-09 21:23:50 -05:00
Mike Koch
8e9e46ec47 Fix view ticket db issue 2016-01-09 21:01:20 -05:00
Mike Koch
a53729f2b9 Merge pull request #459 from mkoch227/bug-fix-knowledgebase-in-maintenance
Bug fix knowledgebase in maintenance
2016-01-09 20:56:39 -05:00
Mike Koch
f739780f9e Fixes #457 Move around some database stuff to fix the knowledgebase error 2016-01-09 20:55:17 -05:00
Mike Koch
1d961132c3 Merge pull request #455 from mkoch227/attachments-phase-two
Attachments phase two
2015-12-28 22:08:01 -05:00
Mike Koch
1eeb477577 Enforce file limits 2015-12-28 22:05:20 -05:00
Mike Koch
3ea316388c Knowledgebase attachment uploading now working 2015-12-28 21:42:56 -05:00
Mike Koch
c99144ec14 Got one of the KB file drops working 2015-12-28 13:06:31 -05:00
Mike Koch
ecf0d1a7dc Drag and drop attachments now working for admin notes and admin replies 2015-12-28 12:47:51 -05:00
Mike Koch
07acdaccb5 Add drag and drop for admin ticket, fix URL for other pages 2015-12-27 22:20:25 -05:00
Mike Koch
71fc6befa1 Reply ticket now uses new attachment holder 2015-12-27 20:53:41 -05:00
Mike Koch
07b82c4d93 New attachment uploader working for customer ticket create 2015-12-27 16:58:33 -05:00
Mike Koch
1bdd658a7d Attachments can be removed via AJAX 2015-12-27 14:57:51 -05:00
Mike Koch
ff4a9af284 Merge pull request #453 from mkoch227/bug-fix-signature-length
Fix signature limit
2015-12-23 13:04:06 -05:00
Mike Koch
4352097882 Signatures can be up to 1000 characters long 2015-12-23 08:10:22 -05:00
Mike Koch
8d581daf80 Signatures can be up to 1000 characters 2015-12-23 08:08:38 -05:00
Mike Koch
056e85d9ea Some more work on attachments 2015-12-22 22:20:30 -05:00
Mike Koch
87f6093138 Add database ID to the file object 2015-12-21 22:02:43 -05:00
Mike Koch
b133a3e31e Can now attach files on the create ticket page via dropzone 2015-12-21 13:11:12 -05:00
Mike Koch
1338bb0167 More work on attachments 2015-12-20 22:19:25 -05:00
Mike Koch
25bb024f2c Dropzone is somewhat working, need to actually try it out 2015-12-19 23:00:00 -05:00
Mike Koch
87f8572f12 Making some progress... not much though. 2015-12-17 13:07:40 -05:00
Mike Koch
c4bc0df5c0 Add dropzone.js dependency 2015-12-17 12:16:59 -05:00
Mike Koch
8b3cc84a4d Merge pull request #451 from mkoch227/bug-fix-form-validate-with-recaptcha
Fix validator with reCAPTCHA
2015-12-16 19:34:55 -05:00
Mike Koch
0e74dfb16d Fixes #450 Keep <div>s in their proper groups 2015-12-16 17:21:43 -05:00
Mike Koch
8ec86ffb9c Merge pull request #448 from mkoch227/add-logging
Basic Logging Support
2015-12-11 21:35:48 -05:00
Mike Koch
a821affe1f Merge pull request #447 from mkoch227/api
API Phase One
2015-12-11 21:35:34 -05:00
Mike Koch
26e750959a Some improvments 2015-12-10 22:15:32 -05:00
Mike Koch
56cf706458 Contentify the page 2015-12-08 22:12:54 -05:00
Mike Koch
9d2fd5f4d0 Some more message log stuff. Almost done. 2015-12-08 18:25:08 -05:00
Mike Koch
eda289931f Search is now working 2015-12-03 21:06:24 -05:00
Mike Koch
0c841ce60b Committing in a bad state...search is half-working 2015-11-30 13:04:38 -05:00
Mike Koch
1f397af222 Basic initial load is working 2015-11-29 22:05:07 -05:00
Mike Koch
5255ef0425 Merge remote-tracking branch 'origin/api' into add-logging 2015-11-29 21:23:17 -05:00
Mike Koch
3c3eb35432 Getting started on message logs 2015-11-29 21:19:50 -05:00
Mike Koch
e5347b145e #329 Update installer for logging table 2015-11-29 20:12:12 -05:00
Mike Koch
641348d757 Converted everything to camelCase se and some other improvements 2015-11-29 15:39:38 -05:00
Mike Koch
b94ea93991 Update some documentation 2015-11-29 11:50:47 -05:00
Mike Koch
22372ca14d Add GET /ticket 2015-11-29 11:45:23 -05:00
Mike Koch
fadcb42a0c #439 Add /admin/user endpoint 2015-11-29 01:27:45 -05:00
Mike Koch
41b208ca8d #444 Remove unnecessary properties, rename some fields 2015-11-29 00:51:30 -05:00
Mike Koch
eb62616247 More API improvements 2015-11-28 22:25:51 -05:00
Mike Koch
b7ff286c43 More API fixes 2015-11-27 22:19:39 -05:00
Mike Koch
16d365bcad Some improvements on category, more API documentation 2015-11-27 22:12:20 -05:00
Mike Koch
4d75b39766 Fix category endpoint, start work on apiDoc 2015-11-26 23:07:18 -05:00
Mike Koch
1d5585adc7 Merge pull request #443 from mkoch227/up
Update CONTRIBUTING.md
2015-11-24 16:53:15 -05:00
Mike Koch
7c13c5d7b9 Update CONTRIBUTING.md 2015-11-24 16:53:07 -05:00
Mike Koch
7537f23bc3 Update CONTRIBUTING.md 2015-11-24 16:51:24 -05:00
Mike Koch
0c6557a1b3 #438 Create endpoint for priority 2015-11-23 22:01:23 -05:00
Mike Koch
209e039cdb Add security to additional endpoints 2015-11-23 12:38:53 -05:00
Mike Koch
ab0082c735 more security stuff 2015-11-22 22:21:42 -05:00
Mike Koch
0db1f88b7f More work on security 2015-11-20 22:05:44 -05:00
Mike Koch
5b098c8fca Tokens can now be reset 2015-11-19 21:14:15 -05:00
Mike Koch
9bb2a3fd3d Tokens can now be generated 2015-11-19 20:37:49 -05:00
Mike Koch
d23b80a37c more user security stuff 2015-11-18 22:04:34 -05:00
Mike Koch
97d7f2d849 Start working on token services 2015-11-17 22:14:34 -05:00
Mike Koch
f84207cc44 Start working on auth token management 2015-11-17 21:56:33 -05:00
Mike Koch
b289325276 Can now enable/disable public API 2015-11-17 21:27:57 -05:00
Mike Koch
82877aff8b #414 Start working on the API settings page 2015-11-16 22:18:38 -05:00
Mike Koch
0c0596fc2d Merge pull request #436 from mkoch227/bug-fix-save-mailgun-settings
Save mailgun settings
2015-11-16 12:46:59 -05:00
Mike Koch
f179d6c1e2 #435 Save mailgun settings 2015-11-16 12:46:20 -05:00
Mike Koch
50dae5f873 Merge pull request #434 from mkoch227/bug-fix-status-on-email
Update ticket status before sending email
2015-11-16 12:30:18 -05:00
Mike Koch
276a0906bd #420 Update ticket status before sending email 2015-11-16 12:29:35 -05:00
Mike Koch
f733351a04 Merge pull request #433 from mkoch227/bug-fix-query-string-custom-fields
Fix custom field query string parsing on admin side
2015-11-16 12:17:18 -05:00
Mike Koch
bb653f0131 #424 Fix custom field query string parsing on admin side 2015-11-16 12:16:41 -05:00
Mike Koch
b57fd89b47 Merge pull request #432 from mkoch227/bug-fix-language-lost-on-edit
Update HTML property when editing ticket/reply
2015-11-15 15:49:36 -05:00
Mike Koch
acf6ff3123 Fixes #417 Update HTML property when editing ticket/reply 2015-11-15 15:48:55 -05:00
Mike Koch
f14e4d55d2 Merge pull request #431 from mkoch227/bug-fix-language-lost-on-edit
Retain language when editing ticket
2015-11-15 15:26:06 -05:00
Mike Koch
1f5827d5a1 Fixes #415 Retain language when editing ticket 2015-11-15 15:25:36 -05:00
Mike Koch
0dd3d05447 Merge pull request #429 from mkoch227/bug-fix-delete-banned-emails
Fix banned emails
2015-11-15 15:06:24 -05:00
Mike Koch
45caec4de8 Fixes #416 fix markup for banned emails 2015-11-15 15:05:23 -05:00
Mike Koch
0cb8d6cf7a Merge pull request #428 from mkoch227/bug-fix-cant-reset-password
Fix Password Reset Page
2015-11-15 12:29:09 -05:00
Mike Koch
4a87f9e74b Fixes #423 remove extra call to load DB functions 2015-11-15 12:27:28 -05:00
Mike Koch
222a964d38 Merge pull request #426 from mkoch227/kb-fallback-to-old-attachments-folder
Fallback to ticket attachments folder for legacy KB attachments
2015-11-15 12:13:29 -05:00
Mike Koch
430087e533 #405 Fallback to ticket attachments folder for legacy KB attachments 2015-11-15 12:05:36 -05:00
Mike Koch
b8c575068a Merge pull request #422 from mkoch227/bug-fix-footer-forgot-password
Fixes #419 Fix footer on lockout screen
2015-11-08 17:30:17 -05:00
Mike Koch
30562fbc87 Fixes #419 Fix footer on lockout screen 2015-11-08 17:29:43 -05:00
Mike Koch
4fa94bec1a Add status API 2015-11-06 22:23:28 -05:00
Mike Koch
0a3d50009a Add get ticket by tracking ID 2015-11-06 21:55:06 -05:00
Mike Koch
40d8b2b4a4 Improve canned responses API 2015-11-05 22:02:49 -05:00
Mike Koch
3129adda88 Improve ticket template API 2015-11-05 22:02:07 -05:00
Mike Koch
ff4c3bfc99 Improve ticket API 2015-11-05 22:01:14 -05:00
Mike Koch
93f98484d9 #412 Add /admin/category 2015-11-05 21:55:23 -05:00
Mike Koch
b6a6a4186b Relocate some APIs, start on category API 2015-11-02 22:13:37 -05:00
Mike Koch
2d70f30256 Remove unnecessary else block 2015-11-02 13:00:34 -05:00
Mike Koch
490dcdb764 Ticket API and return 404 if no results 2015-11-02 12:55:32 -05:00
Mike Koch
79d4574e19 Everything is only needed once 2015-11-02 12:48:59 -05:00
Mike Koch
6530882be7 Some extraction of code into DAOs 2015-11-02 12:45:34 -05:00
Mike Koch
e4763b3e0b Use output function to handle headers and json encoding 2015-11-01 22:08:27 -05:00
Mike Koch
6150f113c9 Rename folder 2015-11-01 14:41:06 -05:00
Mike Koch
5851c4d7f2 Allow retrieval of all canned responses / ticket tpls 2015-11-01 14:20:19 -05:00
Mike Koch
99193274df Add ticket templates, make some tweaks to canned endpoint 2015-11-01 14:17:02 -05:00
Mike Koch
8985413901 #407 Add endpoint for canned responses 2015-11-01 11:58:30 -05:00
Mike Koch
0862b9376f Add application/json headers for errors 2015-11-01 11:58:14 -05:00
Mike Koch
9362a198eb #365 Get started on api 2015-10-31 21:01:48 -04:00
Mike Koch
c43fbcf46b Merge branch 'master' into web-services 2015-10-31 20:59:24 -04:00
Mike Koch
06b9c1826a Merge pull request #406 from mkoch227/bug-fix-kb-folder-ignored
Fixes KB Attachments
2015-10-31 20:53:12 -04:00
Mike Koch
ee9718f44e Fixes #405 Retrieve settings at global level 2015-10-31 20:50:24 -04:00
Mike Koch
d6956c9e06 Merge pull request #404 from mkoch227/2-5-2
2.5.2 Update
2015-10-29 23:15:30 -04:00
Mike Koch
726ec1f8d6 Change version number 2015-10-29 23:11:08 -04:00
Mike Koch
68cb0114dc Update installer 2015-10-29 21:49:13 -04:00
Mike Koch
d1d09c502e Merge pull request #403 from mkoch227/2-6-0
Changes for 2.5.2
2015-10-29 14:19:30 -04:00
Mike Koch
b0f031f716 Merge pull request #402 from mkoch227/bug-fix-parse-date-on-export
#398 Parse date custom fields
2015-10-29 14:18:26 -04:00
Mike Koch
2f301a1cb3 #398 Parse date custom fields 2015-10-29 14:18:05 -04:00
Mike Koch
77d425ee1a Merge pull request #401 from mkoch227/fix-custom-field-requirements
Fix header warning
2015-10-29 14:09:05 -04:00
Mike Koch
2dd27fefe1 Fix header warning 2015-10-29 14:08:35 -04:00
Mike Koch
de044dbdc3 Merge pull request #400 from mkoch227/fix-custom-field-requirements
Fix custom field requirements
2015-10-29 13:36:12 -04:00
Mike Koch
b58bc19286 Validate anti-spam question 2015-10-29 13:35:05 -04:00
Mike Koch
967df9dbd4 #395 Fix custom field requirements 2015-10-29 13:28:50 -04:00
Mike Koch
570d33bf40 Merge pull request #397 from mkoch227/bug-fix-custom-field-alignment
Fix some custom field alignment issues on customer interface
2015-10-29 10:40:17 -04:00
Mike Koch
d7fdca4274 #396 Fix some custom field alignment issues on customer interface 2015-10-29 10:36:10 -04:00
Mike Koch
ab3de941c9 Merge pull request #394 from mkoch227/make-parent-child-linked
Parent/Child tickets are now Linked tickets
2015-10-28 22:02:13 -04:00
Mike Koch
7b38fe3c10 #378 Parent/Child tickets are now Linked tickets 2015-10-28 22:01:34 -04:00
Mike Koch
4ffa0d97b6 Merge branch 'dropdown-for-tools-menu' into 2-6-0
# Conflicts:
#	inc/show_admin_nav.inc.php
2015-10-27 22:25:11 -04:00
Mike Koch
71a38e1156 #390 Add dropdown for tools 2015-10-27 22:15:13 -04:00
Mike Koch
2be13e37ad Merge pull request #392 from mkoch227/add-active-for-navbar-items
Indicate active page on navbar
2015-10-27 20:40:55 -04:00
Mike Koch
eca1dfc0b3 #392 Add constants for all items for admin nav 2015-10-27 18:37:58 -04:00
Mike Koch
7bf2c4c33b #391 Start working on active items on the admin nav 2015-10-27 13:45:42 -04:00
Mike Koch
9a8da11a8f #391 Add .active to customer-side nav items 2015-10-27 13:26:13 -04:00
Mike Koch
471f7fbd17 Update installer 2015-10-23 00:19:12 -04:00
Mike Koch
ae0cec9c10 Merge pull request #384 from mkoch227/bug-fix-screen-res
Closes #383 Fix screen res on index page
2015-10-23 00:12:13 -04:00
Mike Koch
4a1cd39e11 Merge pull request #385 from mkoch227/bug-fix-mfh-settings-on-pipe
Fix HTML emails when piping
2015-10-23 00:11:51 -04:00
Mike Koch
8166a188bb Merge pull request #387 from mkoch227/bug-fix-no-setting-email-validate
Move db connection in verify email
2015-10-23 00:11:36 -04:00
Mike Koch
16aef469a9 Merge pull request #389 from mkoch227/bug-fix-encoded-characters
Properly insert ticket templates and canned responses
2015-10-23 00:11:24 -04:00
Mike Koch
0cc65135e3 Fix issue where textarea wouldn't update after validator 2015-10-23 00:10:36 -04:00
Mike Koch
7db763c1ee Closes #388 Properly insert ticket templates and canned responses when HTML is off 2015-10-22 22:06:24 -04:00
Mike Koch
9f63c22ea8 Closes #386 Move db connection in verify email 2015-10-22 15:49:56 -04:00
Mike Koch
4f23aa0b95 Some more screen res fixes 2015-10-22 13:26:36 -04:00
Mike Koch
accd91fa3a Closes #382 Move to a wider scope 2015-10-22 13:17:04 -04:00
Mike Koch
a21129a11d Closes #383 Fix screen res on index page 2015-10-21 22:01:30 -04:00
Mike Koch
d66d1abef9 Fix reCAPTCHA for some users 2015-10-19 23:33:15 -04:00
Mike Koch
7fa8a83015 Update README 2015-10-19 23:21:58 -04:00
Mike Koch
a28f017848 Merge pull request #379 from mkoch227/2-5-0
2.5.0 Update
2015-10-19 22:09:09 -04:00
Mike Koch
6f26a3c4a6 Merge pull request #381 from mkoch227/bug-fix-ticket-to-tmpvar
Switch from $ticket to $tmpvar
2015-10-19 20:53:07 -04:00
Mike Koch
25cedadb9b Switch from $ticket to $tmpvar 2015-10-19 14:17:17 -04:00
Mike Koch
dd0ba01fb7 Provide basic settings in case settings don't exist yet 2015-10-19 00:23:02 -04:00
Mike Koch
a42ae59d22 Always push new settings to table 2015-10-19 00:15:55 -04:00
Mike Koch
23b9a537c8 Fix references to CSS 2015-10-19 00:10:02 -04:00
Mike Koch
2570061c77 More installer fixes 2015-10-19 00:08:53 -04:00
Mike Koch
06fa58bb83 Cornucopia of installer fixes 2015-10-18 23:55:29 -04:00
Mike Koch
727f9432e9 Fix html2text for MSG_NO_ATTACHMENT and signatures w/special chars 2015-10-18 22:09:05 -04:00
Mike Koch
c5cc934483 Fix saving user agent setting 2015-10-18 21:36:55 -04:00
Mike Koch
e1383c65d8 Update installer 2015-10-18 16:37:55 -04:00
Mike Koch
781bd40a20 Merge pull request #376 from mkoch227/language-file-consistency
Improve Language File Consistency
2015-10-18 11:53:06 -04:00
Mike Koch
0ffd3edf7e #371 Move glyphicon to UI, remove hard-coded string 2015-10-18 11:50:48 -04:00
Mike Koch
ed092c1bbd Merge pull request #374 from mkoch227/bug-fix-download-attachment-email
#370 Fix download attachment with email required
2015-10-18 11:13:04 -04:00
Mike Koch
accd424634 #370 Fix download attachment with email required 2015-10-17 22:06:57 -04:00
Mike Koch
5a66c16144 Merge pull request #373 from mkoch227/stabilize-canned-responses
Stabilize canned responses
2015-10-17 20:59:36 -04:00
Mike Koch
5314f4f49f Remove unused function 2015-10-17 20:58:43 -04:00
Mike Koch
10fb6e374d Remove api folder for now 2015-10-17 20:57:58 -04:00
Mike Koch
56e37e1358 #365 Use the ticket/replies HTML property for emails
Check the latest reply, or if there are no replies, the `html` property of the ticket.  If html is 1, then convert html to plaintext, otherwise leave it alone.
2015-10-17 20:50:16 -04:00
Mike Koch
03afe99284 #365 Convert HTML messages to plaintext using html2text 2015-10-16 22:49:09 -04:00
Mike Koch
a559dc232a #365 Add html2text dependency, initial implementation 2015-10-16 22:01:56 -04:00
Mike Koch
2712f70ba1 #365 Remove HTML column. It won't work 2015-10-16 19:59:23 -04:00
Mike Koch
8a432ec0bd #365 Get started on api 2015-10-15 22:31:24 -04:00
Mike Koch
bd115aaccb #365 Finish install changes 2015-10-15 21:56:25 -04:00
Mike Koch
989d67a231 #365 Add html column to templates and canned responses table 2015-10-12 13:02:45 -04:00
Mike Koch
34ef665699 Merge pull request #369 from mkoch227/client-side-validation
Client side validation
2015-10-10 00:30:56 -04:00
Mike Koch
754ad82c54 Improve private message table 2015-10-09 22:14:31 -04:00
Mike Koch
3528f284f6 #325 Add clientside validation to mail 2015-10-09 22:04:49 -04:00
Mike Koch
89a6c2cfc7 #325 Validate profile page 2015-10-09 21:50:11 -04:00
Mike Koch
77fd639c5a #325 Validate create status modal 2015-10-09 20:50:17 -04:00
Mike Koch
7647b4d559 #325 Remove var_dump 2015-10-09 20:43:13 -04:00
Mike Koch
b33d62aa26 #325 Getting started on statuses validation 2015-10-08 22:03:56 -04:00
Mike Koch
2a210f1185 #325 Add validation to service messages 2015-10-05 13:00:10 -04:00
Mike Koch
67ca7a3379 #325 Add validation to banned_ips 2015-10-05 12:56:16 -04:00
Mike Koch
f8a2802e08 #325 Add validation for banned emails 2015-10-05 12:54:09 -04:00
Mike Koch
4f72e017b8 #325 Add validation to manage_knowledgebase 2015-10-05 12:50:02 -04:00
Mike Koch
dafc94c58a Add validation for ticket templates 2015-10-02 22:23:21 -04:00
Mike Koch
f2ad2f5b98 #325 Add validation to manage_canned 2015-10-02 22:15:09 -04:00
Mike Koch
4543ba415c #325 Add validation to manage categories 2015-09-28 22:01:14 -04:00
Mike Koch
ec7e21cf54 Slight UI change to permission templates 2015-09-28 21:55:27 -04:00
Mike Koch
c53ab310c0 #325 Not validating existing templates... weird issues with the validator 2015-09-28 21:49:53 -04:00
Mike Koch
448d7894ff #325 Some more progress made on manage permission templates validation 2015-09-28 12:50:51 -04:00
Mike Koch
0dd5bff109 #325 Getting started on permission template validation 2015-09-27 22:20:07 -04:00
Mike Koch
feb61469e2 #325 Valiate profile_functions 2015-09-27 14:07:54 -04:00
Mike Koch
92abcf17bc #325 Add validation to admin ticket page 2015-09-26 21:50:04 -04:00
Mike Koch
11dc343f49 Replace deprecated font tag 2015-09-26 20:13:14 -04:00
Mike Koch
405a403a54 #325 Add validation to admin create ticket 2015-09-25 22:28:56 -04:00
Mike Koch
002d6bdd9d #325 Some refactoring, validate find a ticket box 2015-09-24 22:00:43 -04:00
Mike Koch
7e9c09e008 #325 Add validation to view ticket sidebar 2015-09-24 21:25:25 -04:00
Mike Koch
00feae1b7b #325 Finish validation for view ticket 2015-09-24 17:00:16 -04:00
Mike Koch
e2ce9186f0 #325 Add validation to view ticket forms, not including replies 2015-09-18 22:12:07 -04:00
Mike Koch
84a39e814a Now support checkbox/multiselect validation 2015-09-17 22:06:23 -04:00
Mike Koch
8666619192 Testing CI 2015-09-15 18:05:22 -04:00
Mike Koch
d922bb58d7 Only check for rich text if setting is enabled 2015-09-15 13:35:07 -04:00
Mike Koch
75e332ea0c Display proper text and scroll into place. Switch emails to text instead of email 2015-09-15 13:31:24 -04:00
Mike Koch
b7670b6f2b Process TinyMCE validation on submit, fix warning w/multselect 2015-09-15 13:23:35 -04:00
Mike Koch
d563f8381b Got started on message validation for rich text 2015-09-14 12:26:31 -04:00
Mike Koch
7bf3f658f8 Replace deprecated HTML tag 2015-09-14 12:09:02 -04:00
Mike Koch
a76e659027 #325 Some more validation. Not sure how to handle the TinyMCE editor yet 2015-09-14 07:53:45 -04:00
Mike Koch
3c01d428ac #325 Got most custom fields going through validation 2015-09-14 00:16:53 -04:00
Mike Koch
6c0ea488c4 #325 Start work on clientside validation on submit ticket page 2015-09-13 22:18:05 -04:00
Mike Koch
6b86062fcf #325 Add bootstrap validator library 2015-09-13 21:47:10 -04:00
Mike Koch
77750d4aba Merge pull request #362 from mkoch227/add-navbar-title-url-setting
Add setting for navbar title url
2015-09-13 11:38:51 -04:00
Mike Koch
25c8bd8ef5 #361 Add setting for navbar title url 2015-09-13 11:37:54 -04:00
Mike Koch
0d2f4f0871 Merge pull request #358 from mkoch227/fix-indentation
Fix indentation across the project
2015-09-12 00:49:19 -04:00
Mike Koch
a93b6e18f4 #253 Fix indentation across the project 2015-09-12 00:46:46 -04:00
Mike Koch
c5dc8b809f Merge pull request #356 from mkoch227/remove-inline-styling
Remove some inline styling
2015-09-12 00:30:10 -04:00
Mike Koch
cf1f9588a4 Use Mods for HESK build number for cache control 2015-09-12 00:29:12 -04:00
Mike Koch
89fed16339 Moved common CSS into its own stylesheet 2015-09-12 00:25:04 -04:00
Mike Koch
e8b800de52 Remove style tag from ticket.php 2015-09-11 23:54:51 -04:00
Mike Koch
5ed1ea67c8 Remove style tag from knowledgebase 2015-09-11 23:53:39 -04:00
Mike Koch
4dad68c820 Remove some style tags on index 2015-09-11 23:52:39 -04:00
Mike Koch
ddaf235167 Manage users no longer has inline styling 2015-09-10 22:02:46 -04:00
Mike Koch
8c662d218c Removed inline styling on manage_categories 2015-09-10 21:11:58 -04:00
Mike Koch
1491f11073 Manage ticket templates no longer has inline styling 2015-09-10 21:05:01 -04:00
Mike Koch
bdd3622ad1 Manage canned no longer has inline styles 2015-09-10 21:03:20 -04:00
Mike Koch
ea5f692f55 Remove inline styling from manage kb 2015-09-10 17:36:33 -04:00
Mike Koch
1a4d62fec9 Remove inline styling from export 2015-09-10 16:47:31 -04:00
Mike Koch
f5cf6ca754 Remove inline styling from reports 2015-09-10 16:46:25 -04:00
Mike Koch
c1acee66a1 Remove inline styling from manage_statuses 2015-09-10 16:43:39 -04:00
Mike Koch
cd37227cee Remove inline styling from email templates page 2015-09-10 16:41:36 -04:00
Mike Koch
9ae9735454 Remove inline styling from service messages 2015-09-10 16:40:13 -04:00
Mike Koch
7c9a884d85 Remove inline styling in banned_ips 2015-09-10 16:33:16 -04:00
Mike Koch
df07ebf375 Remove inline style from banned_emails 2015-09-10 16:28:06 -04:00
Mike Koch
98828ef1de Remove inline styling from mail 2015-09-10 16:22:50 -04:00
Mike Koch
93116c596c Finished removing inline styling for admin_settings 2015-09-10 16:15:55 -04:00
Mike Koch
6b471e797d Some more inline style removal 2015-09-10 13:30:58 -04:00
Mike Koch
a1d3856dd9 #338 Start with some small CSS refactoring 2015-09-09 22:04:17 -04:00
Mike Koch
956ca9c15e Update CONTRIBUTING.md 2015-09-09 09:30:18 -04:00
Mike Koch
40bf1080b1 Merge pull request #354 from mkoch227/new-custom-fields
New custom fields
2015-09-08 22:16:40 -04:00
Mike Koch
78adcff788 #324 Add new custom fields to create and edit ticket pages 2015-09-08 22:14:00 -04:00
Mike Koch
8e5a23781f #324 Add readonly and hidden custom fields 2015-09-07 17:36:54 -04:00
Mike Koch
fb6eb67064 Merge pull request #352 from mkoch227/use-build-numbers
fix css classes
2015-09-07 14:02:49 -04:00
Mike Koch
6cd71605c1 fix css classes 2015-09-07 14:01:35 -04:00
Mike Koch
941103d5b5 Merge pull request #351 from mkoch227/use-build-numbers
Use build numbers instead of version numbers
2015-09-07 13:59:48 -04:00
Mike Koch
f268994ab4 #348 Use build numbers instead of version numbers 2015-09-07 13:58:23 -04:00
Mike Koch
db30437b66 Merge pull request #349 from mkoch227/remove-v-prefix
Remove v prefix from version numbers
2015-09-07 13:39:58 -04:00
Mike Koch
b054dde714 #337 Remove v prefix from version numbers 2015-09-07 13:11:36 -04:00
Mike Koch
3cf50f2aec Merge pull request #345 from mkoch227/user-agent-support
User agent support
2015-09-06 22:15:32 -04:00
Mike Koch
f899f3dc31 #326 Update pipe_functions to include user agent 2015-09-06 22:14:58 -04:00
Mike Koch
52ba392050 #326 Add setting for showing user agent info 2015-09-06 22:12:49 -04:00
Mike Koch
40e97ede1a #326 Some more user agent stuff 2015-09-06 18:34:58 -04:00
Mike Koch
ce8c681a2c #326 Display a modal for user agent and screen res 2015-09-06 17:52:51 -04:00
Mike Koch
9156e98169 #326 Show user agent info on admin_ticket 2015-09-05 22:04:30 -04:00
Mike Koch
6c8feec6f7 #326 Start displaying user agent information 2015-09-04 22:25:36 -04:00
Mike Koch
bb34ebc7a4 #326 Store user agent string with the ticket 2015-09-04 22:14:25 -04:00
Mike Koch
4661e88702 #326 Add platform.js to header files 2015-09-04 21:59:13 -04:00
Mike Koch
49da07662b #326 Switch from PHP library to platform.js 2015-09-04 21:52:00 -04:00
Mike Koch
f0cd1f5159 Merge branch '2-5-0' into user-agent-support 2015-09-04 21:46:45 -04:00
Mike Koch
6bce24cca0 Merge pull request #344 from mkoch227/convert-new-style-to-css
Rename the RTL css file from .php to .css
2015-09-04 21:45:01 -04:00
Mike Koch
598fd76509 #339 Rename the RTL css file from .php to .css 2015-09-04 21:33:30 -04:00
Mike Koch
868deff525 Merge pull request #342 from mkoch227/move-settings-to-db
Move MFH Settings to Database
2015-09-03 22:11:59 -04:00
Mike Koch
cd63e54fbc Merge pull request #343 from mkoch227/add-message-no-attachments-tag
Add MESSAGE_NO_ATTACHMENTS tag
2015-09-03 22:11:48 -04:00
Mike Koch
de5a568cd2 Merge remote-tracking branch 'origin/master' into move-settings-to-db
# Conflicts:
#	install/mods-for-hesk/sql/installSql.php
2015-09-03 22:01:38 -04:00
Mike Koch
849ef01b17 #327 Settings are finally all driven through the database 2015-09-03 21:58:05 -04:00
Mike Koch
57ba54d044 #327 Fix find_tickets page 2015-09-03 19:58:46 -04:00
Mike Koch
72ffcebe00 #327 Save setting to the DB 2015-09-03 19:47:08 -04:00
Mike Koch
dba84f19b2 #327 Move UI color CSS to header.inc.php 2015-09-03 16:31:54 -04:00
Mike Koch
a784ef1c14 #327 Switched back to getting all settings 2015-09-02 22:04:32 -04:00
Mike Koch
3220f6d299 Update README.md 2015-09-02 13:28:48 -04:00
Mike Koch
28db16119b Add some more badges 2015-09-02 13:27:03 -04:00
Mike Koch
264c2e028e #327 Replaced all instances (I think?) of $modsForHesk_settings 2015-09-01 12:22:25 -04:00
Mike Koch
22465d68dc #327 Some more progress on moving settings to DB 2015-09-01 10:43:55 -04:00
Mike Koch
77489d8eef #330 Add MESSAGE_NO_ATTACHMENTS tag 2015-08-31 12:59:37 -04:00
Mike Koch
f38bff6e0c Update README.md 2015-08-31 07:57:24 -04:00
Mike Koch
6cbd9e7913 Update installer 2015-08-30 22:07:41 -04:00
Mike Koch
da7b0f6691 Merge pull request #335 from mkoch227/fix-canned-templates-and-responses
Fix canned templates and responses
2015-08-30 22:00:02 -04:00
Mike Koch
36d7d08d1d Merge pull request #333 from mkoch227/fix-extra-line-breaks
Fix extra line breaks in HTML templates
2015-08-30 21:59:47 -04:00
Mike Koch
6c81dd451a Merge pull request #332 from mkoch227/update-to-hesk-2-6-5
HESK 2.6.5 Support
2015-08-30 21:59:38 -04:00
Mike Koch
63f0199f9e #334 Properly escape quotes in canned responses/ticket templates 2015-08-30 12:03:43 -04:00
Mike Koch
8c3324ead6 #334 Fix escaping on ticket templates page 2015-08-29 22:26:44 -04:00
Mike Koch
829eb07580 Closes #323 Don't add additional line breaks in HTML messages 2015-08-29 22:10:10 -04:00
Mike Koch
5bdea0c343 #331 Update install functions 2015-08-29 21:44:42 -04:00
Mike Koch
1528c1de7e #331 Update headers 2015-08-29 21:44:26 -04:00
Mike Koch
39a49b9cf5 #331 Update recaptchalib 2015-08-29 21:31:36 -04:00
Mike Koch
b774572766 #331 Update email_functions 2015-08-29 21:30:20 -04:00
Mike Koch
f3d84cf361 #331 Update common 2015-08-29 21:29:35 -04:00
Mike Koch
a0958641ff #331 Update admin_functions 2015-08-29 21:29:22 -04:00
Mike Koch
3619a4c507 #331 Update password 2015-08-29 21:29:12 -04:00
Mike Koch
379d096f88 #331 Update admin_settings_save 2015-08-29 21:29:01 -04:00
Mike Koch
6d9362ed4d #327 Fix query, use DB settings on index page 2015-08-28 22:24:25 -04:00
Mike Koch
4934c60e34 #327 Add method for getting MFH settings 2015-08-28 22:04:21 -04:00
Mike Koch
57c3e6aaa6 #327 Remove modsForHesk_settings.inc.php 2015-08-27 17:35:17 -04:00
Mike Koch
cf6e381989 #327 Make sure the setting exists. Otherwise give it a default value 2015-08-27 16:57:18 -04:00
Mike Koch
8719c51a80 #327 Add SQL to insert all records to DB 2015-08-25 22:18:27 -04:00
Mike Koch
148fe141d8 #326 Add library for parsing user agent 2015-08-25 21:41:34 -04:00
Mike Koch
5b4422c59b Fix installer
I got too copy-paste happy 😦
2015-08-21 13:24:03 -04:00
Mike Koch
88c8506cf3 Merge pull request #322 from mkoch227/2-4-1-fixes
2.4.1 Changes
2015-08-21 12:52:10 -04:00
Mike Koch
ad60d297e5 #320 Update installer 2015-08-21 12:51:14 -04:00
Mike Koch
68ed326695 #320 Enforce the new setting 2015-08-21 12:45:10 -04:00
Mike Koch
a52dbb840f #320 Add setting 2015-08-21 12:38:53 -04:00
Mike Koch
b7e54d3b45 #321 Fix downloads for helpdesks not at root level 2015-08-21 12:29:20 -04:00
Mike Koch
fc1ab9a861 Don't allow status creation in demo mode 2015-08-20 00:34:00 -04:00
Mike Koch
a38a00cf83 Add html column to stage_tickets, update uninstaller 2015-08-19 19:48:46 -04:00
Mike Koch
c630fbf454 Merge pull request #318 from mkoch227/better-html-rendering
Only render HTML if the ticket was created with it enabled
2015-08-19 07:56:58 -04:00
Mike Koch
28a9698f71 #317 Only render HTML if the ticket was created with it enabled 2015-08-19 07:46:52 -04:00
Mike Koch
9f4a5edda7 Merge pull request #314 from mkoch227/improve-update-ux
Improve check for update ux
2015-08-15 22:22:03 -04:00
Mike Koch
094f06d02b #305 Improve check for update ux 2015-08-15 22:11:14 -04:00
Mike Koch
6b70366701 Merge pull request #313 from mkoch227/statuses-tooltips
Add tooltips to statuses page and fix create status issue
2015-08-15 15:47:07 -04:00
Mike Koch
b5576e9b4c #310 Add tooltips to statuses page and fix create status issue 2015-08-15 15:46:38 -04:00
Mike Koch
2ad48fad38 Merge pull request #312 from mkoch227/submit-ticket-quick-help
#309 Add submit ticket page (staff) to quick help section setting
2015-08-15 15:27:17 -04:00
Mike Koch
389ddce086 #309 Add submit ticket page (staff) to quick help section setting 2015-08-15 15:26:55 -04:00
Mike Koch
793191de11 Merge pull request #308 from mkoch227/bug-fix-weird-merge-issue
Fix rare merge issue
2015-08-13 17:28:01 -04:00
Mike Koch
cbb80754fe #231 Append, don't replace the replies sql 2015-08-13 17:27:21 -04:00
Mike Koch
bd420a8933 Merge pull request #307 from mkoch227/remove-deprecated-panel
Remove deprecated panel
2015-08-09 17:29:55 -04:00
Mike Koch
cc5c72bcf1 #303 Remove deprecated panel 2015-08-09 17:08:33 -04:00
Mike Koch
61fae1013a Merge pull request #306 from mkoch227/update-installation
Update installer, fix status issues, fix TinyMCE issues
2015-08-09 17:06:18 -04:00
Mike Koch
f64aa7a2cc Should be ID, not Id 2015-08-09 17:04:11 -04:00
Mike Koch
8fa5bc95b8 #304 Fix inserting canned templates/responses in the TinyMCE editor 2015-08-09 17:02:04 -04:00
Mike Koch
bea4422bdc Enforce the language on the JOIN, not the WHERE 2015-08-09 11:49:41 -04:00
Mike Koch
19cf074fc4 Make sure we can change to the other languages during installation 2015-08-08 15:53:35 -04:00
Mike Koch
9612b61e46 Fix missing quotes 2015-08-08 15:22:08 -04:00
Mike Koch
5a25becff6 It's ID, not Id 2015-08-08 15:09:35 -04:00
Mike Koch
663d0e3863 Also enforce language column 2015-08-08 15:09:30 -04:00
Mike Koch
f2b8fb8f74 Grab the next status id when inserting 2015-08-08 14:55:25 -04:00
Mike Koch
d22c1db84d Fix installer issues 2015-08-08 14:38:16 -04:00
Mike Koch
1cbeb19a7a Change version reqirements for showing the tasks section 2015-08-08 14:37:36 -04:00
Mike Koch
a812b4379a Add line break 2015-08-08 00:30:08 -04:00
Mike Koch
e107f0eabb Update uninstaller 2015-08-08 00:27:45 -04:00
Mike Koch
3fdbced605 Update install pages for 2.4.0 2015-08-08 00:25:20 -04:00
Mike Koch
25dd548e35 Merge pull request #301 from mkoch227/attachment-improvements
Attachment improvements, phase one
2015-08-06 21:43:31 -04:00
Mike Koch
194c4a0dad #275 Utilize the separated folders option 2015-08-06 12:56:44 -04:00
Mike Koch
698e0b678a #275 Add setting for knowledgebase attachments folder 2015-08-06 12:46:14 -04:00
Mike Koch
598e19130b #275 Add attachments.inc.php to source control 2015-08-06 12:27:30 -04:00
Mike Koch
8cba950253 #275 Customers now have the new attachment viewer 2015-08-06 12:21:43 -04:00
Mike Koch
246d2e6261 #275 Show download count next to attachment name 2015-08-04 12:37:36 -04:00
Mike Koch
f375859de3 #275 Only update dl count if the attachment exists 2015-08-04 12:37:18 -04:00
Mike Koch
22d6d3569c #275 Update download count for each attachment 2015-08-03 22:20:49 -04:00
Mike Koch
e7a90e66e4 #275 Add kb attachment download count 2015-08-03 22:20:38 -04:00
Mike Koch
c136e7cd45 Merge branch 'master' into attachment-improvements 2015-08-03 22:12:09 -04:00
Mike Koch
f5cc9da792 #275 Add download count column to attachments table 2015-08-03 22:10:57 -04:00
Mike Koch
121df747f5 #275 Add download_attachment to source control 2015-08-03 22:08:55 -04:00
Mike Koch
ef1b6a1fb7 Merge pull request #299 from mkoch227/status-sort-on-new-status
Fix some status stuff before release
2015-08-03 21:54:16 -04:00
Mike Koch
0d8eda3697 #298 Fix default status for actions 2015-08-03 21:53:07 -04:00
Mike Koch
32efca8f5c #298 Don't allow user to delete statuses that are a default action or have tickets set to that status 2015-08-02 22:21:05 -04:00
Mike Koch
7e5390936f #298 Resort statuses when one is deleted 2015-08-02 22:01:17 -04:00
Mike Koch
d733dbe004 #298 Set a sort value to new statuses 2015-08-02 21:59:48 -04:00
Mike Koch
1b8c69cb31 Merge pull request #297 from mkoch227/bug-fix-zero-kb-attachments
Fix some 0kb attachment issues
2015-08-02 16:53:30 -04:00
Mike Koch
5454341743 Merge pull request #296 from mkoch227/fix-some-htmlawed-stuff
Fix some missing htmLawed references
2015-08-02 16:52:59 -04:00
Mike Koch
0bb4ce223f #287 Fix some 0kb attachment issues 2015-08-02 16:52:36 -04:00
Mike Koch
ce33ee44f6 Fix some missing htmLawed references 2015-08-02 16:51:24 -04:00
Mike Koch
9770f114a4 Merge pull request #295 from mkoch227/bug-fix-statuses-key-on-tickets-table
Add statuses key to tickets table in the very beginning upgrade
2015-08-02 16:32:55 -04:00
Mike Koch
bae3574ee9 #288 Add statuses key to tickets table in the very beginning upgrade 2015-08-02 16:32:23 -04:00
Mike Koch
77c2de5d80 Merge pull request #294 from mkoch227/bug-fix-empty-email-recipient
Don't send email if all email fields are empty
2015-08-02 16:27:23 -04:00
Mike Koch
4e8e072924 #291 Don't send email if all email fields are empty 2015-08-02 16:26:53 -04:00
Mike Koch
ac1d197f42 Merge pull request #285 from mkoch227/tiny-mce-for-tickets
Tiny mce for tickets
2015-08-02 16:21:40 -04:00
Mike Koch
a55b4f1a7f #202 Turn off rich text by default 2015-08-02 16:21:22 -04:00
Mike Koch
4173c366e6 Merge branch 'master' into tiny-mce-for-tickets
# Conflicts:
#	admin/admin_settings.php
#	admin/admin_settings_save.php
#	language/en/text.php
#	modsForHesk_settings.inc.php
2015-08-02 16:20:10 -04:00
Mike Koch
b7c7cd8639 #202 Use htmLawed to help prevent against XSS attacks 2015-08-02 16:14:17 -04:00
Mike Koch
497a7550f4 #202 Use htmLawed to help prevent XSS 2015-08-01 16:38:54 -04:00
Mike Koch
222258a591 #202 Add TinyMCE to manage canned page 2015-07-31 22:17:59 -04:00
Mike Koch
84dda62e71 #209 Start working on TinyMCE for manage canned 2015-07-30 22:04:11 -04:00
Mike Koch
03de74dea7 Merge pull request #293 from mkoch227/improve-statuses-ui
Improve Statuses UI
2015-07-30 13:01:34 -04:00
Mike Koch
e708c722a2 #202 Add TinyMCE to ticket template page 2015-07-30 13:00:53 -04:00
Mike Koch
99d25cbd33 Merge pull request #286 from mkoch227/curl-for-recaptcha
Add cURL Support for reCAPTCHA v2
2015-07-30 12:44:58 -04:00
Mike Koch
c0dd60e576 Merge pull request #283 from mkoch227/bug-fix-custom-field-section-on-canned
Always show custom field selection when editing canned response
2015-07-30 12:44:49 -04:00
Mike Koch
4f65200405 #209 Add setting for status sort to settings page 2015-07-30 12:42:04 -04:00
Mike Koch
9db20734ca #209 Everything uses the new status_functions 2015-07-30 12:35:30 -04:00
Mike Koch
a131b7842e #209 Add sort property, and statuses page honors sort 2015-07-29 22:27:00 -04:00
Mike Koch
05063218c4 #209 Fix checkboxes on search screen and use correct status on ticket table 2015-07-28 22:09:34 -04:00
Mike Koch
c9360fd538 #209 Update search and export pages to show new status table
Still need to fix searching and need to test exporting
2015-07-28 13:00:26 -04:00
Mike Koch
50778c02dd #209 Customer view ticket now supports new status table 2015-07-28 12:52:42 -04:00
Mike Koch
6b83e852d0 #209 Support new status table 2015-07-28 12:52:30 -04:00
Mike Koch
22e8a8efe9 #209 View ticket on admin side now supports new statuses 2015-07-28 12:47:13 -04:00
Mike Koch
98ee61ff6d #209 Write migration to populate the xref table 2015-07-28 12:27:12 -04:00
Mike Koch
6be1d32a54 #209 Start migration logic 2015-07-27 22:11:53 -04:00
Mike Koch
f056e83b40 #209 Statuses can now be sorted 2015-07-27 00:06:57 -04:00
Mike Koch
bb00445ae2 #209 Build modals at end to prevent nested forms, provide suggestions from language file 2015-07-26 23:45:50 -04:00
Mike Koch
90903e8491 #209 Start implementing move up/down 2015-07-26 22:17:30 -04:00
Mike Koch
14ad6cd4f2 #209 Statuses can now be deleted 2015-07-26 21:47:05 -04:00
Mike Koch
1a825b81af #209 Statuses can now be edited 2015-07-26 21:23:04 -04:00
Mike Koch
05be7d7041 #209 Some performance tweaks; also use function for rest of page 2015-07-26 12:17:41 -04:00
Mike Koch
2b6807137f #209 Add ability get status text based on xref or fallback 2015-07-25 22:08:07 -04:00
Mike Koch
03718e2632 #209 New statuses can be created to the xref table 2015-07-25 16:33:44 -04:00
Mike Koch
15c2e7d983 #209 Mockup for create status modal is complete, add table for status text 2015-07-25 01:11:08 -04:00
Mike Koch
e64eebad81 #209 Some more UI changes. Still need to setup modals. 2015-07-23 22:06:02 -04:00
Mike Koch
84e2be3a8c #209 Remove unused save actions 2015-07-23 21:39:34 -04:00
Mike Koch
35a3f80890 #209 Only show move up/down if at the right point 2015-07-23 21:25:27 -04:00
Mike Koch
2e3d9ccded #209 Remove form-related fields from the table 2015-07-22 22:04:10 -04:00
Mike Koch
98e589dfb4 #209 Tweak the statuses UI
- Remove "Language Key" input field
- Add panels to separate content
- Add pencil icon w/tooltip that will soon hold a way to edit the name
2015-07-19 22:20:18 -04:00
Mike Koch
bab50e059f #284 Add cURL support for recaptchalib_v2 2015-07-16 22:04:59 -04:00
Mike Koch
f19f204534 #284 Add recaptchalib to repo 2015-07-16 22:04:42 -04:00
Mike Koch
8473d7280f #202 Don't allow customers to view markup when entering message 2015-07-15 00:03:07 -04:00
Mike Koch
5068c5ba2d #208 Add TinyMCE to client side and fix edit post for admin 2015-07-14 22:21:28 -04:00
Mike Koch
7048ab621b #208 Fix print view 2015-07-14 22:13:58 -04:00
Mike Koch
ffabc4e67d #202 Only decode HTML if rich text is enabled 2015-07-12 22:10:58 -04:00
Mike Koch
01964b61b8 Closes #281 Always show custom field selection when editing canned response 2015-07-12 11:27:00 -04:00
Mike Koch
f75cc87c10 #208 Fix rendering of HTML and for signatures 2015-07-09 22:13:16 -04:00
Mike Koch
9dd83e9f41 #208 Don't use TinyMCE for custom fields 2015-07-09 21:48:06 -04:00
Mike Koch
fc5b47072b #202 Start adding TinyMCE to admin pages.
Still need to fix canned responses on admin_ticket though
2015-07-07 22:16:48 -04:00
Mike Koch
035c5f092a #202 Add setting for rich text 2015-07-06 22:13:50 -04:00
Mike Koch
edae4ffa37 #202 Add setting for rich text 2015-07-05 22:22:05 -04:00
Mike Koch
c73f97e0de Merge branch 'master' into tiny-mce-for-tickets 2015-07-05 22:07:19 -04:00
Mike Koch
5b27b9c464 #202 Display HTML-formatted versions of ticket messages
Should add conditional to parse the HTML or to leave it alone, depending on the helpdesk's setting
2015-07-05 22:03:09 -04:00
Mike Koch
d928a1956b Merge pull request #280 from mkoch227/hide-quick-help-sections
Hide quick help sections
2015-07-05 11:49:14 -04:00
Mike Koch
43d00943c6 #218 Utilize quick help section settings on actual pages 2015-07-05 11:48:19 -04:00
Mike Koch
5c3fca0682 #218 Add settings area for quick help sections 2015-07-04 20:19:02 -04:00
Mike Koch
c3c1f2a43c #218 Add SQL to create quick_help_sections table 2015-07-04 19:47:59 -04:00
Mike Koch
9ceb15d90e Merge pull request #278 from mkoch227/sticky-indicator
Add visual indicator for stickied KB articles
2015-07-04 01:06:30 -04:00
Mike Koch
920ac53de9 Merge pull request #279 from mkoch227/sort-categories-alphabetically
Sort categories alphabetically
2015-07-04 01:06:09 -04:00
Mike Koch
7afb51164a Closes #274 Add setting for setting category sort 2015-07-04 01:04:50 -04:00
Mike Koch
9edb0095a4 #274 Add category sort property for dropdowns and table 2015-07-03 22:23:09 -04:00
Mike Koch
41fe2bc6f5 Closes #277 Add visual indicator for stickied KB articles 2015-07-03 16:54:49 -04:00
Mike Koch
9fd5b31ac1 Update README.md 2015-06-29 07:17:58 -04:00
Mike Koch
469ded409f Update installer 2015-06-28 14:39:42 -04:00
Mike Koch
e4865f192b Close #272 Switch to an https capable CDN 2015-06-28 14:35:03 -04:00
Mike Koch
9cf564a99f Update README 2015-06-28 11:37:12 -04:00
Mike Koch
6b7987ffef Update installer for 2.3.1 2015-06-28 11:27:28 -04:00
Mike Koch
645c01f75f Merge pull request #266 from mkoch227/make-leaflet-stored-locally
Store leaflet CSS/JS locally
2015-06-28 01:16:31 -04:00
Mike Koch
8a9045df40 Merge pull request #267 from mkoch227/large-space-when-requesting-location
Display map div only after getting location
2015-06-28 01:16:15 -04:00
Mike Koch
a202808f0b Merge pull request #268 from mkoch227/knowledgebase-footer
Hopefully fixed the footer...again
2015-06-28 01:16:08 -04:00
Mike Koch
306efad3a0 Merge pull request #269 from mkoch227/fix-reply-layout
Fix response layouts
2015-06-28 01:15:59 -04:00
Mike Koch
5c50c26239 Merge pull request #270 from mkoch227/fix-install-syntax-error
[MFH-1] Fix install sql error
2015-06-28 01:15:54 -04:00
Mike Koch
70b695f5bf Merge pull request #271 from mkoch227/cannot-create-status
[MFH-2] Fix status validation
2015-06-28 01:15:10 -04:00
Mike Koch
0373f60936 [MFH-2] Fix status validation #resolve 2015-06-28 01:14:36 -04:00
Mike Koch
01f513732f [MFH-1] Fix install sql error 2015-06-28 00:58:24 -04:00
Mike Koch
47f4978d5b Closes #263 Fix response layouts 2015-06-27 22:06:27 -04:00
Mike Koch
5b1961159b Closes #259 Hopefully fixed the footer...again 2015-06-27 21:34:18 -04:00
Mike Koch
9986e41c5c Closes #262 Display map div only after getting location 2015-06-27 16:35:07 -04:00
Mike Koch
39c5fc6f86 #264 Store leaflet CSS/JS locally 2015-06-27 16:05:53 -04:00
Mike Koch
458bbc8bdc Fix SQL 2015-06-25 00:16:26 -04:00
Mike Koch
72a8d22982 Some tweaks to permission templates 2015-06-24 23:49:34 -04:00
Mike Koch
eae88f8294 Fix location 2015-06-24 23:35:41 -04:00
Mike Koch
4988fc49bd #257 Update README and LICENSE 2015-06-23 23:47:03 -04:00
Mike Koch
54b8ffe7e8 #255 Update HESK/MFH versions 2015-06-23 23:37:36 -04:00
Mike Koch
b5a2a11b69 #255 Update installer 2015-06-23 23:36:55 -04:00
Mike Koch
40afa50bca #255 Update headers 2015-06-23 23:33:03 -04:00
Mike Koch
e84c27fa16 #255 Update code to 2.6.4 2015-06-23 23:30:49 -04:00
Mike Koch
139853e0d4 #255 Update code for 2.6.3 2015-06-23 23:29:16 -04:00
Mike Koch
5d5a25bf2c Closes #256 Change sub_ticket to sub_support in header 2015-06-19 20:17:31 -04:00
Mike Koch
84b0932042 Merge pull request #254 from mkoch227/permission-groups
Permission groups
2015-06-16 22:11:18 -04:00
Mike Koch
ac3ba746f6 Update uninstaller 2015-06-16 22:10:22 -04:00
Mike Koch
cc58d84311 #196 Add template name to table 2015-06-16 21:00:49 -04:00
Mike Koch
81553d4885 #196 Patch up some permission stuff 2015-06-16 00:15:02 -04:00
Mike Koch
9685a22aa1 Remove unused permission checks 2015-06-16 00:15:00 -04:00
Mike Koch
c50aa6a8d0 #196 Move can_man_settings and can_change_notification_settings into heskprivileges 2015-06-16 00:14:59 -04:00
Mike Koch
9a5bc49ac1 #196 Fix some "custom" template stuff 2015-06-15 23:45:56 -04:00
Mike Koch
18411f652a #196 Can now save/update templates 2015-06-15 23:40:11 -04:00
Mike Koch
7159a71bdb #196 Set template to custom if any checkboxes are clicked 2015-06-15 23:25:55 -04:00
Mike Koch
ebfc51b302 #196 Bring back can_man_settings 2015-06-15 23:16:16 -04:00
Mike Koch
6a7ac9c03f #196 JavaScript for selecting checkboxes now working 2015-06-15 22:10:06 -04:00
Mike Koch
155da1fd5b #196 Working on wiring up the manage_users page 2015-06-15 00:01:04 -04:00
Mike Koch
ef85d1c5f3 #196 Add permission type and navbar link to templates page 2015-06-14 23:38:14 -04:00
Mike Koch
c21b5f24bb #196 Set any user's permission group to 'Custom' if the template was changed 2015-06-14 23:29:48 -04:00
Mike Koch
53e7031117 #196 Allow the template name to be changed 2015-06-14 23:21:27 -04:00
Mike Koch
1247024b61 #196 Don't let templates 1 and 2 be toggled from admin to non-admin (and vice-versa) 2015-06-14 23:19:01 -04:00
Mike Koch
445cf44258 #196 Permission groups can now be deleted and converted b/t admin/non-admin 2015-06-14 22:30:17 -04:00
Mike Koch
82896346ec #196 Can now update permission templates 2015-06-14 15:28:34 -04:00
Mike Koch
8328d206fc #196 Add icon for designating permission template as admin template 2015-06-14 11:56:49 -04:00
Mike Koch
723674fab1 #196 More progress on permission templates 2015-06-13 16:44:52 -04:00
Mike Koch
e095534648 #196 Can now output permission groups 2015-06-13 01:20:45 -04:00
Mike Koch
4a2862e433 #196 Add permission template id to user 2015-06-13 01:20:28 -04:00
Mike Koch
0cff279adb #196 Move feature list into common 2015-06-13 01:20:06 -04:00
Mike Koch
7f4b1036a7 #196 Change query 2015-06-12 22:14:26 -04:00
Mike Koch
ff3ebc5067 #196 fix create sql, add default permission templates 2015-06-12 22:14:09 -04:00
Mike Koch
5af37d5616 #196 Some boilerplate stuff 2015-06-11 22:03:33 -04:00
Mike Koch
8112b1a087 Merge pull request #252 from mkoch227/bug-fix-kb-disabled
Don't show the KB link if KB is disabled
2015-06-07 22:02:07 -04:00
Mike Koch
0c0f1bc92e #249 Don't show the KB link if KB is disabled 2015-06-07 22:01:33 -04:00
Mike Koch
4e02138e3c Merge pull request #251 from mkoch227/designate-category-manager
Designate category manager
2015-06-07 20:32:00 -04:00
Mike Koch
b4315dc62a #208 Add permission for setting manager 2015-06-07 20:31:13 -04:00
Mike Koch
b6c0d20215 #208 Revoke manager rights if they are deactivated / deleted
Or if category access is removed
2015-06-07 18:09:25 -04:00
Mike Koch
09b53031db #208 Only show non-admins 2015-06-07 18:09:05 -04:00
Mike Koch
4ee1095e9c #208 Remove unecessary TODOs 2015-06-07 18:08:57 -04:00
Mike Koch
da02eca770 \# 208 Add category to user if they can't see it
This makes it much easier to tell if the user has access to the category
or not, instead of querying for which categories the user is manager of.
2015-06-07 01:41:20 -04:00
Mike Koch
69b8aaadfe #208 Manager can now access all ticket-related functions 2015-06-07 01:18:30 -04:00
Mike Koch
96fe276ea0 #208 Update some security stuff for managers. Still have a lot to do 2015-06-06 22:13:44 -04:00
Mike Koch
f4fc8ecf43 #208 Manager should have all ticket-related privileges 2015-06-05 19:03:52 -04:00
Mike Koch
eaf79776c7 Still need to setup security, though 2015-06-04 22:00:27 -04:00
Mike Koch
5834fd4720 #208 Add manager column to categories table 2015-06-04 21:52:30 -04:00
Mike Koch
f77720894c Merge pull request #248 from mkoch227/bug-fix-attachments-new-ticket
Fix attachments for creating new tickets
2015-05-27 21:56:55 -04:00
Mike Koch
2d0f3ce037 Closes #226 Fix attachments for creating new tickets 2015-05-27 21:52:26 -04:00
Mike Koch
91a25a942e Allow staff to set location 2015-05-26 22:04:25 -04:00
Mike Koch
836aa910e4 Merge pull request #247 from mkoch227/location-support
Location support. Closes #204
2015-05-23 23:56:55 -04:00
Mike Koch
8c80195d00 #204 Show error message if user's browser doesn't meet requirements 2015-05-23 23:55:52 -04:00
Mike Koch
0ff3d301f2 #204 Update uninstaller 2015-05-23 23:54:31 -04:00
Mike Koch
9e63a0f2ec #204 Drop the correct columns during uninstall 2015-05-23 23:53:20 -04:00
Mike Koch
9e78279564 #204 Set this back to 0 for release 2015-05-23 23:47:54 -04:00
Mike Koch
5b965d34d9 #204 Reset friendly name if not saving 2015-05-23 23:47:10 -04:00
Mike Koch
259e8d79a0 #204 Allow staff to see "friendly" street name 2015-05-23 23:46:10 -04:00
Mike Koch
cbdb8e9f12 #204 Show customer their location when submitting 2015-05-23 22:27:56 -04:00
Mike Koch
73264a6af0 #204 Reset button group when closing w/out saving 2015-05-23 20:34:45 -04:00
Mike Koch
1efb9b69b5 #204 Allow staff to change location if necessary 2015-05-23 14:53:38 -04:00
Mike Koch
179ad074dc #204 Switching this to 1 for now so I don't hafta keep changing it 2015-05-22 22:12:25 -04:00
Mike Koch
a6328e3be8 #204 Process error handling on staff-side 2015-05-21 22:08:18 -04:00
Mike Koch
38704b2c12 #204 Map is now in a modal and can be obtained via FontAwesome icon 2015-05-20 22:02:26 -04:00
Mike Koch
b44884a99e #204 Use leaflet to get a basic map displayed.
Still needs to be improved though. Also may not use the CDN.
2015-05-20 00:07:04 -04:00
Mike Koch
480067381c #204 Only show crosshair if location is enabled 2015-05-19 22:18:12 -04:00
Mike Koch
795419e819 #204 Add javascript for obtaining location 2015-05-19 22:05:50 -04:00
Mike Koch
1b73d0ec54 #204 Save lat/lon when creating new ticket 2015-05-19 22:04:19 -04:00
Mike Koch
4300bf03fd #204 Add setting for location tracking 2015-05-19 20:50:40 -04:00
Mike Koch
83525aabb5 #204 Add crosshair to ticket subject to view location 2015-05-15 22:12:30 -04:00
Mike Koch
20fbf93321 Merge pull request #246 from mkoch227/dashboard-tweaks
Dashboard Tweaks
2015-05-15 18:54:00 -04:00
Mike Koch
43216a93ec #205 Remove unused CSS 2015-05-15 18:53:21 -04:00
Mike Koch
52d80491df #205 Tweaked index page layout and now show top/latest articles based on value in settings 2015-05-15 18:50:43 -04:00
Mike Koch
57345d2f41 Add version 2.3.0 file update function 2015-05-15 11:28:58 -04:00
Mike Koch
283ca7d787 Merge pull request #244 from mkoch227/merged-tickets-ticket-table
Closes #237 Add options to show # of merged tickets in ticket table
2015-05-15 01:35:25 -04:00
Mike Koch
7a9e20557b Closes #237 Add options to show # of merged tickets in ticket table 2015-05-15 01:34:37 -04:00
Mike Koch
4635050ac6 Remove validation from settings save and into manage statuses save 2015-05-13 18:35:18 -04:00
Mike Koch
37932b249a Merge pull request #243 from mkoch227/migrate-settings
Migrate settings
2015-05-13 18:27:49 -04:00
Mike Koch
86ad762b03 #195 Add some more "MFH" badges 2015-05-13 18:26:41 -04:00
Mike Koch
f4e69e90e2 #195 Add warning to old general/statuses area indicating move 2015-05-13 18:26:31 -04:00
Mike Koch
820bd60b7a Fix email cookie on index, add iconpicker to customer header to prevent errors 2015-05-13 18:02:43 -04:00
Mike Koch
1d32ed3887 Fix permission name for email templates, add other two tools to navbar check 2015-05-13 17:57:08 -04:00
Mike Koch
ddc15f3ad0 #195 Add permission for manage ticket statuses 2015-05-13 17:56:52 -04:00
Mike Koch
6d62492cc7 Actually show an error message if the template could not be saved 2015-05-13 17:15:01 -04:00
Mike Koch
afa279d98d #195 Moved statuses to Tools menu
Still need to add the permission
2015-05-13 17:14:59 -04:00
Mike Koch
cc1d6dee77 #195 Moved all settings from the general tab into their new locations 2015-05-11 22:25:43 -04:00
Mike Koch
f3e00678d1 Merge pull request #241 from mkoch227/alignment-issues
Alignment issues
2015-05-11 19:40:41 -04:00
Mike Koch
02a49171d5 #233 Fix panels when number of rows in top/latest are 0 2015-05-11 19:25:16 -04:00
Mike Koch
e950f7fce8 Fixes #240 show the sidebar regardless of number of articles 2015-05-11 19:21:27 -04:00
Mike Koch
494fe73078 #233 Fix footer on new_ticket 2015-05-11 18:53:11 -04:00
Mike Koch
63aeecbdb1 #233 Fix undefined variable and checkbox alignment 2015-05-11 18:48:25 -04:00
Mike Koch
919e5718f7 #233 Fix footer in knowledgebase 2015-05-11 18:39:58 -04:00
Mike Koch
d2a14c0c53 #233 Fix footer on reports page 2015-05-11 18:38:04 -04:00
Mike Koch
16053d6b94 Merge pull request #239 from mkoch227/fix-knowledgebase-markup
Closes #236 fix markup for knowledgebase folder icons
2015-05-10 22:08:04 -04:00
Mike Koch
a13fe410cf Closes #236 fix markup for knowledgebase folder icons 2015-05-10 22:07:20 -04:00
Mike Koch
0068fad7f2 Merge pull request #238 from mkoch227/bug-fix-232-merge-ticket-status
Fixes #232 Show status of merged ticket on client-side view ticket
2015-05-10 21:12:52 -04:00
Mike Koch
db6441c3db Fixes #232 Show status of merged ticket on client-side view ticket 2015-05-10 20:54:42 -04:00
Mike Koch
aa86a094eb #233 Fix some alignment issues 2015-05-09 15:01:22 -04:00
Mike Koch
c2e87677e3 Merge pull request #234 from mkoch227/service-messages
Service messages
2015-05-08 12:10:12 -04:00
Mike Koch
33dc2c3a9c Closes #141 Show correct icon for each service message 2015-05-08 12:05:16 -04:00
Mike Koch
f4c6588e41 Store the selected icon into the DB 2015-05-08 11:55:16 -04:00
Mike Koch
6898a5a9be #141 Finish up making iconpicker changes 2015-05-08 11:55:03 -04:00
Mike Koch
aa58468634 Change text for No Icon
... i still have to figure out some way to localize that piece of text
2015-05-08 10:41:24 -04:00
Mike Koch
0bed4daddf #141 Implement reset button and turn off shadows
So you can actually see the highlighted icon
2015-05-08 10:39:53 -04:00
Mike Koch
75636fa9ac #141 Add reset button to iconpicker 2015-05-07 22:31:38 -04:00
Mike Koch
9c3c298a64 Update bootstrap-iconpicker to allow for a reset button
It doesn't work yet, though
2015-05-07 22:25:53 -04:00
Mike Koch
1ac6602246 Merge branch 'master' into service-messages 2015-05-07 21:03:48 -04:00
Mike Koch
f927fb8f2b #141 Implement bootstrap-iconpicker 2015-04-30 22:02:03 -04:00
Mike Koch
b4b3417b14 Revert "#141 Using jQuery fonticonpicker instead"
This reverts commit 62ec9ebfc388eebd3e74c066e1737bda1e0dcfd0.
2015-04-30 17:31:49 -04:00
Mike Koch
7aabc1a4ae Revert "#141 Implement the icon picker"
This reverts commit e6bef55986d31e8541b019304fa4cc03fa9c9485.
2015-04-30 17:31:44 -04:00
Mike Koch
87be96ff49 Revert "create snippets for json parsing"
This reverts commit 89725ff071de072fe2418f37d11acf89b38ba45d.
2015-04-30 17:31:39 -04:00
Mike Koch
b3830b8b6f Revert "#141 Removed parser snippet"
This reverts commit a6626d98b716f68b3f2aa3f06f7305df7c6cdf9b.
2015-04-30 17:31:33 -04:00
Mike Koch
a6626d98b7 #141 Removed parser snippet 2015-04-29 21:28:45 -04:00
Mike Koch
1c307e0972 Update README.md 2015-04-29 17:24:43 -04:00
Mike Koch
5351407d1e Update README.md 2015-04-29 17:23:47 -04:00
Mike Koch
89725ff071 create snippets for json parsing 2015-04-28 22:30:42 -04:00
Mike Koch
e6bef55986 #141 Implement the icon picker
Still need to actually add the icons by parsing the YAML file of FontAwesome icons
2015-04-27 22:05:58 -04:00
Mike Koch
62ec9ebfc3 #141 Using jQuery fonticonpicker instead 2015-04-27 17:50:27 -04:00
Mike Koch
b2f89369ac #141 Add missing language tags 2015-04-27 17:22:20 -04:00
Mike Koch
9defb24235 Merge branch 'master' into service-messages
Conflicts:
	language/en/text.php
2015-04-27 17:20:42 -04:00
Mike Koch
d53c1285f0 #141 Remove bootstrap-iconpicker
Using different library instead
2015-04-27 17:19:32 -04:00
Mike Koch
082aa5ff33 Basic starting point for service message updates 2015-04-27 17:08:05 -04:00
Mike Koch
b10d4ae971 Fixes #228 Fix file path for plaintext templates 2015-04-27 16:49:33 -04:00
Mike Koch
a29fb44c5b Fix link 2015-04-22 22:25:05 -04:00
Mike Koch
5171512f85 Update install scripts 2015-04-22 22:21:10 -04:00
Mike Koch
9cc69d57c4 Update README 2015-04-22 22:15:14 -04:00
Mike Koch
15bbdcd978 Closes #225 Fix inserting for new statuses 2015-04-22 11:50:03 -04:00
Mike Koch
77ed135c40 Add non-english directories to .gitignore 2015-04-22 11:15:27 -04:00
Mike Koch
9c8887cd48 Fix missing $htmlPath reference, as it's not needed 2015-04-19 09:49:19 -04:00
Mike Koch
bf2d8eabee Fixes #210 don't add tick marks around language 2015-04-19 09:49:03 -04:00
Mike Koch
5b8a00af8d Merge pull request #221 from mkoch227/fix-attachments
Fix attachments
2015-04-18 22:21:47 -04:00
Mike Koch
0ae1d46aa7 Fixes #213 Only add attachments if %%MESSAGE%% tag is present 2015-04-18 22:20:47 -04:00
Mike Koch
48f0747669 #213 Add new parameter to hesk_mail and add helper function to check if message template has a particular tag 2015-04-18 22:00:25 -04:00
Mike Koch
2f33ec794c Fixes #214 always append outer boundary on sent emails 2015-04-18 16:03:34 -04:00
Mike Koch
6c92977f4a Merge pull request #219 from mkoch227/fix-knowledgebase
Fix knowledgebase
2015-04-17 22:11:01 -04:00
Mike Koch
b103a39b90 #216 Improve layout of knowledgebase section 2015-04-17 22:09:49 -04:00
Mike Koch
0efb2250f3 #216 Starting on fixing the knowledgebase 2015-04-17 16:27:08 -04:00
Mike Koch
50da09b201 Fixes #217 Perform case-insensitive comparison for file extensions
Also include jpeg as a valid photo extension
2015-04-17 15:10:27 -04:00
Mike Koch
9a084aa42b Merge branch 'master' into web-services 2015-04-15 11:18:12 -04:00
Mike Koch
e1f25b0e52 Fix variable name 2015-04-13 15:49:06 -04:00
Mike Koch
a2f1b2045d Update README.md 2015-04-13 12:56:11 -04:00
Mike Koch
6f4f1f6da0 Switch to PNG 😦 2015-04-13 12:52:49 -04:00
Mike Koch
67bee2b249 Update README 2015-04-13 12:52:03 -04:00
Mike Koch
a914642622 Closes #200 Actually link the button to the download file 2015-04-13 12:27:54 -04:00
Mike Koch
47b15f39e2 Closes #146 Use multipart/mixed to get multiple boundaries working
...trying to create these emails in plain PHP is torture. Note to self: use PHPMailer for future projects!
2015-04-13 00:48:26 -04:00
Mike Koch
f25edc47f1 fix query string 2015-04-13 00:01:33 -04:00
Mike Koch
2b2392af48 Update install scripts 2015-04-12 23:55:08 -04:00
Mike Koch
dbc351f09c Merge pull request #199 from mkoch227/attachments-in-emails
Attachments in emails
2015-04-12 23:54:29 -04:00
Mike Koch
a22c9c3867 #146 Add file update to install script 2015-04-12 23:47:14 -04:00
Mike Koch
dd35c39440 #146 remove unused parameter 2015-04-12 23:45:04 -04:00
Mike Koch
8963d7396c #146 Update delete attachment queries 2015-04-12 23:41:43 -04:00
Mike Koch
fb25ee73d3 Merge branch 'master' into attachments-in-emails 2015-04-12 23:23:29 -04:00
Mike Koch
292adde39b Merge pull request #198 from mkoch227/widen-ticket-table
Widen admin_main and show_tickets to the full page
2015-04-12 22:14:32 -04:00
Mike Koch
ad1580bf0c Closes #194 Widen admin_main and show_tickets to the full page 2015-04-12 22:13:50 -04:00
Mike Koch
823332a2ee #146 Add setting for attachments to the settings page 2015-04-12 22:05:00 -04:00
Mike Koch
dc4eb3997c #146 Get Mailgun to properly send the attachments 2015-04-12 15:53:06 -04:00
Mike Koch
190b3ff475 #146 Attachments can now be embedded directly into emails
Only tested SMTP, still need to check PHP mail() and Mailgun
2015-04-12 15:26:53 -04:00
Mike Koch
2ddb61bb55 Fix attachment view on HTML-formatted emails 2015-04-12 11:11:31 -04:00
Mike Koch
ab7f4e1cc1 #146 All emails will now be sent as multipart/alternative
Shouldn't cause issues w/plaintext emails, and it'll make it easier to add attachments.
2015-04-10 22:28:38 -04:00
Mike Koch
42f67322c5 Merge pull request #193 from mkoch227/show-other-tickets-from-email
Show other tickets from email
2015-04-09 22:38:03 -04:00
Mike Koch
297afdbf88 #153 Finish adding basic "recent tickets" information 2015-04-09 22:36:01 -04:00
Mike Koch
93ffba2a43 #153 got basic output going. just need to add links and color-coded circles with tooltips 2015-04-09 22:08:23 -04:00
Mike Koch
069c2ebc26 Fixes #191 Only show statuses relevant to the default action (open/closed/don't care) 2015-04-09 16:50:28 -04:00
Mike Koch
91ef48c323 Merge pull request #192 from mkoch227/non-closeable-statuses-157
Non closable statuses 157
2015-04-09 16:42:00 -04:00
Mike Koch
6d01eebb5e Add option for default status for when tickets are autoclosed 2015-04-09 16:41:13 -04:00
Mike Koch
eff75b27b1 Fix a small bug with auto-close and only auto-close if staff is allowed to 2015-04-09 16:27:20 -04:00
Mike Koch
e2d3eb92ac #157 Enforce closable on the customer-side ticket page 2015-04-09 16:13:15 -04:00
Mike Koch
8be17f91e7 Only show "close ticket" if staff can close it 2015-04-09 15:51:05 -04:00
Mike Koch
62d19e255e #157 Add closable setting to statuses
Still need to enforce this though
2015-04-09 11:37:47 -04:00
Mike Koch
54bbbf1610 Merge pull request #190 from mkoch227/email-template-editor
Email template editor
2015-04-08 17:20:13 -04:00
Mike Koch
0fce992568 #169 Show link to other tools pages 2015-04-08 17:13:58 -04:00
Mike Koch
61fed97bfe #169 Don't use a dedicated column 2015-04-08 17:13:56 -04:00
Mike Koch
570ab0e54f #169 Add can_manage_email_template permission 2015-04-08 17:13:49 -04:00
Mike Koch
5b68f5f926 Can now edit and save email templates 😀 2015-04-07 22:23:28 -04:00
Mike Koch
685bf6b008 #169 In a somewhat broken state. Can't use modals due to TinyMCE not wanting to resize inside of a modal. 2015-04-07 00:04:41 -04:00
Mike Koch
89efb15cd0 #169 Now able to dump list of template files and add links for HTML/plaintext 2015-04-06 22:25:09 -04:00
Mike Koch
bc2f2a67a5 Add some more to email templates 2015-04-06 21:16:32 -04:00
Mike Koch
9e43cc20e1 Got started on the email templates page. Nothing fancy 2015-04-06 17:11:22 -04:00
Mike Koch
5a4821f921 Fixes #181 update notify_customer_(new|reply) and show_suggested on profile page 2015-04-05 22:19:15 -04:00
Mike Koch
7ed4d23df4 #186 Fix indentation 2015-04-05 22:03:11 -04:00
Mike Koch
c4b039f41c Fixes #186 fix footer on show_tickets page 2015-04-05 22:02:50 -04:00
Mike Koch
79c261ce7e Fixes #183 turn off all notifications when clicking the deactivate icon 2015-04-05 15:28:21 -04:00
Mike Koch
a4b7e22c1c Fixes #185 Add true parameter to hesk_date for notes 2015-03-29 23:26:10 -04:00
Mike Koch
2962d9cf3e #182 Fixed this bug again for the tenth time... 😆 2015-03-23 17:34:55 -04:00
Mike Koch
34d8882421 Update README.md 2015-03-23 16:06:57 -04:00
Mike Koch
19b2582a19 Add 2.1.1 AJAX PHP logic 2015-03-23 01:23:15 -04:00
Mike Koch
4a3c9fc98d Add 2.1.1 JavaScript and button to installation page 2015-03-23 01:15:26 -04:00
Mike Koch
eb7bdc33fc Force users to install HESK before copying Mods for HES files 2015-03-23 01:15:07 -04:00
Mike Koch
e11745c4cc Update headers to 2.6.2 2015-03-23 01:02:59 -04:00
Mike Koch
79ebb90789 Closes #176 restyle attachments to be more responsive
While keeping the same features 😀
2015-03-23 01:00:15 -04:00
Mike Koch
e9ff6b42ea #176 Something different, but still not working right 2015-03-22 22:23:27 -04:00
Mike Koch
28196447fb Fixes #175 Fixed the layout of responses when using reply at top
The markup is invalid in the source code, but it somehow makes it work. Strange...
2015-03-22 22:02:38 -04:00
Mike Koch
5944ad1731 Fixes #179 fix ability to set auto refresh value when creating/editing users 2015-03-22 20:42:39 -04:00
Mike Koch
59fba0eeff Fixes #178 Show can manage helpdesk settings if the user can view the settings 2015-03-22 20:14:48 -04:00
Mike Koch
489f8c41c9 Closes #174 Update export.php to match HESK 2.6.2 2015-03-22 19:56:17 -04:00
Mike Koch
dcd21cd760 Fixes #180 use the verification table, update stage_tickets table to match tickets table 2015-03-22 19:51:03 -04:00
Mike Koch
0fe850f833 #176 add mission semicolon 2015-03-22 16:23:44 -04:00
Mike Koch
b7c1b30b7c Fixes #177 Set checkbox state to current database value 2015-03-21 21:59:22 -04:00
Mike Koch
acfed4d9c7 Fixes #176 set max-width property on .file-attachment > img 2015-03-21 21:48:50 -04:00
Mike Koch
bbe8ea7ca5 Closes #170 manage_knowledgebase now sets type based on helpdesk setting 2015-03-19 23:57:29 -04:00
Mike Koch
ef3fd06cab #170 Add settings option for default KB article type 2015-03-19 22:01:36 -04:00
Mike Koch
3e9d1b52c9 Closes #171 Wrap URLs in link tags automatically for HTML emails 2015-03-19 21:31:45 -04:00
Mike Koch
ae7e022b3e Fixes #173 Escape HTML-sensitive characters in placeholders 2015-03-19 21:12:50 -04:00
Mike Koch
adfc275cb5 Closes #168 Provide a way to uninstall Mods for HESK 2015-03-19 20:48:46 -04:00
Mike Koch
c3134b459a #168 Add SQL scripts, start JavaScript code 2015-03-17 22:02:19 -04:00
Mike Koch
2ddfc10933 #168 Add uninstall button to install screen, create uninstall php file 2015-03-16 22:08:11 -04:00
Mike Koch
e3000a1414 Update README.md 2015-03-15 21:20:08 -04:00
Mike Koch
0240c05b76 Add a cornucopia of badges 2015-03-15 21:19:41 -04:00
Mike Koch
95d896f721 Update CONTRIBUTING.md 2015-03-14 15:30:05 -04:00
Mike Koch
49748e68f6 Some more 2.6.0 -> 2.6.1 changes 2015-03-14 12:54:37 -04:00
Mike Koch
23dc02399f Update headers that weren't changed to 2.6.1 2015-03-14 12:53:40 -04:00
Mike Koch
02379f0ec6 Update installer 2015-03-14 12:50:05 -04:00
Mike Koch
a120e8d5c5 Add 2.1.0 update scripts 2015-03-14 12:44:40 -04:00
Mike Koch
75168b5026 Improve installation console, fix dynamic settings file update 2015-03-14 12:39:45 -04:00
Mike Koch
90605ed8c2 Revert "#140 Log information to the installLog table"
This reverts commit 029d7f0bf18c1baa902f2632d12f402cd8b038bb.
2015-03-14 01:28:14 -04:00
Mike Koch
029d7f0bf1 #140 Log information to the installLog table 2015-03-13 22:33:26 -04:00
Mike Koch
f0bbff9626 Closes #152 Allow user to disable bootstrap-theme.css 2015-03-12 21:59:52 -04:00
Mike Koch
ffcd684bb3 Closes #160 Add update checking for Mods for HESK 2015-03-11 22:12:46 -04:00
Mike Koch
df277c915e Closes #162 use nl2br for messages for HTML-formatted emails 2015-03-11 20:28:42 -04:00
Mike Koch
3d6796bfd9 Closes #166 Replace VERIFYURL and ACTIVATIONKEY for verifyEmail 2015-03-11 11:16:45 -04:00
Mike Koch
9411f9f980 Closes #164 Tweak login UI to allow for longer strings 2015-03-09 22:16:59 -04:00
Mike Koch
f93620b09e Closes #165 Fix layout for security question and reCAPTCHAs 2015-03-09 21:58:27 -04:00
Mike Koch
7ea2323e3d Create LICENSE 2015-03-09 16:54:32 -04:00
Mike Koch
9324678b65 Closes #163 use the language file for "Go back" 2015-03-09 12:09:08 -04:00
Mike Koch
4c823d351d Closes #150 disable and uncheck "send email" if email field is empty 2015-03-09 00:04:59 -04:00
Mike Koch
b1fee291eb Closes #148 add modsForHesk_settings.inc.php status to sidebar 2015-03-08 23:54:41 -04:00
Mike Koch
553cd0882a Closes #151 Migrate install JS into its own JavaScript source files
Also remove unused file from the install folder
2015-03-08 23:40:08 -04:00
Mike Koch
92ea19e47c Update installer to 2.0.1 2015-03-08 00:09:24 -05:00
Mike Koch
ad63e95975 Closes #158 Fix HTML layout for forgot ticket email by using an unordered list 2015-03-07 22:52:19 -05:00
Mike Koch
b7450785fa Closes #159 Fix HTML emails when sending emails via piping.
Plus the path to the settings file was wrong 😦
2015-03-07 21:28:22 -05:00
Mike Koch
173395b1e6 Closes #161 Style submit message and button to match the rest of MFH 2015-03-06 00:59:48 -05:00
Mike Koch
cd042db343 Update README.md 2015-03-02 12:02:15 -05:00
Mike Koch
37d8d2964d Merge pull request #155 from gitter-badger/gitter-badge
Add a Gitter chat badge to README.md
2015-03-02 12:00:07 -05:00
The Gitter Badger
acf18a2810 Added Gitter badge 2015-03-02 16:58:59 +00:00
Mike Koch
00d2091e7b improve wording 2015-03-01 11:31:27 -05:00
Mike Koch
7c826b70ee Add submitting issues to CONTRIBUTING 2015-03-01 11:31:00 -05:00
Mike Koch
672ba6ade0 Add CONTRIBUTING 2015-03-01 11:26:16 -05:00
Mike Koch
9306030575 Update README.md 2015-02-28 23:28:25 -05:00
Mike Koch
240f18ceb6 Remove beta tag on HTML emails 2015-02-28 23:28:14 -05:00
Mike Koch
edf0f7c852 Fix some bugs on the profile page 2015-02-28 22:28:19 -05:00
Mike Koch
6c43184c50 #147 Fix tooltips on IE 2015-02-27 12:04:57 -05:00
Mike Koch
8e585cd262 Closes #144 Updated to HESK 2.6.1 2015-02-26 18:42:43 -05:00
Mike Koch
dbc5868f27 Closes #143 Include modsForHesk_settings if it hasn't been included yet 2015-02-26 18:33:19 -05:00
Mike Koch
e39553a8d7 Closes #139 - Don't new-line SMTP array headers 2015-02-26 18:30:38 -05:00
Mike Koch
5e9eb4f355 Add after reply setting to create user 2015-02-25 11:08:06 -05:00
Mike Koch
9e116d1172 Closes #138 Fix notification settings when saving 2015-02-23 22:19:50 -05:00
Mike Koch
5c28c07c76 Merge pull request #137 from mkoch227/update-to-2-6-0-stable
Update to 2.6.0 Stable
2015-02-22 23:32:55 -05:00
Mike Koch
f562b59145 #136 Update reply_ticket 2015-02-22 22:22:48 -05:00
Mike Koch
ff355bdf31 #136 Update javascript / CSS 2015-02-22 22:22:48 -05:00
Mike Koch
4ec52a3b20 #136 Update language file 2015-02-22 22:22:48 -05:00
Mike Koch
023aba3442 #136 Update install_functions 2015-02-22 22:22:48 -05:00
Mike Koch
1632cb9c58 #136 Update install.php 2015-02-22 22:22:48 -05:00
Mike Koch
b669e4c0dc #136 Update ticket_list 2015-02-22 22:22:48 -05:00
Mike Koch
917ef469f5 #136 Update show_search_form 2015-02-22 22:22:47 -05:00
Mike Koch
1275fd981e #136 Update common 2015-02-22 22:22:47 -05:00
Mike Koch
107d02b198 #136 Update admin_functions 2015-02-22 22:22:47 -05:00
Mike Koch
17b714c97e #136 Update service_messages 2015-02-22 22:22:47 -05:00
Mike Koch
7cf8f53109 #136 Update reports 2015-02-22 22:22:47 -05:00
Mike Koch
dcff56a6f6 #136 Update password.php 2015-02-22 22:22:47 -05:00
Mike Koch
4dc9697783 #136 Update manage_knowledgebase 2015-02-22 22:22:47 -05:00
Mike Koch
78f20cf66e #136 Update knowledgebase_private 2015-02-22 22:22:47 -05:00
Mike Koch
ec02ea41e3 #136 Update admin index.php 2015-02-22 22:22:47 -05:00
Mike Koch
5025b44a55 #136 Update delete_tickets 2015-02-22 22:22:47 -05:00
Mike Koch
d0fbcf9b27 #136 Update change_status 2015-02-22 22:22:47 -05:00
Mike Koch
fa17916280 #136 Update admin_ticket 2015-02-22 22:22:46 -05:00
Mike Koch
83d65b0a37 #136 Update admin_settings_save 2015-02-22 22:22:46 -05:00
Mike Koch
b842fba2f2 #136 Update admin_settings 2015-02-22 22:22:46 -05:00
Mike Koch
61ec7728c4 Squashed commits:
[9157ee5] squish with version change
[de99bb5] squish with version only changes
[a9954fa] squish with version commit
[f67c9c4] #136 Update print
[032dbfc] #136 Update submit_ticket
[5a41ae9] squish with version commit
[9dc287b] squish with version commit
2015-02-22 22:22:46 -05:00
Mike Koch
50df4767ef Closes #133/#134 - Set status when creating ticket, set correct language for ticket's user 2015-02-19 21:48:16 -05:00
Mike Koch
1b5d4680b6 Merge pull request #131 from mkoch227/master-2-6-0
Update to Mods for HESK 2.0.0 and HESK 2.6.0 beta 1
2015-02-07 16:20:34 -05:00
Mike Koch
fd5e5e6ee5 Show date on ticket list 2015-02-07 15:53:33 -05:00
Mike Koch
603a6bc1de Update README.md 2015-02-05 21:16:34 -05:00
Mike Koch
26c61303f0 Converted README to markdown 2015-02-05 21:13:54 -05:00
Mike Koch
52b4971439 Update README.md 2015-02-05 20:59:15 -05:00
Mike Koch
6d7c1365b0 Update settings file to default 2015-02-05 20:57:22 -05:00
Mike Koch
023ccd505f Update install file and version number 2015-02-05 20:54:04 -05:00
Mike Koch
4b91ff12bc More UI updates 2015-02-05 20:39:49 -05:00
Mike Koch
ee5acad97a Fix some install stuff. Everything appears to be working! 2015-02-05 20:39:43 -05:00
Mike Koch
bda53ff143 Basic way of showing installation is done is implemented 2015-02-05 00:02:15 -05:00
Mike Koch
9d2283ecf7 Wire up migrations and actual database transactions. Things are looking good! 2015-02-04 23:51:12 -05:00
Mike Koch
ec606341f3 Some more changes 2015-02-04 22:03:30 -05:00
Mike Koch
a9713886d8 Making some more progress on AJAX-driven install 2015-02-04 11:00:30 -05:00
Mike Koch
fe1c483b1f Append to console what is going on during install 2015-02-03 00:21:06 -05:00
Mike Koch
7ee62a188d More work on installation UX updates 2015-02-02 22:15:44 -05:00
Mike Koch
55857cdbe9 More progress on new/improved installation 2015-02-01 22:17:51 -05:00
Mike Koch
e3c138130b #124 Try to auto-detect version 2015-02-01 15:30:31 -05:00
Mike Koch
c8c33d55d1 Restyle the updateModsForHesk page a bit 2015-02-01 11:39:51 -05:00
Mike Koch
90083c1c51 Fix installation page UI 2015-02-01 10:42:45 -05:00
Mike Koch
55dc1accde #128 Update Bootstrap and Boostrap-RTL 2015-02-01 10:35:26 -05:00
Mike Koch
4528a22ce2 #127 Update FontAwesome to 4.3.0 2015-02-01 10:28:23 -05:00
Mike Koch
326e6fc98a Default mailgun to "disabled"
Could otherwise cause confusion with users who have SMTP enabled
2015-02-01 01:00:39 -05:00
Mike Koch
f24cf39529 Look for ==, not ===
$_POST['s_smtp'] is a string, not an int.
2015-02-01 00:58:49 -05:00
Mike Koch
c532369fd4 Closes #106: Support HTML-formatted emails 2015-02-01 00:58:12 -05:00
Mike Koch
2a5421e4d5 Closes #126 Add Mailgun support 2015-01-30 00:36:31 -05:00
Mike Koch
c2d38c8a0a #126 / #106 Add Mailgun and HTML emails to settings page 2015-01-30 00:25:57 -05:00
Mike Koch
851da38297 #126 Partial UI update for Mailgun 2015-01-29 22:05:31 -05:00
Mike Koch
3bd35e47db #106 / #126 Add new settings to modsForHesk_settings.inc.php and update script 2015-01-28 22:05:07 -05:00
Mike Koch
daaaead1f7 #122 Patch up some syntax errors 2015-01-27 21:22:44 -05:00
Mike Koch
da259b984d #122 Patch up some files that weren't updated for custom statuses 2015-01-25 00:57:58 -05:00
Mike Koch
a0fdb1ba6b #121 Add missing key for some users if the key does not exist 2015-01-25 00:42:41 -05:00
Mike Koch
07b71d5092 Update version number and add update success message if no IP/email bans 2015-01-25 00:42:27 -05:00
Mike Koch
a94d300cc5 #105 Honor the ticket's language field when setting languages for emails 2015-01-23 00:30:46 -05:00
Mike Koch
c184cc3c1b #105 Allow staff to indicate language when creating ticket and when editing 2015-01-23 00:14:23 -05:00
Mike Koch
1aeb19539f Closes #118 Fix critical XSS vulnerability 2015-01-22 23:40:09 -05:00
Mike Koch
aa051b76e8 #120 Updated ticket templates styling 2015-01-22 22:12:30 -05:00
Mike Koch
6c8b0491c3 #119 Fix IDs 2015-01-22 20:29:14 -05:00
Mike Koch
fb75acbe4f #112 Default value to cc if not explicitly stated 2015-01-22 19:36:32 -05:00
Mike Koch
f290ac865b #112 Don't show cc/bcc as the value if it's an email field 2015-01-22 19:36:19 -05:00
Mike Koch
6a5de96b7d #112 SMTP Cc/Bcc fields are working properly 2015-01-22 00:03:21 -05:00
Mike Koch
975037c29d #112 Add email custom field type
Still need to add it to email functions
2015-01-21 23:38:56 -05:00
Mike Koch
ed4dcdc54c #96 Improve attachment viewing on ticket attachments
- Image thumbnail if the file type is a supported image extension
- Clicking on image shows modal with image.
2015-01-21 00:56:28 -05:00
Mike Koch
96a0269983 Finished some TODOs and related articles 2015-01-19 23:49:35 -05:00
Mike Koch
4aa23af770 Fix undefined variable 2015-01-19 23:18:40 -05:00
Mike Koch
0e45779856 Don't show the range if the "from" and "to" are the same 2015-01-19 11:24:17 -05:00
Mike Koch
470c8390f8 Use Javascript instead of PHP to redirect scripts 2015-01-19 11:17:50 -05:00
Mike Koch
a9d8d13ebd Allow users to migrate IP/email bans 2015-01-19 11:17:38 -05:00
Mike Koch
a26b25e36c Merge pull request #115 from mkoch227/update-to-hesk-2-6-0
Update to HESK 2.6.0
2015-01-19 10:49:18 -05:00
Mike Koch
5d35171332 Closes #113 Support Chrome v39's theme-color meta tag 2015-01-19 10:37:57 -05:00
Mike Koch
5538965a4e Closes #114 Move hesk_dateToString to common 2015-01-19 00:33:46 -05:00
Mike Koch
8fd8d2345b #110 Miscellaneous UI tweaks 2015-01-19 00:33:45 -05:00
Mike Koch
5da1782806 #110 Use the new progress bar for categories 2015-01-19 00:13:39 -05:00
Mike Koch
bdf44e0a16 #110 Update user management / profile pages 2015-01-18 23:58:14 -05:00
Mike Koch
f291aa4f67 #110 Use FontAwesome icon instead of .png 2015-01-17 15:41:38 -05:00
Mike Koch
756e60426d #110 Update admin_ticket to submit as any status, as well as cust. reply 2015-01-17 10:32:57 -05:00
Mike Koch
7bfe92747f #110 Restyle edit_note 2015-01-15 17:01:11 -05:00
Mike Koch
f00c386388 #110 Some admin_settings page tweaks to improve viewing 2015-01-15 16:53:01 -05:00
Mike Koch
5c3aea591b #110 Update notes section and ban icons 2015-01-15 16:33:15 -05:00
Mike Koch
91366130bc #110 Update change priority style 2015-01-14 21:10:48 -05:00
Mike Koch
cc778262a6 #110 Update manage_ticket_templates 2015-01-14 20:38:39 -05:00
Mike Koch
81187235f8 #110 Fix manage_canned submit text 2015-01-14 20:38:23 -05:00
Mike Koch
d603781334 #110 Show dropdown for ticket template / canned responses 2015-01-14 18:51:10 -05:00
Mike Koch
9cf1ef09d1 #110 Update password.php 2015-01-14 18:37:48 -05:00
Mike Koch
ed43191d68 Update the maintenance message style 2015-01-14 17:12:06 -05:00
Mike Koch
e8d0c9f901 Show maintenance mode / kb only above the navbar 2015-01-14 17:08:33 -05:00
Mike Koch
b658af1098 Fix some layout issues 2015-01-14 17:03:05 -05:00
Mike Koch
dd958b6946 #110 Update Service Messages page 2015-01-14 16:57:20 -05:00
Mike Koch
a185d1cf8e #110 Restyled banned_ips 2015-01-13 23:27:47 -05:00
Mike Koch
4ecf5c8d45 #110 Fix tab name and trailing </td> 2015-01-13 21:56:28 -05:00
Mike Koch
02b6778c37 #110 Restyle banned_emails 2015-01-13 21:45:35 -05:00
Mike Koch
8401543f8a #110 Update CSS and JS references 2015-01-13 19:29:47 -05:00
Mike Koch
45f41136b7 Update .gitignore for HESK 2.6.0 2015-01-13 17:02:37 -05:00
Mike Koch
c2303b1fea #92 Update hesk_style_RTL 2015-01-13 16:54:33 -05:00
Mike Koch
89f8bc4b08 #92 Update hesk_style.css 2015-01-13 16:52:00 -05:00
Mike Koch
ae1d7fc19b #92 Update files that are in MFH but didn't have any code changes 2015-01-12 23:24:45 -05:00
Mike Koch
d363fbc04a #92 Update ticket.php 2015-01-12 23:24:34 -05:00
Mike Koch
03ed2f3bde #92 Update suggest_articles.php 2015-01-12 23:18:00 -05:00
Mike Koch
12cc442b6b #92 Update submit_ticket.php 2015-01-12 23:16:12 -05:00
Mike Koch
b4b624edbf #92 Update reply_ticket.php 2015-01-12 23:10:18 -05:00
Mike Koch
9ce5698c2e #92 Update print.php 2015-01-12 23:08:32 -05:00
Mike Koch
6ad5fc39b6 #92 Update en text.php 2015-01-12 23:07:20 -05:00
Mike Koch
841b0eddff #92 Update knowledgebase.php 2015-01-12 23:05:12 -05:00
Mike Koch
cf680463f3 #92 Update install_functions 2015-01-12 22:24:09 -05:00
Mike Koch
a09551cc75 #92 Update install.php 2015-01-12 22:11:13 -05:00
Mike Koch
ff0ca2c99e #92 Update root index.php 2015-01-12 21:44:27 -05:00
Mike Koch
1c2e2cf483 #92 Update ticket_list 2015-01-12 21:00:20 -05:00
Mike Koch
6db9db68bd #92 Update show_search_form 2015-01-12 21:00:11 -05:00
Mike Koch
cd879f9898 #92 Update show_admin_nav.inc.php 2015-01-12 15:27:31 -05:00
Mike Koch
0c4e87b6e4 #92 Update print_tickets.inc.php 2015-01-12 15:27:05 -05:00
Mike Koch
53b86d2dbb #92 Update knowledgebase_functions.inc.php 2015-01-12 15:12:12 -05:00
Mike Koch
520fad4003 #92 Update header.inc.php 2015-01-12 15:12:00 -05:00
Mike Koch
cd333c2c6b #92 Update email_functions.inc.php 2015-01-12 12:49:09 -05:00
Mike Koch
bd5f9f5c0c #92 Update common.inc.php 2015-01-12 12:49:00 -05:00
Mike Koch
817f788496 #92 Update change_status.php 2015-01-12 12:48:48 -05:00
Mike Koch
688054c7ab #92 Update reports.php 2015-01-12 00:02:02 -05:00
Mike Koch
a83a32ec77 #92 Update options.php 2015-01-11 23:39:22 -05:00
Mike Koch
8e553fe61c #92 Update new_ticket.php 2015-01-11 23:36:19 -05:00
Mike Koch
a9cd48eb26 #92 Update manage_knowledgebase 2015-01-11 20:09:37 -05:00
Mike Koch
3ec6b91e80 #92 Update manage_categories 2015-01-11 19:36:14 -05:00
Mike Koch
73a160771a #92 Update manage_canned
Will add a dropdown to the navigation for ticket templates, rather than tabs
2015-01-11 18:44:41 -05:00
Mike Koch
30cd5b285e #92 Update mail.php 2015-01-11 17:41:23 -05:00
Mike Koch
aadfc573cd #92 Update lock.php 2015-01-11 17:36:05 -05:00
Mike Koch
723170496e #92 Update knowledgebase_private 2015-01-11 17:32:42 -05:00
Mike Koch
2cf6dcef88 #92 Update admin index.php 2015-01-11 17:16:16 -05:00
Mike Koch
94cea88ed9 #92 Update find_tickets 2015-01-11 17:01:42 -05:00
Mike Koch
663ad4728a #92 Update export 2015-01-11 17:01:36 -05:00
Mike Koch
86c1980108 #92 Update edit_post 2015-01-11 16:35:20 -05:00
Mike Koch
4eb9d2b47f #92 Update delete_tickets 2015-01-11 16:27:48 -05:00
Mike Koch
bbe69f8f83 #92 Update change_status.php (admin) 2015-01-11 16:18:14 -05:00
Mike Koch
8d5cfb9128 #92 Mostly updated admin_ticket
Still need to make some changes per issue #110
2015-01-11 11:45:56 -05:00
Mike Koch
78e5d11384 #92 Update admin_submit_ticket 2015-01-10 23:58:31 -05:00
Mike Koch
d45c2d5ab9 #92 Update admin_settings_save.php 2015-01-10 23:56:09 -05:00
Mike Koch
f5f02d4200 #92 Update admin_settings.php 2015-01-10 16:31:21 -05:00
Mike Koch
704236ee31 Merge pull request #109 from mkoch227/remove-2-6-0-features
Remove features that will be in HESK 2.6.0
2015-01-09 14:27:25 -05:00
Mike Koch
333789961e #88 Remove IP / email bans function 2015-01-09 14:17:15 -05:00
Mike Koch
b886eeedde #88 Remove customer email notifications profile setting 2015-01-08 23:34:15 -05:00
Mike Koch
59167aff66 #88 Remove dynamic ticket dashboard columns 2015-01-08 22:05:56 -05:00
Mike Koch
41030daad0 #88 Remove email customer on ticket closed feature 2015-01-08 21:16:59 -05:00
Mike Koch
63ed75c7ef #88 Remove edit note functionality 2015-01-08 18:24:35 -05:00
Mike Koch
e56bde8e2d #88 Remove attachments to notes feature 2015-01-08 17:28:40 -05:00
Mike Koch
8bf124fa8b Merge branch 'master' into remove-2-6-0-features
Conflicts:
	admin/admin_settings.php
	admin/admin_settings_save.php
	modsForHesk_settings.inc.php
2015-01-06 00:03:28 -05:00
Mike Koch
be48540bf1 Update README and install_functions 2015-01-04 23:39:30 -05:00
Mike Koch
dcf9f26295 Closes #103 Install errors should be displayed in the main install area, not in the panel 2015-01-04 23:36:21 -05:00
Mike Koch
6b1d746b7c Prep install files for 1.7.0 2015-01-04 23:32:10 -05:00
Mike Koch
4a410887f7 Miscellaneous settings page changes 2015-01-04 23:27:49 -05:00
Mike Koch
029e2ffa65 Closes #102 add MySQL version to settings page 2015-01-04 23:26:27 -05:00
Mike Koch
1a502e7a1e Only allow getTicketById 2015-01-02 22:05:40 -05:00
Mike Koch
d7876bfe50 Merge branch 'master' into web-services 2015-01-02 17:01:43 -05:00
Mike Koch
71fd581dde Tell user what to add to modsForHesk_settings.inc.php if script fails 2015-01-02 17:00:13 -05:00
Mike Koch
4871394265 Only add new settings if they aren't already there 2015-01-02 15:48:38 -05:00
Mike Koch
1a663324e3 Add verify email setting to update script 2015-01-02 12:02:38 -05:00
Mike Koch
b419d47c94 Closes #97 Fix status update script 2015-01-02 12:02:30 -05:00
Mike Koch
073ff3c765 Include multiselect with checkbox check 2015-01-02 00:57:51 -05:00
Mike Koch
351bb5c272 Add select/deselect all buttons to multiselect custom fields 2015-01-02 00:52:35 -05:00
Mike Koch
6e84309289 #30 Some fixes for verify email.
- Actually add the email to the verified_emails table
 - Pass in the $ticket variable to add the customer's name to the email
 - Actually call the correct email function.
2015-01-02 00:40:41 -05:00
Mike Koch
13953d5627 #30 Tell user to verify email if it hasn't been verified yet 2015-01-01 17:00:55 -05:00
Mike Koch
e339b90efd #30 Let the page actually save the setting 2015-01-01 16:14:24 -05:00
Mike Koch
88c8fe5967 #30 Send emails for validated tickets 2015-01-01 14:13:32 -05:00
Mike Koch
efce82d1d6 #30 Only validate emails if the help desk is configured to do so 2015-01-01 14:13:11 -05:00
Mike Koch
94b2b97994 #30 also output if no tickets were created 2015-01-01 12:29:10 -05:00
Mike Koch
9a0da6f16a #30 Use the email as the source of truth, not the # of tickets added 2015-01-01 12:19:06 -05:00
Mike Koch
7e22ce897c #30 Remove the incorrect comment 2015-01-01 12:15:25 -05:00
Mike Koch
47e4fc5f6a #30 Finish up the verification page 2015-01-01 12:14:31 -05:00
Mike Koch
222f1271e5 #30 Start on the verifyemail page.
Still need to do the form portion
2015-01-01 01:33:34 -05:00
Mike Koch
81fb037335 #30 Add email function for verify email 2015-01-01 00:33:31 -05:00
Mike Koch
418338c509 Closes #101 Edit post should support the new custom fields 2014-12-31 16:06:35 -05:00
Mike Koch
a762682ddb Closes #99 Only attempt to send email if ticket's email is not blank 2014-12-31 15:02:29 -05:00
Mike Koch
dfb07b979c Closes #98 Add email template for re-opening ticket assigned to diff user 2014-12-31 11:19:15 -05:00
Mike Koch
3d2616ba89 #30 If the email hasn't been verified, add it to the pending verification table 2014-12-30 00:29:37 -05:00
Mike Koch
e11f14e67c #30 Add pending_verification_emails table 2014-12-30 00:29:21 -05:00
Mike Koch
691deb7f67 #30 Submit ticket now checks the verified_emails table before creating 2014-12-30 00:18:30 -05:00
Mike Koch
75b0e8233f #30 Fix SQL 2014-12-30 00:04:38 -05:00
Mike Koch
3ec81da8d1 #30 Added SQL migrations to update script 2014-12-30 00:03:58 -05:00
Mike Koch
dde55cf4e1 #91 Support multilanguage custom fields 2014-12-29 00:11:53 -05:00
Mike Koch
aa4f8bb736 Fix indentation courtesy of PHPStorm 2014-12-29 00:05:36 -05:00
Mike Koch
94b5f65241 #91 Show respective text on custom fields page depending on MFH setting 2014-12-28 23:56:19 -05:00
Mike Koch
e2c6e2c179 #91 Save custom field multilanguage selection.
Also fixed popovers so they're aren't crammed in on the MFH settings section
2014-12-28 23:56:02 -05:00
Mike Koch
a003a9d89f #91 Some UI updates for multilanguage custom field support 2014-12-28 21:41:55 -05:00
Mike Koch
16606f75b9 #91 Add UI setting for enabling language file custom fields 2014-12-28 12:03:38 -05:00
Mike Koch
69a514a057 #91 Multiselect custom field now working 2014-12-28 00:59:16 -05:00
Mike Koch
2b234e8e1d #91 Finished date custom fields 2014-12-28 00:50:35 -05:00
Mike Koch
b449953950 #91 Dates must be in YYYY-MM-DD format
To prevent any ambiguous M/D/Y vs D/M/Y dates
2014-12-27 23:57:46 -05:00
Mike Koch
602d9c6c27 #91 Use Bootstrap datepicker instead of jQuery UI 2014-12-27 22:25:20 -05:00
Mike Koch
f9590fe67c #91 add date/multiselect to before/after for both pages 2014-12-27 22:24:58 -05:00
Mike Koch
e1880316d7 #91 Actually store the actual timestamp from the date entered 2014-12-27 22:24:36 -05:00
Mike Koch
5941bf7e35 #91 Use jQuery UI's date picker rather than HTML 5 date field
To ensure cross-browser compatibility
2014-12-24 01:47:05 -05:00
Mike Koch
f7064ed399 #91 Add jQuery UI 2014-12-24 01:46:39 -05:00
Mike Koch
085d1b6d22 Multiselect is already working 2014-12-22 00:47:30 -05:00
Mike Koch
e943e44f29 #91 Support multi-select and date custom fields on new ticket page (admin) 2014-12-22 00:47:30 -05:00
Mike Koch
50f5ce4596 #91 Add new custom field options to the array of possible choices 2014-12-22 00:47:29 -05:00
Mike Koch
46e09d618c #91 Add options text for the new custom field types 2014-12-21 23:57:14 -05:00
Mike Koch
73be89c472 #91 Add new custom field options to settings dropdown 2014-12-21 23:41:56 -05:00
Mike Koch
23b68707ec Closes #93 Show the language dropdown on the header 2014-12-14 23:53:06 -05:00
Mike Koch
1ae552f02a Closes #90 Fix the redirect to updateTo1-6-1 2014-12-14 23:42:49 -05:00
Mike Koch
773837d6f3 Revert "Revert the removal of some features...for now"
This reverts commit 0924dd5cc88cf33b9a459f1f0e8b57601698d367.
2014-12-14 23:38:26 -05:00
Mike Koch
0924dd5cc8 Revert the removal of some features...for now
This reverts commit f61c05ac34f3ebf0067de022a30c88564846b4dc.
2014-12-14 23:37:30 -05:00
Mike Koch
21781b20c7 Closes #89 selected from wrong table hame 2014-12-08 21:14:12 -05:00
Mike Koch
f61c05ac34 #88 Remove WHOIS lookup capabilities 2014-12-07 00:07:59 -05:00
Mike Koch
16fc6dea86 #88 Remove maintenance mode feature 2014-12-07 00:04:15 -05:00
Mike Koch
4dc767855a Update install file 2014-12-03 07:16:28 -05:00
Mike Koch
8d81ed5ebd Update version number 2014-12-03 07:14:15 -05:00
Mike Koch
8d3a66ded8 Fix version number retrieval for PHP versions before 5.5 2014-12-03 07:02:58 -05:00
Mike Koch
4b0a40ceaa Fix demo mode for the MFH demo site 2014-11-29 23:59:25 -05:00
Mike Koch
8ed533ecad Forgot to rename JavaScript file 2014-11-29 22:14:13 -05:00
Mike Koch
d26ed0bac1 Run the query before hiding specific fields in demo mode 2014-11-29 22:10:57 -05:00
Mike Koch
f339dbc2ba Wrap each link an <li> tag 2014-11-29 21:51:07 -05:00
Mike Koch
6d7a075d5b Fix link and text.
How did I miss this for so long???
2014-11-29 21:35:11 -05:00
Mike Koch
33ec8ac79a Hopefully making the installation script easier to run 2014-11-29 21:28:51 -05:00
Mike Koch
3aa10dfc43 Updated version numbers 2014-11-29 21:03:50 -05:00
Mike Koch
41ad95ff89 Update README.md 2014-11-29 20:37:44 -05:00
Mike Koch
1df1dfab48 Update README for v1.6.0 2014-11-29 15:13:45 -05:00
Mike Koch
2d7bfaf3d2 Closes #85 Version number now driven via database 2014-11-29 14:32:43 -05:00
Mike Koch
a8a930391e #85 Create migrations to create settings table 2014-11-29 14:25:45 -05:00
Mike Koch
ed6a0a9b7c #85 Remove version number from settings file 2014-11-29 14:18:03 -05:00
Mike Koch
64f6be511c Closes #83 now use Mods for Hesk instead of NuMods 2014-11-29 14:13:00 -05:00
Mike Koch
bdd5402a2e Closes #67 Finished deleting attachments for notes 2014-11-29 00:07:20 -05:00
Mike Koch
a1f7af11fc #67 Note attachments can now be downloaded 2014-11-28 23:58:25 -05:00
Mike Koch
e293aa2e17 Ignore the attachments directory 2014-11-28 22:21:20 -05:00
Mike Koch
2a9219cf25 #67 Partial implementation of adding attachments to the notes view
Still has things to fix and need to add deleting attachments
2014-11-28 22:17:47 -05:00
Mike Koch
65a80089c0 #67 Wired up part of the UI. Still need to add section to view attachments 2014-11-27 11:14:59 -05:00
Mike Koch
f904afe21f #67 Write migration scripts for attachments for notes 2014-11-27 10:48:26 -05:00
Mike Koch
e84d9f3229 Closes #68: Notes can be edited 2014-11-27 01:19:30 -05:00
Mike Koch
26cfe83953 Closes #84: 'can_change_notification_settings' now respected by profile page 2014-11-25 00:13:22 -05:00
Mike Koch
ad4fee1eb3 #84 Wired up the UI for changing notification setting permissions
Only non-admins can be restricted from changing notifications. Admins still can change freely
2014-11-24 23:54:57 -05:00
Mike Koch
e6ff3d2514 #80 Added migration script for current 1.6.0 changes 2014-11-24 23:25:06 -05:00
Mike Koch
c295201f52 #80 Move pre-1.4.0 scripts to freshInstall file 2014-11-24 23:24:53 -05:00
Mike Koch
855b66b1f3 Updated note email text 2014-11-24 23:07:56 -05:00
Mike Koch
db34f581d0 Update README.md 2014-11-24 21:58:39 -05:00
Mike Koch
6caaead890 Closes #66 Update the UI to allow users to change note emails 2014-11-24 21:57:10 -05:00
Mike Koch
3d4c0a99b7 #66 Business Logic portion of emails to admins are done.
Still need to add the option to the edit user / profile page
2014-11-24 21:46:08 -05:00
Mike Koch
219b722917 Closes #74: A new ticket can be modeled after an existing ticket
A dropdown on creation was not feasible, but this works just as well and can be used outside of HESK
2014-11-23 22:35:09 -05:00
Mike Koch
8915114b42 Closes #63 open links in tickets in new tab / window
Typically, users should be given the ability to open links in the same window. However, according to HTML5 specifications, the _blank target attribute is now permitted for specific use cases. Opening external links, in my opinion, is a valid use case.
2014-11-23 15:31:53 -05:00
Mike Koch
83b4b16d48 Closes #73: Send email to customer when ticket closed 2014-11-23 00:30:35 -05:00
Mike Koch
f1f62cbe3c Closes #72: Condense height of green bar for customer 2014-11-22 20:53:18 -05:00
Mike Koch
473f0f905c #72 Condensed the height of the green bar for staff 2014-11-21 00:00:17 -05:00
Mike Koch
caa3e616de Added __latest.txt to .gitignore 2014-11-18 00:00:28 -05:00
Mike Koch
20760987b7 Closes #77 Fix print.php to properly format custom fields 2014-11-18 00:00:06 -05:00
Mike Koch
fabb910cfd Closes #78 Fix layout for ticket w/out customer priority showing 2014-11-17 23:58:48 -05:00
Mike Koch
ade760b3b3 Closes #82 The active flag is an enum value (string), not an integer 2014-11-17 23:56:12 -05:00
Mike Koch
e535f2fb4e Update README.md 2014-11-06 09:24:51 -05:00
Mike Koch
aa2e74a92a Closes #79: Added missing SQL statement in update script 2014-11-02 10:45:35 -05:00
Mike Koch
86393193f4 Updated version number 2014-10-26 21:46:49 -04:00
Mike Koch
a490a6ee5a Closes #75: Current user cannot be deleted, and god admin can't be disabled 2014-10-26 21:18:21 -04:00
Mike Koch
7b210df019 Revert "#57 Finished UI portion of customer category specification feature"
This reverts commit ef5e75696ae550fd1746b6193f2a962d4d01764b.
2014-10-26 20:48:07 -04:00
Mike Koch
ef5e75696a #57 Finished UI portion of customer category specification feature 2014-10-26 14:58:05 -04:00
Mike Koch
a45d97a9db Closes #65: The god admin cannot be edited by other users 2014-10-26 11:19:01 -04:00
Mike Koch
eff111e583 #62 The DB should treat a 1 as "notify the customer", not 0 2014-10-25 00:25:43 -04:00
Mike Koch
95c89c612a #62 Ticket screen now honors the email profile setting 2014-10-25 00:19:20 -04:00
Mike Koch
7c40c25cff #62 The send email property should be set to false by default 2014-10-25 00:14:15 -04:00
Mike Koch
2c03c30e61 #62 The profile page can now handle default settings for sending emails on replies 2014-10-25 00:14:03 -04:00
Mike Koch
1fa8e19f98 Missed some content 2014-10-25 00:06:19 -04:00
Mike Koch
de6136bf26 Fixed some SQL statements 2014-10-24 23:59:49 -04:00
Mike Koch
c4a50d10f7 Missed some content 2014-10-24 23:55:29 -04:00
Mike Koch
52cf5ab447 #59 Only pull back active users 2014-10-24 23:47:07 -04:00
Mike Koch
9c6436a27d #59 Don't show the deactivate icon for the current user 2014-10-24 23:46:03 -04:00
Mike Koch
ddd1a05f65 #59 Don't allow users to deactivate themselves 2014-10-24 23:43:10 -04:00
Mike Koch
c72c5054f0 #59 Contentified some text 2014-10-24 23:40:15 -04:00
Mike Koch
bee3b84855 #59 Active users are now manageable 2014-10-24 23:36:27 -04:00
Mike Koch
e14e5f1050 #59 Partial implementation of active users on the manage users page 2014-10-24 22:15:39 -04:00
Mike Koch
6c126ec78e #59 We check for an active user on login 2014-10-24 20:23:19 -04:00
Mike Koch
270a796090 #59 Now the admin ticket page filters out inactive users 2014-10-24 20:19:15 -04:00
Mike Koch
8f27ba2c48 #59 Mark all current users as active
Otherwise no one can log in
2014-10-24 20:18:13 -04:00
Mike Koch
8fca201ad8 Use an enum instead of an int 2014-10-24 20:13:31 -04:00
Mike Koch
fda266629f #59 Use an enum instead of a bit
PHP/MySQL treats the bit in a really strange way...it just never works right
2014-10-24 20:12:39 -04:00
Mike Koch
96f73211d9 Closes #61: Manage help desk settings can be toggled for non-admins and admins 2014-10-15 23:32:06 -04:00
Mike Koch
16da573a8f #61 Only allow those with access to the settings page to give others access 2014-10-15 22:43:20 -04:00
Mike Koch
3d6c11dd57 #61 Admins can now designate who can view the settings page 2014-10-15 22:09:56 -04:00
Mike Koch
a2c058ea16 Closes #64: The IP address is now a link to it's WHOIS record 2014-10-14 23:48:05 -04:00
Mike Koch
d8130cc442 Closes #70: Notes are now displayed underneath the green row
To keep consistent with the default HESK layout
2014-10-14 21:29:36 -04:00
Mike Koch
6c3237c58c #59: Added alter table statement for a user's active flag 2014-10-13 22:04:50 -04:00
Mike Koch
1ec604f94c Closes #54: Custom language text can now be loaded for each language 2014-10-13 21:31:06 -04:00
Mike Koch
473a307236 Closes #53: The column width for the label text is now larger 2014-10-12 20:20:29 -04:00
Mike Koch
bdbecd11e8 Closes #55: Email is no longer required on admin/edit_post.php 2014-10-12 17:11:44 -04:00
Mike Koch
18f9afb223 Closes #52: Contentified some hard-coded strings 2014-10-12 16:57:50 -04:00
Mike Koch
e6db35fadf Closes #56: Responsified the ticket table 2014-10-12 16:52:45 -04:00
Mike Koch
df847c7e18 Fixed update script for those who attempted the 1.4.0 installation 2014-09-28 10:24:36 -04:00
Mike Koch
16f7aedc97 Update version # 2014-09-28 10:17:32 -04:00
Mike Koch
eab42588fb Added additional queries to base installation script 2014-09-28 10:15:46 -04:00
Mike Koch
56612a4927 Updated version # 2014-09-28 10:14:33 -04:00
Mike Koch
1ad5d5c063 Fixed SQL query 2014-09-28 10:13:57 -04:00
Mike Koch
5f70187de0 Version 1.3.1 was never released 2014-09-28 01:12:53 -04:00
Mike Koch
511ff23d22 Update README.md 2014-09-28 01:03:44 -04:00
Mike Koch
616647e42a I never made 1.3.1 a release 2014-09-28 01:02:36 -04:00
Mike Koch
a05a56fd3e Updated version numbers 2014-09-28 00:58:54 -04:00
Mike Koch
77eb9188b6 Updated update scripts/files 2014-09-28 00:51:06 -04:00
Mike Koch
1855386878 Closes #39 - finished parent/child relationships 2014-09-28 00:07:25 -04:00
Mike Koch
3151ece7df #39 making more progress on parent/child relationships
Still need to update childs when merging/deleting tickets, and need to add the ability to assign its parent, and to delete a parent/child relationship
2014-09-27 22:14:49 -04:00
Mike Koch
a4fa98d010 #39 Ticket screen now shows parent/children of that ticket 2014-09-27 15:13:26 -04:00
Mike Koch
69f7636fa5 Closes #31 e-mail is no longer required for staff 2014-09-27 11:44:03 -04:00
Mike Koch
ea5947c6c1 Closes #50: Don't re-index statuses until after everything has been updated 2014-09-27 11:22:59 -04:00
Mike Koch
f000ebc729 #51 Fixed variable naming clash 2014-09-25 21:50:13 -04:00
Mike Koch
e045921e9f #29 Check the banned emails list for piped emails
We can't check IPs since they can't always be pulled from the email.
2014-09-25 21:32:33 -04:00
Mike Koch
7ede557b64 #29 IP / Email bans now are used on the submit ticket page.
Still need to do POP3 fetching / piping.
2014-09-25 21:11:53 -04:00
Mike Koch
6c25a38134 #29 Use ip2long / long2ip to convert IP addresses to easily compare 2014-09-25 21:11:20 -04:00
Mike Koch
26887979e1 #29 Now IP ranges and emails can be added to the banned tables thru the settings page 2014-09-24 23:48:00 -04:00
Mike Koch
7b3bc087b1 The UI for IP/Email bans is ready to go 2014-09-24 22:02:24 -04:00
Mike Koch
31d4eb3ee5 #29 Getting started on the IP/Email bans 2014-09-22 22:10:35 -04:00
Mike Koch
f43ce1c8d4 Partial update script to 1.4.0 2014-09-22 22:10:07 -04:00
Mike Koch
a34284f337 Updated some miscellaneous files. 2014-09-21 21:07:59 -04:00
Mike Koch
e86e61065a Closes #49: Add help text to all NuMods settings. 2014-09-21 01:28:54 -04:00
Mike Koch
a277ce1060 Use the settingsquestionmark class for all question marks 2014-09-21 01:22:27 -04:00
Mike Koch
77e0b01725 #49 NuMods settings can now be changed via the Settings page 2014-09-21 01:00:54 -04:00
Mike Koch
e357e62e0c #49 Getting started on the NuMods settings page 2014-09-15 22:20:24 -04:00
Mike Koch
b5361d683a Don't show the maintenance page when on the login screen 2014-09-14 01:40:58 -04:00
Mike Koch
bdf2460755 Closes #34: Very basic maintenance mode up and running 2014-09-14 01:36:37 -04:00
Mike Koch
187db3635e Closes #35: Autorefresh now working on the ticket dashboards! 2014-09-14 01:14:54 -04:00
Mike Koch
93a72804f9 #35 Refresh value must be 1000 or greater to prevent constant refreshes 2014-09-14 00:57:41 -04:00
Mike Koch
9f78ed41fd #35 Ticket dashboard now shows autorefresh time 2014-09-14 00:55:28 -04:00
Mike Koch
daaca6c631 Fixed version # in language file 2014-09-14 00:48:12 -04:00
Mike Koch
97a4520d0b #35 removed irrelevant TODO 2014-09-14 00:44:19 -04:00
Mike Koch
e4744829ac #35 Update install scripts for auto-refresh 2014-09-14 00:44:06 -04:00
Mike Koch
b2b0004c49 #35 Added auto-refresh property to the users table 2014-09-12 00:02:20 -04:00
Mike Koch
4983d2a6d7 Closes #48: Custom fields now follow proper styling on the print page 2014-09-11 22:00:26 -04:00
Mike Koch
df15806e42 Closes #47: The panel now collapses to the correct size when there are 0 results. 2014-09-11 21:53:13 -04:00
Mike Koch
29aa70aab7 custom0 isn't a valid custom field 2014-09-11 21:52:44 -04:00
Mike Koch
84f6e91c0b Revert "Getting started on LDAP/Active Directory integration"
This reverts commit 98a7633cb64d778310702344d75bbf41213bbf24.
2014-09-10 20:28:22 -04:00
Mike Koch
30b4c2a908 Revert "Made some more progress on AD authentication"
This reverts commit 0e6bb7c2e4d9658551a6a78077374547067f2803.
2014-09-10 20:28:14 -04:00
Mike Koch
0e6bb7c2e4 Made some more progress on AD authentication 2014-09-10 18:42:09 -04:00
Mike Koch
98a7633cb6 Getting started on LDAP/Active Directory integration
I still have no clue if any of this works; I'm just using a code snippet to get started on this. Still need to LDAP escape the user string (don't want them sending in *!) and test the whole thing.
2014-09-09 22:12:46 -04:00
Mike Koch
cc055e3f12 Updated version number 2014-09-07 23:41:22 -04:00
Mike Koch
291b8fcf5b Shouldn't push the attachments file out in releases. 2014-09-07 23:41:13 -04:00
Mike Koch
fa705816c5 Only show login icon when icons are enabled 2014-09-07 23:41:00 -04:00
Mike Koch
364b2fdd91 #42 Show font icons on the navigation menus if setting is enabled 2014-09-07 23:36:50 -04:00
Mike Koch
666ffe7a77 Updated FontAwesome to 4.2.0 2014-09-07 23:28:51 -04:00
Mike Koch
48e5662def #42 Started on adding icons to areas of the help desk 2014-09-07 22:08:07 -04:00
Mike Koch
19fb152ba5 #26 EXPERIMENTAL support for right-to-left text direction 2014-09-07 21:42:47 -04:00
Mike Koch
820276c402 #46 The new ticket page uses a panel instead of a tabbed bar 2014-09-07 11:43:37 -04:00
Mike Koch
e99db41a69 Merge pull request #43 from waffle-iron/master
waffle.io Badge
2014-09-07 01:52:34 -04:00
Making GitHub Delicious.
6f74e81cde add waffle.io badge 2014-09-06 23:52:16 -06:00
Mike Koch
8398efa538 #25 Dashboard columns can now be added/removed via JavaScript! 2014-09-07 01:50:56 -04:00
Mike Koch
8cd7aebaae #24 the search tickets screen has been restyled 2014-09-06 22:19:59 -04:00
Mike Koch
835ad2acf7 Still a half-baked implementation. Jump to page is driving me nuts. 2014-09-03 22:07:30 -04:00
Mike Koch
de7ed0f1f3 Half-baked newish admin dashboard 2014-09-03 21:32:04 -04:00
Mike Koch
90ce8db424 #23 Now "change language to" no longer appears when multilang is off 2014-08-09 23:49:10 -04:00
Mike Koch
27ba6ebc78 The admin_ticket screen is now fully responsive. Woohoo! 2014-08-09 22:09:11 -04:00
Mike Koch
0f648ddac2 Removed the excess margin on the PM page 2014-08-09 20:30:20 -04:00
Mike Koch
7fa2b81e29 Status section is now a panel, and padded tabbed sections 2014-08-09 20:29:21 -04:00
Mike Koch
2029931974 Now the export page uses a panel instead of a tabbed menu 2014-08-09 19:52:35 -04:00
Mike Koch
9078b6b2ea Now the reports page uses a panel instead of a tabbed container 2014-08-09 19:46:36 -04:00
Mike Koch
08f6678fe8 Knowledgebase page now uses a panel instead of tabbed bar 2014-08-09 16:22:58 -04:00
Mike Koch
4b0495fdd5 Now the managed canned responses page uses a panel 2014-08-09 16:13:41 -04:00
Mike Koch
6439916bac Fixed padding on categories tabbed content
These will not be converted since they are actually useful
2014-08-09 16:06:02 -04:00
Mike Koch
4d5e7dcbe1 Now the manage users page utilizes a panel instead of a tabbed bar 2014-08-09 16:00:36 -04:00
Mike Koch
ab8ac0edd3 Install pages updated to panels 2014-08-09 00:23:16 -04:00
Mike Koch
1ceea3d20b Knowledgebase page now uses panel instead of tabs 2014-08-09 00:14:54 -04:00
Mike Koch
6abbb047b7 Now the ticket input page uses a panel instead of a hacky tab 2014-08-09 00:12:38 -04:00
Mike Koch
90ee80c5cc The ticket page is now more responsive 2014-08-09 00:09:35 -04:00
Mike Koch
80d68ae01d Got a bit further in the responsive green row. Still some work to do. 2014-08-08 22:01:46 -04:00
Mike Koch
c295f081c5 Starting to work on some more responsive layout for ticket.php 2014-08-07 22:06:27 -04:00
Mike Koch
e6d1d715da Now the index page uses a panel instead of a hacky tab bar.
It is also more responsive.
2014-08-06 21:57:18 -04:00
Mike Koch
680a2a16b1 Added update for v1.2.4 2014-08-05 20:48:20 -04:00
Mike Koch
06adabf887 Updated .gitignore 2014-08-05 20:37:36 -04:00
Mike Koch
3883c93229 Updated README 2014-08-05 20:27:34 -04:00
Mike Koch
b40f3f1c78 Updated HESK to 2.5.5 (which is also NuMods 1.2.4) 2014-08-05 20:26:47 -04:00
Mike Koch
407e93fe28 Updated version numbers on license header 2014-08-05 20:26:33 -04:00
Mike Koch
a4e1623b0a Update README.md 2014-07-27 20:14:15 -04:00
Mike Koch
ed94097161 Updated version # and GA tracking 2014-07-23 20:13:43 -04:00
Mike Koch
2964ba6975 #22 Now new tickets can be created, even with multiple pages 2014-07-23 19:43:43 -04:00
Mike Koch
a959e39881 renamed index.php to getTicket 2014-07-13 11:22:38 -04:00
Mike Koch
153201aea4 Merge branch 'master' into web-services 2014-07-13 10:43:24 -04:00
Mike Koch
6dac91ede5 Some code cleanup 2014-07-13 10:42:59 -04:00
Mike Koch
dc57fceab3 #20 Fixed multi-language support 2014-07-13 01:04:11 -04:00
Mike Koch
3d235918ea Now tickets can be retreived by Tracking ID via REST 2014-07-07 09:53:56 -04:00
Mike Koch
bff8f03887 Removed unused reference 2014-07-06 21:49:03 -04:00
Mike Koch
1f1c6071bb Set variable types and return just IDs; other repos will have mappings 2014-07-06 19:20:30 -04:00
Mike Koch
8e48a431af Switched getTicketForId to a static method; no more need for singleton 2014-07-06 19:20:07 -04:00
Mike Koch
71911acc35 Merge branch 'old-web-services' into web-services
Conflicts:
	README.md
2014-07-06 18:47:04 -04:00
Mike Koch
555b532bb2 Merge branch 'hesk-ui' into web-services
Conflicts:
	README.md
2014-06-10 21:47:10 -04:00
Mike Koch
01ccbde4f3 added name for clarity 2014-06-08 11:46:34 -04:00
Mike Koch
1fd00cf40e fixed name 2014-06-08 11:46:07 -04:00
Mike Koch
c63ca99ccc Updated README.md 2014-06-08 11:45:33 -04:00
Mike Koch
c204e925bb Now return true/false for archived/locked 2014-06-08 11:34:34 -04:00
Mike Koch
9435de19d5 Made a public function that should be private private 2014-06-08 11:30:21 -04:00
Mike Koch
34163f2c1d Now more specific/readable information is returned 2014-06-08 11:25:40 -04:00
Mike Koch
404aea6318 Ticket ID to retrieve is no longer hard-coded 2014-06-08 10:52:51 -04:00
Mike Koch
dd19b27b43 Merge branch 'hesk-ui' into web-services 2014-06-08 10:47:36 -04:00
Mike Koch
9654fd38cb Created hacky web service to return basic ticket information 2014-06-08 01:12:33 -04:00
635 changed files with 93227 additions and 23370 deletions

143
.gitignore vendored
View File

@ -1,26 +1,26 @@
# Mods for HESK-specific files
api/vendor
api/Tests/integration_test_mfh_settings.php
# HESK Files
admin/admin_suggest_articles.php
admin/archive.php
admin/assign_owner.php
admin/delete_tickets.php
admin/custom_statuses.php
admin/email_templates.php
admin/generate_spam_question.php
admin/move_category.php
admin/options.php
admin/priority.php
admin/resend_notification.php
admin/test_connection.php
attachments/index.htm
docs/changelog.html
docs/docs_style.css
docs/index.html
docs/quick-guide.html
docs/step-by-step-guide.html
download_attachment.php
cache/
docs/
file_limits.php
footer.txt
head.txt
header.txt
hesk_javascript_v25.js
hesk_settings.inc.php
img/add_article.png
img/add_category.png
img/anonymize.png
img/article_text.png
img/autoassign_off.png
img/autoassign_on.png
@ -33,10 +33,13 @@ img/clip.png
img/code.png
img/code_off.png
img/delete.png
img/delete_off.png
img/delete_ticket.png
img/edit.png
img/email.png
img/error.png
img/existingticket.png
img/export.png
img/flag_critical.png
img/flag_high.png
img/flag_low.png
@ -82,6 +85,7 @@ img/lock.png
img/login.png
img/mail.png
img/manage.png
img/menu.png
img/minus.gif
img/minusbottom.gif
img/minustop.gif
@ -120,6 +124,7 @@ img/print.png
img/private.png
img/public.png
img/reload.png
img/refresh.png
img/roundcornersb.jpg
img/roundcornerslb.jpg
img/roundcornerslm.jpg
@ -149,9 +154,7 @@ img/tag_off.png
img/unlock.png
img/vertical.jpg
img/view.png
inc/admin_functions.inc.php
inc/assignment_search.inc.php
inc/attachments.inc.php
inc/calendar/img/cal.gif
inc/calendar/img/next_mon.gif
inc/calendar/img/next_year.gif
@ -164,10 +167,11 @@ inc/calendar/tcal.js
inc/calendar/tcal.php
inc/database.inc.php
inc/database_mysqli.inc.php
inc/email_functions.inc.php
inc/footer.inc.php
inc/htmlpurifier
inc/index.htm
inc/jscolor/
inc/mail/email_parser.php
inc/mail/hesk_imap.php
inc/mail/hesk_pipe.php
inc/mail/hesk_pop3.php
inc/mail/index.htm
@ -183,8 +187,6 @@ inc/mail/sasl/ntlm_sasl_client.php
inc/mail/sasl/plain_sasl_client.php
inc/mail/sasl/sasl.php
inc/mail/smtp.php
inc/pipe_functions.inc.php
inc/posting_functions.inc.php
inc/prepare_ticket_export.inc.php
inc/prepare_ticket_search.inc.php
inc/print_group.inc.php
@ -194,69 +196,69 @@ inc/recaptcha/recaptchalib.php
inc/reporting_functions.inc.php
inc/secimg.inc.php
inc/setup_functions.inc.php
inc/statuses.inc.php
inc/tabs/index.htm
inc/tabs/tabber-minimized.js
inc/tabs/tabber.css
inc/timer/hesk_timer.js
inc/timer/index.htm
inc/tiny_mce/3.5.10/langs/en.js
inc/tiny_mce/3.5.10/license.txt
inc/tiny_mce/3.5.10/themes/advanced/about.htm
inc/tiny_mce/3.5.10/themes/advanced/anchor.htm
inc/tiny_mce/3.5.10/themes/advanced/charmap.htm
inc/tiny_mce/3.5.10/themes/advanced/color_picker.htm
inc/tiny_mce/3.5.10/themes/advanced/editor_template.js
inc/tiny_mce/3.5.10/themes/advanced/image.htm
inc/tiny_mce/3.5.10/themes/advanced/img/colorpicker.jpg
inc/tiny_mce/3.5.10/themes/advanced/img/flash.gif
inc/tiny_mce/3.5.10/themes/advanced/img/icons.gif
inc/tiny_mce/3.5.10/themes/advanced/img/iframe.gif
inc/tiny_mce/3.5.10/themes/advanced/img/pagebreak.gif
inc/tiny_mce/3.5.10/themes/advanced/img/quicktime.gif
inc/tiny_mce/3.5.10/themes/advanced/img/realmedia.gif
inc/tiny_mce/3.5.10/themes/advanced/img/shockwave.gif
inc/tiny_mce/3.5.10/themes/advanced/img/trans.gif
inc/tiny_mce/3.5.10/themes/advanced/img/video.gif
inc/tiny_mce/3.5.10/themes/advanced/img/windowsmedia.gif
inc/tiny_mce/3.5.10/themes/advanced/js/about.js
inc/tiny_mce/3.5.10/themes/advanced/js/anchor.js
inc/tiny_mce/3.5.10/themes/advanced/js/charmap.js
inc/tiny_mce/3.5.10/themes/advanced/js/color_picker.js
inc/tiny_mce/3.5.10/themes/advanced/js/image.js
inc/tiny_mce/3.5.10/themes/advanced/js/link.js
inc/tiny_mce/3.5.10/themes/advanced/js/source_editor.js
inc/tiny_mce/3.5.10/themes/advanced/langs/en.js
inc/tiny_mce/3.5.10/themes/advanced/langs/en_dlg.js
inc/tiny_mce/3.5.10/themes/advanced/link.htm
inc/tiny_mce/3.5.10/themes/advanced/shortcuts.htm
inc/tiny_mce/3.5.10/themes/advanced/skins/default/content.css
inc/tiny_mce/3.5.10/themes/advanced/skins/default/dialog.css
inc/tiny_mce/3.5.10/themes/advanced/skins/default/img/buttons.png
inc/tiny_mce/3.5.10/themes/advanced/skins/default/img/items.gif
inc/tiny_mce/3.5.10/themes/advanced/skins/default/img/menu_arrow.gif
inc/tiny_mce/3.5.10/themes/advanced/skins/default/img/menu_check.gif
inc/tiny_mce/3.5.10/themes/advanced/skins/default/img/progress.gif
inc/tiny_mce/3.5.10/themes/advanced/skins/default/img/tabs.gif
inc/tiny_mce/3.5.10/themes/advanced/skins/default/ui.css
inc/tiny_mce/3.5.10/themes/advanced/source_editor.htm
inc/tiny_mce/3.5.10/tiny_mce.js
inc/tiny_mce/3.5.10/tiny_mce_popup.js
inc/tiny_mce/3.5.10/utils/editable_selects.js
inc/tiny_mce/3.5.10/utils/form_utils.js
inc/tiny_mce/3.5.10/utils/mctabs.js
inc/tiny_mce/3.5.10/utils/validate.js
inc/tiny_mce/3.5.12/langs/en.js
inc/tiny_mce/3.5.12/license.txt
inc/tiny_mce/3.5.12/themes/advanced/about.htm
inc/tiny_mce/3.5.12/themes/advanced/anchor.htm
inc/tiny_mce/3.5.12/themes/advanced/charmap.htm
inc/tiny_mce/3.5.12/themes/advanced/color_picker.htm
inc/tiny_mce/3.5.12/themes/advanced/editor_template.js
inc/tiny_mce/3.5.12/themes/advanced/image.htm
inc/tiny_mce/3.5.12/themes/advanced/img/colorpicker.jpg
inc/tiny_mce/3.5.12/themes/advanced/img/flash.gif
inc/tiny_mce/3.5.12/themes/advanced/img/icons.gif
inc/tiny_mce/3.5.12/themes/advanced/img/iframe.gif
inc/tiny_mce/3.5.12/themes/advanced/img/pagebreak.gif
inc/tiny_mce/3.5.12/themes/advanced/img/quicktime.gif
inc/tiny_mce/3.5.12/themes/advanced/img/realmedia.gif
inc/tiny_mce/3.5.12/themes/advanced/img/shockwave.gif
inc/tiny_mce/3.5.12/themes/advanced/img/trans.gif
inc/tiny_mce/3.5.12/themes/advanced/img/video.gif
inc/tiny_mce/3.5.12/themes/advanced/img/windowsmedia.gif
inc/tiny_mce/3.5.12/themes/advanced/js/about.js
inc/tiny_mce/3.5.12/themes/advanced/js/anchor.js
inc/tiny_mce/3.5.12/themes/advanced/js/charmap.js
inc/tiny_mce/3.5.12/themes/advanced/js/color_picker.js
inc/tiny_mce/3.5.12/themes/advanced/js/image.js
inc/tiny_mce/3.5.12/themes/advanced/js/link.js
inc/tiny_mce/3.5.12/themes/advanced/js/source_editor.js
inc/tiny_mce/3.5.12/themes/advanced/langs/en.js
inc/tiny_mce/3.5.12/themes/advanced/langs/en_dlg.js
inc/tiny_mce/3.5.12/themes/advanced/link.htm
inc/tiny_mce/3.5.12/themes/advanced/shortcuts.htm
inc/tiny_mce/3.5.12/themes/advanced/skins/default/content.css
inc/tiny_mce/3.5.12/themes/advanced/skins/default/dialog.css
inc/tiny_mce/3.5.12/themes/advanced/skins/default/img/buttons.png
inc/tiny_mce/3.5.12/themes/advanced/skins/default/img/items.gif
inc/tiny_mce/3.5.12/themes/advanced/skins/default/img/menu_arrow.gif
inc/tiny_mce/3.5.12/themes/advanced/skins/default/img/menu_check.gif
inc/tiny_mce/3.5.12/themes/advanced/skins/default/img/progress.gif
inc/tiny_mce/3.5.12/themes/advanced/skins/default/img/tabs.gif
inc/tiny_mce/3.5.12/themes/advanced/skins/default/ui.css
inc/tiny_mce/3.5.12/themes/advanced/source_editor.htm
inc/tiny_mce/3.5.12/tiny_mce.js
inc/tiny_mce/3.5.12/tiny_mce_popup.js
inc/tiny_mce/3.5.12/utils/editable_selects.js
inc/tiny_mce/3.5.12/utils/form_utils.js
inc/tiny_mce/3.5.12/utils/mctabs.js
inc/tiny_mce/3.5.12/utils/validate.js
inc/treemenu/TreeMenu.php
inc/treemenu/index.htm
inc/users_online.inc.php
inc/zip/Zip.php
inc/zip/index.htm
inc/zip/pclzip.lib.php
install/hesk.png
install/update.php
language/en/help_files
language/en/emails/category_moved.txt
language/en/emails/forgot_ticket_id.txt
language/en/emails/index.htm
language/en/emails/new_note.txt
language/en/emails/new_pm.txt
language/en/emails/new_reply_by_customer.txt
language/en/emails/new_reply_by_staff.txt
@ -264,9 +266,18 @@ 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
print_sec_img.php
rate.php
readme.html
robots.txt
.idea/
attachments/__latest.txt
/attachments
img/ban.png
img/banned.png
img/ico_tools.png
ip_whois.php
language/en/emails/reset_password.txt
language/en/help_files/ticket_list.html

90
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,90 @@
stages:
- validate
- test
- package
before_script:
- bash ci/docker_install.sh > /dev/null
validate:7.2:
image: php:7.2
stage: validate
script:
- bash ci/php_lint.sh ./
validate:7.1:
image: php:7.1
stage: validate
script:
- bash ci/php_lint.sh ./
validate:7.0:
image: php:7.0
stage: validate
script:
- bash ci/php_lint.sh ./
validate:5.6:
image: php:5.6
stage: validate
script:
- bash ci/php_lint.sh ./
validate:5.5:
image: php:5.5
stage: validate
script:
- bash ci/php_lint.sh ./
validate:5.4:
image: php:5.4
stage: validate
script:
- bash ci/php_lint.sh ./
validate:5.3:
image: php:5.3
stage: validate
script:
- bash ci/php_lint.sh ./
test:7.1:
image: php:7.1
stage: test
script:
- cd api
- php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
- php composer-setup.php
- php -r "unlink('composer-setup.php');"
- php composer.phar update
- php composer.phar install
- cd Tests
- phpunit
test:7.2:
image: php:7.2
stage: test
script:
- cd api
- php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
- php composer-setup.php
- php -r "unlink('composer-setup.php');"
- php composer.phar update
- php composer.phar install
- cd Tests
- phpunit
package:
image: tetraweb/php
when: manual
stage: package
script:
- apt-get update
- apt-get install zip unzip
- cd api
- composer install --no-dev
- cd ../ci
- bash build_zip.sh
artifacts:
paths:
- release.zip

27
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,27 @@
# Contributing to Mods for HESK
So you want to contribute to Mods for HESK? Awesome! However, there are a few guidelines that need to be followed so the project can be as easy to maintain as possible.
## Submitting an issue
If all you are doing is submitting an issue, please check if your "issue" qualifies as a GitLab issue:
- **Feature Requests:** Feature requests are now being recorded at the Mods for HESK [UserVoice page](https://mods-for-hesk.uservoice.com/forums/254758-general). Please do not open these types of issues on GitLab. Issues opened that are "feature requests" will be closed.
- **Translations:** Translations are now being recorded at the official Mods for HESK [website](https://mods-for-hesk.mkochcs.com/download.php). Please do not open these types of issues on GitLab. Issues opened that pertain to submitting new translations will be closed.
- **Bugs:** Yes, please open these types of issues here. :grinning:
## Getting Started
If you have already completed any of these steps in the past (such as creating a GitLab account), you can skip the respective step.
- Make sure you have a [GitLab account](https://gitlab.com/users/sign_in)
- Fork the repository on GitLab
## Making Changes
- Create a feature branch from where to base your work off of
- This will be the `master` branch in most cases
- *Please do not work off of the `master` branch directly*
- Make commits of logical units.
- For example, if you add 10 new features, please make at least 10 commits (1 per feature). This way, if a feature needs to be removed, it will be as easy as reverting a commit, rather than removing all 10.
- Check for unnecessary whitespace using the `git diff --check` command. If there is trailing whitespace, your pull request will be denied.
## Submitting Changes
- Push your changes to a topic branch in your fork of the repository
- Submit a pull request to the official Mods for HESK repository (mike-koch/Mods-for-HESK)
- The owner of Mods for HESK will then inspect and test the code in the pull request. Feedback will be given via GitLab comments.
- The owner of Mods for HESK expects responses within two weeks of the original comment. If there is no feedback within that time range, the pull request will be considered abandoned and subsequently will be closed.

23
LICENSE Normal file
View File

@ -0,0 +1,23 @@
NOTE: This license only applies to Mods for HESK. It does not apply to HESK.
The MIT License (MIT)
Copyright (c) 2015 Michael Koch
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

126
README.md
View File

@ -1,68 +1,82 @@
[![Analytics](https://ga-beacon.appspot.com/UA-49251479-1/hesk/README)](https://github.com/mkoch227/Hesk)
## [Mods for HESK](http://mods-for-hesk.mkochcs.com) [![Number of Downloads](https://img.shields.io/github/downloads/mkoch227/Mods-for-HESK/latest/total.svg)](https://www.github.com/mkoch227/Mods-for-HESK/releases) [![Current Release](https://img.shields.io/github/release/mkoch227/Mods-for-HESK.svg)](https://www.github.com/mkoch227/Mods-for-HESK/releases) [![Project Status](https://img.shields.io/badge/status-maintained-brightgreen.svg)](https://www.github.com/mkoch227/Mods-for-HESK)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/mkoch227/Mods-for-HESK/blob/master/LICENSE)
[![Join the chat at https://gitter.im/mkoch227/Mods-for-HESK](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mkoch227/Mods-for-HESK?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
<h2>NuMods v1.2.1</h2>
Mods for HESK is a set of modifications for [HESK](https://www.hesk.com) v2.7.x, a free and popular helpdesk solution.
This branch contains all files modified from the base version of HESK to become NuMods, a set of modifications for HESK v2.x
## Features
<table>
<tr>
<td>
<ul>
<li>Calendar planning module</li>
<li>A new, responsive user interface</li>
<li>Ability to create custom ticket statuses</li>
<li>Right-to-left text direction</li>
<li>Designate parent/child relationships for tickets</li>
<li>Ticket dashboard automatic refresh</li>
<li>HTML-formatted e-mails</li>
<li>Mailgun API support</li>
<li>Customer email verifications</li>
<li>Custom fields in multiple languages</li>
<li>Create new ticket based on previous ticket</li>
<li>Admins can restrict users from modifying notification settings</li>
<li>Client-side form validation</li>
</ul>
</td>
<td>
<ul>
<li>Email template editor</li>
<li>Ticket attachments directly in emails</li>
<li>Recent tickets for contact when viewing another ticket</li>
<li>Restrict statuses from being closable</li>
<li>Custom service message icons</li>
<li>Permission templates</li>
<li>Request users location in tickets</li>
<li>Category managers</li>
<li>Show number of merged tickets in ticket search view</li>
<li>Enable / disable staff members</li>
<li>More-restricted settings page access</li>
<li>User agent tracking</li>
<li>New custom fields: Date, Readonly, Hidden, Email, Multiple Select</li>
</ul>
</td>
</tr>
</table>
<h2>Features</h2>
<p>Currently, the two major features of NuMods are:</p>
<ul>
<li>A new, responsive user interface</li>
<li>Ability to create custom ticket statuses</li>
</ul>
## Download
The latest version available for download can be downloaded from https://mods-for-hesk.mkochcs.com.
The `master` branch will always contain the latest release.
<h2>Download</h2>
## Installation
Visit [https://mods-for-hesk.mkochcs.com/download.php](https://mods-for-hesk.mkochcs.com/download.php) for installation instructions.
You can download this tweak via two ways:
## Languages / Support
Please visit https://developers.phpjunkyard.com/viewforum.php?f=19 for translation instructions and support.
Mods for HESK translations are available at http://mods-for-hesk.mkochcs.com.
<ol>
<li><strong>Stable Releases:</strong> Releases that have a release tag associated with a commit are considered releases. You can click on "releases" on the top of the repo, and then click "zip" or "tar.gz" to download the repo at that stage.</li>
<li><strong>Bleeding-edge Releases:</strong> You can also download the latest, bleeding-edge version of NuMods by simply clicking "download as zip" to the right of the repository. This will download an exact copy of this branch in its current state, which may be contain bugs/other issues. This is not recommended for a production use.</li>
</ol>
## Browser Compatibility
Mods for HESK is compatible with the following browsers:
<h2>Installation</h2>
- IE 11 / Edge
- Chrome (Current Version - 2 previous major revisions)
- Firefox (Current Version - 2 previous major revisions)
- Opera (Current Version - 2 previous major revisions)
- Safari (Current Version - 2 previous major revisions)
<ol>
<li>Download HESK from <a href="http://www.hesk.com/download.php" target="_blank">http://www.hesk.com/download.php</a>.</li>
<li>Extract the contents of HESK to a directory of your choice.</li>
<li>Download NuMods from one of the two methods described above.</li>
<li>Copy and paste the contents of the zip/tar.gz bundle and overwrite any files in the original HESK 2.x folder.</li>
<li>Upload the resulting folder to your webserver.</li>
<li>Go to the /install directory in your web browser and click on "Install/Update NuMods Installation"</li>
</ol>
<p>Please consult the official HESK Documentation on how to install HESK, as it is the same for both HESK and NuMods.</p>
It is possible that older browsers may or may not work with Mods for HESK.
However, support will not be provided for older browsers.
<h2>Languages</h2>
<p>As of current, only English is a supported language, as there have been several language items that have been edited/created. If you want to translate NuMods to your own language, it is recommended to download the original HESK language file for your language, and then add/edit the lines listed under <code>//Added or modified in HESK UI</code> and <code>//Added or modified in NuMods X.X.X</code> (where X.X.X is a version number) for your language.</p>
<p>If you create a translation for NuMods, please submit it via a pull request or via the PHP Junkyards forum, where it will be committed to this branch.</p>
## Versioning
Releases will be numbered with the following format:
<h2>Browser Compability</h2>
<p>This list may be incomplete. Please leave a note on the PHP Junkyard forums for additional browser compatibility information.
<ul>
<li><strong>Google Chrome 33+: </strong> Compatible</li>
<li><strong>Mozilla Firefox 28+:</strong> Compatible</li>
<li><strong>Internet Explorer 6/7:</strong> <em>NOT</em> Compatible</li>
<li><strong>Internet Explorer 8:</strong> Partial Compatibility</li>
<li><strong>Internet Explorer 9:</strong> Compatible</li>
</ul>
<p>There are no intentions of making NuMods compatible with Internet Explorer 6 or 7, or any browser that is 2 or more major revisions older than its latest version.</p>
`<major>.<minor>.<patch>`
<h2>Versioning</h2>
<p>NuMods will be maintained under the Semantic Versioning guidelines as much as possible. Releases will be numbered with the following format:</p>
And constructed with the following guidelines:
- Updates to ensure compatibility with new minor/major versions of HESK bumps the major
- New additions, including new minor features, without breaking backward compatibility, or updates to patch versions of HESK bumps the minor (and resets the patch)
- Bug fixes and misc minor changes bumps the patch
<code>&lt;major&gt;.&lt;minor&gt;.&lt;patch&gt;</code>
<p>And constructed with the following guidelines:</p>
<ul>
<li>Breaking backward compatibility bumps the major (and resets the minor and patch)</li>
<li>New additions, including new minor features, without breaking backward compatibility bumps the minor (and resets the patch)</li>
<li>Bug fixes and misc minor changes bumps the patch</li>
</ul>
<p>For more information on SemVer, please visit http://semver.org.</p>
<h2>Credits</h2>
<p>Mike Koch - Creator of NuMods</p>
<p>Klemen Stirn - Creator of HESK</p>
<p>lupolo from PHPJunkyard Scripts - diligent bug reporting on the PHPJunkyard Scripts Forum</p>
## Credits
- Mike Koch - Creator of Mods for HESK
- Klemen Stirn - Creator of HESK

View File

@ -1,143 +1,134 @@
<?php
/*******************************************************************************
* Title: Help Desk Software HESK
* Version: 2.5.3 from 16th March 2014
* Author: Klemen Stirn
* Website: http://www.hesk.com
********************************************************************************
* COPYRIGHT AND TRADEMARK NOTICE
* Copyright 2005-2013 Klemen Stirn. All Rights Reserved.
* HESK is a registered trademark of Klemen Stirn.
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
* The HESK may be used and modified free of charge by anyone
* AS LONG AS COPYRIGHT NOTICES AND ALL THE COMMENTS REMAIN INTACT.
* By using this code you agree to indemnify Klemen Stirn from any
* liability that might arise from it's use.
* Selling the code for this program, in part or full, without prior
* written consent is expressly forbidden.
* Using this code, in part or full, to create derivate work,
* new scripts or products is expressly forbidden. Obtain permission
* before redistributing this software over the Internet or in
* any other medium. In all cases copyright and header must remain intact.
* This Copyright is in full effect in any country that has International
* Trade Agreements with the United States of America or
* with the European Union.
* Removing any of the copyright notices without purchasing a license
* is expressly forbidden. To remove HESK copyright notice you must purchase
* a license for this script. For more information on how to obtain
* a license please visit the page below:
* https://www.hesk.com/buy.php
*******************************************************************************/
define('IN_SCRIPT',1);
define('HESK_PATH','../');
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
/* Make sure the install folder is deleted */
if (is_dir(HESK_PATH . 'install')) {die('Please delete the <b>install</b> folder from your server for security reasons then refresh this page!');}
if (is_dir(HESK_PATH . 'install')) {
die('Please delete the <b>install</b> folder from your server for security reasons then refresh this page!');
}
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/status_functions.inc.php');
require(HESK_PATH . 'inc/mail_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
define('CALENDAR',1);
define('MAIN_PAGE',1);
define('CALENDAR', 1);
define('MAIN_PAGE', 1);
define('PAGE_TITLE', 'ADMIN_HOME');
define('MFH_PAGE_LAYOUT', 'TOP_ONLY');
define('AUTO_RELOAD', 1);
/* Print header */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
/* Print admin navigation */
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
/* Reset default settings? */
if (isset($_GET['reset']) && hesk_token_check()) {
$res = hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` SET `default_list`='' WHERE `id` = '" . intval($_SESSION['id']) . "'");
$_SESSION['default_list'] = '';
} /* Get default settings */
else {
parse_str($_SESSION['default_list'], $defaults);
$_GET = isset($_GET) && is_array($_GET) ? array_merge($_GET, $defaults) : $defaults;
}
?>
<div class="content-wrapper">
<section class="content">
<?php
// Service messages
$service_messages = mfh_get_service_messages('STAFF_HOME');
foreach ($service_messages as $sm) {
hesk_service_message($sm);
}
<div class="row">
<div class="col-md-8 col-md-offset-2" style="padding-top: 20px">
<?php
/* This will handle error, success and notice messages */
hesk_handle_messages();
/* Print tickets? */
if (hesk_checkPermission('can_view_tickets',0))
{
if ( ! isset($_SESSION['hide']['ticket_list']) ) //Number of tickets (table header. NOT ACTUAL TABLE)
{
echo '
<div class="row">
<div class="col-md-4">&nbsp;</div>
<div class="col-md-4" style="text-align: center"><h3>'.$hesklang['open_tickets'].'</h3></div>
<div class="col-md-4">&nbsp;</div>
</div>
';
}
/* Reset default settings? */
if ( isset($_GET['reset']) && hesk_token_check() )
{
$res = hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` SET `default_list`='' WHERE `id` = '".intval($_SESSION['id'])."' LIMIT 1");
$_SESSION['default_list'] = '';
}
/* Get default settings */
else
{
parse_str($_SESSION['default_list'],$defaults);
$_GET = isset($_GET) && is_array($_GET) ? array_merge($_GET, $defaults) : $defaults;
}
/* Print the list of tickets */
require(HESK_PATH . 'inc/print_tickets.inc.php');
echo "&nbsp;<br />";
/* Print forms for listing and searching tickets */
require(HESK_PATH . 'inc/show_search_form.inc.php');
}
else
{
echo '<p><i>'.$hesklang['na_view_tickets'].'</i></p>';
}
$hesk_settings['hesk_license']('HMgPSAxOw0KaWYgKGZpbGVfZXhpc3RzKEhFU0tfUEFUSCAuI
CdoZXNrX2xpY2Vuc2UucGhwJykpDQp7DQokaCA9ICghZW1wdHkoJF9TRVJWRVJbJ0hUVFBfSE9TVCddK
SkgPyAkX1NFUlZFUlsnSFRUUF9IT1NUJ10gOiAoKCFlbXB0eSgkX1NFUlZFUlsnU0VSVkVSX05BTUUnX
SkpID8gJF9TRVJWRVJbJ1NFUlZFUl9OQU1FJ10gOiBnZXRlbnYoJ1NFUlZFUl9OQU1FJykpOw0KJGggP
SBzdHJfcmVwbGFjZSgnd3d3LicsJycsc3RydG9sb3dlcigkaCkpOw0KaW5jbHVkZShIRVNLX1BBVEggL
iAnaGVza19saWNlbnNlLnBocCcpOw0KaWYgKGlzc2V0KCRoZXNrX3NldHRpbmdzWydsaWNlbnNlJ10pI
CYmIHN0cnBvcygkaGVza19zZXR0aW5nc1snbGljZW5zZSddLHNoYTEoJGguJ2gzJkZwMiNMYUEmNTkhd
yg4LlpjXSordVI1MTInKSkgIT09IGZhbHNlKQ0Kew0KJHMgPSAwOw0KfQ0KZWxzZQ0Kew0KZWNobyAnP
HAgc3R5bGU9InRleHQtYWxpZ246Y2VudGVyO2NvbG9yOnJlZDsiPklOVkFMSUQgTElDRU5TRSAoTk9UI
FJFR0lTVEVSRUQgRk9SICcuJGguJykhPC9wPic7DQp9DQp9DQppZiAoJHMpDQp7DQplY2hvICc8aHIgL
z48dGFibGUgYm9yZGVyPSIwIiB3aWR0aD0iMTAwJSI+PHRyPjx0ZD48Yj4nLiRoZXNrbGFuZ1sncmVtb
3ZlX3N0YXRlbWVudCddLic8L2I+PC90ZD48dGQgc3R5bGU9InRleHQtYWxpZ246cmlnaHQiPjxhIGhyZ
WY9IkphdmFzY3JpcHQ6dm9pZCgwKSIgb25jbGljaz0iYWxlcnQoXCcnLiRoZXNrbGFuZ1snc3VwcG9yd
F9ub3RpY2UnXS4nXCcpIj4nLiRoZXNrbGFuZ1snc2gnXS4nPC9hPjwvdGQ+PC90cj48L3RhYmxlPjxwP
icuJGhlc2tsYW5nWydzdXBwb3J0X3JlbW92ZSddLicuIDxhIGhyZWY9Imh0dHBzOi8vd3d3Lmhlc2suY
29tL2J1eS5waHAiIHRhcmdldD0iX2JsYW5rIj4nLiRoZXNrbGFuZ1snY2xpY2tfaW5mbyddLic8L2E+P
C9wPic7DQp9DQo=',"\112");
echo '<hr />&nbsp;<br />';
/* Clean unneeded session variables */
hesk_cleanSessionVars('hide');
hesk_handle_messages();
?>
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['tickets']; ?>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<div class="row">
<div class="col-xs-6 text-left">
<div class="checkbox">
<label>
<input type="checkbox" onclick="toggleAutoRefresh(this);" id="reloadCB">
<?php echo $hesklang['arp']; ?>
<span id="timer"></span>
</label>
</div>
<script type="text/javascript">heskCheckReloading();</script>
</div>
<div class="col-xs-6 text-right">
<a href="new_ticket.php" class="btn btn-success">
<span class="glyphicon glyphicon-plus-sign"></span>
<?php echo $hesklang['nti']; ?>
</a>
</div>
</div>
<?php
/* Print tickets? */
if (hesk_checkPermission('can_view_tickets', 0)) {
/* Print the list of tickets */
require(HESK_PATH . 'inc/print_tickets.inc.php');
echo '<br>';
/* Print forms for listing and searching tickets */
require(HESK_PATH . 'inc/show_search_form.inc.php');
} else {
echo '<p><i>' . $hesklang['na_view_tickets'] . '</i></p>';
}
?>
</div>
</div>
<?php
/*******************************************************************************
The code below handles HESK licensing. Removing or modifying this code without
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
*******************************************************************************/
$x1a="\142a".chr(0163).chr(847249408>>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');
?>
</section>
</div>
<?php
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();
?>

View File

@ -1,39 +1,18 @@
<?php
/*******************************************************************************
* Title: Help Desk Software HESK
* Version: 2.5.3 from 16th March 2014
* Author: Klemen Stirn
* Website: http://www.hesk.com
********************************************************************************
* COPYRIGHT AND TRADEMARK NOTICE
* Copyright 2005-2014 Klemen Stirn. All Rights Reserved.
* HESK is a registered trademark of Klemen Stirn.
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
* The HESK may be used and modified free of charge by anyone
* AS LONG AS COPYRIGHT NOTICES AND ALL THE COMMENTS REMAIN INTACT.
* By using this code you agree to indemnify Klemen Stirn from any
* liability that might arise from it's use.
* Selling the code for this program, in part or full, without prior
* written consent is expressly forbidden.
* Using this code, in part or full, to create derivate work,
* new scripts or products is expressly forbidden. Obtain permission
* before redistributing this software over the Internet or in
* any other medium. In all cases copyright and header must remain intact.
* This Copyright is in full effect in any country that has International
* Trade Agreements with the United States of America or
* with the European Union.
* Removing any of the copyright notices without purchasing a license
* is expressly forbidden. To remove HESK copyright notice you must purchase
* a license for this script. For more information on how to obtain
* a license please visit the page below:
* https://www.hesk.com/buy.php
*******************************************************************************/
define('IN_SCRIPT',1);
define('HESK_PATH','../');
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
@ -42,18 +21,17 @@ require(HESK_PATH . 'inc/admin_functions.inc.php');
hesk_load_database_functions();
require(HESK_PATH . 'inc/email_functions.inc.php');
require(HESK_PATH . 'inc/posting_functions.inc.php');
require(HESK_PATH . 'inc/htmLawed.php');
// We only allow POST requests from the HESK form to this file
if ( $_SERVER['REQUEST_METHOD'] != 'POST' )
{
header('Location: admin_main.php');
exit();
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
header('Location: admin_main.php');
exit();
}
// Check for POST requests larger than what the server can handle
if ( empty($_POST) && ! empty($_SERVER['CONTENT_LENGTH']) )
{
hesk_error($hesklang['maxpost']);
if (empty($_POST) && !empty($_SERVER['CONTENT_LENGTH'])) {
hesk_error($hesklang['maxpost']);
}
hesk_session_start();
@ -61,247 +39,386 @@ hesk_dbConnect();
hesk_isLoggedIn();
/* Check permissions for this feature */
hesk_checkPermission('can_reply_tickets');
if (!isset($_REQUEST['isManager']) || !$_REQUEST['isManager']) {
hesk_checkPermission('can_reply_tickets');
}
/* A security check */
# hesk_token_check('POST');
/* Original ticket ID */
$replyto = intval( hesk_POST('orig_id', 0) ) or die($hesklang['int_error']);
$replyto = intval(hesk_POST('orig_id', 0)) or die($hesklang['int_error']);
/* Get details about the original ticket */
$result = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `id`='{$replyto}' LIMIT 1");
if (hesk_dbNumRows($result) != 1)
{
hesk_error($hesklang['ticket_not_found']);
$result = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `id`='{$replyto}' LIMIT 1");
if (hesk_dbNumRows($result) != 1) {
hesk_error($hesklang['ticket_not_found']);
}
$ticket = hesk_dbFetchAssoc($result);
$trackingID = $ticket['trackid'];
// Do we require owner before allowing to reply?
if ($hesk_settings['require_owner'] && ! $ticket['owner']) {
hesk_process_messages($hesklang['atbr'],'admin_ticket.php?track='.$ticket['trackid'].'&Refresh='.rand(10000,99999));
}
$hesk_error_buffer = array();
// Get the message
$message = hesk_input(hesk_POST('message'));
if (strlen($message))
{
// Attach signature to the message?
if ( ! empty($_POST['signature']))
{
$message .= "\n\n" . addslashes($_SESSION['signature']) . "\n";
}
// Submit as customer?
$submit_as_customer = isset($_POST['submit_as_customer']) ? true : false;
// Make links clickable
$message = hesk_makeURL($message);
$modsForHesk_settings = mfh_getSettings();
if (strlen($message)) {
// Save message for later and ignore the rest?
if (isset($_POST['save_reply'])) {
// Delete any existing drafts from this owner for this ticket
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "reply_drafts` WHERE `owner`=" . intval($_SESSION['id']) . " AND `ticket`=" . intval($ticket['id']));
// Turn newlines into <br /> tags
$message = nl2br($message);
}
else
{
// Save the message draft
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "reply_drafts` (`owner`, `ticket`, `message`) VALUES (" . intval($_SESSION['id']) . ", " . intval($ticket['id']) . ", '" . hesk_dbEscape($message) . "')");
/* Set reply submitted message */
$_SESSION['HESK_SUCCESS'] = TRUE;
$_SESSION['HESK_MESSAGE'] = $hesklang['reply_saved'];
/* What to do after reply? */
if ($_SESSION['afterreply'] == 1) {
header('Location: admin_main.php');
} elseif ($_SESSION['afterreply'] == 2) {
/* Get the next open ticket that needs a reply */
$res = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `owner` IN ('0','" . intval($_SESSION['id']) . "')
AND " . hesk_myCategories() . " AND `status` IN (SELECT `ID` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses`
WHERE `IsNewTicketStatus` = 1 OR `IsCustomerReplyStatus` = 1 OR `IsStaffReopenedStatus` = 1)
ORDER BY `owner` DESC, `priority` ASC LIMIT 1");
if (hesk_dbNumRows($res) == 1) {
$row = hesk_dbFetchAssoc($res);
$_SESSION['HESK_MESSAGE'] .= '<br /><br />' . $hesklang['rssn'];
header('Location: admin_ticket.php?track=' . $row['trackid'] . '&Refresh=' . rand(10000, 99999));
} else {
header('Location: admin_main.php');
}
} else {
header('Location: admin_ticket.php?track=' . $ticket['trackid'] . '&Refresh=' . rand(10000, 99999));
}
exit();
}
// Attach signature to the message?
if (!$submit_as_customer && !empty($_POST['signature'])) {
if ($modsForHesk_settings['rich_text_for_tickets']) {
$signature = nl2br($_SESSION['signature']);
$signature = hesk_htmlspecialchars($signature);
$message .= "<br><br>" . $signature . "<br>";
} else {
$message .= "\n\n" . addslashes($_SESSION['signature']) . "\n";
}
}
if (!$modsForHesk_settings['rich_text_for_tickets']) {
// Make links clickable
$message = hesk_makeURL($message);
// Turn newlines into <br /> tags
$message = nl2br($message);
}
} else {
$hesk_error_buffer[] = $hesklang['enter_message'];
}
/* Attachments */
if ($hesk_settings['attachments']['use'])
{
if ($hesk_settings['attachments']['use']) {
require(HESK_PATH . 'inc/attachments.inc.php');
$attachments = array();
for ($i=1;$i<=$hesk_settings['attachments']['max_number'];$i++)
{
$att = hesk_uploadFile($i);
if ($att !== false && !empty($att))
{
$attachments[$i] = $att;
$use_legacy_attachments = hesk_POST('use-legacy-attachments', 0);
if ($use_legacy_attachments) {
for ($i = 1; $i <= $hesk_settings['attachments']['max_number']; $i++) {
$att = hesk_uploadFile($i);
if ($att !== false && !empty($att)) {
$attachments[$i] = $att;
}
}
} else {
// The user used the new drag-and-drop system.
$temp_attachment_ids = hesk_POST_array('attachment-ids');
foreach ($temp_attachment_ids as $temp_attachment_id) {
// Simply get the temp info and move it to the attachments table
$temp_attachment = mfh_getTemporaryAttachment($temp_attachment_id);
$attachments[] = $temp_attachment;
mfh_deleteTemporaryAttachment($temp_attachment_id);
}
}
}
$myattachments='';
$myattachments = '';
/* Time spent working on ticket */
$time_worked = hesk_getTime(hesk_POST('time_worked'));
/* Any errors? */
if (count($hesk_error_buffer)!=0)
{
if (count($hesk_error_buffer) != 0) {
$_SESSION['ticket_message'] = hesk_POST('message');
$_SESSION['time_worked'] = $time_worked;
// Remove any successfully uploaded attachments
if ($hesk_settings['attachments']['use'])
{
hesk_removeAttachments($attachments);
}
// Remove any successfully uploaded attachments
if ($hesk_settings['attachments']['use']) {
hesk_removeAttachments($attachments);
}
$tmp = '';
foreach ($hesk_error_buffer as $error)
{
foreach ($hesk_error_buffer as $error) {
$tmp .= "<li>$error</li>\n";
}
$hesk_error_buffer = $tmp;
$hesk_error_buffer = $hesklang['pcer'].'<br /><br /><ul>'.$hesk_error_buffer.'</ul>';
hesk_process_messages($hesk_error_buffer,'admin_ticket.php?track='.$ticket['trackid'].'&Refresh='.rand(10000,99999));
$hesk_error_buffer = $hesklang['pcer'] . '<br /><br /><ul>' . $hesk_error_buffer . '</ul>';
hesk_process_messages($hesk_error_buffer, 'admin_ticket.php?track=' . $ticket['trackid'] . '&Refresh=' . rand(10000, 99999));
}
if ($hesk_settings['attachments']['use'] && !empty($attachments))
{
foreach ($attachments as $myatt)
{
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` (`ticket_id`,`saved_name`,`real_name`,`size`) VALUES ('".hesk_dbEscape($trackingID)."','".hesk_dbEscape($myatt['saved_name'])."','".hesk_dbEscape($myatt['real_name'])."','".intval($myatt['size'])."')");
$myattachments .= hesk_dbInsertID() . '#' . $myatt['real_name'] .',';
if ($hesk_settings['attachments']['use'] && !empty($attachments)) {
foreach ($attachments as $myatt) {
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "attachments` (`ticket_id`,`saved_name`,`real_name`,`size`) VALUES ('" . hesk_dbEscape($trackingID) . "','" . hesk_dbEscape($myatt['saved_name']) . "','" . hesk_dbEscape($myatt['real_name']) . "','" . intval($myatt['size']) . "')");
$myattachments .= hesk_dbInsertID() . '#' . $myatt['real_name'] . '#' . $myatt['saved_name'] . ',';
}
}
/* Add reply */
$result = hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`staffid`) VALUES ('".intval($replyto)."','".hesk_dbEscape(addslashes($_SESSION['name']))."','".hesk_dbEscape($message)."',NOW(),'".hesk_dbEscape($myattachments)."','".intval($_SESSION['id'])."')");
// Add reply
$html = $modsForHesk_settings['rich_text_for_tickets'];
if ($submit_as_customer) {
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`html`) VALUES ('" . intval($replyto) . "','" . hesk_dbEscape(addslashes($ticket['name'])) . "','" . hesk_dbEscape($message . "<br /><br /><i>{$hesklang['creb']} {$_SESSION['name']}</i>") . "', NOW(),'" . hesk_dbEscape($myattachments) . "', '" . $html . "')");
} else {
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`staffid`,`html`) VALUES ('" . intval($replyto) . "','" . hesk_dbEscape(addslashes($_SESSION['name'])) . "','" . hesk_dbEscape($message) . "', NOW(),'" . hesk_dbEscape($myattachments) . "','" . intval($_SESSION['id']) . "', '" . $html . "')");
}
/* Track ticket status changes for history */
$revision = '';
/* Change the status of priority? */
if ( ! empty($_POST['set_priority']) )
{
$priority = intval( hesk_POST('priority') );
if ($priority < 0 || $priority > 3)
{
hesk_error($hesklang['select_priority']);
$audit_priority = null;
$audit_closed = null;
$audit_status = null;
$audit_customer_status = null;
$audit_assigned_self = null;
if (!empty($_POST['set_priority'])) {
$priority = intval(hesk_POST('priority'));
if ($priority < 0 || $priority > 3) {
hesk_error($hesklang['select_priority']);
}
$options = array(
0 => '<font class="critical">'.$hesklang['critical'].'</font>',
1 => '<font class="important">'.$hesklang['high'].'</font>',
2 => '<font class="medium">'.$hesklang['medium'].'</font>',
3 => $hesklang['low']
);
$options = array(
0 => '<span class="critical">' . $hesklang['critical'] . '</span>',
1 => '<span class="important">' . $hesklang['high'] . '</span>',
2 => '<span class="medium">' . $hesklang['medium'] . '</span>',
3 => $hesklang['low']
);
$revision = sprintf($hesklang['thist8'],hesk_date(),$options[$priority],$_SESSION['name'].' ('.$_SESSION['user'].')');
$plain_options = array(
0 => 'critical',
1 => 'high',
2 => 'medium',
3 => 'low'
);
$priority_sql = ",`priority`='$priority', `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') ";
}
else
{
$priority_sql = ",`priority`='$priority' ";
$audit_priority = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')',
1 => $plain_options[$priority]);
} else {
$priority_sql = "";
}
/* Update the original ticket */
$defaultStatusReplyStatus = hesk_dbFetchAssoc(hesk_dbQuery("SELECT `ID`, `IsClosed` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE `IsDefaultStaffReplyStatus` = 1 LIMIT 1"));
$staffClosedCheckboxStatus = hesk_dbFetchAssoc(hesk_dbQuery("SELECT `ID`, `IsClosed` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE `IsStaffClosedOption` = 1 LIMIT 1"));
$lockedTicketStatus = hesk_dbFetchAssoc(hesk_dbQuery("SELECT `ID` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE `LockedTicketStatus` = 1 LIMIT 1"));
$defaultStatusReplyStatus = hesk_dbFetchAssoc(hesk_dbQuery("SELECT `ID`, `IsClosed` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` WHERE `IsDefaultStaffReplyStatus` = 1 LIMIT 1"));
$staffClosedCheckboxStatus = hesk_dbFetchAssoc(hesk_dbQuery("SELECT `ID`, `IsClosed` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` WHERE `IsStaffClosedOption` = 1 LIMIT 1"));
$lockedTicketStatus = hesk_dbFetchAssoc(hesk_dbQuery("SELECT `ID` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` WHERE `LockedTicketStatus` = 1 LIMIT 1"));
$new_status = empty($_POST['close']) ? $defaultStatusReplyStatus['ID'] : $staffClosedCheckboxStatus['ID'];
// Get new ticket status
$sql_status = '';
$change_status = true;
// -> If locked, keep it resolved
if ($ticket['locked']) {
$new_status = $lockedTicketStatus['ID'];
} elseif (isset($_POST['submit_as_status'])) {
$new_status = $_POST['submit_as_status'];
/* --> If a ticket is locked keep it closed */
if ($ticket['locked'])
{
$new_status = $lockedTicketStatus['ID'];
if ($ticket['status'] != $new_status) {
// Does this status close the ticket?
$newStatusRs = hesk_dbQuery('SELECT `IsClosed`, `Key` FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'statuses` WHERE `ID` = ' . intval($new_status));
$newStatus = hesk_dbFetchAssoc($newStatusRs);
if ($newStatus['IsClosed'] && hesk_checkPermission('can_resolve', 0)) {
$audit_closed = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')');
$audit_status = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')',
1 => mfh_getDisplayTextForStatusId($new_status)
);
$sql_status = " , `closedat`=NOW(), `closedby`=" . intval($_SESSION['id']) . " ";
// Lock the ticket if customers are not allowed to reopen tickets
if ($hesk_settings['custopen'] != 1) {
$sql_status .= " , `locked`='1' ";
}
} else {
// Ticket isn't being closed, just add the history to the sql query (or tried to close but doesn't have permission)
$audit_status = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')',
1 => mfh_getDisplayTextForStatusId($new_status));
}
}
} // -> Submit as Customer reply
elseif ($submit_as_customer) {
//Get the status ID for customer replies
$customerReplyStatusRs = hesk_dbQuery('SELECT `ID` FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'statuses` WHERE `IsCustomerReplyStatus` = 1 LIMIT 1');
$customerReplyStatus = hesk_dbFetchAssoc($customerReplyStatusRs);
$new_status = $customerReplyStatus['ID'];
if ($ticket['status'] != $new_status) {
$audit_customer_status = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')',
1 => mfh_getDisplayTextForStatusId($new_status));
}
} // -> Default: submit as "Replied by staff"
else {
//Get the status ID for staff replies
$staffReplyStatusRs = hesk_dbQuery('SELECT `ID` FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'statuses` WHERE `IsDefaultStaffReplyStatus` = 1 LIMIT 1');
$staffReplyStatus = hesk_dbFetchAssoc($staffReplyStatusRs);
$new_status = $staffReplyStatus['ID'];
}
$sql = "UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `status`='{$new_status}', `lastreplier`='1', `replierid`='".intval($_SESSION['id'])."' ";
$sql = "UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `status`='{$new_status}',";
$sql .= $submit_as_customer ? "`lastreplier`='0', `replierid`='0' " : "`lastreplier`='1', `replierid`='" . intval($_SESSION['id']) . "' ";
/* Update time_worked or force update lastchange */
if ($time_worked == '00:00:00')
{
$sql .= ", `lastchange` = NOW() ";
}
else
{
$sql .= ",`time_worked` = ADDTIME(`time_worked`,'" . hesk_dbEscape($time_worked) . "') ";
if ($time_worked == '00:00:00') {
$sql .= ", `lastchange` = NOW() ";
} else {
$parts = explode(':', $ticket['time_worked']);
$seconds = ($parts[0] * 3600) + ($parts[1] * 60) + $parts[2];
$parts = explode(':', $time_worked);
$seconds += ($parts[0] * 3600) + ($parts[1] * 60) + $parts[2];
require(HESK_PATH . 'inc/reporting_functions.inc.php');
$ticket['time_worked'] = hesk_SecondsToHHMMSS($seconds);
$sql .= ",`time_worked` = ADDTIME(`time_worked`,'" . hesk_dbEscape($time_worked) . "') ";
}
if ( ! empty($_POST['assign_self']) && hesk_checkPermission('can_assign_self',0))
{
$revision = sprintf($hesklang['thist2'],hesk_date(),$_SESSION['name'].' ('.$_SESSION['user'].')',$_SESSION['name'].' ('.$_SESSION['user'].')');
$sql .= " , `owner`=".intval($_SESSION['id']).", `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') ";
if (!empty($_POST['assign_self']) && (hesk_checkPermission('can_assign_self', 0) || (isset($_REQUEST['isManager']) && $_REQUEST['isManager']))) {
$audit_assigned_self = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')');
$sql .= " , `owner`=" . intval($_SESSION['id']) . " ";
}
$sql .= " $priority_sql ";
$sql .= " $sql_status ";
$isNewStatusClosed = empty($_POST['close']) ? $defaultStatusReplyStatus['IsClosed'] : $staffClosedCheckboxStatus['IsClosed'];
if ($isNewStatusClosed)
{
$revision = sprintf($hesklang['thist3'],hesk_date(),$_SESSION['name'].' ('.$_SESSION['user'].')');
$sql .= " , `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') ";
if ($hesk_settings['custopen'] != 1)
{
$sql .= " , `locked`='1' ";
}
if (!$ticket['firstreplyby']) {
$sql .= " , `firstreply`=NOW(), `firstreplyby`=" . intval($_SESSION['id']) . " ";
}
$sql .= " WHERE `id`='{$replyto}' LIMIT 1";
// Keep track of replies to this ticket for easier reporting
$sql .= " , `replies`=`replies`+1 ";
$sql .= $submit_as_customer ? '' : " , `staffreplies`=`staffreplies`+1 ";
// End and execute the query
$sql .= " WHERE `id`='{$replyto}'";
hesk_dbQuery($sql);
unset($sql);
/* Update number of replies in the users table */
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` SET `replies`=`replies`+1 WHERE `id`='".intval($_SESSION['id'])."' LIMIT 1");
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` SET `replies`=`replies`+1 WHERE `id`='" . intval($_SESSION['id']) . "'");
//-- Insert necessary audit trail records
if ($audit_priority != null) {
mfh_insert_audit_trail_record($replyto, 'TICKET', 'audit_priority', hesk_date(), $audit_priority);
}
if ($audit_closed != null) {
mfh_insert_audit_trail_record($replyto, 'TICKET', 'audit_closed', hesk_date(), $audit_closed);
}
if ($audit_status != null) {
mfh_insert_audit_trail_record($replyto, 'TICKET', 'audit_status', hesk_date(), $audit_status);
}
if ($audit_customer_status != null) {
mfh_insert_audit_trail_record($replyto, 'TICKET', 'audit_status', hesk_date(),
$audit_customer_status);
}
if ($audit_assigned_self != null) {
mfh_insert_audit_trail_record($replyto, 'TICKET', 'audit_assigned_self', hesk_date(), $audit_assigned_self);
}
// --> Prepare reply 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' => $new_status,
'name' => $ticket['name'],
'lastreplier' => $_SESSION['name'],
'subject' => $ticket['subject'],
'message' => stripslashes($message),
'attachments' => $myattachments,
'dt' => hesk_date($ticket['dt']),
'lastchange' => hesk_date($ticket['lastchange']),
'email' => $ticket['email'],
'category' => $ticket['category'],
'priority' => $ticket['priority'],
'owner' => $ticket['owner'],
'trackid' => $ticket['trackid'],
'status' => $new_status,
'name' => $ticket['name'],
'lastreplier' => ($submit_as_customer ? $ticket['name'] : $_SESSION['name']),
'subject' => $ticket['subject'],
'message' => stripslashes($message),
'attachments' => $myattachments,
'dt' => hesk_date($ticket['dt'], true),
'lastchange' => hesk_date($ticket['lastchange'], true),
'id' => $ticket['id'],
'language' => $ticket['language'],
'time_worked' => $ticket['time_worked'],
'last_reply_by' => ($submit_as_customer ? $ticket['name'] : $_SESSION['name']),
);
// 2. Add custom fields to the array
foreach ($hesk_settings['custom_fields'] as $k => $v)
{
$info[$k] = $v['use'] ? $ticket[$k] : '';
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 customer
if ( ! isset($_POST['no_notify']) || intval( hesk_POST('no_notify') ) != 1)
{
hesk_notifyCustomer('new_reply_by_staff');
// Notify the assigned staff?
if ($submit_as_customer) {
if ($ticket['owner'] && $ticket['owner'] != $_SESSION['id']) {
hesk_notifyAssignedStaff(false, 'new_reply_by_customer', $modsForHesk_settings, 'notify_reply_my');
}
} // Notify customer?
elseif (!isset($_POST['no_notify']) || intval(hesk_POST('no_notify')) != 1) {
hesk_notifyCustomer($modsForHesk_settings, 'new_reply_by_staff');
}
// Delete any existing drafts from this owner for this ticket
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "reply_drafts` WHERE `owner`=" . intval($_SESSION['id']) . " AND `ticket`=" . intval($ticket['id']));
/* Set reply submitted message */
$_SESSION['HESK_SUCCESS'] = TRUE;
$_SESSION['HESK_MESSAGE'] = $hesklang['reply_submitted'];
if (!empty($_POST['close']))
{
$_SESSION['HESK_MESSAGE'] .= '<br /><br />'.$hesklang['ticket_marked'].' <span class="resolved">'.$hesklang['closed'].'</span>';
}
/* What to do after reply? */
if ($_SESSION['afterreply'] == 1)
{
header('Location: admin_main.php');
}
elseif ($_SESSION['afterreply'] == 2)
{
/* Get the next open ticket that needs a reply */
$res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `owner` IN ('0','".intval($_SESSION['id'])."') AND " . hesk_myCategories() . " AND `status` IN ('0','1') ORDER BY `owner` DESC, `priority` ASC LIMIT 1");
if ($_SESSION['afterreply'] == 1) {
header('Location: admin_main.php');
} elseif ($_SESSION['afterreply'] == 2) {
/* Get the next open ticket that needs a reply */
$res = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `owner` IN ('0','" . intval($_SESSION['id']) . "') AND " . hesk_myCategories() . " AND `status` IN (SELECT `ID` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses`
WHERE `IsNewTicketStatus` = 1 OR `IsCustomerReplyStatus` = 1 OR `IsStaffReopenedStatus` = 1) ORDER BY `owner` DESC, `priority` ASC LIMIT 1");
if (hesk_dbNumRows($res) == 1)
{
$row = hesk_dbFetchAssoc($res);
$_SESSION['HESK_MESSAGE'] .= '<br /><br />'.$hesklang['rssn'];
header('Location: admin_ticket.php?track='.$row['trackid'].'&Refresh='.rand(10000,99999));
if (hesk_dbNumRows($res) == 1) {
$row = hesk_dbFetchAssoc($res);
$_SESSION['HESK_MESSAGE'] .= '<br /><br />' . $hesklang['rssn'];
header('Location: admin_ticket.php?track=' . $row['trackid'] . '&Refresh=' . rand(10000, 99999));
} else {
header('Location: admin_main.php');
}
else
{
header('Location: admin_main.php');
}
}
else
{
header('Location: admin_ticket.php?track='.$ticket['trackid'].'&Refresh='.rand(10000,99999));
} else {
header('Location: admin_ticket.php?track=' . $ticket['trackid'] . '&Refresh=' . rand(10000, 99999));
}
exit();
?>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,39 +1,18 @@
<?php
/*******************************************************************************
* Title: Help Desk Software HESK
* Version: 2.5.3 from 16th March 2014
* Author: Klemen Stirn
* Website: http://www.hesk.com
********************************************************************************
* COPYRIGHT AND TRADEMARK NOTICE
* Copyright 2005-2013 Klemen Stirn. All Rights Reserved.
* HESK is a registered trademark of Klemen Stirn.
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
* The HESK may be used and modified free of charge by anyone
* AS LONG AS COPYRIGHT NOTICES AND ALL THE COMMENTS REMAIN INTACT.
* By using this code you agree to indemnify Klemen Stirn from any
* liability that might arise from it's use.
* Selling the code for this program, in part or full, without prior
* written consent is expressly forbidden.
* Using this code, in part or full, to create derivate work,
* new scripts or products is expressly forbidden. Obtain permission
* before redistributing this software over the Internet or in
* any other medium. In all cases copyright and header must remain intact.
* This Copyright is in full effect in any country that has International
* Trade Agreements with the United States of America or
* with the European Union.
* Removing any of the copyright notices without purchasing a license
* is expressly forbidden. To remove HESK copyright notice you must purchase
* a license for this script. For more information on how to obtain
* a license please visit the page below:
* https://www.hesk.com/buy.php
*******************************************************************************/
define('IN_SCRIPT',1);
define('HESK_PATH','../');
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
// Get all the required files and functions
require(HESK_PATH . 'hesk_settings.inc.php');
@ -41,74 +20,155 @@ require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
hesk_load_database_functions();
require(HESK_PATH . 'inc/email_functions.inc.php');
require(HESK_PATH . 'inc/htmLawed.php');
require(HESK_PATH . 'inc/posting_functions.inc.php');
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
$modsForHesk_settings = mfh_getSettings();
// We only allow POST requests from the HESK form to this file
if ( $_SERVER['REQUEST_METHOD'] != 'POST' )
{
header('Location: admin_main.php');
exit();
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
header('Location: admin_main.php');
exit();
}
// Check for POST requests larger than what the server can handle
if ( empty($_POST) && ! empty($_SERVER['CONTENT_LENGTH']) )
{
hesk_error($hesklang['maxpost']);
if (empty($_POST) && !empty($_SERVER['CONTENT_LENGTH'])) {
hesk_error($hesklang['maxpost']);
}
$hesk_error_buffer = array();
$tmpvar['name'] = hesk_input( hesk_POST('name') ) or $hesk_error_buffer['name']=$hesklang['enter_your_name'];
$tmpvar['email'] = hesk_validateEmail( hesk_POST('email'), 'ERR', 0) or $hesk_error_buffer['email']=$hesklang['enter_valid_email'];
$tmpvar['category'] = intval( hesk_POST('category') ) or $hesk_error_buffer['category']=$hesklang['sel_app_cat'];
$tmpvar['priority'] = intval( hesk_POST('priority') );
if ($hesk_settings['can_sel_lang']) {
$tmpvar['language'] = hesk_POST('customerLanguage');
}
$tmpvar['name'] = hesk_input(hesk_POST('name')) or $hesk_error_buffer['name'] = $hesklang['enter_your_name'];
$email_available = true;
if ($tmpvar['priority'] < 0 || $tmpvar['priority'] > 3)
{
$hesk_error_buffer['priority']=$hesklang['sel_app_priority'];
if ($hesk_settings['require_email']) {
$tmpvar['email'] = hesk_validateEmail( hesk_POST('email'), 'ERR', 0) or $hesk_error_buffer['email']=$hesklang['enter_valid_email'];
} else {
$tmpvar['email'] = hesk_validateEmail( hesk_POST('email'), 'ERR', 0);
// Not required, but must be valid if it is entered
if ($tmpvar['email'] == '') {
$email_available = false;
if (strlen(hesk_POST('email'))) {
$hesk_error_buffer['email'] = $hesklang['not_valid_email'];
}
}
}
if ($hesk_settings['multi_eml']) {
$tmpvar['email'] = str_replace(';',',', $tmpvar['email']);
}
$tmpvar['category'] = intval(hesk_POST('category')) or $hesk_error_buffer['category'] = $hesklang['sel_app_cat'];
$tmpvar['priority'] = hesk_POST('priority');
$tmpvar['priority'] = strlen($tmpvar['priority']) ? intval($tmpvar['priority']) : -1;
if ($tmpvar['priority'] < 0 || $tmpvar['priority'] > 3) {
// If we are showing "Click to select" priority needs to be selected
if ($hesk_settings['select_pri']) {
$tmpvar['priority'] = -1;
$hesk_error_buffer['priority'] = $hesklang['select_priority'];
} else {
$tmpvar['priority'] = 3;
}
}
$tmpvar['subject'] = hesk_input( hesk_POST('subject') ) or $hesk_error_buffer['subject']=$hesklang['enter_ticket_subject'];
$tmpvar['message'] = hesk_input( hesk_POST('message') ) or $hesk_error_buffer['message']=$hesklang['enter_message'];
$tmpvar['subject'] = hesk_input( hesk_POST('subject') );
if ($hesk_settings['require_subject'] == 1 && $tmpvar['subject'] == '') {
$hesk_error_buffer['subject'] = $hesklang['enter_ticket_subject'];
}
$tmpvar['message'] = hesk_input( hesk_POST('message') );
if ($hesk_settings['require_message'] == 1 && $tmpvar['message'] == '') {
$hesk_error_buffer['message'] = $hesklang['enter_message'];
}
// Is category a valid choice?
if ($tmpvar['category'])
{
hesk_verifyCategory(1);
if ($tmpvar['category']) {
if ( ! hesk_checkPermission('can_submit_any_cat', 0) && ! hesk_okCategory($tmpvar['category'], 0) ) {
hesk_process_messages($hesklang['noauth_submit'],'new_ticket.php');
}
// Is auto-assign of tickets disabled in this category?
if ( empty($hesk_settings['category_data'][$tmpvar['category']]['autoassign']) )
{
$hesk_settings['autoassign'] = false;
}
hesk_verifyCategory(1);
// Is auto-assign of tickets disabled in this category?
if (empty($hesk_settings['category_data'][$tmpvar['category']]['autoassign'])) {
$hesk_settings['autoassign'] = false;
}
}
// Custom fields
foreach ($hesk_settings['custom_fields'] as $k=>$v)
{
if ($v['use'] && isset($_POST[$k]))
{
if (is_array($_POST[$k]))
foreach ($hesk_settings['custom_fields'] as $k=>$v) {
if ($v['use'] && hesk_is_custom_field_in_category($k, $tmpvar['category'])) {
if ($v['type'] == 'checkbox') {
$tmpvar[$k]='';
if (isset($_POST[$k]) && is_array($_POST[$k])) {
foreach ($_POST[$k] as $myCB) {
$tmpvar[$k] .= ( is_array($myCB) ? '' : hesk_input($myCB) ) . '<br />';;
}
$tmpvar[$k]=substr($tmpvar[$k],0,-6);
} else {
if ($v['req'] == 2) {
$hesk_error_buffer[$k]=$hesklang['fill_all'].': '.$v['name'];
}
$_POST[$k] = '';
}
} elseif ($v['type'] == 'date') {
$tmpvar[$k] = hesk_POST($k);
$_SESSION["as_$k"] = '';
if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/", $tmpvar[$k])) {
$date = strtotime($tmpvar[$k] . ' t00:00:00 UTC');
$dmin = strlen($v['value']['dmin']) ? strtotime($v['value']['dmin'] . ' t00:00:00 UTC') : false;
$dmax = strlen($v['value']['dmax']) ? strtotime($v['value']['dmax'] . ' t00:00:00 UTC') : false;
$_SESSION["as_$k"] = $tmpvar[$k];
if ($dmin && $dmin > $date) {
$hesk_error_buffer[$k] = sprintf($hesklang['d_emin'], $v['name'], hesk_custom_date_display_format($dmin, $v['value']['date_format']));
} elseif ($dmax && $dmax < $date) {
$hesk_error_buffer[$k] = sprintf($hesklang['d_emax'], $v['name'], hesk_custom_date_display_format($dmax, $v['value']['date_format']));
} else {
$tmpvar[$k] = $date;
}
} else {
$tmpvar[$k] = '';
if ($v['req'] == 2) {
$hesk_error_buffer[$k]=$hesklang['fill_all'].': '.$v['name'];
}
}
} elseif ($v['type'] == 'email')
{
$tmpvar[$k]='';
foreach ($_POST[$k] as $myCB)
{
$tmpvar[$k] .= ( is_array($myCB) ? '' : hesk_input($myCB) ) . '<br />';
}
$tmpvar[$k]=substr($tmpvar[$k],0,-6);
$tmp = $hesk_settings['multi_eml'];
$hesk_settings['multi_eml'] = $v['value']['multiple'];
$tmpvar[$k] = hesk_validateEmail( hesk_POST($k), 'ERR', 0);
$hesk_settings['multi_eml'] = $tmp;
if ($tmpvar[$k] != '') {
$_SESSION["as_$k"] = hesk_input($tmpvar[$k]);
} else {
$_SESSION["as_$k"] = '';
if ($v['req'] == 2) {
$hesk_error_buffer[$k] = $v['value']['multiple'] ? sprintf($hesklang['cf_noem'], $v['name']) : sprintf($hesklang['cf_noe'], $v['name']);
}
}
} elseif ($v['req'] == 2) {
$tmpvar[$k]=hesk_makeURL(nl2br(hesk_input( hesk_POST($k) )));
if ($tmpvar[$k] == '') {
$hesk_error_buffer[$k]=$hesklang['fill_all'].': '.$v['name'];
}
} else {
$tmpvar[$k]=hesk_makeURL(nl2br(hesk_input(hesk_POST($k))));
}
else
{
$tmpvar[$k]=hesk_makeURL(nl2br(hesk_input($_POST[$k])));
}
}
else
{
$tmpvar[$k] = '';
} else {
$tmpvar[$k] = '';
}
}
@ -116,171 +176,173 @@ foreach ($hesk_settings['custom_fields'] as $k=>$v)
$tmpvar['trackid'] = hesk_createID();
// Log who submitted ticket
$tmpvar['history'] = sprintf($hesklang['thist7'], hesk_date(), $_SESSION['name'].' ('.$_SESSION['user'].')');
$tmpvar['openedby'] = $_SESSION['id'];
// Owner
$tmpvar['owner'] = 0;
if (hesk_checkPermission('can_assign_others',0))
{
$tmpvar['owner'] = intval( hesk_POST('owner') );
$autoassign_owner = null;
if (hesk_checkPermission('can_assign_others', 0)) {
$tmpvar['owner'] = intval(hesk_POST('owner'));
// If ID is -1 the ticket will be unassigned
if ($tmpvar['owner'] == -1)
{
$tmpvar['owner'] = 0;
}
// Automatically assign owner?
elseif ($tmpvar['owner'] == -2 && $hesk_settings['autoassign'] == 1)
{
$autoassign_owner = hesk_autoAssignTicket($tmpvar['category']);
if ($autoassign_owner)
{
$tmpvar['owner'] = intval($autoassign_owner['id']);
$tmpvar['history'] .= sprintf($hesklang['thist10'],hesk_date(),$autoassign_owner['name'].' ('.$autoassign_owner['user'].')');
}
else
{
$tmpvar['owner'] = 0;
// If ID is -1 the ticket will be unassigned
if ($tmpvar['owner'] == -1) {
$tmpvar['owner'] = 0;
} // Automatically assign owner?
elseif ($tmpvar['owner'] == -2 && $hesk_settings['autoassign'] == 1) {
$autoassign_owner = hesk_autoAssignTicket($tmpvar['category']);
if ($autoassign_owner) {
$tmpvar['owner'] = intval($autoassign_owner['id']);
} else {
$tmpvar['owner'] = 0;
}
} // Check for invalid owner values
elseif ($tmpvar['owner'] < 1) {
$tmpvar['owner'] = 0;
} else {
// Has the new owner access to the selected category?
$res = hesk_dbQuery("SELECT `name`,`isadmin`,`categories` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `id`='{$tmpvar['owner']}' LIMIT 1");
if (hesk_dbNumRows($res) == 1) {
$row = hesk_dbFetchAssoc($res);
if (!$row['isadmin']) {
$row['categories'] = explode(',', $row['categories']);
if (!in_array($tmpvar['category'], $row['categories'])) {
$_SESSION['isnotice'][] = 'category';
$hesk_error_buffer['owner'] = $hesklang['onasc'];
}
}
} else {
$_SESSION['isnotice'][] = 'category';
$hesk_error_buffer['owner'] = $hesklang['onasc'];
}
}
// Check for invalid owner values
elseif ($tmpvar['owner'] < 1)
{
$tmpvar['owner'] = 0;
}
else
{
// Has the new owner access to the selected category?
$res = hesk_dbQuery("SELECT `name`,`isadmin`,`categories` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`='{$tmpvar['owner']}' LIMIT 1");
if (hesk_dbNumRows($res) == 1)
{
$row = hesk_dbFetchAssoc($res);
if (!$row['isadmin'])
{
$row['categories']=explode(',',$row['categories']);
if (!in_array($tmpvar['category'],$row['categories']))
{
$_SESSION['isnotice'][] = 'category';
$hesk_error_buffer['owner']=$hesklang['onasc'];
}
}
}
else
{
$_SESSION['isnotice'][] = 'category';
$hesk_error_buffer['owner']=$hesklang['onasc'];
}
}
}
elseif (hesk_checkPermission('can_assign_self',0) && hesk_okCategory($tmpvar['category'],0) && !empty($_POST['assing_to_self']))
{
$tmpvar['owner'] = intval($_SESSION['id']);
} elseif (hesk_checkPermission('can_assign_self', 0) && hesk_okCategory($tmpvar['category'], 0) && !empty($_POST['assing_to_self'])) {
$tmpvar['owner'] = intval($_SESSION['id']);
}
// Notify customer of the ticket?
$notify = ! empty($_POST['notify']) ? 1 : 0;
$notify = (!empty($_POST['notify']) && !empty($tmpvar['email'])) ? 1 : 0;
// Show ticket after submission?
$show = ! empty($_POST['show']) ? 1 : 0;
$show = !empty($_POST['show']) ? 1 : 0;
// Attachments
if ($hesk_settings['attachments']['use'])
{
if ($hesk_settings['attachments']['use']) {
require_once(HESK_PATH . 'inc/attachments.inc.php');
$attachments = array();
$trackingID = $tmpvar['trackid'];
for ($i=1;$i<=$hesk_settings['attachments']['max_number'];$i++)
{
$att = hesk_uploadFile($i);
if ($att !== false && !empty($att))
{
$attachments[$i] = $att;
$trackingID = $tmpvar['trackid'];
$use_legacy_attachments = hesk_POST('use-legacy-attachments', 0);
if ($use_legacy_attachments) {
for ($i = 1; $i <= $hesk_settings['attachments']['max_number']; $i++) {
$att = hesk_uploadFile($i);
if ($att !== false && !empty($att)) {
$attachments[$i] = $att;
}
}
} else {
// The user used the new drag-and-drop system.
$temp_attachment_ids = hesk_POST_array('attachment-ids');
foreach ($temp_attachment_ids as $temp_attachment_id) {
// Simply get the temp info and move it to the attachments table
$temp_attachment = mfh_getTemporaryAttachment($temp_attachment_id);
$attachments[] = $temp_attachment;
mfh_deleteTemporaryAttachment($temp_attachment_id);
}
}
}
$tmpvar['attachments'] = '';
// If we have any errors lets store info in session to avoid re-typing everything
if (count($hesk_error_buffer)!=0)
{
$_SESSION['iserror'] = array_keys($hesk_error_buffer);
if (count($hesk_error_buffer) != 0) {
$_SESSION['iserror'] = array_keys($hesk_error_buffer);
$_SESSION['as_name'] = hesk_POST('name');
$_SESSION['as_email'] = hesk_POST('email');
$_SESSION['as_category'] = hesk_POST('category');
$_SESSION['as_priority'] = hesk_POST('priority');
$_SESSION['as_subject'] = hesk_POST('subject');
$_SESSION['as_message'] = hesk_POST('message');
$_SESSION['as_owner'] = $tmpvar['owner'];
$_SESSION['as_notify'] = $notify;
$_SESSION['as_show'] = $show;
$_SESSION['as_name'] = hesk_POST('name');
$_SESSION['as_email'] = hesk_POST('email');
$_SESSION['as_priority'] = $tmpvar['priority'];
$_SESSION['as_subject'] = hesk_POST('subject');
$_SESSION['as_message'] = hesk_POST('message');
$_SESSION['as_owner'] = $tmpvar['owner'];
$_SESSION['as_notify'] = $notify;
$_SESSION['as_show'] = $show;
foreach ($hesk_settings['custom_fields'] as $k=>$v)
{
if ($v['use'])
{
$_SESSION["as_$k"] = hesk_POST($k);
}
}
foreach ($hesk_settings['custom_fields'] as $k => $v) {
if ($v['use'] && ! in_array($v['type'], array('date', 'email'))) {
$_SESSION["as_$k"] = ($v['type'] == 'checkbox') ? hesk_POST_array($k) : hesk_POST($k);
}
}
$tmp = '';
foreach ($hesk_error_buffer as $error)
{
foreach ($hesk_error_buffer as $error) {
$tmp .= "<li>$error</li>\n";
}
$hesk_error_buffer = $tmp;
// Remove any successfully uploaded attachments
if ($hesk_settings['attachments']['use'])
{
hesk_removeAttachments($attachments);
}
// Remove any successfully uploaded attachments
if ($hesk_settings['attachments']['use']) {
hesk_removeAttachments($attachments);
}
$hesk_error_buffer = $hesklang['pcer'].'<br /><br /><ul>'.$hesk_error_buffer.'</ul>';
hesk_process_messages($hesk_error_buffer,'new_ticket.php');
$hesk_error_buffer = $hesklang['pcer'] . '<br /><br /><ul>' . $hesk_error_buffer . '</ul>';
hesk_process_messages($hesk_error_buffer,'new_ticket.php?category='.$tmpvar['category']);
}
if ($hesk_settings['attachments']['use'] && !empty($attachments))
{
foreach ($attachments as $myatt)
{
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` (`ticket_id`,`saved_name`,`real_name`,`size`) VALUES ('".hesk_dbEscape($tmpvar['trackid'])."','".hesk_dbEscape($myatt['saved_name'])."','".hesk_dbEscape($myatt['real_name'])."','".intval($myatt['size'])."')");
$tmpvar['attachments'] .= hesk_dbInsertID() . '#' . $myatt['real_name'] .',';
if ($hesk_settings['attachments']['use'] && !empty($attachments)) {
foreach ($attachments as $myatt) {
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "attachments` (`ticket_id`,`saved_name`,`real_name`,`size`) VALUES ('" . hesk_dbEscape($tmpvar['trackid']) . "','" . hesk_dbEscape($myatt['saved_name']) . "','" . hesk_dbEscape($myatt['real_name']) . "','" . intval($myatt['size']) . "')");
$tmpvar['attachments'] .= hesk_dbInsertID() . '#' . $myatt['real_name'] . '#' . $myatt['saved_name'] . ',';
}
}
$tmpvar['message']=hesk_makeURL($tmpvar['message']);
$tmpvar['message']=nl2br($tmpvar['message']);
if (!$modsForHesk_settings['rich_text_for_tickets']) {
$tmpvar['message'] = hesk_makeURL($tmpvar['message']);
$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');
$tmpvar['html'] = $modsForHesk_settings['rich_text_for_tickets'];
$tmpvar['due_date'] = hesk_POST('due-date');
// Set user agent and screen res to null
$tmpvar['user_agent'] = NULL;
$tmpvar['screen_resolution_height'] = "NULL";
$tmpvar['screen_resolution_width'] = "NULL";
// Insert ticket to database
$ticket = hesk_newTicket($tmpvar);
mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_created', hesk_date(),
array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'));
if ($autoassign_owner) {
mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_autoassigned', hesk_date(),
array(0 => $autoassign_owner['name'] . ' (' . $autoassign_owner['user'] . ')'));
}
// Notify the customer about the ticket?
if ($notify)
{
hesk_notifyCustomer();
if ($notify && $email_available) {
hesk_notifyCustomer($modsForHesk_settings);
}
// If ticket is assigned to someone notify them?
if ($ticket['owner'] && $ticket['owner'] != intval($_SESSION['id']))
{
// If we don't have info from auto-assign get it from database
if ( ! isset($autoassign_owner['email']) )
{
hesk_notifyAssignedStaff(false, 'ticket_assigned_to_you');
}
else
{
hesk_notifyAssignedStaff($autoassign_owner, 'ticket_assigned_to_you');
if ($ticket['owner'] && $ticket['owner'] != intval($_SESSION['id'])) {
// If we don't have info from auto-assign get it from database
if (!isset($autoassign_owner['email'])) {
hesk_notifyAssignedStaff(false, 'ticket_assigned_to_you', $modsForHesk_settings);
} else {
hesk_notifyAssignedStaff($autoassign_owner, 'ticket_assigned_to_you', $modsForHesk_settings);
}
}
// Ticket unassigned, notify everyone that selected to be notified about unassigned tickets
elseif ( ! $ticket['owner'])
{
hesk_notifyStaff('new_ticket_staff', " `id` != ".intval($_SESSION['id'])." AND `notify_new_unassigned` = '1' ");
} // Ticket unassigned, notify everyone that selected to be notified about unassigned tickets
elseif (!$ticket['owner']) {
hesk_notifyStaff('new_ticket_staff', " `id` != " . intval($_SESSION['id']) . " AND `notify_new_unassigned` = '1' ", $modsForHesk_settings);
}
// Unset temporary variables
@ -295,28 +357,19 @@ hesk_cleanSessionVars('as_message');
hesk_cleanSessionVars('as_owner');
hesk_cleanSessionVars('as_notify');
hesk_cleanSessionVars('as_show');
foreach ($hesk_settings['custom_fields'] as $k=>$v)
{
if ($v['use'])
{
hesk_cleanSessionVars("as_$k");
}
foreach ($hesk_settings['custom_fields'] as $k => $v) {
hesk_cleanSessionVars("as_$k");
}
// If ticket has been assigned to the person submitting it lets show a message saying so
if ($ticket['owner'] && $ticket['owner'] == intval($_SESSION['id']))
{
$hesklang['new_ticket_submitted'] .= '<br />&nbsp;<br />
if ($ticket['owner'] && $ticket['owner'] == intval($_SESSION['id'])) {
$hesklang['new_ticket_submitted'] .= '<br />&nbsp;<br />
<span class="glyphicon glyphicon-comment"></span> <b>' . (isset($autoassign_owner) ? $hesklang['taasy'] : $hesklang['tasy']) . '</b>';
}
// Show the ticket or just the success message
if ($show)
{
hesk_process_messages($hesklang['new_ticket_submitted'],'admin_ticket.php?track=' . $ticket['trackid'] . '&Refresh=' . mt_rand(10000,99999), 'SUCCESS');
}
else
{
hesk_process_messages($hesklang['new_ticket_submitted'].'. <a href="admin_ticket.php?track=' . $ticket['trackid'] . '&Refresh=' . mt_rand(10000,99999) . '">' . $hesklang['view_ticket'] . '</a>', 'new_ticket.php', 'SUCCESS');
}
?>
if ($show) {
hesk_process_messages($hesklang['new_ticket_submitted'], 'admin_ticket.php?track=' . $ticket['trackid'] . '&Refresh=' . mt_rand(10000, 99999), 'SUCCESS');
} else {
hesk_process_messages($hesklang['new_ticket_submitted'] . '. <a href="admin_ticket.php?track=' . $ticket['trackid'] . '&Refresh=' . mt_rand(10000, 99999) . '">' . $hesklang['view_ticket'] . '</a>', 'new_ticket.php', 'SUCCESS');
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
define('IN_SCRIPT',1);
define('HESK_PATH','../');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/privacy_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
// Check permissions for this feature
hesk_checkPermission('can_privacy');
// A security check
hesk_token_check();
// Tracking ID
$trackingID = hesk_cleanID() or die($hesklang['int_error'].': '.$hesklang['no_trackID']);
// Anonymize the ticket and redirect back
if (hesk_anonymizeTicket(0, $trackingID))
{
hesk_process_messages($hesklang['success_anon'],'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999),'SUCCESS');
}
hesk_error($hesklang['no_permission']);

227
admin/api_settings.php Normal file
View File

@ -0,0 +1,227 @@
<?php
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
define('PAGE_TITLE', 'ADMIN_API_SETTINGS');
define('MFH_PAGE_LAYOUT', 'TOP_ONLY');
// Make sure the install folder is deleted
if (is_dir(HESK_PATH . 'install')) {
die('Please delete the <b>install</b> folder from your server for security reasons then refresh this page!');
}
// Get all the required files and functions
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/mail_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
// Check permissions for this feature
hesk_checkPermission('can_man_settings');
$modsForHesk_settings = mfh_getSettings();
define('EXTRA_JS', '<script src="'.HESK_PATH.'internal-api/js/api-settings.js"></script>');
// Print header
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
// Print main manage users page
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
<div class="content-wrapper">
<section class="content">
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['api_information']; ?>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<table class="table table-striped table-fixed">
<tr>
<td class="text-right">
<?php echo $hesklang['api_version']; ?>
</td>
<td class="warning">
<?php echo $hesklang['beta_text']; ?>
</td>
</tr>
<tr>
<td class="text-right">
<?php echo $hesklang['external_api']; ?>
</td>
<td class="success" id="public-api-sidebar">
<?php
$enabled = $modsForHesk_settings['public_api'] == '1' ? '' : 'hide';
$disabled = $modsForHesk_settings['public_api'] == '1' ? 'hide' : '';
?>
<span id="public-api-sidebar-disabled" class="<?php echo $disabled; ?>">
<?php echo $hesklang['disabled_title_case']; ?>
</span>
<span id="public-api-sidebar-enabled" class="<?php echo $enabled; ?>">
<?php echo $hesklang['enabled_title_case']; ?>
</span>
</td>
</tr>
</table>
</div>
</div>
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['api_settings']; ?>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body nav-tabs-custom">
<ul class="nav nav-tabs">
<li class="active"><a href="#general" data-toggle="tab"><?php echo $hesklang['tab_1']; ?></a></li>
<li><a href="#user-security" data-toggle="tab"><?php echo $hesklang['user_security']; ?></a></li>
<li><a href="https://mods-for-hesk.readme.io/reference" target="_blank"><?php echo $hesklang['api_documentation']; ?> <i class="fa fa-external-link"></i></a></li>
</ul>
<div class="tab-content summaryList tabPadding">
<div class="tab-pane fade in active" id="general">
<form class="form-horizontal">
<div class="form-group">
<label for="public-api" class="col-sm-3 control-label">
<?php echo $hesklang['external_api']; ?>
<i class="fa fa-question-circle settingsquestionmark" data-toggle="popover"
title="<?php echo $hesklang['external_api']; ?>"
data-content="<?php echo $hesklang['external_api_help']; ?>"></i>
</label>
<div class="col-sm-9">
<span class="btn-group" data-toggle="buttons">
<?php
$on = $modsForHesk_settings['public_api'] == '1' ? 'active' : '';
$off = $modsForHesk_settings['public_api'] == '1' ? '' : 'active';
?>
<label id="enable-api-button" class="btn btn-success <?php echo $on; ?>">
<input type="radio" name="public-api" value="1"> <i class="fa fa-check-circle"></i>
<?php echo $hesklang['enable']; ?>
</label>
<label id="disable-api-button" class="btn btn-danger <?php echo $off; ?>">
<input type="radio" name="public-api" value="0"> <i class="fa fa-times-circle"></i>
<?php echo $hesklang['disable']; ?>
</label>
</span>
</div>
</div>
<div class="form-group">
<label for="url-rewrite" class="col-sm-3 control-label">
<?php echo $hesklang['url_rewrite']; ?>
<i class="fa fa-question-circle settingsquestionmark" data-toggle="popover"
title="<?php echo $hesklang['url_rewrite']; ?>"
data-content="<?php echo $hesklang['url_rewrite_help']; ?>"></i>
</label>
<div class="col-sm-9">
<span class="btn-group" data-toggle="buttons">
<?php
$on = $modsForHesk_settings['api_url_rewrite'] == '1' ? 'active' : '';
$off = $modsForHesk_settings['api_url_rewrite'] == '1' ? '' : 'active';
?>
<label id="enable-url-rewrite-button" class="btn btn-success <?php echo $on; ?>">
<input type="radio" name="url-rewrite" value="1"> <i class="fa fa-check-circle"></i>
<?php echo $hesklang['enable']; ?>
</label>
<label id="disable-url-rewrite-button" class="btn btn-danger <?php echo $off; ?>">
<input type="radio" name="url-rewrite" value="0"> <i class="fa fa-times-circle"></i>
<?php echo $hesklang['disable']; ?>
</label>
</span>
</div>
</div>
</form>
</div>
<div class="tab-pane fade in" id="user-security">
<?php
$users = array();
$userRs = hesk_dbQuery("SELECT `id`, `user`, `name` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `active` = '1'");
while ($row = hesk_dbFetchAssoc($userRs)) {
$row['number_of_tokens'] = 0;
$users[$row['id']] = $row;
}
$tokensRs = hesk_dbQuery("SELECT `user_id`, 1 FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "user_api_tokens`");
while ($row = hesk_dbFetchAssoc($tokensRs)) {
$users[$row['user_id']]['number_of_tokens']++;
}
?>
<table class="table table-striped">
<thead>
<tr>
<th><?php echo $hesklang['username']; ?></th>
<th><?php echo $hesklang['name']; ?></th>
<th><?php echo $hesklang['number_of_tokens']; ?></th>
<th><?php echo $hesklang['actions']; ?></th>
</tr>
</thead>
<tbody>
<?php
foreach ($users as $row):
?>
<tr>
<td><?php echo $row['user']; ?></td>
<td><?php echo $row['name']; ?></td>
<td id="token-<?php echo $row['id']; ?>-count"><?php echo $row['number_of_tokens']; ?></td>
<td>
<span class="btn-group">
<button class="btn btn-default btn-xs" onclick="generateToken(<?php echo $row['id']; ?>)">
<i class="fa fa-plus-circle"></i>
<?php echo $hesklang['generate_new_token']; ?>
</button>
<button class="btn btn-danger btn-xs" onclick="clearTokens(<?php echo $row['id']; ?>)">
<i class="fa fa-times"></i>
<?php echo $hesklang['revoke_all_tokens']; ?>
</button>
</span>
<span>
<i id="token-<?php echo $row['id']; ?>-success" class="fa fa-check-circle fa-2x green hide media-middle"
data-toggle="tooltip" title="<?php echo $hesklang['changes_saved']; ?>"></i>
<i id="token-<?php echo $row['id']; ?>-failure" class="fa fa-times-circle fa-2x red hide media-middle"
data-toggle="tooltip" title="<?php echo $hesklang['save_failed_check_logs']; ?>"></i>
<i id="token-<?php echo $row['id']; ?>-saving" class="fa fa-spin fa-spinner fa-2x hide media-middle"
data-toggle="tooltip" title="<?php echo $hesklang['saving']; ?>"></i>
</span>
</td>
</tr>
<tr id="token-<?php echo $row['id']; ?>-created" class="success hide">
<td colspan="4">
<?php echo $hesklang['generated_token_colon']; ?> <code class="token"></code>
<p><b><?php echo $hesklang['record_this_token_warning']; ?></b></p>
</td>
</tr>
<tr id="token-<?php echo $row['id']; ?>-reset" class="success hide">
<td colspan="4">
<p><?php echo $hesklang['all_tokens_revoked']; ?></p>
</td>
</tr>
<?php
endforeach;
?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</section>
</div>
<?php
echo mfh_get_hidden_fields_for_language(array('success', 'url_rewrite_saved', 'api_settings_saved', 'an_error_occurred'));
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();

165
admin/assign_owner.php Executable file
View File

@ -0,0 +1,165 @@
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
hesk_load_database_functions();
require(HESK_PATH . 'inc/email_functions.inc.php');
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
$modsForHesk_settings = mfh_getSettings();
$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);
}
/* A security check */
hesk_token_check();
/* Ticket ID */
$trackingID = hesk_cleanID() or die($hesklang['int_error'] . ': ' . $hesklang['no_trackID']);
$res = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `trackid`='" . hesk_dbEscape($trackingID) . "' LIMIT 1");
if (hesk_dbNumRows($res) != 1) {
hesk_error($hesklang['ticket_not_found']);
}
$ticket = hesk_dbFetchAssoc($res);
$_SERVER['PHP_SELF'] = 'admin_ticket.php?track=' . $trackingID . '&Refresh=' . rand(10000, 99999);
/* New owner ID */
$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, `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'] . ')'));
hesk_process_messages($hesklang['tunasi2'], $_SERVER['PHP_SELF'], 'SUCCESS');
} elseif ($owner < 1) {
hesk_process_messages($hesklang['nose'], $_SERVER['PHP_SELF'], 'NOTICE');
}
/* Verify the new owner and permissions */
$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");
$row = hesk_dbFetchAssoc($res);
/* Has new owner access to the category? */
if (!$row['isadmin']) {
$row['categories'] = explode(',', $row['categories']);
if (!in_array($ticket['category'], $row['categories'])) {
hesk_error($hesklang['unoa']);
}
}
// Make sure two people don't assign a ticket to a different user at the same time
if ($ticket['owner'] && $ticket['owner'] != $owner && hesk_REQUEST('unassigned') && hesk_GET('confirm') != 'Y') {
$new_owner = ($owner == $_SESSION['id']) ? $hesklang['scoy'] : sprintf($hesklang['scot'], $row['name']);
$originalOwner = intval($ticket['owner']);
$res = hesk_dbQuery("SELECT `name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`='{$originalOwner}' LIMIT 1");
if (hesk_dbNumRows($res) == 1) {
$row = hesk_dbFetchAssoc($res);
hesk_process_messages(
sprintf($hesklang['taat'], $row['name']) .
'<br /><br />' .
$new_owner .
'<br /><br />' .
'<a href="assign_owner.php?track='.$ticket['trackid'].'&amp;owner='.$owner.'&amp;token='.hesk_token_echo(0).'&amp;unassigned=1&amp;confirm=Y">'.$hesklang['ycto'].'</a> | ' .
'<a href="admin_ticket.php?track='.$ticket['trackid'].'">'.$hesklang['ncto'].'</a>',
$_SERVER['PHP_SELF'], 'NOTICE'
);
}
}
/* Assigning to self? */
if ($can_assign_others || ($owner == $_SESSION['id'] && $can_assign_self)) {
$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(),
array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'));
} else {
// current user -> assigned user
mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_assigned', hesk_date(),
array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')',
1 => $row['name'] . ' (' . $row['user'] . ')'));
}
if ($owner != $_SESSION['id'] && !hesk_checkPermission('can_view_ass_others', 0)) {
$_SERVER['PHP_SELF'] = 'admin_main.php';
}
} else {
hesk_error($hesklang['no_permission']);
}
$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', $modsForHesk_settings);
}
$tmp = ($owner == $_SESSION['id']) ? $hesklang['tasy'] : $hesklang['taso'];
hesk_process_messages($tmp, $_SERVER['PHP_SELF'], 'SUCCESS');
?>

331
admin/banned_emails.php Normal file
View File

@ -0,0 +1,331 @@
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
define('PAGE_TITLE', 'ADMIN_BANNED_EMAILS');
define('MFH_PAGE_LAYOUT', 'TOP_ONLY');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/mail_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
/* Check permissions for this feature */
hesk_checkPermission('can_ban_emails');
$can_unban = hesk_checkPermission('can_unban_emails', 0);
// Define required constants
define('LOAD_TABS', 1);
// What should we do?
if ($action = hesk_REQUEST('a')) {
if (defined('HESK_DEMO')) {
hesk_process_messages($hesklang['ddemo'], 'banned_emails.php', 'NOTICE');
} elseif ($action == 'ban') {
ban_email();
} elseif ($action == 'unban' && $can_unban) {
unban_email();
}
}
/* Print header */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
/* Print main manage users page */
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
<div class="content-wrapper">
<section class="content">
<div class="box">
<div class="box-body">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active">
<a href="#"><?php echo $hesklang['banemail']; ?> <i class="fa fa-question-circle settingsquestionmark"
onclick="javascript:alert('<?php echo hesk_makeJsString($hesklang['banemail_intro']); ?>')"></i></a>
</li>
<?php
// Show a link to banned_ips.php if user has permission to do so
if (hesk_checkPermission('can_ban_ips', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['banip'] . '" href="banned_ips.php">' . $hesklang['banip'] . '</a>
</li>';
}
// Show a link to status_message.php if user has permission to do so
if (hesk_checkPermission('can_service_msg', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['sm_title'] . '" href="service_messages.php">' . $hesklang['sm_title'] . '</a>
</li>';
}
// Show a link to email tpl management if user has permission to do so
if (hesk_checkPermission('can_man_email_tpl', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['email_templates'] . '" href="manage_email_templates.php">' . $hesklang['email_templates'] . '</a>
</li>
';
}
if (hesk_checkPermission('can_man_ticket_statuses', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['statuses'] . '" href="manage_statuses.php">' . $hesklang['statuses'] . '</a>
</li>
';
}
if (hesk_checkPermission('can_man_settings', 0)) {
echo '<li role="presentation"><a title="' . $hesklang['tab_4'] . '" href="custom_fields.php">' . $hesklang['tab_4'] . '</a></li> ';
}
?>
</ul>
<div class="tab-content summaryList tabPadding">
<script language="javascript" type="text/javascript"><!--
function confirm_delete() {
if (confirm('<?php echo hesk_makeJsString($hesklang['delban_confirm']); ?>')) {
return true;
}
else {
return false;
}
}
//-->
</script>
<div class="row">
<div class="col-md-8">
<br><br>
<?php
/* This will handle error, success and notice messages */
hesk_handle_messages();
?>
<form action="banned_emails.php" method="post" name="form1" role="form" class="form-horizontal" data-toggle="validator">
<div class="form-group">
<label for="text" class="col-sm-3 control-label"><?php echo $hesklang['bananemail']; ?></label>
<div class="col-sm-9">
<input type="text" class="form-control" name="email" size="30" maxlength="255" data-error="<?php echo htmlspecialchars($hesklang['enterbanemail']); ?>"
placeholder="<?php echo htmlspecialchars($hesklang['email']); ?>" required>
<input type="hidden" name="token" value="<?php hesk_token_echo(); ?>"/>
<input type="hidden" name="a" value="ban"/>
<div class="help-block with-errors"></div>
</div>
</div>
<div class="form-group">
<div class="col-sm-9 col-sm-offset-3">
<input type="submit" value="<?php echo $hesklang['savebanemail']; ?>"
class="btn btn-default">
</div>
</div>
</form>
</div>
<div class="col-md-4">
<h6 class="bold"><?php echo $hesklang['banex']; ?></h6>
<div class="footerWithBorder blankSpace"></div>
<b>john@example.com</b><br/>
<b>@example.com</b>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<?php
// Get banned emails from database
$res = hesk_dbQuery('SELECT * FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'banned_emails` ORDER BY `email` ASC');
$num = hesk_dbNumRows($res);
echo '<h4>' . $hesklang['eperm'] . '</h4>';
if ($num < 1) {
echo '<p>' . $hesklang['no_banemails'] . '</p>';
} else {
// List of staff
if (!isset($admins)) {
$admins = array();
$res2 = hesk_dbQuery("SELECT `id`,`name` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users`");
while ($row = hesk_dbFetchAssoc($res2)) {
$admins[$row['id']] = $row['name'];
}
}
?>
<table class="table table-hover">
<thead>
<tr>
<th><?php echo $hesklang['email']; ?></th>
<th><?php echo $hesklang['banby']; ?></th>
<th><?php echo $hesklang['date']; ?></th>
<?php
if ($can_unban) {
?>
<th><?php echo $hesklang['opt']; ?></th>
<?php
}
?>
</tr>
</thead>
<tbody>
<?php
while ($ban = hesk_dbFetchAssoc($res)) {
$color = '';
if (isset($_SESSION['ban_email']['id']) && $ban['id'] == $_SESSION['ban_email']['id']) {
$color = 'success';
unset($_SESSION['ban_email']['id']);
}
echo '
<tr>
<td class="' . $color . ' text-left">' . $ban['email'] . '</td>
<td class="' . $color . ' text-left">' . (isset($admins[$ban['banned_by']]) ? $admins[$ban['banned_by']] : $hesklang['e_udel']) . '</td>
<td class="' . $color . ' text-left">' . $ban['dt'] . '</td>
';
if ($can_unban) {
echo '
<td class="' . $color . ' text-left">
<a name="Unban '.$ban['email'].'" href="banned_emails.php?a=unban&amp;id=' . $ban['id'] . '&amp;token=' . hesk_token_echo(0) . '" onclick="return confirm_delete();">
<i class="fa fa-times red font-size-16p" data-toggle="tooltip" data-placement="top" data-original-title="' . $hesklang['delban'] . '"></i>
</a>
</td>
';
}
echo '</tr>';
} // End while
?>
</tbody>
</table>
<?php
}
?>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
<?php
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();
/*** START FUNCTIONS ***/
function ban_email()
{
global $hesk_settings, $hesklang;
// A security check
hesk_token_check();
// Get the email
$email = hesk_emailCleanup(strtolower(hesk_input(hesk_REQUEST('email'))));
// Nothing entered?
if (!strlen($email)) {
hesk_process_messages($hesklang['enterbanemail'], 'banned_emails.php');
}
// Only allow one email to be entered
$email = ($index = strpos($email, ',')) ? substr($email, 0, $index) : $email;
$email = ($index = strpos($email, ';')) ? substr($email, 0, $index) : $email;
// Validate email address
$hesk_settings['multi_eml'] = 0;
if (!hesk_validateEmail($email, '', 0) && !verify_email_domain($email)) {
hesk_process_messages($hesklang['validbanemail'], 'banned_emails.php');
}
// Redirect either to banned emails or ticket page from now on
$redirect_to = ($trackingID = hesk_cleanID()) ? 'admin_ticket.php?track=' . $trackingID . '&Refresh=' . mt_rand(10000, 99999) : 'banned_emails.php';
// Prevent duplicate rows
if ($_SESSION['ban_email']['id'] = hesk_isBannedEmail($email)) {
hesk_process_messages(sprintf($hesklang['emailbanexists'], $email), $redirect_to, 'NOTICE');
}
// Insert the email address into database
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "banned_emails` (`email`,`banned_by`) VALUES ('" . hesk_dbEscape($email) . "','" . intval($_SESSION['id']) . "')");
// Remember email that got banned
$_SESSION['ban_email']['id'] = hesk_dbInsertID();
// Show success
hesk_process_messages(sprintf($hesklang['email_banned'], $email), $redirect_to, 'SUCCESS');
} // End ban_email()
function unban_email()
{
global $hesk_settings, $hesklang;
// A security check
hesk_token_check();
// Delete from bans
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "banned_emails` WHERE `id`=" . intval(hesk_GET('id')));
// Redirect either to banned emails or ticket page from now on
$redirect_to = ($trackingID = hesk_cleanID()) ? 'admin_ticket.php?track=' . $trackingID . '&Refresh=' . mt_rand(10000, 99999) : 'banned_emails.php';
// Show success
hesk_process_messages($hesklang['email_unbanned'], $redirect_to, 'SUCCESS');
} // End unban_email()
function verify_email_domain($domain)
{
// Does it start with an @?
$atIndex = strrpos($domain, "@");
if ($atIndex !== 0) {
return false;
}
// Get the domain and domain length
$domain = substr($domain, 1);
$domainLen = strlen($domain);
// Check domain part length
if ($domainLen < 1 || $domainLen > 254) {
return false;
}
// Check domain part characters
if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)) {
return false;
}
// Domain part mustn't have two consecutive dots
if (strpos($domain, '..') !== false) {
return false;
}
// All OK
return true;
} // END verify_email_domain()
?>

436
admin/banned_ips.php Normal file
View File

@ -0,0 +1,436 @@
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
define('PAGE_TITLE', 'ADMIN_BANNED_IPS');
define('MFH_PAGE_LAYOUT', 'TOP_ONLY');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/mail_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
/* Check permissions for this feature */
hesk_checkPermission('can_ban_ips');
$can_unban = hesk_checkPermission('can_unban_ips', 0);
// Define required constants
define('LOAD_TABS', 1);
// What should we do?
if ($action = hesk_REQUEST('a')) {
if (defined('HESK_DEMO')) {
hesk_process_messages($hesklang['ddemo'], 'banned_ips.php', 'NOTICE');
} elseif ($action == 'ban') {
ban_ip();
} elseif ($action == 'unban' && $can_unban) {
unban_ip();
} elseif ($action == 'unbantemp' && $can_unban) {
unban_temp_ip();
}
}
/* Print header */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
/* Print main manage users page */
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
<div class="content-wrapper">
<section class="content">
<div class="box">
<div class="box-body">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs" role="tablist">
<?php
// Show a link to banned_emails.php if user has permission to do so
if (hesk_checkPermission('can_ban_emails', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['banemail'] . '" href="banned_emails.php">' . $hesklang['banemail'] . '</a>
</li>';
}
?>
<li role="presentation" class="active">
<a href="#"><?php echo $hesklang['banip']; ?> <i class="fa fa-question-circle settingsquestionmark"
onclick="javascript:alert('<?php echo hesk_makeJsString($hesklang['banip_intro']); ?>')"></i></a>
</li>
<?php
// Show a link to status_message.php if user has permission to do so
if (hesk_checkPermission('can_service_msg', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['sm_title'] . '" href="service_messages.php">' . $hesklang['sm_title'] . '</a>
</li>';
}
// Show a link to email tpl management if user has permission to do so
if (hesk_checkPermission('can_man_email_tpl', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['email_templates'] . '" href="manage_email_templates.php">' . $hesklang['email_templates'] . '</a>
</li>
';
}
if (hesk_checkPermission('can_man_ticket_statuses', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['statuses'] . '" href="manage_statuses.php">' . $hesklang['statuses'] . '</a>
</li>
';
}
if (hesk_checkPermission('can_man_settings', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['tab_4'] . '" href="custom_fields.php">' . $hesklang['tab_4'] . '</a>
</li>';
}
?>
</ul>
<div class="tab-content summaryList tabPadding">
<script language="javascript" type="text/javascript"><!--
function confirm_delete() {
if (confirm('<?php echo hesk_makeJsString($hesklang['delban_confirm']); ?>')) {
return true;
}
else {
return false;
}
}
//-->
</script>
<div class="row">
<div class="col-md-8">
<?php
/* This will handle error, success and notice messages */
hesk_handle_messages();
?>
<form action="banned_ips.php" method="post" name="form1" role="form" class="form-horizontal" data-toggle="validator">
<div class="form-group">
<label for="ip" class="col-sm-3 control-label"><?php echo $hesklang['bananip']; ?></label>
<div class="col-sm-9">
<input type="text" name="ip" size="30" maxlength="255" class="form-control" data-error="<?php echo htmlspecialchars($hesklang['enterbanip']); ?>"
placeholder="<?php echo htmlspecialchars($hesklang['iprange']); ?>" required>
<input type="hidden" name="token" value="<?php hesk_token_echo(); ?>"/>
<input type="hidden" name="a" value="ban"/>
<div class="help-block with-errors"></div>
</div>
</div>
<div class="form-group">
<div class="col-sm-9 col-sm-offset-3">
<input type="submit" value="<?php echo $hesklang['savebanip']; ?>" class="btn btn-default">
</div>
</div>
</form>
</div>
<div class="col-md-4">
<h6 class="bold"><?php echo $hesklang['banex']; ?></h6>
<div class="footerWithBorder blankSpace"></div>
<b>123.0.0.0</b><br/>
<b>123.0.0.1 - 123.0.0.53</b><br/>
<b>123.0.0.0/24</b><br/>
<b>123.0.*.*</b>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<?php
// Get login failures
$res = hesk_dbQuery("SELECT `ip`, TIMESTAMPDIFF(MINUTE, NOW(), DATE_ADD(`last_attempt`, INTERVAL " . intval($hesk_settings['attempt_banmin']) . " MINUTE) ) AS `minutes` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "logins` WHERE `number` >= " . intval($hesk_settings['attempt_limit']) . " AND `last_attempt` > (NOW() - INTERVAL " . intval($hesk_settings['attempt_banmin']) . " MINUTE)");
$num = hesk_dbNumRows($res);
echo '<h4>' . $hesklang['iptemp'] . '</h4>';
if ($num > 0) {
?>
<table class="table table-hover">
<thead>
<tr>
<th><?php echo $hesklang['ip']; ?></th>
<th><?php echo $hesklang['m2e']; ?></th>
<?php
if ($can_unban) {
?>
<th><?php echo $hesklang['opt']; ?></th>
<?php
}
?>
</tr>
</thead>
<tbody>
<?php
while ($ban = hesk_dbFetchAssoc($res)) {
echo '
<tr>
<td>' . $ban['ip'] . '</td>
<td>' . $ban['minutes'] . '</td>
';
if ($can_unban) {
echo '
<td>
<a href="banned_ips.php?a=ban&amp;ip=' . urlencode($ban['ip']) . '&amp;token=' . hesk_token_echo(0) . '">
<i class="fa fa-ban red font-size-16p" data-toggle="tooltip" data-placement="top" data-original-title="' . $hesklang['ippermban'] . '"></i></a>
<a href="banned_ips.php?a=unbantemp&amp;ip=' . urlencode($ban['ip']) . '&amp;token=' . hesk_token_echo(0) . '" onclick="return confirm_delete();">
<i class="fa fa-times red font-size-16p" data-toggle="tooltip" data-placement="top" data-original-title="' . $hesklang['delban'] . '"></i></a>
</td>
';
}
echo '</tr>';
} // End while
?>
</tbody>
</table>
<?php
} else {
echo '<p>' . $hesklang['no_banips'] . '</p>';
}
// Get banned ips from database
$res = hesk_dbQuery('SELECT * FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'banned_ips` ORDER BY `ip_from` ASC');
$num = hesk_dbNumRows($res);
echo '<br><h4>' . $hesklang['ipperm'] . '</h4>';
if ($num < 1) {
echo '<p>' . $hesklang['no_banips'] . '</p>';
} else {
// List of staff
if (!isset($admins)) {
$admins = array();
$res2 = hesk_dbQuery("SELECT `id`,`name` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users`");
while ($row = hesk_dbFetchAssoc($res2)) {
$admins[$row['id']] = $row['name'];
}
}
?>
<table class="table table-hover">
<thead>
<tr>
<th><?php echo $hesklang['ip']; ?></th>
<th><?php echo $hesklang['iprange']; ?></th>
<th><?php echo $hesklang['banby']; ?></th>
<th><?php echo $hesklang['date']; ?></th>
<?php
if ($can_unban) {
?>
<th><?php echo $hesklang['opt']; ?></th>
<?php
}
?>
</tr>
</thead>
<tbody>
<?php
while ($ban = hesk_dbFetchAssoc($res)) {
$color = '';
if (isset($_SESSION['ban_ip']['id']) && $ban['id'] == $_SESSION['ban_ip']['id']) {
$color = 'success';
unset($_SESSION['ban_ip']['id']);
}
echo '
<tr>
<td class="' . $color . '">' . $ban['ip_display'] . '</td>
<td class="' . $color . '">' . (($ban['ip_to'] == $ban['ip_from']) ? long2ip($ban['ip_to']) : long2ip($ban['ip_from']) . ' - ' . long2ip($ban['ip_to'])) . '</td>
<td class="' . $color . '">' . (isset($admins[$ban['banned_by']]) ? $admins[$ban['banned_by']] : $hesklang['e_udel']) . '</td>
<td class="' . $color . '">' . $ban['dt'] . '</td>
';
if ($can_unban) {
echo '
<td class="' . $color . ' text-left">
<a name="Unban '.$ban['ip_display'].'" href="banned_ips.php?a=unban&amp;id=' . $ban['id'] . '&amp;token=' . hesk_token_echo(0) . '" onclick="return confirm_delete();">
<i class="fa fa-times red font-size-16p" data-toggle="tooltip" data-placement="top" data-original-title="' . $hesklang['delban'] . '"></i></a>
</td>
';
}
echo '</tr>';
} // End while
?>
</tbody>
</table>
<?php
}
?>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
<?php
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();
/*** START FUNCTIONS ***/
function ban_ip()
{
global $hesk_settings, $hesklang;
// A security check
hesk_token_check();
// Get the ip
$ip = preg_replace('/[^0-9\.\-\/\*]/', '', hesk_REQUEST('ip'));
$ip_display = str_replace('-', ' - ', $ip);
// Nothing entered?
if (!strlen($ip)) {
hesk_process_messages($hesklang['enterbanip'], 'banned_ips.php');
}
// Convert asterisk to ranges
if (strpos($ip, '*') !== false) {
$ip = str_replace('*', '0', $ip) . '-' . str_replace('*', '255', $ip);
}
$ip_regex = '(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])';
// Is this a single IP address?
if (preg_match('/^' . $ip_regex . '$/', $ip)) {
$ip_from = ip2long($ip);
$ip_to = $ip_from;
} // Is this an IP range?
elseif (preg_match('/^' . $ip_regex . '\-' . $ip_regex . '$/', $ip)) {
list($ip_from, $ip_to) = explode('-', $ip);
$ip_from = ip2long($ip_from);
$ip_to = ip2long($ip_to);
} // Is this an IP with CIDR?
elseif (preg_match('/^' . $ip_regex . '\/([0-9]{1,2})$/', $ip, $matches) && $matches[4] >= 0 && $matches[4] <= 32) {
list($ip_from, $ip_to) = hesk_cidr_to_range($ip);
} // Not a valid input
else {
hesk_process_messages($hesklang['validbanip'], 'banned_ips.php');
}
// Make sure we have valid ranges
if ($ip_from < 0) {
$ip_from += 4294967296;
} elseif ($ip_from > 4294967296) {
$ip_from = 4294967296;
}
if ($ip_to < 0) {
$ip_to += 4294967296;
} elseif ($ip_to > 4294967296) {
$ip_to = 4294967296;
}
// Make sure $ip_to is not lower that $ip_from
if ($ip_to < $ip_from) {
$tmp = $ip_to;
$ip_to = $ip_from;
$ip_from = $tmp;
}
// Is this IP address already banned?
$res = hesk_dbQuery("SELECT `id` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "banned_ips` WHERE {$ip_from} BETWEEN `ip_from` AND `ip_to` AND {$ip_to} BETWEEN `ip_from` AND `ip_to` LIMIT 1");
if (hesk_dbNumRows($res) == 1) {
$_SESSION['ban_ip']['id'] = hesk_dbResult($res);
$hesklang['ipbanexists'] = ($ip_to == $ip_from) ? sprintf($hesklang['ipbanexists'], long2ip($ip_to)) : sprintf($hesklang['iprbanexists'], long2ip($ip_from) . ' - ' . long2ip($ip_to));
hesk_process_messages($hesklang['ipbanexists'], 'banned_ips.php', 'NOTICE');
}
// Delete any duplicate banned IP or ranges that are within the new banned range
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "banned_ips` WHERE `ip_from` >= {$ip_from} AND `ip_to` <= {$ip_to}");
// Delete temporary bans from logins table
if ($ip_to == $ip_from) {
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "logins` WHERE `ip`='" . hesk_dbEscape($ip_display) . "'");
}
// Redirect either to banned ips or ticket page from now on
$redirect_to = ($trackingID = hesk_cleanID()) ? 'admin_ticket.php?track=' . $trackingID . '&Refresh=' . mt_rand(10000, 99999) : 'banned_ips.php';
// Insert the ip address into database
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "banned_ips` (`ip_from`,`ip_to`,`ip_display`,`banned_by`) VALUES ({$ip_from}, {$ip_to},'" . hesk_dbEscape($ip_display) . "','" . intval($_SESSION['id']) . "')");
// Remember ip that got banned
$_SESSION['ban_ip']['id'] = hesk_dbInsertID();
// Generate success message
$hesklang['ip_banned'] = ($ip_to == $ip_from) ? sprintf($hesklang['ip_banned'], long2ip($ip_to)) : sprintf($hesklang['ip_rbanned'], long2ip($ip_from) . ' - ' . long2ip($ip_to));
// Show success
hesk_process_messages(sprintf($hesklang['ip_banned'], $ip), $redirect_to, 'SUCCESS');
} // End ban_ip()
function unban_temp_ip()
{
global $hesk_settings, $hesklang;
// A security check
hesk_token_check();
// Get the ip
$ip = preg_replace('/[^0-9\.\-\/\*]/', '', hesk_REQUEST('ip'));
// Delete from bans
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "logins` WHERE `ip`='" . hesk_dbEscape($ip) . "'");
// Show success
hesk_process_messages($hesklang['ip_tempun'], 'banned_ips.php', 'SUCCESS');
} // End unban_temp_ip()
function unban_ip()
{
global $hesk_settings, $hesklang;
// A security check
hesk_token_check();
// Delete from bans
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "banned_ips` WHERE `id`=" . intval(hesk_GET('id')));
// Redirect either to banned ips or ticket page from now on
$redirect_to = ($trackingID = hesk_cleanID()) ? 'admin_ticket.php?track=' . $trackingID . '&Refresh=' . mt_rand(10000, 99999) : 'banned_ips.php';
// Show success
hesk_process_messages($hesklang['ip_unbanned'], $redirect_to, 'SUCCESS');
} // End unban_ip()
function hesk_cidr_to_range($cidr)
{
$range = array();
$cidr = explode('/', $cidr);
$range[0] = (ip2long($cidr[0])) & ((-1 << (32 - (int)$cidr[1])));
$range[1] = (ip2long($cidr[0])) + pow(2, (32 - (int)$cidr[1])) - 1;
return $range;
} // END hesk_cidr_to_range()
?>

629
admin/calendar.php Normal file
View File

@ -0,0 +1,629 @@
<?php
define('IN_SCRIPT', 1);
define('VALIDATOR', 1);
define('HESK_PATH', '../');
define('PAGE_TITLE', 'ADMIN_CALENDAR');
define('MFH_PAGE_LAYOUT', 'TOP_AND_SIDE');
define('USE_JQUERY_2', 1);
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/mail_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
// Define required constants
if (hesk_checkPermission('can_man_calendar', 0)) {
define('MFH_CALENDAR', 1);
} else {
define('MFH_CALENDAR_READONLY', 1);
}
// Is the calendar enabled?
$modsForHesk_settings = mfh_getSettings();
if ($modsForHesk_settings['enable_calendar'] == '0') {
hesk_error($hesklang['calendar_disabled']);
}
// Get categories for the dropdown
$order_by = $modsForHesk_settings['category_order_column'];
$rs = hesk_dbQuery("SELECT `id`, `name`, `background_color`, `foreground_color`, `display_border_outline`
FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "categories`
WHERE `usage` <> 1 ORDER BY `" . hesk_dbEscape($order_by) . "`");
$categories = array();
while ($row = hesk_dbFetchAssoc($rs)) {
if (!$_SESSION['isadmin'] && !in_array($row['id'], $_SESSION['categories'])) {
continue;
}
$row['css_style'] = "background: {$row['background_color']};";
$row['background_volatile'] = 'background-volatile';
if ($row['foreground_color'] != 'AUTO') {
$row['background_volatile'] = '';
$row['css_style'] .= " color: {$row['foreground_color']};";
if ($row['display_border_outline'] == '1') {
$row['css_style'] .= " border: solid 1px {$row['foreground_color']};";
}
}
$categories[] = $row;
}
/* Print header */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
/* Print main manage users page */
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
<aside class="main-sidebar">
<section class="sidebar" style="height: auto">
<ul class="sidebar-menu">
<li class="header text-uppercase"><?php echo $hesklang['calendar_categories']; ?></li>
<?php foreach ($categories as $category): ?>
<li>
<div class="ticket-info">
<div class="hide-on-overflow no-wrap event-category <?php echo $category['background_volatile']; ?>"
data-select-toggle="category-toggle" data-name="category-toggle" data-category-value="<?php echo $category['id']; ?>"
data-checked="1"
data-toggle="tooltip"
title="<?php echo $hesklang['click_to_toggle']; ?>"
style="<?php echo $category['css_style']; ?>">
<?php echo $category['name']; ?>
</div>
</div>
</li>
<?php endforeach; ?>
<li>
<div class="ticket-info">
<button id="select-all" class="btn btn-default btn-sm" data-select-all="category-toggle">
<?php echo $hesklang['select_all_title_case']; ?>
</button>
<button id="deselect-all" class="btn btn-default btn-sm" data-deselect-all="category-toggle">
<?php echo $hesklang['deselect_all_title_case']; ?>
</button>
</div>
<script>
$('#select-all').click(function() {
$('div[data-name="category-toggle"]').attr('data-checked', 1);
updateCategoryVisibility();
});
$('#deselect-all').click(function() {
$('div[data-name="category-toggle"]').attr('data-checked', 0);
updateCategoryVisibility();
});
</script>
</li>
<li class="header text-uppercase"><?php echo $hesklang['legend']; ?></li>
<li>
<div class="ticket-info">
<i class="fa fa-calendar"></i> <?php echo $hesklang['event']; ?>
</div>
</li>
<li>
<div class="ticket-info">
<i class="fa fa-ticket"></i> <?php echo $hesklang['ticket']; ?>
</div>
</li>
<li>
<div class="ticket-info">
<i class="fa fa-exclamation-triangle"></i> <?php echo $hesklang['overdue_ticket_legend']; ?>
</div>
</li>
</ul>
</section>
</aside>
<div class="content-wrapper">
<section class="content">
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-header">
<h1 class="box-title">
<?php echo $hesklang['calendar_title_case']; ?>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body no-padding">
<?php if (hesk_checkPermission('can_man_calendar', 0)): ?>
<div class="row" style="padding-right: 10px">
<div class="col-xs-12 text-right">
<button class="btn btn-success" id="create-event-button">
<i class="fa fa-plus-circle"></i>
<?php echo $hesklang['new_event']; ?>
</button>
</div>
</div>
<?php endif; ?>
<div id="calendar"></div>
</div>
</div>
</div>
</div>
</section>
</div>
<div class="modal fade" id="create-event-modal" tabindex="-1" role="dialog" style="overflow: hidden">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header" style="cursor: move">
<button type="button" class="close cancel-callback" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="myModalLabel">
<?php echo $hesklang['create_event']; ?>
</h4>
</div>
<form id="create-form" class="form-horizontal" data-toggle="validator">
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label for="name" class="col-sm-3 control-label">
<?php echo $hesklang['event_title']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="tooltip"
title="<?php echo htmlspecialchars($hesklang['event_title_tooltip']); ?>"></i></label>
<div class="col-sm-9">
<input type="text" name="name" class="form-control" placeholder="<?php echo htmlspecialchars($hesklang['event_title']); ?>"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
required>
<div class="help-block with-errors"></div>
</div>
</div>
<div class="form-group">
<label for="location" class="col-sm-3 control-label">
<?php echo $hesklang['event_location']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="tooltip"
title="<?php echo htmlspecialchars($hesklang['event_location_tooltip']); ?>"></i>
</label>
<div class="col-sm-9">
<input type="text" name="location" class="form-control"
placeholder="<?php echo htmlspecialchars($hesklang['event_location']); ?>">
<div class="help-block with-errors"></div>
</div>
</div>
<div class="form-group">
<label for="category" class="col-sm-3 control-label">
<?php echo $hesklang['category']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="tooltip"
title="<?php echo htmlspecialchars($hesklang['event_category_tooltip']); ?>"></i>
</label>
<div class="col-sm-9">
<select name="category" class="form-control"
pattern="[0-9]+"
data-error="<?php echo htmlspecialchars($hesklang['sel_app_cat']); ?>" required>
<?php
if ($hesk_settings['select_cat']) {
echo '<option value="">'.$hesklang['select'].'</option>';
}
foreach ($categories as $category): ?>
<option value="<?php echo $category['id']; ?>" data-background-color="<?php echo htmlspecialchars($category['background_color']); ?>"
data-foreground-color="<?php echo htmlspecialchars($category['foreground_color']); ?>"
data-display-border="<?php echo htmlspecialchars($category['display_border_outline']); ?>">
<?php echo $category['name']; ?>
</option>
<?php endforeach; ?>
</select>
<div class="help-block with-errors"></div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="start-date" class="col-sm-6 control-label">
<?php echo $hesklang['event_start']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="tooltip"
title="<?php echo htmlspecialchars($hesklang['event_start_tooltip']); ?>"></i>
</label>
<div class="col-sm-6">
<input type="text" name="start-date" class="form-control datepicker"
placeholder="<?php echo htmlspecialchars($hesklang['event_start_date']); ?>"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
required>
<input type="text" name="start-time" class="form-control clockpicker"
placeholder="<?php echo htmlspecialchars($hesklang['event_start_time']); ?>"
data-placement="left" data-align="top" data-autoclose="true">
<div class="help-block with-errors"></div>
<div class="checkbox">
<label>
<input type="checkbox" name="all-day"> <?php echo $hesklang['event_all_day']; ?>
</label>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="end-date" class="col-sm-6 control-label">
<?php echo $hesklang['event_end']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="tooltip"
title="<?php echo htmlspecialchars($hesklang['event_end_tooltip']); ?>"></i>
</label>
<div class="col-sm-6">
<input type="text" name="end-date" class="form-control datepicker"
placeholder="<?php echo htmlspecialchars($hesklang['event_end_date']); ?>"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
required>
<input type="text" name="end-time" class="form-control clockpicker"
data-placement="left"
data-align="top"
data-autoclose="true"
placeholder="<?php echo htmlspecialchars($hesklang['event_end_time']); ?>">
<div class="help-block with-errors"></div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label for="reminder" class="col-sm-3 control-label">
<?php echo $hesklang['event_reminder']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="tooltip"
title="<?php echo htmlspecialchars($hesklang['event_reminder_tooltip']); ?>"></i>
</label>
<div class="col-sm-2">
<input type="text" name="reminder-value" class="form-control" placeholder="#">
</div>
<div class="col-sm-4">
<select name="reminder-unit" class="form-control">
<option value="MINUTE"><?php echo $hesklang['event_min_before_event']; ?></option>
<option value="HOUR"><?php echo $hesklang['event_hours_before_event']; ?></option>
<option value="DAY"><?php echo $hesklang['event_days_before_event']; ?></option>
<option value="WEEK"><?php echo $hesklang['event_weeks_before_event']; ?></option>
</select>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label for="comments" class="col-sm-3 control-label">
<?php echo $hesklang['event_comments']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="tooltip"
title="<?php echo htmlspecialchars($hesklang['event_comments_tooltip']); ?>"></i>
</label>
<div class="col-sm-9">
<textarea name="comments" class="form-control" placeholder="<?php echo htmlspecialchars($hesklang['event_comments']); ?>"></textarea>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<input type="hidden" name="action" value="create">
<div class="btn-group">
<button type="button" class="btn btn-default cancel-callback" data-dismiss="modal">
<i class="fa fa-times-circle"></i>
<span><?php echo $hesklang['cancel']; ?></span>
</button>
<button type="submit" class="btn btn-success callback-btn">
<i class="fa fa-check-circle"></i>
<span><?php echo $hesklang['save']; ?></span>
</button>
</div>
</div>
</form>
</div>
</div>
</div>
<?php // End create modal, begin edit modal ?>
<div class="modal fade" id="edit-event-modal" tabindex="-1" role="dialog" style="overflow: hidden">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header" style="cursor: move">
<button type="button" class="close cancel-callback" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="myModalLabel">Edit Event</h4>
</div>
<form id="edit-form" class="form-horizontal" data-toggle="validator">
<div class="modal-body">
<ul class="nav nav-tabs" role="tablist" id="edit-modal-tabs">
<li role="presentation" class="active"><a href="#edit-contents" aria-controls="home" role="tab" data-toggle="tab"><?php echo $hesklang['information']; ?></a></li>
<li role="presentation"><a href="#edit-history" aria-controls="profile" role="tab" data-toggle="tab"><?php echo $hesklang['thist']; ?></a></li>
</ul>
<div class="tab-content" id="information-tab">
<div role="tabpanel" class="tab-pane active" id="edit-contents">
<br>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label for="name" class="col-sm-3 control-label">
<?php echo $hesklang['event_title']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="tooltip"
title="<?php echo htmlspecialchars($hesklang['event_title_tooltip']); ?>"></i></label>
<div class="col-sm-9">
<input type="text" name="name" class="form-control"
placeholder="<?php echo htmlspecialchars($hesklang['event_title']); ?>"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
required>
<div class="help-block with-errors"></div>
</div>
</div>
<div class="form-group">
<label for="location" class="col-sm-3 control-label">
<?php echo $hesklang['event_location']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="tooltip"
title="<?php echo htmlspecialchars($hesklang['event_location_tooltip']); ?>"></i>
</label>
<div class="col-sm-9">
<input type="text" name="location" class="form-control"
placeholder="<?php echo htmlspecialchars($hesklang['event_location']); ?>">
<div class="help-block with-errors"></div>
</div>
</div>
<div class="form-group">
<label for="category" class="col-sm-3 control-label">
<?php echo $hesklang['category']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="tooltip"
title="<?php echo htmlspecialchars($hesklang['event_category_tooltip']); ?>"></i>
</label>
<div class="col-sm-9">
<select name="category" class="form-control"
pattern="[0-9]+"
data-error="<?php echo htmlspecialchars($hesklang['sel_app_cat']); ?>" required>
<?php
if ($hesk_settings['select_cat']) {
echo '<option value="">'.$hesklang['select'].'</option>';
}
foreach ($categories as $category): ?>
<option value="<?php echo $category['id']; ?>" data-background-color="<?php echo htmlspecialchars($category['background_color']); ?>"
data-foreground-color="<?php echo htmlspecialchars($category['foreground_color']); ?>"
data-display-border="<?php echo htmlspecialchars($category['display_border_outline']); ?>">
<?php echo $category['name']; ?>
</option>
<?php endforeach; ?>
</select>
<div class="help-block with-errors"></div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="start-date" class="col-sm-6 control-label">
<?php echo $hesklang['event_start']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="tooltip"
title="<?php echo htmlspecialchars($hesklang['event_start_tooltip']); ?>"></i>
</label>
<div class="col-sm-6">
<input type="text" name="start-date" class="form-control datepicker"
placeholder="<?php echo htmlspecialchars($hesklang['event_start_date']); ?>"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
required>
<input type="text" name="start-time" class="form-control clockpicker"
placeholder="<?php echo htmlspecialchars($hesklang['event_start_time']); ?>"
data-placement="left" data-align="top" data-autoclose="true">
<div class="help-block with-errors"></div>
<div class="checkbox">
<label>
<input type="checkbox" name="all-day"> <?php echo $hesklang['event_all_day']; ?>
</label>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="end-date" class="col-sm-6 control-label">
<?php echo $hesklang['event_end']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="tooltip"
title="<?php echo htmlspecialchars($hesklang['event_end_tooltip']); ?>"></i>
</label>
<div class="col-sm-6">
<input type="text" name="end-date" class="form-control datepicker"
placeholder="<?php echo htmlspecialchars($hesklang['event_end_date']); ?>"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
required>
<input type="text" name="end-time" class="form-control clockpicker"
data-placement="left" data-align="top" data-autoclose="true"
placeholder="<?php echo htmlspecialchars($hesklang['event_end_time']); ?>">
<div class="help-block with-errors"></div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label for="reminder" class="col-sm-3 control-label">
<?php echo $hesklang['event_reminder']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="tooltip"
title="<?php echo htmlspecialchars($hesklang['event_reminder_tooltip']); ?>"></i>
</label>
<div class="col-sm-2">
<input type="text" name="reminder-value" class="form-control" placeholder="#">
</div>
<div class="col-sm-4">
<select name="reminder-unit" class="form-control">
<option value="MINUTE"><?php echo $hesklang['event_min_before_event']; ?></option>
<option value="HOUR"><?php echo $hesklang['event_hours_before_event']; ?></option>
<option value="DAY"><?php echo $hesklang['event_days_before_event']; ?></option>
<option value="WEEK"><?php echo $hesklang['event_weeks_before_event']; ?></option>
</select>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label for="comments" class="col-sm-3 control-label">
<?php echo $hesklang['event_comments']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="tooltip"
title="<?php echo htmlspecialchars($hesklang['event_comments_tooltip']); ?>"></i>
</label>
<div class="col-sm-9">
<textarea name="comments" class="form-control" placeholder="<?php echo htmlspecialchars($hesklang['event_comments']); ?>"></textarea>
</div>
</div>
</div>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="edit-history">
<br>
<table class="table table-striped">
<thead>
<tr>
<th><?php echo $hesklang['date']; ?></th>
<th><?php echo $hesklang['description']; ?></th>
</tr>
</thead>
<tbody id="history-table"></tbody>
</table>
</div>
</div>
</div>
<div class="modal-footer">
<input type="hidden" name="id">
<div class="btn-group">
<button type="button" class="btn btn-danger" id="delete-button">
<i class="fa fa-trash"></i>
<span><?php echo $hesklang['delete']; ?></span>
</button>
<a href="#" class="btn btn-primary" id="create-ticket-button">
<i class="fa fa-plus"></i>
<span><?php echo $hesklang['event_create_ticket']; ?></span>
</a>
<button type="button" class="btn btn-default cancel-callback" data-dismiss="modal">
<i class="fa fa-times-circle"></i>
<span><?php echo $hesklang['cancel']; ?></span>
</button>
<button type="submit" class="btn btn-success callback-btn">
<i class="fa fa-check-circle"></i>
<span><?php echo $hesklang['save']; ?></span>
</button>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="popover-template" style="display: none">
<div>
<div class="popover-location">
<strong><?php echo $hesklang['event_location']; ?></strong>
<span></span>
</div>
<div class="popover-category">
<strong><?php echo $hesklang['category']; ?></strong>
<span></span>
</div>
<div class="popover-from">
<strong><?php echo $hesklang['from']; ?></strong>
<span></span>
</div>
<div class="popover-to">
<strong><?php echo $hesklang['to_title_case']; ?></strong>
<span></span>
</div>
<div class="popover-comments">
<strong><?php echo $hesklang['event_comments']; ?></strong>
<span></span>
</div>
</div>
</div>
<div class="ticket-popover-template" style="display: none">
<div>
<div class="popover-tracking-id">
<strong><?php echo $hesklang['trackID']; ?></strong>
<span></span>
</div>
<div class="popover-owner">
<strong><?php echo $hesklang['owner']; ?></strong>
<span></span>
</div>
<div class="popover-subject">
<strong><?php echo $hesklang['subject']; ?></strong>
<span></span>
</div>
<div class="popover-category">
<strong><?php echo $hesklang['category']; ?></strong>
<span></span>
</div>
<div class="popover-status">
<strong><?php echo $hesklang['status']; ?></strong>
<span></span>
</div>
<div class="popover-priority">
<strong><?php echo $hesklang['priority']; ?></strong>
<span></span>
</div>
</div>
</div>
<?php
echo mfh_get_hidden_fields_for_language(array('error_loading_events',
'error_deleting_event',
'event_deleted',
'event_created',
'error_creating_event',
'event_updated',
'error_updating_event',
'ticket_due_date_updated',
'error_updating_ticket_due_date',
'critical',
'high',
'medium',
'low',
'audit_event_created',
'audit_event_updated'));
?>
<div style="display: none">
<p id="setting_first_day_of_week"><?php echo $modsForHesk_settings['first_day_of_week']; ?></p>
<p id="setting_default_view">
<?php
$view_array = array(
0 => 'month',
1 => 'agendaWeek',
2 => 'agendaDay',
);
echo $view_array[$_SESSION['default_calendar_view']];
?>
</p>
<p id="setting_show_start_time"><?php echo $modsForHesk_settings['calendar_show_start_time']; ?></p>
<?php
$businessHoursRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "mfh_calendar_business_hours`");
while ($row = hesk_dbFetchAssoc($businessHoursRs)):
?>
<p id="business_hours_<?php echo $row['day_of_week']; ?>_start"><?php echo $row['start_time']; ?></p>
<p id="business_hours_<?php echo $row['day_of_week']; ?>_end"><?php echo $row['end_time']; ?></p>
<?php endwhile; ?>
</div>
<script type="text/html" id="audit-trail-template">
<tr>
<td data-property="date"></td>
<td data-property="description"></td>
</tr>
</script>
<?php
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();
/*** START FUNCTIONS ***/

View File

@ -1,39 +1,18 @@
<?php
/*******************************************************************************
* Title: Help Desk Software HESK
* Version: 2.5.3 from 16th March 2014
* Author: Klemen Stirn
* Website: http://www.hesk.com
********************************************************************************
* COPYRIGHT AND TRADEMARK NOTICE
* Copyright 2005-2014 Klemen Stirn. All Rights Reserved.
* HESK is a registered trademark of Klemen Stirn.
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
* The HESK may be used and modified free of charge by anyone
* AS LONG AS COPYRIGHT NOTICES AND ALL THE COMMENTS REMAIN INTACT.
* By using this code you agree to indemnify Klemen Stirn from any
* liability that might arise from it's use.
* Selling the code for this program, in part or full, without prior
* written consent is expressly forbidden.
* Using this code, in part or full, to create derivate work,
* new scripts or products is expressly forbidden. Obtain permission
* before redistributing this software over the Internet or in
* any other medium. In all cases copyright and header must remain intact.
* This Copyright is in full effect in any country that has International
* Trade Agreements with the United States of America or
* with the European Union.
* Removing any of the copyright notices without purchasing a license
* is expressly forbidden. To remove HESK copyright notice you must purchase
* a license for this script. For more information on how to obtain
* a license please visit the page below:
* https://www.hesk.com/buy.php
*******************************************************************************/
define('IN_SCRIPT',1);
define('HESK_PATH','../');
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
@ -44,64 +23,127 @@ hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
$modsForHesk_settings = mfh_getSettings();
/* Check permissions for this feature */
hesk_checkPermission('can_view_tickets');
hesk_checkPermission('can_reply_tickets');
if (!isset($_REQUEST['isManager']) || !$_REQUEST['isManager']) {
hesk_checkPermission('can_view_tickets');
hesk_checkPermission('can_reply_tickets');
}
/* A security check */
hesk_token_check();
/* Ticket ID */
$trackingID = hesk_cleanID() or die($hesklang['int_error'].': '.$hesklang['no_trackID']);
$trackingID = hesk_cleanID() or die($hesklang['int_error'] . ': ' . $hesklang['no_trackID']);
$ticket_id_rs = hesk_dbQuery("SELECT `id` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `trackid` = '" . hesk_dbEscape($trackingID) . "'");
$ticket_id_row = hesk_dbFetchAssoc($ticket_id_rs);
$ticket_id = $ticket_id_row['id'];
/* Valid statuses */
$statusSql = "SELECT `ID`, `ShortNameContentKey` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses`";
$statusSql = "SELECT `ID` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses`";
$status_options = array();
$results = hesk_dbQuery($statusSql);
while ($row = $results->fetch_assoc())
{
$status_options[$row['ID']] = $hesklang[$row['ShortNameContentKey']];
while ($row = hesk_dbFetchAssoc($results)) {
$status_options[$row['ID']] = mfh_getDisplayTextForStatusId($row['ID']);
}
/* New status */
$status = intval( hesk_REQUEST('s') );
if ( ! isset($status_options[$status]))
{
hesk_process_messages($hesklang['instat'],'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999),'NOTICE');
$status = intval(hesk_REQUEST('s'));
if (!isset($status_options[$status])) {
hesk_process_messages($hesklang['instat'], 'admin_ticket.php?track=' . $trackingID . '&Refresh=' . mt_rand(10000, 99999), 'NOTICE');
}
$locked = 0;
$statusRow = hesk_dbFetchAssoc(hesk_dbQuery("SELECT `ID`, `IsClosed` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE ID = ".$status));
$audit_closed = null;
$audit_locked = null;
$audit_status = null;
$audit_opened = null;
$statusRow = hesk_dbFetchAssoc(hesk_dbQuery("SELECT `ID`, `IsClosed` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` WHERE ID = " . $status));
if ($statusRow['IsClosed']) // Closed
{
$action = $hesklang['ticket_been'] . ' ' . $hesklang['close'];
$revision = sprintf($hesklang['thist3'],hesk_date(),$_SESSION['name'].' ('.$_SESSION['user'].')');
if ($hesk_settings['custopen'] != 1)
{
$locked = 1;
if ( ! hesk_checkPermission('can_resolve', 0)) {
hesk_process_messages($hesklang['noauth_resolve'],'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999),'NOTICE');
}
}
elseif ($statusRow['ID'] != 0) //Ticket is still open, but not new
$action = $hesklang['ticket_been'] . ' ' . $hesklang['close'];
$audit_closed = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')');
$audit_status = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')',
1 => $status_options[$status]);
if ($hesk_settings['custopen'] != 1) {
$locked = 1;
$audit_locked = array();
}
// Notify customer of closed ticket?
if ($hesk_settings['notify_closed']) {
// Get ticket info
$result = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `trackid`='" . hesk_dbEscape($trackingID) . "' LIMIT 1");
if (hesk_dbNumRows($result) != 1) {
hesk_error($hesklang['ticket_not_found']);
}
$ticket = hesk_dbFetchAssoc($result);
$ticket['status'] = $status;
$ticket['dt'] = hesk_date($ticket['dt'], true);
$ticket['lastchange'] = hesk_date($ticket['lastchange'], true);
$ticket = hesk_ticketToPlain($ticket, 1, 0);
// Notify customer
require(HESK_PATH . 'inc/email_functions.inc.php');
hesk_notifyCustomer($modsForHesk_settings, 'ticket_closed');
}
// Log who marked the ticket resolved
$closedby_sql = ' , `closedat`=NOW(), `closedby`=' . intval($_SESSION['id']) . ' ';
} elseif ($statusRow['IsNewTicketStatus'] == 0) //Ticket is still open, but not new
{
$action = sprintf($hesklang['tsst'],$status_options[$status]);
$revision = sprintf($hesklang['thist9'],hesk_date(),$status_options[$status],$_SESSION['name'].' ('.$_SESSION['user'].')');
}
else // Ticket is marked as "NEW"
$action = sprintf($hesklang['tsst'], $status_options[$status]);
$audit_status = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')',
1 => $status_options[$status]);
// Ticket is not resolved
$closedby_sql = ' , `closedat`=NULL, `closedby`=NULL ';
} else // Ticket is marked as "NEW"
{
$action = $hesklang['ticket_been'] . ' ' . $hesklang['opened'];
$revision = sprintf($hesklang['thist4'],hesk_date(),$_SESSION['name'].' ('.$_SESSION['user'].')');
$action = $hesklang['ticket_been'] . ' ' . $hesklang['opened'];
$audit_opened = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')');
// Ticket is not resolved
$closedby_sql = ' , `closedat`=NULL, `closedby`=NULL ';
}
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `status`='{$status}', `locked`='{$locked}', `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') WHERE `trackid`='".hesk_dbEscape($trackingID)."' LIMIT 1");
if (hesk_dbAffectedRows() != 1)
{
hesk_error("$hesklang[int_error]: $hesklang[trackID_not_found].");
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `status`='{$status}', `locked`='{$locked}' $closedby_sql WHERE `trackid`='" . hesk_dbEscape($trackingID) . "'");
if ($audit_status !== null) {
mfh_insert_audit_trail_record($ticket_id, 'TICKET', 'audit_status', hesk_date(),
$audit_status);
}
hesk_process_messages($action,'admin_ticket.php?track='.$trackingID.'&Refresh='.rand(10000,99999),'SUCCESS');
?>
if ($audit_closed !== null) {
mfh_insert_audit_trail_record($ticket_id, 'TICKET', 'audit_closed', hesk_date(),
$audit_closed);
}
if ($audit_locked !== null) {
mfh_insert_audit_trail_record($ticket_id, 'TICKET', 'audit_automatically_locked', hesk_date(),
array());
}
if ($audit_opened !== null) {
mfh_insert_audit_trail_record($ticket_id, 'TICKET', 'audit_opened', hesk_date(),
$audit_opened);
}
if (hesk_dbAffectedRows() != 1) {
hesk_error("$hesklang[int_error]: $hesklang[trackID_not_found].");
}
hesk_process_messages($action, 'admin_ticket.php?track=' . $trackingID . '&Refresh=' . rand(10000, 99999), 'SUCCESS');

1384
admin/custom_fields.php Executable file

File diff suppressed because it is too large Load Diff

599
admin/delete_tickets.php Normal file
View File

@ -0,0 +1,599 @@
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
$modsForHesk_settings = mfh_getSettings();
/* Set correct return URL */
if (isset($_SERVER['HTTP_REFERER'])) {
$url = hesk_input($_SERVER['HTTP_REFERER']);
$url = str_replace('&amp;', '&', $url);
if ($tmp = strstr($url, 'show_tickets.php')) {
$referer = $tmp;
} elseif ($tmp = strstr($url, 'find_tickets.php')) {
$referer = $tmp;
} elseif ($tmp = strstr($url, 'admin_main.php')) {
$referer = $tmp;
} else {
$referer = 'admin_main.php';
}
} else {
$referer = 'admin_main.php';
}
/* Is this a delete ticket request from within a ticket ("delete" icon)? */
if (isset($_GET['delete_ticket'])) {
/* Check permissions for this feature */
hesk_checkPermission('can_del_tickets');
/* A security check */
hesk_token_check();
// Tracking ID
$trackingID = hesk_cleanID() or die($hesklang['int_error'] . ': ' . $hesklang['no_trackID']);
/* Get ticket info */
$result = hesk_dbQuery("SELECT `id`,`trackid`,`category` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `trackid`='" . hesk_dbEscape($trackingID) . "' LIMIT 1");
if (hesk_dbNumRows($result) != 1) {
hesk_error($hesklang['ticket_not_found']);
}
$ticket = hesk_dbFetchAssoc($result);
/* Is this user allowed to delete tickets inside this category? */
hesk_okCategory($ticket['category']);
hesk_fullyDeleteTicket();
hesk_process_messages(sprintf($hesklang['num_tickets_deleted'], 1), $referer, 'SUCCESS');
}
/* This is a request from ticket list. Must be POST and id must be an array */
if (!isset($_POST['id']) || !is_array($_POST['id'])) {
hesk_process_messages($hesklang['no_selected'], $referer, 'NOTICE');
} /* If not, then needs an action (a) POST variable set */
elseif (!isset($_POST['a'])) {
hesk_process_messages($hesklang['invalid_action'], $referer);
}
$i = 0;
// Possible priorities
$priorities = array(
'critical' => array('value' => 0, 'lang' => 'critical', 'text' => $hesklang['critical'], 'formatted' => '<font class="critical">' . $hesklang['critical'] . '</font>'),
'high' => array('value' => 1, 'lang' => 'high', 'text' => $hesklang['high'], 'formatted' => '<font class="important">' . $hesklang['high'] . '</font>'),
'medium' => array('value' => 2, 'lang' => 'medium', 'text' => $hesklang['medium'], 'formatted' => '<font class="medium">' . $hesklang['medium'] . '</font>'),
'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']);
$res = hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `owner`=0, `assignedby`=NULL WHERE `id`={$this_id} LIMIT 1");
mfh_insert_audit_trail_record($this_id, 'TICKET', 'audit_unassigned', hesk_date(), array(0 => $_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'])) {
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `owner`={$owner}, `assignedby`=".intval($_SESSION['id'])." WHERE `id`={$this_id} LIMIT 1");
mfh_insert_audit_trail_record($this_id, 'TICKET', 'audit_assigned', hesk_date(), array(0 => $_SESSION['name'].' ('.$_SESSION['user'].')',
1 => $owner_data['name'].' ('.$owner_data['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', $modsForHesk_settings);
}
} 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
hesk_token_check('POST');
// Priority info
$priority = $priorities[$_POST['a']];
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 `priority`, `category` 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['priority'] == $priority['value']) {
continue;
}
hesk_okCategory($ticket['category']);
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `priority`='{$priority['value']}' WHERE `id`={$this_id}");
mfh_insert_audit_trail_record($this_id, 'TICKET', 'audit_priority', hesk_date(),
array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')',
1 => $priority['lang']));
$i++;
}
hesk_process_messages($hesklang['pri_set_to'] . ' ' . $priority['formatted'], $referer, 'SUCCESS');
} /* DELETE */
elseif ($_POST['a'] == 'delete') {
/* Check permissions for this feature */
hesk_checkPermission('can_del_tickets');
/* A security check */
hesk_token_check('POST');
// Will we need ticket notifications?
if ($hesk_settings['notify_closed']) {
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 `id`,`trackid`,`category` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `id`='" . intval($this_id) . "' LIMIT 1");
if (hesk_dbNumRows($result) != 1) {
continue;
}
$ticket = hesk_dbFetchAssoc($result);
hesk_okCategory($ticket['category']);
hesk_fullyDeleteTicket();
$i++;
}
hesk_process_messages(sprintf($hesklang['num_tickets_deleted'], $i), $referer, 'SUCCESS');
} /* MERGE TICKETS */
elseif ($_POST['a'] == 'merge') {
/* Check permissions for this feature */
hesk_checkPermission('can_merge_tickets');
/* A security check */
hesk_token_check('POST');
/* Sort IDs, tickets will be merged to the lowest ID */
sort($_POST['id'], SORT_NUMERIC);
/* Select lowest ID as the target ticket */
$merge_into = array_shift($_POST['id']);
/* Merge tickets or throw an error */
if (hesk_mergeTickets($_POST['id'], $merge_into)) {
hesk_process_messages($hesklang['merged'], $referer, 'SUCCESS');
} else {
$hesklang['merge_err'] .= ' ' . $_SESSION['error'];
hesk_cleanSessionVars($_SESSION['error']);
hesk_process_messages($hesklang['merge_err'], $referer);
}
} /* TAG/UNTAG TICKETS */
elseif ($_POST['a'] == 'tag' || $_POST['a'] == 'untag') {
/* Check permissions for this feature */
hesk_checkPermission('can_add_archive');
/* A security check */
hesk_token_check('POST');
if ($_POST['a'] == 'tag') {
$archived = 1;
$action = $hesklang['num_tickets_tag'];
} else {
$archived = 0;
$action = $hesklang['num_tickets_untag'];
}
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`,`category` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `id`='" . intval($this_id) . "' LIMIT 1");
if (hesk_dbNumRows($result) != 1) {
continue;
}
$ticket = hesk_dbFetchAssoc($result);
hesk_okCategory($ticket['category']);
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `archive`='$archived' WHERE `id`='" . intval($this_id) . "'");
$i++;
}
hesk_process_messages(sprintf($action, $i), $referer, 'SUCCESS');
}
/* 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(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');
// 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');
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title><?php echo $hesk_settings['hesk_title']; ?></title>
<meta http-equiv="Content-Type" content="text/html; charset=<?php echo $hesklang['ENCODING']; ?>">
<style type="text/css">
body, table, td, p {
color : black;
font-family : Verdana, Geneva, Arial, Helvetica, sans-serif;
font-size : <?php echo $hesk_settings['print_font_size']; ?>px;
}
table {
border-collapse:collapse;
}
hr {
border: 0;
color: #9e9e9e;
background-color: #9e9e9e;
height: 1px;
width: 100%;
text-align: left;
}
</style>
</head>
<body onload="window.print()">
<?php
// Loop through ticket IDs and print them
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 `t1`.* , `ticketStatus`.`IsClosed` AS `isClosed`, `ticketStatus`.`Key` AS `statusKey`, `t2`.name AS `repliername`
FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` AS `t1` LEFT JOIN `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` AS `t2` ON `t1`.`replierid` = `t2`.`id`
INNER JOIN `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` AS `ticketStatus` ON `t1`.`status` = `ticketStatus`.`ID`
WHERE `t1`.`id`='{$this_id}' LIMIT 1");
if (hesk_dbNumRows($result) != 1) {
continue;
}
$ticket = hesk_dbFetchAssoc($result);
// Check that we have proper permissions to view this ticket
hesk_okCategory($ticket['category']);
$can_view_ass_by = hesk_checkPermission('can_view_ass_by', 0);
$can_view_unassigned = hesk_checkPermission('can_view_unassigned',0);
if ($ticket['owner'] && $ticket['owner'] != $_SESSION['id'] && ! hesk_checkPermission('can_view_ass_others',0)) {
// 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) {
hesk_error($hesklang['ycovtay']);
}
// All good, continue...
$category['name'] = isset($hesk_settings['categories'][$ticket['category']]) ? $hesk_settings['categories'][$ticket['category']] : $hesklang['catd'];
// Get replies
$res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` WHERE `replyto`='{$ticket['id']}' ORDER BY `id` ASC");
$replies = hesk_dbNumRows($res);
// Print ticket
require(HESK_PATH . 'inc/print_template.inc.php');
flush();
}
?>
</body>
</html>
<?php
exit();
}
/* JUST CLOSE */
else {
/* Check permissions for this feature */
hesk_checkPermission('can_view_tickets');
hesk_checkPermission('can_reply_tickets');
hesk_checkPermission('can_resolve');
/* A security check */
hesk_token_check('POST');
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`='" . intval($this_id) . "' LIMIT 1");
$ticket = hesk_dbFetchAssoc($result);
hesk_okCategory($ticket['category']);
$closedStatusRS = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` WHERE `IsStaffClosedOption` = 1");
$closedStatus = hesk_dbFetchAssoc($closedStatusRS);
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `status`='" . $closedStatus['ID'] . "', `closedat`=NOW(), `closedby`=" . intval($_SESSION['id']) . " WHERE `id`='" . intval($this_id) . "'");
mfh_insert_audit_trail_record($this_id, 'TICKET', 'audit_closed', hesk_date(),
array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'));
$i++;
// Notify customer of closed ticket?
if ($hesk_settings['notify_closed']) {
$ticket['dt'] = hesk_date($ticket['dt'], true);
$ticket['lastchange'] = hesk_date($ticket['lastchange'], true);
$ticket = hesk_ticketToPlain($ticket, 1, 0);
hesk_notifyCustomer($modsForHesk_settings, 'ticket_closed');
}
}
hesk_process_messages(sprintf($hesklang['num_tickets_closed'], $i), $referer, 'SUCCESS');
}
/*** START FUNCTIONS ***/
function hesk_fullyDeleteTicket()
{
global $hesk_settings, $hesklang, $ticket;
/* Delete attachment files */
$res = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "attachments` WHERE `ticket_id`='" . hesk_dbEscape($ticket['trackid']) . "'");
if (hesk_dbNumRows($res)) {
$hesk_settings['server_path'] = dirname(dirname(__FILE__));
while ($file = hesk_dbFetchAssoc($res)) {
hesk_unlink($hesk_settings['server_path'] . '/' . $hesk_settings['attach_dir'] . '/' . $file['saved_name']);
}
}
/* Delete attachments info from the database */
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "attachments` WHERE `ticket_id`='" . hesk_dbEscape($ticket['trackid']) . "'");
/* Delete the ticket */
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `id`='" . intval($ticket['id']) . "'");
/* Delete replies to the ticket */
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` WHERE `replyto`='" . intval($ticket['id']) . "'");
/* Delete ticket notes */
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "notes` WHERE `ticket`='" . intval($ticket['id']) . "'");
/* Delete audit trail records */
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "audit_trail_to_replacement_values`
WHERE `audit_trail_id` IN (
SELECT `id` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "audit_trail`
WHERE `entity_type` = 'TICKET' AND `entity_id` = " . intval($ticket['id']) . ")");
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "audit_trail` WHERE `entity_type`='TICKET'
AND `entity_id` = " . intval($ticket['id']));
/* Delete ticket reply drafts */
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "reply_drafts` WHERE `ticket`=" . intval($ticket['id']));
return true;
}
?>

133
admin/edit_note.php Normal file
View File

@ -0,0 +1,133 @@
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
define('MFH_PAGE_LAYOUT', 'TOP_ONLY');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/mail_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
/* Check permissions for this feature */
hesk_checkPermission('can_view_tickets');
// Ticket ID
$trackingID = hesk_cleanID() or die($hesklang['int_error'] . ': ' . $hesklang['no_trackID']);
// Note ID
$noteID = intval(hesk_REQUEST('note')) or die($hesklang['int_error'] . ': ' . $hesklang['mis_note']);
// Get ticket info
$result = hesk_dbQuery("SELECT `id` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `trackid`='" . hesk_dbEscape($trackingID) . "' LIMIT 1");
if (hesk_dbNumRows($result) != 1) {
hesk_error($hesklang['ticket_not_found']);
}
$ticket = hesk_dbFetchAssoc($result);
// Get note info
$result = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "notes` WHERE `id`={$noteID}");
if (hesk_dbNumRows($result) != 1) {
hesk_error($hesklang['no_note']);
}
$note = hesk_dbFetchAssoc($result);
// Make sure the note matches the ticket and the user has permission to edit it
if ($note['ticket'] != $ticket['id'] || (!hesk_checkPermission('can_del_notes', 0) && $note['who'] != $_SESSION['id'])) {
hesk_error($hesklang['perm_deny']);
}
// Save changes?
if (isset($_POST['save'])) {
// A security check
hesk_token_check('POST');
// Get message
$tmpvar['message'] = nl2br(hesk_makeURL(hesk_input(hesk_POST('message'))));
// If we have message or attachments do the update
if (strlen($tmpvar['message']) || strlen($note['attachments'])) {
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "notes` SET `message`='" . hesk_dbEscape($tmpvar['message']) . "' WHERE `id`={$noteID}");
hesk_process_messages($hesklang['ednote2'], 'admin_ticket.php?track=' . $trackingID . '&Refresh=' . mt_rand(10000, 99999), 'SUCCESS');
} // If not, delete the note
else {
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "notes` WHERE `id`={$noteID}");
header('Location: admin_ticket.php?track=' . $trackingID . '&Refresh=' . mt_rand(10000, 99999));
exit();
}
}
$note['message'] = hesk_msgToPlain($note['message'], 0, 0);
/* Print header */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
/* Print admin navigation */
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
<div class="content-wrapper">
<ol class="breadcrumb">
<li>
<a href="admin_ticket.php?track=<?php echo $trackingID; ?>&amp;Refresh=<?php echo mt_rand(10000, 99999); ?>"><?php echo $hesklang['ticket'] . ' ' . $trackingID; ?></a>
</li>
<li class="active"><?php echo $hesklang['ednote']; ?></li>
</ol>
<section class="content">
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['ednote']; ?>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<form method="post" action="edit_note.php" name="form1" class="form-horizontal" role="form">
<div class="form-group">
<label for="message" class="col-md-2 control-label"><?php echo $hesklang['message']; ?></label>
<div class="col-md-10">
<textarea name="message" class="form-control" rows="12"
cols="60"><?php echo $note['message']; ?></textarea>
</div>
</div>
<div class="form-group">
<div class="col-md-10 col-md-offset-2">
<input type="hidden" name="save" value="1">
<input type="hidden" name="track" value="<?php echo $trackingID; ?>">
<input type="hidden" name="token" value="<?php hesk_token_echo(); ?>">
<input type="hidden" name="note" value="<?php echo $noteID; ?>">
<div class="btn-group">
<input type="submit" value="<?php echo $hesklang['save_changes']; ?>" class="btn btn-primary">
<a href="javascript:history.go(-1)" class="btn btn-default"><?php echo $hesklang['back']; ?></a>
</div>
</div>
</div>
</form>
</div>
</div>
</section>
</div>
<?php
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

54
admin/export_ticket.php Normal file
View File

@ -0,0 +1,54 @@
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
define('IN_SCRIPT',1);
define('HESK_PATH','../');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/privacy_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
// Check permissions for this feature
hesk_checkPermission('can_export');
// A security check
hesk_token_check();
// Tracking ID
$trackingID = hesk_cleanID() or die($hesklang['int_error'].': '.$hesklang['no_trackID']);
// Generate SQL for the ticket, make sure the user has access to it
$sql = "SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `trackid`='".hesk_dbEscape($trackingID)."' AND ";
$sql .= hesk_myCategories();
$sql .= " AND " . hesk_myOwnership();
$sql .= " LIMIT 1";
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 == 1)
{
hesk_process_messages($success_msg,'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999),'SUCCESS');
}
hesk_error($hesklang['n2ex']);

View File

@ -1,51 +1,34 @@
<?php
/*******************************************************************************
* Title: Help Desk Software HESK
* Version: 2.5.3 from 16th March 2014
* Author: Klemen Stirn
* Website: http://www.hesk.com
********************************************************************************
* COPYRIGHT AND TRADEMARK NOTICE
* Copyright 2005-2013 Klemen Stirn. All Rights Reserved.
* HESK is a registered trademark of Klemen Stirn.
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
* The HESK may be used and modified free of charge by anyone
* AS LONG AS COPYRIGHT NOTICES AND ALL THE COMMENTS REMAIN INTACT.
* By using this code you agree to indemnify Klemen Stirn from any
* liability that might arise from it's use.
* Selling the code for this program, in part or full, without prior
* written consent is expressly forbidden.
* Using this code, in part or full, to create derivate work,
* new scripts or products is expressly forbidden. Obtain permission
* before redistributing this software over the Internet or in
* any other medium. In all cases copyright and header must remain intact.
* This Copyright is in full effect in any country that has International
* Trade Agreements with the United States of America or
* with the European Union.
* Removing any of the copyright notices without purchasing a license
* is expressly forbidden. To remove HESK copyright notice you must purchase
* a license for this script. For more information on how to obtain
* a license please visit the page below:
* https://www.hesk.com/buy.php
*******************************************************************************/
define('IN_SCRIPT',1);
define('HESK_PATH','../');
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
define('PAGE_TITLE', 'ADMIN_HOME');
define('MFH_PAGE_LAYOUT', 'TOP_ONLY');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/status_functions.inc.php');
require(HESK_PATH . 'inc/mail_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
define('CALENDAR',1);
define('CALENDAR', 1);
$_SESSION['hide']['ticket_list'] = true;
/* Check permissions for this feature */
@ -53,202 +36,250 @@ hesk_checkPermission('can_view_tickets');
$_SERVER['PHP_SELF'] = './admin_main.php';
// Load custom fields
require_once(HESK_PATH . 'inc/custom_fields.inc.php');
/* Print header */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
/* Print admin navigation */
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
</td>
</tr>
<tr>
<td>
<h3 align="center"><?php echo $hesklang['tickets_found']; ?></h3>
<?php
// This SQL code will be used to retrieve results
$sql_final = "SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE ";
$sql_final = "SELECT
`id`,
`trackid`,
`name`,
`email`,
`category`,
`priority`,
`subject`,
LEFT(`message`, 400) AS `message`,
`dt`,
`lastchange`,
`firstreply`,
`closedat`,
`status`,
`openedby`,
`firstreplyby`,
`closedby`,
`replies`,
`staffreplies`,
`owner`,
`time_worked`,
`lastreplier`,
`replierid`,
`archive`,
`locked`,
`merged`
";
// This code will be used to count number of results
$sql_count = "SELECT COUNT(*) FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE ";
foreach ($hesk_settings['custom_fields'] as $k => $v) {
if ($v['use']) {
$sql_final .= ", `" . $k . "`";
}
}
// This is common SQL for both queries
$sql = "";
$sql_final .= " FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE ";
// Some default settings
$archive = array(1=>0,2=>0);
$s_my = array(1=>1,2=>1);
$s_ot = array(1=>1,2=>1);
$s_un = array(1=>1,2=>1);
// This code will be used to count number of results
$sql_count = "SELECT COUNT(*) FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE ";
// --> TICKET CATEGORY
$category = intval( hesk_GET('category', 0) );
// This is common SQL for both queries
$sql = "";
// Make sure user has access to this category
if ($category && hesk_okCategory($category, 0) )
{
$sql .= " `category`='{$category}' ";
}
// No category selected, show only allowed categories
else
{
$sql .= hesk_myCategories();
}
// Some default settings
$archive = array(1 => 0, 2 => 0);
$s_my = array(1 => 1, 2 => 1);
$s_ot = array(1 => 1, 2 => 1);
$s_un = array(1 => 1, 2 => 1);
// Show only tagged tickets?
if ( ! empty($_GET['archive']) )
{
$archive[2]=1;
$sql .= " AND `archive`='1' ";
}
// --> TICKET CATEGORY
$category = intval(hesk_GET('category', 0));
// Ticket owner preferences
$fid = 2;
require(HESK_PATH . 'inc/assignment_search.inc.php');
// Make sure user has access to this category
if ($category && hesk_okCategory($category, 0)) {
$sql .= " `category`='{$category}' ";
} // No category selected, show only allowed categories
else {
$sql .= hesk_myCategories();
}
$hesk_error_buffer = '';
$no_query = 0;
// Show only tagged tickets?
if (!empty($_GET['archive'])) {
$archive[2] = 1;
$sql .= " AND `archive`='1' ";
}
// Search query
$q = stripslashes( hesk_input( hesk_GET('q', '') ) );
// Ticket owner preferences
$fid = 2;
require(HESK_PATH . 'inc/assignment_search.inc.php');
// No query entered?
if ( ! strlen($q) )
{
$hesk_error_buffer .= $hesklang['fsq'];
$no_query = 1;
}
$hesk_error_buffer = '';
$no_query = 0;
// What field are we searching in
$what = hesk_GET('what', '') or $hesk_error_buffer .= '<br />' . $hesklang['wsel'];
// Search query
$q = stripslashes(hesk_input(hesk_GET('q', '')));
// Sequential ID supported?
if ($what == 'seqid' && ! $hesk_settings['sequential'])
{
$what = 'trackid';
}
// No query entered?
if (!strlen($q)) {
$hesk_error_buffer .= $hesklang['fsq'];
$no_query = 1;
}
// Setup SQL based on searching preferences
if ( ! $no_query)
{
$sql .= " AND ";
// What field are we searching in
$what = hesk_GET('what', '') or $hesk_error_buffer .= '<br />' . $hesklang['wsel'];
switch ($what)
{
case 'trackid':
$sql .= " ( `trackid` = '".hesk_dbEscape($q)."' OR `merged` LIKE '%#".hesk_dbEscape($q)."#%' ) ";
break;
case 'name':
$sql .= "`name` LIKE '%".hesk_dbEscape($q)."%' COLLATE '" . hesk_dbEscape($hesklang['_COLLATE']) . "' ";
break;
case 'email':
$sql .= "`email` LIKE '%".hesk_dbEscape($q)."%' ";
break;
case 'subject':
$sql .= "`subject` LIKE '%".hesk_dbEscape($q)."%' COLLATE '" . hesk_dbEscape($hesklang['_COLLATE']) . "' ";
break;
case 'message':
$sql .= " ( `message` LIKE '%".hesk_dbEscape($q)."%' COLLATE '" . hesk_dbEscape($hesklang['_COLLATE']) . "'
// Sequential ID supported?
if ($what == 'seqid' && !$hesk_settings['sequential']) {
$what = 'trackid';
}
// Setup SQL based on searching preferences
if (!$no_query) {
$sql .= " AND ";
switch ($what) {
case 'trackid':
$sql .= " ( `trackid` = '" . hesk_dbEscape($q) . "' OR `merged` LIKE '%#" . hesk_dbEscape($q) . "#%' ) ";
break;
case 'name':
$sql .= "`name` LIKE '%".hesk_dbEscape( hesk_dbLike($q) )."%' COLLATE '" . hesk_dbCollate() . "' ";
break;
case 'email':
$sql .= "`email` LIKE '%" . hesk_dbEscape($q) . "%' ";
break;
case 'subject':
$sql .= "`subject` LIKE '%".hesk_dbEscape( hesk_dbLike($q) )."%' COLLATE '" . hesk_dbCollate() . "' ";
break;
case 'message':
$sql .= " ( `message` LIKE '%".hesk_dbEscape( hesk_dbLike($q) )."%' COLLATE '" . hesk_dbCollate() . "'
OR
`id` IN (
SELECT DISTINCT `replyto`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."replies`
WHERE `message` LIKE '%".hesk_dbEscape($q)."%' COLLATE '" . hesk_dbEscape($hesklang['_COLLATE']) . "' )
FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies`
WHERE `message` LIKE '%".hesk_dbEscape( hesk_dbLike($q) )."%' COLLATE '" . hesk_dbCollate() . "' )
)
";
break;
case 'seqid':
$sql .= "`id` = '".intval($q)."' ";
break;
case 'notes':
$sql .= "`id` IN (
break;
case 'seqid':
$sql .= "`id` = '" . intval($q) . "' ";
break;
case 'notes':
$sql .= "`id` IN (
SELECT DISTINCT `ticket`
FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."notes`
WHERE `message` LIKE '%".hesk_dbEscape($q)."%' COLLATE '" . hesk_dbEscape($hesklang['_COLLATE']) . "' )
FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "notes`
WHERE `message` LIKE '%".hesk_dbEscape( hesk_dbLike($q) )."%' COLLATE '" . hesk_dbCollate() . "' )
";
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_dbEscape($hesklang['_COLLATE']) . "' ";
}
else
{
$hesk_error_buffer .= '<br />' . $hesklang['invalid_search'];
}
}
}
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() . "' ";
} else {
$hesk_error_buffer .= '<br />' . $hesklang['invalid_search'];
}
}
}
/* Date */
/* -> Check for compatibility with old date format */
if (preg_match("/(\d{4})-(\d{2})-(\d{2})/", hesk_GET('dt'), $m))
{
$_GET['dt']=$m[2].$m[3].$m[1];
}
// Owner
if ($tmp = intval(hesk_GET('owner', 0))) {
$sql .= " AND `owner`={$tmp} ";
$owner_input = $tmp;
$hesk_error_buffer = str_replace($hesklang['fsq'], '', $hesk_error_buffer);
} else {
$owner_input = 0;
}
/* -> Now process the date value */
$dt = preg_replace('/[^0-9]/','', hesk_GET('dt') );
if (strlen($dt) == 8)
{
$date = substr($dt,4,4) . '-' . substr($dt,0,2) . '-' . substr($dt,2,2);
$date_input= substr($dt,0,2) . '/' . substr($dt,2,2) . '/' . substr($dt,4,4);
/* Date */
/* -> Now process the date value */
$dt = preg_replace('/[^0-9]/', '', hesk_GET('dt'));
if (strlen($dt) == 8) {
$date = substr($dt, 0, 4) . '-' . substr($dt, 4, 2) . '-' . substr($dt, 6, 2);
$date_input = $date;
/* This search is valid even if no query is entered */
if ($no_query)
{
$hesk_error_buffer = str_replace($hesklang['fsq'],'',$hesk_error_buffer);
}
/* This search is valid even if no query is entered */
if ($no_query) {
$hesk_error_buffer = str_replace($hesklang['fsq'], '', $hesk_error_buffer);
}
$sql .= " AND (`dt` LIKE '".hesk_dbEscape($date)."%' OR `lastchange` LIKE '".hesk_dbEscape($date)."%') ";
}
else
{
$date = '';
$date_input = '';
}
$sql .= " AND `dt` BETWEEN '{$date} 00:00:00' AND '{$date} 23:59:59' ";
} else {
$date = '';
$date_input = '';
}
/* Any errors? */
if (strlen($hesk_error_buffer))
{
hesk_process_messages($hesk_error_buffer,'NOREDIRECT');
}
/* Any errors? */
if (strlen($hesk_error_buffer)) {
hesk_process_messages($hesk_error_buffer, 'NOREDIRECT');
}
/* This will handle error, success and notice messages */
$handle = hesk_handle_messages();
# echo "$sql<br/>";
# echo "$sql<br/>";
// That's all the SQL we need for count
$sql_count .= $sql;
$sql = $sql_final . $sql;
// That's all the SQL we need for count
$sql_count .= $sql;
$sql = $sql_final . $sql;
// Strip extra slashes
$q = stripslashes($q);
/* Prepare variables used in search and forms */
require_once(HESK_PATH . 'inc/prepare_ticket_search.inc.php');
/* Prepare variables used in search and forms */
require_once(HESK_PATH . 'inc/prepare_ticket_search.inc.php');
?>
<div class="content-wrapper">
<section class="content">
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['tickets']; ?>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<?php $handle = hesk_handle_messages(); ?>
<div class="row">
<div class="col-xs-6 text-left">
<div class="checkbox">
<label>
<input type="checkbox" onclick="toggleAutoRefresh(this);" id="reloadCB">
<?php echo $hesklang['arp']; ?>
<span id="timer"></span>
</label>
</div>
<script type="text/javascript">heskCheckReloading();</script>
</div>
<div class="col-xs-6 text-right">
<a href="new_ticket.php" class="btn btn-success">
<span class="glyphicon glyphicon-plus-sign"></span>
<?php echo $hesklang['nti']; ?>
</a>
</div>
</div>
<?php
if ($handle !== FALSE) {
$href = 'find_tickets.php';
require_once(HESK_PATH . 'inc/ticket_list.inc.php');
echo '<br>';
}
/* If there has been an error message skip searching for tickets */
if ($handle !== FALSE)
{
$href = 'find_tickets.php';
require_once(HESK_PATH . 'inc/ticket_list.inc.php');
}
?>
/* Clean unneeded session variables */
hesk_cleanSessionVars('hide');
<hr />
<?php
/* Clean unneeded session variables */
hesk_cleanSessionVars('hide');
/* Show the search form */
require_once(HESK_PATH . 'inc/show_search_form.inc.php');
/* Print footer */
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();
?>
/* Show the search form */
require_once(HESK_PATH . 'inc/show_search_form.inc.php');
?>
</div>
</div>
</section>
</div>
<?php
/* Print footer */
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();

View File

@ -1,39 +1,19 @@
<?php
/*******************************************************************************
* Title: Help Desk Software HESK
* Version: 2.5.3 from 16th March 2014
* Author: Klemen Stirn
* Website: http://www.hesk.com
********************************************************************************
* COPYRIGHT AND TRADEMARK NOTICE
* Copyright 2005-2013 Klemen Stirn. All Rights Reserved.
* HESK is a registered trademark of Klemen Stirn.
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
* The HESK may be used and modified free of charge by anyone
* AS LONG AS COPYRIGHT NOTICES AND ALL THE COMMENTS REMAIN INTACT.
* By using this code you agree to indemnify Klemen Stirn from any
* liability that might arise from it's use.
* Selling the code for this program, in part or full, without prior
* written consent is expressly forbidden.
* Using this code, in part or full, to create derivate work,
* new scripts or products is expressly forbidden. Obtain permission
* before redistributing this software over the Internet or in
* any other medium. In all cases copyright and header must remain intact.
* This Copyright is in full effect in any country that has International
* Trade Agreements with the United States of America or
* with the European Union.
* Removing any of the copyright notices without purchasing a license
* is expressly forbidden. To remove HESK copyright notice you must purchase
* a license for this script. For more information on how to obtain
* a license please visit the page below:
* https://www.hesk.com/buy.php
*******************************************************************************/
define('IN_SCRIPT',1);
define('HESK_PATH','../');
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
define('PAGE_TITLE', 'LOGIN');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
@ -43,223 +23,226 @@ hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
$modsForHesk_settings = mfh_getSettings();
/* What should we do? */
$action = hesk_REQUEST('a');
switch ($action)
{
switch ($action) {
case 'do_login':
do_login();
do_login();
break;
case 'login':
print_login();
print_login();
break;
case 'logout':
logout();
logout();
break;
default:
hesk_autoLogin();
print_login();
hesk_autoLogin();
print_login();
}
/* Print footer */
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();
/*** START FUNCTIONS ***/
function do_login()
{
global $hesk_settings, $hesklang;
global $hesk_settings, $hesklang, $modsForHesk_settings;
$hesk_error_buffer = array();
$user = hesk_input( hesk_POST('user') );
if (empty($user))
{
$myerror = $hesk_settings['list_users'] ? $hesklang['select_username'] : $hesklang['enter_username'];
$user = hesk_input(hesk_POST('user'));
if (empty($user)) {
$myerror = $hesk_settings['list_users'] ? $hesklang['select_username'] : $hesklang['enter_username'];
$hesk_error_buffer['user'] = $myerror;
}
define('HESK_USER', $user);
$pass = hesk_input( hesk_POST('pass') );
if (empty($pass))
{
$hesk_error_buffer['pass'] = $hesklang['enter_pass'];
}
if ($hesk_settings['secimg_use'] == 2 && !isset($_SESSION['img_a_verified']))
{
// Using ReCaptcha?
if ($hesk_settings['recaptcha_use'])
{
require_once(HESK_PATH . 'inc/recaptcha/recaptchalib.php');
$resp = recaptcha_check_answer($hesk_settings['recaptcha_private_key'],
$_SERVER['REMOTE_ADDR'],
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 PHP generated image
else
{
$mysecnum = intval( hesk_POST('mysecnum', 0) );
if ( empty($mysecnum) )
{
$hesk_error_buffer['mysecnum'] = $hesklang['sec_miss'];
}
else
{
require(HESK_PATH . 'inc/secimg.inc.php');
$sc = new PJ_SecurityImage($hesk_settings['secimg_sum']);
if ( isset($_SESSION['checksum']) && $sc->checkCode($mysecnum, $_SESSION['checksum']) )
{
$_SESSION['img_a_verified'] = true;
}
else
{
$hesk_error_buffer['mysecnum'] = $hesklang['sec_wrng'];
}
}
}
}
/* Any missing fields? */
if (count($hesk_error_buffer)!=0)
{
$_SESSION['a_iserror'] = array_keys($hesk_error_buffer);
$tmp = '';
foreach ($hesk_error_buffer as $error)
{
$tmp .= "<li>$error</li>\n";
}
$hesk_error_buffer = $tmp;
$hesk_error_buffer = $hesklang['pcer'].'<br /><br /><ul>'.$hesk_error_buffer.'</ul>';
hesk_process_messages($hesk_error_buffer,'NOREDIRECT');
print_login();
exit();
}
elseif (isset($_SESSION['img_a_verified']))
{
unset($_SESSION['img_a_verified']);
$pass = hesk_input(hesk_POST('pass'));
if (empty($pass)) {
$hesk_error_buffer['pass'] = $hesklang['enter_pass'];
}
/* User entered all required info, now lets limit brute force attempts */
hesk_limitBfAttempts();
if ($hesk_settings['secimg_use'] == 2 && !isset($_SESSION['img_a_verified'])) {
// Using ReCaptcha?
if ($hesk_settings['recaptcha_use']) {
require(HESK_PATH . 'inc/recaptcha/recaptchalib_v2.php');
$result = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `user` = '".hesk_dbEscape($user)."' LIMIT 1");
if (hesk_dbNumRows($result) != 1)
{
hesk_session_stop();
$_SESSION['a_iserror'] = array('user','pass');
hesk_process_messages($hesklang['wrong_user'],'NOREDIRECT');
print_login();
exit();
}
$resp = null;
$reCaptcha = new ReCaptcha($hesk_settings['recaptcha_private_key']);
$res=hesk_dbFetchAssoc($result);
foreach ($res as $k=>$v)
{
$_SESSION[$k]=$v;
}
// Was there a reCAPTCHA response?
if (isset($_POST["g-recaptcha-response"])) {
$resp = $reCaptcha->verifyResponse(hesk_getClientIP(), hesk_POST("g-recaptcha-response"));
}
/* Check password */
if (hesk_Pass2Hash($pass) != $_SESSION['pass'])
{
hesk_session_stop();
$_SESSION['a_iserror'] = array('pass');
hesk_process_messages($hesklang['wrong_pass'],'NOREDIRECT');
print_login();
exit();
}
if ($resp != null && $resp->success) {
$_SESSION['img_a_verified'] = true;
} else {
$hesk_error_buffer['mysecnum'] = $hesklang['recaptcha_error'];
}
} // Using PHP generated image
else {
$mysecnum = intval(hesk_POST('mysecnum', 0));
$pass_enc = hesk_Pass2Hash($_SESSION['pass'].strtolower($user).$_SESSION['pass']);
/* Check if default password */
if ($_SESSION['pass'] == '499d74967b28a841c98bb4baaabaad699ff3c079')
{
hesk_process_messages($hesklang['chdp'],'NOREDIRECT','NOTICE');
}
unset($_SESSION['pass']);
/* Login successful, clean brute force attempts */
hesk_cleanBfAttempts();
/* Regenerate session ID (security) */
hesk_session_regenerate_id();
/* Remember username? */
if ($hesk_settings['autologin'] && hesk_POST('remember_user') == 'AUTOLOGIN')
{
setcookie('hesk_username', "$user", strtotime('+1 year'));
setcookie('hesk_p', "$pass_enc", strtotime('+1 year'));
}
elseif ( hesk_POST('remember_user') == 'JUSTUSER')
{
setcookie('hesk_username', "$user", strtotime('+1 year'));
setcookie('hesk_p', '');
}
else
{
// Expire cookie if set otherwise
setcookie('hesk_username', '');
setcookie('hesk_p', '');
}
/* Close any old tickets here so Cron jobs aren't necessary */
if ($hesk_settings['autoclose'])
{
$revision = sprintf($hesklang['thist3'],hesk_date(),$hesklang['auto']);
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `status`='3', `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') WHERE `status` = '2' AND `lastchange` <= '".hesk_dbEscape( date('Y-m-d H:i:s',time() - $hesk_settings['autoclose']*86400) )."'");
}
/* Redirect to the destination page */
if ( hesk_isREQUEST('goto') )
{
$url = hesk_REQUEST('goto');
$url = str_replace('&amp;','&',$url);
/* goto parameter can be set to the local domain only */
$myurl = parse_url($hesk_settings['hesk_url']);
$goto = parse_url($url);
if (isset($myurl['host']) && isset($goto['host']))
{
if ( str_replace('www.','',strtolower($myurl['host'])) != str_replace('www.','',strtolower($goto['host'])) )
{
$url = 'admin_main.php';
if (empty($mysecnum)) {
$hesk_error_buffer['mysecnum'] = $hesklang['sec_miss'];
} else {
require(HESK_PATH . 'inc/secimg.inc.php');
$sc = new PJ_SecurityImage($hesk_settings['secimg_sum']);
if (isset($_SESSION['checksum']) && $sc->checkCode($mysecnum, $_SESSION['checksum'])) {
$_SESSION['img_a_verified'] = true;
} else {
$hesk_error_buffer['mysecnum'] = $hesklang['sec_wrng'];
}
}
}
}
header('Location: '.$url);
}
else
{
header('Location: admin_main.php');
}
exit();
/* Any missing fields? */
if (count($hesk_error_buffer) != 0) {
$_SESSION['a_iserror'] = array_keys($hesk_error_buffer);
$tmp = '';
foreach ($hesk_error_buffer as $error) {
$tmp .= "<li>$error</li>\n";
}
$hesk_error_buffer = $tmp;
$hesk_error_buffer = $hesklang['pcer'] . '<br /><br /><ul>' . $hesk_error_buffer . '</ul>';
hesk_process_messages($hesk_error_buffer, 'NOREDIRECT');
print_login();
exit();
} elseif (isset($_SESSION['img_a_verified'])) {
unset($_SESSION['img_a_verified']);
}
/* User entered all required info, now lets limit brute force attempts */
hesk_limitBfAttempts();
$result = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `user` = '" . hesk_dbEscape($user) . "' LIMIT 1");
if (hesk_dbNumRows($result) != 1) {
hesk_session_stop();
$_SESSION['a_iserror'] = array('user', 'pass');
hesk_process_messages($hesklang['wrong_user'], 'NOREDIRECT');
print_login();
exit();
}
$res = hesk_dbFetchAssoc($result);
foreach ($res as $k => $v) {
$_SESSION[$k] = $v;
}
/* Check password */
if (hesk_Pass2Hash($pass) != $_SESSION['pass']) {
hesk_session_stop();
$_SESSION['a_iserror'] = array('pass');
hesk_process_messages($hesklang['wrong_pass'], 'NOREDIRECT');
print_login();
exit();
}
$pass_enc = hesk_Pass2Hash($_SESSION['pass'].hesk_mb_strtolower($user).$_SESSION['pass']);
/* Check if default password */
if ($_SESSION['pass'] == '499d74967b28a841c98bb4baaabaad699ff3c079') {
hesk_process_messages($hesklang['chdp'], 'NOREDIRECT', 'NOTICE');
}
// Set a tag that will be used to expire sessions after username or password change
$_SESSION['session_verify'] = hesk_activeSessionCreateTag($user, $_SESSION['pass']);
// We don't need the password hash anymore
unset($_SESSION['pass']);
/* Login successful, clean brute force attempts */
hesk_cleanBfAttempts();
/* Make sure our user is active */
if (!$_SESSION['active']) {
hesk_session_stop();
$_SESSION['a_iserror'] = array('active');
hesk_process_messages($hesklang['inactive_user'], 'NOREDIRECT');
print_login();
exit();
}
/* Regenerate session ID (security) */
hesk_session_regenerate_id();
/* Remember username? */
if ($hesk_settings['autologin'] && hesk_POST('remember_user') == 'AUTOLOGIN') {
hesk_setcookie('hesk_username', "$user", strtotime('+1 year'));
hesk_setcookie('hesk_p', "$pass_enc", strtotime('+1 year'));
} elseif (hesk_POST('remember_user') == 'JUSTUSER') {
hesk_setcookie('hesk_username', "$user", strtotime('+1 year'));
hesk_setcookie('hesk_p', '');
} else {
// Expire cookie if set otherwise
hesk_setcookie('hesk_username', '');
hesk_setcookie('hesk_p', '');
}
/* Close any old tickets here so Cron jobs aren't necessary */
if ($hesk_settings['autoclose']) {
$dt = date('Y-m-d H:i:s', time() - $hesk_settings['autoclose'] * 86400);
$closedStatusRs = hesk_dbQuery('SELECT `ID`, `Closable` FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'statuses` WHERE `IsDefaultStaffReplyStatus` = 1');
$closedStatus = hesk_dbFetchAssoc($closedStatusRs);
// Are we allowed to close tickets in this status?
if ($closedStatus['Closable'] == 'yes' || $closedStatus['Closable'] == 'sonly') {
$result = hesk_dbQuery("SELECT * FROM `" . $hesk_settings['db_pfix'] . "tickets` WHERE `status` = " . $closedStatus['ID'] . " AND `lastchange` <= '" . hesk_dbEscape($dt) . "' ");
if (hesk_dbNumRows($result) > 0) {
global $ticket;
// Load required functions?
if (!function_exists('hesk_notifyCustomer')) {
require(HESK_PATH . 'inc/email_functions.inc.php');
}
while ($ticket = hesk_dbFetchAssoc($result)) {
$ticket['dt'] = hesk_date($ticket['dt'], true);
$ticket['lastchange'] = hesk_date($ticket['lastchange'], true);
$ticket = hesk_ticketToPlain($ticket, 1, 0);
mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_automatically_closed', hesk_date(), array());
// Notify customer of closed ticket?
if ($hesk_settings['notify_closed']) {
// Get list of tickets
hesk_notifyCustomer($modsForHesk_settings, 'ticket_closed');
}
}
}
// Update ticket statuses and history in database if we're allowed to do so
$defaultCloseRs = hesk_dbQuery('SELECT `ID` FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'statuses` WHERE `IsAutocloseOption` = 1');
$defaultCloseStatus = hesk_dbFetchAssoc($defaultCloseRs);
hesk_dbQuery("UPDATE `" . $hesk_settings['db_pfix'] . "tickets` SET `status`=" . intval($defaultCloseStatus['ID']) . ", `closedat`=NOW(), `closedby`='-1' WHERE `status` = " . $closedStatus['ID'] . " AND `lastchange` <= '" . hesk_dbEscape($dt) . "' ");
}
}
/* Redirect to the destination page */
header('Location: ' . hesk_verifyGoto());
exit();
} // End do_login()
function print_login()
{
global $hesk_settings, $hesklang;
global $hesk_settings, $hesklang, $modsForHesk_settings;
// Tell header to load reCaptcha API if needed
if ($hesk_settings['recaptcha_use'])
{
define('RECAPTCHA',1);
}
$hesk_settings['tmp_title'] = $hesk_settings['hesk_title'] . ' - ' .$hesklang['admin_login'];
require_once(HESK_PATH . 'inc/header.inc.php');
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
if ( hesk_isREQUEST('notice') )
{
@ -272,206 +255,234 @@ function print_login()
}
?>
<div class="loginError"><?php
/* This will handle error, success and notice messages */
hesk_handle_messages();
?></div>
<div>
<form class="form-signin form-horizontal" role="form" action="index.php" method="post" name="form1">
<h2 class="form-signin-heading">&nbsp;<?php echo $hesklang['admin_login']; ?></a></h2><br/>
<?php if (in_array('pass',$_SESSION['a_iserror'])) { echo '<div class="form-group has-error">';} else { echo '<div class="form-group">';}?>
<label for="user" class="col-sm-3 control-label"><?php echo $hesklang['username']; ?>:</label>
<div class="col-sm-9">
<div class="login-box">
<div class="login-box-container">
<div class="login-box-background"></div>
<div class="login-box-body">
<div class="loginError">
<?php
/* This will handle error, success and notice messages */
hesk_handle_messages();
// Service messages
$service_messages = mfh_get_service_messages('STAFF_LOGIN');
foreach ($service_messages as $sm) {
hesk_service_message($sm);
}
?>
</div>
<div class="login-logo">
<?php if ($modsForHesk_settings['login_box_header'] == 'image'): ?>
<img src="<?php echo HESK_PATH . $hesk_settings['cache_dir'] . '/lbh_' . $modsForHesk_settings['login_box_header_image']; ?>"
style="height: 75px">
<?php else:
echo $hesk_settings['hesk_title'];
endif; ?>
</div>
<h4 class="login-box-msg">
<?php echo $hesklang['staff_login_title']; ?>
</h4>
<form class="form-horizontal" role="form" action="index.php" method="post" name="form1" id="form1">
<?php
$has_error = '';
if (in_array('pass',$_SESSION['a_iserror'])) {
$has_error = 'has-error';
}
?>
<div class="form-group <?php echo $has_error; ?>">
<label for="user" class="col-sm-4 control-label">
<?php echo $hesklang['username']; ?>
</label>
<div class="col-sm-8">
<?php
if (defined('HESK_USER')) {
$savedUser = HESK_USER;
} else {
$savedUser = hesk_htmlspecialchars(hesk_COOKIE('hesk_username'));
}
$is_1 = '';
$is_2 = '';
$is_3 = '';
$remember_user = hesk_POST('remember_user');
if ($hesk_settings['autologin'] && (isset($_COOKIE['hesk_p']) || $remember_user == 'AUTOLOGIN')) {
$is_1 = 'checked';
} elseif (isset($_COOKIE['hesk_username']) || $remember_user == 'JUSTUSER') {
$is_2 = 'checked';
} else {
$is_3 = 'checked';
}
if ($hesk_settings['list_users']) :
$res = hesk_dbQuery("SELECT `user` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `active` = '1' ORDER BY `user` ASC");
?>
<select class="form-control" name="user">
<?php
while ($row = hesk_dbFetchAssoc($res)):
$sel = (hesk_mb_strtolower($savedUser) == hesk_mb_strtolower($row['user'])) ? 'selected="selected"' : '';
?>
<option value="<?php echo $row['user']; ?>" <?php echo $sel; ?>>
<?php echo $row['user']; ?>
</option>
<?php endwhile; ?>
</select>
<?php else: ?>
<input class="form-control" type="text" name="user" size="35"
placeholder="<?php echo htmlspecialchars($hesklang['username']); ?>"
value="<?php echo $savedUser; ?>">
<?php endif; ?>
</div>
</div>
<?php
$has_error = '';
if (in_array('pass',$_SESSION['a_iserror'])) {
$has_error = 'has-error';
}
?>
<div class="form-group <?php echo $has_error; ?>">
<label for="pass" class="col-sm-4 control-label">
<?php echo $hesklang['pass']; ?>
</label>
<div class="col-sm-8">
<input type="password" class="form-control" id="pass" name="pass" size="35" placeholder="<?php echo htmlspecialchars($hesklang['pass']); ?>">
</div>
</div>
<?php
if ($hesk_settings['secimg_use'] == 2 && $hesk_settings['recaptcha_use'] != 1)
{
// SPAM prevention verified for this session
if (isset($_SESSION['img_a_verified']))
{
echo '<img src="'.HESK_PATH.'img/success.png" width="16" height="16" border="0" alt="" style="vertical-align:text-bottom" /> '.$hesklang['vrfy'];
}
// Use reCaptcha API v2?
elseif ($hesk_settings['recaptcha_use'] == 2)
{
?>
<div class="form-group">
<div class="col-md-8 col-md-offset-4">
<div class="g-recaptcha" data-sitekey="<?php echo $hesk_settings['recaptcha_public_key']; ?>"></div>
</div>
</div>
<?php
}
// At least use some basic PHP generated image (better than nothing)
else
{
echo '<div class="form-group"><div class="col-md-8 col-md-offset-4">';
$cls = in_array('mysecnum',$_SESSION['a_iserror']) ? ' class="isError" ' : '';
echo $hesklang['sec_enter'].'<br><br><img src="'.HESK_PATH.'print_sec_img.php?'.rand(10000,99999).'" width="150" height="40" alt="'.$hesklang['sec_img'].'" title="'.$hesklang['sec_img'].'" border="1" name="secimg" style="vertical-align:text-bottom"> '.
'<a href="javascript:void(0)" onclick="javascript:document.form1.secimg.src=\''.HESK_PATH.'print_sec_img.php?\'+ ( Math.floor((90000)*Math.random()) + 10000);"><img src="'.HESK_PATH.'img/reload.png" height="24" width="24" alt="'.$hesklang['reload'].'" title="'.$hesklang['reload'].'" border="0" style="vertical-align:text-bottom"></a>'.
'<br><br><input type="text" name="mysecnum" size="20" maxlength="5" '.$cls.'>';
echo '</div></div>';
}
} // End if $hesk_settings['secimg_use'] == 2
if ($hesk_settings['autologin'])
{
?>
<div class="form-group">
<div class="col-md-offset-4 col-md-8">
<div class="radio">
<label><input type="radio" name="remember_user" value="AUTOLOGIN" <?php echo $is_1; ?>> <?php echo $hesklang['autologin']; ?></label>
</div>
<div class="radio">
<label><input type="radio" name="remember_user" value="JUSTUSER" <?php echo $is_2; ?>> <?php echo $hesklang['just_user']; ?></label>
</div>
<div class="radio">
<label><input type="radio" name="remember_user" value="NOTHANKS" <?php echo $is_3; ?>> <?php echo $hesklang['nothx']; ?></label>
</div>
</div>
</div>
<?php
if (defined('HESK_USER'))
{
$savedUser = HESK_USER;
}
else
{
$savedUser = hesk_htmlspecialchars( hesk_COOKIE('hesk_username') );
}
$is_1 = '';
$is_2 = '';
$is_3 = '';
$remember_user = hesk_POST('remember_user');
if ($hesk_settings['autologin'] && (isset($_COOKIE['hesk_p']) || $remember_user == 'AUTOLOGIN') )
{
$is_1 = 'checked="checked"';
}
elseif (isset($_COOKIE['hesk_username']) || $remember_user == 'JUSTUSER' )
{
$is_2 = 'checked="checked"';
}
else
{
$is_3 = 'checked="checked"';
}
if ($hesk_settings['list_users'])
{
echo '<select class="form-control" name="user" '.$cls.'>';
$res = hesk_dbQuery('SELECT * FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'users` ORDER BY `user` ASC');
while ($row=hesk_dbFetchAssoc($res))
{
$sel = (strtolower($savedUser) == strtolower($row['user'])) ? 'selected="selected"' : '';
echo '<option value="'.$row['user'].'" '.$sel.'>'.$row['user'].'</option>';
}
echo '</select>';
}
else
{
echo '<input class="form-control" type="text" name="user" size="35" placeholder="'.$hesklang['username'].'" value="'.$savedUser.'" />';
}
?>
</div>
</div>
<?php if (in_array('pass',$_SESSION['a_iserror'])) { echo '<div class="form-group has-error">';} else { echo '<div class="form-group">';}?>
<label for="pass" class="col-sm-3 control-label"><?php echo $hesklang['pass']; ?>:</label>
<div class="col-sm-9">
<input type="password" class="form-control" id="pass" name="pass" size="35" placeholder="<?php echo $hesklang['pass']; ?>" />
</div>
</div>
<?php
if ($hesk_settings['secimg_use'] == 2)
{
// SPAM prevention verified for this session
if (isset($_SESSION['img_a_verified']))
{
echo '<img src="'.HESK_PATH.'img/success.png" width="16" height="16" border="0" alt="" style="vertical-align:text-bottom" /> '.$hesklang['vrfy'];
}
// Not verified yet, should we use Recaptcha?
elseif ($hesk_settings['recaptcha_use'])
{
?>
<script type="text/javascript">
var RecaptchaOptions = {
theme : '<?php echo ( isset($_SESSION['a_iserror']) && in_array('mysecnum',$_SESSION['a_iserror']) ) ? 'red' : 'white'; ?>',
custom_translations : {
visual_challenge : "<?php echo hesk_slashJS($hesklang['visual_challenge']); ?>",
audio_challenge : "<?php echo hesk_slashJS($hesklang['audio_challenge']); ?>",
refresh_btn : "<?php echo hesk_slashJS($hesklang['refresh_btn']); ?>",
instructions_visual : "<?php echo hesk_slashJS($hesklang['instructions_visual']); ?>",
instructions_context : "<?php echo hesk_slashJS($hesklang['instructions_context']); ?>",
instructions_audio : "<?php echo hesk_slashJS($hesklang['instructions_audio']); ?>",
help_btn : "<?php echo hesk_slashJS($hesklang['help_btn']); ?>",
play_again : "<?php echo hesk_slashJS($hesklang['play_again']); ?>",
cant_hear_this : "<?php echo hesk_slashJS($hesklang['cant_hear_this']); ?>",
incorrect_try_again : "<?php echo hesk_slashJS($hesklang['incorrect_try_again']); ?>",
image_alt_text : "<?php echo hesk_slashJS($hesklang['image_alt_text']); ?>",
},
};
</script>
<?php
require_once(HESK_PATH . 'inc/recaptcha/recaptchalib.php');
echo recaptcha_get_html($hesk_settings['recaptcha_public_key'], null, $hesk_settings['recaptcha_ssl']);
}
// At least use some basic PHP generated image (better than nothing)
else
{
$cls = in_array('mysecnum',$_SESSION['a_iserror']) ? ' class="isError" ' : '';
echo $hesklang['sec_enter'].'<br />&nbsp;<br /><img src="'.HESK_PATH.'print_sec_img.php?'.rand(10000,99999).'" width="150" height="40" alt="'.$hesklang['sec_img'].'" title="'.$hesklang['sec_img'].'" border="1" name="secimg" style="vertical-align:text-bottom" /> '.
'<a href="javascript:void(0)" onclick="javascript:document.form1.secimg.src=\''.HESK_PATH.'print_sec_img.php?\'+ ( Math.floor((90000)*Math.random()) + 10000);"><img src="'.HESK_PATH.'img/reload.png" height="24" width="24" alt="'.$hesklang['reload'].'" title="'.$hesklang['reload'].'" border="0" style="vertical-align:text-bottom" /></a>'.
'<br />&nbsp;<br /><input type="text" name="mysecnum" size="20" maxlength="5" '.$cls.' />';
}
} // End if $hesk_settings['secimg_use'] == 2
if ($hesk_settings['autologin'])
{
?>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="radio">
<label><input type="radio" name="remember_user" value="AUTOLOGIN" <?php echo $is_1; ?> /> <?php echo $hesklang['autologin']; ?></label>
}
else
{
?>
<div class="form-group">
<div class="col-md-offset-4 col-md-8">
<div class="checkbox">
<label><input type="checkbox" name="remember_user" value="JUSTUSER" <?php echo $is_2; ?> /> <?php echo $hesklang['remember_user']; ?></label>
</div>
</div>
</div>
<div class="radio">
<label><input type="radio" name="remember_user" value="JUSTUSER" <?php echo $is_2; ?> /> <?php echo $hesklang['just_user']; ?></label>
</div>
<div class="radio">
<label><input type="radio" name="remember_user" value="NOTHANKS" <?php echo $is_3; ?> /> <?php echo $hesklang['nothx']; ?></label>
<?php
} // End if $hesk_settings['autologin']
?>
<div class="form-group">
<div class="col-md-offset-4 col-md-8">
<input type="submit" value="<?php echo $hesklang['click_login']; ?>" class="btn btn-default" id="recaptcha-submit">
<input type="hidden" name="a" value="do_login">
<?php
if ( hesk_isREQUEST('goto') && $url=hesk_REQUEST('goto') )
{
echo '<input type="hidden" name="goto" value="'.$url.'">';
}
// Do we allow staff password reset?
if ($hesk_settings['reset_pass'])
{
echo '<br><br><a href="password.php" class="smaller">'.$hesklang['fpass'].'</a>';
}
?>
</div>
</div>
</div>
<?php
}
else
{
?>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" name="remember_user" value="JUSTUSER" <?php echo $is_2; ?> /> <?php echo $hesklang['remember_user']; ?></label>
</div>
</div>
</div>
<?php
} // End if $hesk_settings['autologin']
?>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input type="submit" value="<?php echo $hesklang['click_login']; ?>" class="btn btn-default" />
<input type="hidden" name="a" value="do_login" />
<?php
if ( hesk_isREQUEST('goto') && $url=hesk_REQUEST('goto') )
{
echo '<input type="hidden" name="goto" value="'.$url.'" />';
}
?>
</div>
<?php
// Use Invisible reCAPTCHA?
if ($hesk_settings['secimg_use'] == 2 && $hesk_settings['recaptcha_use'] == 1 && ! isset($_SESSION['img_a_verified'])) {
?>
<div class="g-recaptcha" data-sitekey="<?php echo $hesk_settings['recaptcha_public_key']; ?>" data-bind="recaptcha-submit" data-callback="recaptcha_submitForm"></div>
<?php
}
?>
</form>
<a class="btn btn-default" href="<?php echo $hesk_settings['hesk_url']; ?>">
<i class="fa fa-chevron-left"></i> <?php echo $hesklang['back']; ?>
</a>
</div>
</form>
</div>
<p>&nbsp;</p>
<?php
</div>
<?php
hesk_cleanSessionVars('a_iserror');
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();
} // End print_login()
function logout() {
global $hesk_settings, $hesklang;
function logout()
{
global $hesk_settings, $hesklang;
if ( ! hesk_token_check('GET', 0))
{
print_login();
if (!hesk_token_check('GET', 0)) {
print_login();
exit();
}
/* Delete from Who's online database */
if ($hesk_settings['online'])
{
require(HESK_PATH . 'inc/users_online.inc.php');
hesk_setOffline($_SESSION['id']);
}
if ($hesk_settings['online']) {
require(HESK_PATH . 'inc/users_online.inc.php');
hesk_setOffline($_SESSION['id']);
}
/* Destroy session and cookies */
hesk_session_stop();
hesk_session_stop();
/* If we're using the security image for admin login start a new session */
if ($hesk_settings['secimg_use'] == 2)
{
hesk_session_start();
if ($hesk_settings['secimg_use'] == 2) {
hesk_session_start();
}
/* Show success message and reset the cookie */
hesk_process_messages($hesklang['logout_success'],'NOREDIRECT','SUCCESS');
setcookie('hesk_p', '');
/* Show success message and reset the cookie */
hesk_process_messages($hesklang['logout_success'], 'NOREDIRECT', 'SUCCESS');
hesk_setcookie('hesk_p', '');
/* Print the login form */
print_login();
exit();
print_login();
exit();
} // End logout()
?>

View File

@ -1,50 +1,35 @@
<?php
/*******************************************************************************
* Title: Help Desk Software HESK
* Version: 2.5.3 from 16th March 2014
* Author: Klemen Stirn
* Website: http://www.hesk.com
********************************************************************************
* COPYRIGHT AND TRADEMARK NOTICE
* Copyright 2005-2013 Klemen Stirn. All Rights Reserved.
* HESK is a registered trademark of Klemen Stirn.
* The HESK may be used and modified free of charge by anyone
* AS LONG AS COPYRIGHT NOTICES AND ALL THE COMMENTS REMAIN INTACT.
* By using this code you agree to indemnify Klemen Stirn from any
* liability that might arise from it's use.
* Selling the code for this program, in part or full, without prior
* written consent is expressly forbidden.
* Using this code, in part or full, to create derivate work,
* new scripts or products is expressly forbidden. Obtain permission
* before redistributing this software over the Internet or in
* any other medium. In all cases copyright and header must remain intact.
* This Copyright is in full effect in any country that has International
* Trade Agreements with the United States of America or
* with the European Union.
* Removing any of the copyright notices without purchasing a license
* is expressly forbidden. To remove HESK copyright notice you must purchase
* a license for this script. For more information on how to obtain
* a license please visit the page below:
* https://www.hesk.com/buy.php
*******************************************************************************/
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
define('IN_SCRIPT',1);
define('HESK_PATH','../');
define('PAGE_TITLE', 'ADMIN_KB');
define('MFH_PAGE_LAYOUT', 'TOP_ONLY');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/knowledgebase_functions.inc.php');
require(HESK_PATH . 'inc/mail_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
hesk_kb_preheader();
/* Is Knowledgebase enabled? */
if ( ! $hesk_settings['kb_enable'])
@ -59,6 +44,7 @@ $can_man_kb = hesk_checkPermission('can_man_kb',0);
$catid = intval( hesk_GET('category', 1) );
$artid = intval( hesk_GET('article', 0) );
if (isset($_GET['search']))
{
$query = hesk_input( hesk_GET('search') );
@ -72,7 +58,9 @@ $hesk_settings['kb_link'] = ($artid || $catid != 1 || $query) ? '<a href="knowle
if ($hesk_settings['kb_search'] && $query)
{
hesk_kb_search($query);
if (hesk_kb_search($query)) {
hesk_show_kb_category(1,1);
}
}
elseif ($artid)
{
@ -107,20 +95,19 @@ exit();
/*** START FUNCTIONS ***/
function hesk_kb_preheader() {
global $hesk_settings, $hesklang, $can_man_kb;
/* Print admin navigation */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
}
function hesk_kb_header($kb_link, $catid=1)
{
global $hesk_settings, $hesklang, $can_man_kb;
/* Print admin navigation */
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
</td>
</tr>
<tr>
<td>
<ol class="breadcrumb">
<?php
if ($can_man_kb)
@ -132,17 +119,11 @@ function hesk_kb_header($kb_link, $catid=1)
?>
<li class="active"><?php echo $kb_link; ?></li>
</ol>
<!-- SUB NAVIGATION -->
<?php show_subnav('view', $catid); ?>
<!-- SUB NAVIGATION -->
<div style="margin-left:40px;margin-right:40px">
<?php hesk_kbSearchLarge(1); ?>
<?php
<?php
show_subnav('view', $catid);
echo '<div style="margin-left:40px;margin-right:40px">';
hesk_kbSearchLarge(1);
echo '</div>';
} // END hesk_kb_header()
@ -150,79 +131,76 @@ function hesk_kb_search($query)
{
global $hesk_settings, $hesklang;
define('HESK_NO_ROBOTS',1);
/* Print header */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
hesk_kb_header($hesk_settings['kb_link']);
$res = hesk_dbQuery('SELECT t1.`id`, t1.`subject`, t1.`content`, t1.`rating` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'kb_articles` AS t1 LEFT JOIN `'.hesk_dbEscape($hesk_settings['db_pfix']).'kb_categories` AS t2 ON t1.`catid` = t2.`id` '." WHERE t1.`type` IN ('0','1') AND MATCH(`subject`,`content`,`keywords`) AGAINST ('".hesk_dbEscape($query)."') LIMIT ".intval($hesk_settings['kb_search_limit']));
$res = hesk_dbQuery('SELECT t1.`id`, t1.`subject`, LEFT(`t1`.`content`, '.max(200, $hesk_settings['kb_substrart'] * 2).') AS `content`, t1.`rating` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'kb_articles` AS t1 LEFT JOIN `'.hesk_dbEscape($hesk_settings['db_pfix']).'kb_categories` AS t2 ON t1.`catid` = t2.`id` '." WHERE t1.`type` IN ('0','1') AND MATCH(`subject`,`content`,`keywords`) AGAINST ('".hesk_dbEscape($query)."') LIMIT ".intval($hesk_settings['kb_search_limit']));
$num = hesk_dbNumRows($res);
$show_default_category = false;
?>
<h4><?php echo $hesklang['sr']; ?> (<?php echo $num; ?>)</h4>
<div class="footerWithBorder blankSpace"></div>
<div class="content-wrapper">
<?php hesk_kb_header($hesk_settings['kb_link']); ?>
<section style="padding: 15px">
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['sr']; ?> (<?php echo $num; ?>)
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<?php
if ($num == 0) {
echo '<i>'.$hesklang['nosr'].'</i>';
$show_default_category = true;
} else {
?>
<table class="table table-striped">
<?php
while ($article = hesk_dbFetchAssoc($res))
{
$txt = hesk_kbArticleContentPreview($article['content']);
<?php
if ($num == 0)
{
echo '<p style="margin-left:20px"><i>'.$hesklang['nosr'].'</i></p>';
hesk_show_kb_category(1,1);
}
else
{
?>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
<div align="center">
<table border="0" cellspacing="1" cellpadding="3" width="100%">
<?php
while ($article = hesk_dbFetchAssoc($res))
{
$txt = hesk_kbArticleContentPreview($article['content']);
if ($hesk_settings['kb_rating'])
{
$rat = '<td width="1" valign="top">' . mfh_get_stars($article['rating']) . '</td>';
}
else
{
$rat = '';
}
if ($hesk_settings['kb_rating'])
{
$alt = $article['rating'] ? sprintf($hesklang['kb_rated'], sprintf("%01.1f", $article['rating'])) : $hesklang['kb_not_rated'];
$rat = '<td width="1" valign="top"><img src="../img/star_'.(hesk_round_to_half($article['rating'])*10).'.png" width="85" height="16" alt="'.$alt.'" border="0" style="vertical-align:text-bottom" /></td>';
}
else
{
$rat = '';
}
echo '
<tr>
<td>
<table border="0" width="100%" cellspacing="0" cellpadding="1">
<tr>
<td width="1" valign="top"><span class="glyphicon glyphicon-file"></span></td>
<td valign="top"><a href="knowledgebase_private.php?article='.$article['id'].'">'.$article['subject'].'</a></td>
'.$rat.'
</tr>
</table>
<table border="0" width="100%" cellspacing="0" cellpadding="1">
<tr>
<td width="1" valign="top"><img src="../img/blank.gif" width="16" height="10" style="vertical-align:middle" alt="" /></td>
<td><span class="article_list">'.$txt.'</span></td>
</tr>
</table>
echo '
<tr>
<td>
<table border="0" width="100%" cellspacing="0" cellpadding="1">
<tr>
<td width="1" valign="top"><span class="glyphicon glyphicon-file"></span></td>
<td valign="top"><a href="knowledgebase_private.php?article='.$article['id'].'">'.$article['subject'].'</a></td>
'.$rat.'
</tr>
</table>
<table border="0" width="100%" cellspacing="0" cellpadding="1">
<tr>
<td width="1" valign="top"><img src="../img/blank.gif" width="16" height="10" style="vertical-align:middle" alt="" /></td>
<td><span class="article_list">'.$txt.'</span></td>
</tr>
</table>
</td>
</tr>';
}
?>
</table>
</div>
</td>
</tr>
</table>
<p><br /><a href="javascript:history.go(-1)"><span class="glyphicon glyphicon-circle-arrow-left"></span>&nbsp;<?php echo $hesklang['back']; ?></a></p>
</td>
</tr>';
}
?>
</table>
<a href="javascript:history.go(-1)"><span class="glyphicon glyphicon-circle-arrow-left"></span>&nbsp;<?php echo $hesklang['back']; ?></a>
<?php } ?>
</div>
</div>
</section>
</div>
<?php
} // END else
return $show_default_category;
} // END hesk_kb_search()
@ -232,77 +210,186 @@ function hesk_show_kb_article($artid)
// Print header
$hesk_settings['tmp_title'] = $article['subject'];
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
hesk_kb_header($hesk_settings['kb_link'], $article['catid']);
// Update views by 1
hesk_dbQuery('UPDATE `'.hesk_dbEscape($hesk_settings['db_pfix'])."kb_articles` SET `views`=`views`+1 WHERE `id`='".intval($artid)."' LIMIT 1");
hesk_dbQuery('UPDATE `'.hesk_dbEscape($hesk_settings['db_pfix'])."kb_articles` SET `views`=`views`+1 WHERE `id`={$artid}");
echo '<h3>'.$article['subject'].'</h3>
<div class="footerWithBorder blankSpace"></div>
<h4>'.$hesklang['as'].'</h4>
'. $article['content'];
if ( ! empty($article['attachments']))
{
echo '<p><b>'.$hesklang['attachments'].':</b><br />';
$att=explode(',',substr($article['attachments'], 0, -1));
foreach ($att as $myatt)
{
list($att_id, $att_name) = explode('#', $myatt);
echo '<i class="fa fa-papercip"></i> <a href="../download_attachment.php?kb_att='.$att_id.'" rel="nofollow">'.$att_name.'</a><br />';
}
echo '</p>';
}
if ($article['catid']==1)
{
$link = 'knowledgebase_private.php';
}
else
{
$link = 'knowledgebase_private.php?category='.$article['catid'];
?>
<div class="content-wrapper">
<?php
hesk_kb_header($hesk_settings['kb_link'], $article['catid']);
echo '<div style="margin-left:40px;margin-right:40px">';
$service_messages = mfh_get_service_messages('STAFF_VIEW_KB_ARTICLE');
foreach ($service_messages as $sm) {
hesk_service_message($sm);
}
echo '</div>';
?>
<br><br>
<h4><?php echo $hesklang['ad']; ?></h4>
<div class="footerWithBorder blankSpace"></div>
<table border="0">
<tr>
<td><?php echo $hesklang['aid']; ?>: </td>
<td><?php echo $article['id']; ?></td>
</tr>
<tr>
<td><?php echo $hesklang['category']; ?>: </td>
<td><a href="<?php echo $link; ?>"><?php echo $article['cat_name']; ?></a></td>
</tr>
<tr>
<td><?php echo $hesklang['dta']; ?>: </td>
<td><?php echo hesk_date($article['dt']); ?></td>
</tr>
<tr>
<td><?php echo $hesklang['views']; ?>: </td>
<td><?php echo (isset($_GET['rated']) ? $article['views'] : $article['views']+1); ?></td>
</tr>
</table>
<section class="content">
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $article['subject']; ?>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<?php echo $article['content']; ?>
</div>
<?php if (!empty($article['attachments'])): ?>
<div class="box-footer">
<p><b><?php echo $hesklang['attachments']; ?></b></p>
<?php
$att=explode(',',substr($article['attachments'], 0, -1));
foreach ($att as $myatt)
{
list($att_id, $att_name) = explode('#', $myatt);
echo '<i class="fa fa-paperclip"></i> <a href="../download_attachment.php?kb_att='.$att_id.'" rel="nofollow">'.$att_name.'</a><br />';
}
?>
</div>
<?php endif; ?>
</div>
<?php
<?php
if (!isset($_GET['back']))
{
?>
<p><br /><a href="javascript:history.go(-1)"><span class="glyphicon glyphicon-circle-arrow-left"></span>&nbsp;<?php echo $hesklang['back']; ?></a></p>
<?php
}
else
{
?>
<p>&nbsp;</p>
<?php
}
if ($article['catid']==1)
{
$link = 'knowledgebase_private.php';
}
else
{
$link = 'knowledgebase_private.php?category='.$article['catid'];
}
?>
<br><br>
<div class="row">
<?php
$showRelated = false;
$column = 'col-md-12';
require(HESK_PATH . 'inc/mail/email_parser.php');
$query = hesk_dbEscape( $article['subject'] . ' ' . convert_html_to_text($article['content']) );
// Get relevant articles from the database
$res = hesk_dbQuery("SELECT `id`, `subject`, MATCH(`subject`,`content`,`keywords`) AGAINST ('{$query}') AS `score` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_articles` WHERE `type` IN ('0','1') AND MATCH(`subject`,`content`,`keywords`) AGAINST ('{$query}') LIMIT ".intval($hesk_settings['kb_related']+1));
// Array with related articles
$related_articles = array();
while ($related = hesk_dbFetchAssoc($res))
{
// Get base match score from the first (this) article
if ( ! isset($base_score) )
{
$base_score = $related['score'];
}
// Ignore this article
if ($related['id'] == $artid)
{
continue;
}
// Stop when articles reach less than 10% of base score
if ($related['score'] / $base_score < 0.10)
{
break;
}
// This is a valid related article
$related_articles[$related['id']] = $related['subject'];
}
// Print related articles if we have any valid matches
if ( count($related_articles) ) {
$column = 'col-md-6';
$showRelated = true;
}
?>
<div class="<?php echo $column; ?> col-sm-12">
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['ad']; ?>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<table border="0">
<tr>
<td><?php echo $hesklang['aid']; ?>: </td>
<td>
<?php
echo $article['id'];
if ($article['type'] == 0)
{
echo ' [<a href="' . $hesk_settings['hesk_url'] . '/knowledgebase.php?article=' . $article['id'] . '">' . $hesklang['public_link'] . '</a>]';
}
?>
</td>
</tr>
<tr>
<td><?php echo $hesklang['category']; ?>: </td>
<td><a href="<?php echo $link; ?>"><?php echo $article['cat_name']; ?></a></td>
</tr>
<tr>
<td><?php echo $hesklang['dta']; ?>: </td>
<td><?php echo hesk_date($article['dt'], true); ?></td>
</tr>
<tr>
<td><?php echo $hesklang['views']; ?>: </td>
<td><?php echo (isset($_GET['rated']) ? $article['views'] : $article['views']+1); ?></td>
</tr>
</table>
</div>
</div>
</div>
<?php if ($showRelated) { ?>
<div class="col-md-6 col-sm-12">
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['relart']; ?>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<?php
// Related articles
foreach ($related_articles as $id => $subject)
{
echo '<span class="glyphicon glyphicon-file" style="font-size: 16px;"></span> <a href="knowledgebase_private.php?article='.$id.'">'.$subject.'</a><br />';
}
?>
</div>
</div>
</div>
<?php } ?>
</div>
<?php
if (!isset($_GET['back']))
{
?>
<p><br /><a href="javascript:history.go(-1)"><span class="glyphicon glyphicon-circle-arrow-left"></span>&nbsp;<?php echo $hesklang['back']; ?></a></p>
<?php
}
?>
</section>
</div>
<?php
} // END hesk_show_kb_article()
@ -310,153 +397,163 @@ function hesk_show_kb_article($artid)
function hesk_show_kb_category($catid, $is_search = 0) {
global $hesk_settings, $hesklang;
if ($is_search == 0)
{
/* Print header */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
hesk_kb_header($hesk_settings['kb_link'], $catid);
if ($catid == 1)
{
echo $hesklang['priv'];
}
}
$res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_categories` WHERE `id`='".intval($catid)."' LIMIT 1");
$res = hesk_dbQuery("SELECT `name`,`parent` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_categories` WHERE `id`='".intval($catid)."' LIMIT 1");
$thiscat = hesk_dbFetchAssoc($res) or hesk_error($hesklang['kb_cat_inv']);
if ($thiscat['parent'])
?>
<div class="content-wrapper">
<?php
if ($is_search == 0)
{
$link = ($thiscat['parent'] == 1) ? 'knowledgebase_private.php' : 'knowledgebase_private.php?category='.$thiscat['parent'];
echo '<h3>'.$hesklang['kb_cat'].': '.$thiscat['name'].'</h3>
<p align="left"><a href="javascript:history.go(-1)"><span class="glyphicon glyphicon-circle-arrow-left"></span>'.$hesklang['back'].'</a></p>
<div class="footerWithBorder blankSpace"></div>';
}
$result = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_categories` WHERE `parent`='".intval($catid)."' ORDER BY `parent` ASC, `cat_order` ASC");
if (hesk_dbNumRows($result) > 0)
{
?>
<h4><?php echo $hesklang['kb_cat_sub']; ?></h4>
<div class="footerWithBorder blankSpace"></div>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
<table border="0" cellspacing="1" cellpadding="3" width="100%">
/* Print header */
hesk_kb_header($hesk_settings['kb_link'], $catid);
echo '<div style="margin-left:40px;margin-right:40px">';
$service_messages = mfh_get_service_messages('STAFF_KB_HOME');
foreach ($service_messages as $sm) {
hesk_service_message($sm);
}
echo '</div>';
} ?>
<section class="content">
<?php if ($thiscat['parent']): ?>
<h3><?php echo $hesklang['kb_cat'].': '.$thiscat['name']; ?></h3>
<p align="left"><a href="javascript:history.go(-1)">
<span class="glyphicon glyphicon-circle-arrow-left"></span>
<?php echo $hesklang['back']; ?>
</a></p>
<?php
$per_col = $hesk_settings['kb_cols'];
$i = 1;
endif;
while ($cat = hesk_dbFetchAssoc($result))
{
$result = hesk_dbQuery("SELECT `id`,`name`,`articles`,`type` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_categories` WHERE `parent`='".intval($catid)."' ORDER BY `parent` ASC, `cat_order` ASC");
if ($i == 1)
{
echo '<tr>';
}
if (hesk_dbNumRows($result) > 0) {
?>
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['kb_cat_sub']; ?>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<table class="table table-striped">
<?php
$per_col = $hesk_settings['kb_cols'];
$i = 1;
$private = ($cat['type'] == 1) ? ' *' : '';
while ($cat = hesk_dbFetchAssoc($result))
{
echo '
if ($i == 1)
{
echo '<tr>';
}
$private = ($cat['type'] == 1) ? ' *' : '';
echo '
<td width="50%" valign="top">
<table border="0">
<tr><td><span class="glyphicon glyphicon-folder-close"></span>&nbsp;<a href="knowledgebase_private.php?category='.$cat['id'].'">'.$cat['name'].'</a>'.$private.'</td></tr>
';
/* Print most popular/sticky articles */
if ($hesk_settings['kb_numshow'] && $cat['articles'])
{
$res = hesk_dbQuery("SELECT `id`,`subject`,`type` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_articles` WHERE `catid`='".intval($cat['id'])."' AND `type` IN ('0','1') ORDER BY `sticky` DESC, `views` DESC, `art_order` ASC LIMIT " . (intval($hesk_settings['kb_numshow']) + 1) );
$num = 1;
while ($art = hesk_dbFetchAssoc($res))
{
$private = ($art['type'] == 1) ? ' *' : '';
echo '
/* Print most popular/sticky articles */
if ($hesk_settings['kb_numshow'] && $cat['articles'])
{
$res = hesk_dbQuery("SELECT `id`,`subject`,`type` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_articles` WHERE `catid`='".intval($cat['id'])."' AND `type` IN ('0','1') ORDER BY `sticky` DESC, `views` DESC, `art_order` ASC LIMIT " . (intval($hesk_settings['kb_numshow']) + 1) );
$num = 1;
while ($art = hesk_dbFetchAssoc($res))
{
$private = ($art['type'] == 1) ? ' *' : '';
echo '
<tr>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="glyphicon glyphicon-file"></span>
<a href="knowledgebase_private.php?article='.$art['id'].'" class="article">'.$art['subject'].'</a>'.$private.'</td>
</tr>';
if ($num == $hesk_settings['kb_numshow'])
{
break;
}
else
{
$num++;
}
}
if (hesk_dbNumRows($res) > $hesk_settings['kb_numshow'])
{
echo '<tr><td>&raquo; <a href="knowledgebase_private.php?category='.$cat['id'].'"><i>'.$hesklang['m'].'</i></a></td></tr>';
}
}
if ($num == $hesk_settings['kb_numshow'])
{
break;
}
else
{
$num++;
}
}
if (hesk_dbNumRows($res) > $hesk_settings['kb_numshow'])
{
echo '<tr><td>&raquo; <a href="knowledgebase_private.php?category='.$cat['id'].'"><i>'.$hesklang['m'].'</i></a></td></tr>';
}
}
echo '
echo '
</table>
</td>
';
if ($i == $per_col)
{
echo '</tr>';
$i = 0;
}
$i++;
}
/* Finish the table if needed */
if ($i != 1)
{
for ($j=1;$j<=$per_col;$j++)
{
echo '<td width="50%">&nbsp;</td>';
if ($i == $per_col)
{
echo '</tr>';
break;
}
$i++;
}
}
if ($i == $per_col)
{
echo '</tr>';
$i = 0;
}
$i++;
}
/* Finish the table if needed */
if ($i != 1)
{
for ($j=1;$j<=$per_col;$j++)
{
echo '<td width="50%">&nbsp;</td>';
if ($i == $per_col)
{
echo '</tr>';
break;
}
$i++;
}
}
?>
</table>
?>
</table>
</div>
<div class="box-footer">
<?php echo $hesklang['private_category_star']; ?>
</div>
</div>
<?php } ?>
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['ac']; ?>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<?php
$res = hesk_dbQuery("SELECT `id`, `subject`, LEFT(`content`, ".max(200, $hesk_settings['kb_substrart'] * 2).") AS `content`, `rating`, `type` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_articles` WHERE `catid`='".intval($catid)."' AND `type` IN ('0','1') ORDER BY `sticky` DESC, `art_order` ASC");
if (hesk_dbNumRows($res) == 0)
{
echo '<i>'.$hesklang['noac'].'</i>';
}
else
{
echo '<table border="0" cellspacing="1" cellpadding="3" width="100%">';
while ($article = hesk_dbFetchAssoc($res))
{
$private = ($article['type'] == 1) ? ' *' : '';
</td>
</tr>
</table>
$txt = hesk_kbArticleContentPreview($article['content']);
<?php
} // END if NumRows > 0
?>
<br>
<h4><?php echo $hesklang['ac']; ?></h4>
<div class="footerWithBorder blankSpace"></div>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
<?php
$res = hesk_dbQuery("SELECT `id`, `subject`, `content`, `rating`, `type` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."kb_articles` WHERE `catid`='".intval($catid)."' AND `type` IN ('0','1') ORDER BY `sticky` DESC, `art_order` ASC");
if (hesk_dbNumRows($res) == 0)
{
echo '<p><i>'.$hesklang['noac'].'</i></p>';
}
else
{
echo '<div align="center"><table border="0" cellspacing="1" cellpadding="3" width="100%">';
while ($article = hesk_dbFetchAssoc($res))
{
$private = ($article['type'] == 1) ? ' *' : '';
$txt = hesk_kbArticleContentPreview($article['content']);
echo '
echo '
<tr>
<td>
<table border="0" width="100%" cellspacing="0" cellpadding="1">
@ -473,14 +570,17 @@ function hesk_show_kb_category($catid, $is_search = 0) {
</table>
</td>
</tr>';
}
echo '</table></div>';
}
?>
</td>
</tr>
</table>
}
echo '</table>';
}
?>
</div>
<div class="box-footer">
<?php echo $hesklang['private_article_star']; ?>
</div>
</div>
</section>
</div>
<?php
} // END hesk_show_kb_category()
@ -516,10 +616,10 @@ function show_subnav($hide='', $catid=1)
echo $link['newa'];
echo $link['newc'];
?>
<i class="fa fa-pencil" style="color:orange;font-size:16px"></i></a> <input type="hidden" name="a" value="edit_article" /><?php echo $hesklang['aid']; ?>: <input type="text" name="id" size="3" <?php if ($artid) echo 'value="' . $artid . '"'; ?> /> <input type="submit" value="<?php echo $hesklang['edit']; ?>" class="btn btn-default btn-xs" />
<i class="fa fa-pencil" style="color:orange;font-size:16px"></i> <input type="hidden" name="a" value="edit_article" /><?php echo $hesklang['aid']; ?>: <input type="text" name="id" size="3" <?php if ($artid) echo 'value="' . $artid . '"'; ?> /> <input type="submit" value="<?php echo $hesklang['edit']; ?>" class="btn btn-default btn-xs" />
</form>
</div>
<?php
} // End show_subnav()
?>
?>

View File

@ -1,39 +1,18 @@
<?php
/*******************************************************************************
* Title: Help Desk Software HESK
* Version: 2.5.3 from 16th March 2014
* Author: Klemen Stirn
* Website: http://www.hesk.com
********************************************************************************
* COPYRIGHT AND TRADEMARK NOTICE
* Copyright 2005-2014 Klemen Stirn. All Rights Reserved.
* HESK is a registered trademark of Klemen Stirn.
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
* The HESK may be used and modified free of charge by anyone
* AS LONG AS COPYRIGHT NOTICES AND ALL THE COMMENTS REMAIN INTACT.
* By using this code you agree to indemnify Klemen Stirn from any
* liability that might arise from it's use.
* Selling the code for this program, in part or full, without prior
* written consent is expressly forbidden.
* Using this code, in part or full, to create derivate work,
* new scripts or products is expressly forbidden. Obtain permission
* before redistributing this software over the Internet or in
* any other medium. In all cases copyright and header must remain intact.
* This Copyright is in full effect in any country that has International
* Trade Agreements with the United States of America or
* with the European Union.
* Removing any of the copyright notices without purchasing a license
* is expressly forbidden. To remove HESK copyright notice you must purchase
* a license for this script. For more information on how to obtain
* a license please visit the page below:
* https://www.hesk.com/buy.php
*******************************************************************************/
define('IN_SCRIPT',1);
define('HESK_PATH','../');
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
@ -44,39 +23,80 @@ hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
$modsForHesk_settings = mfh_getSettings();
/* Check permissions for this feature */
hesk_checkPermission('can_view_tickets');
hesk_checkPermission('can_reply_tickets');
hesk_checkPermission('can_edit_tickets');
hesk_checkPermission('can_resolve');
/* A security check */
hesk_token_check();
/* Ticket ID */
$trackingID = hesk_cleanID() or die($hesklang['int_error'].': '.$hesklang['no_trackID']);
$trackingID = hesk_cleanID() or die($hesklang['int_error'] . ': ' . $hesklang['no_trackID']);
/* New archived status */
if (empty($_GET['locked']))
{
$status = 0;
$tmp = $hesklang['tunlock'];
$revision = sprintf($hesklang['thist6'],hesk_date(),$_SESSION['name'].' ('.$_SESSION['user'].')');
// Get ticket info
$result = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `trackid`='" . hesk_dbEscape($trackingID) . "' LIMIT 1");
if (hesk_dbNumRows($result) != 1) {
hesk_error($hesklang['ticket_not_found']);
}
else
{
$status = 1;
$tmp = $hesklang['tlock'];
$revision = sprintf($hesklang['thist5'],hesk_date(),$_SESSION['name'].' ('.$_SESSION['user'].')');
$ticket = hesk_dbFetchAssoc($result);
$audit_unlocked = null;
$audit_locked = null;
/* New locked status */
if (empty($_GET['locked'])) {
$status = 0;
$tmp = $hesklang['tunlock'];
$audit_unlocked = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')');
$closedby_sql = ' , `closedat`=NULL, `closedby`=NULL ';
} else {
$status = 1;
$tmp = $hesklang['tlock'];
$audit_locked = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')');
$closedby_sql = ' , `closedat`=NOW(), `closedby`=' . intval($_SESSION['id']) . ' ';
// Notify customer of closed ticket?
if ($hesk_settings['notify_closed']) {
$closedStatusRS = hesk_dbQuery('SELECT `ID` FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'statuses` WHERE `IsClosed` = 1');
$ticketIsOpen = true;
while ($row = hesk_dbFetchAssoc($closedStatusRS)) {
if ($ticket['status'] == $row['ID']) {
$ticketIsOpen = false;
}
}
// Notify customer, but only if ticket is not already closed
if ($ticketIsOpen) {
require(HESK_PATH . 'inc/email_functions.inc.php');
$ticket['dt'] = hesk_date($ticket['dt'], true);
$ticket['lastchange'] = hesk_date($ticket['lastchange'], true);
hesk_notifyCustomer($modsForHesk_settings, 'ticket_closed');
}
}
}
/* Update database */
$statusSql = 'SELECT `ID` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'statuses` WHERE `LockedTicketStatus` = 1';
$statusRow = hesk_dbQuery($statusSql)->fetch_assoc();
$statusSql = 'SELECT `ID` FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'statuses` WHERE `LockedTicketStatus` = 1';
$statusRs = hesk_dbQuery($statusSql);
$statusRow = hesk_dbFetchAssoc($statusRs);
$statusId = $statusRow['ID'];
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `status`='{$statusId}',`locked`='{$status}', `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') WHERE `trackid`='".hesk_dbEscape($trackingID)."' LIMIT 1");
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `status`= {$statusId},`locked`='{$status}' $closedby_sql WHERE `trackid`='" . hesk_dbEscape($trackingID) . "'");
if ($audit_unlocked) {
mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_unlocked', hesk_date(),
$audit_unlocked);
}
if ($audit_locked) {
mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_locked', hesk_date(),
$audit_locked);
}
/* Back to ticket page and show a success message */
hesk_process_messages($tmp,'admin_ticket.php?track='.$trackingID.'&Refresh='.rand(10000,99999),'SUCCESS');
?>
hesk_process_messages($tmp, 'admin_ticket.php?track=' . $trackingID . '&Refresh=' . rand(10000, 99999), 'SUCCESS');

File diff suppressed because it is too large Load Diff

View File

@ -1,63 +1,57 @@
<?php
/*******************************************************************************
* Title: Help Desk Software HESK
* Version: 2.5.3 from 16th March 2014
* Author: Klemen Stirn
* Website: http://www.hesk.com
********************************************************************************
* COPYRIGHT AND TRADEMARK NOTICE
* Copyright 2005-2013 Klemen Stirn. All Rights Reserved.
* HESK is a registered trademark of Klemen Stirn.
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
* The HESK may be used and modified free of charge by anyone
* AS LONG AS COPYRIGHT NOTICES AND ALL THE COMMENTS REMAIN INTACT.
* By using this code you agree to indemnify Klemen Stirn from any
* liability that might arise from it's use.
* Selling the code for this program, in part or full, without prior
* written consent is expressly forbidden.
* Using this code, in part or full, to create derivate work,
* new scripts or products is expressly forbidden. Obtain permission
* before redistributing this software over the Internet or in
* any other medium. In all cases copyright and header must remain intact.
* This Copyright is in full effect in any country that has International
* Trade Agreements with the United States of America or
* with the European Union.
* Removing any of the copyright notices without purchasing a license
* is expressly forbidden. To remove HESK copyright notice you must purchase
* a license for this script. For more information on how to obtain
* a license please visit the page below:
* https://www.hesk.com/buy.php
*******************************************************************************/
define('IN_SCRIPT',1);
define('HESK_PATH','../');
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
define('VALIDATOR', 1);
define('PAGE_TITLE', 'ADMIN_CANNED');
define('MFH_PAGE_LAYOUT', 'TOP_ONLY');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/mail_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
define('WYSIWYG', 1);
/* Check permissions for this feature */
hesk_checkPermission('can_man_canned');
// Load custom fields
require_once(HESK_PATH . 'inc/custom_fields.inc.php');
/* What should we do? */
if ( $action = hesk_REQUEST('a') )
{
if ( defined('HESK_DEMO') ) {hesk_process_messages($hesklang['ddemo'], 'manage_canned.php', 'NOTICE');}
elseif ($action == 'new') {new_saved();}
elseif ($action == 'edit') {edit_saved();}
elseif ($action == 'remove') {remove();}
elseif ($action == 'order') {order_saved();}
if ($action = hesk_REQUEST('a')) {
if (defined('HESK_DEMO')) {
hesk_process_messages($hesklang['ddemo'], 'manage_canned.php', 'NOTICE');
} elseif ($action == 'new') {
new_saved();
} elseif ($action == 'edit') {
edit_saved();
} elseif ($action == 'remove') {
remove();
} elseif ($action == 'order') {
order_saved();
}
}
$modsForHesk_settings = mfh_getSettings();
/* Print header */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
@ -66,244 +60,337 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
<script language="javascript" type="text/javascript"><!--
function confirm_delete()
{
if (confirm('<?php echo addslashes($hesklang['delete_saved']); ?>')) {return true;}
else {return false;}
}
function confirm_delete() {
if (confirm('<?php echo hesk_makeJsString($hesklang['delete_saved']); ?>')) {
return true;
}
else {
return false;
}
}
function hesk_insertTag(tag) {
var text_to_insert = '%%'+tag+'%%';
hesk_insertAtCursor(document.form1.msg, text_to_insert);
document.form1.msg.focus();
}
function hesk_insertTag(tag) {
var text_to_insert = '%%' + tag + '%%';
var msg = '';
<?php
if ($modsForHesk_settings['rich_text_for_tickets']) { ?>
msg = $('#message').val();
$("#message").summernote('reset');
$("#message").summernote('editor.insertText', msg + text_to_insert));
<?php } else { ?>
msg = document.getElementById('message').value;
document.getElementById('message').value = msg + text_to_insert;
<?php }
?>
document.form1.msg.focus();
}
function hesk_insertAtCursor(myField, myValue) {
if (document.selection) {
myField.focus();
sel = document.selection.createRange();
sel.text = myValue;
}
else if (myField.selectionStart || myField.selectionStart == '0') {
var startPos = myField.selectionStart;
var endPos = myField.selectionEnd;
myField.value = myField.value.substring(0, startPos)
+ myValue
+ myField.value.substring(endPos, myField.value.length);
} else {
myField.value += myValue;
}
}
//-->
function hesk_insertAtCursor(myField, myValue) {
if (document.selection) {
myField.focus();
sel = document.selection.createRange();
sel.text = myValue;
} else if (myField.selectionStart || myField.selectionStart == '0') {
var startPos = myField.selectionStart;
var endPos = myField.selectionEnd;
myField.value = myField.value.substring(0, startPos)
+ myValue
+ myField.value.substring(endPos, myField.value.length);
} else {
myField.value += myValue;
}
}
//-->
</script>
<?php
$result = hesk_dbQuery('SELECT * FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'std_replies` ORDER BY `reply_order` ASC');
$options='';
$javascript_messages='';
$javascript_titles='';
$result = hesk_dbQuery('SELECT * FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'std_replies` ORDER BY `reply_order` ASC');
$options = '';
$javascript_messages = '';
$javascript_titles = '';
$i=1;
$j=0;
$num = hesk_dbNumRows($result);
$i = 1;
$j = 0;
$num = hesk_dbNumRows($result);
?>
<div class="enclosingDashboard" style="padding-top: 20px">
<div class="row">
<div class="col-md-5">
<div class="moreToLeft">
<ul class="nav nav-tabs">
<li class="active"><a href="#" onclick="return false;"><?php echo $hesklang['savedResponses']; ?></a></li>
</ul>
<div class="summaryList">
<div class="viewTicketSidebar">
<?php if ($num < 1)
{
echo '<p>'.$hesklang['no_saved'].'</p>';
}
else
{ ?>
<table class="table table-hover">
<tr>
<th><?php echo $hesklang['saved_title']; ?></th>
<th><?php echo $hesklang['opt']; ?></th>
</tr>
<?php
while ($mysaved=hesk_dbFetchAssoc($result))
{
$j++;
if (isset($_SESSION['canned']['selcat2']) && $mysaved['id'] == $_SESSION['canned']['selcat2'])
{
$color = 'admin_green';
unset($_SESSION['canned']['selcat2']);
}
else
{
$color = $i ? 'admin_white' : 'admin_gray';
}
$tmp = $i ? 'White' : 'Blue';
$style = 'class="option'.$tmp.'OFF" onmouseover="this.className=\'option'.$tmp.'ON\'" onmouseout="this.className=\'option'.$tmp.'OFF\'"';
$i = $i ? 0 : 1;
$options .= '<option value="'.$mysaved['id'].'"';
$options .= (isset($_SESSION['canned']['id']) && $_SESSION['canned']['id'] == $mysaved['id']) ? ' selected="selected" ' : '';
$options .= '>'.$mysaved['title'].'</option>';
$javascript_messages.='myMsgTxt['.$mysaved['id'].']=\''.str_replace("\r\n","\\r\\n' + \r\n'", addslashes($mysaved['message']) )."';\n";
$javascript_titles.='myTitle['.$mysaved['id'].']=\''.addslashes($mysaved['title'])."';\n";
echo '
<tr>
<td>'.$mysaved['title'].'</td>
<td>
';
if ($num > 1)
{
if ($j == 1)
{
echo'<img src="../img/blank.gif" width="16" height="16" alt="" style="padding:3px;border:none;" /> <a href="manage_canned.php?a=order&amp;replyid='.$mysaved['id'].'&amp;move=15&amp;token='.hesk_token_echo(0).'" data-toggle="tooltip" data-placement="top" title="'.$hesklang['move_dn'].'"><i class="fa fa-arrow-down" style="font-size: 14px; color: green"></i></a>';
}
elseif ($j == $num)
{
echo'<a href="manage_canned.php?a=order&amp;replyid='.$mysaved['id'].'&amp;move=-15&amp;token='.hesk_token_echo(0).'" data-toggle="tooltip" data-placement="top" title="'.$hesklang['move_up'].'"><i class="fa fa-arrow-up" style="font-size: 14px; color: green"></i></a> <img src="../img/blank.gif" width="16" height="16" alt="" style="padding:3px;border:none;" />';
}
else
{
echo'
<a href="manage_canned.php?a=order&amp;replyid='.$mysaved['id'].'&amp;move=-15&amp;token='.hesk_token_echo(0).'" data-toggle="tooltip" data-placement="top" title="'.$hesklang['move_up'].'"><i class="fa fa-arrow-up" style="font-size: 14px; color: green"></i></a>
<a href="manage_canned.php?a=order&amp;replyid='.$mysaved['id'].'&amp;move=15&amp;token='.hesk_token_echo(0).'" data-toggle="tooltip" data-placement="top" title="'.$hesklang['move_dn'].'"><i class="fa fa-arrow-down" style="font-size: 14px; color: green"></i></a>
';
}
}
else
{
echo '';
}
echo '
<a href="manage_canned.php?a=remove&amp;id='.$mysaved['id'].'&amp;token='.hesk_token_echo(0).'" onclick="return confirm_delete();" data-toggle="tooltip" data-placement="top" title="'.$hesklang['delete'].'"><i class="fa fa-times" style="font-size: 14px; color: #FF0000"></i></a>&nbsp;</td>
</tr>
';
} // End while
}
?>
</table>
</div>
</div>
<div class="content-wrapper">
<section class="content">
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['savedResponses']; ?>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="col-md-7">
<script language="javascript" type="text/javascript"><!--
var myMsgTxt = new Array();
myMsgTxt[0]='';
var myTitle = new Array();
myTitle[0]='';
<?php
echo $javascript_titles;
echo $javascript_messages;
?>
function setMessage(msgid) {
if (document.getElementById) {
document.getElementById('HeskMsg').innerHTML='<textarea class="form-control" name="msg" rows="15" cols="70">'+myMsgTxt[msgid]+'</textarea>';
document.getElementById('HeskTitle').innerHTML='<input type="text" class="form-control" name="name" size="40" maxlength="50" value="'+myTitle[msgid]+'">';
} else {
document.form1.msg.value=myMsgTxt[msgid];
document.form1.name.value=myTitle[msgid];
}
if (msgid==0) {
document.form1.a[0].checked=true;
} else {
document.form1.a[1].checked=true;
}
<div class="box-body">
<?php if ($num < 1)
{
echo '<p>' . $hesklang['no_saved'] . '</p>';
}
//-->
</script>
else
{ ?>
<table class="table table-hover">
<tr>
<th><?php echo $hesklang['saved_title']; ?></th>
<th><?php echo $hesklang['opt']; ?></th>
</tr>
<?php
while ($mysaved = hesk_dbFetchAssoc($result)) {
$j++;
if (isset($_SESSION['canned']['selcat2']) && $mysaved['id'] == $_SESSION['canned']['selcat2']) {
$color = 'admin_green';
unset($_SESSION['canned']['selcat2']);
} else {
$color = $i ? 'admin_white' : 'admin_gray';
}
$tmp = $i ? 'White' : 'Blue';
$style = 'class="option' . $tmp . 'OFF" onmouseover="this.className=\'option' . $tmp . 'ON\'" onmouseout="this.className=\'option' . $tmp . 'OFF\'"';
$i = $i ? 0 : 1;
$options .= '<option value="' . $mysaved['id'] . '"';
$options .= (isset($_SESSION['canned']['id']) && $_SESSION['canned']['id'] == $mysaved['id']) ? ' selected="selected" ' : '';
$options .= '>' . $mysaved['title'] . '</option>';
$javascript_titles .= 'myTitle[' . $mysaved['id'] . ']=\'' . addslashes($mysaved['title']) . "';\n";
if ($modsForHesk_settings['rich_text_for_tickets']) {
$theMessage = hesk_html_entity_decode($mysaved['message']);
$theMessage = addslashes($theMessage);
$javascript_messages .= 'myMsgTxt[' . $mysaved['id'] . ']=\'' . str_replace("\r\n", "\\r\\n' + \r\n'", $theMessage) . "';\n";
} else {
$javascript_messages .= 'myMsgTxt[' . $mysaved['id'] . ']=\'' . str_replace("\r\n", "\\r\\n' + \r\n'", addslashes($mysaved['message'])) . "';\n";
}
echo '
<tr>
<td>' . $mysaved['title'] . '</td>
<td>
';
if ($num > 1) {
if ($j == 1) {
echo '<img src="../img/blank.gif" width="16" height="16" alt="" style="padding:3px;border:none;" /> <a href="manage_canned.php?a=order&amp;replyid=' . $mysaved['id'] . '&amp;move=15&amp;token=' . hesk_token_echo(0) . '"><i class="fa fa-fw fa-arrow-down icon-link green" data-toggle="tooltip" data-placement="top" title="' . $hesklang['move_dn'] . '"></i></a>';
} elseif ($j == $num) {
echo '<a href="manage_canned.php?a=order&amp;replyid=' . $mysaved['id'] . '&amp;move=-15&amp;token=' . hesk_token_echo(0) . '"><i class="fa fa-arrow-up icon-link green" data-toggle="tooltip" data-placement="top" title="' . $hesklang['move_up'] . '"></i></a> <img src="../img/blank.gif" width="16" height="16" alt="" style="padding:3px;border:none;" />';
} else {
echo '
<a href="manage_canned.php?a=order&amp;replyid=' . $mysaved['id'] . '&amp;move=-15&amp;token=' . hesk_token_echo(0) . '"><i class="fa fa-arrow-up icon-link green" data-toggle="tooltip" data-placement="top" title="' . $hesklang['move_up'] . '"></i></a>
<a href="manage_canned.php?a=order&amp;replyid=' . $mysaved['id'] . '&amp;move=15&amp;token=' . hesk_token_echo(0) . '"><i class="fa fa-arrow-down icon-link green" data-toggle="tooltip" data-placement="top" title="' . $hesklang['move_dn'] . '"></i></a>
';
}
} else {
echo '';
}
echo '
<a name="'.$mysaved['title'].'" href="manage_canned.php?a=remove&amp;id=' . $mysaved['id'] . '&amp;token=' . hesk_token_echo(0) . '" onclick="return confirm_delete();"><i class="fa fa-times icon-link red" data-toggle="tooltip" data-placement="top" title="' . $hesklang['delete'] . '"></i></a>&nbsp;</td>
</tr>
';
} // End while
}
?>
</table>
</div>
</div>
<?php if ($modsForHesk_settings['rich_text_for_tickets']): ?>
<script type="text/javascript">
/* <![CDATA[ */
$(document).ready(function() {
$('.htmlEditor').summernote({
height: 200,
toolbar: [
['style', ['bold', 'italic', 'underline', 'clear']],
['font', ['strikethrough', 'superscript', 'subscript']],
['para', ['ul', 'ol']]
]
});
});
/* ]]> */
</script>
<?php endif; ?>
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['manage_saved']; ?> <a href="javascript:void(0)"
onclick="javascript:alert('<?php echo hesk_makeJsString($hesklang['manage_intro']); ?>')"><i
class="fa fa-question-circle settingsquestionmark"></i></a>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<script language="javascript" type="text/javascript"><!--
// -->
var myMsgTxt = new Array();
var myTitle = new Array();
myMsgTxt[0] = '';
myTitle[0] = '';
<?php
echo $javascript_titles;
echo $javascript_messages;
?>
function setMessage(msgid) {
var useHtmlEditor = <?php echo $modsForHesk_settings['rich_text_for_tickets']; ?>;
var myMsg = myMsgTxt[msgid];
var mySubject = myTitle[msgid];
if (myMsg == '') {
if (useHtmlEditor) {
$("#message").summernote("reset");
}
else {
$('#message').val('');
}
$('#subject').val('');
return true;
}
if (document.getElementById) {
if (useHtmlEditor) {
$("#message").summernote('reset');
$("#message").summernote('editor.insertText', myMsg));
} else {
myMsg = $('<textarea />').html(myMsg).text();
$('#message').val(myMsg).trigger('input');
}
mySubject = $('<textarea />').html(mySubject).text();
$('#subject').val(mySubject).trigger('input');
}
else {
document.form1.message.value = myMsg;
document.form1.subject.value = mySubject;
}
if (msgid == 0) {
document.form1.a[0].checked = true;
} else {
document.form1.a[1].checked = true;
}
}
//-->
</script>
<?php
/* This will handle error, success and notice messages */
hesk_handle_messages();
?>
<h3><?php echo $hesklang['manage_saved']; ?> <a href="javascript:void(0)" onclick="javascript:alert('<?php echo hesk_makeJsString($hesklang['manage_intro']); ?>')"><i class="fa fa-question-circle" style="color:black"></i></a></h3>
<div class="footerWithBorder blankSpace"></div>
<form action="manage_canned.php" method="post" name="form1" class="form-horizontal" role="form">
<h3><?php echo $hesklang['new_saved']; ?></h3>
<div class="footerWithBorder blankSpace"></div>
<?php
$onsubmit = '';
if ($modsForHesk_settings['rich_text_for_tickets']) {
$onsubmit = 'onsubmit="return validateRichText(\'message-help-block\', \'message-group\', \'message\', \''.htmlspecialchars($hesklang['this_field_is_required']).'\')"';
}
?>
<form action="manage_canned.php" method="post" name="form1" class="form-horizontal" role="form" data-toggle="validator" <?php echo $onsubmit; ?>>
<div class="form-group">
<div class="col-sm-12">
<?php
if ($num > 0)
{
?>
<div class="radio">
<label><input type="radio" name="a" value="new" <?php echo (!isset($_SESSION['canned']['what']) || $_SESSION['canned']['what'] != 'EDIT') ? 'checked="checked"' : ''; ?> /> <?php echo $hesklang['canned_add']; ?></label>
if ($num > 0) {
?>
<div class="row">
<div class="col-sm-12">
<div class="radio">
<label><input type="radio" name="a"
value="new" <?php echo (!isset($_SESSION['canned']['what']) || $_SESSION['canned']['what'] != 'EDIT') ? 'checked="checked"' : ''; ?> /> <?php echo $hesklang['canned_add']; ?>
</label>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="radio">
<label><input type="radio" name="a" value="edit" <?php echo (isset($_SESSION['canned']['what']) && $_SESSION['canned']['what'] == 'EDIT') ? 'checked="checked"' : ''; ?> /> <?php echo $hesklang['canned_edit']; ?></label>:
<label><input type="radio" name="a"
value="edit" <?php echo (isset($_SESSION['canned']['what']) && $_SESSION['canned']['what'] == 'EDIT') ? 'checked="checked"' : ''; ?> /> <?php echo $hesklang['canned_edit']; ?>
</label>:
</div>
</div>
<div class="col-sm-6">
<select class="form-control" name="saved_replies" onchange="setMessage(this.value)"><option value="0"> - <?php echo $hesklang['select_empty']; ?> - </option><?php echo $options; ?></select>
<select class="form-control" name="saved_replies" onchange="setMessage(this.value)">
<option value="0"> - <?php echo $hesklang['select_empty']; ?>-
</option><?php echo $options; ?></select>
</div>
</div>
<?php
}
else
{
echo '<input type="hidden" name="a" value="new" /><label> ' . $hesklang['canned_add'] . '</label>';
<?php
} else {
echo '<input type="hidden" name="a" value="new" /><label> ' . $hesklang['canned_add'] . '</label>';
}
?>
</div>
</div>
<div class="form-group">
<label for="name" class="col-sm-2 control-label"><?php echo $hesklang['saved_title']; ?>:</label>
<label for="name" class="col-sm-2 control-label"><?php echo $hesklang['saved_title']; ?></label>
<div class="col-sm-10">
<span id="HeskTitle"><input class="form-control" placeholder="<?php echo $hesklang['saved_title']; ?>" type="text" name="name" size="40" maxlength="50" <?php if (isset($_SESSION['canned']['name'])) {echo ' value="'.stripslashes($_SESSION['canned']['name']).'" ';} ?> /></span>
<span id="HeskTitle"><input id="subject" class="form-control"
placeholder="<?php echo htmlspecialchars($hesklang['saved_title']); ?>"
type="text" name="name" size="40"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
maxlength="50" <?php if (isset($_SESSION['canned']['name'])) {
echo ' value="' . stripslashes($_SESSION['canned']['name']) . '" ';
} ?> required></span>
<div class="help-block with-errors"></div>
</div>
</div>
<div class="form-group">
<label for="msg" class="col-sm-2 control-label"><?php echo $hesklang['message']; ?>:</label>
<div class="form-group" id="message-group">
<label for="msg" class="col-sm-2 control-label"><?php echo $hesklang['message']; ?></label>
<div class="col-sm-10">
<span id="HeskMsg">
<textarea class="form-control" placeholder="<?php echo $hesklang['message']; ?>" name="msg" rows="15" cols="70"><?php
if (isset($_SESSION['canned']['msg']))
{
echo stripslashes($_SESSION['canned']['msg']);
}
?></textarea>
<?php echo $hesklang['insert_special']; ?>:
<a href="javascript:void(0)" onclick="hesk_insertTag('HESK_NAME')"><?php echo $hesklang['name']; ?></a> |
<a href="javascript:void(0)" onclick="hesk_insertTag('HESK_EMAIL')"><?php echo $hesklang['email']; ?></a>
<?php
foreach ($hesk_settings['custom_fields'] as $k=>$v)
{
if ($v['use'])
{
echo '| <a href="javascript:void(0)" onclick="hesk_insertTag(\'HESK_'.$k.'\')">'.$v['name'].'</a> ';
}
}
?>
</span>
</div>
<span id="HeskMsg">
<textarea id="message" class="htmlEditor form-control"
placeholder="<?php echo htmlspecialchars($hesklang['message']); ?>" name="msg"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
rows="15" cols="70" required><?php
if (isset($_SESSION['canned']['msg'])) {
echo stripslashes($_SESSION['canned']['msg']);
}
?></textarea>
</span>
<div class="help-block with-errors" id="message-help-block"></div>
<?php echo $hesklang['insert_special']; ?>:
<a href="javascript:void(0)"
onclick="hesk_insertTag('HESK_ID')"><?php echo $hesklang['seqid']; ?></a> |
<a href="javascript:void(0)"
onclick="hesk_insertTag('HESK_TRACK_ID')"><?php echo $hesklang['trackID']; ?></a> |
<a href="javascript:void(0)"
onclick="hesk_insertTag('HESK_NAME')"><?php echo $hesklang['name']; ?></a> |
<a href="javascript:void(0)"
onclick="hesk_insertTag('HESK_FIRST_NAME')"><?php echo $hesklang['fname']; ?></a> |
<a href="javascript:void(0)"
onclick="hesk_insertTag('HESK_EMAIL')"><?php echo $hesklang['email']; ?></a> |
<a href="javascript:void(0)"
onclick="hesk_insertTag('HESK_OWNER')"><?php echo $hesklang['owner']; ?></a>
<?php
foreach ($hesk_settings['custom_fields'] as $k => $v) {
if ($v['use']) {
if ($modsForHesk_settings['custom_field_setting']) {
$v['name'] = $hesklang[$v['name']];
}
echo '| <a href="javascript:void(0)" onclick="hesk_insertTag(\'HESK_' . $k . '\')">' . $v['name'] . '</a> ';
}
}
?>
</div>
</div>
<div class="form-group text-center">
<input type="hidden" name="token" value="<?php hesk_token_echo(); ?>"/>
<input type="submit" value="<?php echo $hesklang['save_changes']; ?>" class="btn btn-default"/>
</div>
<div class="form-group" style="text-align: center">
<input type="hidden" name="token" value="<?php hesk_token_echo(); ?>" />
<input type="submit" value="<?php echo $hesklang['save_reply']; ?>" class="btn btn-default" />
</div>
</form>
</div>
</div>
</section>
</div>
<?php
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();
@ -313,129 +400,127 @@ exit();
function edit_saved()
{
global $hesk_settings, $hesklang;
global $hesk_settings, $hesklang;
/* A security check */
hesk_token_check('POST');
/* A security check */
hesk_token_check('POST');
$hesk_error_buffer = '';
$id = intval( hesk_POST('saved_replies') ) or $hesk_error_buffer .= '<li>' . $hesklang['selcan'] . '</li>';
$savename = hesk_input( hesk_POST('name') ) or $hesk_error_buffer .= '<li>' . $hesklang['ent_saved_title'] . '</li>';
$msg = hesk_input( hesk_POST('msg') ) or $hesk_error_buffer .= '<li>' . $hesklang['ent_saved_msg'] . '</li>';
$id = intval(hesk_POST('saved_replies')) or $hesk_error_buffer .= '<li>' . $hesklang['selcan'] . '</li>';
$savename = hesk_input(hesk_POST('name')) or $hesk_error_buffer .= '<li>' . $hesklang['ent_saved_title'] . '</li>';
$msg = hesk_input(hesk_POST('msg')) or $hesk_error_buffer .= '<li>' . $hesklang['ent_saved_msg'] . '</li>';
// Avoid problems with utf-8 newline chars in Javascript code, detect and remove them
$msg = preg_replace('/\R/u', "\r\n", $msg);
$_SESSION['canned']['what'] = 'EDIT';
$_SESSION['canned']['what'] = 'EDIT';
$_SESSION['canned']['id'] = $id;
$_SESSION['canned']['name'] = $savename;
$_SESSION['canned']['msg'] = $msg;
/* Any errors? */
if (strlen($hesk_error_buffer))
{
$hesk_error_buffer = $hesklang['rfm'].'<br /><br /><ul>'.$hesk_error_buffer.'</ul>';
hesk_process_messages($hesk_error_buffer,'manage_canned.php?saved_replies='.$id);
if (strlen($hesk_error_buffer)) {
$hesk_error_buffer = $hesklang['rfm'] . '<br /><br /><ul>' . $hesk_error_buffer . '</ul>';
hesk_process_messages($hesk_error_buffer, 'manage_canned.php?saved_replies=' . $id);
}
$result = hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."std_replies` SET `title`='".hesk_dbEscape($savename)."',`message`='".hesk_dbEscape($msg)."' WHERE `id`='".intval($id)."' LIMIT 1");
$result = hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "std_replies` SET `title`='" . hesk_dbEscape($savename) . "',`message`='" . hesk_dbEscape($msg) . "' WHERE `id`='" . intval($id) . "'");
unset($_SESSION['canned']['what']);
unset($_SESSION['canned']['what']);
unset($_SESSION['canned']['id']);
unset($_SESSION['canned']['name']);
unset($_SESSION['canned']['msg']);
hesk_process_messages($hesklang['your_saved'],'manage_canned.php?saved_replies='.$id,'SUCCESS');
hesk_process_messages($hesklang['your_saved'], 'manage_canned.php?saved_replies=' . $id, 'SUCCESS');
} // End edit_saved()
function new_saved()
{
global $hesk_settings, $hesklang;
global $hesk_settings, $hesklang;
/* A security check */
hesk_token_check('POST');
/* A security check */
hesk_token_check('POST');
$hesk_error_buffer = '';
$savename = hesk_input( hesk_POST('name') ) or $hesk_error_buffer .= '<li>' . $hesklang['ent_saved_title'] . '</li>';
$msg = hesk_input( hesk_POST('msg') ) or $hesk_error_buffer .= '<li>' . $hesklang['ent_saved_msg'] . '</li>';
$savename = hesk_input(hesk_POST('name')) or $hesk_error_buffer .= '<li>' . $hesklang['ent_saved_title'] . '</li>';
$msg = hesk_input(hesk_POST('msg')) or $hesk_error_buffer .= '<li>' . $hesklang['ent_saved_msg'] . '</li>';
// Avoid problems with utf-8 newline chars in Javascript code, detect and remove them
$msg = preg_replace('/\R/u', "\r\n", $msg);
$_SESSION['canned']['what'] = 'NEW';
$_SESSION['canned']['what'] = 'NEW';
$_SESSION['canned']['name'] = $savename;
$_SESSION['canned']['msg'] = $msg;
/* Any errors? */
if (strlen($hesk_error_buffer))
{
$hesk_error_buffer = $hesklang['rfm'].'<br /><br /><ul>'.$hesk_error_buffer.'</ul>';
hesk_process_messages($hesk_error_buffer,'manage_canned.php');
if (strlen($hesk_error_buffer)) {
$hesk_error_buffer = $hesklang['rfm'] . '<br /><br /><ul>' . $hesk_error_buffer . '</ul>';
hesk_process_messages($hesk_error_buffer, 'manage_canned.php');
}
/* Get the latest reply_order */
$result = hesk_dbQuery('SELECT `reply_order` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'std_replies` ORDER BY `reply_order` DESC LIMIT 1');
$row = hesk_dbFetchRow($result);
$my_order = $row[0]+10;
/* Get the latest reply_order */
$result = hesk_dbQuery('SELECT `reply_order` FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'std_replies` ORDER BY `reply_order` DESC LIMIT 1');
$row = hesk_dbFetchRow($result);
$my_order = $row[0] + 10;
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."std_replies` (`title`,`message`,`reply_order`) VALUES ('".hesk_dbEscape($savename)."','".hesk_dbEscape($msg)."','".intval($my_order)."')");
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "std_replies` (`title`,`message`,`reply_order`) VALUES ('" . hesk_dbEscape($savename) . "','" . hesk_dbEscape($msg) . "','" . intval($my_order) . "')");
unset($_SESSION['canned']['what']);
unset($_SESSION['canned']['what']);
unset($_SESSION['canned']['name']);
unset($_SESSION['canned']['msg']);
hesk_process_messages($hesklang['your_saved'],'manage_canned.php','SUCCESS');
hesk_process_messages($hesklang['your_saved'], 'manage_canned.php', 'SUCCESS');
} // End new_saved()
function remove()
{
global $hesk_settings, $hesklang;
global $hesk_settings, $hesklang;
/* A security check */
hesk_token_check();
/* A security check */
hesk_token_check();
$mysaved = intval( hesk_GET('id') ) or hesk_error($hesklang['id_not_valid']);
$mysaved = intval(hesk_GET('id')) or hesk_error($hesklang['id_not_valid']);
hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."std_replies` WHERE `id`='".intval($mysaved)."' LIMIT 1");
if (hesk_dbAffectedRows() != 1)
{
hesk_error("$hesklang[int_error]: $hesklang[reply_not_found].");
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "std_replies` WHERE `id`='" . intval($mysaved) . "'");
if (hesk_dbAffectedRows() != 1) {
hesk_error("$hesklang[int_error]: $hesklang[reply_not_found].");
}
hesk_process_messages($hesklang['saved_rem_full'],'manage_canned.php','SUCCESS');
hesk_process_messages($hesklang['saved_rem_full'], 'manage_canned.php', 'SUCCESS');
} // End remove()
function order_saved()
{
global $hesk_settings, $hesklang;
global $hesk_settings, $hesklang;
/* A security check */
hesk_token_check();
/* A security check */
hesk_token_check();
$replyid = intval( hesk_GET('replyid') ) or hesk_error($hesklang['reply_move_id']);
$replyid = intval(hesk_GET('replyid')) or hesk_error($hesklang['reply_move_id']);
$_SESSION['canned']['selcat2'] = $replyid;
$reply_move = intval( hesk_GET('move') );
$reply_move = intval(hesk_GET('move'));
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."std_replies` SET `reply_order`=`reply_order`+".intval($reply_move)." WHERE `id`='".intval($replyid)."' LIMIT 1");
if (hesk_dbAffectedRows() != 1) {hesk_error("$hesklang[int_error]: $hesklang[reply_not_found].");}
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "std_replies` SET `reply_order`=`reply_order`+" . intval($reply_move) . " WHERE `id`='" . intval($replyid) . "'");
if (hesk_dbAffectedRows() != 1) {
hesk_error("$hesklang[int_error]: $hesklang[reply_not_found].");
}
/* Update all category fields with new order */
$result = hesk_dbQuery('SELECT `id` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'std_replies` ORDER BY `reply_order` ASC');
/* Update all category fields with new order */
$result = hesk_dbQuery('SELECT `id` FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'std_replies` ORDER BY `reply_order` ASC');
$i = 10;
while ($myreply=hesk_dbFetchAssoc($result))
{
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."std_replies` SET `reply_order`=".intval($i)." WHERE `id`='".intval($myreply['id'])."' LIMIT 1");
$i += 10;
}
$i = 10;
while ($myreply = hesk_dbFetchAssoc($result)) {
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "std_replies` SET `reply_order`=" . intval($i) . " WHERE `id`='" . intval($myreply['id']) . "'");
$i += 10;
}
header('Location: manage_canned.php');
exit();
header('Location: manage_canned.php');
exit();
} // End order_saved()
?>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,275 @@
<?php
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
define('PAGE_TITLE', 'ADMIN_CUSTOM_NAV_ELEMENTS');
define('MFH_PAGE_LAYOUT', 'TOP_ONLY');
define('EXTRA_JS', '<script src="'.HESK_PATH.'internal-api/js/manage-custom-nav-elements.js"></script>');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/mail_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
//hesk_checkPermission('can_man_custom_nav');
/* Print header */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
/* Print main manage users page */
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
<div class="content-wrapper">
<section class="content">
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['custom_nav_menu_elements']; ?>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<div class="row">
<div class="col-md-12 text-right">
<button id="create-button" class="btn btn-success">
<i class="fa fa-plus-circle"></i>&nbsp;
<?php echo $hesklang['create_new']; ?>
</button>
</div>
<div class="col-md-12">
<table class="table table-striped">
<thead>
<tr>
<th><?php echo $hesklang['id']; ?></th>
<th><?php echo $hesklang['custom_nav_text']; ?></th>
<th><?php echo $hesklang['custom_nav_subtext']; ?></th>
<th><?php echo $hesklang['image_url_slash_font_icon']; ?></th>
<th><?php echo $hesklang['url']; ?></th>
<th><?php echo $hesklang['actions']; ?></th>
</tr>
</thead>
<tbody id="table-body">
</tbody>
</table>
</div>
</div>
</div>
<div class="overlay" id="overlay">
<i class="fa fa-spinner fa-spin"></i>
</div>
</div>
</section>
</div>
<div class="modal fade" id="nav-element-modal" tabindex="-1" role="dialog" style="overflow: hidden">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header" style="cursor: move">
<button type="button" class="close cancel-callback" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="edit-label">
<?php echo $hesklang['edit_custom_nav_element_title_case']; ?>
</h4>
<h4 class="modal-title" id="create-label">
<?php echo $hesklang['create_custom_nav_element_title_case']; ?>
</h4>
</div>
<form id="manage-nav-element" class="form-horizontal" data-toggle="validator">
<input type="hidden" name="id">
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label for="place" class="col-md-4 col-sm-12 control-label">
<?php echo $hesklang['place']; ?>
<i class="fa fa-question-circle settingsquestionmark" data-toggle="htmlpopover"
title="<?php echo $hesklang['place']; ?>"
data-content="<?php echo $hesklang['place_help']; ?>"></i>
</label>
<div class="col-md-8 col-sm-12">
<select name="place" id="place" class="form-control"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
required>
<option value="1"><?php echo $hesklang['homepage_block']; ?></option>
<option value="2"><?php echo $hesklang['customer_navigation']; ?></option>
<option value="3"><?php echo $hesklang['staff_navigation']; ?></option>
</select>
<div class="help-block with-errors"></div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-sm-12">
<h4><?php echo $hesklang['custom_nav_text']; ?></h4>
<?php foreach ($hesk_settings['languages'] as $language => $value): ?>
<div class="form-group">
<label for="text[<?php echo $language; ?>]" class="col-md-4 col-sm-12 control-label">
<?php echo $language; ?>
</label>
<div class="col-md-8 col-sm-12">
<input type="text" name="text" class="form-control"
data-text-language="<?php echo $language; ?>"
id="text[<?php echo $language; ?>" placeholder="<?php echo $hesklang['custom_nav_text']; ?>"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
required>
<div class="help-block with-errors"></div>
</div>
</div>
<?php endforeach; ?>
<div id="subtext">
<h4><?php echo $hesklang['custom_nav_subtext']; ?></h4>
<?php foreach ($hesk_settings['languages'] as $language => $value): ?>
<div class="form-group">
<label for="subtext[<?php echo $language; ?>]" class="col-md-4 col-sm-12 control-label">
<?php echo $language; ?>
</label>
<div class="col-md-8 col-sm-12">
<input type="text" name="subtext" class="form-control"
data-subtext-language="<?php echo $language; ?>"
id="subtext[<?php echo $language; ?>" placeholder="<?php echo $hesklang['custom_nav_subtext']; ?>"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
required>
<div class="help-block with-errors"></div>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<div class="col-md-6 col-sm-12">
<h4><?php echo $hesklang['url']; ?></h4>
<div class="form-group">
<label for="image-type" class="col-md-4 col-sm-12 control-label">
<?php echo $hesklang['url']; ?>
<i class="fa fa-question-circle settingsquestionmark" data-toggle="htmlpopover"
title="<?php echo $hesklang['url']; ?>"
data-content="<?php echo $hesklang['url_help']; ?>"></i>
</label>
<div class="col-md-8 col-sm-12">
<input type="text" name="url" class="form-control"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
placeholder="<?php echo $hesklang['url']; ?>" required>
<div class="help-block with-errors"></div>
</div>
</div>
<h4><?php echo $hesklang['image']; ?></h4>
<div class="form-group">
<label for="image-type" class="col-md-4 col-sm-12 control-label"><?php echo $hesklang['image_type']; ?></label>
<div class="col-md-8 col-sm-12">
<select name="image-type" id="image-type" class="form-control"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
required>
<option value="image-url"><?php echo $hesklang['image_url']; ?></option>
<option value="font-icon"><?php echo $hesklang['font_icon']; ?></option>
</select>
<div class="help-block with-errors"></div>
</div>
</div>
<div class="form-group" id="image-url-group">
<label for="image-url" class="col-md-4 col-sm-12 control-label">
<?php echo $hesklang['image_url']; ?>
<i class="fa fa-question-circle settingsquestionmark" data-toggle="htmlpopover"
title="<?php echo $hesklang['image_url']; ?>"
data-content="<?php echo $hesklang['image_url_help']; ?>"></i>
</label>
<div class="col-md-8 col-sm-12">
<input type="text" name="image-url" class="form-control"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
placeholder="<?php echo $hesklang['image_url']; ?>" required>
<div class="help-block with-errors"></div>
</div>
</div>
<div class="form-group" id="font-icon-group">
<p style="display:none" id="no-icon"><?php echo $hesklang['sm_no_icon']; ?></p>
<p style="display:none" id="search-icon"><?php echo $hesklang['sm_search_icon']; ?></p>
<p style="display:none"
id="footer-icon"><?php echo $hesklang['sm_iconpicker_footer_label']; ?></p>
<label for="font-icon" class="col-md-4 col-sm-12 control-label"><?php echo $hesklang['font_icon']; ?></label>
<div class="col-md-8 col-sm-12">
<div class="btn btn-default iconpicker-container" data-toggle="nav-iconpicker">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<div class="btn-group" id="action-buttons">
<button type="button" class="btn btn-default cancel-button" data-dismiss="modal">
<i class="fa fa-times-circle"></i>
<span><?php echo $hesklang['cancel']; ?></span>
</button>
<button type="submit" class="btn btn-success save-button">
<i class="fa fa-check-circle"></i>
<span><?php echo $hesklang['save']; ?></span>
</button>
</div>
</div>
</form>
</div>
</div>
</div>
<?php
echo mfh_get_hidden_fields_for_language(
array(
'edit',
'delete',
'no_custom_nav_elements_found',
'failed_to_load_custom_nav_elements',
'custom_nav_element_deleted',
'error_deleting_custom_nav_element',
'error_sorting_custom_nav_elements',
'custom_nav_element_created',
'custom_nav_element_saved',
'homepage_block',
'customer_navigation',
'staff_navigation',
'error_saving_custom_nav_element',
)
);
?>
<script type="text/html" id="nav-element-template">
<tr>
<td><span data-property="id" data-value="x"></span></td>
<td><span>
<ul data-property="text" class="list-unstyled"></ul>
</span></td>
<td><span>
<ul data-property="subtext" class="list-unstyled"></ul>
</span></td>
<td><span data-property="image-or-font"></span></td>
<td><span data-property="url"></span></td>
<td>
<a href="#" data-action="sort"
data-direction="up">
<i class="fa fa-fw fa-arrow-up icon-link green"
data-toggle="tooltip" title="<?php echo $hesklang['move_up']; ?>"></i>
</a>
<a href="#" data-action="sort"
data-direction="down">
<i class="fa fa-fw fa-arrow-down icon-link green"
data-toggle="tooltip" title="<?php echo $hesklang['move_dn'] ?>"></i>
</a>
<a href="#" data-action="edit">
<i class="fa fa-fw fa-pencil icon-link orange"
data-toggle="tooltip" title="<?php echo $hesklang['edit']; ?>"></i>
</a>
<a href="#" data-action="delete">
<i class="fa fa-fw fa-times icon-link red"
data-toggle="tooltip" title="<?php echo $hesklang['delete']; ?>"></i>
</a>
</td>
</tr>
</script>
<?php
require_once(HESK_PATH . 'inc/footer.inc.php');

View File

@ -0,0 +1,340 @@
<?php
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
define('PAGE_TITLE', 'ADMIN_EMAIL_TEMPLATES');
define('MFH_PAGE_LAYOUT', 'TOP_ONLY');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/mail_functions.inc.php');
require(HESK_PATH . 'inc/custom_fields.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
hesk_checkPermission('can_man_email_tpl');
define('WYSIWYG', 1);
// Are we performing an action?
$showEditPanel = false;
if (isset($_GET['action'])) {
if ($_GET['action'] == 'edit') {
$showEditPanel = true;
}
}
// Are we saving?
if (isset($_POST['action'])) {
if ($_POST['action'] == 'save') {
save();
}
}
/* Print header */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
if ($modsForHesk_settings['html_emails']) {
?>
<script type="text/javascript">
/* <![CDATA[ */
$(document).ready(function() {
$('.htmlEditor').summernote({
height: 200,
toolbar: [
['style', ['bold', 'italic', 'underline', 'clear']],
['font', ['strikethrough', 'superscript', 'subscript']],
['para', ['ul', 'ol']]
]
});
});
/* ]]> */
</script>
<?php
}
/* Print main manage users page */
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
<div class="content-wrapper">
<section class="content">
<div class="box">
<div class="box-body">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs" role="tablist">
<?php
// Show a link to banned_emails.php if user has permission
if (hesk_checkPermission('can_ban_emails', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['banemail'] . '" href="banned_emails.php">' . $hesklang['banemail'] . '</a>
</li>
';
}
if (hesk_checkPermission('can_ban_ips', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['banip'] . '" href="banned_ips.php">' . $hesklang['banip'] . '</a>
</li>';
}
// Show a link to status_message.php if user has permission to do so
if (hesk_checkPermission('can_service_msg', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['sm_title'] . '" href="service_messages.php">' . $hesklang['sm_title'] . '</a>
</li>';
}
?>
<li role="presentation" class="active">
<a href="#"><?php echo $hesklang['email_templates']; ?> <i
class="fa fa-question-circle settingsquestionmark" data-toggle="popover"
title="<?php echo $hesklang['email_templates']; ?>"
data-content="<?php echo $hesklang['email_templates_intro']; ?>"></i></a>
</li>
<?php
if (hesk_checkPermission('can_man_ticket_statuses', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['statuses'] . '" href="manage_statuses.php">' . $hesklang['statuses'] . '</a>
</li>
';
}
if (hesk_checkPermission('can_man_settings', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['tab_4'] . '" href="custom_fields.php">' .
$hesklang['tab_4']
. '</a>
</li>
';
}
?>
</ul>
<div class="tab-content summaryList tabPadding">
<?php if ($showEditPanel): ?>
<div class="row">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
<h4>
<?php
$isHtml = ($_GET['html'] == 'true');
$class = 'plaintext-editor';
if ($isHtml) {
$class = 'htmlEditor';
echo sprintf($hesklang['editing_html_template'], $_GET['template']);
} else {
echo sprintf($hesklang['editing_plain_text_template'], $_GET['template']);
} ?>
</h4>
</div>
<div class="panel-body">
<?php
$fileContent = '';
if ($isHtml) {
$fileContent = file_get_contents(HESK_PATH . 'language/' . urldecode($_GET['language']) . '/emails/html/' . $_GET['template']);
} else {
$fileContent = file_get_contents(HESK_PATH . 'language/' . urldecode($_GET['language']) . '/emails/' . $_GET['template']);
}
if ($fileContent === false) {
//throw error
}
?>
<a href="#" id="showSpecialTags"
onclick="toggleContainers(['specialTags'],['showSpecialTags'])">
<?php echo $hesklang['show_special_tags']; ?>
</a>
<div id="specialTags" style="display: none">
<a href="#" onclick="toggleContainers(['showSpecialTags'],['specialTags'])">
<?php echo $hesklang['hide_special_tags']; ?>
</a>
<table class="table table-striped table-responsive table-condensed">
<thead>
<tr>
<th><?php echo $hesklang['special_tag']; ?></th>
<th><?php echo $hesklang['description'] ?></th>
</tr>
</thead>
<tbody>
<?php
$tags = getSpecialTagMap();
foreach ($tags as $tag => $text): ?>
<tr>
<td><?php echo $tag; ?></td>
<td><?php echo $text; ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<form action="manage_email_templates.php" method="post">
<textarea name="text" rows="15"
class="form-control <?php echo $class; ?>"><?php echo $fileContent; ?></textarea>
<input type="hidden" name="action" value="save">
<input type="hidden" name="template"
value="<?php echo htmlspecialchars($_GET['template']); ?>">
<input type="hidden" name="language"
value="<?php echo htmlspecialchars($_GET['language']); ?>">
<input type="hidden" name="html" value="<?php echo $isHtml; ?>">
<br>
<?php
$fileWritable = false;
if ($isHtml) {
$fileWritable = is_writable(HESK_PATH . 'language/' . $_GET['language'] . '/emails/html/' . $_GET['template']);
} else {
$fileWritable = is_writable(HESK_PATH . 'language/' . $_GET['language'] . '/emails/' . $_GET['template']);
}
if (!$fileWritable) {
echo '<div class="alert alert-danger">
<p>' . sprintf($hesklang['email_template_directory_not_writable'], $_GET['template']) . '</p>
</div>';
} else {
echo '<input type="submit" class="btn btn-default" value="' . $hesklang['save'] . '">';
}
?>
</form>
</div>
</div>
</div>
</div>
<?php endif; ?>
<div class="row">
<div class="col-md-12">
<?php
/* This will handle error, success and notice messages */
hesk_handle_messages();
// Output list of templates, and provide links to edit the plaintext and HTML versions for each language
// First get list of languages
$languages = array();
foreach ($hesk_settings['languages'] as $key => $value) {
$languages[$key] = $hesk_settings['languages'][$key]['folder'];
}
// Get all files, but don't worry about index.htm, items beginning with '.', or the html folder
// We'll also assume the template file exists in all language folders and in the html folder
reset($languages);
$firstKey = key($languages);
$firstDirectory = HESK_PATH . 'language/' . $languages[$firstKey] . '/emails';
$directoryListing = preg_grep('/^([^.])/', scandir($firstDirectory));
$emailTemplates = array_diff($directoryListing, array('html', 'index.htm'));
?>
<table class="table table-striped table-responsive">
<thead>
<tr>
<th><?php echo $hesklang['file_name']; ?></th>
<?php foreach ($languages as $language => $languageCode): ?>
<th><?php echo $language; ?></th>
<?php endforeach; ?>
</tr>
</thead>
<tbody>
<?php foreach ($emailTemplates as $template): ?>
<tr>
<td><?php echo $template; ?></td>
<?php foreach ($languages as $language => $languageCode): ?>
<td>
<?php
echo getTemplateMarkup($template, $languageCode);
echo '&nbsp;&nbsp;&nbsp;';
if ($modsForHesk_settings['html_emails']) {
echo getTemplateMarkup($template, $languageCode, true);
}
?>
</td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
<?php
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();
function getTemplateMarkup($template, $languageCode, $html = false)
{
global $hesklang;
$templateUrl = urlencode($template);
$languageCodeUrl = urlencode($languageCode);
if ($html) {
$markup = '<a name="Edit '.$templateUrl.'" href="manage_email_templates.php?action=edit&template=' . $templateUrl . '&language=' . $languageCodeUrl . '&html=true">';
$markup .= '<i class="fa fa-html5 font-size-150" data-toggle="tooltip" title="' . $hesklang['edit_html_template'] . '"></i>';
$markup .= '</a>';
return $markup;
} else {
$markup = '<a name="Edit '.$templateUrl.'" href="manage_email_templates.php?action=edit&template=' . $templateUrl . '&language=' . $languageCodeUrl . '&html=false">';
$markup .= '<i class="fa fa-file-text-o font-size-150" data-toggle="tooltip" title="' . $hesklang['edit_plain_text_template'] . '"></i>';
$markup .= '</a>';
return $markup;
}
}
function save()
{
global $hesklang;
$filePath = HESK_PATH . 'language/' . $_POST['language'] . '/emails/' . $_POST['template'];
if ($_POST['html'] == '1') {
$filePath = HESK_PATH . 'language/' . $_POST['language'] . '/emails/html/' . $_POST['template'];
}
$success = file_put_contents($filePath, $_POST['text']);
if ($success === false) {
hesk_process_messages($hesklang['email_template_not_saved'], 'manage_email_templates.php');
} else {
$message = sprintf($hesklang['email_template_saved'], $_POST['template']);
hesk_process_messages($message, 'manage_email_templates.php', 'SUCCESS');
}
}
function getSpecialTagMap()
{
global $hesk_settings, $modsForHesk_settings, $hesklang;
$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'];
$map['%%MESSAGE_NO_ATTACHMENTS%%'] = $hesklang['ticket_message_no_attachments'];
$map['%%CREATED%%'] = $hesklang['ticket_created'];
$map['%%UPDATED%%'] = $hesklang['ticket_updated'];
$map['%%TRACK_ID%%'] = $hesklang['ticket_trackID'];
$map['%%TRACK_URL%%'] = $hesklang['ticket_url'];
$map['%%SITE_TITLE%%'] = $hesklang['wbst_title'];
$map['%%SITE_URL%%'] = $hesklang['wbst_url'];
$map['%%CATEGORY%%'] = $hesklang['ticket_category'];
$map['%%OWNER%%'] = $hesklang['ticket_owner'];
$map['%%PRIORITY%%'] = $hesklang['ticket_priority'];
$map['%%STATUS%%'] = $hesklang['ticket_status'];
$map['%%LAST_REPLY_BY%%'] = $hesklang['last_replier'];
$map['%%TIME_WORKED%%'] = $hesklang['ts'];
$i = 1;
foreach ($hesk_settings['custom_fields'] as $key => $value) {
if ($value['use']) {
$uppercaseKey = strtoupper($key);
$map['%%' . $uppercaseKey . '%%'] = sprintf($hesklang['custom_field_x'], $i++);
}
}
return $map;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,515 @@
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
define('VALIDATOR', 1);
define('PAGE_TITLE', 'ADMIN_PERMISSION_TPL');
define('MFH_PAGE_LAYOUT', 'TOP_ONLY');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/mail_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
/* Check permissions for this feature */
hesk_checkPermission('can_man_permission_tpl');
/* What should we do? */
if ($action = hesk_REQUEST('a')) {
if ($action == 'save') {
save();
} elseif ($action == 'create') {
create();
} elseif ($action == 'delete') {
deleteTemplate();
}
}
/* Print header */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
/* Print main manage users page */
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
$modsForHesk_settings = mfh_getSettings();
$res = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "permission_templates` ORDER BY `name` ASC");
$templates = array();
while ($row = hesk_dbFetchAssoc($res)) {
$templates[] = $row;
}
$featureArray = hesk_getFeatureArray();
$orderBy = $modsForHesk_settings['category_order_column'];
$res = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "categories` ORDER BY `" . $orderBy . "` ASC");
$categories = array();
while ($row = hesk_dbFetchAssoc($res)) {
$categories[] = $row;
}
?>
<div class="content-wrapper">
<section class="content">
<?php hesk_handle_messages(); ?>
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['manage_permission_groups']; ?>
<i class="fa fa-question-circle settingsquestionmark" data-toggle="tooltip" data-placement="right"
title="<?php echo $hesklang['manage_permission_groups_help']; ?>"></i>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<div class="text-right">
<a href="#" data-toggle="modal" data-target="#modal-template-new" class="btn btn-success nu-floatRight">
<i class="fa fa-plus-circle"></i> <?php echo $hesklang['create_new']; ?>
</a>
</div>
<table class="table table-striped">
<thead>
<tr>
<th><?php echo $hesklang['name']; ?></th>
<th><?php echo $hesklang['number_of_users']; ?></th>
<th><?php echo $hesklang['actions']; ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($templates as $row): ?>
<tr>
<td><?php echo $row['name']; ?></td>
<td><?php echo getNumberOfUsersWithPermissionGroup($row['id']); ?></td>
<td>
<a href="#" data-toggle="modal" data-target="#modal-template-<?php echo $row['id'] ?>">
<i class="fa fa-fw fa-pencil icon-link orange" data-toggle="tooltip"
title="<?php echo $hesklang['view_permissions_for_this_group'] ?>"></i></a>
<?php
if ($row['id'] != 1 && $row['id'] != 2):
?>
<a href="manage_permission_groups.php?a=delete&amp;id=<?php echo $row['id']; ?>">
<i class="fa fa-fw fa-times icon-link red" data-toggle="tooltip"
title="<?php echo $hesklang['delete']; ?>"></i></a>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</section>
</div>
<?php
foreach ($templates as $template) {
createEditModal($template, $featureArray, $categories);
}
buildCreateModal($featureArray, $categories);
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();
/*** START FUNCTIONS ***/
function getNumberOfUsersWithPermissionGroup($templateId)
{
global $hesk_settings;
$res = hesk_dbQuery("SELECT 1 FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `permission_template` = " . intval($templateId));
return hesk_dbNumRows($res);
}
function createEditModal($template, $features, $categories)
{
global $hesklang;
$enabledFeatures = array();
$enabledCategories = array();
if ($template['heskprivileges'] !== 'ALL') {
$enabledFeatures = explode(',', $template['heskprivileges']);
$enabledCategories = explode(',', $template['categories']);
}
?>
<div class="modal fade" id="modal-template-<?php echo $template['id'] ?>" tabindex="-1" role="dialog"
aria-labelledby="myLargeModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<form action="manage_permission_groups.php" role="form" method="post" id="form<?php echo $template['id']; ?>">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
<h4 class="modal-title"><?php echo sprintf($hesklang['permissions_for_group'], $template['name']); ?></h4>
</div>
<div class="modal-body">
<?php if ($template['id'] == 1): ?>
<div class="alert alert-info">
<i class="fa fa-info-circle"></i>
<?php echo $hesklang['protected_group']; ?>
</div>
<?php endif; ?>
<div class="row">
<div class="form-group">
<div class="col-sm-2">
<label for="name"
class="control-label"><?php echo $hesklang['group_name']; ?></label>
</div>
<div class="col-sm-10">
<input type="text" class="form-control" name="name"
value="<?php echo htmlspecialchars($template['name']); ?>"
placeholder="<?php echo htmlspecialchars($hesklang['group_name']); ?>"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
required>
<div class="help-block with-errors"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-sm-12">
<h4><?php echo $hesklang['menu_cat']; ?></h4>
<div class="footerWithBorder blankSpace"></div>
<div class="form-group">
<?php
foreach ($categories as $category):
$can_man_categories = hesk_checkPermission('can_man_cat', 0);
$checked = '';
$disabled = '';
if (in_array($category['id'], $enabledCategories) ||
$template['categories'] == 'ALL') {
$checked = 'checked ';
}
if ((!hesk_SESSION('isadmin') &&
!in_array($category['id'], $_SESSION['categories']) &&
!$can_man_categories) ||
$template['categories'] === 'ALL') {
$disabled = ' disabled';
}
if ($_SESSION['isadmin'] || $can_man_categories || in_array($category['id'], $_SESSION['categories']) || $checked): ?>
<div class="checkbox">
<label>
<input type="checkbox" name="categories[]"
value="<?php echo $category['id']; ?>" <?php echo $checked . ' ' . $disabled; ?>>
<?php echo $category['name']; ?>
</label>
</div>
<?php
endif;
endforeach; ?>
<div class="help-block with-errors"></div>
</div>
</div>
<div class="col-md-6 col-sm-12">
<h4><?php echo $hesklang['allow_feat']; ?></h4>
<div class="footerWithBorder blankSpace"></div>
<div class="form-group">
<?php
foreach ($features as $feature): ?>
<?php
$checked = '';
$disabled = '';
if (in_array($feature, $enabledFeatures) ||
$template['heskprivileges'] === 'ALL') {
$checked = 'checked ';
}
if ((!hesk_SESSION('isadmin') &&
strpos($_SESSION['heskprivileges'], $feature) === false) ||
$template['heskprivileges'] === 'ALL') {
$disabled = ' disabled';
}
if ($_SESSION['isadmin'] || strpos($_SESSION['heskprivileges'], $feature) !== false || $checked): ?>
<div class="checkbox">
<label>
<input type="checkbox" name="features[]"
value="<?php echo $feature; ?>" <?php echo $checked . $disabled; ?>>
<?php echo $hesklang[$feature]; ?>
</label>
</div>
<?php endif;
endforeach; ?>
<div class="help-block with-errors"></div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<input type="hidden" name="a" value="save">
<input type="hidden" name="template_id" value="<?php echo $template['id']; ?>">
<div class="btn-group">
<input type="submit" class="btn btn-success"
value="<?php echo $hesklang['save_changes']; ?>">
<button type="button" class="btn btn-default"
data-dismiss="modal"><?php echo $hesklang['close_modal_without_saving']; ?></button>
</div>
</div>
</form>
</div>
</div>
</div>
<?php
}
function buildCreateModal($features, $categories)
{
global $hesklang;
?>
<div class="modal fade" id="modal-template-new" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<form action="manage_permission_groups.php" role="form" method="post" id="createForm">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
<h4 class="modal-title"><?php echo $hesklang['create_new_group_title']; ?></h4>
</div>
<div class="modal-body">
<div class="row">
<div class="form-group">
<div class="col-sm-2">
<label for="name"
class="control-label"><?php echo $hesklang['group_name']; ?></label>
</div>
<div class="col-sm-10">
<input type="text" class="form-control" name="name"
placeholder="<?php echo $hesklang['group_name']; ?>" required>
<div class="help-block with-errors"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-sm-12">
<h4><?php echo $hesklang['menu_cat']; ?></h4>
<div class="footerWithBorder blankSpace"></div>
<div class="form-group">
<?php
foreach ($categories as $category):
if (hesk_SESSION('isadmin') || in_array($category['id'], $_SESSION['categories'])): ?>
<div class="checkbox">
<label>
<input type="checkbox" name="categories[]"
data-modal="new-categories"
data-checkbox="categories"
value="<?php echo $category['id']; ?>">
<?php echo $category['name']; ?>
</label>
</div>
<?php endif; endforeach; ?>
<div class="help-block with-errors"></div>
</div>
</div>
<div class="col-md-6 col-sm-12">
<h4><?php echo $hesklang['allow_feat']; ?></h4>
<div class="footerWithBorder blankSpace"></div>
<div class="form-group">
<?php foreach ($features as $feature):
if (strpos($_SESSION['heskprivileges'], $feature) !== false || hesk_SESSION('isadmin')):
?>
<div class="checkbox">
<label>
<input type="checkbox" name="features[]"
data-modal="new-features"
data-checkbox="features"
value="<?php echo $feature; ?>">
<?php echo $hesklang[$feature]; ?>
</label>
</div>
<?php endif; endforeach; ?>
<div class="help-block with-errors"></div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<input type="hidden" name="a" value="create">
<div class="btn-group">
<input type="submit" class="btn btn-success"
value="<?php echo $hesklang['save_changes']; ?>">
<button type="button" class="btn btn-default"
data-dismiss="modal"><?php echo $hesklang['close_modal_without_saving']; ?></button>
</div>
</div>
</form>
<script>
buildValidatorForPermissionTemplates('createForm', '<?php echo $hesklang['select_at_least_one_value']; ?>');
</script>
</div>
</div>
</div>
<?php
}
function save()
{
global $hesk_settings, $hesklang;
$templateId = hesk_POST('template_id');
$res = hesk_dbQuery("SELECT `heskprivileges`, `categories` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "permission_templates`
WHERE `id` = " . intval($templateId));
$row = hesk_dbFetchAssoc($res);
// Add 'can ban emails' if 'can unban emails' is set (but not added). Same with 'can ban ips'
$catArray = hesk_POST_array('categories');
$featArray = hesk_POST_array('features');
validate($featArray, $catArray);
if (in_array('can_unban_emails', $featArray) && !in_array('can_ban_emails', $featArray)) {
array_push($catArray, 'can_ban_emails');
}
if (in_array('can_unban_ips', $featArray) && !in_array('can_ban_ips', $featArray)) {
array_push($featArray, 'can_ban_ips');
}
$categories = implode(',', $catArray);
$features = implode(',', $featArray);
$name = hesk_POST('name');
// Only allow users to add what they are allowed to add
// Admins can handle anything
if (!$_SESSION['isadmin']) {
// Update categories based on user visibility
$originalCategories = explode(',', $row['categories']);
$newCategories = array();
foreach ($originalCategories as $innerCategory) {
if (in_array($innerCategory, $catArray) && in_array($innerCategory, $_SESSION['categories'])) {
$newCategories[] = $innerCategory;
} elseif (!in_array($innerCategory, $catArray) && !in_array($innerCategory, $_SESSION['categories'])) {
// The user can't modify this, so keep it in
$newCategories[] = $innerCategory;
}
// If neither, the user removed it.
}
// Update features based on user visibility
$originalFeatures = explode(',', $row['heskprivileges']);
$newFeatures = array();
foreach ($originalFeatures as $innerFeature) {
if (in_array($innerFeature, $featArray) && strpos($_SESSION['heskprivileges'], $innerFeature) !== false) {
$newFeatures[] = $innerFeature;
} elseif (!in_array($innerFeature, $featArray) && strpos($_SESSION['heskprivileges'], $innerFeature) === false) {
// The user can't modify this, so keep it in
$newFeatures[] = $innerFeature;
}
// If neither, the user removed it.
}
$categories = implode(',', $newCategories);
$features = implode(',', $newFeatures);
}
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "permission_templates`
SET `categories` = '" . hesk_dbEscape($categories) . "', `heskprivileges` = '" . hesk_dbEscape($features) . "',
`name` = '" . hesk_dbEscape($name) . "'
WHERE `id` = " . intval($templateId));
if ($row['categories'] != $categories || $row['heskprivileges'] != $features) {
// Any users with this template should have their permissions updated
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` SET `heskprivileges` = '" . hesk_dbEscape($features) . "',
`categories` = '" . hesk_dbEscape($categories) . "'
WHERE `permission_template` = " . intval($templateId));
}
hesk_process_messages($hesklang['permission_group_updated'], $_SERVER['PHP_SELF'], 'SUCCESS');
}
function create()
{
global $hesk_settings, $hesklang;
// Add 'can ban emails' if 'can unban emails' is set (but not added). Same with 'can ban ips'
$catArray = hesk_POST_array('categories');
$featArray = hesk_POST_array('features');
$name = hesk_POST('name');
validate($featArray, $catArray, true, $name);
if (in_array('can_unban_emails', $featArray) && !in_array('can_ban_emails', $featArray)) {
array_push($catArray, 'can_ban_emails');
}
if (in_array('can_unban_ips', $featArray) && !in_array('can_ban_ips', $featArray)) {
array_push($featArray, 'can_ban_ips');
}
$categories = implode(',', $catArray);
$features = implode(',', $featArray);
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "permission_templates` (`name`, `heskprivileges`, `categories`)
VALUES ('" . hesk_dbEscape($name) . "', '" . hesk_dbEscape($features) . "', '" . hesk_dbEscape($categories) . "')");
hesk_process_messages($hesklang['group_created'], $_SERVER['PHP_SELF'], 'SUCCESS');
}
function validate($features, $categories, $create = false, $name = '')
{
global $hesklang;
$errorMarkup = '<ul>';
$isValid = true;
if ($create && $name == '') {
$errorMarkup .= '<li>' . $hesklang['group_name_required'] . '</li>';
$isValid = false;
}
if (count($features) == 0) {
$errorMarkup .= '<li>' . $hesklang['you_must_select_a_feature'] . '</li>';
$isValid = false;
}
if (count($categories) == 0) {
$errorMarkup .= '<li>' . $hesklang['you_must_select_a_category'] . '</li>';
$isValid = false;
}
$errorMarkup .= '</ul>';
if (!$isValid) {
$error = sprintf($hesklang['permission_group_error'], $errorMarkup);
hesk_process_messages($error, $_SERVER['PHP_SELF']);
}
return true;
}
function deleteTemplate()
{
global $hesk_settings, $hesklang;
$id = hesk_GET('id');
// Admin/Staff templates cannot be deleted!
if ($id == 1 || $id == 2) {
hesk_process_messages($hesklang['cannot_delete_admin_or_staff'], $_SERVER['PHP_SELF']);
}
// Otherwise delete the template
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "permission_templates` WHERE `id` = " . intval($id));
if (hesk_dbAffectedRows() != 1) {
hesk_process_messages($hesklang['no_group_were_deleted'], $_SERVER['PHP_SELF']);
}
// Move all users who used to be in this group to "custom"
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` SET `permission_template` = NULL
WHERE `permission_template` = " . intval($id));
hesk_process_messages($hesklang['permission_group_deleted'], $_SERVER['PHP_SELF'], 'SUCCESS');
}
?>

909
admin/manage_statuses.php Normal file
View File

@ -0,0 +1,909 @@
<?php
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
define('PAGE_TITLE', 'ADMIN_STATUSES');
define('MFH_PAGE_LAYOUT', 'TOP_ONLY');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/status_functions.inc.php');
require(HESK_PATH . 'inc/mail_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
hesk_checkPermission('can_man_ticket_statuses');
define('WYSIWYG', 1);
// Are we performing an action?
if (isset($_REQUEST['a'])) {
if (defined('HESK_DEMO')) {
hesk_process_messages($hesklang['cannot_edit_status_demo'], 'manage_statuses.php');
} elseif ($_REQUEST['a'] == 'create') {
createStatus();
} elseif ($_REQUEST['a'] == 'update') {
updateStatus();
} elseif ($_REQUEST['a'] == 'delete') {
deleteStatus();
} elseif ($_REQUEST['a'] == 'sort') {
moveStatus();
} elseif ($_REQUEST['a'] == 'save') {
save();
}
}
$modsForHesk_settings = mfh_getSettings();
/* Print header */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
/* Print main manage users page */
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
<div class="content-wrapper">
<section class="content">
<div class="box">
<div class="box-body">
<div class="nav-tabs-custom">
<ul class="nav nav-tabs" role="tablist">
<?php
// Show a link to banned_emails.php if user has permission
if (hesk_checkPermission('can_ban_emails', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['banemail'] . '" href="banned_emails.php">' . $hesklang['banemail'] . '</a>
</li>
';
}
if (hesk_checkPermission('can_ban_ips', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['banip'] . '" href="banned_ips.php">' . $hesklang['banip'] . '</a>
</li>';
}
// Show a link to status_message.php if user has permission to do so
if (hesk_checkPermission('can_service_msg', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['sm_title'] . '" href="service_messages.php">' . $hesklang['sm_title'] . '</a>
</li>';
}
if (hesk_checkPermission('can_man_email_tpl', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['email_templates'] . '" href="manage_email_templates.php">' . $hesklang['email_templates'] . '</a>
</li>
';
}
?>
<li role="presentation" class="active">
<a href="#"><?php echo $hesklang['statuses']; ?> <i class="fa fa-question-circle settingsquestionmark"
data-toggle="popover"
title="<?php echo $hesklang['statuses']; ?>"
data-content="<?php echo $hesklang['statuses_intro']; ?>"></i></a>
</li>
<?php
if (hesk_checkPermission('can_man_settings', 0)) {
echo '
<li role="presentation">
<a title="' . $hesklang['tab_4'] . '" href="custom_fields.php">' .
$hesklang['tab_4']
. '</a>
</li>
';
}
?>
</ul>
<div class="tab-content summaryList tabPadding">
<div class="row">
<div class="col-md-12">
<?php
/* This will handle error, success and notice messages */
hesk_handle_messages();
//-- We need to get all of the statuses and dump the information to the page.
$numOfStatusesRS = hesk_dbQuery('SELECT 1 FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'statuses`');
$numberOfStatuses = hesk_dbNumRows($numOfStatusesRS);
$statuses = mfh_getAllStatuses();
?>
<form class="form-horizontal" method="post" action="manage_statuses.php" role="form">
<div class="panel panel-default">
<div class="panel-heading">
<h4>
<?php echo $hesklang['statuses']; ?>
<span style="float: right; margin-top: -7px">
<button type="button" class="btn btn-success" data-toggle="modal" data-target="#modal-status-new">
<i class="fa fa-plus-circle"></i>
<?php
echo $hesklang['new_status'];
?>
</button>
</span>
</h4>
</div>
<table class="table table-hover">
<thead>
<tr>
<th><?php echo $hesklang['status_name_title']; ?></th>
<th><?php echo $hesklang['closable_question']; ?></th>
<th><?php echo $hesklang['closedQuestionMark']; ?></th>
<th><?php echo $hesklang['actions']; ?></th>
</tr>
</thead>
<tbody>
<?php
$j = 1;
foreach ($statuses as $key => $row):
?>
<tr id="s<?php echo $row['ID']; ?>_row">
<td class="bold" style="color: <?php echo $row['TextColor']; ?>">
<?php echo $row['text']; ?>
</td>
<td>
<?php
if ($row['Closable'] == 'yes') {
echo $hesklang['yes_title_case'];
} elseif ($row['Closable'] == 'conly') {
echo $hesklang['customers_only'];
} elseif ($row['Closable'] == 'sonly') {
echo $hesklang['staff_only'];
} elseif ($row['Closable'] == 'no') {
echo $hesklang['no_title_case'];
}
?>
</td>
<td>
<?php
if ($row['IsClosed']) {
echo '<i class="fa fa-check-circle icon-link green"></i>';
}
?>
</td>
<td>
<span data-toggle="modal" data-target="#modal-status-<?php echo $row['ID']; ?>"
style="cursor: pointer;">
<i class="fa fa-pencil icon-link orange"
data-toggle="tooltip" title="<?php echo $hesklang['edit']; ?>"></i>
</span>
<?php echoArrows($j, $numberOfStatuses, $row['ID'], $modsForHesk_settings); ?>
<?php
// Only show the delete button if (1) it's not a default action and (2) no tickets are set to that status
$delete = canStatusBeDeleted($row['ID']);
$cursor = 'cursor: pointer';
$iconStyle = 'color: red';
$dataTarget = 'data-target="#modal-status-delete-' . $row['ID'] . '"';
$tooltip = $hesklang['delete'];
if ($delete == 'no-default' || $delete == 'no-tickets') {
$cursor = '';
$dataTarget = '';
$iconStyle = 'color: grey';
}
if ($delete == 'no-default') {
$tooltip = $hesklang['whyCantIDeleteThisStatusReason'];
} elseif ($delete == 'no-tickets') {
$tooltip = $hesklang['cannot_delete_status_tickets'];
}
?>
<span data-toggle="modal" <?php echo $dataTarget; ?>
style="<?php echo $cursor; ?>;">
<i class="fa fa-times icon-link" style="<?php echo $iconStyle; ?>"
data-toggle="tooltip" title="<?php echo $tooltip; ?>"></i>
</span>
</td>
</tr>
<?php
$j++;
endforeach; ?>
</tbody>
</table>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h4><?php echo $hesklang['defaultStatusForAction']; ?></h4>
</div>
<div class="panel-body">
<div class="form-group">
<label for="newTicket"
class="col-sm-6 col-xs-12 control-label"><?php echo $hesklang['isNewTicketMsg']; ?></label>
<div class="col-sm-6 col-xs-12">
<select name="newTicket" class="form-control" id="newTicket">
<?php
foreach ($statuses as $key => $row) {
if ($row['IsClosed'] == 1) {
continue;
}
$selectedEcho = ($row['IsNewTicketStatus'] == 1) ? 'selected="selected"' : '';
echo '<option value="' . $row['ID'] . '" ' . $selectedEcho . '>' . mfh_getDisplayTextForStatusId($row['ID']) . '</option>';
}
?>
</select>
</div>
</div>
<div class="form-group">
<label for="closedByClient"
class="col-sm-6 col-xs-12 control-label"><?php echo $hesklang['isClosedByClientMsg']; ?></label>
<div class="col-sm-6 col-xs-12">
<select name="closedByClient" class="form-control" id="closedByClient">
<?php
foreach ($statuses as $key => $row) {
if ($row['IsClosed'] == 0) {
continue;
}
$selectedEcho = ($row['IsClosedByClient'] == 1) ? 'selected="selected"' : '';
echo '<option value="' . $row['ID'] . '" ' . $selectedEcho . '>' . mfh_getDisplayTextForStatusId($row['ID']) . '</option>';
}
?>
</select>
</div>
</div>
<div class="form-group">
<label for="replyFromClient"
class="col-sm-6 col-xs-12 control-label"><?php echo $hesklang['isRepliedByClientMsg']; ?></label>
<div class="col-sm-6 col-xs-12">
<select name="replyFromClient" class="form-control" id="replyFromClient">
<?php
foreach ($statuses as $key => $row) {
if ($row['IsClosed'] == 1) {
continue;
}
$selectedEcho = ($row['IsCustomerReplyStatus'] == 1) ? 'selected="selected"' : '';
echo '<option value="' . $row['ID'] . '" ' . $selectedEcho . '>' . mfh_getDisplayTextForStatusId($row['ID']) . '</option>';
}
?>
</select>
</div>
</div>
<div class="form-group">
<label for="staffClosedOption"
class="col-sm-6 col-xs-12 control-label"><?php echo $hesklang['isStaffClosedOptionMsg']; ?></label>
<div class="col-sm-6 col-xs-12">
<select name="staffClosedOption" class="form-control" id="staffClosedOption">
<?php
foreach ($statuses as $key => $row) {
if ($row['IsClosed'] == 0) {
continue;
}
$selectedEcho = ($row['IsStaffClosedOption'] == 1) ? 'selected="selected"' : '';
echo '<option value="' . $row['ID'] . '" ' . $selectedEcho . '>' . mfh_getDisplayTextForStatusId($row['ID']) . '</option>';
}
?>
</select>
</div>
</div>
<div class="form-group">
<label for="staffReopenedStatus"
class="col-sm-6 col-xs-12 control-label"><?php echo $hesklang['isStaffReopenedStatusMsg']; ?></label>
<div class="col-sm-6 col-xs-12">
<select name="staffReopenedStatus" class="form-control"
id="staffReopenedStatus">
<?php
foreach ($statuses as $key => $row) {
if ($row['IsClosed'] == 1) {
continue;
}
$selectedEcho = ($row['IsStaffReopenedStatus'] == 1) ? 'selected="selected"' : '';
echo '<option value="' . $row['ID'] . '" ' . $selectedEcho . '>' . mfh_getDisplayTextForStatusId($row['ID']) . '</option>';
}
?>
</select>
</div>
</div>
<div class="form-group">
<label for="defaultStaffReplyStatus"
class="col-sm-6 col-xs-12 control-label"><?php echo $hesklang['isDefaultStaffReplyStatusMsg']; ?></label>
<div class="col-sm-6 col-xs-12">
<select name="defaultStaffReplyStatus" class="form-control"
id="defaultStaffReplyStatus">
<?php
foreach ($statuses as $key => $row) {
if ($row['IsClosed'] == 1) {
continue;
}
$selectedEcho = ($row['IsDefaultStaffReplyStatus'] == 1) ? 'selected="selected"' : '';
echo '<option value="' . $row['ID'] . '" ' . $selectedEcho . '>' . mfh_getDisplayTextForStatusId($row['ID']) . '</option>';
}
?>
</select>
</div>
</div>
<div class="form-group">
<label for="lockedTicketStatus"
class="col-sm-6 col-xs-12 control-label"><?php echo $hesklang['lockedTicketStatusMsg']; ?></label>
<div class="col-sm-6 col-xs-12">
<select name="lockedTicketStatus" class="form-control" id="lockedTicketStatus">
<?php
foreach ($statuses as $key => $row) {
$selectedEcho = ($row['LockedTicketStatus'] == 1) ? 'selected="selected"' : '';
echo '<option value="' . $row['ID'] . '" ' . $selectedEcho . '>' . mfh_getDisplayTextForStatusId($row['ID']) . '</option>';
}
?>
</select>
</div>
</div>
<div class="form-group">
<label for="autocloseTicketOption"
class="col-sm-6 col-xs-12 control-label"><?php echo $hesklang['autoclose_ticket_status']; ?></label>
<div class="col-sm-6 col-xs-12">
<select name="autocloseTicketOption" class="form-control"
id="autocloseTicketOption">
<?php
foreach ($statuses as $key => $row) {
if ($row['IsClosed'] == 0) {
continue;
}
$selectedEcho = ($row['IsAutocloseOption'] == 1) ? 'selected' : '';
echo '<option value="' . $row['ID'] . '" ' . $selectedEcho . '>' . mfh_getDisplayTextForStatusId($row['ID']) . '</option>';
}
?>
</select>
</div>
</div>
</div>
</div>
<div class="col-sm-6 col-sm-offset-6">
<input type="hidden" name="a" value="save">
<input type="submit" class="btn btn-default"
value="<?php echo $hesklang['save_changes']; ?>">
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
<?php
foreach ($statuses as $status) {
buildEditModal($status['ID']);
buildConfirmDeleteModal($status['ID']);
}
buildCreateModal();
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();
function buildConfirmDeleteModal($statusId)
{
global $hesklang;
?>
<div class="modal fade" id="modal-status-delete-<?php echo $statusId; ?>" tabindex="-1" role="dialog"
aria-labelledby="myLargeModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
<h4 class="modal-title"><?php echo $hesklang['confirm_delete_status_question']; ?></h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<p><?php echo $hesklang['confirm_delete_status']; ?></p>
</div>
</div>
</div>
<div class="modal-footer">
<input type="hidden" name="a" value="create">
<div class="btn-group">
<a href="manage_statuses.php?a=delete&id=<?php echo $statusId; ?>" class="btn btn-danger">
<?php echo $hesklang['delete']; ?>
</a>
<button type="button" class="btn btn-default"
data-dismiss="modal"><?php echo $hesklang['cancel']; ?></button>
</div>
</div>
</div>
</div>
</div>
<?php
}
function echoArrows($index, $numberOfStatuses, $statusId, $modsForHesk_settings)
{
global $hesklang;
if ($modsForHesk_settings['statuses_order_column'] == 'name') {
return;
}
if ($index !== 1) {
// Display move up
echo '<a href="manage_statuses.php?a=sort&move=-15&id=' . $statusId . '">
<i class="fa fa-arrow-up icon-link green" data-toggle="tooltip"
title="' . htmlspecialchars($hesklang['move_up']) . '"></i></a> ';
} else {
echo '<img src="../img/blank.gif" width="16" height="16" alt="" style="padding:3px;border:none;"> ';
}
if ($index !== $numberOfStatuses) {
// Display move down
echo '<a href="manage_statuses.php?a=sort&move=15&id=' . $statusId . '">
<i class="fa fa-arrow-down icon-link green" data-toggle="tooltip"
title="' . htmlspecialchars($hesklang['move_dn']) . '"></i></a>';
} else {
echo '<img src="../img/blank.gif" width="16" height="16" alt="" style="padding:3px;border:none;">';
}
}
function buildCreateModal()
{
global $hesklang, $hesk_settings;
$languages = array();
foreach ($hesk_settings['languages'] as $key => $value) {
$languages[$key] = $hesk_settings['languages'][$key]['folder'];
}
?>
<div class="modal fade" id="modal-status-new" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<form action="manage_statuses.php" role="form" method="post" class="form-horizontal" data-toggle="validator">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
<h4 class="modal-title"><?php echo $hesklang['create_new_status_title']; ?></h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-6">
<h4><?php echo $hesklang['status_name_title']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="popover"
title="<?php echo $hesklang['status_name_title']; ?>"
data-content="<?php echo $hesklang['status_name_title_help']; ?>"></i></h4>
<div class="footerWithBorder blankSpace"></div>
<?php foreach ($languages as $language => $languageCode): ?>
<div class="form-group">
<label class="col-sm-3 control-label" for="name[<?php echo $language; ?>]">
<?php echo $language; ?>
</label>
<div class="col-sm-9">
<input type="text" placeholder="<?php echo htmlspecialchars($language); ?>"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
class="form-control" name="name[<?php echo $language; ?>]" required>
<div class="help-block with-errors"></div>
</div>
</div>
<?php endforeach; ?>
</div>
<div class="col-md-6">
<h4><?php echo $hesklang['properties']; ?></h4>
<div class="footerWithBorder blankSpace"></div>
<div class="form-group">
<label for="text-color" class="col-sm-4 control-label">
<?php echo $hesklang['textColor']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="popover"
title="<?php echo $hesklang['textColor']; ?>"
data-content="<?php echo $hesklang['textColorDescr']; ?>"></i>
</label>
<div class="col-sm-8">
<input type="text" name="text-color" class="form-control colorpicker-trigger"
data-color=""
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
placeholder="<?php echo htmlspecialchars($hesklang['textColor']); ?>" required>
<div class="help-block with-errors"></div>
</div>
</div>
<div class="form-group">
<label for="closable" class="col-sm-4 control-label">
<?php echo $hesklang['closable']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="htmlpopover"
title="<?php echo $hesklang['closable']; ?>"
data-content="<?php echo $hesklang['closable_description']; ?>"></i>
</label>
<div class="col-sm-8">
<select name="closable" class="form-control">
<option value="yes"><?php echo $hesklang['yes_title_case']; ?></option>
<option value="conly"><?php echo $hesklang['customers_only']; ?></option>
<option value="sonly"><?php echo $hesklang['staff_only']; ?></option>
<option value="no"><?php echo $hesklang['no_title_case']; ?></option>
</select>
</div>
</div>
<div class="form-group">
<label for="closed" class="col-sm-4 control-label">
<?php echo $hesklang['closed_title']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="htmlpopover"
title="<?php echo $hesklang['closed_title']; ?>"
data-content="<?php echo $hesklang['closedQuestionMarkDescr']; ?>"></i>
</label>
<div class="col-sm-8">
<select name="closed" class="form-control">
<option value="1"><?php echo $hesklang['yes_title_case']; ?></option>
<option value="0"><?php echo $hesklang['no_title_case']; ?></option>
</select>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<input type="hidden" name="a" value="create">
<div class="btn-group">
<input type="submit" class="btn btn-success"
value="<?php echo $hesklang['save_changes']; ?>">
<button type="button" class="btn btn-default"
data-dismiss="modal"><?php echo $hesklang['close_modal_without_saving']; ?></button>
</div>
</div>
</form>
</div>
</div>
</div>
<?php
}
function buildEditModal($statusId)
{
global $hesklang, $hesk_settings;
// Get status information for this status
$getStatusRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` WHERE `ID` = " . intval($statusId));
$status = hesk_dbFetchAssoc($getStatusRs);
$textRs = hesk_dbQuery("SELECT `language`, `text` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "text_to_status_xref`
WHERE `status_id` = " . intval($statusId));
$textArray = array();
while ($row = hesk_dbFetchAssoc($textRs)) {
$textArray[$row['language']] = $row['text'];
}
$languages = array();
foreach ($hesk_settings['languages'] as $key => $value) {
$languages[$key] = $hesk_settings['languages'][$key]['folder'];
}
?>
<div class="modal fade" id="modal-status-<?php echo $statusId; ?>" tabindex="-1" role="dialog"
aria-labelledby="myLargeModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<form action="manage_statuses.php" role="form" method="post" class="form-horizontal" data-toggle="validator">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
<h4 class="modal-title"><?php echo sprintf($hesklang['editing_status_x'], $status['TextColor'], mfh_getDisplayTextForStatusId($statusId)); ?></h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-6">
<h4>
<?php echo $hesklang['status_name_title']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="popover"
title="<?php echo $hesklang['status_name_title']; ?>"
data-content="<?php echo $hesklang['status_name_title_help']; ?>"></i>
</h4>
<div class="footerWithBorder blankSpace"></div>
<?php foreach ($languages as $language => $languageCode):
$warning = '';
if (isset($textArray[$language])) {
$text = $textArray[$language];
} else {
hesk_setLanguage($language);
$text = $hesklang[$status['Key']];
hesk_resetLanguage();
$warning = 'has-warning';
}
?>
<div class="form-group <?php echo $warning; ?>">
<label class="col-sm-3 control-label" for="name[<?php echo $language; ?>]">
<?php
if ($warning != '') {
echoWarningForStatus();
}
echo $language;
?>
</label>
<div class="col-sm-9">
<input type="text" placeholder="<?php echo htmlspecialchars($language); ?>"
class="form-control" name="name[<?php echo $language; ?>]"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
value="<?php echo htmlspecialchars($text); ?>" required>
<div class="help-block with-errors"></div>
</div>
</div>
<?php endforeach; ?>
</div>
<div class="col-md-6">
<h4><?php echo $hesklang['properties']; ?></h4>
<div class="footerWithBorder blankSpace"></div>
<div class="form-group">
<label for="text-color" class="col-sm-4 control-label">
<?php echo $hesklang['textColor']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="popover"
title="<?php echo $hesklang['textColor']; ?>"
data-content="<?php echo $hesklang['textColorDescr']; ?>"></i>
</label>
<div class="col-sm-8">
<input type="text" name="text-color" class="form-control colorpicker-trigger"
value="<?php echo $status['TextColor']; ?>"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
placeholder="<?php echo htmlspecialchars($hesklang['textColor']); ?>" required>
<div class="help-block with-errors"></div>
</div>
</div>
<div class="form-group">
<label for="closable" class="col-sm-4 control-label">
<?php echo $hesklang['closable']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="htmlpopover"
title="<?php echo $hesklang['closable']; ?>"
data-content="<?php echo $hesklang['closable_description']; ?>"></i>
</label>
<div class="col-sm-8">
<?php
$yesSelected = $status['Closable'] == 'yes' ? 'selected' : '';
$customersOnlySelected = $status['Closable'] == 'conly' ? 'selected' : '';
$staffOnlySelected = $status['Closable'] == 'sonly' ? 'selected' : '';
$noSelected = $status['Closable'] == 'no' ? 'selected' : '';
?>
<select name="closable" class="form-control">
<option
value="yes" <?php echo $yesSelected; ?>><?php echo $hesklang['yes_title_case']; ?></option>
<option
value="conly" <?php echo $customersOnlySelected; ?>><?php echo $hesklang['customers_only']; ?></option>
<option
value="sonly" <?php echo $staffOnlySelected; ?>><?php echo $hesklang['staff_only']; ?></option>
<option
value="no" <?php echo $noSelected; ?>><?php echo $hesklang['no_title_case']; ?></option>
</select>
</div>
</div>
<div class="form-group">
<label for="closed" class="col-sm-4 control-label">
<?php echo $hesklang['closed_title']; ?>
<i class="fa fa-question-circle settingsquestionmark"
data-toggle="htmlpopover"
title="<?php echo $hesklang['closed_title']; ?>"
data-content="<?php echo $hesklang['closedQuestionMarkDescr']; ?>"></i>
</label>
<div class="col-sm-8">
<?php
$yes = $status['IsClosed'] == 1 ? 'selected' : '';
$no = $status['IsClosed'] == 1 ? '' : 'selected';
?>
<select name="closed" class="form-control">
<option
value="1" <?php echo $yes; ?>><?php echo $hesklang['yes_title_case']; ?></option>
<option
value="0" <?php echo $no; ?>><?php echo $hesklang['no_title_case']; ?></option>
</select>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<input type="hidden" name="a" value="update">
<input type="hidden" name="status-id" value="<?php echo $statusId; ?>">
<div class="btn-group">
<input type="submit" class="btn btn-success"
value="<?php echo $hesklang['save_changes']; ?>">
<button type="button" class="btn btn-default"
data-dismiss="modal"><?php echo $hesklang['close_modal_without_saving']; ?></button>
</div>
</div>
</form>
</div>
</div>
</div>
<?php
}
function canStatusBeDeleted($id)
{
global $hesk_settings;
$defaultActionSql = "SELECT 1 FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` WHERE `ID` = " . intval($id) . " AND
(`IsNewTicketStatus` = 1 OR `IsClosedByClient` = 1 OR `IsCustomerReplyStatus` = 1 OR `IsStaffClosedOption` = 1
OR `IsStaffReopenedStatus` = 1 OR `IsDefaultStaffReplyStatus` = 1 OR `LockedTicketStatus` = 1 OR `IsAutocloseOption` = 1)";
$defaultActionRs = hesk_dbQuery($defaultActionSql);
if (hesk_dbNumRows($defaultActionRs) > 0) {
// it's a default action
return 'no-default';
}
// check if any tickets have this status
$statusRs = hesk_dbQuery("SELECT 1 FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `status` = " . intval($id));
if (hesk_dbNumRows($statusRs) > 0) {
return 'no-tickets';
}
return 'yes';
}
function echoWarningForStatus()
{
global $hesklang;
echo '<i class="fa fa-exclamation-triangle" data-toggle="tooltip" title="' . htmlspecialchars($hesklang['status_not_in_database']) . '"></i> ';
}
function createStatus()
{
global $hesklang, $hesk_settings;
hesk_dbConnect();
// Create the new status record
$isClosed = hesk_POST('closed');
$closable = hesk_POST('closable');
$textColor = hesk_POST('text-color');
/* Get the latest cat_order */
$res = hesk_dbQuery("SELECT `sort` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` ORDER BY `sort` DESC LIMIT 1");
$row = hesk_dbFetchRow($res);
$my_order = $row[0] + 10;
// Get the next status id
$res = hesk_dbQuery("SELECT `ID` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` ORDER BY `ID` DESC LIMIT 1");
$row = hesk_dbFetchAssoc($res);
$nextId = $row['ID'] + 1;
$insert = "INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` (`ID`, `Key`, `TextColor`, `IsClosed`, `Closable`, `sort`)
VALUES (" . intval($nextId) . ", 'STORED IN XREF TABLE', '" . hesk_dbEscape($textColor) . "', " . intval($isClosed) . ", '" . hesk_dbEscape($closable) . "', " . intval($my_order) . ")";
hesk_dbQuery($insert);
// For each language, create a value in the xref table
foreach (hesk_POST_array('name') as $language => $translation) {
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "text_to_status_xref` (`language`, `text`, `status_id`)
VALUES ('" . hesk_dbEscape($language) . "', '" . hesk_dbEscape($translation) . "', " . intval($nextId) . ")");
}
hesk_process_messages($hesklang['new_status_created'], 'manage_statuses.php', 'SUCCESS');
}
function updateStatus()
{
global $hesklang, $hesk_settings;
$statusId = hesk_POST('status-id');
$isClosed = hesk_POST('closed');
$closable = hesk_POST('closable');
$textColor = hesk_POST('text-color');
$update = "UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses`
SET `TextColor` = '" . hesk_dbEscape($textColor) . "',
`IsClosed` = " . intval($isClosed) . ",
`Closable` = '" . hesk_dbEscape($closable) . "'
WHERE `ID` = " . intval($statusId);
hesk_dbQuery($update);
// For each language, delete the xref record and insert the new ones
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "text_to_status_xref` WHERE `status_id` = " . intval($statusId));
foreach (hesk_POST_array('name') as $language => $translation) {
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "text_to_status_xref` (`language`, `text`, `status_id`)
VALUES ('" . hesk_dbEscape($language) . "', '" . hesk_dbEscape($translation) . "', " . intval($statusId) . ")");
}
hesk_process_messages($hesklang['ticket_status_updated'], 'manage_statuses.php', 'SUCCESS');
}
function deleteStatus()
{
global $hesklang, $hesk_settings;
$statusId = hesk_GET('id');
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "text_to_status_xref` WHERE `status_id` = " . intval($statusId));
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` WHERE `ID` = " . intval($statusId));
resortStatuses();
hesk_process_messages($hesklang['ticket_status_deleted'], 'manage_statuses.php', 'SUCCESS');
}
function moveStatus()
{
global $hesk_settings, $hesklang;
$statusId = intval(hesk_GET('id'));
$statusMove = intval(hesk_GET('move'));
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` SET `sort` = `sort`+" . intval($statusMove) . "
WHERE `ID` = '" . intval($statusId) . "' LIMIT 1");
resortStatuses();
hesk_process_messages($hesklang['status_sort_updated'], 'manage_statuses.php', 'SUCCESS');
}
function resortStatuses()
{
global $hesk_settings;
/* Update all category fields with new order */
$res = hesk_dbQuery("SELECT `ID` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` ORDER BY `sort` ASC");
$i = 10;
while ($myStatus = hesk_dbFetchAssoc($res)) {
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` SET `sort`=" . intval($i) . "
WHERE `ID`='" . intval($myStatus['ID']) . "' LIMIT 1");
$i += 10;
}
}
function save()
{
global $hesklang, $hesk_settings;
//-- Update default status for actions
$defaultQuery = "UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` SET ";
hesk_dbQuery($defaultQuery . "`IsNewTicketStatus` = 0");
$updateQuery = $defaultQuery . "`IsNewTicketStatus` = 1 WHERE `ID` = " . intval($_POST['newTicket']);
hesk_dbQuery($updateQuery);
hesk_dbQuery($defaultQuery . "`IsClosedByClient` = 0");
$updateQuery = $defaultQuery . "`IsClosedByClient` = 1 WHERE `ID` = " . intval($_POST['closedByClient']);
hesk_dbQuery($updateQuery);
hesk_dbQuery($defaultQuery . "`IsCustomerReplyStatus` = 0");
$updateQuery = $defaultQuery . "`IsCustomerReplyStatus` = 1 WHERE `ID` = " . intval($_POST['replyFromClient']);
hesk_dbQuery($updateQuery);
hesk_dbQuery($defaultQuery . "`IsStaffClosedOption` = 0");
$updateQuery = $defaultQuery . "`IsStaffClosedOption` = 1 WHERE `ID` = " . intval($_POST['staffClosedOption']);
hesk_dbQuery($updateQuery);
hesk_dbQuery($defaultQuery . "`IsStaffReopenedStatus` = 0");
$updateQuery = $defaultQuery . "`IsStaffReopenedStatus` = 1 WHERE `ID` = " . intval($_POST['staffReopenedStatus']);
hesk_dbQuery($updateQuery);
hesk_dbQuery($defaultQuery . "`IsDefaultStaffReplyStatus` = 0");
$updateQuery = $defaultQuery . "`IsDefaultStaffReplyStatus` = 1 WHERE `ID` = " . intval($_POST['defaultStaffReplyStatus']);
hesk_dbQuery($updateQuery);
hesk_dbQuery($defaultQuery . "`LockedTicketStatus` = 0");
$updateQuery = $defaultQuery . "`LockedTicketStatus` = 1 WHERE `ID` = " . intval($_POST['lockedTicketStatus']);
hesk_dbQuery($updateQuery);
hesk_dbQuery($defaultQuery . "`IsAutocloseOption` = 0");
$updateQuery = $defaultQuery . "`IsAutocloseOption` = 1 WHERE `ID` = " . intval($_POST['autocloseTicketOption']);
hesk_dbQuery($updateQuery);
hesk_process_messages($hesklang['default_statuses_updated'], 'manage_statuses.php', 'SUCCESS');
}

View File

@ -0,0 +1,488 @@
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
define('VALIDATOR', 1);
define('PAGE_TITLE', 'ADMIN_TICKET_TPL');
define('MFH_PAGE_LAYOUT', 'TOP_ONLY');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/mail_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
$modsForHesk_settings = mfh_getSettings();
/* Check permissions for this feature */
hesk_checkPermission('can_man_ticket_tpl');
// Define required constants
define('LOAD_TABS', 1);
if ($modsForHesk_settings['rich_text_for_tickets']) {
define('WYSIWYG', 1);
}
/* What should we do? */
if ($action = hesk_REQUEST('a')) {
if (defined('HESK_DEMO')) {
hesk_process_messages($hesklang['ddemo'], 'manage_ticket_templates.php', 'NOTICE');
} elseif ($action == 'new') {
new_saved();
} elseif ($action == 'edit') {
edit_saved();
} elseif ($action == 'remove') {
remove();
} elseif ($action == 'order') {
order_saved();
}
}
/* Print header */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
/* Print main manage users page */
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
<script language="javascript" type="text/javascript"><!--
function confirm_delete() {
if (confirm('<?php echo hesk_makeJsString($hesklang['delete_tpl']); ?>')) {
return true;
}
else {
return false;
}
}
//-->
</script>
<?php
// Get canned responses from database
$result = hesk_dbQuery('SELECT * FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'ticket_templates` ORDER BY `tpl_order` ASC');
$options = '';
$javascript_messages = '';
$javascript_titles = '';
$i = 1;
$j = 0;
$num = hesk_dbNumRows($result);
?>
<div class="content-wrapper">
<section class="content">
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['saved_ticket_tpl']; ?>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<?php if ($num < 1) {
echo '<p>' . $hesklang['no_ticket_tpl'] . '</p>';
} else {
?>
<table class="table table-hover">
<thead>
<tr>
<th><?php echo $hesklang['ticket_tpl_title']; ?></th>
<th><?php echo $hesklang['opt']; ?></th>
</tr>
</thead>
<tbody>
<?php
while ($mysaved = hesk_dbFetchAssoc($result)) {
$j++;
$color = '';
if (isset($_SESSION['canned']['selcat2']) && $mysaved['id'] == $_SESSION['canned']['selcat2']) {
$color = 'success';
unset($_SESSION['canned']['selcat2']);
}
$options .= '<option class="form-control" value="' . $mysaved['id'] . '"';
$options .= (isset($_SESSION['canned']['id']) && $_SESSION['canned']['id'] == $mysaved['id']) ? ' selected="selected" ' : '';
$options .= '>' . $mysaved['title'] . '</option>';
if ($modsForHesk_settings['rich_text_for_tickets']) {
$theMessage = html_entity_decode($mysaved['message']);
$theMessage = addslashes($theMessage);
$javascript_messages .= 'myMsgTxt[' . $mysaved['id'] . ']=\'' . str_replace("\r\n", "\\r\\n' + \r\n'", $theMessage) . "';\n";
} else {
$javascript_messages .= 'myMsgTxt[' . $mysaved['id'] . ']=\'' . str_replace("\r\n", "\\r\\n' + \r\n'", addslashes($mysaved['message'])) . "';\n";
}
$javascript_titles .= 'myTitle[' . $mysaved['id'] . ']=\'' . addslashes($mysaved['title']) . "';\n";
echo '
<tr>
<td>' . $mysaved['title'] . '</td>
<td class="text-left">
';
if ($num > 1) {
if ($j == 1) {
echo '<img src="../img/blank.gif" width="16" height="16" alt="" style="padding:3px;border:none;" />
<a href="manage_ticket_templates.php?a=order&amp;replyid=' . $mysaved['id'] . '&amp;move=15&amp;token=' . hesk_token_echo(0) . '">
<i class="fa fa-arrow-down icon-link green" data-toggle="tooltip" data-placement="top" data-original-title="' . $hesklang['move_dn'] . '"></i></a>';
} elseif ($j == $num) {
echo '<a href="manage_ticket_templates.php?a=order&amp;replyid=' . $mysaved['id'] . '&amp;move=-15&amp;token=' . hesk_token_echo(0) . '"><i class="fa fa-arrow-up icon-link green" data-toggle="tooltip" data-placement="top" data-original-title="' . $hesklang['move_up'] . '"></i></a> <img src="../img/blank.gif" width="16" height="16" alt="" style="padding:3px;border:none;" />';
} else {
echo '
<a href="manage_ticket_templates.php?a=order&amp;replyid=' . $mysaved['id'] . '&amp;move=-15&amp;token=' . hesk_token_echo(0) . '"><i class="fa fa-arrow-up icon-link green" data-toggle="tooltip" data-placement="top" data-original-title="' . $hesklang['move_up'] . '"></i></a>
<a href="manage_ticket_templates.php?a=order&amp;replyid=' . $mysaved['id'] . '&amp;move=15&amp;token=' . hesk_token_echo(0) . '"><i class="fa fa-arrow-down icon-link green" data-toggle="tooltip" data-placement="top" data-original-title="' . $hesklang['move_dn'] . '"></i></a>
';
}
} else {
echo '';
}
echo '
<a name="'.$mysaved['title'].'" href="manage_ticket_templates.php?a=remove&amp;id=' . $mysaved['id'] . '&amp;token=' . hesk_token_echo(0) . '" onclick="return confirm_delete();"><i class="fa fa-times icon-link red" data-toggle="tooltip" data-placement="top" data-original-title="' . $hesklang['delete'] . '"></i></a></td>
</tr>
';
} // End while
?>
</tbody>
</table>
<?php
}
?>
</div>
</div>
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['new_ticket_tpl']; ?>
<a href="javascript:void(0)"
onclick="javascript:alert('<?php echo hesk_makeJsString($hesklang['ticket_tpl_intro']); ?>')"><i
class="fa fa-question-circle settingsquestionmark"></i></a>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<?php
/* This will handle error, success and notice messages */
hesk_handle_messages();
$onsubmit = '';
if ($modsForHesk_settings['rich_text_for_tickets']) {
$onsubmit = 'onsubmit="return validateRichText(\'message-help-block\', \'message-group\', \'message\', \''.htmlspecialchars($hesklang['this_field_is_required']).'\')"';
}
?>
<form class="form-horizontal" action="manage_ticket_templates.php" method="post" name="form1" role="form" data-toggle="validator" <?php echo $onsubmit; ?>>
<?php
if ($num > 0) {
?>
<div class="form-group">
<div class="col-sm-12">
<div class="row">
<div class="col-sm-12">
<div class="radio">
<label>
<input type="radio" name="a"
value="new" <?php echo (!isset($_SESSION['canned']['what']) || $_SESSION['canned']['what'] != 'EDIT') ? 'checked=' : ''; ?>>
<?php echo $hesklang['ticket_tpl_add']; ?>
</label>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="radio">
<label>
<input type="radio" name="a"
value="edit" <?php echo (isset($_SESSION['canned']['what']) && $_SESSION['canned']['what'] == 'EDIT') ? 'checked' : ''; ?>>
<?php echo $hesklang['ticket_tpl_edit']; ?>
</label>
</div>
</div>
<div class="col-sm-6">
<select class="form-control" name="saved_replies" onchange="setMessage(this.value)">
<option value="0"> - <?php echo $hesklang['select_empty']; ?>-
</option><?php echo $options; ?></select>
</div>
</div>
</div>
</div>
<?php
} else {
echo '<p><input type="hidden" name="a" value="new" /> ' . $hesklang['ticket_tpl_add'] . '</label></p>';
}
?>
<div class="form-group">
<label for="name" class="col-sm-2 control-label"><?php echo $hesklang['ticket_tpl_title']; ?></label>
<div class="col-sm-10">
<span id="HeskTitle">
<input id="subject" class="form-control" type="text" name="name" size="40" maxlength="50"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
placeholder="<?php echo htmlspecialchars($hesklang['ticket_tpl_title']); ?>"
<?php if (isset($_SESSION['canned']['name'])) {
echo ' value="' . stripslashes($_SESSION['canned']['name']) . '" ';
} ?> required>
</span>
<div class="help-block with-errors"></div>
</div>
</div>
<div class="form-group" id="message-group">
<label for="msg" class="col-sm-2 control-label"><?php echo $hesklang['message']; ?></label>
<div class="col-sm-10">
<span id="HeskMsg">
<textarea id="message" class="form-control htmlEditor"
data-error="<?php echo htmlspecialchars($hesklang['this_field_is_required']); ?>"
placeholder="<?php echo htmlspecialchars($hesklang['message']); ?>" name="msg"
rows="15" cols="70" required><?php
if (isset($_SESSION['canned']['msg'])) {
if ($modsForHesk_settings['rich_text_for_tickets']) {
echo $_SESSION['canned']['msg'];
} else {
echo stripslashes($_SESSION['canned']['msg']);
}
}
?></textarea>
</span>
<div class="help-block with-errors" id="message-help-block"></div>
</div>
</div>
<div class="form-group">
<div class="col-sm-10 col-sm-offset-2">
<input type="hidden" name="token" value="<?php hesk_token_echo(); ?>"/>
<input type="submit" value="<?php echo $hesklang['save_ticket_tpl']; ?>" class="btn btn-default">
</div>
</div>
</form>
</div>
</div>
</section>
</div>
<?php if ($modsForHesk_settings['rich_text_for_tickets']): ?>
<script type="text/javascript">
/* <![CDATA[ */
$(document).ready(function() {
$('.htmlEditor').summernote({
height: 200,
toolbar: [
['style', ['bold', 'italic', 'underline', 'clear']],
['font', ['strikethrough', 'superscript', 'subscript']],
['para', ['ul', 'ol']]
]
});
});
/* ]]> */
</script>
<?php endif; ?>
<script language="javascript" type="text/javascript"><!--
// -->
var myMsgTxt = new Array();
var myTitle = new Array();
myMsgTxt[0] = '';
myTitle[0] = '';
<?php
echo $javascript_titles;
echo $javascript_messages;
?>
function setMessage(msgid) {
var useHtmlEditor = <?php echo $modsForHesk_settings['rich_text_for_tickets']; ?>;
var myMsg = myMsgTxt[msgid];
var mySubject = myTitle[msgid];
if (myMsg == '') {
if (useHtmlEditor) {
$("#message").summernote('reset');
}
else {
$('#message').val('');
}
$('#subject').val('');
return true;
}
if (document.getElementById) {
if (useHtmlEditor) {
$("#message").summernote('reset');
$("#message").summernote('editor.insertText', myMsg));
} else {
myMsg = $('<textarea />').html(myMsg).text();
$('#message').val(myMsg).trigger('input');
}
mySubject = $('<textarea />').html(mySubject).text();
$('#subject').val(mySubject).trigger('input');
}
else {
document.form1.message.value = myMsg;
document.form1.subject.value = mySubject;
}
if (msgid == 0) {
document.form1.a[0].checked = true;
} else {
document.form1.a[1].checked = true;
}
}
//-->
</script>
<?php
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();
/*** START FUNCTIONS ***/
function edit_saved()
{
global $hesk_settings, $hesklang;
/* A security check */
hesk_token_check('POST');
$hesk_error_buffer = '';
$id = intval(hesk_POST('saved_replies')) or $hesk_error_buffer .= '<li>' . $hesklang['sel_ticket_tpl'] . '</li>';
$savename = hesk_input(hesk_POST('name')) or $hesk_error_buffer .= '<li>' . $hesklang['ent_ticket_tpl_title'] . '</li>';
$msg = hesk_input(hesk_POST('msg')) or $hesk_error_buffer .= '<li>' . $hesklang['ent_ticket_tpl_msg'] . '</li>';
// Avoid problems with utf-8 newline chars in Javascript code, detect and remove them
$msg = preg_replace('/\R/u', "\r\n", $msg);
$_SESSION['canned']['what'] = 'EDIT';
$_SESSION['canned']['id'] = $id;
$_SESSION['canned']['name'] = $savename;
$_SESSION['canned']['msg'] = $msg;
/* Any errors? */
if (strlen($hesk_error_buffer)) {
$hesk_error_buffer = $hesklang['rfm'] . '<br /><br /><ul>' . $hesk_error_buffer . '</ul>';
hesk_process_messages($hesk_error_buffer, 'manage_ticket_templates.php?saved_replies=' . $id);
}
$result = hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "ticket_templates` SET `title`='" . hesk_dbEscape($savename) . "',`message`='" . hesk_dbEscape($msg) . "' WHERE `id`='" . intval($id) . "'");
unset($_SESSION['canned']['what']);
unset($_SESSION['canned']['id']);
unset($_SESSION['canned']['name']);
unset($_SESSION['canned']['msg']);
hesk_process_messages($hesklang['ticket_tpl_saved'], 'manage_ticket_templates.php?saved_replies=' . $id, 'SUCCESS');
} // End edit_saved()
function new_saved()
{
global $hesk_settings, $hesklang;
/* A security check */
hesk_token_check('POST');
$hesk_error_buffer = '';
$savename = hesk_input(hesk_POST('name')) or $hesk_error_buffer .= '<li>' . $hesklang['ent_ticket_tpl_title'] . '</li>';
$msg = hesk_input(hesk_POST('msg')) or $hesk_error_buffer .= '<li>' . $hesklang['ent_ticket_tpl_msg'] . '</li>';
// Avoid problems with utf-8 newline chars in Javascript code, detect and remove them
$msg = preg_replace('/\R/u', "\r\n", $msg);
$_SESSION['canned']['what'] = 'NEW';
$_SESSION['canned']['name'] = $savename;
$_SESSION['canned']['msg'] = $msg;
/* Any errors? */
if (strlen($hesk_error_buffer)) {
$hesk_error_buffer = $hesklang['rfm'] . '<br /><br /><ul>' . $hesk_error_buffer . '</ul>';
hesk_process_messages($hesk_error_buffer, 'manage_ticket_templates.php');
}
/* Get the latest tpl_order */
$result = hesk_dbQuery('SELECT `tpl_order` FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'ticket_templates` ORDER BY `tpl_order` DESC LIMIT 1');
$row = hesk_dbFetchRow($result);
$my_order = $row[0] + 10;
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "ticket_templates` (`title`,`message`,`tpl_order`) VALUES ('" . hesk_dbEscape($savename) . "','" . hesk_dbEscape($msg) . "','" . intval($my_order) . "')");
unset($_SESSION['canned']['what']);
unset($_SESSION['canned']['name']);
unset($_SESSION['canned']['msg']);
hesk_process_messages($hesklang['ticket_tpl_saved'], 'manage_ticket_templates.php', 'SUCCESS');
} // End new_saved()
function remove()
{
global $hesk_settings, $hesklang;
/* A security check */
hesk_token_check();
$mysaved = intval(hesk_GET('id')) or hesk_error($hesklang['id_not_valid']);
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "ticket_templates` WHERE `id`='" . intval($mysaved) . "'");
if (hesk_dbAffectedRows() != 1) {
hesk_error("$hesklang[int_error]: $hesklang[ticket_tpl_not_found].");
}
hesk_process_messages($hesklang['ticket_tpl_removed'], 'manage_ticket_templates.php', 'SUCCESS');
} // End remove()
function order_saved()
{
global $hesk_settings, $hesklang;
/* A security check */
hesk_token_check();
$tplid = intval(hesk_GET('replyid')) or hesk_error($hesklang['ticket_tpl_id']);
$_SESSION['canned']['selcat2'] = $tplid;
$tpl_move = intval(hesk_GET('move'));
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "ticket_templates` SET `tpl_order`=`tpl_order`+" . intval($tpl_move) . " WHERE `id`='" . intval($tplid) . "'");
if (hesk_dbAffectedRows() != 1) {
hesk_error("$hesklang[int_error]: $hesklang[ticket_tpl_not_found].");
}
/* Update all category fields with new order */
$result = hesk_dbQuery('SELECT `id` FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'ticket_templates` ORDER BY `tpl_order` ASC');
$i = 10;
while ($mytpl = hesk_dbFetchAssoc($result)) {
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "ticket_templates` SET `tpl_order`=" . intval($i) . " WHERE `id`='" . intval($mytpl['id']) . "'");
$i += 10;
}
header('Location: manage_ticket_templates.php');
exit();
} // End order_saved()
?>

File diff suppressed because it is too large Load Diff

177
admin/move_category.php Executable file
View File

@ -0,0 +1,177 @@
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
hesk_load_database_functions();
require(HESK_PATH . 'inc/email_functions.inc.php');
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
$modsForHesk_settings = mfh_getSettings();
/* Check permissions for this feature */
if (hesk_checkPermission('can_change_cat', 0)) {
hesk_checkPermission('can_change_own_cat');
}
/* A security check */
hesk_token_check('POST');
/* Ticket ID */
$trackingID = hesk_cleanID() or die($hesklang['int_error'] . ': ' . $hesklang['no_trackID']);
/* Category ID */
$category = intval(hesk_POST('category', -1));
if ($category < 1) {
hesk_process_messages($hesklang['incat'], 'admin_ticket.php?track=' . $trackingID . '&Refresh=' . rand(10000, 99999), 'NOTICE');
}
/* Get new category details */
$res = hesk_dbQuery("SELECT `name`,`autoassign` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "categories` WHERE `id`='{$category}' LIMIT 1");
if (hesk_dbNumRows($res) != 1) {
hesk_error("$hesklang[int_error]: $hesklang[kb_cat_inv].");
}
$row = hesk_dbFetchAssoc($res);
/* Should tickets in new category be auto-assigned if necessary? */
if (!$row['autoassign']) {
$hesk_settings['autoassign'] = false;
}
/* Is user allowed to view tickets in new category? */
$category_ok = hesk_okCategory($category, 0);
// Is user allowed to move tickets to this category?
if ( ! $category_ok && ! hesk_checkPermission('can_change_cat', 0) ) {
hesk_process_messages($hesklang['noauth_move'],'admin_main.php');
}
/* Get details about the original ticket */
$res = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `trackid`='" . hesk_dbEscape($trackingID) . "' LIMIT 1");
if (hesk_dbNumRows($res) != 1) {
hesk_error($hesklang['ticket_not_found']);
}
$ticket = hesk_dbFetchAssoc($res);
/* Is the ticket assigned to someone? If yes, check that the user has access to category or change to unassigned */
$need_to_reassign = 0;
if ($ticket['owner']) {
if ($ticket['owner'] == $_SESSION['id'] && !$category_ok) {
$need_to_reassign = 1;
} else {
$res = hesk_dbQuery("SELECT `isadmin`,`categories` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `id`='" . intval($ticket['owner']) . "' LIMIT 1");
if (hesk_dbNumRows($res) != 1) {
$need_to_reassign = 1;
} else {
$tmp = hesk_dbFetchAssoc($res);
if (!hesk_okCategory($category, 0, $tmp['isadmin'], explode(',', $tmp['categories']))) {
$need_to_reassign = 1;
}
}
}
}
/* Reassign automatically if possible */
$autoassign_owner = null;
if ($need_to_reassign || !$ticket['owner']) {
$need_to_reassign = 1;
$autoassign_owner = hesk_autoAssignTicket($category);
if ($autoassign_owner) {
$ticket['owner'] = $autoassign_owner['id'];
} else {
$ticket['owner'] = 0;
}
}
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `category`='" . intval($category) . "', `owner`='" . intval($ticket['owner']) . "' WHERE `trackid`='" . hesk_dbEscape($trackingID) . "'");
/* Log that ticket is being moved */
mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_moved_category', hesk_date(), array(
0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')',
1 => $row['name']
));
if ($autoassign_owner) {
mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_autoassigned', hesk_date(), array(
0 => $autoassign_owner['name'] . ' (' . $autoassign_owner['user'] . ')'
));
}
$ticket['category'] = $category;
/* --> 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);
/* Need to notify any staff? */
/* --> From autoassign? */
if ($need_to_reassign && !empty($autoassign_owner['email'])) {
hesk_notifyAssignedStaff($autoassign_owner, 'ticket_assigned_to_you', $modsForHesk_settings);
} /* --> No autoassign, find and notify appropriate staff */
elseif (!$ticket['owner']) {
hesk_notifyStaff('category_moved', "`notify_new_unassigned`='1' AND `id`!=" . intval($_SESSION['id']), $modsForHesk_settings);
}
/* Is the user allowed to view tickets in the new category? */
if ($category_ok) {
/* Ticket has an owner */
if ($ticket['owner']) {
/* Staff is owner or can view tickets assigned to others */
if ($ticket['owner'] == $_SESSION['id'] || hesk_checkPermission('can_view_ass_others', 0)) {
hesk_process_messages($hesklang['moved_to'], 'admin_ticket.php?track=' . $trackingID . '&Refresh=' . rand(10000, 99999), 'SUCCESS');
} else {
hesk_process_messages($hesklang['moved_to'], 'admin_main.php', 'SUCCESS');
}
} /* Ticket is unassigned, staff can view unassigned tickets */
elseif (hesk_checkPermission('can_view_unassigned', 0)) {
hesk_process_messages($hesklang['moved_to'], 'admin_ticket.php?track=' . $trackingID . '&Refresh=' . rand(10000, 99999), 'SUCCESS');
} /* Ticket is unassigned, staff cannot view unassigned tickets */
else {
hesk_process_messages($hesklang['moved_to'], 'admin_main.php', 'SUCCESS');
}
} else {
hesk_process_messages($hesklang['moved_to'], 'admin_main.php', 'SUCCESS');
}
?>

File diff suppressed because it is too large Load Diff

290
admin/password.php Normal file
View File

@ -0,0 +1,290 @@
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
define('PAGE_TITLE', 'LOGIN');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
// Connect to database and check for brute force attempts
hesk_load_database_functions();
hesk_dbConnect();
$modsForHesk_settings = mfh_getSettings();
// Is the password reset function enabled?
if (!$hesk_settings['reset_pass']) {
die($hesklang['attempt']);
}
// Allow additional 5 attempts in case the user is already blocked
$hesk_settings['attempt_limit'] += 5;
// Start session
hesk_session_start();
if (!isset($_SESSION['a_iserror'])) {
$_SESSION['a_iserror'] = array();
}
$hesk_error_buffer = array();
// If this is a POST method, check input
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// Verify security image
if ($hesk_settings['secimg_use']) {
// Using ReCaptcha?
if ($hesk_settings['recaptcha_use']) {
require(HESK_PATH . 'inc/recaptcha/recaptchalib_v2.php');
$resp = null;
$reCaptcha = new ReCaptcha($hesk_settings['recaptcha_private_key']);
// Was there a reCAPTCHA response?
if (isset($_POST["g-recaptcha-response"])) {
$resp = $reCaptcha->verifyResponse(hesk_getClientIP(), hesk_POST("g-recaptcha-response"));
}
if ($resp != null && $resp->success) {
//$_SESSION['img_a_verified']=true;
} else {
$hesk_error_buffer['mysecnum'] = $hesklang['recaptcha_error'];
}
} // Using PHP generated image
else {
$mysecnum = intval(hesk_POST('mysecnum', 0));
if (empty($mysecnum)) {
$hesk_error_buffer['mysecnum'] = $hesklang['sec_miss'];
} else {
require(HESK_PATH . 'inc/secimg.inc.php');
$sc = new PJ_SecurityImage($hesk_settings['secimg_sum']);
if (isset($_SESSION['checksum']) && $sc->checkCode($mysecnum, $_SESSION['checksum'])) {
//$_SESSION['img_a_verified'] = true;
} else {
$hesk_error_buffer['mysecnum'] = $hesklang['sec_wrng'];
}
}
}
}
hesk_limitBfAttempts();
// Get email
$email = hesk_validateEmail(hesk_POST('email'), 'ERR', 0) or $hesk_error_buffer['email'] = $hesklang['enter_valid_email'];
// Any errors?
if (count($hesk_error_buffer) != 0) {
$_SESSION['a_iserror'] = array_keys($hesk_error_buffer);
$tmp = '';
foreach ($hesk_error_buffer as $error) {
$tmp .= "<li>$error</li>\n";
}
$hesk_error_buffer = $tmp;
$hesk_error_buffer = $hesklang['pcer'] . '<br /><br /><ul>' . $hesk_error_buffer . '</ul>';
hesk_process_messages($hesk_error_buffer, 'NOREDIRECT');
} elseif (defined('HESK_DEMO')) {
hesk_process_messages($hesklang['ddemo'], 'NOREDIRECT');
} else {
// Get user data from the database
$res = hesk_dbQuery("SELECT `id`, `name`, `pass` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `email` LIKE '" . hesk_dbEscape($email) . "' LIMIT 1");
if (hesk_dbNumRows($res) != 1) {
hesk_process_messages($hesklang['noace'], 'NOREDIRECT');
} else {
$row = hesk_dbFetchAssoc($res);
$hash = sha1(microtime() . hesk_getClientIP() . mt_rand() . $row['id'] . $row['name'] . $row['pass']);
// Insert the verification hash into the database
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "reset_password` (`user`, `hash`, `ip`) VALUES (" . intval($row['id']) . ", '{$hash}', '" . hesk_dbEscape($_SERVER['REMOTE_ADDR']) . "') ");
// Prepare and send email
require(HESK_PATH . 'inc/email_functions.inc.php');
// Get the email message
$msg = hesk_getEmailMessage('reset_password', array(), $modsForHesk_settings, 1, 0, 1);
$htmlMsg = hesk_getHtmlMessage('reset_password', array(), $modsForHesk_settings, 1, 0, 1);
// Replace message special tags
$msg = str_replace('%%NAME%%', hesk_msgToPlain($row['name'], 1, 1), $msg);
$msg = str_replace('%%SITE_URL%%', $hesk_settings['site_url'], $msg);
$msg = str_replace('%%SITE_TITLE%%', $hesk_settings['site_title'], $msg);
$msg = str_replace('%%PASSWORD_RESET%%', $hesk_settings['hesk_url'] . '/' . $hesk_settings['admin_dir'] . '/password.php?h=' . $hash, $msg);
$htmlMsg = str_replace('%%NAME%%', hesk_msgToPlain($row['name'], 1, 1), $htmlMsg);
$htmlMsg = str_replace('%%SITE_URL%%', $hesk_settings['site_url'], $htmlMsg);
$htmlMsg = str_replace('%%SITE_TITLE%%', $hesk_settings['site_title'], $htmlMsg);
$htmlMsg = str_replace('%%PASSWORD_RESET%%', $hesk_settings['hesk_url'] . '/' . $hesk_settings['admin_dir'] . '/password.php?h=' . $hash, $htmlMsg);
// Send email
hesk_mail($email, $hesklang['reset_password'], $msg, $htmlMsg, $modsForHesk_settings);
// Show success
hesk_process_messages($hesklang['pemls'], 'NOREDIRECT', 'SUCCESS');
}
}
} // If the "h" parameter is set verify it and reset the password
elseif (isset($_GET['h'])) {
// Get the hash
$hash = preg_replace('/[^a-zA-Z0-9]/', '', $_GET['h']);
// Connect to database
hesk_dbConnect();
// Expire verification hashes older than 2 hours
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "reset_password` WHERE `dt` < (NOW() - INTERVAL 2 HOUR)");
// Verify the hash exists
$res = hesk_dbQuery("SELECT `user`, `ip` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "reset_password` WHERE `hash` = '{$hash}' LIMIT 1");
if (hesk_dbNumRows($res) != 1) {
// Not a valid hash
hesk_limitBfAttempts();
hesk_process_messages($hesklang['ehash'], 'NOREDIRECT');
} else {
// Get info from database
$row = hesk_dbFetchAssoc($res);
// Only allow resetting password from the same IP address that submitted password reset request
if ($row['ip'] != $_SERVER['REMOTE_ADDR']) {
hesk_limitBfAttempts();
hesk_process_messages($hesklang['ehaip'], 'NOREDIRECT');
} else {
// Expire all verification hashes for this user
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "reset_password` WHERE `user`=" . intval($row['user']));
// Load additional required functions
require(HESK_PATH . 'inc/admin_functions.inc.php');
// Get user details
$res = hesk_dbQuery('SELECT * FROM `' . $hesk_settings['db_pfix'] . "users` WHERE `id`=" . intval($row['user']) . " LIMIT 1");
$row = hesk_dbFetchAssoc($res);
foreach ($row as $k => $v) {
$_SESSION[$k] = $v;
}
// Set a tag that will be used to expire sessions after username or password change
$_SESSION['session_verify'] = hesk_activeSessionCreateTag($_SESSION['user'], $_SESSION['pass']);
// We don't need the password hash anymore
unset($_SESSION['pass']);
// Clean brute force attempts
hesk_cleanBfAttempts();
// Regenerate session ID (security)
hesk_session_regenerate_id();
// Get allowed categories
if (empty($_SESSION['isadmin'])) {
$_SESSION['categories'] = explode(',', $_SESSION['categories']);
}
// Redirect to the profile page
hesk_process_messages($hesklang['resim'], 'profile.php', 'NOTICE');
exit();
} // End IP matches
}
}
// Tell header to load reCaptcha API if needed
if ($hesk_settings['recaptcha_use']) {
define('RECAPTCHA', 1);
}
$hesk_settings['tmp_title'] = $hesk_settings['hesk_title'] . ' - ' . $hesklang['passr'];
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
?>
<div class="login-box">
<div class="login-logo">
<?php echo $hesk_settings['hesk_title']; ?>
</div>
<div class="login-box-body">
<h4 class="login-box-msg">
<?php echo $hesklang['passr']; ?>
</h4>
<form action="password.php" method="post" name="form1" id="form1" class="form-horizontal" role="form">
<?php
/* This will handle error, success and notice messages */
hesk_handle_messages();
$has_error = '';
if (in_array('email', $_SESSION['a_iserror'])) {
$has_error = 'has-error';
}
$form_email = '';
if (isset($email)) {
$form_email = stripslashes(hesk_input($email));
}
?>
<div class="form-group <?php echo $has_error; ?>">
<label for="email" class="col-sm-3 control-label">
<?php echo $hesklang['email']; ?>
</label>
<div class="col-sm-9">
<input type="text" name="email" size="35" value="<?php echo $form_email; ?>"
class="form-control" placeholder="<?php echo htmlspecialchars($hesklang['email']); ?>">
</div>
</div>
<?php
if ($hesk_settings['secimg_use'] && $hesk_settings['recaptcha_use'] != 1) {
?>
<div class="form-group">
<div class="col-sm-11 col-sm-offset-1">
<?php
// Use reCaptcha API v2?
if ($hesk_settings['recaptcha_use'] == 2)
{
?>
<div class="g-recaptcha"
data-sitekey="<?php echo $hesk_settings['recaptcha_public_key']; ?>"></div>
<?php
}
// At least use some basic PHP generated image (better than nothing)
else {
$cls = in_array('mysecnum', $_SESSION['a_iserror']) ? ' class="isError" ' : '';
echo $hesklang['sec_enter'] . '<br />&nbsp;<br /><img src="' . HESK_PATH . 'print_sec_img.php?' . rand(10000, 99999) . '" width="150" height="40" alt="' . $hesklang['sec_img'] . '" title="' . $hesklang['sec_img'] . '" border="1" name="secimg" style="vertical-align:text-bottom" /> ' .
'<a href="javascript:void(0)" onclick="javascript:document.form1.secimg.src=\'' . HESK_PATH . 'print_sec_img.php?\'+ ( Math.floor((90000)*Math.random()) + 10000);"><img src="' . HESK_PATH . 'img/reload.png" height="24" width="24" alt="' . $hesklang['reload'] . '" title="' . $hesklang['reload'] . '" border="0" style="vertical-align:text-bottom" /></a>' .
'<br />&nbsp;<br /><input type="text" name="mysecnum" size="20" maxlength="5" ' . $cls . ' />';
}
?>
</div>
</div>
<?php
}
?>
<div class="form-group">
<div class="col-sm-9 col-sm-offset-3">
<input type="submit" value="<?php echo $hesklang['passs']; ?>" class="btn btn-default">
</div>
</div>
<?php
// Use Invisible reCAPTCHA?
if ($hesk_settings['secimg_use'] && $hesk_settings['recaptcha_use'] == 1) {
?>
<div class="g-recaptcha" data-sitekey="<?php echo $hesk_settings['recaptcha_public_key']; ?>" data-bind="recaptcha-submit" data-callback="recaptcha_submitForm"></div>
<?php
}
?>
</form>
</div>
</div>
<?php
// Clean session errors
hesk_cleanSessionVars('a_iserror');
hesk_cleanSessionVars('img_a_verified');
?>

73
admin/priority.php Normal file
View File

@ -0,0 +1,73 @@
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
define('IN_SCRIPT',1);
define('HESK_PATH','../');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
/* Check permissions for this feature */
hesk_checkPermission('can_view_tickets');
hesk_checkPermission('can_reply_tickets');
/* A security check */
hesk_token_check('POST');
/* Ticket ID */
$trackingID = hesk_cleanID() or die($hesklang['int_error'].': '.$hesklang['no_trackID']);
$priority = intval( hesk_POST('priority') );
if ($priority < 0 || $priority > 3)
{
hesk_process_messages($hesklang['inpr'],'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999),'NOTICE');
}
$options = array(
0 => '<font class="critical">'.$hesklang['critical'].'</font>',
1 => '<font class="important">'.$hesklang['high'].'</font>',
2 => '<font class="medium">'.$hesklang['medium'].'</font>',
3 => $hesklang['low']
);
$plain_options = array(
0 => 'critical',
1 => 'high',
2 => 'medium',
3 => 'low'
);
$ticketRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `trackid` = '" . hesk_dbEscape($trackingID) . "'");
$ticket = hesk_dbFetchAssoc($ticketRs);
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `priority`='{$priority}' WHERE `trackid`='".hesk_dbEscape($trackingID)."'");
mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_priority', hesk_date(), array(
0 => $_SESSION['name'].' ('.$_SESSION['user'].')',
1 => $plain_options[$priority]
));
if (hesk_dbAffectedRows() != 1)
{
hesk_process_messages($hesklang['inpr'],'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999),'NOTICE');
}
hesk_process_messages(sprintf($hesklang['chpri2'],$options[$priority]),'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999),'SUCCESS');
?>

View File

@ -1,44 +1,27 @@
<?php
/*******************************************************************************
* Title: Help Desk Software HESK
* Version: 2.5.3 from 16th March 2014
* Author: Klemen Stirn
* Website: http://www.hesk.com
********************************************************************************
* COPYRIGHT AND TRADEMARK NOTICE
* Copyright 2005-2013 Klemen Stirn. All Rights Reserved.
* HESK is a registered trademark of Klemen Stirn.
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
* The HESK may be used and modified free of charge by anyone
* AS LONG AS COPYRIGHT NOTICES AND ALL THE COMMENTS REMAIN INTACT.
* By using this code you agree to indemnify Klemen Stirn from any
* liability that might arise from it's use.
* Selling the code for this program, in part or full, without prior
* written consent is expressly forbidden.
* Using this code, in part or full, to create derivate work,
* new scripts or products is expressly forbidden. Obtain permission
* before redistributing this software over the Internet or in
* any other medium. In all cases copyright and header must remain intact.
* This Copyright is in full effect in any country that has International
* Trade Agreements with the United States of America or
* with the European Union.
* Removing any of the copyright notices without purchasing a license
* is expressly forbidden. To remove HESK copyright notice you must purchase
* a license for this script. For more information on how to obtain
* a license please visit the page below:
* https://www.hesk.com/buy.php
*******************************************************************************/
define('IN_SCRIPT',1);
define('HESK_PATH','../');
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
define('PAGE_TITLE', 'ADMIN_PROFILE');
define('MFH_PAGE_LAYOUT', 'TOP_ONLY');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/profile_functions.inc.php');
require(HESK_PATH . 'inc/mail_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
@ -46,48 +29,38 @@ hesk_dbConnect();
hesk_isLoggedIn();
/* Check permissions */
$can_view_tickets = hesk_checkPermission('can_view_tickets',0);
$can_reply_tickets = hesk_checkPermission('can_reply_tickets',0);
$can_view_unassigned = hesk_checkPermission('can_view_unassigned',0);
$can_view_tickets = hesk_checkPermission('can_view_tickets', 0);
$can_reply_tickets = hesk_checkPermission('can_reply_tickets', 0);
$can_view_unassigned = hesk_checkPermission('can_view_unassigned', 0);
/* Update profile? */
if ( ! empty($_POST['action']))
{
// Demo mode
if ( defined('HESK_DEMO') )
{
hesk_process_messages($hesklang['sdemo'], 'profile.php', 'NOTICE');
}
if (!empty($_POST['action'])) {
// Demo mode
if (defined('HESK_DEMO')) {
hesk_process_messages($hesklang['sdemo'], 'profile.php', 'NOTICE');
}
// Update profile
update_profile();
}
else
{
$res = hesk_dbQuery('SELECT * FROM `'.hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id` = '".intval($_SESSION['id'])."' LIMIT 1");
$tmp = hesk_dbFetchAssoc($res);
// Update profile
update_profile();
} else {
$res = hesk_dbQuery('SELECT * FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `id` = '" . intval($_SESSION['id']) . "' LIMIT 1");
$tmp = hesk_dbFetchAssoc($res);
foreach ($tmp as $k=>$v)
{
if ($k == 'pass')
{
if ($v == '499d74967b28a841c98bb4baaabaad699ff3c079')
{
define('WARN_PASSWORD',true);
}
continue;
foreach ($tmp as $k => $v) {
if ($k == 'pass') {
if ($v == '499d74967b28a841c98bb4baaabaad699ff3c079') {
define('WARN_PASSWORD', true);
}
continue;
} elseif ($k == 'categories') {
continue;
}
elseif ($k == 'categories')
{
continue;
}
$_SESSION['new'][$k]=$v;
}
$_SESSION['new'][$k] = $v;
}
}
if ( ! isset($_SESSION['new']['username']))
{
$_SESSION['new']['username'] = '';
if (!isset($_SESSION['new']['username'])) {
$_SESSION['new']['username'] = '';
}
/* Print header */
@ -96,216 +69,81 @@ require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
/* Print admin navigation */
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
<div class="row">
<div class="col-md-8 col-md-offset-2" style="padding-top: 20px">
<?php
/* This will handle error, success and notice messages */
hesk_handle_messages();
if (defined('WARN_PASSWORD'))
{
hesk_show_notice($hesklang['chdp2'],$hesklang['security']);
}
?>
<h3><?php echo $hesklang['profile_for'].' <b>'.$_SESSION['new']['user']; ?></b></h3>
<h6><?php echo $hesklang['req_marked_with']; ?> <span class="important">*</span></h6>
<div class="footerWithBorder blankSpace"></div>
<?php
if ($hesk_settings['can_sel_lang'])
{
/* Update preferred language in the database? */
if (isset($_GET['save_language']) )
{
$newlang = hesk_input( hesk_GET('language') );
/* Only update if it's a valid language */
if ( isset($hesk_settings['languages'][$newlang]) )
{
$newlang = ($newlang == HESK_DEFAULT_LANGUAGE) ? "NULL" : "'" . hesk_dbEscape($newlang) . "'";
hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` SET `language`=$newlang WHERE `id`='".intval($_SESSION['id'])."' LIMIT 1");
}
}
$str = '<form class="form-horizontal" role="form" method="get" action="profile.php">';
$str .= '<input type="hidden" name="save_language" value="1" />';
$str .= '<div class="form-group">';
$str .= '<label for="language" class="col-sm-3 control-label">'.$hesklang['chol'].':</label>';
if ( ! isset($_GET) )
{
$_GET = array();
}
foreach ($_GET as $k => $v)
{
if ($k == 'language' || $k == 'save_language')
{
continue;
}
$str .= '<input type="hidden" name="'.htmlentitieshesk_htmlentities($k).'" value="'.hesk_htmlentities($v).'" />';
}
$str .= '<div class="col-sm-9"><select class="form-control" name="language" onchange="this.form.submit()">';
$str .= hesk_listLanguages(0);
$str .= '</select></div>';
$str .= '</div>'
?>
<script language="javascript" type="text/javascript">
document.write('<?php echo str_replace(array('"','<','=','>'),array('\42','\74','\75','\76'),$str . '</form>'); ?>');
</script>
<noscript>
<?php
echo $str . '<input type="submit" value="'.$hesklang['go'].'" /></form>';
?>
</noscript>
<?php
}
?>
<form role="form" class="form-horizontal" method="post" action="profile.php" name="form1">
<h4><?php echo $hesklang['pinfo']; ?></h4>
<div class="footerWithBorder blankSpace"></div>
<!-- Contact info -->
<div class="form-group">
<label for="name" class="col-sm-3 control-label"><?php echo $hesklang['name']; ?>: <font class="important">*</font></label>
<div class="col-sm-9">
<input class="form-control" type="text" name="name" size="30" maxlength="50" value="<?php echo $_SESSION['new']['name']; ?>" placeholder="<?php echo $hesklang['name']; ?>" />
</div>
</div>
<div class="form-group">
<label for="email" class="col-sm-3 control-label"><?php echo $hesklang['email']; ?>: <font class="important">*</font></label>
<div class="col-sm-9">
<input type="text" class="form-control" name="email" size="30" maxlength="255" value="<?php echo $_SESSION['new']['email']; ?>" placeholder="<?php echo $hesklang['email']; ?>"/>
</div>
<div class="content-wrapper">
<section class="content">
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['profile_for']; ?> <b><?php echo $_SESSION['new']['user']; ?></b>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<?php echo $hesklang['req_marked_with']; ?> <span class="important">*</span>
<?php
// Let admins change their username
if ($_SESSION['isadmin'])
{
?>
<div class="form-group">
<label for="user" class="col-sm-3 control-label"><?php echo $hesklang['username']; ?>: <font class="important">*</font></label>
<div class="col-sm-9">
<input type="text" class="form-control" name="user" size="30" maxlength="50" value="<?php echo $_SESSION['new']['user']; ?>" autocomplete="off" placeholder="<?php echo $hesklang['username']; ?>" />
</div>
</div>
<?php
/* This will handle error, success and notice messages */
hesk_handle_messages();
if (defined('WARN_PASSWORD')) {
hesk_show_notice($hesklang['chdp2'], $hesklang['security']);
}
if ($hesk_settings['can_sel_lang']) {
/* Update preferred language in the database? */
if (isset($_GET['save_language'])) {
$newlang = hesk_input(hesk_GET('language'));
/* Only update if it's a valid language */
if (isset($hesk_settings['languages'][$newlang])) {
$newlang = ($newlang == HESK_DEFAULT_LANGUAGE) ? "NULL" : "'" . hesk_dbEscape($newlang) . "'";
hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` SET `language`=$newlang WHERE `id`='" . intval($_SESSION['id']) . "'");
}
}
$str = '<form class="form-horizontal" role="form" method="get" action="profile.php">';
$str .= '<input type="hidden" name="save_language" value="1" />';
$str .= '<div class="form-group">';
$str .= '<label for="language" class="col-sm-3 control-label">' . $hesklang['chol'] . ':</label>';
if (!isset($_GET)) {
$_GET = array();
}
foreach ($_GET as $k => $v) {
if ($k == 'language' || $k == 'save_language') {
continue;
}
$str .= '<input type="hidden" name="' . htmlentitieshesk_htmlentities($k) . '" value="' . hesk_htmlentities($v) . '" />';
}
$str .= '<div class="col-sm-9"><select class="form-control" name="language" onchange="this.form.submit()">';
$str .= hesk_listLanguages(0);
$str .= '</select></div>';
$str .= '</div>'
?>
<script language="javascript" type="text/javascript">
document.write('<?php echo str_replace(array('"','<','=','>',"'"),array('\42','\74','\75','\76','\47'),$str . '</form>'); ?>');
</script>
<noscript>
<?php
echo $str . '<input type="submit" value="' . $hesklang['go'] . '" /></form>';
?>
</noscript>
<?php
}
?>
<div class="form-group">
<label for="newpass" class="col-sm-3 control-label"><?php echo $hesklang['new_pass']; ?>:</label>
<div class="col-sm-9">
<input type="password" class="form-control" name="newpass" size="30" onkeyup="javascript:hesk_checkPassword(this.value)" autocomplete="off" placeholder="<?php echo $hesklang['new_pass']; ?>" />
</div>
</div>
<div class="form-group">
<label for="newpass2" class="col-sm-3 control-label"><?php echo $hesklang['confirm_pass']; ?>:</label>
<div class="col-sm-9">
<input type="password" class="form-control" name="newpass2" size="30" autocomplete="off" placeholder="<?php echo $hesklang['confirm_pass']; ?>" />
</div>
</div>
<div class="form-group">
<label for="pwdStrength" class="col-sm-3 control-label"><?php echo $hesklang['pwdst']; ?>:</label>
<div class="col-sm-9">
<div style="border: 1px solid gray; width: 100px;">
<div id="progressBar"
style="font-size: 1px; height: 14px; width: 0px; border: 1px solid white;">
</div>
</div>
</div>
</div>
<h4><?php echo $hesklang['sig']; ?></h4>
<div class="footerWithBorder blankSpace"></div>
<!-- Signature -->
<div class="form-group">
<label for="signature" class="col-sm-3 control-label"><?php echo $hesklang['signature_max']; ?>:</label>
<div class="col-sm-9">
<textarea class="form-control" name="signature" rows="6" cols="40" placholder="<?php echo $hesklang['sig']; ?>"><?php echo $_SESSION['new']['signature']; ?></textarea><br />
<?php echo $hesklang['sign_extra']; ?>
</div>
</div>
<?php
if ($can_reply_tickets)
{
?>
<h4><?php echo $hesklang['pref']; ?></h4>
<div class="footerWithBorder blankSpace"></div>
<div class="form-group">
<label for="afterreply" class="col-sm-3 control-label"><?php echo $hesklang['aftrep']; ?>:</label>
<div class="col-sm-9">
<div class="radio">
<label><input type="radio" name="afterreply" value="0" <?php if (!$_SESSION['new']['afterreply']) {echo 'checked="checked"';} ?>/> <?php echo $hesklang['showtic']; ?></label>
</div>
<div class="radio">
<label><input type="radio" name="afterreply" value="1" <?php if ($_SESSION['new']['afterreply'] == 1) {echo 'checked="checked"';} ?>/> <?php echo $hesklang['gomain']; ?></label>
</div>
<div class="radio">
<label><input type="radio" name="afterreply" value="2" <?php if ($_SESSION['new']['afterreply'] == 2) {echo 'checked="checked"';} ?>/> <?php echo $hesklang['shownext']; ?></label>
</div>
</div>
</div>
<div class="form-group">
<label for="autostart" class="col-sm-3 control-label"><?php echo $hesklang['ts']; ?>:</label>
<div class="col-sm-9">
<div class="checkbox">
<label><input type="checkbox" name="autostart" value="1" <?php if (!empty($_SESSION['new']['autostart'])) {echo 'checked="checked"';}?> /> <?php echo $hesklang['autoss']; ?></label>
</div>
</div>
</div>
<?php } ?>
<h4><?php echo $hesklang['notn']; ?></h4>
<h6><?php echo $hesklang['nomw']; ?></h6>
<div class="footerWithBorder blankSpace"></div>
<div class="form-group">
<?php
if ($can_view_tickets)
{
if ($can_view_unassigned)
{
?>
<div class="col-md-9 col-md-offset-3"><div class="checkbox"><label><input type="checkbox" name="notify_new_unassigned" value="1" <?php if (!empty($_SESSION['new']['notify_new_unassigned'])) {echo 'checked="checked"';}?> /> <?php echo $hesklang['nwts']; ?> <?php echo $hesklang['unas']; ?></label></div></div>
<?php
}
else
{
?>
<input type="hidden" name="notify_new_unassigned" value="0" />
<?php
}
?>
<div class="col-md-9 col-md-offset-3"><div class="checkbox"><label><input type="checkbox" name="notify_new_my" value="1" <?php if (!empty($_SESSION['new']['notify_new_my'])) {echo 'checked="checked"';}?> /> <?php echo $hesklang['nwts']; ?> <?php echo $hesklang['s_my']; ?></label></div></div>
<?php if ($can_view_unassigned)
{
?>
<div class="col-md-9 col-md-offset-3"><div class="checkbox"><label><input type="checkbox" name="notify_reply_unassigned" value="1" <?php if (!empty($_SESSION['new']['notify_reply_unassigned'])) {echo 'checked="checked"';}?> /> <?php echo $hesklang['ncrt']; ?> <?php echo $hesklang['unas']; ?></label></div></div>
<?php
}
else
{
?>
<input type="hidden" name="notify_reply_unassigned" value="0" />
<?php
}
?>
<div class="col-md-9 col-md-offset-3"><div class="checkbox"><label><input type="checkbox" name="notify_reply_my" value="1" <?php if (!empty($_SESSION['new']['notify_reply_my'])) {echo 'checked="checked"';}?> /> <?php echo $hesklang['ncrt']; ?> <?php echo $hesklang['s_my']; ?></label></div></div>
<div class="col-md-9 col-md-offset-3"><div class="checkbox"><label><input type="checkbox" name="notify_assigned" value="1" <?php if (!empty($_SESSION['new']['notify_assigned'])) {echo 'checked="checked"';}?> /> <?php echo $hesklang['ntam']; ?></label></div></div>
<div class="col-md-9 col-md-offset-3"><div class="checkbox"><label><input type="checkbox" name="notify_note" value="1" <?php if (!empty($_SESSION['new']['notify_note'])) {echo 'checked="checked"';}?> /> <?php echo $hesklang['ntnote']; ?></label></div></div>
<?php
} // END $can_view_tickets
?>
<div class="col-md-9 col-md-offset-3"><div class="checkbox"><label><input type="checkbox" name="notify_pm" value="1" <?php if (!empty($_SESSION['new']['notify_pm'])) {echo 'checked="checked"';}?> /> <?php echo $hesklang['npms']; ?></label></div></div>
</div>
<input type="hidden" name="action" value="update" />
<input type="hidden" name="token" value="<?php hesk_token_echo(); ?>" />
<div style="text-align: center"><input type="submit" class="btn btn-default" value="<?php echo $hesklang['update_profile']; ?>" class="orangebutton" /></div>
</form>
<form role="form" class="form-horizontal" method="post" action="profile.php" name="form1" data-toggle="validator">
<?php hesk_profile_tab('new'); ?>
</form>
</div>
</div>
</section>
</div>
<?php
@ -315,136 +153,162 @@ exit();
/*** START FUNCTIONS ***/
function update_profile() {
global $hesk_settings, $hesklang, $can_view_unassigned;
function update_profile()
{
global $hesk_settings, $hesklang, $can_view_unassigned;
/* A security check */
hesk_token_check('POST');
/* A security check */
hesk_token_check('POST');
$sql_pass = '';
$sql_username = '';
$hesk_error_buffer = '';
$_SESSION['new']['name'] = hesk_input( hesk_POST('name') ) or $hesk_error_buffer .= '<li>' . $hesklang['enter_your_name'] . '</li>';
$_SESSION['new']['email'] = hesk_validateEmail( hesk_POST('email'), 'ERR', 0) or $hesk_error_buffer = '<li>' . $hesklang['enter_valid_email'] . '</li>';
$_SESSION['new']['signature'] = hesk_input( hesk_POST('signature') );
$_SESSION['new']['name'] = hesk_input(hesk_POST('name')) or $hesk_error_buffer .= '<li>' . $hesklang['enter_your_name'] . '</li>';
$_SESSION['new']['email'] = hesk_validateEmail( hesk_POST('email'), 'ERR', 0) or $hesk_error_buffer .= '<li>' . $hesklang['enter_valid_email'] . '</li>';
$_SESSION['new']['signature'] = hesk_input(hesk_POST('signature'));
/* Signature */
if (strlen($_SESSION['new']['signature'])>255)
{
$hesk_error_buffer .= '<li>' . $hesklang['signature_long'] . '</li>';
/* Signature */
if (hesk_mb_strlen($_SESSION['new']['signature']) > 1000) {
$hesk_error_buffer .= '<li>' . $hesklang['signature_long'] . '</li>';
}
/* Admins can change username */
if ($_SESSION['isadmin'])
{
$_SESSION['new']['user'] = hesk_input( hesk_POST('user') ) or $hesk_error_buffer .= '<li>' . $hesklang['enter_username'] . '</li>';
if ($_SESSION['isadmin']) {
$_SESSION['new']['user'] = hesk_input(hesk_POST('user')) or $hesk_error_buffer .= '<li>' . $hesklang['enter_username'] . '</li>';
/* Check for duplicate usernames */
$result = hesk_dbQuery("SELECT `id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `user`='".hesk_dbEscape($_SESSION['new']['user'])."' AND `id`!='".intval($_SESSION['id'])."' LIMIT 1");
if (hesk_dbNumRows($result) != 0)
{
$hesk_error_buffer .= '<li>' . $hesklang['duplicate_user'] . '</li>';
}
else
{
$sql_username = ",`user`='" . hesk_dbEscape($_SESSION['new']['user']) . "'";
/* Check for duplicate usernames */
$result = hesk_dbQuery("SELECT `id` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `user`='" . hesk_dbEscape($_SESSION['new']['user']) . "' AND `id`!='" . intval($_SESSION['id']) . "' LIMIT 1");
if (hesk_dbNumRows($result) != 0) {
$hesk_error_buffer .= '<li>' . $hesklang['duplicate_user'] . '</li>';
} else {
$sql_username = ",`user`='" . hesk_dbEscape($_SESSION['new']['user']) . "'";
}
}
/* Change password? */
$newpass = hesk_input( hesk_POST('newpass') );
/* Change password? */
$newpass = hesk_input(hesk_POST('newpass'));
$passlen = strlen($newpass);
if ($passlen > 0)
{
if ($passlen > 0) {
/* At least 5 chars? */
if ($passlen < 5)
{
$hesk_error_buffer .= '<li>' . $hesklang['password_not_valid'] . '</li>';
}
/* Check password confirmation */
else
{
$newpass2 = hesk_input( hesk_POST('newpass2') );
if ($passlen < 5) {
$hesk_error_buffer .= '<li>' . $hesklang['password_not_valid'] . '</li>';
} /* Check password confirmation */
else {
$newpass2 = hesk_input(hesk_POST('newpass2'));
if ($newpass != $newpass2)
{
$hesk_error_buffer .= '<li>' . $hesklang['passwords_not_same'] . '</li>';
}
else
{
$v = hesk_Pass2Hash($newpass);
if ($v == '499d74967b28a841c98bb4baaabaad699ff3c079')
{
define('WARN_PASSWORD',true);
}
$sql_pass = ',`pass`=\''.$v.'\'';
if ($newpass != $newpass2) {
$hesk_error_buffer .= '<li>' . $hesklang['passwords_not_same'] . '</li>';
} else {
$newpass_hash = hesk_Pass2Hash($newpass);
if ($newpass_hash == '499d74967b28a841c98bb4baaabaad699ff3c079') {
define('WARN_PASSWORD', true);
}
$sql_pass = ',`pass`=\'' . $newpass_hash . '\'';
}
}
}
}
/* After reply */
$_SESSION['new']['afterreply'] = intval( hesk_POST('afterreply') );
if ($_SESSION['new']['afterreply'] != 1 && $_SESSION['new']['afterreply'] != 2)
{
$_SESSION['new']['afterreply'] = 0;
$_SESSION['new']['afterreply'] = intval(hesk_POST('afterreply'));
if ($_SESSION['new']['afterreply'] != 1 && $_SESSION['new']['afterreply'] != 2) {
$_SESSION['new']['afterreply'] = 0;
}
$_SESSION['new']['notify_customer_new'] = isset($_POST['notify_customer_new']) ? 1 : 0;
$_SESSION['new']['notify_customer_reply'] = isset($_POST['notify_customer_reply']) ? 1 : 0;
$_SESSION['new']['show_suggested'] = isset($_POST['show_suggested']) ? 1 : 0;
$_SESSION['new']['autoreload'] = isset($_POST['autoreload']) ? 1 : 0;
if ($_SESSION['new']['autoreload']) {
$_SESSION['new']['autoreload'] = intval(hesk_POST('reload_time'));
if (hesk_POST('secmin') == 'min') {
$_SESSION['new']['autoreload'] *= 60;
}
if ($_SESSION['new']['autoreload'] < 0 || $_SESSION['new']['autoreload'] > 65535) {
$_SESSION['new']['autoreload'] = 30;
}
} else {
hesk_setcookie('autorefresh', '');
}
/* Auto-start ticket timer */
$_SESSION['new']['autostart'] = isset($_POST['autostart']) ? 1 : 0;
/* Default calendar view */
$_SESSION['new']['default_calendar_view'] = hesk_POST('default-calendar-view', 0);
/* Notifications */
$_SESSION['new']['notify_new_unassigned'] = empty($_POST['notify_new_unassigned']) || ! $can_view_unassigned ? 0 : 1;
$_SESSION['new']['notify_new_my'] = empty($_POST['notify_new_my']) ? 0 : 1;
$_SESSION['new']['notify_reply_unassigned'] = empty($_POST['notify_reply_unassigned']) || ! $can_view_unassigned ? 0 : 1;
$_SESSION['new']['notify_reply_my'] = empty($_POST['notify_reply_my']) ? 0 : 1;
$_SESSION['new']['notify_assigned'] = empty($_POST['notify_assigned']) ? 0 : 1;
$_SESSION['new']['notify_note'] = empty($_POST['notify_note']) ? 0 : 1;
$_SESSION['new']['notify_pm'] = empty($_POST['notify_pm']) ? 0 : 1;
if (!(!$_SESSION[$session_array]['isadmin'] && isset($_SESSION[$session_array]['heskprivileges'])
&& strpos($_SESSION[$session_array]['heskprivileges'], 'can_change_notification_settings') === false)) {
$_SESSION['new']['notify_new_unassigned'] = empty($_POST['notify_new_unassigned']) || !$can_view_unassigned ? 0 : 1;
$_SESSION['new']['notify_new_my'] = empty($_POST['notify_new_my']) ? 0 : 1;
$_SESSION['new']['notify_reply_unassigned'] = empty($_POST['notify_reply_unassigned']) || !$can_view_unassigned ? 0 : 1;
$_SESSION['new']['notify_reply_my'] = empty($_POST['notify_reply_my']) ? 0 : 1;
$_SESSION['new']['notify_assigned'] = empty($_POST['notify_assigned']) ? 0 : 1;
$_SESSION['new']['notify_note'] = empty($_POST['notify_note']) ? 0 : 1;
$_SESSION['new']['notify_note_unassigned'] = empty($_POST['notify_note_unassigned']) ? 0 : 1;
$_SESSION['new']['notify_pm'] = empty($_POST['notify_pm']) ? 0 : 1;
$_SESSION['new']['notify_overdue_unassigned'] = empty($_POST['notify_overdue_unassigned']) ? 0 : 1;
}
/* Any errors? */
if (strlen($hesk_error_buffer))
{
/* Process the session variables */
$_SESSION['new'] = hesk_stripArray($_SESSION['new']);
if (strlen($hesk_error_buffer)) {
/* Process the session variables */
$_SESSION['new'] = hesk_stripArray($_SESSION['new']);
$hesk_error_buffer = $hesklang['rfm'].'<br /><br /><ul>'.$hesk_error_buffer.'</ul>';
hesk_process_messages($hesk_error_buffer,'NOREDIRECT');
}
else
{
/* Update database */
hesk_dbQuery(
"UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` SET
`name`='".hesk_dbEscape($_SESSION['new']['name'])."',
`email`='".hesk_dbEscape($_SESSION['new']['email'])."',
`signature`='".hesk_dbEscape($_SESSION['new']['signature'])."'
$hesk_error_buffer = $hesklang['rfm'] . '<br /><br /><ul>' . $hesk_error_buffer . '</ul>';
hesk_process_messages($hesk_error_buffer, 'NOREDIRECT');
} else {
/* Update database */
hesk_dbQuery(
"UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` SET
`name`='" . hesk_dbEscape($_SESSION['new']['name']) . "',
`email`='" . hesk_dbEscape($_SESSION['new']['email']) . "',
`signature`='" . hesk_dbEscape($_SESSION['new']['signature']) . "'
$sql_username
$sql_pass ,
`afterreply`='".intval($_SESSION['new']['afterreply'])."' ,
`autostart`='".intval($_SESSION['new']['autostart'])."' ,
`notify_new_unassigned`='".intval($_SESSION['new']['notify_new_unassigned'])."' ,
`notify_new_my`='".intval($_SESSION['new']['notify_new_my'])."' ,
`notify_reply_unassigned`='".intval($_SESSION['new']['notify_reply_unassigned'])."' ,
`notify_reply_my`='".intval($_SESSION['new']['notify_reply_my'])."' ,
`notify_assigned`='".intval($_SESSION['new']['notify_assigned'])."' ,
`notify_pm`='".intval($_SESSION['new']['notify_pm'])."',
`notify_note`='".intval($_SESSION['new']['notify_note'])."'
WHERE `id`='".intval($_SESSION['id'])."' LIMIT 1"
`afterreply`='" . intval($_SESSION['new']['afterreply']) . "' ,
`autostart`='" . intval($_SESSION['new']['autostart']) . "' ,
`autoreload`='".($_SESSION['new']['autoreload'])."' ,
`notify_new_unassigned`='" . intval($_SESSION['new']['notify_new_unassigned']) . "' ,
`notify_new_my`='" . intval($_SESSION['new']['notify_new_my']) . "' ,
`notify_reply_unassigned`='" . intval($_SESSION['new']['notify_reply_unassigned']) . "' ,
`notify_reply_my`='" . intval($_SESSION['new']['notify_reply_my']) . "' ,
`notify_assigned`='" . intval($_SESSION['new']['notify_assigned']) . "' ,
`notify_pm`='" . intval($_SESSION['new']['notify_pm']) . "',
`notify_note`='" . intval($_SESSION['new']['notify_note']) . "',
`notify_note_unassigned`='" . intval($_SESSION['new']['notify_note_unassigned']) . "',
`notify_customer_new`='" . $_SESSION['new']['notify_customer_new'] . "',
`notify_customer_reply`='" . $_SESSION['new']['notify_customer_reply'] . "',
`notify_overdue_unassigned`='" . $_SESSION['new']['notify_overdue_unassigned'] . "',
`show_suggested`='" . $_SESSION['new']['show_suggested'] . "',
`default_calendar_view`=" . intval($_SESSION['new']['default_calendar_view']) . "
WHERE `id`='" . intval($_SESSION['id']) . "'"
);
/* Process the session variables */
$_SESSION['new'] = hesk_stripArray($_SESSION['new']);
/* Process the session variables */
$_SESSION['new'] = hesk_stripArray($_SESSION['new']);
// Do we need a new session_verify tag?
if (strlen($sql_username) && strlen($sql_pass)) {
$_SESSION['session_verify'] = hesk_activeSessionCreateTag($_SESSION['new']['user'], $newpass_hash);
} elseif (strlen($sql_pass)) {
$_SESSION['session_verify'] = hesk_activeSessionCreateTag($_SESSION['user'], $newpass_hash);
} elseif (strlen($sql_username)) {
$res = hesk_dbQuery('SELECT `pass` FROM `' . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `id` = '" . intval($_SESSION['id']) . "' LIMIT 1");
$_SESSION['session_verify'] = hesk_activeSessionCreateTag($_SESSION['new']['user'], hesk_dbResult($res));
}
/* Update session variables */
foreach ($_SESSION['new'] as $k => $v)
{
$_SESSION[$k] = $v;
foreach ($_SESSION['new'] as $k => $v) {
$_SESSION[$k] = $v;
}
unset($_SESSION['new']);
hesk_process_messages($hesklang['profile_updated_success'],'profile.php','SUCCESS');
hesk_process_messages($hesklang['profile_updated_success'], 'profile.php', 'SUCCESS');
}
} // End update_profile()

File diff suppressed because it is too large Load Diff

439
admin/service_messages.php Normal file
View File

@ -0,0 +1,439 @@
<?php
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
define('PAGE_TITLE', 'ADMIN_SERVICE_MESSAGES');
define('MFH_PAGE_LAYOUT', 'TOP_ONLY');
define('EXTRA_JS', '<script src="'.HESK_PATH.'internal-api/js/service-messages.js"></script>');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/mail_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
/* Check permissions for this feature */
hesk_checkPermission('can_service_msg');
// Define required constants
define('WYSIWYG', 1);
/* Print header */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
/* Print main manage users page */
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
<div class="content-wrapper">
<section class="content">
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['manage_service_messages']; ?>
<i class="fa fa-question-circle settingsquestionmark" data-toggle="tooltip"
title="<?php echo hesk_makeJsString($hesklang['sm_intro']); ?>"
data-placement="bottom"></i>
</h1>
</div>
<div class="box-body">
<div class="row">
<div class="col-md-12 text-right">
<button id="create-button" class="btn btn-success">
<i class="fa fa-plus-circle"></i>&nbsp;
<?php echo $hesklang['create_new']; ?>
</button>
</div>
<div class="col-sm-12">
<?php
if ($hesk_settings['kb_wysiwyg']) {
?>
<script type="text/javascript">
/* <![CDATA[ */
$(document).ready(function() {
$('#content').summernote({
height: 200,
toolbar: [
['style', ['bold', 'italic', 'underline', 'clear']],
['font', ['strikethrough', 'superscript', 'subscript']],
['para', ['ul', 'ol']]
]
});
});
/* ]]> */
</script>
<input type="hidden" name="kb_wysiwyg" value="1">
<?php
} else {
?>
<input type="hidden" name="kb_wysiwyg" value="0">
<?php
}
?>
<table class="table table-hover">
<thead>
<tr>
<th style="display: none"><?php echo $hesklang['id']; ?></th>
<th><?php echo $hesklang['sm_mtitle']; ?></th>
<th><?php echo $hesklang['sm_author']; ?></th>
<th><?php echo $hesklang['lgs']; ?></th>
<th><?php echo $hesklang['sm_type']; ?></th>
<th><?php echo $hesklang['opt']; ?></th>
</tr>
</thead>
<tbody id="table-body">
</tbody>
</table>
</div>
</div>
</div>
<div class="overlay" id="overlay">
<i class="fa fa-spinner fa-spin"></i>
</div>
</div>
</section>
</div>
<div class="modal fade" id="service-message-modal" tabindex="-1" role="dialog" style="overflow: hidden">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close cancel-callback" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="myModalLabel">
<span id="edit-label"><?php echo $hesklang['edit_sm']; ?></span>
<span id="create-label"><?php echo $hesklang['new_sm']; ?></span>
</h4>
</div>
<form id="service-message" class="form-horizontal" data-toggle="validator" method="post">
<div class="modal-body">
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#sm-contents" role="tab" data-toggle="tab"><?php echo $hesklang['kb_content']; ?></a></li>
<li role="presentation"><a href="#properties" role="tab" data-toggle="tab"><?php echo $hesklang['properties']; ?></a></li>
</ul><br>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="sm-contents">
<div class="form-group">
<label for="title"
class="col-md-2 control-label"><?php echo $hesklang['sm_mtitle']; ?></label>
<div class="col-md-10">
<input class="form-control"
placeholder="<?php echo htmlspecialchars($hesklang['sm_mtitle']); ?>"
type="text" name="title" size="70" maxlength="255"
data-error="<?php echo htmlspecialchars($hesklang['sm_e_title']); ?>" required>
<div class="help-block with-errors"></div>
</div>
</div>
<div class="form-group">
<label for="message"
class="col-md-2 control-label"><?php echo $hesklang['sm_msg']; ?></label>
<div class="col-md-10">
<textarea placeholder="<?php echo htmlspecialchars($hesklang['sm_msg']); ?>"
class="form-control" name="message" id="content"></textarea>
</div>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="properties">
<div class="form-group">
<label for="language" class="col-md-2 control-label">
<?php echo $hesklang['lgs']; ?>
</label>
<div class="col-md-10">
<select name="language" class="form-control">
<option value="ALL"><?php echo $hesklang['all']; ?></option>
<?php foreach($hesk_settings['languages'] as $name => $info): ?>
<option value="<?php echo $info['folder']; ?>">
<?php echo $name; ?>
</option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="form-group">
<div class="row" style="padding-bottom: 10px;">
<label for="style"
class="col-md-2 control-label"><?php echo $hesklang['sm_style']; ?></label>
<div class="col-md-3">
<div class="radio alert pad-5" style="box-shadow: none; border-radius: 4px;">
<label>
<input type="radio" name="style" value="0" onclick="setIcon('')">
<?php echo $hesklang['sm_none']; ?>
</label>
</div>
</div>
<div class="col-md-3">
<div class="radio alert alert-success pad-5">
<label style="margin-top: -5px">
<input type="radio" name="style" value="1" onclick="setIcon('fa fa-check-circle')">
<?php echo $hesklang['sm_success']; ?>
</label>
</div>
</div>
<div class="col-md-3">
<div class="radio alert alert-info pad-5" onclick="setIcon('fa fa-comment')">
<label style="margin-top: -5px">
<input type="radio" name="style" value="2">
<?php echo $hesklang['sm_info']; ?>
</label>
</div>
</div>
</div>
<div class="row">
<div class="col-md-3 col-md-offset-2">
<div class="radio alert alert-warning pad-5">
<label style="margin-top: -5px">
<input type="radio" name="style" value="3"
onclick="setIcon('fa fa-exclamation-triangle')">
<?php echo $hesklang['sm_notice']; ?>
</label>
</div>
</div>
<div class="col-md-3">
<div class="radio alert alert-danger pad-5">
<label style="margin-top: -5px">
<input type="radio" name="style" value="4" onclick="setIcon('fa fa-times-circle')">
<?php echo $hesklang['sm_error']; ?>
</label>
</div>
</div>
</div>
</div>
<div class="form-group">
<label for="icon" class="col-md-2 control-label"><?php echo $hesklang['sm_icon']; ?></label>
<div class="col-md-10">
<p style="display:none" id="no-icon"><?php echo $hesklang['sm_no_icon']; ?></p>
<p style="display:none" id="search-icon"><?php echo $hesklang['sm_search_icon']; ?></p>
<p style="display:none"
id="footer-icon"><?php echo $hesklang['sm_iconpicker_footer_label']; ?></p>
<div name="icon" class="btn btn-default iconpicker-container" data-toggle="iconpicker"
data-search="false" data-icon=""></div>
</div>
</div>
<div class="form-group">
<label for="type" class="col-md-2 control-label"><?php echo $hesklang['sm_type']; ?></label>
<div class="col-md-2">
<div class="radio pad-5">
<label>
<input type="radio" name="type" value="0">
<?php echo $hesklang['sm_published']; ?>
</label>
</div>
</div>
<div class="col-md-2">
<div class="radio pad-5">
<label>
<input type="radio" name="type" value="1">
<?php echo $hesklang['sm_draft']; ?>
</label>
</div>
</div>
</div>
<div class="form-group">
<label for="location" class="col-md-2 control-label"><?php echo $hesklang['sm_location']; ?></label>
<div class="col-sm-4" style="margin-left:20px">
<h5 style="text-decoration: underline;"><?php echo $hesklang['sm_customer_pages']; ?></h5>
<div class="btn-group btn-group-sm">
<div data-select-all="customer-location" class="btn btn-default">
<?php echo $hesklang['select_all_title_case']; ?>
</div>
<div data-deselect-all="customer-location" class="btn btn-default">
<?php echo $hesklang['deselect_all_title_case']; ?>
</div>
</div>
<div class="checkbox">
<input data-select-target="customer-location" type="checkbox"
name="location[]" value="CUSTOMER_HOME"> <?php echo $hesklang['sm_homepage']; ?>
</div>
<?php if ($hesk_settings['kb_enable'] > 0): ?>
<div class="checkbox">
<input data-select-target="customer-location" type="checkbox"
name="location[]" value="CUSTOMER_KB_HOME"> <?php echo $hesklang['sm_kb_home']; ?>
</div>
<div class="checkbox">
<input data-select-target="customer-location" type="checkbox"
name="location[]" value="CUSTOMER_VIEW_KB_ARTICLE"> <?php echo $hesklang['sm_view_kb_article']; ?>
</div>
<?php endif; if ($hesk_settings['kb_enable'] != 2): ?>
<div class="checkbox">
<input data-select-target="customer-location" type="checkbox"
name="location[]" value="CUSTOMER_SUBMIT_TICKET"> <?php echo $hesklang['sm_submit_ticket']; ?>
</div>
<div class="checkbox">
<input data-select-target="customer-location" type="checkbox"
name="location[]" value="CUSTOMER_VIEW_TICKET"> <?php echo $hesklang['sm_view_ticket']; ?>
</div>
<?php endif; ?>
</div>
<div class="col-sm-4" style="margin-left:20px">
<h5 style="text-decoration: underline;"><?php echo $hesklang['sm_staff_pages']; ?></h5>
<div class="btn-group btn-group-sm">
<div data-select-all="staff-location" class="btn btn-default">
<?php echo $hesklang['select_all_title_case']; ?>
</div>
<div data-deselect-all="staff-location" class="btn btn-default">
<?php echo $hesklang['deselect_all_title_case']; ?>
</div>
</div>
<div class="checkbox">
<input data-select-target="staff-location" type="checkbox"
name="location[]" value="STAFF_LOGIN"> <?php echo $hesklang['sm_login_page']; ?>
</div>
<div class="checkbox">
<input data-select-target="staff-location" type="checkbox"
name="location[]" value="STAFF_HOME"> <?php echo $hesklang['sm_homepage']; ?>
</div>
<?php if ($hesk_settings['kb_enable'] > 0): ?>
<div class="checkbox">
<input data-select-target="staff-location" type="checkbox"
name="location[]" value="STAFF_KB_HOME"> <?php echo $hesklang['sm_kb_home']; ?>
</div>
<div class="checkbox">
<input data-select-target="staff-location" type="checkbox"
name="location[]" value="STAFF_VIEW_KB_ARTICLE"> <?php echo $hesklang['sm_view_kb_article']; ?>
</div>
<?php endif; if ($hesk_settings['kb_enable'] != 2): ?>
<div class="checkbox">
<input data-select-target="staff-location" type="checkbox"
name="location[]" value="STAFF_SUBMIT_TICKET"> <?php echo $hesklang['sm_submit_ticket']; ?>
</div>
<div class="checkbox">
<input data-select-target="staff-location" type="checkbox"
name="location[]" value="STAFF_VIEW_TICKET"> <?php echo $hesklang['sm_view_ticket']; ?>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
<div id="preview-pane"></div>
</div>
<div class="modal-footer">
<input type="hidden" name="id">
<input type="hidden" name="order">
<div id="action-buttons" class="btn-group">
<button type="button" class="btn btn-default cancel-button cancel-callback" data-dismiss="modal">
<i class="fa fa-times-circle"></i>
<span><?php echo $hesklang['cancel']; ?></span>
</button>
<button type="button" class="btn btn-primary preview-button">
<i class="fa fa-search"></i>
<span><?php echo $hesklang['sm_preview']; ?></span>
</button>
<button type="submit" class="btn btn-success save-button">
<i class="fa fa-check-circle"></i>
<span><?php echo $hesklang['save']; ?></span>
</button>
</div>
</div>
</form>
</div>
</div>
</div>
<?php
echo mfh_get_hidden_fields_for_language(array(
'sm_published',
'sm_draft',
'no_sm',
'sm_added',
'sm_mdf',
'error_saving_updating_sm',
'sm_deleted',
'error_deleting_sm',
'error_sorting_categories',
'error_retrieving_sm',
'all',
'e_udel',
));
echo '<script>var users = [];';
$usersRs = hesk_dbQuery("SELECT `id`, `name` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` WHERE `active` = '1'");
$users = array();
while ($row = hesk_dbFetchAssoc($usersRs)) {
$users[] = $row;
echo "users[" . $row['id'] . "] = {
id: ".$row['id'].",
name: '".$row['name']."'
}\n";
}
echo "
var languages = [];\n";
foreach ($hesk_settings['languages'] as $key => $value) {
echo "languages[" . json_encode($value['folder']) . "] = " . json_encode($key) . ";\n";
}
echo '</script>';
?>
<script type="text/html" id="service-message-title-template">
<div class="{{CLASS}}">
<i data-property="icon"></i>
<b data-property="title"></b>
</div>
</script>
<script type="text/html" id="service-message-preview-template">
<?php
$sm = array(
'icon' => 'fa',
'style' => 0,
'title' => '{{TITLE}}',
'message' => '{{MESSAGE}}'
);
hesk_service_message($sm);
?>
</script>
<script type="text/html" id="service-message-template">
<tr>
<td style="display: none"><span data-property="id" data-value="x"></span></td>
<td><span data-property="title"></span></td>
<td><span data-property="author"></span></td>
<td><span data-property="language"></span></td>
<td><span data-property="type"></span></td>
<td>
<span class="sort-arrows">
<a href="#" data-action="sort"
data-direction="up">
<i class="fa fa-fw fa-arrow-up icon-link green"
data-toggle="tooltip" title="<?php echo $hesklang['move_up']; ?>"></i>
</a>
<a href="#" data-action="sort"
data-direction="down">
<i class="fa fa-fw fa-arrow-down icon-link green"
data-toggle="tooltip" title="<?php echo $hesklang['move_dn'] ?>"></i>
</a>
</span>
<a name="Edit Service Message" href="#" data-action="edit">
<i class="fa fa-fw fa-pencil icon-link orange"
data-toggle="tooltip" title="<?php echo $hesklang['edit']; ?>"></i>
</a>
<a name="Delete Service Message" href="#" data-action="delete">
<i class="fa fa-fw fa-times icon-link red"
data-toggle="tooltip" title="<?php echo $hesklang['delete']; ?>"></i>
</a>
</td>
</tr>
</script>
<?php
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();
?>

View File

@ -1,88 +1,106 @@
<?php
/*******************************************************************************
* Title: Help Desk Software HESK
* Version: 2.5.3 from 16th March 2014
* Author: Klemen Stirn
* Website: http://www.hesk.com
********************************************************************************
* COPYRIGHT AND TRADEMARK NOTICE
* Copyright 2005-2013 Klemen Stirn. All Rights Reserved.
* HESK is a registered trademark of Klemen Stirn.
/**
*
* This file is part of HESK - PHP Help Desk Software.
*
* (c) Copyright Klemen Stirn. All rights reserved.
* https://www.hesk.com
*
* For the full copyright and license agreement information visit
* https://www.hesk.com/eula.php
*
*/
* The HESK may be used and modified free of charge by anyone
* AS LONG AS COPYRIGHT NOTICES AND ALL THE COMMENTS REMAIN INTACT.
* By using this code you agree to indemnify Klemen Stirn from any
* liability that might arise from it's use.
* Selling the code for this program, in part or full, without prior
* written consent is expressly forbidden.
* Using this code, in part or full, to create derivate work,
* new scripts or products is expressly forbidden. Obtain permission
* before redistributing this software over the Internet or in
* any other medium. In all cases copyright and header must remain intact.
* This Copyright is in full effect in any country that has International
* Trade Agreements with the United States of America or
* with the European Union.
* Removing any of the copyright notices without purchasing a license
* is expressly forbidden. To remove HESK copyright notice you must purchase
* a license for this script. For more information on how to obtain
* a license please visit the page below:
* https://www.hesk.com/buy.php
*******************************************************************************/
define('IN_SCRIPT',1);
define('HESK_PATH','../');
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
define('PAGE_TITLE', 'ADMIN_TICKET');
define('MFH_PAGE_LAYOUT', 'TOP_ONLY');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/status_functions.inc.php');
require(HESK_PATH . 'inc/mail_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
define('CALENDAR',1);
define('CALENDAR', 1);
define('AUTO_RELOAD',1);
/* Check permissions for this feature */
hesk_checkPermission('can_view_tickets');
/* Print header */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
/* Print admin navigation */
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
<div class="content-wrapper">
<section class="content">
<?php hesk_handle_messages(); ?>
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['tickets']; ?>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<div class="row">
<div class="col-xs-6 text-left">
<div class="checkbox">
<label>
<input type="checkbox" onclick="toggleAutoRefresh(this);" id="reloadCB">
<?php echo $hesklang['arp']; ?>
<span id="timer"></span>
</label>
</div>
<script type="text/javascript">heskCheckReloading();</script>
</div>
<div class="col-xs-6 text-right">
<a href="new_ticket.php" class="btn btn-success">
<span class="glyphicon glyphicon-plus-sign"></span>
<?php echo $hesklang['nti']; ?>
</a>
</div>
</div>
<?php
/* Print the list of tickets */
$is_search = 1;
require_once(HESK_PATH . 'inc/print_tickets.inc.php');
echo '<br>';
/* Update staff default settings? */
if (!empty($_GET['def'])) {
hesk_updateStaffDefaults();
}
<div class="col-md-8 col-md-offset-2">
/* Print forms for listing and searching tickets */
require_once(HESK_PATH . 'inc/show_search_form.inc.php');
?>
</div>
</div>
<?php
/* This will handle error, success and notice messages */
hesk_handle_messages();
?>
<h3 style="text-align: center"><?php echo $hesklang['tickets']; ?></h3>
<?php
/* Print the list of tickets */
$is_search = 1;
require_once(HESK_PATH . 'inc/print_tickets.inc.php');
/* Update staff default settings? */
if ( ! empty($_GET['def']))
{
hesk_updateStaffDefaults();
}
/* Print forms for listing and searching tickets */
require_once(HESK_PATH . 'inc/show_search_form.inc.php');
/* Print footer */
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();
/* Clean unneeded session variables */
hesk_cleanSessionVars('hide');
?>
</section>
</div>
<?php
/* Print footer */
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();
?>

111
admin/view_message_log.php Normal file
View File

@ -0,0 +1,111 @@
<?php
define('IN_SCRIPT', 1);
define('HESK_PATH', '../');
define('PAGE_TITLE', 'ADMIN_LOGS');
define('MFH_PAGE_LAYOUT', 'TOP_ONLY');
/* Get all the required files and functions */
require(HESK_PATH . 'hesk_settings.inc.php');
require(HESK_PATH . 'inc/common.inc.php');
require(HESK_PATH . 'inc/admin_functions.inc.php');
require(HESK_PATH . 'inc/mail_functions.inc.php');
hesk_load_database_functions();
hesk_session_start();
hesk_dbConnect();
hesk_isLoggedIn();
hesk_checkPermission('can_view_logs');
define('EXTRA_JS', '<script src="'.HESK_PATH.'internal-api/js/view-message-log.js"></script>');
/* Print header */
require_once(HESK_PATH . 'inc/headerAdmin.inc.php');
/* Print main manage users page */
require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
?>
<div class="content-wrapper">
<section class="content">
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['search_logs']; ?>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<div class="form-horizontal">
<div class="form-group">
<label for="location" class="control-label col-sm-4">
<?php echo $hesklang['custom_place']; ?>
</label>
<div class="col-sm-8">
<input type="text" name="location" class="form-control" placeholder="<?php echo hesk_htmlspecialchars($hesklang['custom_place']); ?>">
</div>
</div>
<div class="form-group">
<label for="date" class="control-label col-sm-4">
<?php echo $hesklang['date_logged']; ?>
</label>
<div class="col-sm-8">
<input type="text" name="from-date" class="datepicker form-control white-readonly no-bottom-round-corners no-bottom-border" placeholder="<?php echo hesk_htmlspecialchars($hesklang['from_date']); ?>" readonly>
<input type="text" name="to-date" class="datepicker form-control white-readonly no-top-round-corners" placeholder="<?php echo hesk_htmlspecialchars($hesklang['to_date']); ?>" readonly>
</div>
</div>
<div class="form-group">
<label for="severity" class="control-label col-sm-4"><?php echo $hesklang['severity']; ?></label>
<div class="col-sm-8">
<select name="severity" class="form-control">
<option value="-1" selected><?php echo $hesklang['all']; ?></option>
<option value="0"><?php echo $hesklang['debug']; ?></option>
<option value="1"><?php echo $hesklang['info']; ?></option>
<option value="2"><?php echo $hesklang['warning_title_case']; ?></option>
<option value="3"><?php echo $hesklang['sm_error']; ?></option>
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-8 col-sm-offset-4">
<button class="btn btn-default" id="search-button"><?php echo $hesklang['search']; ?></button>
</div>
</div>
</div>
</div>
</div>
<div class="box">
<div class="box-header with-border">
<h1 class="box-title">
<?php echo $hesklang['logs']; ?>
</h1>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-minus"></i>
</button>
</div>
</div>
<div class="box-body">
<table class="table table-striped" id="results-table">
<thead>
<tr>
<th><?php echo $hesklang['date']; ?></th>
<th><?php echo $hesklang['user']; ?></th>
<th><?php echo $hesklang['custom_place']; ?></th>
<th><?php echo $hesklang['message']; ?></th>
<th><?php echo $hesklang['stack_trace_header']; ?></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</section>
</div>
<?php
require_once(HESK_PATH . 'inc/footer.inc.php');
exit();

7
api/BaseClass.php Normal file
View File

@ -0,0 +1,7 @@
<?php
class BaseClass {
static function clazz() {
return get_called_class();
}
}

7
api/BaseException.php Normal file
View File

@ -0,0 +1,7 @@
<?php
class BaseException extends Exception {
static function clazz() {
return get_called_class();
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace BusinessLogic\Attachments;
class Attachment extends \BaseClass {
/* @var $id int */
public $id;
/* @var $savedName string */
public $savedName;
/* @var $displayName string */
public $displayName;
/* @var $id int */
public $fileSize;
/* @var $downloadCount int */
public $downloadCount;
}

View File

@ -0,0 +1,479 @@
<?php
namespace BusinessLogic\Attachments;
use BusinessLogic\Exceptions\AccessViolationException;
use BusinessLogic\Exceptions\ApiFriendlyException;
use BusinessLogic\Exceptions\ValidationException;
use BusinessLogic\Security\UserContext;
use BusinessLogic\Security\UserPrivilege;
use BusinessLogic\Security\UserToTicketChecker;
use BusinessLogic\Tickets\Attachment;
use BusinessLogic\Tickets\Ticket;
use BusinessLogic\ValidationModel;
use DataAccess\Attachments\AttachmentGateway;
use DataAccess\Files\FileDeleter;
use DataAccess\Files\FileWriter;
use DataAccess\Tickets\TicketGateway;
class AttachmentHandler extends \BaseClass {
/* @var $ticketGateway TicketGateway */
private $ticketGateway;
/* @var $attachmentGateway AttachmentGateway */
private $attachmentGateway;
/* @var $fileWriter FileWriter */
private $fileWriter;
/* @var $fileDeleter FileDeleter */
private $fileDeleter;
/* @var $userToTicketChecker UserToTicketChecker */
private $userToTicketChecker;
function __construct(TicketGateway $ticketGateway,
AttachmentGateway $attachmentGateway,
FileWriter $fileWriter,
UserToTicketChecker $userToTicketChecker,
FileDeleter $fileDeleter) {
$this->ticketGateway = $ticketGateway;
$this->attachmentGateway = $attachmentGateway;
$this->fileWriter = $fileWriter;
$this->userToTicketChecker = $userToTicketChecker;
$this->fileDeleter = $fileDeleter;
}
/**
* @param $createAttachmentModel CreateAttachmentForTicketModel
* @param $userContext UserContext
* @param $heskSettings array
* @return TicketAttachment the newly created attachment
* @throws \Exception
*/
function createAttachmentForTicket($createAttachmentModel, $userContext, $heskSettings) {
$this->validate($createAttachmentModel, $heskSettings);
$decodedAttachment = base64_decode($createAttachmentModel->attachmentContents);
$ticket = $this->ticketGateway->getTicketById($createAttachmentModel->ticketId, $heskSettings);
if ($ticket === null) {
throw new ApiFriendlyException("Ticket {$createAttachmentModel->ticketId} not found", "Ticket Not Found", 404);
}
$extraPermissions = $createAttachmentModel->isEditing
? array(UserPrivilege::CAN_EDIT_TICKETS)
: array();
if (!$this->userToTicketChecker->isTicketAccessibleToUser($userContext, $ticket, $heskSettings, $extraPermissions)) {
throw new AccessViolationException("User does not have access to ticket {$ticket->id} being created / edited!");
}
$cleanedFileName = $this->cleanFileName($createAttachmentModel->displayName);
$fileParts = pathinfo($cleanedFileName);
$ticketAttachment = new TicketAttachment();
$ticketAttachment->savedName = $this->generateSavedName($ticket->trackingId,
$cleanedFileName, $fileParts['extension']);
$ticketAttachment->displayName = $cleanedFileName;
$ticketAttachment->ticketTrackingId = $ticket->trackingId;
$ticketAttachment->type = 0;
$ticketAttachment->downloadCount = 0;
$ticketAttachment->fileSize =
$this->fileWriter->writeToFile($ticketAttachment->savedName, $heskSettings['attach_dir'], $decodedAttachment);
$attachmentId = $this->attachmentGateway->createAttachmentForTicket($ticketAttachment, $heskSettings);
$this->updateAttachmentsOnTicket($ticket, $ticketAttachment, $attachmentId, $heskSettings);
$ticketAttachment->id = $attachmentId;
return $ticketAttachment;
}
/**
* Supports deleting attachments from both ticket messages AND replies
*
* @param $ticketId int The ticket ID
* @param $attachmentId int The attachment ID
* @param $userContext UserContext
* @param $heskSettings array
* @throws ApiFriendlyException
* @throws \Exception
*/
function deleteAttachmentFromTicket($ticketId, $attachmentId, $userContext, $heskSettings) {
$ticket = $this->ticketGateway->getTicketById($ticketId, $heskSettings);
if ($ticket === null) {
throw new ApiFriendlyException("Ticket {$ticketId} not found!", "Ticket Not Found", 404);
}
if (!$this->userToTicketChecker->isTicketAccessibleToUser($userContext, $ticket, $heskSettings, array(UserPrivilege::CAN_EDIT_TICKETS))) {
throw new AccessViolationException("User does not have access to ticket {$ticketId} being created / edited!");
}
$indexToRemove = -1;
$attachmentType = AttachmentType::MESSAGE;
$replyId = -1;
for ($i = 0; $i < count($ticket->attachments); $i++) {
$attachment = $ticket->attachments[$i];
if ($attachment->id === $attachmentId) {
$indexToRemove = $i;
$this->fileDeleter->deleteFile($attachment->savedName, $heskSettings['attach_dir']);
$this->attachmentGateway->deleteAttachment($attachment->id, $heskSettings);
}
}
foreach ($ticket->replies as $reply) {
for ($i = 0; $i < count($reply->attachments); $i++) {
$attachment = $reply->attachments[$i];
if ($attachment->id === $attachmentId) {
$indexToRemove = $i;
$replyId = $reply->id;
$attachmentType = AttachmentType::REPLY;
$this->fileDeleter->deleteFile($attachment->savedName, $heskSettings['attach_dir']);
$this->attachmentGateway->deleteAttachment($attachment->id, $heskSettings);
}
}
}
if ($indexToRemove === -1) {
throw new ApiFriendlyException("Attachment not found for ticket or reply! ID: {$attachmentId}", "Attachment not found", 404);
}
if ($attachmentType == AttachmentType::MESSAGE) {
$attachments = $ticket->attachments;
unset($attachments[$indexToRemove]);
$this->ticketGateway->updateAttachmentsForTicket($ticketId, $attachments, $heskSettings);
} else {
$attachments = $ticket->replies[$replyId]->attachments;
unset($attachments[$indexToRemove]);
$this->ticketGateway->updateAttachmentsForReply($replyId, $attachments, $heskSettings);
}
}
/**
* @param $createAttachmentModel CreateAttachmentForTicketModel
* @param $heskSettings array
* @throws ValidationException
*/
private function validate($createAttachmentModel, $heskSettings) {
$errorKeys = array();
if ($createAttachmentModel->attachmentContents === null ||
trim($createAttachmentModel->attachmentContents) === '') {
$errorKeys[] = 'CONTENTS_EMPTY';
}
if (base64_decode($createAttachmentModel->attachmentContents, true) === false) {
$errorKeys[] = 'CONTENTS_NOT_BASE_64';
}
if ($createAttachmentModel->displayName === null ||
trim($createAttachmentModel->displayName === '')) {
$errorKeys[] = 'DISPLAY_NAME_EMPTY';
}
if ($createAttachmentModel->ticketId === null ||
$createAttachmentModel->ticketId < 1) {
$errorKeys[] = 'TICKET_ID_MISSING';
}
$fileParts = pathinfo($createAttachmentModel->displayName);
if (!isset($fileParts['extension']) || !in_array(".{$fileParts['extension']}", $heskSettings['attachments']['allowed_types'])) {
$errorKeys[] = 'EXTENSION_NOT_PERMITTED';
}
$fileContents = base64_decode($createAttachmentModel->attachmentContents);
if (function_exists('mb_strlen')) {
$fileSize = mb_strlen($fileContents, '8bit');
} else {
$fileSize = strlen($fileContents);
}
if ($fileSize > $heskSettings['attachments']['max_size']) {
$errorKeys[] = 'FILE_SIZE_TOO_LARGE';
}
if (count($errorKeys) > 0) {
$validationModel = new ValidationModel();
$validationModel->errorKeys = $errorKeys;
throw new ValidationException($validationModel);
}
}
private function generateSavedName($trackingId, $displayName, $fileExtension) {
$fileExtension = ".{$fileExtension}";
$useChars = 'AEUYBDGHJLMNPQRSTVWXZ123456789';
$tmp = uniqid();
for ($j = 1; $j < 10; $j++) {
$tmp .= $useChars{mt_rand(0, 29)};
}
return substr($trackingId . '_' . md5($tmp . $displayName), 0, 200) . $fileExtension;
}
/**
* @param $displayName string original file name
* @return string The cleaned file name
*/
private function cleanFileName($displayName) {
$filename = str_replace(array('%20', '+'), '-', $displayName);
$filename = preg_replace('/[\s-]+/', '-', $filename);
$filename = $this->removeAccents($filename);
$filename = preg_replace('/[^A-Za-z0-9\.\-_]/', '', $filename);
$filename = trim($filename, '-_');
return $filename;
}
// The following code has been borrowed from Wordpress, and also from posting_functions.inc.php :P
// Credits: http://wordpress.org
private function removeAccents($string)
{
if (!preg_match('/[\x80-\xff]/', $string)) {
return $string;
}
if ($this->seemsUtf8($string)) {
$chars = array(
// Decompositions for Latin-1 Supplement
chr(194) . chr(170) => 'a', chr(194) . chr(186) => 'o',
chr(195) . chr(128) => 'A', chr(195) . chr(129) => 'A',
chr(195) . chr(130) => 'A', chr(195) . chr(131) => 'A',
chr(195) . chr(132) => 'A', chr(195) . chr(133) => 'A',
chr(195) . chr(134) => 'AE', chr(195) . chr(135) => 'C',
chr(195) . chr(136) => 'E', chr(195) . chr(137) => 'E',
chr(195) . chr(138) => 'E', chr(195) . chr(139) => 'E',
chr(195) . chr(140) => 'I', chr(195) . chr(141) => 'I',
chr(195) . chr(142) => 'I', chr(195) . chr(143) => 'I',
chr(195) . chr(144) => 'D', chr(195) . chr(145) => 'N',
chr(195) . chr(146) => 'O', chr(195) . chr(147) => 'O',
chr(195) . chr(148) => 'O', chr(195) . chr(149) => 'O',
chr(195) . chr(150) => 'O', chr(195) . chr(153) => 'U',
chr(195) . chr(154) => 'U', chr(195) . chr(155) => 'U',
chr(195) . chr(156) => 'U', chr(195) . chr(157) => 'Y',
chr(195) . chr(158) => 'TH', chr(195) . chr(159) => 's',
chr(195) . chr(160) => 'a', chr(195) . chr(161) => 'a',
chr(195) . chr(162) => 'a', chr(195) . chr(163) => 'a',
chr(195) . chr(164) => 'a', chr(195) . chr(165) => 'a',
chr(195) . chr(166) => 'ae', chr(195) . chr(167) => 'c',
chr(195) . chr(168) => 'e', chr(195) . chr(169) => 'e',
chr(195) . chr(170) => 'e', chr(195) . chr(171) => 'e',
chr(195) . chr(172) => 'i', chr(195) . chr(173) => 'i',
chr(195) . chr(174) => 'i', chr(195) . chr(175) => 'i',
chr(195) . chr(176) => 'd', chr(195) . chr(177) => 'n',
chr(195) . chr(178) => 'o', chr(195) . chr(179) => 'o',
chr(195) . chr(180) => 'o', chr(195) . chr(181) => 'o',
chr(195) . chr(182) => 'o', chr(195) . chr(184) => 'o',
chr(195) . chr(185) => 'u', chr(195) . chr(186) => 'u',
chr(195) . chr(187) => 'u', chr(195) . chr(188) => 'u',
chr(195) . chr(189) => 'y', chr(195) . chr(190) => 'th',
chr(195) . chr(191) => 'y', chr(195) . chr(152) => 'O',
// Decompositions for Latin Extended-A
chr(196) . chr(128) => 'A', chr(196) . chr(129) => 'a',
chr(196) . chr(130) => 'A', chr(196) . chr(131) => 'a',
chr(196) . chr(132) => 'A', chr(196) . chr(133) => 'a',
chr(196) . chr(134) => 'C', chr(196) . chr(135) => 'c',
chr(196) . chr(136) => 'C', chr(196) . chr(137) => 'c',
chr(196) . chr(138) => 'C', chr(196) . chr(139) => 'c',
chr(196) . chr(140) => 'C', chr(196) . chr(141) => 'c',
chr(196) . chr(142) => 'D', chr(196) . chr(143) => 'd',
chr(196) . chr(144) => 'D', chr(196) . chr(145) => 'd',
chr(196) . chr(146) => 'E', chr(196) . chr(147) => 'e',
chr(196) . chr(148) => 'E', chr(196) . chr(149) => 'e',
chr(196) . chr(150) => 'E', chr(196) . chr(151) => 'e',
chr(196) . chr(152) => 'E', chr(196) . chr(153) => 'e',
chr(196) . chr(154) => 'E', chr(196) . chr(155) => 'e',
chr(196) . chr(156) => 'G', chr(196) . chr(157) => 'g',
chr(196) . chr(158) => 'G', chr(196) . chr(159) => 'g',
chr(196) . chr(160) => 'G', chr(196) . chr(161) => 'g',
chr(196) . chr(162) => 'G', chr(196) . chr(163) => 'g',
chr(196) . chr(164) => 'H', chr(196) . chr(165) => 'h',
chr(196) . chr(166) => 'H', chr(196) . chr(167) => 'h',
chr(196) . chr(168) => 'I', chr(196) . chr(169) => 'i',
chr(196) . chr(170) => 'I', chr(196) . chr(171) => 'i',
chr(196) . chr(172) => 'I', chr(196) . chr(173) => 'i',
chr(196) . chr(174) => 'I', chr(196) . chr(175) => 'i',
chr(196) . chr(176) => 'I', chr(196) . chr(177) => 'i',
chr(196) . chr(178) => 'IJ', chr(196) . chr(179) => 'ij',
chr(196) . chr(180) => 'J', chr(196) . chr(181) => 'j',
chr(196) . chr(182) => 'K', chr(196) . chr(183) => 'k',
chr(196) . chr(184) => 'k', chr(196) . chr(185) => 'L',
chr(196) . chr(186) => 'l', chr(196) . chr(187) => 'L',
chr(196) . chr(188) => 'l', chr(196) . chr(189) => 'L',
chr(196) . chr(190) => 'l', chr(196) . chr(191) => 'L',
chr(197) . chr(128) => 'l', chr(197) . chr(129) => 'L',
chr(197) . chr(130) => 'l', chr(197) . chr(131) => 'N',
chr(197) . chr(132) => 'n', chr(197) . chr(133) => 'N',
chr(197) . chr(134) => 'n', chr(197) . chr(135) => 'N',
chr(197) . chr(136) => 'n', chr(197) . chr(137) => 'N',
chr(197) . chr(138) => 'n', chr(197) . chr(139) => 'N',
chr(197) . chr(140) => 'O', chr(197) . chr(141) => 'o',
chr(197) . chr(142) => 'O', chr(197) . chr(143) => 'o',
chr(197) . chr(144) => 'O', chr(197) . chr(145) => 'o',
chr(197) . chr(146) => 'OE', chr(197) . chr(147) => 'oe',
chr(197) . chr(148) => 'R', chr(197) . chr(149) => 'r',
chr(197) . chr(150) => 'R', chr(197) . chr(151) => 'r',
chr(197) . chr(152) => 'R', chr(197) . chr(153) => 'r',
chr(197) . chr(154) => 'S', chr(197) . chr(155) => 's',
chr(197) . chr(156) => 'S', chr(197) . chr(157) => 's',
chr(197) . chr(158) => 'S', chr(197) . chr(159) => 's',
chr(197) . chr(160) => 'S', chr(197) . chr(161) => 's',
chr(197) . chr(162) => 'T', chr(197) . chr(163) => 't',
chr(197) . chr(164) => 'T', chr(197) . chr(165) => 't',
chr(197) . chr(166) => 'T', chr(197) . chr(167) => 't',
chr(197) . chr(168) => 'U', chr(197) . chr(169) => 'u',
chr(197) . chr(170) => 'U', chr(197) . chr(171) => 'u',
chr(197) . chr(172) => 'U', chr(197) . chr(173) => 'u',
chr(197) . chr(174) => 'U', chr(197) . chr(175) => 'u',
chr(197) . chr(176) => 'U', chr(197) . chr(177) => 'u',
chr(197) . chr(178) => 'U', chr(197) . chr(179) => 'u',
chr(197) . chr(180) => 'W', chr(197) . chr(181) => 'w',
chr(197) . chr(182) => 'Y', chr(197) . chr(183) => 'y',
chr(197) . chr(184) => 'Y', chr(197) . chr(185) => 'Z',
chr(197) . chr(186) => 'z', chr(197) . chr(187) => 'Z',
chr(197) . chr(188) => 'z', chr(197) . chr(189) => 'Z',
chr(197) . chr(190) => 'z', chr(197) . chr(191) => 's',
// Decompositions for Latin Extended-B
chr(200) . chr(152) => 'S', chr(200) . chr(153) => 's',
chr(200) . chr(154) => 'T', chr(200) . chr(155) => 't',
// Euro Sign
chr(226) . chr(130) . chr(172) => 'E',
// GBP (Pound) Sign
chr(194) . chr(163) => '',
// Vowels with diacritic (Vietnamese)
// unmarked
chr(198) . chr(160) => 'O', chr(198) . chr(161) => 'o',
chr(198) . chr(175) => 'U', chr(198) . chr(176) => 'u',
// grave accent
chr(225) . chr(186) . chr(166) => 'A', chr(225) . chr(186) . chr(167) => 'a',
chr(225) . chr(186) . chr(176) => 'A', chr(225) . chr(186) . chr(177) => 'a',
chr(225) . chr(187) . chr(128) => 'E', chr(225) . chr(187) . chr(129) => 'e',
chr(225) . chr(187) . chr(146) => 'O', chr(225) . chr(187) . chr(147) => 'o',
chr(225) . chr(187) . chr(156) => 'O', chr(225) . chr(187) . chr(157) => 'o',
chr(225) . chr(187) . chr(170) => 'U', chr(225) . chr(187) . chr(171) => 'u',
chr(225) . chr(187) . chr(178) => 'Y', chr(225) . chr(187) . chr(179) => 'y',
// hook
chr(225) . chr(186) . chr(162) => 'A', chr(225) . chr(186) . chr(163) => 'a',
chr(225) . chr(186) . chr(168) => 'A', chr(225) . chr(186) . chr(169) => 'a',
chr(225) . chr(186) . chr(178) => 'A', chr(225) . chr(186) . chr(179) => 'a',
chr(225) . chr(186) . chr(186) => 'E', chr(225) . chr(186) . chr(187) => 'e',
chr(225) . chr(187) . chr(130) => 'E', chr(225) . chr(187) . chr(131) => 'e',
chr(225) . chr(187) . chr(136) => 'I', chr(225) . chr(187) . chr(137) => 'i',
chr(225) . chr(187) . chr(142) => 'O', chr(225) . chr(187) . chr(143) => 'o',
chr(225) . chr(187) . chr(148) => 'O', chr(225) . chr(187) . chr(149) => 'o',
chr(225) . chr(187) . chr(158) => 'O', chr(225) . chr(187) . chr(159) => 'o',
chr(225) . chr(187) . chr(166) => 'U', chr(225) . chr(187) . chr(167) => 'u',
chr(225) . chr(187) . chr(172) => 'U', chr(225) . chr(187) . chr(173) => 'u',
chr(225) . chr(187) . chr(182) => 'Y', chr(225) . chr(187) . chr(183) => 'y',
// tilde
chr(225) . chr(186) . chr(170) => 'A', chr(225) . chr(186) . chr(171) => 'a',
chr(225) . chr(186) . chr(180) => 'A', chr(225) . chr(186) . chr(181) => 'a',
chr(225) . chr(186) . chr(188) => 'E', chr(225) . chr(186) . chr(189) => 'e',
chr(225) . chr(187) . chr(132) => 'E', chr(225) . chr(187) . chr(133) => 'e',
chr(225) . chr(187) . chr(150) => 'O', chr(225) . chr(187) . chr(151) => 'o',
chr(225) . chr(187) . chr(160) => 'O', chr(225) . chr(187) . chr(161) => 'o',
chr(225) . chr(187) . chr(174) => 'U', chr(225) . chr(187) . chr(175) => 'u',
chr(225) . chr(187) . chr(184) => 'Y', chr(225) . chr(187) . chr(185) => 'y',
// acute accent
chr(225) . chr(186) . chr(164) => 'A', chr(225) . chr(186) . chr(165) => 'a',
chr(225) . chr(186) . chr(174) => 'A', chr(225) . chr(186) . chr(175) => 'a',
chr(225) . chr(186) . chr(190) => 'E', chr(225) . chr(186) . chr(191) => 'e',
chr(225) . chr(187) . chr(144) => 'O', chr(225) . chr(187) . chr(145) => 'o',
chr(225) . chr(187) . chr(154) => 'O', chr(225) . chr(187) . chr(155) => 'o',
chr(225) . chr(187) . chr(168) => 'U', chr(225) . chr(187) . chr(169) => 'u',
// dot below
chr(225) . chr(186) . chr(160) => 'A', chr(225) . chr(186) . chr(161) => 'a',
chr(225) . chr(186) . chr(172) => 'A', chr(225) . chr(186) . chr(173) => 'a',
chr(225) . chr(186) . chr(182) => 'A', chr(225) . chr(186) . chr(183) => 'a',
chr(225) . chr(186) . chr(184) => 'E', chr(225) . chr(186) . chr(185) => 'e',
chr(225) . chr(187) . chr(134) => 'E', chr(225) . chr(187) . chr(135) => 'e',
chr(225) . chr(187) . chr(138) => 'I', chr(225) . chr(187) . chr(139) => 'i',
chr(225) . chr(187) . chr(140) => 'O', chr(225) . chr(187) . chr(141) => 'o',
chr(225) . chr(187) . chr(152) => 'O', chr(225) . chr(187) . chr(153) => 'o',
chr(225) . chr(187) . chr(162) => 'O', chr(225) . chr(187) . chr(163) => 'o',
chr(225) . chr(187) . chr(164) => 'U', chr(225) . chr(187) . chr(165) => 'u',
chr(225) . chr(187) . chr(176) => 'U', chr(225) . chr(187) . chr(177) => 'u',
chr(225) . chr(187) . chr(180) => 'Y', chr(225) . chr(187) . chr(181) => 'y',
// Vowels with diacritic (Chinese, Hanyu Pinyin)
chr(201) . chr(145) => 'a',
// macron
chr(199) . chr(149) => 'U', chr(199) . chr(150) => 'u',
// acute accent
chr(199) . chr(151) => 'U', chr(199) . chr(152) => 'u',
// caron
chr(199) . chr(141) => 'A', chr(199) . chr(142) => 'a',
chr(199) . chr(143) => 'I', chr(199) . chr(144) => 'i',
chr(199) . chr(145) => 'O', chr(199) . chr(146) => 'o',
chr(199) . chr(147) => 'U', chr(199) . chr(148) => 'u',
chr(199) . chr(153) => 'U', chr(199) . chr(154) => 'u',
// grave accent
chr(199) . chr(155) => 'U', chr(199) . chr(156) => 'u',
);
$string = strtr($string, $chars);
} else {
// Assume ISO-8859-1 if not UTF-8
$chars['in'] = chr(128) . chr(131) . chr(138) . chr(142) . chr(154) . chr(158)
. chr(159) . chr(162) . chr(165) . chr(181) . chr(192) . chr(193) . chr(194)
. chr(195) . chr(196) . chr(197) . chr(199) . chr(200) . chr(201) . chr(202)
. chr(203) . chr(204) . chr(205) . chr(206) . chr(207) . chr(209) . chr(210)
. chr(211) . chr(212) . chr(213) . chr(214) . chr(216) . chr(217) . chr(218)
. chr(219) . chr(220) . chr(221) . chr(224) . chr(225) . chr(226) . chr(227)
. chr(228) . chr(229) . chr(231) . chr(232) . chr(233) . chr(234) . chr(235)
. chr(236) . chr(237) . chr(238) . chr(239) . chr(241) . chr(242) . chr(243)
. chr(244) . chr(245) . chr(246) . chr(248) . chr(249) . chr(250) . chr(251)
. chr(252) . chr(253) . chr(255);
$chars['out'] = "EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy";
$string = strtr($string, $chars['in'], $chars['out']);
$double_chars['in'] = array(chr(140), chr(156), chr(198), chr(208), chr(222), chr(223), chr(230), chr(240), chr(254));
$double_chars['out'] = array('OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th');
$string = str_replace($double_chars['in'], $double_chars['out'], $string);
}
return $string;
}
private function seemsUtf8($str)
{
$length = strlen($str);
for ($i = 0; $i < $length; $i++) {
$c = ord($str[$i]);
if ($c < 0x80) $n = 0; # 0bbbbbbb
elseif (($c & 0xE0) == 0xC0) $n = 1; # 110bbbbb
elseif (($c & 0xF0) == 0xE0) $n = 2; # 1110bbbb
elseif (($c & 0xF8) == 0xF0) $n = 3; # 11110bbb
elseif (($c & 0xFC) == 0xF8) $n = 4; # 111110bb
elseif (($c & 0xFE) == 0xFC) $n = 5; # 1111110b
else return false; # Does not match any model
for ($j = 0; $j < $n; $j++) { # n bytes matching 10bbbbbb follow ?
if ((++$i == $length) || ((ord($str[$i]) & 0xC0) != 0x80))
return false;
}
}
return true;
}
/**
* @param $ticket Ticket
* @param $ticketAttachment TicketAttachment
* @param $attachmentId int
* @param $heskSettings array
*/
private function updateAttachmentsOnTicket($ticket, $ticketAttachment, $attachmentId, $heskSettings) {
$attachments = $ticket->attachments === null ? array() : $ticket->attachments;
$newAttachment = new Attachment();
$newAttachment->savedName = $ticketAttachment->savedName;
$newAttachment->fileName = $ticketAttachment->displayName;
$newAttachment->id = $attachmentId;
$attachments[] = $newAttachment;
$this->ticketGateway->updateAttachmentsForTicket($ticket->id, $attachments, $heskSettings);
}
}

View File

@ -0,0 +1,64 @@
<?php
namespace BusinessLogic\Attachments;
use BusinessLogic\Exceptions\AccessViolationException;
use BusinessLogic\Exceptions\ApiFriendlyException;
use BusinessLogic\Security\UserToTicketChecker;
use DataAccess\Attachments\AttachmentGateway;
use DataAccess\Files\FileReader;
use DataAccess\Tickets\TicketGateway;
class AttachmentRetriever extends \BaseClass {
/* @var $attachmentGateway AttachmentGateway */
private $attachmentGateway;
/* @var $fileReader FileReader */
private $fileReader;
/* @var $ticketGateway TicketGateway */
private $ticketGateway;
/* @var $userToTicketChecker UserToTicketChecker */
private $userToTicketChecker;
function __construct($attachmentGateway, $fileReader, $ticketGateway, $userToTicketChecker) {
$this->attachmentGateway = $attachmentGateway;
$this->fileReader = $fileReader;
$this->ticketGateway = $ticketGateway;
$this->userToTicketChecker = $userToTicketChecker;
}
//-- TODO Test
function getAttachmentContentsForTrackingId($trackingId, $attachmentId, $userContext, $heskSettings) {
$ticket = $this->ticketGateway->getTicketByTrackingId($trackingId, $heskSettings);
if ($ticket === null) {
throw new ApiFriendlyException("Ticket {$trackingId} not found!", "Ticket Not Found", 404);
}
$attachment = $this->attachmentGateway->getAttachmentById($attachmentId, $heskSettings);
return array('meta' => $attachment,
'contents' => $this->fileReader->readFromFile($attachment->savedName, $heskSettings['attach_dir']));
}
function getAttachmentContentsForTicket($ticketId, $attachmentId, $userContext, $heskSettings) {
$ticket = $this->ticketGateway->getTicketById($ticketId, $heskSettings);
if ($ticket === null) {
throw new ApiFriendlyException("Ticket {$ticketId} not found!", "Ticket Not Found", 404);
}
if (!$this->userToTicketChecker->isTicketAccessibleToUser($userContext, $ticket, $heskSettings)) {
throw new AccessViolationException("User does not have access to attachment {$attachmentId}!");
}
$attachment = $this->attachmentGateway->getAttachmentById($attachmentId, $heskSettings);
$contents = base64_encode($this->fileReader->readFromFile(
$attachment->savedName, $heskSettings['attach_dir']));
return $contents;
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace BusinessLogic\Attachments;
class AttachmentType extends \BaseClass {
const MESSAGE = 0;
const REPLY = 1;
}

View File

@ -0,0 +1,9 @@
<?php
namespace BusinessLogic\Attachments;
class CreateAttachmentForTicketModel extends CreateAttachmentModel {
/* @var $ticketId int */
public $ticketId;
}

View File

@ -0,0 +1,21 @@
<?php
namespace BusinessLogic\Attachments;
class CreateAttachmentModel extends \BaseClass {
/* @var $savedName string */
public $savedName;
/* @var $displayName string */
public $displayName;
/* @var $id int */
public $fileSize;
/* @var $attachmentContents string */
public $attachmentContents;
/* @var $isEditing bool */
public $isEditing;
}

View File

@ -0,0 +1,12 @@
<?php
namespace BusinessLogic\Attachments;
class TicketAttachment extends Attachment {
/* @var $ticketTrackingId string */
public $ticketTrackingId;
/* @var $type int [use <code>AttachmentType</code>] */
public $type;
}

View File

@ -0,0 +1,22 @@
<?php
namespace BusinessLogic\Calendar;
class AbstractEvent {
public $id;
public $startTime;
public $title;
public $categoryId;
public $categoryName;
public $backgroundColor;
public $foregroundColor;
public $displayBorder;
}

View File

@ -0,0 +1,15 @@
<?php
namespace BusinessLogic\Calendar;
class BusinessHours {
/* @var $dayOfWeek int */
public $dayOfWeek;
/* @var $startTime string */
public $startTime;
/* @var $endTime string */
public $endTime;
}

View File

@ -0,0 +1,26 @@
<?php
namespace BusinessLogic\Calendar;
use BusinessLogic\Tickets\AuditTrail;
class CalendarEvent extends AbstractEvent {
public $type = 'CALENDAR';
public $endTime;
/* @var $allDay bool */
public $allDay;
public $location;
public $comments;
public $reminderValue;
public $reminderUnits;
/* @var $auditTrail AuditTrail[] */
public $auditTrail = array();
}

View File

@ -0,0 +1,96 @@
<?php
namespace BusinessLogic\Calendar;
use BusinessLogic\DateTimeHelpers;
use BusinessLogic\Security\UserContext;
use BusinessLogic\Tickets\AuditTrailEntityType;
use DataAccess\AuditTrail\AuditTrailGateway;
use DataAccess\Calendar\CalendarGateway;
class CalendarHandler extends \BaseClass {
private $calendarGateway;
private $auditTrailGateway;
public function __construct(CalendarGateway $calendarGateway,
AuditTrailGateway $auditTrailGateway) {
$this->calendarGateway = $calendarGateway;
$this->auditTrailGateway = $auditTrailGateway;
}
public function getEventsForStaff($searchEventsFilter, $heskSettings) {
return $this->calendarGateway->getEventsForStaff($searchEventsFilter, $heskSettings);
}
/**
* @param $calendarEvent CalendarEvent
* @param $userContext UserContext
* @param $heskSettings array
* @return CalendarEvent
* @throws \Exception If more than one event is returned for the given ID
*/
public function updateEvent($calendarEvent, $userContext, $heskSettings) {
$this->calendarGateway->updateEvent($calendarEvent, $userContext, $heskSettings);
$this->auditTrailGateway->insertAuditTrailRecord($calendarEvent->id,
AuditTrailEntityType::CALENDAR_EVENT,
'audit_event_updated',
DateTimeHelpers::heskDate($heskSettings),
array(0 => $userContext->name . ' (' . $userContext->username . ')'), $heskSettings);
$eventFilter = new SearchEventsFilter();
$eventFilter->eventId = $calendarEvent->id;
$eventFilter->reminderUserId = $userContext->id;
$events = $this->calendarGateway->getEventsForStaff($eventFilter, $heskSettings);
if (count($events) !== 1) {
throw new \Exception("Expected exactly 1 event, found: " . count($events));
}
$event = $events[0];
return $event;
}
/**
* @param $calendarEvent CalendarEvent
* @param $userContext UserContext
* @param $heskSettings array
* @return AbstractEvent
* @throws \Exception
*/
public function createEvent($calendarEvent, $userContext, $heskSettings) {
$this->calendarGateway->createEvent($calendarEvent, $userContext, $heskSettings);
$eventFilter = new SearchEventsFilter();
$eventFilter->eventId = $calendarEvent->id;
$eventFilter->reminderUserId = $userContext->id;
$events = $this->calendarGateway->getEventsForStaff($eventFilter, $heskSettings);
if (count($events) !== 1) {
throw new \Exception("Expected exactly 1 event, found: " . count($events));
}
$event = $events[0];
$this->auditTrailGateway->insertAuditTrailRecord($event->id,
AuditTrailEntityType::CALENDAR_EVENT,
'audit_event_created',
DateTimeHelpers::heskDate($heskSettings),
array(0 => $userContext->name . ' (' . $userContext->username . ')'), $heskSettings);
return $event;
}
public function deleteEvent($id, $userContext, $heskSettings) {
$this->calendarGateway->deleteEvent($id, $userContext, $heskSettings);
}
public function getBusinessHours($heskSettings) {
return $this->calendarGateway->getBusinessHours($heskSettings);
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace BusinessLogic\Calendar;
class ReminderUnit {
const MINUTE = 0;
const HOUR = 1;
const DAY = 2;
const WEEK = 3;
static function getByValue($value) {
switch ($value) {
case 0:
return 'MINUTE';
case 1:
return 'HOUR';
case 2:
return 'DAY';
case 3:
return 'WEEK';
default:
return 'UNKNOWN';
}
}
static function getByName($name) {
switch ($name) {
case 'MINUTE':
return self::MINUTE;
case 'HOUR':
return self::HOUR;
case 'DAY':
return self::DAY;
case 'WEEK':
return self::WEEK;
default:
return null;
}
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace BusinessLogic\Calendar;
class SearchEventsFilter {
/* @var $startTime int|null */
public $startTime;
/* @var $endTime int|null */
public $endTime;
/* @var $id int|null */
public $eventId;
/* @var $categories int[]|null */
public $categories;
/* @var $reminderUserId int|null */
public $reminderUserId;
/* @var $includeTickets bool */
public $includeTickets;
/* @var $includeUnassignedTickets bool */
public $includeUnassignedTickets;
/* @var $includeTicketsAssignedToOthers bool */
public $includeTicketsAssignedToOthers;
/* @var $includeTicketsAssignedToMe bool */
public $includeTicketsAssignedToMe;
}

View File

@ -0,0 +1,20 @@
<?php
namespace BusinessLogic\Calendar;
class TicketEvent extends AbstractEvent {
public $type = 'TICKET';
public $trackingId;
public $subject;
public $url;
public $owner;
public $priority;
public $status;
}

View File

@ -0,0 +1,73 @@
<?php
namespace BusinessLogic\Categories;
class Category extends \BaseClass {
/**
* @var int The Categories ID
*/
public $id;
/* @var $name string */
public $name;
/**
* @var int Categories order number
*/
public $catOrder;
/**
* @var bool Tickets autoassigned in this Categories
*/
public $autoAssign;
/**
* @var int The type of Categories (1 = Private, 0 = Public)
*/
public $type;
/**
* @var int The Categories's usage (0 = Tickets and Events, 1 = Tickets, 2 = Events)
*/
public $usage;
/**
* @var string
*/
public $backgroundColor;
/**
* @var string
*/
public $foregroundColor;
/**
* @var bool
*/
public $displayBorder;
/**
* @var int The default Tickets priority
*/
public $priority;
/**
* @var int|null The manager for the Categories, if applicable
*/
public $manager;
/**
* @var bool Indication if the user has access to the Categories
*/
public $accessible;
/**
* @var string
*/
public $description;
/**
* @var int
*/
public $numberOfTickets;
}

View File

@ -0,0 +1,203 @@
<?php
namespace BusinessLogic\Categories;
use BusinessLogic\Exceptions\AccessViolationException;
use BusinessLogic\Exceptions\ValidationException;
use BusinessLogic\Navigation\Direction;
use BusinessLogic\Security\PermissionChecker;
use BusinessLogic\Security\UserPrivilege;
use BusinessLogic\ValidationModel;
use DataAccess\Categories\CategoryGateway;
use DataAccess\Settings\ModsForHeskSettingsGateway;
use DataAccess\Tickets\TicketGateway;
class CategoryHandler extends \BaseClass {
/* @var $categoryGateway CategoryGateway */
private $categoryGateway;
/* @var $ticketGateway TicketGateway */
private $ticketGateway;
/* @var $permissionChecker PermissionChecker */
private $permissionChecker;
/* @var $modsForHeskSettingsGateway ModsForHeskSettingsGateway */
private $modsForHeskSettingsGateway;
function __construct(CategoryGateway $categoryGateway,
TicketGateway $ticketGateway,
PermissionChecker $permissionChecker,
ModsForHeskSettingsGateway $modsForHeskSettingsGateway) {
$this->categoryGateway = $categoryGateway;
$this->ticketGateway = $ticketGateway;
$this->permissionChecker = $permissionChecker;
$this->modsForHeskSettingsGateway = $modsForHeskSettingsGateway;
}
/**
* @param $category Category
* @param $userContext
* @param $heskSettings array
* @return Category The newly created category with ID
* @throws ValidationException When validation fails
* @throws \Exception When the newly created category was not retrieved
*/
//TODO Test
function createCategory($category, $userContext, $heskSettings) {
$modsForHeskSettings = $this->modsForHeskSettingsGateway->getAllSettings($heskSettings);
$validationModel = $this->validate($category, $userContext);
if (count($validationModel->errorKeys) > 0) {
throw new ValidationException($validationModel);
}
$id = $this->categoryGateway->createCategory($category, $heskSettings);
$allCategories = $this->categoryGateway->getAllCategories($heskSettings, $modsForHeskSettings);
foreach ($allCategories as $innerCategory) {
if ($innerCategory->id === $id) {
return $innerCategory;
}
}
throw new \BaseException("Newly created category {$id} lost! :O");
}
/**
* @param $category Category
* @param $userContext
* @param $creating bool
* @return ValidationModel
* @throws AccessViolationException
*/
//TODO Test
private function validate($category, $userContext, $creating = true) {
$validationModel = new ValidationModel();
if (!$this->permissionChecker->doesUserHavePermission($userContext, UserPrivilege::CAN_MANAGE_CATEGORIES)) {
throw new AccessViolationException('User cannot manage categories!');
}
if (!$creating && $category->id < 1) {
$validationModel->errorKeys[] = 'ID_MISSING';
}
if ($category->backgroundColor === null || trim($category->backgroundColor) === '') {
$validationModel->errorKeys[] = 'BACKGROUND_COLOR_MISSING';
}
if ($category->foregroundColor === null || trim($category->foregroundColor) === '') {
$validationModel->errorKeys[] = 'FOREGROUND_COLOR_MISSING';
}
if ($category->name === null || trim($category->name) === '') {
$validationModel->errorKeys[] = 'NAME_MISSING';
}
if ($category->priority === null || intval($category->priority) < 0 || intval($category->priority) > 3) {
$validationModel->errorKeys[] = 'INVALID_PRIORITY';
}
if ($category->autoAssign === null || !is_bool($category->autoAssign)) {
$validationModel->errorKeys[] = 'INVALID_AUTOASSIGN';
}
if ($category->displayBorder === null || !is_bool($category->displayBorder)) {
$validationModel->errorKeys[] = 'INVALID_DISPLAY_BORDER';
}
if ($category->type === null || (intval($category->type) !== 0 && intval($category->type) !== 1)) {
$validationModel->errorKeys[] = 'INVALID_TYPE';
}
return $validationModel;
}
/**
* @param $category Category
* @param $userContext
* @param $heskSettings array
* @return Category
* @throws ValidationException
* @throws \Exception When the category is missing
*/
function editCategory($category, $userContext, $heskSettings) {
$modsForHeskSettings = $this->modsForHeskSettingsGateway->getAllSettings($heskSettings);
$validationModel = $this->validate($category, $userContext, false);
if (count($validationModel->errorKeys) > 0) {
throw new ValidationException($validationModel);
}
$this->categoryGateway->updateCategory($category, $heskSettings);
$this->categoryGateway->resortAllCategories($heskSettings);
$allCategories = $this->categoryGateway->getAllCategories($heskSettings, $modsForHeskSettings);
foreach ($allCategories as $innerCategory) {
if ($innerCategory->id === $category->id) {
return $innerCategory;
}
}
throw new \BaseException("Category {$category->id} vanished! :O");
}
function deleteCategory($id, $userContext, $heskSettings) {
if (!$this->permissionChecker->doesUserHavePermission($userContext, UserPrivilege::CAN_MANAGE_CATEGORIES)) {
throw new AccessViolationException('User cannot manage categories!');
}
if ($id === 1) {
throw new \BaseException("Category 1 cannot be deleted!");
}
$this->ticketGateway->moveTicketsToDefaultCategory($id, $heskSettings);
$this->categoryGateway->deleteCategory($id, $heskSettings);
$this->categoryGateway->resortAllCategories($heskSettings);
}
function sortCategory($id, $direction, $heskSettings) {
$modsForHeskSettings = $this->modsForHeskSettingsGateway->getAllSettings($heskSettings);
$categories = $this->categoryGateway->getAllCategories($heskSettings, $modsForHeskSettings);
$category = null;
foreach ($categories as $innerCategory) {
if ($innerCategory->id === intval($id)) {
$category = $innerCategory;
break;
}
}
if ($category === null) {
throw new \BaseException("Could not find category with ID {$id}!");
}
if ($direction === Direction::UP) {
$category->catOrder -= 15;
} else {
$category->catOrder += 15;
}
$this->categoryGateway->updateCategory($category, $heskSettings);
$this->categoryGateway->resortAllCategories($heskSettings);
}
function getPublicCategories($heskSettings) {
$allCategories = $this->categoryGateway->getAllCategories($heskSettings, $this->modsForHeskSettingsGateway->getAllSettings($heskSettings));
$publicCategories = array();
foreach ($allCategories as $category) {
if ($category->type === 0) {
$publicCategories[] = $category;
}
}
return $publicCategories;
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace BusinessLogic\Categories;
use BusinessLogic\Security\UserContext;
use DataAccess\Categories\CategoryGateway;
use DataAccess\Settings\ModsForHeskSettingsGateway;
class CategoryRetriever extends \BaseClass {
/**
* @var CategoryGateway
*/
private $categoryGateway;
/**
* @var ModsForHeskSettingsGateway
*/
private $modsForHeskSettingsGateway;
function __construct(CategoryGateway $categoryGateway,
ModsForHeskSettingsGateway $modsForHeskSettingsGateway) {
$this->categoryGateway = $categoryGateway;
$this->modsForHeskSettingsGateway = $modsForHeskSettingsGateway;
}
/**
* @param $heskSettings array
* @param $userContext UserContext
* @return array
*/
function getAllCategories($heskSettings, $userContext) {
$modsForHeskSettings = $this->modsForHeskSettingsGateway->getAllSettings($heskSettings);
$categories = $this->categoryGateway->getAllCategories($heskSettings, $modsForHeskSettings);
foreach ($categories as $category) {
$category->accessible = $userContext->admin ||
in_array($category->id, $userContext->categories);
}
return $categories;
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace BusinessLogic;
class DateTimeHelpers {
static function heskDate($heskSettings, $dt = '', $isStr = true, $return_str = true) {
if (!$dt) {
$dt = time();
} elseif ($isStr) {
$dt = strtotime($dt);
}
// Return formatted date
return $return_str ? date($heskSettings['timeformat'], $dt) : $dt;
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace BusinessLogic\Emails;
class Addressees extends \BaseClass {
/**
* @var $to string[]
*/
public $to;
/**
* @var $cc string[]|null
*/
public $cc = array();
/**
* @var $bcc string[]|null
*/
public $bcc = array();
}

View File

@ -0,0 +1,84 @@
<?php
namespace BusinessLogic\Emails;
use BusinessLogic\Tickets\Attachment;
use BusinessLogic\Tickets\Ticket;
use PHPMailer;
class BasicEmailSender extends \BaseClass implements EmailSender {
function sendEmail($emailBuilder, $heskSettings, $modsForHeskSettings, $sendAsHtml) {
$toEmails = implode(',', $emailBuilder->to);
if (preg_match("/\n|\r|\t|%0A|%0D|%08|%09/", $toEmails . $emailBuilder->subject)) {
return false;
}
$mailer = new PHPMailer();
if ($heskSettings['smtp']) {
$mailer->isSMTP();
$mailer->SMTPAuth = true;
//-- We'll set this explicitly below if the user has it enabled.
$mailer->SMTPAutoTLS = false;
if ($heskSettings['smtp_ssl']) {
$mailer->SMTPSecure = "ssl";
} elseif ($heskSettings['smtp_tls']) {
$mailer->SMTPSecure = "tls";
}
$mailer->Host = $heskSettings['smtp_host_name'];
$mailer->Port = $heskSettings['smtp_host_port'];
$mailer->Username = $heskSettings['smtp_user'];
$mailer->Password = $heskSettings['smtp_password'];
}
$mailer->FromName = $heskSettings['noreply_name'] !== null &&
$heskSettings['noreply_name'] !== '' ? $heskSettings['noreply_name'] : '';
$mailer->From = $heskSettings['noreply_mail'];
if ($emailBuilder->to !== null) {
foreach ($emailBuilder->to as $to) {
$mailer->addAddress($to);
}
}
if ($emailBuilder->cc !== null) {
foreach ($emailBuilder->cc as $cc) {
$mailer->addCC($cc);
}
}
if ($emailBuilder->bcc !== null) {
foreach ($emailBuilder->bcc as $bcc) {
$mailer->addBCC($bcc);
}
}
$mailer->Subject = $emailBuilder->subject;
if ($sendAsHtml) {
$mailer->Body = $emailBuilder->htmlMessage;
$mailer->AltBody = $emailBuilder->message;
} else {
$mailer->Body = $emailBuilder->message;
$mailer->isHTML(false);
}
$mailer->Timeout = $heskSettings['smtp_timeout'];
if ($emailBuilder->attachments !== null) {
foreach ($emailBuilder->attachments as $attachment) {
$mailer->addAttachment(__DIR__ . '/../../../' . $heskSettings['attach_dir'] . '/' . $attachment->savedName,
$attachment->fileName);
}
}
if ($mailer->send()) {
return true;
}
return $mailer->ErrorInfo;
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace BusinessLogic\Emails;
use BusinessLogic\Tickets\Attachment;
class EmailBuilder extends \BaseClass {
/**
* @var $to string[]
*/
public $to;
/**
* @var $cc string[]
*/
public $cc;
/**
* @var $bcc string[]
*/
public $bcc;
/**
* @var $subject string
*/
public $subject;
/**
* @var $message string
*/
public $message;
/**
* @var $htmlMessage string
*/
public $htmlMessage;
/**
* @var $attachments Attachment[]
*/
public $attachments;
}

View File

@ -0,0 +1,21 @@
<?php
namespace BusinessLogic\Emails;
use BusinessLogic\Tickets\Attachment;
use BusinessLogic\Tickets\Ticket;
use PHPMailer;
interface EmailSender {
/**
* Use to send emails
*
* @param $emailBuilder EmailBuilder
* @param $heskSettings array
* @param $modsForHeskSettings array
* @param $sendAsHtml bool
* @return bool|string|\stdClass true if message sent successfully, string for PHPMail/Smtp error, stdClass for Mailgun error
*/
function sendEmail($emailBuilder, $heskSettings, $modsForHeskSettings, $sendAsHtml);
}

View File

@ -0,0 +1,76 @@
<?php
namespace BusinessLogic\Emails;
use BusinessLogic\Tickets\Ticket;
class EmailSenderHelper extends \BaseClass {
/**
* @var $emailTemplateParser EmailTemplateParser
*/
private $emailTemplateParser;
/**
* @var $basicEmailSender BasicEmailSender
*/
private $basicEmailSender;
/**
* @var $mailgunEmailSender MailgunEmailSender
*/
private $mailgunEmailSender;
function __construct(EmailTemplateParser $emailTemplateParser,
BasicEmailSender $basicEmailSender,
MailgunEmailSender $mailgunEmailSender) {
$this->emailTemplateParser = $emailTemplateParser;
$this->basicEmailSender = $basicEmailSender;
$this->mailgunEmailSender = $mailgunEmailSender;
}
/**
* @param $templateId int the EmailTemplateRetriever::TEMPLATE_NAME
* @param $language string the language name
* @param $addressees Addressees the addressees. **cc and bcc addresses from custom fields will be added here!**
* @param $ticket Ticket
* @param $heskSettings array
* @param $modsForHeskSettings array
*/
function sendEmailForTicket($templateId, $language, $addressees, $ticket, $heskSettings, $modsForHeskSettings) {
$languageCode = $heskSettings['languages'][$language]['folder'];
$parsedTemplate = $this->emailTemplateParser->getFormattedEmailForLanguage($templateId, $languageCode,
$ticket, $heskSettings, $modsForHeskSettings);
$emailBuilder = new EmailBuilder();
$emailBuilder->subject = $parsedTemplate->subject;
$emailBuilder->message = $parsedTemplate->message;
$emailBuilder->htmlMessage = $parsedTemplate->htmlMessage;
$emailBuilder->to = $addressees->to;
$emailBuilder->cc = $addressees->cc;
$emailBuilder->bcc = $addressees->bcc;
foreach ($heskSettings['custom_fields'] as $k => $v) {
$number = intval(str_replace('custom', '', $k));
if ($v['use'] && $v['type'] == 'email' && !empty($ticket->customFields[$number])) {
if ($v['value']['email_type'] == 'cc') {
$emailBuilder->cc[] = $ticket->customFields[$number];
} elseif ($v['value']['email_type'] == 'bcc') {
$emailBuilder->bcc[] = $ticket->customFields[$number];
}
}
}
if ($modsForHeskSettings['attachments']) {
$emailBuilder->attachments = $ticket->attachments;
}
if ($modsForHeskSettings['use_mailgun']) {
$this->mailgunEmailSender->sendEmail($emailBuilder, $heskSettings, $modsForHeskSettings, $modsForHeskSettings['html_emails']);
} else {
$this->basicEmailSender->sendEmail($emailBuilder, $heskSettings, $modsForHeskSettings, $modsForHeskSettings['html_emails']);
}
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace BusinessLogic\Emails;
class EmailTemplate extends \BaseClass {
/**
* @var $languageKey string
*/
public $languageKey;
/**
* @var $fileName string
*/
public $fileName;
/**
* @var $forStaff bool
*/
public $forStaff;
function __construct($forStaff, $fileName, $languageKey = null) {
$this->languageKey = $languageKey === null ? $fileName : $languageKey;
$this->fileName = $fileName;
$this->forStaff = $forStaff;
}
}

View File

@ -0,0 +1,385 @@
<?php
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;
use Core\Constants\Priority;
use DataAccess\Categories\CategoryGateway;
use DataAccess\Logging\LoggingGateway;
use DataAccess\Security\UserGateway;
use DataAccess\Statuses\StatusGateway;
class EmailTemplateParser extends \BaseClass {
/**
* @var $statusGateway StatusGateway
*/
private $statusGateway;
/**
* @var $categoryGateway CategoryGateway
*/
private $categoryGateway;
/**
* @var $userGateway UserGateway
*/
private $userGateway;
/**
* @var $emailTemplateRetriever EmailTemplateRetriever
*/
private $emailTemplateRetriever;
/**
* @var $logger LoggingGateway
*/
private $logger;
function __construct(StatusGateway $statusGateway,
CategoryGateway $categoryGateway,
UserGateway $userGateway,
EmailTemplateRetriever $emailTemplateRetriever,
LoggingGateway $loggingGateway) {
$this->statusGateway = $statusGateway;
$this->categoryGateway = $categoryGateway;
$this->userGateway = $userGateway;
$this->emailTemplateRetriever = $emailTemplateRetriever;
$this->logger = $loggingGateway;
}
/**
* @param $templateId int
* @param $languageCode string
* @param $ticket Ticket
* @param $heskSettings array
* @param $modsForHeskSettings array
* @return ParsedEmailProperties
* @throws InvalidEmailTemplateException
* @throws \Exception
*/
function getFormattedEmailForLanguage($templateId, $languageCode, $ticket, $heskSettings, $modsForHeskSettings) {
global $hesklang;
$emailTemplate = $this->emailTemplateRetriever->getTemplate($templateId);
if ($emailTemplate === null) {
throw new InvalidEmailTemplateException($templateId);
}
$template = self::getFromFileSystem($emailTemplate->fileName, $languageCode, false);
$htmlTemplate = self::getFromFileSystem($emailTemplate->fileName, $languageCode, true);
$subject = $hesklang[$emailTemplate->languageKey];
$fullLanguageName = null;
foreach ($heskSettings['languages'] as $key => $value) {
if ($value['folder'] === $languageCode) {
$fullLanguageName = $key;
break;
}
}
if ($fullLanguageName === null) {
throw new \BaseException("Language code {$languageCode} did not return any valid HESK languages!");
}
$subject = $this->parseSubject($subject, $ticket, $fullLanguageName, $heskSettings, $modsForHeskSettings);
$message = $this->parseMessage($template, $ticket, $fullLanguageName, $emailTemplate->forStaff, $heskSettings, $modsForHeskSettings, false);
$htmlMessage = $this->parseMessage($htmlTemplate, $ticket, $fullLanguageName, $emailTemplate->forStaff, $heskSettings, $modsForHeskSettings, true);
return new ParsedEmailProperties($subject, $message, $htmlMessage);
}
/**
* @param $template string
* @param $language string
* @param $html bool
* @return string The template
* @throws EmailTemplateNotFoundException If the template was not found in the filesystem for the provided language
*/
private function getFromFileSystem($template, $language, $html)
{
$htmlFolder = $html ? 'html/' : '';
/* Get email template */
$file = "language/{$language}/emails/{$htmlFolder}{$template}.txt";
$absoluteFilePath = __DIR__ . '/../../../' . $file;
if (file_exists($absoluteFilePath)) {
return file_get_contents($absoluteFilePath);
} else {
throw new EmailTemplateNotFoundException($template, $language);
}
}
/**
* @param $subjectTemplate string
* @param $ticket Ticket
* @param $language string
* @param $heskSettings array
* @return string
* @throws \Exception if common.inc.php isn't loaded
*/
private function parseSubject($subjectTemplate, $ticket, $language, $heskSettings, $modsForHeskSettings) {
global $hesklang;
if (!function_exists('hesk_msgToPlain')) {
throw new \BaseException("common.inc.php not loaded!");
}
if ($ticket === null) {
return $subjectTemplate;
}
// Status name and category name
$defaultStatus = $this->statusGateway->getStatusForDefaultAction(DefaultStatusForAction::NEW_TICKET, $heskSettings);
if (key_exists($language, $defaultStatus->localizedNames)) {
$statusName = $defaultStatus->localizedNames[$language];
} elseif (key_exists('English', $defaultStatus->localizedNames)) {
$statusName = $defaultStatus->localizedNames['English'];
$this->logger->logWarning('EmailTemplateParser', "No localized status found for status '{$defaultStatus->id}' and language '{$language}'. Defaulted to English.", "", new UserContext(), $heskSettings);
} else {
$statusName = "[ERROR: No localized status found for status '{$defaultStatus->id}']";
$this->logger->logError('EmailTemplateParser', "No localized status found for status '{$defaultStatus->id}'", "", new UserContext(), $heskSettings);
}
$categories = $this->categoryGateway->getAllCategories($heskSettings, $modsForHeskSettings);
$category = null;
foreach ($categories as $innerCategory) {
if ($innerCategory->id === $ticket->categoryId) {
$category = $innerCategory;
break;
}
}
switch ($ticket->priorityId) {
case Priority::CRITICAL:
$priority = $hesklang['critical'];
break;
case Priority::HIGH:
$priority = $hesklang['high'];
break;
case Priority::MEDIUM:
$priority = $hesklang['medium'];
break;
case Priority::LOW:
$priority = $hesklang['low'];
break;
default:
$priority = 'PRIORITY NOT FOUND';
break;
}
// Special tags
$subject = str_replace('%%SUBJECT%%', $ticket->subject, $subjectTemplate);
$subject = str_replace('%%TRACK_ID%%', $ticket->trackingId, $subject);
$subject = str_replace('%%CATEGORY%%', $category->id, $subject);
$subject = str_replace('%%PRIORITY%%', $priority, $subject);
$subject = str_replace('%%STATUS%%', $statusName, $subject);
return $subject;
}
/**
* @param $messageTemplate string
* @param $ticket Ticket
* @param $language string
* @param $heskSettings array
* @return string
* @throws \Exception if common.inc.php isn't loaded
*/
private function parseMessage($messageTemplate, $ticket, $language, $admin, $heskSettings, $modsForHeskSettings, $html) {
global $hesklang;
if (!function_exists('hesk_msgToPlain')) {
throw new \BaseException("common.inc.php not loaded!");
}
if ($ticket === null) {
return $messageTemplate;
}
$heskSettings['site_title'] = hesk_msgToPlain($heskSettings['site_title'], 1);
// Is email required to view ticket (for customers only)?
$heskSettings['e_param'] = $heskSettings['email_view_ticket'] ? '&e=' . rawurlencode(implode(';', $ticket->email)) : '';
/* Generate the ticket URLs */
$trackingURL = $heskSettings['hesk_url'];
$trackingURL .= $admin ? '/' . $heskSettings['admin_dir'] . '/admin_ticket.php' : '/ticket.php';
$trackingURL .= '?track=' . $ticket->trackingId . ($admin ? '' : $heskSettings['e_param']) . '&Refresh=' . rand(10000, 99999);
// Status name and category name
$defaultStatus = $this->statusGateway->getStatusForDefaultAction(DefaultStatusForAction::NEW_TICKET, $heskSettings);
$statusName = hesk_msgToPlain($defaultStatus->localizedNames[$language]);
$categories = $this->categoryGateway->getAllCategories($heskSettings, $modsForHeskSettings);
$category = null;
foreach ($categories as $innerCategory) {
if ($innerCategory->id === $ticket->categoryId) {
$category = $innerCategory;
break;
}
}
$category = hesk_msgToPlain($category->name);
$owner = $this->userGateway->getUserById($ticket->ownerId, $heskSettings);
$ownerName = $owner === null ? $hesklang['unas'] : hesk_msgToPlain($owner->name);
switch ($ticket->priorityId) {
case Priority::CRITICAL:
$priority = $hesklang['critical'];
break;
case Priority::HIGH:
$priority = $hesklang['high'];
break;
case Priority::MEDIUM:
$priority = $hesklang['medium'];
break;
case Priority::LOW:
$priority = $hesklang['low'];
break;
default:
$priority = 'PRIORITY NOT FOUND';
break;
}
// Special tags
$msg = str_replace('%%NAME%%', $ticket->name, $messageTemplate);
$msg = str_replace('%%SUBJECT%%', $ticket->subject, $msg);
$msg = str_replace('%%TRACK_ID%%', $ticket->trackingId, $msg);
$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);
$msg = str_replace('%%STATUS%%', $statusName, $msg);
$msg = str_replace('%%EMAIL%%', implode(';', $ticket->email), $msg);
$msg = str_replace('%%CREATED%%', $ticket->dateCreated, $msg);
$msg = str_replace('%%UPDATED%%', $ticket->lastChanged, $msg);
$msg = str_replace('%%ID%%', $ticket->id, $msg);
$msg = str_replace('%%TIME_WORKED%%', $ticket->timeWorked, $msg);
$lastReplyBy = '';
// Get the last reply by
if (!empty($ticket->lastReplier)) {
$lastReplyBy = $ticket->lastReplier;
} else {
$lastReplyBy = $ticket->name;
}
$msg = str_replace('%%LAST_REPLY_BY%%', $lastReplyBy, $msg);
/* All custom fields */
for ($i=1; $i<=50; $i++) {
$k = 'custom'.$i;
if (isset($heskSettings['custom_fields'][$k]) && isset($ticket->customFields[$i])) {
$v = $heskSettings['custom_fields'][$k];
switch ($v['type']) {
case 'checkbox':
$ticket->customFields[$i] = str_replace("<br>","\n",$ticket->customFields[$i]);
break;
case 'date':
$ticket->customFields[$i] = hesk_custom_date_display_format($ticket->customFields[$i], $v['value']['date_format']);
break;
}
$msg = str_replace('%%'.strtoupper($k).'%%',stripslashes($ticket->customFields[$i]),$msg);
} else {
$msg = str_replace('%%'.strtoupper($k).'%%','',$msg);
}
}
// Is message tag in email template?
if (strpos($msg, '%%MESSAGE%%') !== false) {
// Replace message
if ($html) {
$htmlMessage = html_entity_decode($ticket->message);
$htmlMessage = nl2br($htmlMessage);
$msg = str_replace('%%MESSAGE%%', $htmlMessage, $msg);
} else {
$plainTextMessage = $ticket->message;
$messageHtml = $ticket->usesHtml;
if (count($ticket->replies) > 0) {
$lastReply = end($ticket->replies);
$messageHtml = $lastReply->usesHtml;
}
if ($messageHtml) {
if (!function_exists('convert_html_to_text')) {
require(__DIR__ . '/../../../inc/html2text/html2text.php');
}
$plainTextMessage = convert_html_to_text($plainTextMessage);
$plainTextMessage = fix_newlines($plainTextMessage);
}
$msg = str_replace('%%MESSAGE%%', $plainTextMessage, $msg);
}
// Add direct links to any attachments at the bottom of the email message
if ($heskSettings['attachments']['use'] && isset($ticket->attachments) && count($ticket->attachments) > 0) {
if (!$modsForHeskSettings['attachments']) {
if ($html) {
$msg .= "<br><br><br>" . $hesklang['fatt'];
} else {
$msg .= "\n\n\n" . $hesklang['fatt'];
}
foreach ($ticket->attachments as $attachment) {
if ($html) {
$msg .= "<br><br>{$attachment->fileName}<br>";
} else {
$msg .= "\n\n{$attachment->fileName}\n";
}
$msg .= "{$heskSettings['hesk_url']}/download_attachment.php?att_id={$attachment->id}&track={$ticket->trackingId}{$heskSettings['e_param']}";
}
}
}
// For customer notifications: if we allow email piping/pop 3 fetching and
// stripping quoted replies add an "reply above this line" tag
if (!$admin && ($heskSettings['email_piping'] || $heskSettings['pop3']) && $heskSettings['strip_quoted']) {
$msg = $hesklang['EMAIL_HR'] . "\n\n" . $msg;
}
} elseif (strpos($msg, '%%MESSAGE_NO_ATTACHMENTS%%') !== false) {
if ($html) {
$htmlMessage = nl2br($ticket->message);
$msg = str_replace('%%MESSAGE_NO_ATTACHMENTS%%', $htmlMessage, $msg);
} else {
$plainTextMessage = $ticket->message;
$messageHtml = $ticket->usesHtml;
if (count($ticket->replies) > 0) {
$lastReply = end($ticket->replies);
$messageHtml = $lastReply->usesHtml;
}
if ($messageHtml) {
if (!function_exists('convert_html_to_text')) {
require(__DIR__ . '/../../../inc/html2text/html2text.php');
}
$plainTextMessage = convert_html_to_text($plainTextMessage);
$plainTextMessage = fix_newlines($plainTextMessage);
}
$msg = str_replace('%%MESSAGE_NO_ATTACHMENTS%%', $plainTextMessage, $msg);
}
}
return $msg;
}
}

View File

@ -0,0 +1,65 @@
<?php
namespace BusinessLogic\Emails;
class EmailTemplateRetriever extends \BaseClass {
/**
* @var $validTemplates EmailTemplate[]
*/
private $validTemplates;
function __construct() {
$this->validTemplates = array();
$this->initializeArray();
}
const FORGOT_TICKET_ID = 0;
const NEW_REPLY_BY_STAFF = 1;
const NEW_TICKET = 2;
const VERIFY_EMAIL = 3;
const TICKET_CLOSED = 4;
const CATEGORY_MOVED = 5;
const NEW_REPLY_BY_CUSTOMER = 6;
const NEW_TICKET_STAFF = 7;
const TICKET_ASSIGNED_TO_YOU = 8;
const NEW_PM = 9;
const NEW_NOTE = 10;
const RESET_PASSWORD = 11;
const CALENDAR_REMINDER = 12;
const OVERDUE_TICKET = 13;
function initializeArray() {
if (count($this->validTemplates) > 0) {
//-- Map already built
return;
}
$this->validTemplates[self::FORGOT_TICKET_ID] = new EmailTemplate(false, 'forgot_ticket_id');
$this->validTemplates[self::NEW_REPLY_BY_STAFF] = new EmailTemplate(false, 'new_reply_by_staff');
$this->validTemplates[self::NEW_TICKET] = new EmailTemplate(false, 'new_ticket', 'ticket_received');
$this->validTemplates[self::VERIFY_EMAIL] = new EmailTemplate(false, 'verify_email');
$this->validTemplates[self::TICKET_CLOSED] = new EmailTemplate(false, 'ticket_closed');
$this->validTemplates[self::CATEGORY_MOVED] = new EmailTemplate(true, 'category_moved');
$this->validTemplates[self::NEW_REPLY_BY_CUSTOMER] = new EmailTemplate(true, 'new_reply_by_customer');
$this->validTemplates[self::NEW_TICKET_STAFF] = new EmailTemplate(true, 'new_ticket_staff');
$this->validTemplates[self::TICKET_ASSIGNED_TO_YOU] = new EmailTemplate(true, 'ticket_assigned_to_you');
$this->validTemplates[self::NEW_PM] = new EmailTemplate(true, 'new_pm');
$this->validTemplates[self::NEW_NOTE] = new EmailTemplate(true, 'new_note');
$this->validTemplates[self::RESET_PASSWORD] = new EmailTemplate(true, 'reset_password');
$this->validTemplates[self::CALENDAR_REMINDER] = new EmailTemplate(true, 'reset_password');
$this->validTemplates[self::OVERDUE_TICKET] = new EmailTemplate(true, 'overdue_ticket');
}
/**
* @param $templateId
* @return EmailTemplate|null
*/
function getTemplate($templateId) {
if (isset($this->validTemplates[$templateId])) {
return $this->validTemplates[$templateId];
}
return null;
}
}

View File

@ -0,0 +1,73 @@
<?php
namespace BusinessLogic\Emails;
use BusinessLogic\Tickets\Attachment;
use BusinessLogic\Tickets\Ticket;
use Mailgun\Mailgun;
class MailgunEmailSender extends \BaseClass implements EmailSender {
function sendEmail($emailBuilder, $heskSettings, $modsForHeskSettings, $sendAsHtml) {
$mailgunArray = array();
$mailgunArray['from'] = $heskSettings['noreply_mail']; // Email Address
if ($heskSettings['noreply_name'] !== null && $heskSettings['noreply_name'] !== '') {
$mailgunArray['from'] = "{$heskSettings['noreply_name']} <{$heskSettings['noreply_mail']}>"; // Name and address
}
$mailgunArray['to'] = implode(',', $emailBuilder->to);
if ($emailBuilder->cc !== null && count($emailBuilder->cc) > 0) {
$mailgunArray['cc'] = implode(',', $emailBuilder->cc);
}
if ($emailBuilder->bcc !== null && count($emailBuilder->bcc) > 0) {
$mailgunArray['bcc'] = implode(',', $emailBuilder->bcc);
}
$mailgunArray['subject'] = $emailBuilder->subject;
$mailgunArray['text'] = $emailBuilder->message;
if ($sendAsHtml) {
$mailgunArray['html'] = $emailBuilder->htmlMessage;
}
$mailgunAttachments = array();
if ($emailBuilder->attachments !== null) {
foreach ($emailBuilder->attachments as $attachment) {
$mailgunAttachments[] = array(
'remoteName' => $attachment->fileName,
'filePath' => __DIR__ . '/../../../' . $heskSettings['attach_dir'] . '/' . $attachment->savedName
);
}
}
$result = $this->sendMessage($mailgunArray, $mailgunAttachments, $modsForHeskSettings);
if (isset($result->http_response_code)
&& $result->http_response_code === 200) {
return true;
}
return $result;
}
private function sendMessage($mailgunArray, $attachments, $modsForHeskSettings) {
$ssl = !defined('NO_MAILGUN_SSL');
$messageClient = new Mailgun($modsForHeskSettings['mailgun_api_key'], 'api.mailgun.net', 'v2', $ssl);
$mailgunAttachments = array();
if (count($attachments) > 0) {
$mailgunAttachments = array(
'attachment' => $attachments
);
}
$result = $messageClient->sendMessage($modsForHeskSettings['mailgun_domain'], $mailgunArray, $mailgunAttachments);
return $result;
}
}

View File

@ -0,0 +1,27 @@
<?php
namespace BusinessLogic\Emails;
class ParsedEmailProperties extends \BaseClass {
function __construct($subject, $message, $htmlMessage) {
$this->subject = $subject;
$this->message = $message;
$this->htmlMessage = $htmlMessage;
}
/**
* @var $subject string
*/
public $subject;
/**
* @var $message string
*/
public $message;
/**
* @var $htmlMessage string
*/
public $htmlMessage;
}

View File

@ -0,0 +1,10 @@
<?php
namespace BusinessLogic\Exceptions;
class AccessViolationException extends ApiFriendlyException {
function __construct($message) {
parent::__construct($message, 'Access Exception', 403);
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace BusinessLogic\Exceptions;
use Exception;
class ApiFriendlyException extends \BaseException {
public $title;
public $httpResponseCode;
/**
* ApiFriendlyException constructor.
* @param string $message
* @param string $title
* @param int $httpResponseCode
*/
function __construct($message, $title, $httpResponseCode) {
$this->title = $title;
$this->httpResponseCode = $httpResponseCode;
parent::__construct($message);
}
}

View File

@ -0,0 +1,17 @@
<?php
/**
* Created by PhpStorm.
* User: mkoch
* Date: 2/22/2017
* Time: 10:00 PM
*/
namespace BusinessLogic\Exceptions;
class EmailTemplateNotFoundException extends ApiFriendlyException {
function __construct($emailTemplate, $language) {
parent::__construct(sprintf("The email template '%s' was not found for the language '%s'", $emailTemplate, $language),
'Email Template Not Found!', 400);
}
}

View File

@ -0,0 +1,10 @@
<?php
namespace BusinessLogic\Exceptions;
class InternalUseOnlyException extends ApiFriendlyException {
function __construct() {
parent::__construct("This endpoint can only be used internally", "Internal Use Only", 401);
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace BusinessLogic\Exceptions;
class InvalidAuthenticationTokenException extends ApiFriendlyException {
public function __construct() {
parent::__construct('The X-Auth-Token is invalid. The token must be for an active helpdesk user.',
'Security Exception',
401);
}
}

View File

@ -0,0 +1,16 @@
<?php
/**
* Created by PhpStorm.
* User: mkoch
* Date: 2/23/2017
* Time: 8:13 PM
*/
namespace BusinessLogic\Exceptions;
class InvalidEmailTemplateException extends ApiFriendlyException {
function __construct($template) {
parent::__construct(sprintf("The email template '%s' is invalid", $template), 'Invalid Email Template', 400);
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace BusinessLogic\Exceptions;
class MissingAuthenticationTokenException extends ApiFriendlyException {
function __construct() {
parent::__construct("An 'X-Auth-Token' is required for this request",
'Security Exception',
401);
}
}

View File

@ -0,0 +1,16 @@
<?php
/**
* Created by PhpStorm.
* User: cokoch
* Date: 5/2/2017
* Time: 12:28 PM
*/
namespace BusinessLogic\Exceptions;
class SessionNotActiveException extends ApiFriendlyException {
function __construct() {
parent::__construct("You must be logged in to call internal API methods", "Authentication Required", 401);
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace BusinessLogic\Exceptions;
use BusinessLogic\ValidationModel;
use Exception;
class ValidationException extends ApiFriendlyException {
/**
* ValidationException constructor.
* @param ValidationModel $validationModel The validation model
* @throws Exception If the validationModel's errorKeys is empty
*/
function __construct($validationModel) {
if (count($validationModel->errorKeys) === 0) {
throw new Exception('Tried to throw a ValidationException, but the validation model was valid or had 0 error keys!');
}
parent::__construct(implode(",", $validationModel->errorKeys), "Validation Failed. Error keys are available in the message section.", 400);
}
}

View File

@ -0,0 +1,244 @@
<?php
namespace BusinessLogic;
class Helpers extends \BaseClass {
static function getHeader($key) {
$headers = getallheaders();
$uppercaseHeaders = array();
foreach ($headers as $header => $value) {
$uppercaseHeaders[strtoupper($header)] = $value;
}
return isset($uppercaseHeaders[$key])
? $uppercaseHeaders[$key]
: NULL;
}
static function hashToken($token) {
return hash('sha512', $token);
}
static function safeArrayGet($array, $key) {
return $array !== null && array_key_exists($key, $array)
? $array[$key]
: null;
}
static function boolval($val) {
return $val == true;
}
static function heskHtmlSpecialCharsDecode($in) {
return str_replace(array('&amp;', '&lt;', '&gt;', '&quot;'), 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',
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',
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\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&amp;)+)@((((([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',
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<a href=\"$url\" target=\"blank\" $class>$text</a>$append";
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);
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace BusinessLogic\Navigation;
class CustomNavElement extends \BaseClass {
/* @var $id int*/
public $id;
/* @var $text string[] */
public $text;
/* @var $subtext string[]|null */
public $subtext;
/* @var $imageUrl string|null */
public $imageUrl;
/* @var $fontIcon string|null */
public $fontIcon;
/* @var $place int */
public $place;
/* @var $url string */
public $url;
/* @var $sort int */
public $sort;
}

View File

@ -0,0 +1,70 @@
<?php
namespace BusinessLogic\Navigation;
// TODO Test!
use BusinessLogic\Exceptions\ApiFriendlyException;
use DataAccess\Navigation\CustomNavElementGateway;
class CustomNavElementHandler extends \BaseClass {
/* @var $customNavElementGateway CustomNavElementGateway */
private $customNavElementGateway;
function __construct(CustomNavElementGateway $customNavElementGateway) {
$this->customNavElementGateway = $customNavElementGateway;
}
function getAllCustomNavElements($heskSettings) {
return $this->customNavElementGateway->getAllCustomNavElements($heskSettings);
}
function getCustomNavElement($id, $heskSettings) {
$elements = $this->getAllCustomNavElements($heskSettings);
foreach ($elements as $element) {
if ($element->id === intval($id)) {
return output($element);
}
}
throw new ApiFriendlyException("Custom nav element {$id} not found!", "Element Not Found", 404);
}
function deleteCustomNavElement($id, $heskSettings) {
$this->customNavElementGateway->deleteCustomNavElement($id, $heskSettings);
$this->customNavElementGateway->resortAllElements($heskSettings);
}
function saveCustomNavElement($element, $heskSettings) {
$this->customNavElementGateway->saveCustomNavElement($element, $heskSettings);
}
function createCustomNavElement($element, $heskSettings) {
$element = $this->customNavElementGateway->createCustomNavElement($element, $heskSettings);
$this->customNavElementGateway->resortAllElements($heskSettings);
return $element;
}
function sortCustomNavElement($elementId, $direction, $heskSettings) {
/* @var $element CustomNavElement */
$elements = $this->customNavElementGateway->getAllCustomNavElements($heskSettings);
$elementToChange = null;
foreach ($elements as $element) {
if ($element->id === intval($elementId)) {
$elementToChange = $element;
}
}
if ($direction === Direction::UP) {
$elementToChange->sort -= 15;
} else {
$elementToChange->sort += 15;
}
$this->customNavElementGateway->saveCustomNavElement($elementToChange, $heskSettings);
$this->customNavElementGateway->resortAllElements($heskSettings);
}
}

View File

@ -0,0 +1,10 @@
<?php
namespace BusinessLogic\Navigation;
class CustomNavElementPlace extends \BaseClass {
const HOMEPAGE_BLOCK = 1;
const CUSTOMER_NAVIGATION = 2;
const ADMIN_NAVIGATION = 3;
}

View File

@ -0,0 +1,9 @@
<?php
namespace BusinessLogic\Navigation;
class Direction extends \BaseClass {
const UP = 'up';
const DOWN = 'down';
}

View File

@ -0,0 +1,52 @@
<?php
namespace BusinessLogic\Security;
use DataAccess\Security\BanGateway;
class BanRetriever extends \BaseClass {
/**
* @var BanGateway
*/
private $banGateway;
function __construct(BanGateway $banGateway) {
$this->banGateway = $banGateway;
}
/**
* @param $email
* @param $heskSettings
* @return bool
*/
function isEmailBanned($email, $heskSettings) {
$bannedEmails = $this->banGateway->getEmailBans($heskSettings);
foreach ($bannedEmails as $bannedEmail) {
if ($bannedEmail->email === $email) {
return true;
}
}
return false;
}
/**
* @param $ip int the IP address, converted beforehand using ip2long()
* @param $heskSettings
* @return bool
*/
function isIpAddressBanned($ip, $heskSettings) {
$bannedIps = $this->banGateway->getIpBans($heskSettings);
foreach ($bannedIps as $bannedIp) {
if ($bannedIp->ipFrom <= $ip && $bannedIp->ipTo >= $ip) {
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace BusinessLogic\Security;
class BannedEmail extends \BaseClass {
/**
* @var int
*/
public $id;
/**
* @var string
*/
public $email;
/**
* @var int|null The user who banned the email, or null if the user was deleted
*/
public $bannedById;
/**
* @var string
*/
public $dateBanned;
}

View File

@ -0,0 +1,36 @@
<?php
namespace BusinessLogic\Security;
class BannedIp extends \BaseClass {
/**
* @var int
*/
public $id;
/**
* @var int the lower bound of the IP address range
*/
public $ipFrom;
/**
* @var int the upper bound of the IP address range
*/
public $ipTo;
/**
* @var string the display of the IP ban to be shown to the user
*/
public $ipDisplay;
/**
* @var int|null The user who banned the IP, or null if the user was deleted
*/
public $bannedById;
/**
* @var string
*/
public $dateBanned;
}

View File

@ -0,0 +1,23 @@
<?php
namespace BusinessLogic\Security;
class PermissionChecker extends \BaseClass {
/**
* @param $userContext UserContext
* @param $permission string
* @return bool
*/
function doesUserHavePermission($userContext, $permission) {
if ($userContext->admin) {
return true;
}
if (in_array($permission, $userContext->permissions)) {
return true;
}
return false;
}
}

View File

@ -0,0 +1,131 @@
<?php
namespace BusinessLogic\Security;
use BusinessLogic\Helpers;
class UserContext extends \BaseClass {
/* @var $id int */
public $id;
/* @var $username string */
public $username;
/* @var $admin bool */
public $admin;
/* @var $name string */
public $name;
/* @var $email string */
public $email;
/* @var $signature string */
public $signature;
/* @var $language string|null */
public $language;
/* @var $categories int[] */
public $categories;
/* @var $permissions string[] */
public $permissions;
/* @var UserContextPreferences */
public $preferences;
/* @var UserContextNotifications */
public $notificationSettings;
/* @var $autoAssign bool */
public $autoAssign;
/* @var $ratingNegative int */
public $ratingNegative;
/* @var $ratingPositive int */
public $ratingPositive;
/* @var $rating float */
public $rating;
/* @var $totalNumberOfReplies int */
public $totalNumberOfReplies;
/* @var $active bool */
public $active;
function isAnonymousUser() {
return $this->id === -1;
}
static function buildAnonymousUser() {
$userContext = new UserContext();
$userContext->id = -1;
$userContext->username = "API - ANONYMOUS USER"; // Usernames can't have spaces, so no one will take this username
$userContext->admin = false;
$userContext->name = "ANONYMOUS USER";
$userContext->email = "anonymous-user@example.com";
$userContext->categories = array();
$userContext->permissions = array();
$userContext->autoAssign = false;
$userContext->active = true;
return $userContext;
}
/**
* Builds a user context based on the current session. **The session must be active!**
* @param $dataRow array the $_SESSION superglobal or the hesk_users result set
* @return UserContext the built user context
*/
static function fromDataRow($dataRow) {
$userContext = new UserContext();
$userContext->id = intval($dataRow['id']);
$userContext->username = $dataRow['user'];
$userContext->admin = Helpers::boolval($dataRow['isadmin']);
$userContext->name = $dataRow['name'];
$userContext->email = $dataRow['email'];
$userContext->signature = $dataRow['signature'];
$userContext->language = $dataRow['language'];
if (is_array($dataRow['categories'])) {
$userContext->categories = $dataRow['categories'];
} else {
$userContext->categories = explode(',', $dataRow['categories']);
}
$userContext->permissions = explode(',', $dataRow['heskprivileges']);
$userContext->autoAssign = Helpers::boolval($dataRow['autoassign']);
$userContext->ratingNegative = intval($dataRow['ratingneg']);
$userContext->ratingPositive = intval($dataRow['ratingpos']);
$userContext->rating = floatval($dataRow['rating']);
$userContext->totalNumberOfReplies = intval($dataRow['replies']);
$userContext->active = Helpers::boolval($dataRow['active']);
$preferences = new UserContextPreferences();
$preferences->afterReply = intval($dataRow['afterreply']);
$preferences->autoStartTimeWorked = Helpers::boolval($dataRow['autostart']);
$preferences->autoreload = intval($dataRow['autoreload']);
$preferences->defaultNotifyCustomerNewTicket = Helpers::boolval($dataRow['notify_customer_new']);
$preferences->defaultNotifyCustomerReply = Helpers::boolval($dataRow['notify_customer_reply']);
$preferences->showSuggestedKnowledgebaseArticles = Helpers::boolval($dataRow['show_suggested']);
$preferences->defaultCalendarView = intval($dataRow['default_calendar_view']);
$preferences->defaultTicketView = $dataRow['default_list'];
$userContext->preferences = $preferences;
$notifications = new UserContextNotifications();
$notifications->newUnassigned = Helpers::boolval($dataRow['notify_new_unassigned']);
$notifications->newAssignedToMe = Helpers::boolval($dataRow['notify_new_my']);
$notifications->replyUnassigned = Helpers::boolval($dataRow['notify_reply_unassigned']);
$notifications->replyToMe = Helpers::boolval($dataRow['notify_reply_my']);
$notifications->ticketAssignedToMe = Helpers::boolval($dataRow['notify_assigned']);
$notifications->privateMessage = Helpers::boolval($dataRow['notify_pm']);
$notifications->noteOnTicketAssignedToMe = Helpers::boolval($dataRow['notify_note']);
$notifications->noteOnTicketNotAssignedToMe = Helpers::boolval($dataRow['notify_note_unassigned']);
$notifications->overdueTicketUnassigned = Helpers::boolval($dataRow['notify_overdue_unassigned']);
$userContext->notificationSettings = $notifications;
return $userContext;
}
}

View File

@ -0,0 +1,87 @@
<?php
namespace BusinessLogic\Security;
use BusinessLogic\Exceptions\InvalidAuthenticationTokenException;
use BusinessLogic\Exceptions\MissingAuthenticationTokenException;
use BusinessLogic\Helpers;
use DataAccess\Security\UserGateway;
class UserContextBuilder extends \BaseClass {
/**
* @var UserGateway
*/
private $userGateway;
function __construct(UserGateway $userGateway) {
$this->userGateway = $userGateway;
}
function buildUserContext($authToken, $heskSettings) {
$NULL_OR_EMPTY_STRING = 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e';
$hashedToken = Helpers::hashToken($authToken);
if ($hashedToken === $NULL_OR_EMPTY_STRING) {
throw new MissingAuthenticationTokenException();
}
$userRow = $this->userGateway->getUserForAuthToken($hashedToken, $heskSettings);
if ($userRow === null) {
throw new InvalidAuthenticationTokenException();
}
return UserContext::fromDataRow($userRow);
}
/**
* Builds a user context based on the current session. **The session must be active!**
* @param $dataRow array the $_SESSION superglobal or the hesk_users result set
* @return UserContext the built user context
*/
function fromDataRow($dataRow) {
$userContext = new UserContext();
$userContext->id = $dataRow['id'];
$userContext->username = $dataRow['user'];
$userContext->admin = $dataRow['isadmin'];
$userContext->name = $dataRow['name'];
$userContext->email = $dataRow['email'];
$userContext->signature = $dataRow['signature'];
$userContext->language = $dataRow['language'];
$userContext->categories = explode(',', $dataRow['categories']);
$userContext->permissions = explode(',', $dataRow['heskprivileges']);
$userContext->autoAssign = $dataRow['autoassign'];
$userContext->ratingNegative = $dataRow['ratingneg'];
$userContext->ratingPositive = $dataRow['ratingpos'];
$userContext->rating = $dataRow['rating'];
$userContext->totalNumberOfReplies = $dataRow['replies'];
$userContext->active = $dataRow['active'];
$preferences = new UserContextPreferences();
$preferences->afterReply = $dataRow['afterreply'];
$preferences->autoStartTimeWorked = $dataRow['autostart'];
$preferences->autoreload = $dataRow['autoreload'];
$preferences->defaultNotifyCustomerNewTicket = $dataRow['notify_customer_new'];
$preferences->defaultNotifyCustomerReply = $dataRow['notify_customer_reply'];
$preferences->showSuggestedKnowledgebaseArticles = $dataRow['show_suggested'];
$preferences->defaultCalendarView = $dataRow['default_calendar_view'];
$preferences->defaultTicketView = $dataRow['default_list'];
$userContext->preferences = $preferences;
$notifications = new UserContextNotifications();
$notifications->newUnassigned = $dataRow['notify_new_unassigned'];
$notifications->newAssignedToMe = $dataRow['notify_new_my'];
$notifications->replyUnassigned = $dataRow['notify_reply_unassigned'];
$notifications->replyToMe = $dataRow['notify_reply_my'];
$notifications->ticketAssignedToMe = $dataRow['notify_assigned'];
$notifications->privateMessage = $dataRow['notify_pm'];
$notifications->noteOnTicketAssignedToMe = $dataRow['notify_note'];
$notifications->noteOnTicketNotAssignedToMe = $dataRow['notify_note_unassigned'];
$notifications->overdueTicketUnassigned = $dataRow['notify_overdue_unassigned'];
$userContext->notificationSettings = $notifications;
return $userContext;
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace BusinessLogic\Security;
class UserContextNotifications extends \BaseClass {
public $newUnassigned;
public $newAssignedToMe;
public $replyUnassigned;
public $replyToMe;
public $ticketAssignedToMe;
public $privateMessage;
public $noteOnTicketAssignedToMe;
public $noteOnTicketNotAssignedToMe;
public $overdueTicketUnassigned;
}

View File

@ -0,0 +1,15 @@
<?php
namespace BusinessLogic\Security;
class UserContextPreferences extends \BaseClass {
public $afterReply;
public $autoStartTimeWorked;
public $autoreload;
public $defaultNotifyCustomerNewTicket;
public $defaultNotifyCustomerReply;
public $showSuggestedKnowledgebaseArticles;
public $defaultCalendarView;
public $defaultTicketView;
}

View File

@ -0,0 +1,23 @@
<?php
/**
* Created by PhpStorm.
* User: mkoch
* Date: 3/12/2017
* Time: 12:11 PM
*/
namespace BusinessLogic\Security;
class UserPrivilege extends \BaseClass {
const CAN_VIEW_TICKETS = 'can_view_tickets';
const CAN_REPLY_TO_TICKETS = 'can_reply_tickets';
const CAN_EDIT_TICKETS = 'can_edit_tickets';
const CAN_DELETE_TICKETS = 'can_del_tickets';
const CAN_MANAGE_CATEGORIES = 'can_man_cat';
const CAN_VIEW_ASSIGNED_TO_OTHER = 'can_view_ass_others';
const CAN_VIEW_UNASSIGNED = 'can_view_unassigned';
const CAN_VIEW_ASSIGNED_BY_ME = 'can_view_ass_by';
const CAN_MANAGE_SERVICE_MESSAGES = 'can_service_msg';
const CAN_CHANGE_DUE_DATE = 'can_change_due_date';
}

Some files were not shown because too many files have changed in this diff Show More