extractPassthroughParameters(); if (strlen($query_string) > 0) { // Parse the url to preserve the fragment. $pieces = parse_url($url); if (isset($pieces['fragment'])) { $url = str_replace('#' . $pieces['fragment'], '', $url); } // Handle additional query string params. if ($query_string) { if (stristr($url, '?')) { $url .= '&' . $query_string; } else { $url .= '?' . $query_string; } } // slap the fragment onto the end per URL spec if (isset($pieces['fragment'])) { $url .= '#' . $pieces['fragment']; } } CRM_Utils_System::redirect($url, [ 'for' => 'civicrm/mailing/url', 'queue_id' => $queue_id, 'url_id' => $url_id, ]); } /** * Determine if this request has any valid pass-through parameters. * * Under CRM-7103 (v3.3), all unrecognized query-parameters (besides qid/u) are passed * through as part of the redirect. This mechanism is relevant to certain * customizations (eg using `hook_alterMailParams` to append extra URL args) * but does not matter for normal URLs. * * The functionality seems vaguely problematic (IMHO) - especially now that * 'extern/url.php' is moving into the CMS/Civi router ('civicrm/mailing/url'). * But it's the current protocol. * * A better design might be to support `hook_alterRedirect` in the CiviMail * click-through tracking. Then you don't have to take any untrusted inputs * and you can fix URL mistakes in realtime. * * @return string * @link https://issues.civicrm.org/jira/browse/CRM-7103 */ protected function extractPassthroughParameters():string { $config = CRM_Core_Config::singleton(); $query_param = $_GET; unset($query_param['qid']); unset($query_param['u']); unset($query_param[$config->userFrameworkURLVar]); if ($config->userFramework === 'WordPress') { // Ugh unset($query_param['page']); unset($query_param['noheader']); } $query_string = http_build_query($query_param); return $query_string; } }