DATE_SUB(NOW(), INTERVAL 2 MINUTE)"); while ($row = mysqli_fetch_array($query)) { $users[] = $row['user_name']; } if (!empty($users)) { $users = array_unique($users); if (count($users) > 1) { // Multiple viewers $response['message'] = "" . nullable_htmlentities(implode(", ", $users) . " are viewing this ticket."); } else { // Single viewer $response['message'] = "" . nullable_htmlentities(implode("", $users) . " is viewing this ticket."); } } else { // No viewers $response['message'] = ""; } echo json_encode($response); } /* * Generates public/guest links for sharing logins/docs */ if (isset($_GET['share_generate_link'])) { validateTechRole(); $item_encrypted_username = ''; // Default empty $item_encrypted_credential = ''; // Default empty $client_id = intval($_GET['client_id']); $item_type = sanitizeInput($_GET['type']); $item_id = intval($_GET['id']); $item_email = sanitizeInput($_GET['contact_email']); $item_note = sanitizeInput($_GET['note']); $item_view_limit = intval($_GET['views']); $item_expires = sanitizeInput($_GET['expires']); $item_expires_friendly = "never"; // default never if ($item_expires == "30 MINUTE") { $item_expires_friendly = "30 minutes"; } elseif ($item_expires == "24 HOUR") { $item_expires_friendly = "24 hours"; } elseif ($item_expires == "72 HOUR") { $item_expires_friendly = "72 hours (3 days)"; } $item_key = randomString(156); if ($item_type == "Document") { $row = mysqli_fetch_array(mysqli_query($mysqli, "SELECT document_name FROM documents WHERE document_id = $item_id AND document_client_id = $client_id LIMIT 1")); $item_name = sanitizeInput($row['document_name']); } if ($item_type == "File") { $row = mysqli_fetch_array(mysqli_query($mysqli, "SELECT file_name FROM files WHERE file_id = $item_id AND file_client_id = $client_id LIMIT 1")); $item_name = sanitizeInput($row['file_name']); } if ($item_type == "Login") { $login = mysqli_query($mysqli, "SELECT login_name, login_username, login_password FROM logins WHERE login_id = $item_id AND login_client_id = $client_id LIMIT 1"); $row = mysqli_fetch_array($login); $item_name = sanitizeInput($row['login_name']); // Decrypt & re-encrypt username/password for sharing $login_encryption_key = randomString(); $login_username_cleartext = decryptLoginEntry($row['login_username']); $iv = randomString(); $username_ciphertext = openssl_encrypt($login_username_cleartext, 'aes-128-cbc', $login_encryption_key, 0, $iv); $item_encrypted_username = $iv . $username_ciphertext; $login_password_cleartext = decryptLoginEntry($row['login_password']); $iv = randomString(); $password_ciphertext = openssl_encrypt($login_password_cleartext, 'aes-128-cbc', $login_encryption_key, 0, $iv); $item_encrypted_credential = $iv . $password_ciphertext; } // Insert entry into DB $sql = mysqli_query($mysqli, "INSERT INTO shared_items SET item_active = 1, item_key = '$item_key', item_type = '$item_type', item_related_id = $item_id, item_encrypted_username = '$item_encrypted_username', item_encrypted_credential = '$item_encrypted_credential', item_note = '$item_note', item_views = 0, item_view_limit = $item_view_limit, item_expire_at = NOW() + INTERVAL + $item_expires, item_client_id = $client_id"); $share_id = $mysqli->insert_id; // Return URL if ($item_type == "Login") { $url = "https://$config_base_url/guest_view_item.php?id=$share_id&key=$item_key&ek=$login_encryption_key"; } else { $url = "https://$config_base_url/guest_view_item.php?id=$share_id&key=$item_key"; } $sql = mysqli_query($mysqli,"SELECT * FROM companies WHERE company_id = 1"); $row = mysqli_fetch_array($sql); $company_name = sanitizeInput($row['company_name']); $company_phone = sanitizeInput(formatPhoneNumber($row['company_phone'])); // Sanitize Config vars from get_settings.php $config_ticket_from_name = sanitizeInput($config_ticket_from_name); $config_ticket_from_email = sanitizeInput($config_ticket_from_email); $config_mail_from_name = sanitizeInput($config_mail_from_name); $config_mail_from_email = sanitizeInput($config_mail_from_email); // Send user e-mail, if specified if(!empty($config_smtp_host) && filter_var($item_email, FILTER_VALIDATE_EMAIL)){ $subject = "Time sensitive - $company_name secure link enclosed"; if ($item_expires_friendly == "never") { $subject = "$company_name secure link enclosed"; } $body = "Hello,

$session_name from $company_name sent you a time sensitive secure link regarding \"$item_name\".

The link will expire in $item_expires_friendly and may only be viewed $item_view_limit times, before the link is destroyed.

Click here to access your secure content

--
$company_name - Support
$config_ticket_from_email
$company_phone"; $data = [ [ 'from' => $config_mail_from_email, 'from_name' => $config_mail_from_name, 'recipient' => $item_email, 'recipient_name' => $item_email, 'subject' => $subject, 'body' => $body ] ]; $mail = addToMailQueue($mysqli, $data); if ($mail !== true) { mysqli_query($mysqli,"INSERT INTO notifications SET notification_type = 'Mail', notification = 'Failed to send email to $item_email'"); mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Mail', log_action = 'Error', log_description = 'Failed to send email to $item_email regarding $subject. $item_mail', log_ip = '$session_ip', log_user_agent = '$session_user_agent', log_user_id = $session_user_id"); } } echo json_encode($url); // Logging mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Sharing', log_action = 'Create', log_description = '$session_name created shared link for $item_type - $item_name', log_client_id = $client_id, log_ip = '$session_ip', log_user_agent = '$session_user_agent', log_user_id = $session_user_id"); } /* * Looks up info for a given recurring (was scheduled) ticket ID from the database, used to dynamically populate modal edit fields */ if (isset($_GET['recurring_ticket_get_json_details'])) { validateTechRole(); $client_id = intval($_GET['client_id']); $ticket_id = intval($_GET['ticket_id']); // Get all contacts, to allow tickets to be raised under a specific contact $contact_sql = mysqli_query($mysqli, "SELECT contact_id, contact_name FROM contacts WHERE contact_client_id = $client_id AND contact_archived_at IS NULL ORDER BY contact_primary DESC, contact_technical DESC, contact_name ASC" ); while ($row = mysqli_fetch_array($contact_sql)) { $response['contacts'][] = $row; } // Get ticket details $ticket_sql = mysqli_query($mysqli, "SELECT * FROM scheduled_tickets WHERE scheduled_ticket_id = $ticket_id AND scheduled_ticket_client_id = $client_id LIMIT 1"); while ($row = mysqli_fetch_array($ticket_sql)) { $response['ticket'][] = $row; } // Get assets $asset_sql = mysqli_query($mysqli, "SELECT asset_id, asset_name FROM assets WHERE asset_client_id = $client_id AND asset_archived_at IS NULL"); while ($row = mysqli_fetch_array($asset_sql)) { $response['assets'][] = $row; } // Get technicians to auto assign the ticket to $sql_agents = mysqli_query( $mysqli, "SELECT users.user_id, user_name FROM users LEFT JOIN user_settings on users.user_id = user_settings.user_id WHERE user_role > 1 AND user_status = 1 AND user_archived_at IS NULL ORDER BY user_name ASC" ); while ($row = mysqli_fetch_array($sql_agents)) { $response['agents'][] = $row; } echo json_encode($response); } /* * Looks up info for a given quote ID from the database, used to dynamically populate modal fields */ if (isset($_GET['quote_get_json_details'])) { $quote_id = intval($_GET['quote_id']); // Get quote details $quote_sql = mysqli_query( $mysqli, "SELECT * FROM quotes LEFT JOIN clients ON quote_client_id = client_id WHERE quote_id = $quote_id LIMIT 1" ); while ($row = mysqli_fetch_array($quote_sql)) { $response['quote'][] = $row; } // Get all income-related categories for quoting $quote_created_at = $response['quote'][0]['quote_created_at']; $category_sql = mysqli_query( $mysqli, "SELECT category_id, category_name FROM categories WHERE category_type = 'Income' AND (category_archived_at > '$quote_created_at' OR category_archived_at IS NULL) ORDER BY category_name" ); while ($row = mysqli_fetch_array($category_sql)) { $response['categories'][] = $row; } echo json_encode($response); } /* * Returns sorted list of active clients */ if (isset($_GET['get_active_clients'])) { $client_sql = mysqli_query( $mysqli, "SELECT client_id, client_name FROM clients WHERE client_archived_at IS NULL ORDER BY client_accessed_at DESC" ); while ($row = mysqli_fetch_array($client_sql)) { $response['clients'][] = $row; } echo json_encode($response); } /* * Returns ordered list of active contacts for a specified client */ if (isset($_GET['get_client_contacts'])) { $client_id = intval($_GET['client_id']); $contact_sql = mysqli_query( $mysqli, "SELECT contact_id, contact_name, contact_primary, contact_important, contact_technical FROM contacts WHERE contacts.contact_archived_at IS NULL AND contact_client_id = $client_id ORDER BY contact_primary DESC, contact_technical DESC, contact_important DESC, contact_name" ); while ($row = mysqli_fetch_array($contact_sql)) { $response['contacts'][] = $row; } echo json_encode($response); } /* * Dynamic TOTP "resolver" * When provided with a TOTP secret, returns a 6-digit code * // TODO: Check if this can now be removed */ if (isset($_GET['get_totp_token'])) { $otp = TokenAuth6238::getTokenCode(strtoupper($_GET['totp_secret'])); echo json_encode($otp); } /* * NEW TOTP getter for client login/passwords page * When provided with a login ID, checks permissions and returns the 6-digit code */ if (isset($_GET['get_totp_token_via_id'])) { validateTechRole(); $login_id = intval($_GET['login_id']); $sql = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT login_name, login_otp_secret, login_client_id FROM logins WHERE login_id = $login_id")); $name = sanitizeInput($sql['login_name']); $totp_secret = $sql['login_otp_secret']; $client_id = intval($sql['login_client_id']); $otp = TokenAuth6238::getTokenCode(strtoupper($totp_secret)); echo json_encode($otp); // Logging // Only log the TOTP view if the user hasn't already viewed this specific login entry recently, this prevents logs filling if a user hovers across an entry a few times $check_recent_totp_view_logged_sql = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT(log_id) AS recent_totp_view FROM logs WHERE log_type = 'Login' AND log_action = 'View TOTP' AND log_user_id = $session_user_id AND log_entity_id = $login_id AND log_client_id = $client_id AND log_created_at > (NOW() - INTERVAL 5 MINUTE)")); $recent_totp_view_logged_count = intval($check_recent_totp_view_logged_sql['recent_totp_view']); if ($recent_totp_view_logged_count == 0) { mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Login', log_action = 'View TOTP', log_description = '$session_name viewed login TOTP code for $name', log_ip = '$session_ip', log_user_agent = '$session_user_agent', log_client_id = $client_id, log_user_id = $session_user_id, log_entity_id = $login_id"); } } if (isset($_GET['get_readable_pass'])) { echo json_encode(GenerateReadablePassword(4)); }