securepages.module in Secure Pages 6
Same filename and directory in other branches
Provide method of creating allowing certain pages to only viewable from https pages
File
securepages.moduleView source
<?php
/**
* @file
* Provide method of creating allowing certain pages to only viewable from
* https pages
*/
/**
* Implementation of hook_boot().
*/
function securepages_boot() {
$path = isset($_GET['q']) ? $_GET['q'] : '';
if ($path == 'admin/build/securepages/test') {
if (securepages_is_secure()) {
header('HTTP/1.1 200 OK');
}
else {
header('HTTP/1.1 404 Not Found');
}
exit;
}
if (!variable_get('securepages_enable', 0) || basename($_SERVER['PHP_SELF']) != 'index.php' || php_sapi_name() == 'cli') {
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
return;
}
}
/**
* If this is a cached page we need to do the check here even though we
* have no access to the menu.
*/
$cache_mode = variable_get('cache', CACHE_DISABLED);
// Get the page from the cache.
$cache = $cache_mode == CACHE_DISABLED ? '' : page_get_cache();
if ($cache) {
return;
}
if (!isset($_SESSION['securepages_redirect'])) {
securepages_redirect();
}
}
/**
* Implementation of hook_init().
*/
function securepages_init() {
if (!variable_get('securepages_enable', 0) || basename($_SERVER['PHP_SELF']) != 'index.php' || php_sapi_name() == 'cli') {
return;
}
/**
* If we have redirected in the hook_boot(). Then don't try to redirect
* again. This will prevent a loop
*/
if (!isset($_SESSION['securepages_redirect'])) {
securepages_redirect();
}
else {
unset($_SESSION['securepages_redirect']);
}
}
/**
* Implementation of hook_menu().
*/
function securepages_menu() {
$items = array();
$items['admin/build/securepages'] = array(
'title' => 'Secure Pages',
'description' => 'Configure which pages are and are not to be viewed in SSL',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'securepages_settings',
),
'access arguments' => array(
'administer site configuration',
),
'type' => MENU_NORMAL_ITEM,
'secure' => 1,
'file' => 'securepages.admin.inc',
);
return $items;
}
/**
* Implementation of hook_form_alter().
*/
function securepages_form_alter(&$form, &$form_state, $form_id) {
if (!variable_get('securepages_enable', 0)) {
return;
}
if (isset($form['#action']) && securepages_can_alter_url($form['#action'])) {
@extract(@parse_url($form['#action']));
if (isset($query)) {
parse_str($query, $query);
}
else {
$query = array();
}
if (isset($query['q'])) {
$path = $query['q'];
}
else {
$base_path = base_path();
$path = !strncmp($path, $base_path, drupal_strlen($base_path)) ? drupal_substr($path, drupal_strlen($base_path)) : $path;
}
$path = drupal_get_normal_path($path);
$query = drupal_query_string_encode($query);
$page_match = securepages_match($path);
if ($page_match && !securepages_is_secure()) {
$form['#action'] = securepages_url($path, array(
'query' => $query,
'secure' => TRUE,
));
}
elseif ($page_match === 0 && securepages_is_secure() && variable_get('securepages_switch', FALSE)) {
$form['#action'] = securepages_url($path, array(
'query' => $query,
'secure' => FALSE,
));
}
}
}
/**
* Implementation of hook_link_alter().
*/
function securepages_link_alter(&$links, $node, $comment = NULL) {
if (!variable_get('securepages_enable', 0)) {
return;
}
foreach ($links as $module => $link) {
if (isset($link['href']) && $link['href'] && securepages_can_alter_url($link['href'])) {
$page_match = securepages_match($link['href']);
if ($page_match && !securepages_is_secure()) {
$links[$module]['href'] = securepages_url($link['href'], array(
'secure' => TRUE,
));
}
elseif ($page_match === 0 && securepages_is_secure() && variable_get('securepages_switch', FALSE)) {
$links[$module]['href'] = securepages_url($link['href'], array(
'secure' => FALSE,
));
}
}
}
}
/**
* Check the current page and see if we need to redirect to the secure or
* insecure version of the page.
*/
function securepages_redirect() {
global $base_url;
$path = isset($_GET['q']) ? $_GET['q'] : '';
$page_match = securepages_match($path);
if ($_POST) {
// If something has been posted to here then ignore the rules.
}
elseif ($page_match && !securepages_is_secure()) {
securepages_goto(TRUE);
}
elseif ($page_match === 0 && securepages_is_secure() && variable_get('securepages_switch', FALSE)) {
securepages_goto(FALSE);
}
// Correct the base_url so that everything comes from https.
if (securepages_is_secure()) {
$base_url = securepages_baseurl();
}
}
/**
* securepage_goto()
*
* Redirects the current page to the secure or insecure version.
*
* @param $secure
* Determine which version of the set to move to.
*/
function securepages_goto($secure) {
global $base_root;
$_SESSION['securepages_redirect'] = TRUE;
$path = !empty($_REQUEST['q']) ? $_REQUEST['q'] : '';
$query = count($_GET) > 1 ? securepages_get_query($_GET) : NULL;
$url = securepages_url($path, array(
'query' => $query,
'secure' => $secure,
));
if (function_exists('module_invoke_all')) {
foreach (module_implements('exit') as $module) {
if ($module != 'devel') {
module_invoke($module, 'exit');
}
}
}
else {
bootstrap_invoke_all('exit');
}
header('Location: ' . $url);
// Make sure the cache is clear so that the next page will not pick up a cached version.
cache_clear_all($base_root . request_uri(), 'cache_page');
exit;
}
/**
* securepages_match()
*
* check the page past and see if it should be secure or insecure.
*
* @param $path
* the page of the page to check.
*
* @return
* 0 - page should be insecure.
* 1 - page should be secure.
* NULL - do not change page.
*/
function securepages_match($path) {
/**
* Check to see if the page matches the current settings
*/
$secure = variable_get('securepages_secure', 1);
$pages = variable_get('securepages_pages', "node/add*\nnode/*/edit\nuser/*\nadmin*");
$ignore = variable_get('securepages_ignore', '');
$path = securepages_strtolower(trim($path, '/'));
if ($ignore) {
$regexp = '/^(' . preg_replace(array(
'/(\\r\\n?|\\n)/',
'/\\\\\\*/',
'/(^|\\|)\\\\<front\\\\>($|\\|)/',
), array(
'|',
'.*',
'\\1' . preg_quote(variable_get('site_frontpage', 'node'), '/') . '\\2',
), preg_quote($ignore, '/')) . ')$/';
if (preg_match($regexp, $path)) {
return securepages_is_secure() ? 1 : 0;
}
}
if ($pages) {
$regexp = '/^(' . preg_replace(array(
'/(\\r\\n?|\\n)/',
'/\\\\\\*/',
'/(^|\\|)\\\\<front\\\\>($|\\|)/',
), array(
'|',
'.*',
'\\1' . preg_quote(variable_get('site_frontpage', 'node'), '/') . '\\2',
), preg_quote($pages, '/')) . ')$/';
$result = preg_match($regexp, $path);
if (function_exists('drupal_get_path_alias')) {
$path_alias = drupal_get_path_alias($path);
$result |= preg_match($regexp, $path_alias);
}
return !($secure xor $result) ? 1 : 0;
}
else {
return;
}
}
/**
* Secure Pages SSL Test
*/
function securepages_test() {
// If we are in an SSL page then assume that SSL is configured correctly.
if (securepages_is_secure()) {
return TRUE;
}
$url = 'https://' . preg_replace(';^http[s]?://;s', '', url('admin/build/securepages/test', array(
'absolute' => TRUE,
)));
$response = drupal_http_request($url);
return $response->code == 200 ? TRUE : FALSE;
}
/**
* Check if the current page is SSL
*/
function securepages_is_secure() {
foreach (variable_get('securepages_ssl_checks', array(
'HTTPS' => array(
'on',
'1',
),
'HTTP_X_FORWARDED_PROTO' => 'https',
)) as $key => $value) {
if (isset($_SERVER[$key]) && is_array($value) && in_array($_SERVER[$key], $value)) {
return TRUE;
}
elseif (isset($_SERVER[$key]) && $_SERVER[$key] == $value) {
return TRUE;
}
}
return FALSE;
}
/**
* Generate a URL from a Drupal menu path. Will also pass-through existing URLs.
*
* @param $path
* The Drupal path being linked to, such as "admin/content/node", or an
* existing URL like "http://drupal.org/". The special path
* '<front>' may also be given and will generate the site's base URL.
* @param $options
* An associative array of additional options, with the following keys:
* - 'query'
* A query string to append to the link, or an array of query key/value
* properties.
* - 'fragment'
* A fragment identifier (or named anchor) to append to the link.
* Do not include the '#' character.
* - 'alias' (default FALSE)
* Whether the given path is an alias already.
* - 'external'
* Whether the given path is an external URL.
* - 'language'
* An optional language object. Used to build the URL to link to and
* look up the proper alias for the link.
* - 'base_url'
* Only used internally, to modify the base URL when a language dependent
* URL requires so.
* - 'prefix'
* Only used internally, to modify the path when a language dependent URL
* requires so.
* - 'secure'
* Specifies if the secure or insecure url should be returned.
* @return
* A string containing a URL to the given path.
*
* When creating links in modules, consider whether l() could be a better
* alternative than url().
*/
function securepages_url($path = NULL, $options = array()) {
// Merge in defaults.
$options += array(
'fragment' => '',
'query' => '',
'alias' => FALSE,
'prefix' => '',
'secure' => TRUE,
);
if ($options['fragment']) {
$options['fragment'] = '#' . $options['fragment'];
}
if (is_array($options['query'])) {
$options['query'] = drupal_query_string_encode($options['query']);
}
global $base_url;
static $script;
static $clean_url;
if (!isset($script)) {
// On some web servers, such as IIS, we can't omit "index.php". So, we
// generate "index.php?q=foo" instead of "?q=foo" on anything that is not
// Apache.
$script = strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') === FALSE ? 'index.php' : '';
}
// Cache the clean_url variable to improve performance.
if (!isset($clean_url)) {
$clean_url = (bool) variable_get('clean_url', '0');
}
if (!isset($options['base_url'])) {
// The base_url might be rewritten from the language rewrite in domain mode.
$options['base_url'] = securepages_baseurl($options['secure']);
}
// Preserve the original path before aliasing.
$original_path = $path;
// The special path '<front>' links to the default front page.
if ($path == '<front>') {
$path = '';
}
elseif (!empty($path) && !$options['alias'] && function_exists('drupal_get_path_alias')) {
$path = drupal_get_path_alias($path, isset($options['language']) ? $options['language']->language : '');
}
$base = $options['base_url'] . '/';
$prefix = empty($path) ? rtrim($options['prefix'], '/') : $options['prefix'];
$path = securepages_urlencode($prefix . $path);
if ($clean_url) {
// With Clean URLs.
if ($options['query']) {
return $base . $path . '?' . $options['query'] . $options['fragment'];
}
else {
return $base . $path . $options['fragment'];
}
}
else {
// Without Clean URLs.
$variables = array();
if (!empty($path)) {
$variables[] = 'q=' . $path;
}
if (!empty($options['query'])) {
$variables[] = $options['query'];
}
if ($query = join('&', $variables)) {
return $base . $script . '?' . $query . $options['fragment'];
}
else {
return $base . $options['fragment'];
}
}
}
/**
* Return the secure base path
*/
function securepages_baseurl($secure = TRUE) {
global $base_url;
if ($secure) {
$url = variable_get('securepages_basepath_ssl', NULL);
}
else {
$url = variable_get('securepages_basepath', NULL);
}
if (!empty($url)) {
return $url;
}
// No url has been set, so convert the base_url from 1 to the other
return preg_replace('/http[s]?:\\/\\//i', $secure ? 'https://' : 'http://', $base_url, 1);
}
/**
* Return a querystring without the q paramter
*/
function securepages_get_query($query) {
return trim(str_replace('q=' . $query['q'], '', $_SERVER['QUERY_STRING']), '&');
}
/**
* Copy of Drupals so we can redirect correctly
*/
function securepages_urlencode($text) {
if (variable_get('clean_url', '0')) {
return str_replace(array(
'%2F',
'%26',
'%23',
'//',
), array(
'/',
'%2526',
'%2523',
'/%252F',
), rawurlencode($text));
}
else {
return str_replace('%2F', '/', rawurlencode($text));
}
}
/**
* Lowercase a UTF-8 string.
*
* @param $text
* The string to run the operation on.
*
* @return string
* The string in lowercase.
*
* @ingroup php_wrappers
*/
function securepages_strtolower($text) {
global $multibyte;
if ($multibyte == 1) {
return mb_strtolower($text);
}
else {
// Use C-locale for ASCII-only lowercase
$text = strtolower($text);
// Case flip Latin-1 accented letters
$text = preg_replace_callback('/\\xC3[\\x80-\\x96\\x98-\\x9E]/', '_securepages_unicode_caseflip', $text);
return $text;
}
}
/**
* Helper function for case conversion of Latin-1.
* Used for flipping U+C0-U+DE to U+E0-U+FD and back.
*/
function _securepages_unicode_caseflip($matches) {
return $matches[0][0] . chr(ord($matches[0][1]) ^ 32);
}
/**
* Check the url and make sure that it is a url that you can alter this url.
*/
function securepages_can_alter_url($url) {
global $base_path, $base_url;
$path = '';
@extract(@parse_url($url));
// If there is no scheme then it is a relative url and can be altered
if (!isset($scheme) && $base_path == '/') {
return TRUE;
}
// If the host names are not the same then don't allow altering of the path.
if (isset($host) && strtolower($host) != strtolower($_SERVER['HTTP_HOST'])) {
return FALSE;
}
if (strlen($base_path) > 1 && substr($base_url, -1) != substr($path, 1, strlen($base_path))) {
return FALSE;
}
return TRUE;
}
Functions
Name | Description |
---|---|
securepages_baseurl | Return the secure base path |
securepages_boot | Implementation of hook_boot(). |
securepages_can_alter_url | Check the url and make sure that it is a url that you can alter this url. |
securepages_form_alter | Implementation of hook_form_alter(). |
securepages_get_query | Return a querystring without the q paramter |
securepages_goto | securepage_goto() |
securepages_init | Implementation of hook_init(). |
securepages_is_secure | Check if the current page is SSL |
securepages_link_alter | Implementation of hook_link_alter(). |
securepages_match | securepages_match() |
securepages_menu | Implementation of hook_menu(). |
securepages_redirect | Check the current page and see if we need to redirect to the secure or insecure version of the page. |
securepages_strtolower | Lowercase a UTF-8 string. |
securepages_test | Secure Pages SSL Test |
securepages_url | Generate a URL from a Drupal menu path. Will also pass-through existing URLs. |
securepages_urlencode | Copy of Drupals so we can redirect correctly |
_securepages_unicode_caseflip | Helper function for case conversion of Latin-1. Used for flipping U+C0-U+DE to U+E0-U+FD and back. |