diff --git a/portal/lib/portal_mail.inc b/portal/lib/portal_mail.inc index 0a78261505a..3e5808fd22f 100644 --- a/portal/lib/portal_mail.inc +++ b/portal/lib/portal_mail.inc @@ -133,7 +133,7 @@ function getPortalPatientNotes($owner = '', $limit = '', $offset = 0, $search = p.reply_mail_chain FROM onsite_mail AS p - WHERE p.deleted != 1 AND p.owner = ? AND p.recipient_id = ? + WHERE p.deleted != 1 AND p.owner = ? AND p.recipient_id = ? $search ORDER BY `date` desc $limit @@ -233,18 +233,18 @@ function getPortalPatientSentNotes($owner = '', $limit = '', $offset = 0, $searc return $all; } -function updatePortalMailMessageStatus($id, $message_status) +function updatePortalMailMessageStatus($id, $message_status, $owner) { if ($message_status == "Done") { - sqlStatement("update onsite_mail set message_status = ?, activity = '0' where id = ?", array($message_status, $id)); + sqlStatement("update onsite_mail set message_status = ?, activity = '0' where id = ? and `owner` = ?", array($message_status, $id, $owner)); } elseif ($message_status == "Delete") { - sqlStatement("update onsite_mail set message_status = ?, activity = '1', deleted = '1',delete_date = ? where mail_chain = ? OR id = ?", array($message_status, date('Y-m-d H:i:s'), $id, $id)); + sqlStatement("update onsite_mail set message_status = ?, activity = '1', deleted = '1',delete_date = ? where (mail_chain = ? OR id = ?) and `owner` = ?", array($message_status, date('Y-m-d H:i:s'), $id, $id, $owner)); } else { - sqlStatement("update onsite_mail set message_status = ?, activity = '1' where id = ?", array($message_status, $id)); + sqlStatement("update onsite_mail set message_status = ?, activity = '1' where id = ? and `owner` = ?", array($message_status, $id, $owner)); } if ($message_status == "Delete") { - $stats = sqlQuery("Select * From onsite_mail Where id = ?", array($id)); + $stats = sqlQuery("Select * From onsite_mail Where id = ? AND `owner` = ?", array($id, $owner)); $by = $_SESSION['authUser'] ? $_SESSION['authUser'] : $_SESSION['ptName']; $loguser = $_SESSION['authUser'] ? $_SESSION['authUser'] : $_SESSION['portal_username']; $evt = "secure message soft delete by " . $by . " msg id: $id from " . $stats['sender_name'] . " to recipient: " . $stats['recipient_name']; @@ -298,20 +298,6 @@ function getMails($owner, $dotype, $nsrch, $nfsrch) } } -function getMailDetails($id, $owner = '') -{ - if ($owner) { - $result = getMailById($id); - if ($result['owner'] == $owner && $result['message_status'] == 'New') { - updatePortalMailMessageStatus($id, 'Read'); - } - - return $result; - } else { - return 'failed'; - } -} - function sendMail($owner, $note, string $title = null, $to, $noteid, $sid, $sn, $rid, $rn, $status = 'New', $replyid = '') { if (!$title) { @@ -324,9 +310,3 @@ function sendMail($owner, $note, string $title = null, $to, $noteid, $sid, $sn, return 'failed'; } } - -function updateStatus($id, $status) -{ - updatePortalMailMessageStatus($id, $status); - return 1; -} diff --git a/portal/messaging/handle_note.php b/portal/messaging/handle_note.php index 9b0207272c5..010ca6b2dac 100644 --- a/portal/messaging/handle_note.php +++ b/portal/messaging/handle_note.php @@ -17,22 +17,55 @@ OpenEMR\Common\Session\SessionUtil::portalSessionStart(); if (isset($_SESSION['pid']) && isset($_SESSION['patient_portal_onsite_two'])) { + // ensure patient is bootstrapped (if sent) + if (!empty($_POST['pid'])) { + if ($_POST['pid'] != $_SESSION['pid']) { + echo "illegal Action"; + OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy(); + exit; + } + } $ignoreAuth_onsite_portal = true; require_once(dirname(__FILE__) . "/../../interface/globals.php"); + if (empty($_SESSION['portal_username'])) { + echo xlt("illegal Action"); + OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy(); + exit; + } + // owner is the patient portal_username + $owner = $_SESSION['portal_username']; } else { OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy(); $ignoreAuth = false; require_once(dirname(__FILE__) . "/../../interface/globals.php"); - if (! isset($_SESSION['authUserID'])) { + if (!isset($_SESSION['authUserID']) || empty($_SESSION['authUser'])) { $landingpage = "index.php"; header('Location: ' . $landingpage); exit(); } + //owner is the user authUser + $owner = $_SESSION['authUser']; } require_once(dirname(__FILE__) . "/../lib/portal_mail.inc"); require_once("$srcdir/pnotes.inc"); +use OpenEMR\Common\Csrf\CsrfUtils; + +if (!(isset($GLOBALS['portal_onsite_two_enable'])) || !($GLOBALS['portal_onsite_two_enable'])) { + echo xlt('Patient Portal is turned off'); + exit; +} +// confirm csrf (from both portal and core) +if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"], 'messages-portal')) { + CsrfUtils::csrfNotVerified(); +} + +if (empty($owner)) { + echo xlt('Critical error, so exiting'); + exit; +} + $task = $_POST['task']; if (! $task) { return 'no task'; @@ -41,7 +74,6 @@ $noteid = ($_POST['noteid'] ?? null) ?: 0; $notejson = ($_POST['notejson'] ?? null) ? json_decode($_POST['notejson'], true) : 0; $reply_noteid = $_POST['replyid'] ?? null ?: 0; -$owner = $_POST['owner'] ?? $_SESSION['pid']; $note = $_POST['inputBody'] ?? null; $title = $_POST['title'] ?? null; $sid = $_POST['sender_id'] ?? null; @@ -54,7 +86,7 @@ case "forward": $pid = isset($_POST['pid']) ? $_POST['pid'] : 0; addPnote($pid, $note, 1, 1, $title, $sid, '', 'New'); - updatePortalMailMessageStatus($noteid, 'Sent'); + updatePortalMailMessageStatus($noteid, 'Sent', $owner); if (empty($_POST["submit"])) { echo 'ok'; } @@ -76,14 +108,14 @@ } break; case "delete": - updatePortalMailMessageStatus($noteid, 'Delete'); + updatePortalMailMessageStatus($noteid, 'Delete', $owner); if (empty($_POST["submit"])) { echo 'ok'; } break; case "massdelete": foreach ($notejson as $deleteid) { - updatePortalMailMessageStatus($deleteid, 'Delete'); + updatePortalMailMessageStatus($deleteid, 'Delete', $owner); if (empty($_POST["submit"])) { echo 'ok'; } @@ -91,7 +123,7 @@ break; case "setread": if ($noteid > 0) { - updatePortalMailMessageStatus($noteid, 'Read'); + updatePortalMailMessageStatus($noteid, 'Read', $owner); if (empty($_POST["submit"])) { echo 'ok'; } diff --git a/portal/messaging/messages.php b/portal/messaging/messages.php index b27de7a0185..8a05a1b7b9c 100644 --- a/portal/messaging/messages.php +++ b/portal/messaging/messages.php @@ -43,8 +43,14 @@ require_once("$srcdir/classes/Document.class.php"); require_once("./../lib/portal_mail.inc"); +use OpenEMR\Common\Csrf\CsrfUtils; use OpenEMR\Core\Header; +if (!(isset($GLOBALS['portal_onsite_two_enable'])) || !($GLOBALS['portal_onsite_two_enable'])) { + echo xlt('Patient Portal is turned off'); + exit; +} + $docid = empty($_REQUEST['docid']) ? 0 : (int)$_REQUEST['docid']; $orderid = empty($_REQUEST['orderid']) ? 0 : (int)$_REQUEST['orderid']; @@ -130,6 +136,7 @@ function getAuthPortalUsers() $scope.xLate.confirm.one = ; $scope.xLate.confirm.all = ; $scope.xLate.confirm.err = ; // I think I got rid of this ability - look into.. + $scope.csrf = ; $scope.init = function () { $http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; @@ -225,7 +232,7 @@ function getAuthPortalUsers() itemToDelete.push($scope.items[i.indexOf(o)].id); } }) - $http.post('handle_note.php', $.param({'task': 'massdelete', 'notejson': JSON.stringify(itemToDelete)})).then(function successCallback(response) { + $http.post('handle_note.php', $.param({'task': 'massdelete', 'notejson': JSON.stringify(itemToDelete), 'csrf_token_form': $scope.csrf})).then(function successCallback(response) { $window.location.reload(); }, function errorCallback(response) { alert(response.data); @@ -234,7 +241,7 @@ function getAuthPortalUsers() }; $scope.deleteMessage = function (id) { - $http.post('handle_note.php', $.param({'task': 'delete', 'noteid': id})).then(function successCallback(response) { + $http.post('handle_note.php', $.param({'task': 'delete', 'noteid': id, 'csrf_token_form': $scope.csrf})).then(function successCallback(response) { return true; }, function errorCallback(response) { alert(response.data); @@ -286,7 +293,7 @@ function getAuthPortalUsers() $scope.readMessage = function (idx) { if ($scope.items[idx].message_status == 'New') { // mark mail read else ignore - $http.post('handle_note.php', $.param({'task': 'setread', 'noteid': $scope.items[idx].id})).then(function successCallback(response) { + $http.post('handle_note.php', $.param({'task': 'setread', 'noteid': $scope.items[idx].id, 'csrf_token_form': $scope.csrf})).then(function successCallback(response) { $scope.items[idx].message_status = 'Read'; $scope.selected.message_status = 'Read'; }, function errorCallback(response) { @@ -326,7 +333,7 @@ function getAuthPortalUsers() }; $scope.getInbox = function () { - $http.post('handle_note.php', $.param({'task': 'getinbox', 'owner': $scope.cUserId})).then(function successCallback(response) { + $http.post('handle_note.php', $.param({'task': 'getinbox', 'csrf_token_form': $scope.csrf})).then(function successCallback(response) { if (response.data) { $scope.inboxItems = angular.copy(response.data); } else alert(response.data); @@ -336,7 +343,7 @@ function getAuthPortalUsers() }; $scope.getAllMessages = function () { - $http.post('handle_note.php', $.param({'task': 'getall', 'owner': $scope.cUserId})).then(function successCallback(response) { + $http.post('handle_note.php', $.param({'task': 'getall', 'csrf_token_form': $scope.csrf})).then(function successCallback(response) { if (response.data) { $scope.allItems = angular.copy(response.data); } else alert(response.data); @@ -346,7 +353,7 @@ function getAuthPortalUsers() }; $scope.getDeletedMessages = function () { - $http.post('handle_note.php', $.param({'task': 'getdeleted', 'owner': $scope.cUserId})).then(function successCallback(response) { + $http.post('handle_note.php', $.param({'task': 'getdeleted', 'csrf_token_form': $scope.csrf})).then(function successCallback(response) { if (response.data) { $scope.deletedItems = []; $scope.deletedItems = angular.copy(response.data); @@ -357,7 +364,7 @@ function getAuthPortalUsers() }; $scope.getSentMessages = function () { - $http.post('handle_note.php', $.param({'task': 'getsent', 'owner': $scope.cUserId})).then(function successCallback(response) { + $http.post('handle_note.php', $.param({'task': 'getsent', 'csrf_token_form': $scope.csrf})).then(function successCallback(response) { $scope.sentItems = []; $scope.sentItems = angular.copy(response.data); }, function errorCallback(response) { @@ -371,10 +378,10 @@ function getAuthPortalUsers() $("#title").prop("disabled", false); $("#selSendto").prop("disabled", false); - compose.owner = $scope.cUserId; + compose.csrf_token_form = $scope.csrf; compose.sender_id = $scope.cUserId; compose.sender_name = $scope.userproper; - if ($scope.selrecip == compose.owner) { + if ($scope.selrecip == $scope.cUserId) { if (!confirm($scope.xLate.confirm.err)) return false; } @@ -727,9 +734,9 @@ class="float-right glyphicon glyphicon-warning-sign text-danger">
+ - diff --git a/portal/portal_payment.php b/portal/portal_payment.php index e0a43b594a5..677cde2b75d 100644 --- a/portal/portal_payment.php +++ b/portal/portal_payment.php @@ -46,6 +46,7 @@ use OpenEMR\Billing\BillingUtilities; use OpenEMR\Common\Crypto\CryptoGen; +use OpenEMR\Common\Csrf\CsrfUtils; use OpenEMR\PaymentProcessing\Sphere\SpherePayment; $cryptoGen = new CryptoGen(); @@ -449,7 +450,6 @@ function notifyPatient() { let pid = ; let note = $('#pop_receipt').html(); let formURL = './messaging/handle_note.php'; - let owner = ; let sn = ; let rid = ; let rn = ; @@ -457,8 +457,8 @@ function notifyPatient() { url: formURL, type: "POST", data: { + 'csrf_token_form': , 'task': 'add', - 'owner': owner, 'pid': pid, 'inputBody': note, 'title': 'Bill/Collect',