Skip to content

Commit

Permalink
Merge branch 'master' of github.com:freescout-helpdesk/freescout into…
Browse files Browse the repository at this point in the history
… dist
  • Loading branch information
freescout-help-desk committed Jan 5, 2024
2 parents 85954ab + a5f4908 commit 7d035f5
Show file tree
Hide file tree
Showing 25 changed files with 336 additions and 86 deletions.
5 changes: 2 additions & 3 deletions app/Attachment.php
Original file line number Diff line number Diff line change
Expand Up @@ -418,9 +418,8 @@ public static function deleteAttachments($attachments)
public function duplicate($thread_id = null)
{
$new_attachment = $this->replicate();
if ($thread_id) {
$new_attachment->thread_id = $thread_id;
}

$new_attachment->thread_id = $thread_id;

$new_attachment->save();

Expand Down
2 changes: 1 addition & 1 deletion app/Console/Commands/CleanTmp.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function __construct()
*/
public function handle()
{
shell_exec('find '.\Helper::getTempDir().' -mtime +7 -type f -name '.\Helper::getTempFilePrefix().'* -exec rm -r -f {} \;');
\Helper::shellExec('find '.\Helper::getTempDir().' -mtime +7 -type f -name '.\Helper::getTempFilePrefix().'* -exec rm -r -f {} \;');

$this->comment("Done");
}
Expand Down
16 changes: 14 additions & 2 deletions app/Console/Commands/FetchEmails.php
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ public function processMessage($message, $message_id, $mailbox, $mailboxes, $ext
$body = $message->getTextBody() ?? '';
$body = htmlspecialchars($body);
}
$body = $this->separateReply($body, $is_html, $is_reply, !$message_from_customer);
$body = $this->separateReply($body, $is_html, $is_reply, !$message_from_customer, ($message_from_customer ? $prev_thread->getMessageId($mailbox) : ''));

// We have to fetch absolutely all emails, even with empty body.
// if (!$body) {
Expand Down Expand Up @@ -1238,7 +1238,7 @@ public function processAttachmentName($name)
*
* @return string
*/
public function separateReply($body, $is_html, $is_reply, $user_reply_to_notification = false)
public function separateReply($body, $is_html, $is_reply, $user_reply_to_notification = false, $prev_message_id = '')
{
$cmp_reply_length_desc = function ($a, $b) {
if (mb_strlen($a) == mb_strlen($b)) {
Expand Down Expand Up @@ -1301,6 +1301,18 @@ public function separateReply($body, $is_html, $is_reply, $user_reply_to_notific
$reply_separators = [\MailHelper::REPLY_SEPARATOR_NOTIFICATION];
}

// Try to separate customer reply using hashed reply separator.
// In this case some extra text may appear below customer's reply:
// On Thu, Jan 4, 2024 at 8:41 AM John Doe | Demo <[email protected]> wrote:
if (config('app.alternative_reply_separation')) {
if (!$user_reply_to_notification && $prev_message_id) {
$hashed_reply_separator = \MailHelper::getHashedReplySeparator($prev_message_id);
if (strstr($result, $hashed_reply_separator)) {
$reply_separators = [$hashed_reply_separator];
}
}
}

foreach ($reply_separators as $reply_separator) {
if (\Str::startsWith($reply_separator, 'regex:')) {
$regex = preg_replace("/^regex:/", '', $reply_separator);
Expand Down
80 changes: 79 additions & 1 deletion app/Http/Controllers/ConversationsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -403,13 +403,14 @@ public function create(Request $request, $mailbox_id)

// Create conversation from thread
$thread = null;
$attachments = [];
if (!empty($request->from_thread_id)) {
$orig_thread = Thread::find($request->from_thread_id);
if ($orig_thread) {
$subject = $orig_thread->conversation->subject;
$subject = preg_replace('/^Fwd:/i', 'Re: ', $subject);

$thread = new \App\Thread();
$thread = new Thread();
$thread->body = $orig_thread->body;
// If this is a forwarded message, try to fetch From
preg_match_all("/From:[^<\n]+<([^<\n]+)>/m", html_entity_decode(strip_tags($thread->body)), $m);
Expand All @@ -422,6 +423,17 @@ public function create(Request $request, $mailbox_id)
}
}
}

// Clone attachments.
$orig_attachments = Attachment::where('thread_id', $orig_thread->id)->get();

if (count($orig_attachments)) {
$conversation->has_attachments = true;
$thread->has_attachments = true;
foreach ($orig_attachments as $attachment) {
$attachments[] = $attachment->duplicate();
}
}
}
}

Expand All @@ -443,6 +455,7 @@ public function create(Request $request, $mailbox_id)
'after_send' => $after_send,
'to' => $to,
'from_aliases' => $mailbox->getAliases(true, true),
'attachments' => $attachments,
]);
}

Expand Down Expand Up @@ -1742,6 +1755,14 @@ public function ajax(Request $request)
// Conversations navigation
case 'conversations_pagination':
if (!empty($request->filter)) {
// Filter conversations by Assigned To column in Search.
if (!empty($request->params['user_id']) && !empty($request->filter['f'])) {
$filter = $request->filter ?? [];
$filter['f']['assigned'] = (int)$request->params['user_id'];

$request->merge(['filter' => $filter]);
}

$response = $this->ajaxConversationsFilter($request, $response, $user);
} else {
$response = $this->ajaxConversationsPagination($request, $response, $user);
Expand Down Expand Up @@ -2374,6 +2395,8 @@ public function ajaxHtml(Request $request)
return $this->ajaxHtmlMoveConv();
case 'merge_conv':
return $this->ajaxHtmlMergeConv();
case 'assignee_filter':
return $this->ajaxAssigneeFilter();
case 'default_redirect':
return $this->ajaxHtmlDefaultRedirect();
}
Expand Down Expand Up @@ -2558,6 +2581,50 @@ public function ajaxHtmlMergeConv()
]);
}

/**
* Filter conversations by assignee.
*/
public function ajaxAssigneeFilter()
{
$users = collect([]);

$mailbox_id = Input::get('mailbox_id');
$user_id = Input::get('user_id');

$user = auth()->user();

if ($mailbox_id) {

$mailbox = Mailbox::find($mailbox_id);
if (!$mailbox) {
abort(404);
}
if (!$user->can('view', $mailbox)) {
\Helper::denyAccess();
}
// Show users having access to the mailbox.
$users = $mailbox->usersAssignable();
} else {
// Show users from all accessible mailboxes.
$mailboxes = $user->mailboxesCanView();
foreach ($mailboxes as $mailbox) {
$users = $users->merge($mailbox->usersAssignable())->unique('id');
}
}

if (!$users->contains('id', $user->id)) {
$users[] = $user;
}

// Sort by full name.
$users = User::sortUsers($users);

return view('conversations/ajax_html/assignee_filter', [
'users' => $users,
'user_id' => $user_id,
]);
}

/**
* Change default redirect for the mailbox.
*/
Expand Down Expand Up @@ -2707,6 +2774,11 @@ public function ajaxConversationsPagination(Request $request, $response, $user)

if (!$response['msg']) {
$query_conversations = Conversation::getQueryByFolder($folder, $user->id);

if (!empty($request->params['user_id'])) {
$query_conversations->where('conversations.user_id', (int)$request->params['user_id']);
}

$conversations = $folder->queryAddOrderBy($query_conversations)->paginate(Conversation::DEFAULT_LIST_SIZE, ['*'], 'page', $request->page);
}

Expand All @@ -2715,6 +2787,7 @@ public function ajaxConversationsPagination(Request $request, $response, $user)
$response['html'] = view('conversations/conversations_table', [
'folder' => $folder,
'conversations' => $conversations,
'params' => $request->params ?? [],
])->render();

return $response;
Expand Down Expand Up @@ -2977,6 +3050,7 @@ public function ajaxConversationsFilter(Request $request, $response, $user)
$response['html'] = view('conversations/conversations_table', [
'conversations' => $conversations,
'params' => $request->params ?? [],
'conversations_filter' => $request->filter['f'] ?? $request->filter ?? [],
])->render();

return $response;
Expand All @@ -3001,6 +3075,10 @@ public function conversationsFilterQuery($request, $user)
}
}

if (!empty($request->params['user_id'])) {
$query_conversations->where('conversations.user_id', (int)$request->params['user_id']);
}

return $query_conversations->paginate(Conversation::DEFAULT_LIST_SIZE);
}

Expand Down
15 changes: 10 additions & 5 deletions app/Http/Controllers/MailboxesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -622,17 +622,22 @@ public function ajax(Request $request)
}

if (!$response['msg']) {
$test_result = false;
$test_result = [
'status' => 'error'
];

try {
$test_result = \App\Misc\Mail::sendTestMail($request->to, $mailbox);
$test_result = \MailHelper::sendTestMail($request->to, $mailbox);
} catch (\Exception $e) {
$response['msg'] = $e->getMessage();
$test_result['msg'] = $e->getMessage();
}

if (!$test_result && !$response['msg']) {
$response['msg'] = __('Error occurred sending email. Please check your mail server logs for more details.');
if ($test_result['status'] == 'error') {
$response['msg'] = $test_result['msg']
?: __('Error occurred sending email. Please check your mail server logs for more details.');
}

$response['log'] = $test_result['log'] ?? '';
}

if (!$response['msg']) {
Expand Down
13 changes: 9 additions & 4 deletions app/Http/Controllers/SettingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -394,17 +394,22 @@ public function ajax(Request $request)
}

if (!$response['msg']) {
$test_result = false;
$test_result = [
'status' => 'error'
];

try {
$test_result = \MailHelper::sendTestMail($request->to);
} catch (\Exception $e) {
$response['msg'] = $e->getMessage();
$test_result['msg'] = $e->getMessage();
}

if (!$test_result && !$response['msg']) {
$response['msg'] = __('Error occurred sending email. Please check your mail server logs for more details.');
if ($test_result['status'] == 'error') {
$response['msg'] = $test_result['msg']
?: __('Error occurred sending email. Please check your mail server logs for more details.');
}

$response['log'] = $test_result['log'] ?? '';
}

if (!$response['msg']) {
Expand Down
4 changes: 2 additions & 2 deletions app/Http/Controllers/SystemController.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public function status(Request $request)
// Check if cache files are writable.
$non_writable_cache_file = '';
if (function_exists('shell_exec')) {
$non_writable_cache_file = shell_exec('find '.base_path('storage/framework/cache/data/').' -type f | xargs -I {} sh -c \'[ ! -w "{}" ] && echo {}\' 2>&1 | head -n 1');
$non_writable_cache_file = \Helper::shellExec('find '.base_path('storage/framework/cache/data/').' -type f | xargs -I {} sh -c \'[ ! -w "{}" ] && echo {}\' 2>&1 | head -n 1');
$non_writable_cache_file = trim($non_writable_cache_file ?? '');
// Leave only one line (in case head -n 1 does not work)
$non_writable_cache_file = preg_replace("#[\r\n].+#m", '', $non_writable_cache_file);
Expand Down Expand Up @@ -97,7 +97,7 @@ public function status(Request $request)
$running_commands = 0;

try {
$processes = preg_split("/[\r\n]/", shell_exec("ps aux | grep '{$command_identifier}'"));
$processes = preg_split("/[\r\n]/", \Helper::shellExec("ps aux | grep '{$command_identifier}'"));
$pids = [];
foreach ($processes as $process) {
$process = trim($process);
Expand Down
21 changes: 17 additions & 4 deletions app/Misc/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -1413,7 +1413,7 @@ public static function getRunningProcesses($search = '')
$pids = [];

try {
$processes = preg_split("/[\r\n]/", shell_exec("ps aux | grep '".$search."'"));
$processes = preg_split("/[\r\n]/", \Helper::shellExec("ps aux | grep '".$search."'"));
foreach ($processes as $process) {
$process = trim($process);
preg_match("/^[\S]+\s+([\d]+)\s+/", $process, $m);
Expand Down Expand Up @@ -1921,7 +1921,7 @@ public static function checkRequiredExtensions()
if (self::isConsole() || !function_exists('shell_exec')) {
$pcntl_enabled = extension_loaded('pcntl');
} else {
$pcntl_enabled = preg_match("/enable/m", shell_exec("php -i | grep pcntl") ?? '');
$pcntl_enabled = preg_match("/enable/m", \Helper::shellExec("php -i | grep pcntl") ?? '');
}
$php_extensions['pcntl (console PHP)'] = $pcntl_enabled;

Expand All @@ -1935,8 +1935,8 @@ public static function checkRequiredFunctions()
'proc_open (PHP)' => function_exists('proc_open'),
'fpassthru (PHP)' => function_exists('fpassthru'),
'symlink (PHP)' => function_exists('symlink'),
'pcntl_signal (console PHP)' => function_exists('shell_exec') ? (int)shell_exec('php -r "echo (int)function_exists(\'pcntl_signal\');"') : false,
'ps (shell)' => function_exists('shell_exec') ? shell_exec('ps') : false,
'pcntl_signal (console PHP)' => function_exists('shell_exec') ? (int)\Helper::shellExec('php -r "echo (int)function_exists(\'pcntl_signal\');"') : false,
'ps (shell)' => function_exists('shell_exec') ? \Helper::shellExec('ps') : false,
];
}

Expand Down Expand Up @@ -2120,4 +2120,17 @@ public static function sanitizeDatepickerDatetime($datetime)
{
return str_replace('T', ' ', $datetime);
}

// To catch possible exception:
// shell_exec(): Unable to execute
public static function shellExec($command)
{
try {
return shell_exec($command);
} catch (\Exception $e) {
self::logException($e, '\Helper::shellExec() - ');
}

return '';
}
}
Loading

0 comments on commit 7d035f5

Please sign in to comment.