From 4a4a05cfa82fcdf8d90a92773b99c09698b6ea64 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 18 Feb 2010 11:50:18 +0000 Subject: [PATCH] MDL-21637 "bug in some versions of php version 5 prevents cookieless sessions working" --- lib/cookieless.php | 272 +++++++++++++++++++++++++-------------------- lib/setup.php | 1 - 2 files changed, 153 insertions(+), 120 deletions(-) diff --git a/lib/cookieless.php b/lib/cookieless.php index f346ff46939..aa952085050 100644 --- a/lib/cookieless.php +++ b/lib/cookieless.php @@ -13,132 +13,166 @@ * @author Richard at postamble.co.uk and Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU Public License */ -/** -* You won't call this function directly. This function is used to process -* text buffered by php in an output buffer. All output is run through this function -* before it is ouput. -* @param string $buffer is the output sent from php -* @return string the output sent to the browser -*/ -function sid_ob_rewrite($buffer){ - $replacements = array( - '/(<\s*(a|link|script|frame|area|img)\s[^>]*(href|src)\s*=\s*")([^"]*)(")/i', - '/(<\s*(a|link|script|frame|area|img)\s[^>]*(href|src)\s*=\s*\')([^\']*)(\')/i'); - - $buffer = preg_replace_callback($replacements, "sid_rewrite_link_tag", $buffer); - $buffer = preg_replace('/]*>/i', - '\0', $buffer); - - return $buffer; -} -/** -* You won't call this function directly. This function is used to process -* text buffered by php in an output buffer. All output is run through this function -* before it is ouput. -* This function only processes absolute urls, it is used when we decide that -* php is processing other urls itself but needs some help with internal absolute urls still. -* @param string $buffer is the output sent from php -* @return string the output sent to the browser -*/ -function sid_ob_rewrite_absolute($buffer){ - $replacements = array( - '/(<\s*(a|link|script|frame|area|img)\s[^>]*(href|src)\s*=\s*")((?:http|https)[^"]*)(")/i', - '/(<\s*(a|link|script|frame|area|img)\s[^>]*(href|src)\s*=\s*\')((?:http|https)[^\']*)(\')/i'); - - $buffer = preg_replace_callback($replacements, "sid_rewrite_link_tag", $buffer); - $buffer = preg_replace('/]*>/i', - '\0', $buffer); - return $buffer; -} -/** -* A function to process link, a and script tags found -* by preg_replace_callback in {@link sid_ob_rewrite($buffer)}. -*/ -function sid_rewrite_link_tag($matches){ - $url = $matches[4]; - $url=sid_process_url($url); - return $matches[1]. $url.$matches[5]; +class cookieless_sid { + + /** + * @var string Using this variable to store $CFG->wwwroot. Found that in some versions of php the $CFG global was null in + * the callback functions used by the output buffer. + */ + var $httproot = null; + /** + * @var string Using this variable to store $CFG->httpswwwroot. + */ + var $httpsroot = null; + + /** + * @var boolean Using this variable to store $CFG->usesid. + */ + var $usesid = false; + + /** + * You won't call this function directly. This function is used to process + * text buffered by php in an output buffer. All output is run through this function + * before it is ouput. + * @param string $buffer is the output sent from php + * @return string the output sent to the browser + */ + function ob_rewrite($buffer){ + $replacements = array( + '/(<\s*(a|link|script|frame|area)\s[^>]*(href|src)\s*=\s*")([^"]*)(")/i', + '/(<\s*(a|link|script|frame|area)\s[^>]*(href|src)\s*=\s*\')([^\']*)(\')/i'); + + $buffer = preg_replace_callback($replacements, array($this, "rewrite_link_tag"), $buffer); + $buffer = preg_replace('/]*>/i', + '\0', $buffer); + + return $buffer; + } + /** + * You won't call this function directly. This function is used to process + * text buffered by php in an output buffer. All output is run through this function + * before it is ouput. + * This function only processes absolute urls, it is used when we decide that + * php is processing other urls itself but needs some help with internal absolute urls still. + * @param string $buffer is the output sent from php + * @return string the output sent to the browser + */ + function ob_rewrite_absolute($buffer){ + $replacements = array( + '/(<\s*(a|link|script|frame|area)\s[^>]*(href|src)\s*=\s*")((?:http|https)[^"]*)(")/i', + '/(<\s*(a|link|script|frame|area)\s[^>]*(href|src)\s*=\s*\')((?:http|https)[^\']*)(\')/i'); + + $buffer = preg_replace_callback($replacements, array($this, "rewrite_link_tag"), $buffer); + $buffer = preg_replace('/]*>/i', + '\0', $buffer); + return $buffer; + } + /** + * A function to process link, a and script tags found + * by preg_replace_callback in ob_rewrite($buffer). + */ + function rewrite_link_tag($matches){ + $url = $matches[4]; + $url= $this->process_url($url); + return $matches[1]. $url.$matches[5]; + } + /** + * You can call this function directly. This function is used to process + * urls to add a moodle session id to the url for internal links. + * @param string $url is a url + * @return string the processed url + */ + function process_url($url) { + if ((preg_match('/^(http|https):/i', $url)) // absolute url + && ((stripos($url, $this->httproot)!==0) && stripos($url, $this->httpsroot)!==0)) { // and not local one + //error_log("non local url : $url ; \$CFG->wwwroot : ".$this->httproot); + return $url; //don't attach sessid to non local urls + } + if ($url[0]=='#' || (stripos($url, 'javascript:')===0)) { + //error_log("anchor : $url"); + return $url; //don't attach sessid to anchors + } + if (strpos($url, session_name())!==FALSE) + { + //error_log("already has one sessid : $url"); + return $url; //don't attach sessid to url that already has one sessid + } + if (strpos($url, "?")===FALSE){ + $append="?".strip_tags(session_name() . '=' . session_id() ); + } else { + $append="&".strip_tags(session_name() . '=' . session_id() ); + } + //put sessid before any anchor + $p = strpos($url, "#"); + if($p!==FALSE){ + $anch = substr($url, $p); + $url = substr($url, 0, $p).$append.$anch ; + } else { + $url .= $append ; + } + //error_log("added sid : $url"); + return $url; + } + + + + /** + * Call this function before there has been any output to the browser to + * buffer output and add session ids to all internal links. + */ + function start_ob(){ + global $CFG; + + $this->httproot = $CFG->wwwroot; + $this->httpsroot = $CFG->httpswwwroot; + $this->usesid = !empty($CFG->usesid); + + //don't attach sess id for bots + + if (!empty($_SERVER['HTTP_USER_AGENT'])) { + if (!empty($CFG->opentogoogle)) { + if (strpos($_SERVER['HTTP_USER_AGENT'], 'Googlebot') !== false ) { + @ini_set('session.use_trans_sid', '0'); // try and turn off trans_sid + $CFG->usesid=false; + return; + } + if (strpos($_SERVER['HTTP_USER_AGENT'], 'google.com') !== false ) { + @ini_set('session.use_trans_sid', '0'); // try and turn off trans_sid + $CFG->usesid=false; + return; + } + } + if (strpos($_SERVER['HTTP_USER_AGENT'], 'W3C_Validator') !== false ) { + @ini_set('session.use_trans_sid', '0'); // try and turn off trans_sid + $CFG->usesid=false; + return; + } + } + @ini_set('session.use_trans_sid', '1'); // try and turn on trans_sid + if (ini_get('session.use_trans_sid')!=0 ){ + // use trans sid as its available + ini_set('url_rewriter.tags', 'a=href,area=href,script=src,link=href,' + . 'frame=src,form=fakeentry'); + ob_start(array($this, 'ob_rewrite_absolute')); + }else{ + //rewrite all links ourselves + ob_start(array($this, 'ob_rewrite')); + } + } } + +$url_processor_for_cookieless_sessions = new cookieless_sid(); +$url_processor_for_cookieless_sessions->start_ob(); /** * You can call this function directly. This function is used to process * urls to add a moodle session id to the url for internal links. +* Still using this function as a facade to access the instantiated object, +* that actually does the processing, to preserve the old api. * @param string $url is a url * @return string the processed url */ function sid_process_url($url) { - global $CFG; - static $wwwroot = null; - static $httpswwwroot = null; - if ($wwwroot == null){ - $wwwroot = $CFG->wwwroot; - } - if ($httpswwwroot == null){ - $httpswwwroot = $CFG->httpswwwroot; - } - if ((preg_match('/^(http|https):/i', $url)) // absolute url - && ((stripos($url, $wwwroot)!==0) && stripos($url, $httpswwwroot)!==0)) { // and not local one - return $url; //don't attach sessid to non local urls - } - if ($url[0]=='#' || (stripos($url, 'javascript:')===0)) { - return $url; //don't attach sessid to anchors - } - if (strpos($url, session_name())!==FALSE) - { - return $url; //don't attach sessid to url that already has one sessid - } - if (strpos($url, "?")===FALSE){ - $append="?".strip_tags(session_name() . '=' . session_id() ); - } else { - $append="&".strip_tags(session_name() . '=' . session_id() ); - } - //put sessid before any anchor - $p = strpos($url, "#"); - if($p!==FALSE){ - $anch = substr($url, $p); - $url = substr($url, 0, $p).$append.$anch ; - } else { - $url .= $append ; - } - return $url; -} - - -/** -* Call this function before there has been any output to the browser to -* buffer output and add session ids to all internal links. -*/ -function sid_start_ob(){ - global $CFG; - //don't attach sess id for bots - - if (!empty($_SERVER['HTTP_USER_AGENT'])) { - if (!empty($CFG->opentogoogle)) { - if (strpos($_SERVER['HTTP_USER_AGENT'], 'Googlebot') !== false ) { - @ini_set('session.use_trans_sid', '0'); // try and turn off trans_sid - $CFG->usesid=false; - return; - } - if (strpos($_SERVER['HTTP_USER_AGENT'], 'google.com') !== false ) { - @ini_set('session.use_trans_sid', '0'); // try and turn off trans_sid - $CFG->usesid=false; - return; - } - } - if (strpos($_SERVER['HTTP_USER_AGENT'], 'W3C_Validator') !== false ) { - @ini_set('session.use_trans_sid', '0'); // try and turn off trans_sid - $CFG->usesid=false; - return; - } - } - @ini_set('session.use_trans_sid', '1'); // try and turn on trans_sid - if (ini_get('session.use_trans_sid')!=0 ){ - // use trans sid as its available - ini_set('url_rewriter.tags', 'a=href,img=src,area=href,script=src,link=href,' - . 'frame=src,form=fakeentry'); - ob_start('sid_ob_rewrite_absolute'); - }else{ - //rewrite all links ourselves - ob_start('sid_ob_rewrite'); - } + global $url_processor_for_cookieless_sessions; + return $url_processor_for_cookieless_sessions->process_url($url); } ?> diff --git a/lib/setup.php b/lib/setup.php index ec7dcd9dbe4..4dee4a24af2 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -617,7 +617,6 @@ global $HTTPSPAGEREQUIRED; } if (!empty($CFG->usesid) && empty($_COOKIE['MoodleSession'.$CFG->sessioncookie])) { require_once("$CFG->dirroot/lib/cookieless.php"); - sid_start_ob(); } /// In VERY rare cases old PHP server bugs (it has been found on PHP 4.1.2 running /// as a CGI under IIS on Windows) may require that you uncomment the following: