Index: singlesignon/singlesignon.info =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/singlesignon/singlesignon.info,v retrieving revision 1.2 diff -u -r1.2 singlesignon.info --- singlesignon/singlesignon.info 20 Jan 2007 17:19:17 -0000 1.2 +++ singlesignon/singlesignon.info 25 Feb 2008 03:02:48 -0000 @@ -1,5 +1,5 @@ ; $Id: singlesignon.info,v 1.2 2007/01/20 17:19:17 danielc Exp $ -name = "Single Sign-On" -description = "Enables 'Single Sign-Ons' between related Drupal sites on one server with a shared databse." -package = "Authentication" +name = Shared Sign-On +description = Enables shared sign-ons between related Drupal sites on one server with a shared database (previously known as single sign-on). +package = Authentication Index: singlesignon/singlesignon.install =================================================================== RCS file: singlesignon/singlesignon.install diff -N singlesignon/singlesignon.install --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ singlesignon/singlesignon.install 25 Feb 2008 03:02:48 -0000 @@ -0,0 +1,13 @@ +name); + } +} + Index: singlesignon/singlesignon.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/singlesignon/singlesignon.module,v retrieving revision 1.23 diff -u -r1.23 singlesignon.module --- singlesignon/singlesignon.module 22 Jan 2007 13:26:08 -0000 1.23 +++ singlesignon/singlesignon.module 25 Feb 2008 03:02:50 -0000 @@ -60,13 +60,22 @@ * "singlesignon" module is enabled. */ function singlesignon_init() { - global $base_url, $user; + global $base_url, $user, $singlesignon_bot_matches; + + $variable_defaults = array( + 'useragents_case' => '/Google|Yahoo|BlogPulse|ia_archiver|Pingdom|Teoma|Netcraft|Mnogosearch|page-store|libwww-perl|libcurl|del.icio.us/', + 'useragents_nocase' => '/bot|spider/i', + 'client_IP' => '/64.191.203.34/', // Digg + 'target_url' => '/\/cron.php$|\/feed$|\/rss.xml$/', // Allows remote cron, feed, and rss + ); $master_url = variable_get('singlesignon_master_url', ''); - if (!$master_url) { - /* - * If the Master URL isn't set, we can't know what to do, so do nothing. - */ + $singlesignon_bot_matches = variable_get('singlesignon_bot_matches', $variable_defaults); + + if ( + (!$master_url) // If the Master URL isn't set, we can't know what to do, so do nothing + || _singlesignon_is_bot() // Likewise, bots don't sign on + ) { return null; } @@ -273,6 +282,19 @@ return true; } +/** + * Internal function: Tries to determine whether the client is a bot or not + */ +function _singlesignon_is_bot() { + global $singlesignon_bot_matches; + + return( + preg_match($singlesignon_bot_matches['useragents_nocase'], $_SERVER['HTTP_USER_AGENT']) + || preg_match($singlesignon_bot_matches['useragents_case'], $_SERVER['HTTP_USER_AGENT']) + || preg_match($singlesignon_bot_matches['client_IP'], $_SERVER['REMOTE_ADDR']) + || preg_match($singlesignon_bot_matches['target_url'], $_SERVER['REQUEST_URI']) + ); +} // }}} // {{{ other hook functions @@ -294,7 +316,8 @@ $items = array( array( 'path' => 'admin/settings/singlesignon', - 'title' => t('singlesignon'), + 'title' => t('Shared Sign-on'), + 'description' => t('Shares users and sign-ons between sites (previously called "Single Sign-on"'), 'callback' => 'drupal_get_form', 'callback arguments' => 'singlesignon_admin_settings', 'access' => user_access('access administration pages'), @@ -324,7 +347,103 @@ ), ); + $form['singlesignon_bot_matches'] = array( + '#type' => 'fieldset', + '#title' => t('Bot matches'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#tree' => TRUE, + '#description' => << 'textarea', + '#title' => 'Case-sensitive User Agents', + '#rows' => 5, + '#cols' => 40, + '#default_value' => _singlesignon_get_bm_variable('useragents_case'), + '#description' => t('A list of case-sensitive strings that might match a referrer. This is the recommended method'), + ); + $form['singlesignon_bot_matches']['useragents_nocase'] = array( + '#type' => 'textarea', + '#title' => 'Case-insensitive User Agents', + '#rows' => 5, + '#cols' => 40, + '#default_value' => _singlesignon_get_bm_variable('useragents_nocase'), + '#description' => t('A list of case-INsensitive strings that might match a referrer'), + ); + $form['singlesignon_bot_matches']['client_IP'] = array( + '#type' => 'textarea', + '#title' => 'Client IP', + '#rows' => 5, + '#cols' => 40, + '#default_value' => _singlesignon_get_bm_variable('IP'), + '#description' => t("A list of IPs that might match the bot's IP"), + ); + $form['singlesignon_bot_matches']['target_url'] = array( + '#type' => 'textarea', + '#title' => 'Target URL', + '#rows' => 5, + '#cols' => 40, + '#default_value' => _singlesignon_get_bm_variable('target_url'), + '#description' => t('A list of case-sensitive strings that might match a referrer. Not recommended (in general; we have a few specific cases here)'), + ); + return system_settings_form($form); } +/** + * Internal function for use of singlesignon_admin_settings; turns | separated string into \n separated string + * @param $variable: The short name of the singlesignon bot matching variable + * @param $text: The default text for the variable + */ +function _singlesignon_get_bm_variable($variable) { + global $singlesignon_bot_matches; + + return(preg_replace( + array("/^\/(.*?)\/i?$/", "/\|/"), + array("$1", "\n"), + $singlesignon_bot_matches[$variable] + )); +} + +/** + * Hook for validating a form; verifies the values for singlesignon bot recognition + */ +function singlesignon_bot_matches_validate($form_id, $form_values, $form) { + $s['useragents_case'] = _singlesignon_verify_value($form_values, 'useragents_case'); + $s['useragents_nocase'] = _singlesignon_verify_value($form_values, 'useragents_nocase', '', 'i'); + $s['client_IP'] = _singlesignon_verify_value($form_values, 'client_IP', '\d{1-3}\.\d{1-3}\.\d{1-3}\.\d{1-3}'); + $s['target_url'] = _singlesignon_verify_value($form_values, 'target_url', '\\\\\/[A-Za-z0-9_\.]*\$$'); + + form_set_value($form['singlesignon_bot_matches'], $s); +} + +/** + * Internal function: Verifies one singlesignon bot recognition value + * @param $form_values: The values we're validating + * @param $value: The name of the value we're validation + * @param $allowed: A regex specifying what values are allowed + * @param $extras: The regex parameters (ie. 'i' is case insensitive) + */ +function _singlesignon_verify_value($form_values, $value, $allowed = '', $extras = '') { + if($allowed == '') { $allowed = '[A-Za-z0-9_\.]*'; } + if ($form_values['singlesignon_bot_matches'][$value] != '') { + $vals = explode("\n", $form_values['singlesignon_bot_matches'][$value]); + foreach($vals as $val) { + $val = preg_replace("/^\s*(.*?)\s*$/", "$1", $val); + if(preg_match("/^$allowed$/", $val)) { + $rvals[] = $val; + } else { + form_set_error('', t("The strings in $value contain non-word characters (we allow $allowed at the moment, and '" . $val . "' is a problem)")); + } + } + return('/' . join('|', $rvals) . "/$extras"); + } + return($form_values['singlesignon_bot_matches'][$value]); +} + // }}}