Skip to content

Commit

Permalink
COMCL-885: Apply CIVI-SA-2024-04
Browse files Browse the repository at this point in the history
Core commits

civicrm@039d777
  • Loading branch information
Muhammad Shahrukh authored and shahrukh-compuco committed Oct 25, 2024
1 parent c46b884 commit f486767
Show file tree
Hide file tree
Showing 13 changed files with 91 additions and 19 deletions.
9 changes: 7 additions & 2 deletions CRM/Admin/Page/Job.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public function &links() {
CRM_Core_Action::COPY => array(
'name' => ts('Copy'),
'url' => 'civicrm/admin/job',
'qs' => 'action=copy&id=%%id%%',
'qs' => 'action=copy&id=%%id%%&qfKey=%%key%%',
'title' => ts('Copy Scheduled Job'),
),
);
Expand Down Expand Up @@ -122,6 +122,11 @@ public function run() {
);

if (($this->_action & CRM_Core_Action::COPY) && (!empty($this->_id))) {
$key = $_POST['qfKey'] ?? $_GET['qfKey'] ?? $_REQUEST['qfKey'] ?? NULL;
$k = CRM_Core_Key::validate($key, CRM_Utils_System::getClassName($this));
if (!$k) {
$this->invalidKey();
}
try {
$jobResult = civicrm_api3('Job', 'clone', array('id' => $this->_id));
if ($jobResult['count'] > 0) {
Expand Down Expand Up @@ -176,7 +181,7 @@ public function browse() {
}

$job->action = CRM_Core_Action::formLink($this->links(), $action,
['id' => $job->id],
['id' => $job->id, 'key' => CRM_Core_Key::get(CRM_Utils_System::getClassName($this))],
ts('more'),
FALSE,
'job.manage.action',
Expand Down
16 changes: 9 additions & 7 deletions CRM/Contribute/Page/ContributionPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public static function &actionLinks() {
CRM_Core_Action::COPY => array(
'name' => ts('Make a Copy'),
'url' => CRM_Utils_System::currentPath(),
'qs' => 'action=copy&gid=%%id%%',
'qs' => 'action=copy&gid=%%id%%&qfKey=%%key%%',
'title' => ts('Make a Copy of CiviCRM Contribution Page'),
'extra' => 'onclick = "return confirm(\'' . $copyExtra . '\');"',
),
Expand Down Expand Up @@ -306,12 +306,14 @@ public function run() {
$this->assign('CiviMember', CRM_Core_Component::isEnabled('CiviMember'));
}
elseif ($action & CRM_Core_Action::COPY) {
// @todo Unused local variable can be safely removed.
// But are there any side effects of CRM_Core_Session::singleton() that we
// need to preserve?
$session = CRM_Core_Session::singleton();
CRM_Core_Session::setStatus(ts('A copy of the contribution page has been created'), ts('Successfully Copied'), 'success');
$key = $_POST['qfKey'] ?? $_GET['qfKey'] ?? $_REQUEST['qfKey'] ?? NULL;
$k = CRM_Core_Key::validate($key, CRM_Utils_System::getClassName($this));
if (!$k) {
$this->invalidKey();
}

$this->copy();
CRM_Core_Session::setStatus(ts('A copy of the contribution page has been created'), ts('Successfully Copied'), 'success');
}
elseif ($action & CRM_Core_Action::DELETE) {
CRM_Utils_System::appendBreadCrumb($breadCrumb);
Expand Down Expand Up @@ -518,7 +520,7 @@ public function browse($action = NULL) {
//build the normal action links.
$contributions[$dao->id]['action'] = CRM_Core_Action::formLink(self::actionLinks(),
$action,
array('id' => $dao->id),
['id' => $dao->id, 'key' => CRM_Core_Key::get(CRM_Utils_System::getClassName($this))],
ts('more'),
TRUE,
'contributionpage.action.links',
Expand Down
5 changes: 5 additions & 0 deletions CRM/Core/Page.php
Original file line number Diff line number Diff line change
Expand Up @@ -540,4 +540,9 @@ public function addExpectedSmartyVariables(array $elementNames): void {
}
}

public function invalidKey() {
$msg = ts("We can't load the requested web page. This page requires cookies to be enabled in your browser settings. Please check this setting and enable cookies (if they are not enabled). Then try again. If this error persists, contact the site administrator for assistance.") . '<br /><br />' . ts('Site Administrators: This error may indicate that users are accessing this page using a domain or URL other than the configured Base URL. EXAMPLE: Base URL is http://example.org, but some users are accessing the page via http://www.example.org or a domain alias like http://myotherexample.org.') . '<br /><br />' . ts('Error type: Could not find a valid session key.');
throw new CRM_Core_Exception($msg);
}

}
9 changes: 7 additions & 2 deletions CRM/Event/Page/ManageEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public function &links() {
CRM_Core_Action::COPY => [
'name' => ts('Copy'),
'url' => CRM_Utils_System::currentPath(),
'qs' => 'reset=1&action=copy&id=%%id%%',
'qs' => 'reset=1&action=copy&id=%%id%%&qfKey=%%key%%',
'extra' => 'onclick = "return confirm(\'' . $copyExtra . '\');"',
'title' => ts('Copy Event'),
],
Expand Down Expand Up @@ -259,6 +259,11 @@ public function run() {
return $controller->run();
}
elseif ($action & CRM_Core_Action::COPY) {
$key = $_POST['qfKey'] ?? $_GET['qfKey'] ?? $_REQUEST['qfKey'] ?? NULL;
$k = CRM_Core_Key::validate($key, CRM_Utils_System::getClassName($this));
if (!$k) {
$this->invalidKey();
}
$this->copy();
}

Expand Down Expand Up @@ -394,7 +399,7 @@ public function browse() {
);
$manageEvent[$dao->id]['action'] = CRM_Core_Action::formLink(self::links(),
$action,
['id' => $dao->id],
['id' => $dao->id, 'key' => CRM_Core_Key::get(CRM_Utils_System::getClassName($this))],
ts('more'),
TRUE,
'event.manage.list',
Expand Down
1 change: 1 addition & 0 deletions CRM/Financial/Form/BatchTransaction.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public function preProcess() {
$this->assign('columnHeaders', $columnHeaders);
}
$this->assign('batchStatus', $this->_batchStatus);
$this->assign('financialAJAXQFKey', CRM_Core_key::get('CRM_Financial_Page_AJAX'));
}

/**
Expand Down
5 changes: 5 additions & 0 deletions CRM/Financial/Page/AJAX.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ public static function jqFinancialType($config) {
public static function assignRemove() {
$op = CRM_Utils_Type::escape($_POST['op'], 'String');
$recordBAO = CRM_Utils_Type::escape($_POST['recordBAO'], 'String');
$key = CRM_Utils_Request::retrieveValue('qfKey', 'String');
$k = CRM_Core_Key::validate($key, 'CRM_Financial_Page_AJAX');
if (!$k) {
CRM_Utils_JSON::output(['status' => 'invalid key']);
}
foreach ($_POST['records'] as $record) {
$recordID = CRM_Utils_Type::escape($record, 'Positive', FALSE);
if ($recordID) {
Expand Down
1 change: 1 addition & 0 deletions CRM/Financial/Page/Batch.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public function userContext($mode = NULL) {
public function browse() {
$status = CRM_Utils_Request::retrieve('status', 'Positive', CRM_Core_DAO::$_nullObject, FALSE, 1);
$this->assign('status', $status);
$this->assign('financialAJAXQFKey', CRM_Core_Key::get('CRM_Financial_Page_AJAX'));
$this->search();
}

Expand Down
1 change: 1 addition & 0 deletions CRM/Financial/Page/FinancialBatch.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public function run() {
) {
$this->edit($this->_action, $id);
}
$this->assign('financialAJAXQFKey', CRM_Core_Key::get('CRM_Financial_Page_AJAX'))
// parent run
return CRM_Core_Page::run();
}
Expand Down
9 changes: 7 additions & 2 deletions CRM/Price/Page/Set.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public function &actionLinks() {
CRM_Core_Action::COPY => [
'name' => ts('Copy Price Set'),
'url' => CRM_Utils_System::currentPath(),
'qs' => 'action=copy&sid=%%sid%%',
'qs' => 'action=copy&sid=%%sid%%&qfKey=%%key%%',
'title' => ts('Make a Copy of Price Set'),
'extra' => 'onclick = "return confirm(\'' . $copyExtra . '\');"',
],
Expand Down Expand Up @@ -126,6 +126,11 @@ public function run() {
$this->preview($sid);
}
elseif ($action & CRM_Core_Action::COPY) {
$key = $_POST['qfKey'] ?? $_GET['qfKey'] ?? $_REQUEST['qfKey'] ?? NULL;
$k = CRM_Core_Key::validate($key, CRM_Utils_System::getClassName($this));
if (!$k) {
$this->invalidKey();
}
CRM_Core_Session::setStatus(ts('A copy of the price set has been created'), ts('Saved'), 'success');
$this->copy();
}
Expand Down Expand Up @@ -280,7 +285,7 @@ public function browse($action = NULL) {
$actionLinks[CRM_Core_Action::BROWSE]['name'] = ts('View Price Fields');
}
$priceSet[$dao->id]['action'] = CRM_Core_Action::formLink($actionLinks, $action,
['sid' => $dao->id],
['sid' => $dao->id, 'key' => CRM_Core_Key::get(CRM_Utils_System::getClassName($this))],
ts('more'),
FALSE,
'priceSet.row.actions',
Expand Down
9 changes: 7 additions & 2 deletions CRM/UF/Page/Group.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public static function &actionLinks() {
CRM_Core_Action::COPY => [
'name' => ts('Copy'),
'url' => 'civicrm/admin/uf/group',
'qs' => 'action=copy&gid=%%id%%',
'qs' => 'action=copy&gid=%%id%%&qfKey=%%key%%',
'title' => ts('Make a Copy of CiviCRM Profile Group'),
'extra' => 'onclick = "return confirm(\'' . $copyExtra . '\');"',
],
Expand Down Expand Up @@ -166,6 +166,11 @@ public function run() {
$this->preview($id, $action);
}
elseif ($action & CRM_Core_Action::COPY) {
$key = $_POST['qfKey'] ?? $_GET['qfKey'] ?? $_REQUEST['qfKey'] ?? NULL;
$k = CRM_Core_Key::validate($key, CRM_Utils_System::getClassName($this));
if (!$k) {
$this->invalidKey();
}
$this->copy();
}
// finally browse the uf groups
Expand Down Expand Up @@ -349,7 +354,7 @@ public function browse($action = NULL) {
$ufGroup[$id]['group_type'] = self::formatGroupTypes($groupTypes);

$ufGroup[$id]['action'] = CRM_Core_Action::formLink(self::actionLinks(), $action,
['id' => $id],
['id' => $id, 'key' => CRM_Core_Key::get(CRM_Utils_System::getClassName($this))],
ts('more'),
FALSE,
'ufGroup.row.actions',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ abstract class AbstractRunAction extends \Civi\Api4\Generic\AbstractAction {
*/
private $_afform;

/**
* @var array
* Ex: ['civicrm/foo/bar?id=[id]&widget=gizmo' => 'CRMFooBar1234abcd1234abcd']
*/
private $_qfKeys = [];

/**
* Override execute method to change the result object type
* @return \Civi\Api4\Result\SearchDisplayRunResult
Expand Down Expand Up @@ -405,9 +411,13 @@ private function formatFieldLinks($column, $data, $value): array {
$path = $this->getLinkPath($column['link'], $data, $index);
$path = $this->replaceTokens($path, $data, 'url', $index);
if ($path) {
$query = [];
if (($column['link']['csrf'] ?? NULL) === 'qfKey' && $column['link']['path']) {
$query['qfKey'] = $this->getQfKey($column['link']['path']);
}
$link = [
'text' => $val,
'url' => $this->getUrl($path),
'url' => $this->getUrl($path, $query),
];
if (!empty($column['link']['target'])) {
$link['target'] = $column['link']['target'];
Expand Down Expand Up @@ -435,9 +445,13 @@ private function formatLinksColumn($column, $data): array {
}
$path = $this->replaceTokens($this->getLinkPath($item, $data), $data, 'url');
if ($path) {
$query = [];
if (($item['csrf'] ?? NULL) === 'qfKey' && $item['path']) {
$query['qfKey'] = $this->getQfKey($item['path']);
}
$link = [
'text' => $this->replaceTokens($item['text'] ?? '', $data, 'view'),
'url' => $this->getUrl($path),
'url' => $this->getUrl($path, $query),
];
foreach (['target', 'style', 'icon'] as $prop) {
if (!empty($item[$prop])) {
Expand Down Expand Up @@ -1260,4 +1274,27 @@ private function loadSearchDisplay(): void {
}
}

/**
* @param string $pathExpr
* Path formula. Should specify an explicit path.
* Ex: 'civicrm/foo/bar?id=[id]&widget=gizmo`
* @return string|null
*/
private function getQfKey(string $pathExpr): ?string {
if (isset($this->_qfKeys[$pathExpr])) {
// No point re-computing this for 100x links per page-view - same value works.
return $this->_qfKeys[$pathExpr];
}
$result = NULL;
if ($routeName = parse_url($pathExpr, PHP_URL_PATH)) {
if ($routeItem = \CRM_Core_Menu::get($routeName)) {
if (!empty($routeItem['page_callback'])) {
$result = \CRM_Core_Key::get($routeItem['page_callback']);
}
}
}
$this->_qfKeys[$pathExpr] = $result;
return $result;
}

}
2 changes: 1 addition & 1 deletion templates/CRM/Financial/Form/Search.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ CRM.$(function($) {
}

function saveRecords(records, op) {
var postUrl = CRM.url('civicrm/ajax/rest', 'className=CRM_Financial_Page_AJAX&fnName=assignRemove');
var postUrl = CRM.url('civicrm/ajax/rest', 'className=CRM_Financial_Page_AJAX&fnName=assignRemove&qfKey={/literal}{$financialAJAXQFKey}{literal}');
//post request and get response
$.post(postUrl, {records: records, recordBAO: 'CRM_Batch_BAO_Batch', op: op, key: {/literal}"{crmKey name='civicrm/ajax/ar'}"{literal}},
function(response) {
Expand Down
2 changes: 1 addition & 1 deletion templates/CRM/Financial/Page/BatchTransaction.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ function saveRecord(recordID, op, recordBAO, entityID) {
window.location.href = CRM.url('civicrm/financial/batch/export', {reset: 1, id: recordID, status: 1});
return;
}
var postUrl = {/literal}"{crmURL p='civicrm/ajax/rest' h=0 q='className=CRM_Financial_Page_AJAX&fnName=assignRemove'}"{literal};
var postUrl = {/literal}"{crmURL p='civicrm/ajax/rest' h=0 q="className=CRM_Financial_Page_AJAX&fnName=assignRemove&qfKey={$financialAJAXQFKey}"}"{literal};
//post request and get response
CRM.$.post( postUrl, { records: [recordID], recordBAO: recordBAO, op:op, entityID:entityID, key: {/literal}"{crmKey name='civicrm/ajax/ar'}"{literal} }, function( html ){
//this is custom status set when record update success.
Expand Down

0 comments on commit f486767

Please sign in to comment.