123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416 |
- <?php
- //
- //Note about the include/exclude hooks. As an example, this module includes /cart* which essentially secures ALL cart pages with SSL. But it also implements an exclude which is called /cart Which you would think would negate the include but it DOES NOT. Even though Excludes take presedence over includes, it still allows /cart/1 for example, to be secured. Why? Because the exclude is not a wildcard match! Thus the exclude would NOT match /cart/1 because it's defined as /cart. Thus while /cart IS excluded (not secured with SSL),/cart/1 is STILL secured.
- //Implementation of hook_include_ssl_paths()
- //NOTE: Exclude takes presedence over Includes!!! So if the same path is in both hooks, then the path will be EXCLUDED from secured pages.
- //Since base_url has a design flaw in D4/D5/D6/D7 that seemingly will never be fixed, we fix it here.
- function uc_ssl_boot()
- {
- global $conf;
-
- //the $conf['https'] option MUST be enabled if mixed ssl mode is enabled. We make sure its enabled here. If it's not enabled then user
- //sessions will not persist across the secure and non-secure domain names resulting in the user being prompted to log in whenever they are
- //sent to a secure page.
- if (uc_ssl_switch_to_non_ssl() && !isset($conf['https']) || (isset($conf['https']) && !$conf['https']))
- {
- $conf['https'] = TRUE;
- }
- if ($GLOBALS['base_url'])
- {
- //If base_url exists and is set to a non-secure protocol while the page being called is secure, allow base_url to be changed to
- //the secure version of the website. Drupal for some reason doesnt have this logic anywhere for $base_url.
- if (uc_ssl_page_is_in_https_mode() && stristr($GLOBALS['base_url'], 'http://'))
- {
- $GLOBALS['base_url'] = str_ireplace('http://', 'https://', $GLOBALS['base_url']);
- }
- }
- }
- function uc_ssl_permission()
- {
- $perms = array(
- 'administer uc_ssl' => array(
- 'title' => t('Administer Ubercart SSL settings'),
- ),
- );
- return $perms;
- }
- function uc_ssl_page_is_in_https_mode()
- {
- if (isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']))
- {
- return TRUE;
- }
- return FALSE;
- }
- function uc_ssl_disable_overlay_module()
- {
- $modules = module_list();
- $base_path = base_path();
- if (variable_get('uc_ssl_switch_to_non_ssl', '') && in_array('overlay', $modules))
- {
- //Overlay is on, lets disable it.
- module_disable(array(0 => 'overlay'));
- }
- }
- function uc_ssl_init()
- {
- //Drupals Overlay panel is not secure! Fix that here by disable it all together. We cannot allow this. Drupal 7 is insecure by default, such a sad thing :/
- uc_ssl_disable_overlay_module();
- //menu_rebuild();
- //First and foremost, make sure Clean URLs are on.
- if (uc_ssl_clean_urls_enabled() && !drupal_is_cli())
- {
- //Setup a hook for ssl checking
- uc_ssl_check();
- //Run ssl check on every page load.
- uc_ssl_run();
- }
- }
- function uc_ssl_include_ssl_paths()
- {
- global $user;
- $paths = array(
- 'All Ubercart Cart pages' => '/cart*', //Secure ALL cart pages.
-
- //NOTE: If you remove the /user definition here, you CAN NOT use Mixed SSL Mode with D7. It HAS to exist because D7 http sessions are missing
- //data that https sessions require. But http sessions work with the https session variables. Thus, you MUST login with https or your sessions
- //will not carry between the http and https versions of your wesite. This is a D7 bug only, I believe its more of a feature than a bug.
- 'All User pages' => '/user*', //Secure ALL user pages.
-
- //Added support for Drupal commerce which is based upon Ubercart.
- 'All Drupal Commerce Checkout pages' => '/checkout*', //Secure ALL cart pages. NOTE: SEE EXCLUDES to see why the cart listing itself isnt secured!
-
- //This supports both UC and Commerce admins
- 'All Ubercart Cart Admin pages' => '/admin/store*', //Secure ALL UC admin pages.
- #'example 1' => '/cart', //Only secure the /cart and /cart/ page.
- #'example 2' => 'cart', //Only secure the /cart and /cart/ page.
- #'example 3' => 'cart/', //Only secure the /cart and /cart/ page.
- #'example 4' => '/cart*/something', //matches /cartThis/something and /cart/something but NOT thiscart/something etc.
- #'example 5' => '/cart/*/something', //Matches /cart/123/something and cart/this/something, but NOT /cart/something
- #'example 6' => '/cart/something', //Only secure the /cart/something and /cart/something/ page.
- );
- return $paths;
- }
- //Implementation of hook_exclude_ssl_paths()
- function uc_ssl_exclude_ssl_paths()
- {
- $paths = array(
- //These excludes no longer seem to be required for the D7 version and thus they have been removed until issues come up again.
- //'Exclude the cart page itself' => '/cart', //We dont need to secure the cart contents so we exclude that here
- //'Exclude Autocomplete' => '*autocomplete*',
- //'Exclude Ajax' => '*ajax*',
- #'example 1' => '/cart', //Only exclude the /cart and /cart/ page.
- #'example 2' => 'cart', //Only exclude the /cart and /cart/ page.
- #'example 3' => 'cart/', //Only secure the /cart and /cart/ page.
- #'example 4' => '/cart*/something', //matches /cartThis/something and /cart/something but NOT thiscart/something etc.
- #'example 5' => '/cart/*/something', //Matches /cart/123/something and cart/this/something, but NOT /cart/something
- #'example 6' => '/cart/something', //Only exclude the /cart/something and /cart/something/ page.
- );
- return $paths;
- }
- //Implementation of hook_exclude_ssl_paths()
- //This function is so you can completely ignore ANY switching at all no matter what.
- function uc_ssl_exclude_ssl_switch_paths()
- {
- $paths = array(
- #'example 1' => '/*ajax*', //Dont touch ajax paths whatsoever, this is just an example.
- );
- return $paths;
- }
- function uc_ssl_menu()
- {
- $items = array();
- $items['admin/config/system/uc_ssl'] = array(
- 'title' => 'Ubercart SSL',
- // 'title' => 'Ubercart SSL module settings',
- 'description' => 'Ubercart SSL module settings',
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('uc_ssl_admin'),
- 'access arguments' => array('administer uc_ssl'),
- 'type' => MENU_NORMAL_ITEM,
- 'file' => 'uc_ssl.admin.inc',
- );
- return $items;
- }
- function uc_ssl_enabled()
- {
- return variable_get('uc_ssl_status', '');
- }
- function uc_ssl_is_configured()
- {
- $query = "SELECT count(name) AS count from {variable} WHERE name = 'uc_ssl_status'";
- $results = db_query($query);
- $rows = $results->fetchAll();
- $rows = $rows[0];
- //If uc_ssl is not configured, warn the user and show a link to config it.
- if (!$rows->count)
- {
- $admin_link = 'http://'.$_SERVER['HTTP_HOST'].url().'admin/config/system/uc_ssl';
- drupal_set_message("Please configure Ubercart SSL for SSL enabled cart checkouts to work: <a href = '$admin_link'>$admin_link</a>", 'warning');
- }
- return $rows->count;
- }
- function uc_ssl_switch_to_non_ssl()
- {
- return variable_get('uc_ssl_switch_to_non_ssl', '');
- }
- function uc_ssl_path_match($path, $pages)
- {
- $result = FALSE; //This is here just to get rid of retarded php 'notice' messages. I hate php notices.
- if (!empty($pages))
- {
- //Trim off trailing / and then re-add it to avoid double /'s. This allows cart and cart/ to match as the same thing or cart/1 and cart/1/ to be the same.
- $path = trim($path, '/').'/';
- $regexp = '/^(';
- foreach ($pages AS $key => $regexp_path)
- {
- if ($regexp_path)
- {
- $regexp_path = trim($regexp_path, '/').'/';
- $regexp_path1 = str_replace('/', '\/', $regexp_path); //replace / with a \/
- $regexp_path2 = str_replace('*', '.*', $regexp_path1);//replace * with a .*
- $regexp .= $regexp_path2.'|'; //Append a | to signify end of this expression
- }
- }
- $regexp = trim($regexp, '|');
- $regexp .= ')$/';
- if (variable_get('uc_ssl_case_insensitive', 1))
- {
- $regexp .= 'i';
- }
- $result = preg_match($regexp, $path);
- }
- return $result;
- }
- function is_clean_url($path)
- {
- //Skip ANY ?q= urls since these do NOT come from a web browser when clean URLs is on. Doing this allows us to skip
- //ajax and autocomplete type URLs that come from within drupal itself. This is a major problem with Secure_Pages module
- //and we dont want the same problems so we restrict people to using ONLY clean URLs.
- if (!stristr($path, '?q='))
- {
- return TRUE;
- }
- return FALSE;
- }
- function uc_ssl_http_request($url)
- {
- //Handle JS type urls in the background as they are likely to be ajax type posts.
- if (arg(0) == 'js')
- {
- $js_response = drupal_http_request($url);
- return;
- }
- //Handle post type URLs. This should handle ajax POST urls such as the tax calculation/progress bars.
- if ($_SERVER['REQUEST_METHOD'] == 'POST' && empty($_POST['uc_ssl_post']))
- {
- $_POST['uc_ssl_post'] = 1;
- $options['headers'] = array('Content-Type' => 'application/x-www-form-urlencoded');
- $options['method'] = 'POST';
- $options['data'] = http_build_query($_POST, '', '&');
- //Drupal 7 decided to completely recode drupal_http_request so I dont know if this will cause issues or not. Report any bugs please.
- //$response = drupal_http_request($url, $headers, 'POST', http_build_query($_POST, '', '&'));
- $response = drupal_http_request($url, $options);
- return;
- }
- //All other types of urls are handled normally.
- // Reset destination variables or we'll get sent there instead of to $url
- unset($_REQUEST['destination'], $_GET['destination']);
- drupal_goto($url);
- return;
- }
- function uc_ssl_run()
- {
- //Set the current path without url() since it will mess up regex checks. Using url() also supports languages, base_path does not.
- //$current_path = trim($_SERVER['REQUEST_URI'], url());
- $root = url();
- $current_path = substr(trim($_SERVER['REQUEST_URI']),strlen($root));
- $ssl_domain = variable_get('uc_ssl_ssl_domain', '');
- $nonssl_domain = variable_get('uc_ssl_non_ssl_domain', '');
- //If uc_ssl is configured, run it.
- if (uc_ssl_is_configured() && is_clean_url($current_path))
- {
- if (uc_ssl_enabled())
- {
- //Get a list of all the URL links that should be included and excluded from SSL pages from other modules.
- $items = array();
- $exclude_secured_urls = array();
- $exclude_secured_urls = module_invoke('uc_ssl', 'exclude_ssl_paths', $exclude_secured_urls);
- foreach (module_implements('exclude_ssl_paths') as $module)
- {
- $new = module_invoke($module, 'exclude_ssl_paths', $exclude_secured_urls);
- if ($module != 'uc_ssl') //Skip uc_ssl since we already processed it above. Allow external modules to change uc_ssl defaults.
- {
- if (is_array($new))
- {
- $exclude_secured_urls = array_merge($exclude_secured_urls, $new);
- }
- }
- }
- $include_secured_urls = array();
- $include_secured_urls = module_invoke('uc_ssl', 'include_ssl_paths', $include_secured_urls);
- foreach (module_implements('include_ssl_paths') as $module)
- {
- $new = module_invoke($module, 'include_ssl_paths', $include_secured_urls);
- if ($module != 'uc_ssl') //Skip uc_ssl since we already processed it above. Allow external modules to change uc_ssl defaults.
- {
- if (is_array($new))
- {
- $include_secured_urls = array_merge($include_secured_urls, $new);
- }
- }
- }
-
- // Get a list of all the URL links that should not switch between HTTP/HTTPS at all.
- $exclude_switch_urls = array();
- $exclude_switch_urls = module_invoke('uc_ssl', 'exclude_ssl_switch_paths', $exclude_switch_urls);
- foreach (module_implements('exclude_ssl_switch_paths') as $module)
- {
- $new = module_invoke($module, 'exclude_ssl_switch_paths', $exclude_switch_urls);
- if ($module != 'uc_ssl') //Skip uc_ssl since we already processed it above. Allow external modules to change uc_ssl defaults.
- {
- if (is_array($new))
- {
- $exclude_switch_urls = array_merge($exclude_switch_urls, $new);
- }
- }
- }
- // make sure we return an array
- if (! is_array($include_secured_urls)) { $include_secured_urls = array(); }
- if (! is_array($exclude_secured_urls)) { $exclude_secured_urls = array(); }
- if (! is_array($exclude_switch_urls)) { $exclude_switch_urls = array(); }
-
- //If the path is in the exclude switch hook, dont do ANYTHING at all.
- if (uc_ssl_path_match($current_path, $exclude_switch_urls))
- {
- return;
- }
-
- //Switch to SSL no matter what the link is if Switch isnt on.
- if (!uc_ssl_switch_to_non_ssl())
- {
- if (!uc_ssl_page_is_in_https_mode() && !uc_ssl_path_match($current_path, $exclude_secured_urls))
- {
- uc_ssl_http_request($ssl_domain . $_SERVER['REQUEST_URI']);
- }
- }
- else
- {
- //If uc_ssl_switch_to_non_ssl() is enabled then we switch back to non-ssl link for non-cart links.
- if (uc_ssl_page_is_in_https_mode())
- {
- //The only exceptions are the links listed in the exclude list by other modules.
- if (uc_ssl_path_match($current_path, $exclude_secured_urls))
- {
- uc_ssl_http_request($nonssl_domain . $_SERVER['REQUEST_URI']);
- }
- if (!uc_ssl_path_match($current_path, $include_secured_urls) && uc_ssl_switch_to_non_ssl())
- {
- uc_ssl_http_request($nonssl_domain . $_SERVER['REQUEST_URI']);
- }
- }
- }
- //If on a cart url, use HTTPS and re-post/re-direct to the SSL version of the url.
- if (!uc_ssl_page_is_in_https_mode() && uc_ssl_path_match($current_path, $include_secured_urls) && !uc_ssl_path_match($current_path, $exclude_secured_urls))
- {
- uc_ssl_http_request($ssl_domain . $_SERVER['REQUEST_URI']);
- }
- }
- }
- }
- function uc_ssl_clean_urls_enabled()
- {
- $check = variable_get('clean_url', 0);
- if ($check == 1)
- {
- return TRUE;
- }
- drupal_set_message('Ubercart SSL (uc_ssl): The uc_ssl module REQUIRES that Clean URLs be enabled in order to work properly. This allows the module to distinguish between an Ajax call and a Web browser call as the two are handled differently so we need a way to distinguish them and this is the quickest easiest way to do so. This will also make your website URLs search engine friendly as well which is a good thing. Please enable clean urls here: <a href="?q=admin/settings/clean-urls">Clean URLs</a>', 'warn');
- return FALSE;
- }
- //This is a quickie hook to see if SSL works or not. It's not fool proof but it works for me.
- function uc_ssl_check($site = '')
- {
- error_reporting(E_ALL);
- if (!$site)
- {
- if (isset($_GET['uc_ssl_check']) && $_GET['uc_ssl_check'])
- {
- if (uc_ssl_page_is_in_https_mode())
- {
- echo TRUE;
- }
- else
- {
- echo FALSE;
- }
- exit;
- }
- }
- else
- {
- $check = drupal_http_request($site."?uc_ssl_check=1");
- if (isset($check->data) && $check->data == '1')
- {
- return TRUE;
- }
- //IF we are here, then the request failed for some reason, so we try to use a different method.
- if (ini_get('allow_url_fopen'))
- {
- if (file_get_contents($site."?uc_ssl_check=1") == '1')
- {
- return TRUE;
- }
- }
- //If we are here, something went wrong. Give the user some ideas on what they need to fix.
- drupal_set_message("Ubercart SSL (uc_ssl): The uc_ssl_check() function is returning FALSE because it was unable to contact the SSL (https) version of your website that you defined in the settings. This can be caused by 3 things. 1. Your website is not setup properly for SSL, 2. The OpenSSL extension is not enabled on in your PHP installation, 3. allow_url_fopen is not enabled in php.ini. If #2 fails, uc_ssl will try to use file_get_contents() which requires allow_url_fopen to be set to TRUE in php.ini. Hopefully these hints will help you fix this issue so that you can use uc_ssl. You can try to debug this by going to $site?uc_ssl_check=1", "error");
- }
- return FALSE;
- }
- if (!function_exists('printr'))
- {
- function printr($arr)
- {
- echo "<pre>";
- print_r($arr);
- echo "</pre>";
- }
- }
|