'admin/settings/securepages', 'title' => t('Secure Pages'), 'description' => t('Configure which pages are and are not to be viewed in SSL'), 'callback' => 'drupal_get_form', 'callback arguments' => 'securepages_settings', 'access' => user_access('administer site configuration'), 'type' => MENU_NORMAL_ITEM, ); } return $items; } /** * Implementation of hook_settings() */ function securepages_settings() { $form = array(); $form['securepages_enable'] = array( '#type' => 'radios', '#title' => t('Enable Secure Pages'), '#default_value' => variable_get('securepages_enable', 0), '#options' => array(t('Disabled'), t('Enabled')), '#disabled' => !securepages_test(), '#description' => t('To start using secure pages this setting must be enabled. This setting will only be able to changed when the web server has been configured for SSL.
If this test has failed then go here', array('!url' => preg_replace(';^http://;i', 'https://', url($_GET['q'], NULL, NULL, TRUE)))), ); $form['securepages_switch'] = array( '#type' => 'checkbox', '#title' => t('Switch back to http pages when there are no matches'), '#return_value' => TRUE, '#default_value' => variable_get('securepages_switch', FALSE), ); $form['securepages_basepath'] = array( '#type' => 'textfield', '#title' => t('Non-secure Base URL'), '#default_value' => variable_get('securepages_basepath', ''), ); $form['securepages_basepath_ssl'] = array( '#type' => 'textfield', '#title' => t('Secure Base URL'), '#default_value' => variable_get('securepages_basepath_ssl', ''), ); $form['securepages_secure'] = array( '#type' => 'radios', '#title' => t('Pages which will be be secure'), '#default_value' => variable_get('securepages_secure', 1), '#options' => array(t('Make secure every page except the listed pages.'), t('Make secure only the listed pages.')), ); $form['securepages_pages'] = array( '#type' => 'textarea', '#title' => t('Pages'), '#default_value' => variable_get('securepages_pages', "node/add*\nnode/*/edit\nuser/*\nadmin*"), '#cols' => 40, '#rows' => 5, '#description' => t("Enter one page per line as Drupal paths. The '*' character is a wildcard. Example paths are 'blog' for the blog page and 'blog/*' for every personal blog. '<front>' is the front page."), ); $form['securepages_ignore'] = array( '#type' => 'textarea', '#title' => t('Ignore pages'), '#default_value' => variable_get('securepages_ignore', "*/autocomplete/*"), '#cols' => 40, '#rows' => 5, '#description' => t("The pages listed here will be ignored and be either returned in http or https. Enter one page per line as Drupal paths. The '*' character is a wildcard. Example paths are 'blog' for the blog page and 'blog/*' for every personal blog. '<front>' is the front page."), ); return system_settings_form($form); } /** * Implementation of hook_form_alter() */ function securepages_form_alter($form_id, &$form) { if (!variable_get('securepages_enable', 0)) { return; } if (isset($form['#action']) && securepages_can_alter_url($form['#action'])) { extract(parse_url($form['#action'])); parse_str($query, $query); if (isset($query['q'])) { $path = $query['q']; } else { $base_path = base_path(); $path = (!strncmp($path, $base_path, strlen($base_path)) ? substr($path, 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, $query, NULL, TRUE); } elseif ($page_match === 0 && securepages_is_secure() && variable_get('securepages_switch', FALSE)) { $form['#action'] = securepages_url($path, $query, NULL, FALSE); } } } /** * Implementation of hook_link_alter() */ function securepages_link_alter(&$node, &$links) { if (!variable_get('securepages_enable', 0)) { return; } foreach ($links as $module => $link) { if ($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'], NULL, NULL, TRUE); } elseif ($page_match === 0 && securepages_is_secure() && variable_get('securepages_switch', FALSE)) { $links[$module]['href'] = securepages_url($link['href'], NULL, NULL, FALSE); } } } } /** * 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) { $path = !empty($_REQUEST['q']) ? $_REQUEST['q'] : ''; $query = count($_GET) > 1 ? securepages_get_query($_GET) : NULL; $url = securepages_url($path, $query, NULL, $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); 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 current menu item has a preference and ignore the * secure pages settings */ if (function_exists('menu_get_item')) { $item = menu_get_item(menu_get_active_item()); if (isset($item['secure'])) { return $item['secure']; } } /** * 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', "*/autocomplete/*\n*/ajax/*"); if ($ignore) { $regexp = '/^('. preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/', '/(^|\|)\\\\($|\|)/'), 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)/', '/\\\\\*/', '/(^|\|)\\\\($|\|)/'), array('|', '.*', '\1'. preg_quote(variable_get('site_frontpage', 'node'), '/') .'\2'), preg_quote($pages, '/')) .')$/'; return !($secure xor preg_match($regexp, $path)) ? 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/settings/securepages/test', NULL, NULL, TRUE)); $response = drupal_http_request($url); return $response->code == 200 ? TRUE : FALSE; } /** * Check if the current page is SSL */ function securepages_is_secure() { return (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? TRUE : FALSE; } /** * Generate a URL from a Drupal menu path. Will also pass-through existing URLs. * * When creating links in modules, consider whether l() could be a better alternative than url(). * */ function securepages_url($path = NULL, $query = NULL, $fragment = NULL, $secure = FALSE) { if (isset($fragment)) { $fragment = '#'. $fragment; } // Return an external link if $path contains an allowed absolute URL. // Only call the slow filter_xss_bad_protocol if $path contains a ':' before any / ? or #. $colonpos = strpos($path, ':'); if ($colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && filter_xss_bad_protocol($path, FALSE) == check_plain($path)) { // Split off the fragment if (strpos($path, '#') !== FALSE) { list($path, $old_fragment) = explode('#', $path, 2); if (isset($old_fragment) && !isset($fragment)) { $fragment = '#'. $old_fragment; } } // Append the query if (isset($query)) { $path .= (strpos($path, '?') !== FALSE ? '&' : '?') . $query; } // Reassemble return $path . $fragment; } 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'); } $base = securepages_baseurl($secure) .'/'; // The special path '' links to the default front page. if (!empty($path) && $path != '' && function_exists('drupal_get_path_alias')) { $path = drupal_get_path_alias($path); $path = drupal_urlencode($path); if (!$clean_url) { if (!empty($query)) { return $base . $script .'?q='. $path .'&'. $query . $fragment; } else { return $base . $script .'?q='. $path . $fragment; } } else { if (!empty($query)) { return $base . $path .'?'. $query . $fragment; } else { return $base . $path . $fragment; } } } else { if (!empty($query)) { return $base . $script .'?'. $query . $fragment; } else { return $base . $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) { unset($query['q']); $q = array(); foreach ($query as $key => $value) { $q[] = drupal_urlencode($key) .'='. drupal_urlencode($value); } return implode('&', $q); } /** * 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'), urlencode($text)); } else { return str_replace('%2F', '/', urlencode($text)); } } /** * 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; 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 (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; }