示例#1
0
/**
 * Write the jsConnect string for single sign on.
 *
 * @param array $User An array containing information about the currently signed on user. If no user is signed in then this should be an empty array.
 * @param array $Request An array of the $_GET request.
 * @param string $ClientID The string client ID that you set up in the jsConnect settings page.
 * @param string $Secret The string secred that you set up in the jsConnect settings page.
 * @param string|bool $Secure Whether or not to check for security. This is one of these values.
 *  - true: Check for security and sign the response with an md5 hash.
 *  - false: Don't check for security, but sign the response with an md5 hash.
 *  - string: Check for security and sign the response with the given hash algorithm. See hash_algos() for what your server can support.
 *  - null: Don't check for security and don't sign the response.
 * @since 1.1b Added the ability to provide a hash algorithm to $Secure.
 */
function writeJsConnect($User, $Request, $ClientID, $Secret, $Secure = true)
{
    $User = array_change_key_case($User);
    // Error checking.
    if ($Secure) {
        // Check the client.
        if (!isset($Request['client_id'])) {
            $Error = ['error' => 'invalid_request', 'message' => 'The client_id parameter is missing.'];
        } elseif ($Request['client_id'] != $ClientID) {
            $Error = ['error' => 'invalid_client', 'message' => "Unknown client {$Request['client_id']}."];
        } elseif (!isset($Request['timestamp']) && !isset($Request['signature'])) {
            if (is_array($User) && count($User) > 0) {
                // This isn't really an error, but we are just going to return public information when no signature is sent.
                $Error = ['name' => $User['name'], 'photourl' => @$User['photourl']];
            } else {
                $Error = ['name' => '', 'photourl' => ''];
            }
        } elseif (!isset($Request['timestamp']) || !is_numeric($Request['timestamp'])) {
            $Error = ['error' => 'invalid_request', 'message' => 'The timestamp parameter is missing or invalid.'];
        } elseif (!isset($Request['signature'])) {
            $Error = ['error' => 'invalid_request', 'message' => 'Missing  signature parameter.'];
        } elseif (($Diff = abs($Request['timestamp'] - jsTimestamp())) > JS_TIMEOUT) {
            $Error = ['error' => 'invalid_request', 'message' => 'The timestamp is invalid.'];
        } else {
            // Make sure the timestamp hasn't timed out.
            $Signature = jsHash($Request['timestamp'] . $Secret, $Secure);
            if ($Signature != $Request['signature']) {
                $Error = ['error' => 'access_denied', 'message' => 'Signature invalid.'];
            }
        }
    }
    if (isset($Error)) {
        $Result = $Error;
    } elseif (is_array($User) && count($User) > 0) {
        if ($Secure === null) {
            $Result = $User;
        } else {
            $Result = signJsConnect($User, $ClientID, $Secret, $Secure, true);
        }
    } else {
        $Result = ['name' => '', 'photourl' => ''];
    }
    $Json = json_encode($Result);
    if (isset($Request['callback'])) {
        safeHeader('Content-Type: application/javascript');
        echo "{$Request['callback']}({$Json})";
    } else {
        safeHeader('Content-Type: application/json');
        echo $Json;
    }
}
 /**
  * Authenticate the user attempting to sign in.
  *
  * Events: BeforeAuth
  *
  * @since 2.0.0
  * @access public
  *
  * @param string $AuthenticationSchemeAlias Type of authentication we're attempting.
  */
 public function auth($AuthenticationSchemeAlias = 'default')
 {
     Gdn::session()->ensureTransientKey();
     $this->EventArguments['AuthenticationSchemeAlias'] = $AuthenticationSchemeAlias;
     $this->fireEvent('BeforeAuth');
     // Allow hijacking auth type
     $AuthenticationSchemeAlias = $this->EventArguments['AuthenticationSchemeAlias'];
     // Attempt to set Authenticator with requested method or fallback to default
     try {
         $Authenticator = Gdn::authenticator()->authenticateWith($AuthenticationSchemeAlias);
     } catch (Exception $e) {
         $Authenticator = Gdn::authenticator()->authenticateWith('default');
     }
     // Set up controller
     $this->View = 'auth/' . $Authenticator->getAuthenticationSchemeAlias();
     $this->Form->setModel($this->UserModel);
     $this->Form->addHidden('ClientHour', date('Y-m-d H:00'));
     // Use the server's current hour as a default.
     $Target = $this->target();
     $this->Form->addHidden('Target', $Target);
     // Import authenticator data source
     switch ($Authenticator->dataSourceType()) {
         case Gdn_Authenticator::DATA_FORM:
             $Authenticator->fetchData($this->Form);
             break;
         case Gdn_Authenticator::DATA_REQUEST:
         case Gdn_Authenticator::DATA_COOKIE:
             $Authenticator->fetchData(Gdn::request());
             break;
     }
     // By default, just render the view
     $Reaction = Gdn_Authenticator::REACT_RENDER;
     // Where are we in the process? Still need to gather (render view) or are we validating?
     $AuthenticationStep = $Authenticator->currentStep();
     switch ($AuthenticationStep) {
         // User is already logged in
         case Gdn_Authenticator::MODE_REPEAT:
             $Reaction = $Authenticator->repeatResponse();
             break;
             // Not enough information to perform authentication, render input form
         // Not enough information to perform authentication, render input form
         case Gdn_Authenticator::MODE_GATHER:
             $this->addJsFile('entry.js');
             $Reaction = $Authenticator->loginResponse();
             if ($this->Form->isPostBack()) {
                 $this->Form->addError('ErrorCredentials');
                 Logger::event('signin_failure', Logger::WARNING, '{username} failed to sign in. Some or all credentials were missing.');
             }
             break;
             // All information is present, authenticate
         // All information is present, authenticate
         case Gdn_Authenticator::MODE_VALIDATE:
             // Attempt to authenticate.
             try {
                 if (!$this->Request->isAuthenticatedPostBack() && !c('Garden.Embed.Allow')) {
                     $this->Form->addError('Please try again.');
                     $Reaction = $Authenticator->failedResponse();
                 } else {
                     $AuthenticationResponse = $Authenticator->authenticate();
                     $UserInfo = array();
                     $UserEventData = array_merge(array('UserID' => Gdn::session()->UserID, 'Payload' => val('HandshakeResponse', $Authenticator, false)), $UserInfo);
                     Gdn::authenticator()->trigger($AuthenticationResponse, $UserEventData);
                     switch ($AuthenticationResponse) {
                         case Gdn_Authenticator::AUTH_PERMISSION:
                             $this->Form->addError('ErrorPermission');
                             Logger::event('signin_failure', Logger::WARNING, '{username} failed to sign in. Permission denied.');
                             $Reaction = $Authenticator->failedResponse();
                             break;
                         case Gdn_Authenticator::AUTH_DENIED:
                             $this->Form->addError('ErrorCredentials');
                             Logger::event('signin_failure', Logger::WARNING, '{username} failed to sign in. Authentication denied.');
                             $Reaction = $Authenticator->failedResponse();
                             break;
                         case Gdn_Authenticator::AUTH_INSUFFICIENT:
                             // Unable to comply with auth request, more information is needed from user.
                             Logger::event('signin_failure', Logger::WARNING, '{username} failed to sign in. More information needed from user.');
                             $this->Form->addError('ErrorInsufficient');
                             $Reaction = $Authenticator->failedResponse();
                             break;
                         case Gdn_Authenticator::AUTH_PARTIAL:
                             // Partial auth completed.
                             $Reaction = $Authenticator->partialResponse();
                             break;
                         case Gdn_Authenticator::AUTH_SUCCESS:
                         default:
                             // Full auth completed.
                             if ($AuthenticationResponse == Gdn_Authenticator::AUTH_SUCCESS) {
                                 $UserID = Gdn::session()->UserID;
                             } else {
                                 $UserID = $AuthenticationResponse;
                             }
                             safeHeader("X-Vanilla-Authenticated: yes");
                             safeHeader("X-Vanilla-TransientKey: " . Gdn::session()->transientKey());
                             $Reaction = $Authenticator->successResponse();
                     }
                 }
             } catch (Exception $Ex) {
                 $this->Form->addError($Ex);
             }
             break;
         case Gdn_Authenticator::MODE_NOAUTH:
             $Reaction = Gdn_Authenticator::REACT_REDIRECT;
             break;
     }
     switch ($Reaction) {
         case Gdn_Authenticator::REACT_RENDER:
             // Do nothing (render the view)
             break;
         case Gdn_Authenticator::REACT_EXIT:
             exit;
             break;
         case Gdn_Authenticator::REACT_REMOTE:
             // Let the authenticator handle generating output, using a blank slate
             $this->_DeliveryType = DELIVERY_TYPE_VIEW;
             exit;
             break;
         case Gdn_Authenticator::REACT_REDIRECT:
         default:
             if (is_string($Reaction)) {
                 $Route = $Reaction;
             } else {
                 $Route = $this->redirectTo();
             }
             if ($this->_RealDeliveryType != DELIVERY_TYPE_ALL && $this->_DeliveryType != DELIVERY_TYPE_ALL) {
                 $this->RedirectUrl = url($Route);
             } else {
                 if ($Route !== false) {
                     redirect($Route);
                 } else {
                     redirect(Gdn::router()->getDestination('DefaultController'));
                 }
             }
             break;
     }
     $this->setData('SendWhere', "/entry/auth/{$AuthenticationSchemeAlias}");
     $this->render();
 }
 /**
  * Display 'no permission' page.
  *
  * @since 2.0.0
  * @access public
  */
 public function unauthorized()
 {
     Gdn_Theme::section('Error');
     if ($this->deliveryMethod() == DELIVERY_METHOD_XHTML) {
         safeHeader("HTTP/1.0 401", true, 401);
         $this->render();
     } else {
         $this->RenderException(permissionException());
     }
 }
示例#4
0
 * here, but some things have already been loaded and are immutable.
 */
if (file_exists(PATH_CONF . '/bootstrap.early.php')) {
    require_once PATH_CONF . '/bootstrap.early.php';
}
Gdn::config()->caching(true);
debug(c('Debug', false));
setHandlers();
/**
 * Installer Redirect
 *
 * If Garden is not yet installed, force the request to /dashboard/setup and
 * begin installation.
 */
if (Gdn::config('Garden.Installed', false) === false && strpos(Gdn_Url::request(), 'setup') === false) {
    safeHeader('Location: ' . Gdn::request()->url('dashboard/setup', true));
    exit;
}
/**
 * Extension Managers
 *
 * Now load the Addon, Application, Theme and Plugin managers into the Factory, and
 * process the application-specific configuration defaults.
 */
// ApplicationManager
Gdn::factoryInstall(Gdn::AliasApplicationManager, 'Gdn_ApplicationManager', '', Gdn::FactorySingleton, [Gdn::addonManager()]);
// ThemeManager
Gdn::factoryInstall(Gdn::AliasThemeManager, 'Gdn_ThemeManager', '', Gdn::FactorySingleton, [Gdn::addonManager()]);
// PluginManager
Gdn::factoryInstall(Gdn::AliasPluginManager, 'Gdn_PluginManager', '', Gdn::FactorySingleton, [Gdn::addonManager()]);
// Start the addons, plugins, and applications.
示例#5
0
 public function ServeCss($ThemeType, $Filename)
 {
     // Split the filename into filename and etag.
     if (preg_match('`([\\w_-]+?)-(\\w+).css$`', $Filename, $Matches)) {
         $Basename = $Matches[1];
         $ETag = $Matches[2];
     } else {
         throw NotFoundException();
     }
     $Basename = ucfirst($Basename);
     $this->EventArguments['Basename'] = $Basename;
     $this->EventArguments['ETag'] = $ETag;
     $this->FireEvent('BeforeServeCss');
     if (function_exists('header_remove')) {
         header_remove('Set-Cookie');
     }
     safeHeader("Content-Type: text/css");
     if (!in_array($Basename, array('Style', 'Admin'))) {
         safeHeader("HTTP/1.0 404", TRUE, 404);
         echo "/* Could not find {$Basename}/{$ETag} */";
         die;
     }
     $RequestETags = GetValue('HTTP_IF_NONE_MATCH', $_SERVER);
     if (get_magic_quotes_gpc()) {
         $RequestETags = stripslashes($RequestETags);
     }
     $RequestETags = explode(',', $RequestETags);
     foreach ($RequestETags as $RequestETag) {
         if ($RequestETag == $ETag) {
             safeHeader("HTTP/1.0 304", TRUE, 304);
             die;
         }
     }
     safeHeader("Cache-Control:public, max-age=14400");
     $CurrentETag = self::ETag();
     safeHeader("ETag: {$CurrentETag}");
     $CachePath = PATH_CACHE . '/css/' . CLIENT_NAME . '-' . $ThemeType . '-' . strtolower($Basename) . "-{$CurrentETag}.css";
     if (!Debug() && file_exists($CachePath)) {
         readfile($CachePath);
         die;
     }
     // Include minify...
     set_include_path(PATH_LIBRARY . "/vendors/Minify/lib" . PATH_SEPARATOR . get_include_path());
     require_once PATH_LIBRARY . "/vendors/Minify/lib/Minify/CSS.php";
     ob_start();
     echo "/* CSS generated for etag: {$CurrentETag}.\n *\n";
     $Paths = $this->GetCssFiles($ThemeType, $Basename, $ETag, $NotFound);
     // First, do a pass through the files to generate some information.
     foreach ($Paths as $Info) {
         list($Path, $UrlPath) = $Info;
         echo " * {$UrlPath}\n";
     }
     // Echo the paths that weren't found to help debugging.
     foreach ($NotFound as $Info) {
         list($Filename, $Folder) = $Info;
         echo " * {$Folder}/{$Filename} NOT FOUND.\n";
     }
     echo " */\n\n";
     // Now that we have all of the paths we want to serve them.
     foreach ($Paths as $Info) {
         list($Path, $UrlPath, $Options) = $Info;
         echo "/* File: {$UrlPath} */\n";
         $Css = GetValue('Css', $Options);
         if (!$Css) {
             $Css = file_get_contents($Path);
         }
         $Css = Minify_CSS::minify($Css, array('preserveComments' => TRUE, 'prependRelativePath' => $this->UrlPrefix . Asset(dirname($UrlPath) . '/'), 'currentDir' => dirname($Path), 'minify' => TRUE));
         echo $Css;
         echo "\n\n";
     }
     // Create a cached copy of the file.
     $Css = ob_get_flush();
     if (!file_exists(dirname($CachePath))) {
         mkdir(dirname($CachePath), 0775, TRUE);
     }
     file_put_contents($CachePath, $Css);
 }
示例#6
0
 /**
  * Serve all CSS files.
  *
  * @param $themeType
  * @param $filename
  * @throws Exception
  */
 public function serveCss($themeType, $filename)
 {
     // Split the filename into filename and etag.
     if (preg_match('`([\\w-]+?)-(\\w+).css$`', $filename, $matches)) {
         $basename = $matches[1];
         $eTag = $matches[2];
     } else {
         throw notFoundException();
     }
     $basename = strtolower($basename);
     $this->EventArguments['Basename'] = $basename;
     $this->EventArguments['ETag'] = $eTag;
     $this->fireEvent('BeforeServeCss');
     if (function_exists('header_remove')) {
         header_remove('Set-Cookie');
     }
     // Get list of anchor files
     $anchors = $this->getAnchors();
     safeHeader("Content-Type: text/css");
     $anchorFileName = "{$basename}.css";
     if (!in_array($anchorFileName, $anchors)) {
         safeHeader("HTTP/1.0 404", true, 404);
         echo "/* Could not find {$basename}/{$eTag} */";
         die;
     }
     $requestETags = val('HTTP_IF_NONE_MATCH', $_SERVER);
     $requestETags = explode(',', $requestETags);
     foreach ($requestETags as $requestETag) {
         if ($requestETag == $eTag) {
             safeHeader("HTTP/1.0 304", true, 304);
             die;
         }
     }
     safeHeader("Cache-Control:public, max-age=14400");
     $currentETag = self::eTag();
     safeHeader("ETag: {$currentETag}");
     $cachePath = PATH_CACHE . '/css/' . CLIENT_NAME . '-' . $themeType . '-' . "{$basename}-{$currentETag}.css";
     if (!Debug() && file_exists($cachePath)) {
         readfile($cachePath);
         die;
     }
     // Include minify...
     set_include_path(PATH_LIBRARY . "/vendors/Minify/lib" . PATH_SEPARATOR . get_include_path());
     require_once PATH_LIBRARY . "/vendors/Minify/lib/Minify/CSS.php";
     ob_start();
     echo "/* CSS generated for etag: {$currentETag}.\n *\n";
     $notFound = [];
     $paths = $this->getCssFiles($themeType, $basename, $eTag, $notFound);
     // First, do a pass through the files to generate some information.
     foreach ($paths as $info) {
         list($path, $urlPath) = $info;
         echo " * {$urlPath}\n";
     }
     // Echo the paths that weren't found to help debugging.
     foreach ($notFound as $info) {
         list($filename, $folder) = $info;
         echo " * {$folder}/{$filename} NOT FOUND.\n";
     }
     echo " */\n\n";
     // Now that we have all of the paths we want to serve them.
     foreach ($paths as $info) {
         list($path, $urlPath, $options) = $info;
         echo "/* File: {$urlPath} */\n";
         $css = val('Css', $options);
         if (!$css) {
             $css = file_get_contents($path);
         }
         $css = Minify_CSS::minify($css, ['preserveComments' => true, 'prependRelativePath' => $this->UrlPrefix . asset(dirname($urlPath) . '/'), 'currentDir' => dirname($path), 'minify' => true]);
         echo $css;
         echo "\n\n";
     }
     // Create a cached copy of the file.
     $css = ob_get_flush();
     if (!file_exists(dirname($cachePath))) {
         mkdir(dirname($cachePath), 0775, true);
     }
     file_put_contents($cachePath, $css);
 }
示例#7
0
 /**
  * Serves a file to the browser.
  *
  * @param string $File Full path to the file being served.
  * @param string $Name Name to give the file being served. Including extension overrides $File extension. Uses $File filename if empty.
  * @param string $MimeType The mime type of the file.
  * @param string $ServeMode Whether to download the file as an attachment, or inline
  */
 public static function serveFile($File, $Name = '', $MimeType = '', $ServeMode = 'attachment')
 {
     $FileIsLocal = substr($File, 0, 4) == 'http' ? false : true;
     $FileAvailable = $FileIsLocal ? is_readable($File) : true;
     if ($FileAvailable) {
         // Close the database connection
         Gdn::database()->closeConnection();
         // Determine if Path extension should be appended to Name
         $NameExtension = strtolower(pathinfo($Name, PATHINFO_EXTENSION));
         $FileExtension = strtolower(pathinfo($File, PATHINFO_EXTENSION));
         if ($NameExtension == '') {
             if ($Name == '') {
                 $Name = pathinfo($File, PATHINFO_FILENAME) . '.' . $FileExtension;
             } elseif (!stringEndsWith($Name, '.' . $FileExtension)) {
                 $Name .= '.' . $FileExtension;
             }
         } else {
             $Extension = $NameExtension;
         }
         $Name = rawurldecode($Name);
         // Figure out the MIME type
         $MimeTypes = array("pdf" => "application/pdf", "txt" => "text/plain", "html" => "text/html", "htm" => "text/html", "exe" => "application/octet-stream", "zip" => "application/zip", "doc" => "application/msword", "xls" => "application/vnd.ms-excel", "ppt" => "application/vnd.ms-powerpoint", "gif" => "image/gif", "png" => "image/png", "jpeg" => "image/jpg", "jpg" => "image/jpg", "php" => "text/plain", "ico" => "image/vnd.microsoft.icon");
         if ($MimeType == '') {
             if (array_key_exists($FileExtension, $MimeTypes)) {
                 $MimeType = $MimeTypes[$FileExtension];
             } else {
                 $MimeType = 'application/force-download';
             }
         }
         @ob_end_clean();
         // required for IE, otherwise Content-Disposition may be ignored
         if (ini_get('zlib.output_compression')) {
             ini_set('zlib.output_compression', 'Off');
         }
         if ($ServeMode == 'inline') {
             safeHeader('Content-Disposition: inline; filename="' . $Name . '"');
         } else {
             safeHeader('Content-Disposition: attachment; filename="' . $Name . '"');
         }
         safeHeader('Content-Type: ' . $MimeType);
         safeHeader("Content-Transfer-Encoding: binary");
         safeHeader('Accept-Ranges: bytes');
         safeHeader("Cache-control: private");
         safeHeader('Pragma: private');
         safeHeader("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
         readfile($File);
         exit;
     } else {
         die('not readable');
     }
 }
示例#8
0
 /**
  * Set P3P header because IE won't allow cookies thru the iFrame without it.
  *
  * This must be done in the Dispatcher because of PrivateCommunity.
  * That precludes using Controller->SetHeader.
  * This is done so comment & forum embedding can work in old IE.
  */
 public function Gdn_Dispatcher_AppStartup_Handler($Sender)
 {
     safeHeader('P3P: CP="CAO PSA OUR"', TRUE);
     if ($SSO = Gdn::Request()->Get('sso')) {
         SaveToConfig('Garden.Registration.SendConnectEmail', FALSE, FALSE);
         $IsApi = preg_match('`\\.json$`i', Gdn::Request()->Path());
         $UserID = FALSE;
         try {
             $CurrentUserID = Gdn::Session()->UserID;
             $UserID = Gdn::UserModel()->SSO($SSO);
         } catch (Exception $Ex) {
             Trace($Ex, TRACE_ERROR);
         }
         if ($UserID) {
             Gdn::Session()->Start($UserID, !$IsApi, !$IsApi);
             if ($UserID != $CurrentUserID) {
                 Gdn::UserModel()->FireEvent('AfterSignIn');
             }
         } else {
             // There was some sort of error. Let's print that out.
             Trace(Gdn::UserModel()->Validation->ResultsText(), TRACE_WARNING);
         }
     }
 }
示例#9
0
// ThemeManager
Gdn::FactoryInstall(Gdn::AliasThemeManager, 'Gdn_ThemeManager');
// PluginManager
Gdn::FactoryInstall(Gdn::AliasPluginManager, 'Gdn_PluginManager');
// Load the configurations for enabled Applications
foreach (Gdn::ApplicationManager()->EnabledApplicationFolders() as $ApplicationName => $ApplicationFolder) {
    Gdn::Config()->Load(PATH_APPLICATIONS . "/{$ApplicationFolder}/settings/configuration.php");
}
/**
 * Installer Redirect
 *
 * If Garden is not yet installed, force the request to /dashboard/setup and
 * begin installation.
 */
if (Gdn::Config('Garden.Installed', FALSE) === FALSE && strpos(Gdn_Url::Request(), 'setup') === FALSE) {
    safeHeader('Location: ' . Gdn::Request()->Url('dashboard/setup', TRUE));
    exit;
}
// Re-apply loaded user settings
Gdn::Config()->OverlayDynamic();
/**
 * Bootstrap Late
 *
 * All configurations are loaded, as well as the Application, Plugin and Theme
 * managers.
 */
if (file_exists(PATH_CONF . '/bootstrap.late.php')) {
    require_once PATH_CONF . '/bootstrap.late.php';
}
if (C('Debug')) {
    Debug(TRUE);
 function Redirect($Destination = FALSE, $StatusCode = NULL)
 {
     if (!$Destination) {
         $Destination = Url('');
     }
     //      if (Debug() && $Trace = Trace()) {
     //         Trace("Redirecting to $Destination");
     //         return;
     //      }
     // Close any db connections before exit
     $Database = Gdn::Database();
     $Database->CloseConnection();
     // Clear out any previously sent content
     @ob_end_clean();
     // assign status code
     $SendCode = is_null($StatusCode) ? 302 : $StatusCode;
     // re-assign the location header
     safeHeader("Location: " . Url($Destination), TRUE, $SendCode);
     // Exit
     exit;
 }
示例#11
0
 /**
  * Display 'no permission' page.
  *
  * @since 2.0.0
  * @access public
  */
 public function Permission()
 {
     Gdn_Theme::Section('Error');
     if ($this->DeliveryMethod() == DELIVERY_METHOD_XHTML) {
         safeHeader("HTTP/1.0 401", TRUE, 401);
         $this->Render();
     } else {
         $this->RenderException(PermissionException());
     }
 }
示例#12
0
 /**
  * Parses the query string looking for supplied request parameters. Places
  * anything useful into this object's Controller properties.
  *
  * @param int $FolderDepth
  */
 protected function analyzeRequest(&$Request)
 {
     // Here is the basic format of a request:
     // [/application]/controller[/method[.json|.xml]]/argn|argn=valn
     // Here are some examples of what this method could/would receive:
     // /application/controller/method/argn
     // /controller/method/argn
     // /application/controller/argn
     // /controller/argn
     // /controller
     // Clear the slate
     $this->_ApplicationFolder = '';
     $this->ControllerName = '';
     $this->ControllerMethod = 'index';
     $this->_ControllerMethodArgs = array();
     $this->Request = $Request->path(false);
     $PathAndQuery = $Request->PathAndQuery();
     $MatchRoute = Gdn::router()->matchRoute($PathAndQuery);
     // We have a route. Take action.
     if ($MatchRoute !== false) {
         switch ($MatchRoute['Type']) {
             case 'Internal':
                 $Request->pathAndQuery($MatchRoute['FinalDestination']);
                 $this->Request = $Request->path(false);
                 break;
             case 'Temporary':
                 safeHeader("HTTP/1.1 302 Moved Temporarily");
                 safeHeader("Location: " . Url($MatchRoute['FinalDestination']));
                 exit;
                 break;
             case 'Permanent':
                 safeHeader("HTTP/1.1 301 Moved Permanently");
                 safeHeader("Location: " . Url($MatchRoute['FinalDestination']));
                 exit;
                 break;
             case 'NotAuthorized':
                 safeHeader("HTTP/1.1 401 Not Authorized");
                 $this->Request = $MatchRoute['FinalDestination'];
                 break;
             case 'NotFound':
                 safeHeader("HTTP/1.1 404 Not Found");
                 $this->Request = $MatchRoute['FinalDestination'];
                 break;
             case 'Test':
                 $Request->pathAndQuery($MatchRoute['FinalDestination']);
                 $this->Request = $Request->path(false);
                 decho($MatchRoute, 'Route');
                 decho(array('Path' => $Request->path(), 'Get' => $Request->get()), 'Request');
                 die;
         }
     }
     switch ($Request->outputFormat()) {
         case 'rss':
             $this->_SyndicationMethod = SYNDICATION_RSS;
             $this->_DeliveryMethod = DELIVERY_METHOD_RSS;
             break;
         case 'atom':
             $this->_SyndicationMethod = SYNDICATION_ATOM;
             $this->_DeliveryMethod = DELIVERY_METHOD_RSS;
             break;
         case 'default':
         default:
             $this->_SyndicationMethod = SYNDICATION_NONE;
             break;
     }
     if ($this->Request == '') {
         $DefaultController = Gdn::router()->getRoute('DefaultController');
         $this->Request = $DefaultController['Destination'];
     }
     $Parts = explode('/', str_replace('\\', '/', $this->Request));
     /**
      * The application folder is either the first argument or is not provided. The controller is therefore
      * either the second argument or the first, depending on the result of the previous statement. Check that.
      */
     try {
         // if the 1st argument is a valid application, check if it has a controller matching the 2nd argument
         if (in_array($Parts[0], $this->enabledApplicationFolders())) {
             $this->findController(1, $Parts);
         }
         // if no match, see if the first argument is a controller
         $this->findController(0, $Parts);
         // 3] See if there is a plugin trying to create a root method.
         list($MethodName, $DeliveryMethod) = $this->_splitDeliveryMethod(GetValue(0, $Parts), true);
         if ($MethodName && Gdn::pluginManager()->hasNewMethod('RootController', $MethodName, true)) {
             $this->_DeliveryMethod = $DeliveryMethod;
             $Parts[0] = $MethodName;
             $Parts = array_merge(array('root'), $Parts);
             $this->findController(0, $Parts);
         }
         throw new GdnDispatcherControllerNotFoundException();
     } catch (GdnDispatcherControllerFoundException $e) {
         switch ($this->_DeliveryMethod) {
             case DELIVERY_METHOD_JSON:
             case DELIVERY_METHOD_XML:
                 $this->_DeliveryType = DELIVERY_TYPE_DATA;
                 break;
             case DELIVERY_METHOD_TEXT:
                 $this->_DeliveryType = DELIVERY_TYPE_VIEW;
                 break;
             case DELIVERY_METHOD_XHTML:
             case DELIVERY_METHOD_RSS:
                 break;
             default:
                 $this->_DeliveryMethod = DELIVERY_METHOD_XHTML;
                 break;
         }
         return true;
     } catch (GdnDispatcherControllerNotFoundException $e) {
         $this->EventArguments['Handled'] = false;
         $Handled =& $this->EventArguments['Handled'];
         $this->fireEvent('NotFound');
         if (!$Handled) {
             safeHeader("HTTP/1.1 404 Not Found");
             $Request->withRoute('Default404');
             return $this->analyzeRequest($Request);
         }
     }
 }
示例#13
0
 /**
  * @param Gdn_Dispatcher $sender
  */
 public function gdn_dispatcher_sendHeaders_handler($sender)
 {
     $csrfToken = Gdn::request()->post(Gdn_Session::CSRF_NAME, Gdn::request()->get(Gdn_Session::CSRF_NAME, Gdn::request()->getValueFrom(Gdn_Request::INPUT_SERVER, 'HTTP_X_CSRF_TOKEN')));
     if ($csrfToken && Gdn::session()->isValid() && !Gdn::session()->validateTransientKey($csrfToken)) {
         safeHeader('X-CSRF-Token: ' . Gdn::session()->transientKey());
     }
 }
示例#14
0
 /**
  * Rewrite the request based on rewrite rules (currently called routes in Vanilla).
  *
  * This method modifies the passed {@link $request} object. It can also cause a redirect if a rule matches that
  * specifies a redirect.
  *
  * @param Gdn_Request $request The request to rewrite.
  */
 private function rewriteRequest($request)
 {
     $pathAndQuery = $request->PathAndQuery();
     $matchRoute = Gdn::router()->matchRoute($pathAndQuery);
     // We have a route. Take action.
     if (!empty($matchRoute)) {
         $dest = $matchRoute['FinalDestination'];
         if (strpos($dest, '?') === false) {
             // The rewrite rule doesn't include a query string so keep the current one intact.
             $request->path($dest);
         } else {
             // The rewrite rule has a query string so rewrite that too.
             $request->pathAndQuery($dest);
         }
         switch ($matchRoute['Type']) {
             case 'Internal':
                 // Do nothing. The request has been rewritten.
                 break;
             case 'Temporary':
                 safeHeader("HTTP/1.1 302 Moved Temporarily");
                 safeHeader("Location: " . url($matchRoute['FinalDestination']));
                 exit;
                 break;
             case 'Permanent':
                 safeHeader("HTTP/1.1 301 Moved Permanently");
                 safeHeader("Location: " . url($matchRoute['FinalDestination']));
                 exit;
                 break;
             case 'NotAuthorized':
                 safeHeader("HTTP/1.1 401 Not Authorized");
                 break;
             case 'NotFound':
                 safeHeader("HTTP/1.1 404 Not Found");
                 break;
             case 'Drop':
                 die;
             case 'Test':
                 decho($matchRoute, 'Route');
                 decho(array('Path' => $request->path(), 'Get' => $request->get()), 'Request');
                 die;
         }
     } elseif (in_array($request->path(), ['', '/'])) {
         $this->isHomepage = true;
         $defaultController = Gdn::router()->getRoute('DefaultController');
         $request->pathAndQuery($defaultController['Destination']);
     }
     return $request;
 }
示例#15
0
 /**
  * Set P3P header because IE won't allow cookies thru the iFrame without it.
  *
  * This must be done in the Dispatcher because of PrivateCommunity.
  * That precludes using Controller->SetHeader.
  * This is done so comment & forum embedding can work in old IE.
  *
  * @param Gdn_Dispatcher $Sender
  */
 public function gdn_dispatcher_appStartup_handler($Sender)
 {
     safeHeader('P3P: CP="CAO PSA OUR"', true);
     if ($SSO = Gdn::request()->get('sso')) {
         saveToConfig('Garden.Registration.SendConnectEmail', false, false);
         $IsApi = preg_match('`\\.json$`i', Gdn::request()->path());
         $UserID = false;
         try {
             $CurrentUserID = Gdn::session()->UserID;
             $UserID = Gdn::userModel()->sso($SSO);
         } catch (Exception $Ex) {
             trace($Ex, TRACE_ERROR);
         }
         if ($UserID) {
             Gdn::session()->start($UserID, !$IsApi, !$IsApi);
             if ($IsApi) {
                 Gdn::session()->validateTransientKey(true);
             }
             if ($UserID != $CurrentUserID) {
                 Gdn::userModel()->fireEvent('AfterSignIn');
             }
         } else {
             // There was some sort of error. Let's print that out.
             foreach (Gdn::userModel()->Validation->resultsArray() as $msg) {
                 trace($msg, TRACE_ERROR);
             }
             Gdn::userModel()->Validation->reset();
         }
     }
 }
示例#16
0
 /**
  * Redirect to a specific url that can be outside of the site.
  *
  * @param string $url The url to redirect to.
  * @param int $code The http status code.
  */
 function redirectUrl($url, $code = 302)
 {
     if (!$url) {
         $url = Url('', true);
     }
     // Close any db connections before exit
     $Database = Gdn::Database();
     $Database->CloseConnection();
     // Clear out any previously sent content
     @ob_end_clean();
     if (!in_array($code, array(301, 302))) {
         $code = 302;
     }
     safeHeader("Location: " . $url, true, $code);
     exit;
 }
示例#17
0
 /**
  * Looks for a Last-Modified header from the browser and compares it to the
  * supplied date. If the Last-Modified date is after the supplied date, the
  * controller will send a "304 Not Modified" response code to the web
  * browser and stop all execution. Otherwise it sets the Last-Modified
  * header for this page and continues processing.
  *
  * @param string $LastModifiedDate A unix timestamp representing the date that the current page was last
  *  modified.
  */
 public function setLastModified($LastModifiedDate)
 {
     $GMD = gmdate('D, d M Y H:i:s', $LastModifiedDate) . ' GMT';
     $this->setHeader('Etag', '"' . $GMD . '"');
     $this->setHeader('Last-Modified', $GMD);
     $IncomingHeaders = getallheaders();
     if (isset($IncomingHeaders['If-Modified-Since']) && isset($IncomingHeaders['If-None-Match'])) {
         $IfNoneMatch = $IncomingHeaders['If-None-Match'];
         $IfModifiedSince = $IncomingHeaders['If-Modified-Since'];
         if ($GMD == $IfNoneMatch && $IfModifiedSince == $GMD) {
             $Database = Gdn::database();
             if (!is_null($Database)) {
                 $Database->closeConnection();
             }
             $this->setHeader('Content-Length', '0');
             $this->sendHeaders();
             safeHeader('HTTP/1.1 304 Not Modified');
             exit("\n\n");
             // Send two linefeeds so that the client knows the response is complete
         }
     }
 }
示例#18
0
/**
 * A custom error handler that displays much more, very useful information when
 * errors are encountered in Garden.
 *
 * @param Exception $Exception The exception that was thrown.
 */
function Gdn_ExceptionHandler($Exception)
{
    try {
        $ErrorNumber = $Exception->getCode();
        $Message = $Exception->getMessage();
        $File = $Exception->getFile();
        $Line = $Exception->getLine();
        if (method_exists($Exception, 'getContext')) {
            $Arguments = $Exception->getContext();
        } else {
            $Arguments = '';
        }
        $Backtrace = $Exception->getTrace();
        // Clean the output buffer in case an error was encountered in-page.
        @ob_end_clean();
        // prevent headers already sent error
        if (!headers_sent()) {
            if ($ErrorNumber >= 100 && $ErrorNumber < 600) {
                $Code = $ErrorNumber;
            } else {
                $Code = 500;
            }
            if (class_exists('Gdn_Controller', false)) {
                $msg = Gdn_Controller::getStatusMessage($Code);
            } else {
                $msg = 'Error';
            }
            safeHeader("HTTP/1.0 {$Code} {$msg}", true, $ErrorNumber);
            safeHeader('Content-Type: text/html; charset=utf-8');
        }
        $SenderMessage = $Message;
        $SenderObject = 'PHP';
        $SenderMethod = 'Gdn_ErrorHandler';
        $SenderCode = false;
        $SenderTrace = $Backtrace;
        $MessageInfo = explode('|', $Message);
        $MessageCount = count($MessageInfo);
        if ($MessageCount == 4) {
            list($SenderMessage, $SenderObject, $SenderMethod, $SenderCode) = $MessageInfo;
        } elseif ($MessageCount == 3) {
            list($SenderMessage, $SenderObject, $SenderMethod) = $MessageInfo;
        } elseif (function_exists('GetValueR')) {
            $IsError = GetValueR('0.function', $SenderTrace) == 'Gdn_ErrorHandler';
            // not exception
            $N = $IsError ? '1' : '0';
            $SenderMethod = GetValueR($N . '.function', $SenderTrace, $SenderMethod);
            $SenderObject = GetValueR($N . '.class', $SenderTrace, $SenderObject);
        }
        $SenderMessage = htmlspecialchars($SenderMessage);
        $Master = false;
        // The parsed master view
        $CssPath = false;
        // The web-path to the css file
        $ErrorLines = false;
        // The lines near the error's line #
        $DeliveryType = defined('DELIVERY_TYPE_ALL') ? DELIVERY_TYPE_ALL : 'ALL';
        if (array_key_exists('DeliveryType', $_POST)) {
            $DeliveryType = $_POST['DeliveryType'];
        } elseif (array_key_exists('DeliveryType', $_GET)) {
            $DeliveryType = $_GET['DeliveryType'];
        }
        if (function_exists('debug') && debug()) {
            $Debug = true;
        } else {
            $Debug = false;
        }
        // Make sure all of the required custom functions and variables are defined.
        $PanicError = false;
        // Should we just dump a message and forget about the master view?
        if (!defined('DS')) {
            $PanicError = true;
        }
        if (!defined('PATH_ROOT')) {
            $PanicError = true;
        }
        if (!defined('APPLICATION')) {
            define('APPLICATION', 'Garden');
        }
        if (!defined('APPLICATION_VERSION')) {
            define('APPLICATION_VERSION', 'Unknown');
        }
        $WebRoot = '';
        // Try and rollback a database transaction.
        if (class_exists('Gdn', false)) {
            $Database = Gdn::database();
            if (is_object($Database)) {
                $Database->rollbackTransaction();
            }
        }
        if ($PanicError === false) {
            // See if we can get the file that caused the error
            if (is_string($File) && is_numeric($ErrorNumber)) {
                $ErrorLines = @file($File);
            }
            // If this error was encountered during an ajax request, don't bother gettting the css or theme files
            if ($DeliveryType == DELIVERY_TYPE_ALL) {
                $CssPaths = array();
                // Potential places where the css can be found in the filesystem.
                $MasterViewPaths = array();
                $MasterViewName = 'error.master.php';
                $MasterViewCss = 'error.css';
                if ($Debug) {
                    $MasterViewName = 'deverror.master.php';
                }
                if (class_exists('Gdn', false)) {
                    $CurrentTheme = '';
                    // The currently selected theme
                    $CurrentTheme = C('Garden.Theme', '');
                    $MasterViewName = C('Garden.Errors.MasterView', $MasterViewName);
                    $MasterViewCss = substr($MasterViewName, 0, strpos($MasterViewName, '.'));
                    if ($MasterViewCss == '') {
                        $MasterViewCss = 'error';
                    }
                    $MasterViewCss .= '.css';
                    if ($CurrentTheme != '') {
                        // Look for CSS in the theme folder:
                        $CssPaths[] = PATH_THEMES . DS . $CurrentTheme . DS . 'design' . DS . $MasterViewCss;
                        // Look for Master View in the theme folder:
                        $MasterViewPaths[] = PATH_THEMES . DS . $CurrentTheme . DS . 'views' . DS . $MasterViewName;
                    }
                }
                // Look for CSS in the dashboard design folder.
                $CssPaths[] = PATH_APPLICATIONS . DS . 'dashboard' . DS . 'design' . DS . $MasterViewCss;
                // Look for Master View in the dashboard view folder.
                $MasterViewPaths[] = PATH_APPLICATIONS . DS . 'dashboard' . DS . 'views' . DS . $MasterViewName;
                $CssPath = false;
                $Count = count($CssPaths);
                for ($i = 0; $i < $Count; ++$i) {
                    if (file_exists($CssPaths[$i])) {
                        $CssPath = $CssPaths[$i];
                        break;
                    }
                }
                if ($CssPath !== false) {
                    $CssPath = str_replace(array(PATH_ROOT, DS), array('', '/'), $CssPath);
                    $CssPath = ($WebRoot == '' ? '' : '/' . $WebRoot) . $CssPath;
                }
                $MasterViewPath = false;
                $Count = count($MasterViewPaths);
                for ($i = 0; $i < $Count; ++$i) {
                    if (file_exists($MasterViewPaths[$i])) {
                        $MasterViewPath = $MasterViewPaths[$i];
                        break;
                    }
                }
                if ($MasterViewPath !== false) {
                    include $MasterViewPath;
                    $Master = true;
                }
            }
        }
        if ($DeliveryType != DELIVERY_TYPE_ALL) {
            if (!$Debug) {
                echo '<b class="Bonk">Whoops! There was an error.</b>';
                echo '<div class="BonkError Hidden">';
            }
            // This is an ajax request, so dump an error that is more eye-friendly in the debugger
            echo '<h1>FATAL ERROR IN: ', $SenderObject, '.', $SenderMethod, "();</h1>\n<pre class=\"AjaxError\">\"" . $SenderMessage . "\"\n";
            if ($SenderCode != '') {
                echo htmlspecialchars($SenderCode, ENT_COMPAT, C('Garden.Charset', 'UTF-8')) . "\n";
            }
            if (is_array($ErrorLines) && $Line > -1) {
                echo "\nLOCATION: ", $File, "\n";
            }
            $LineCount = count($ErrorLines);
            $Padding = strlen($Line + 5);
            for ($i = 0; $i < $LineCount; ++$i) {
                if ($i > $Line - 6 && $i < $Line + 4) {
                    if ($i == $Line - 1) {
                        echo '>>';
                    }
                    echo '> ' . str_pad($i + 1, $Padding, " ", STR_PAD_LEFT), ': ', str_replace(array("\n", "\r"), array('', ''), htmlspecialchars($ErrorLines[$i])), "\n";
                }
            }
            if (is_array($Backtrace)) {
                echo "\nBACKTRACE:\n";
                $BacktraceCount = count($Backtrace);
                for ($i = 0; $i < $BacktraceCount; ++$i) {
                    if (array_key_exists('file', $Backtrace[$i])) {
                        $File = $Backtrace[$i]['file'] . ' ' . $Backtrace[$i]['line'];
                    }
                    echo '[' . $File . ']', ' ', array_key_exists('class', $Backtrace[$i]) ? $Backtrace[$i]['class'] : 'PHP', array_key_exists('type', $Backtrace[$i]) ? $Backtrace[$i]['type'] : '::', $Backtrace[$i]['function'], '();', "\n";
                }
            }
            echo '</pre>';
            if (!$Debug) {
                echo '</div>';
            }
        } else {
            // If the master view wasn't found, assume a panic state and dump the error.
            if ($Master === false) {
                echo '<!DOCTYPE html>
   <html>
   <head>
      <title>Fatal Error</title>
   </head>
   <body>
      <h1>Fatal Error in   ', $SenderObject, '.', $SenderMethod, '();</h1>
      <h2>', $SenderMessage, "</h2>\n";
                if ($SenderCode != '') {
                    echo '<code>', htmlentities($SenderCode, ENT_COMPAT, 'UTF-8'), "</code>\n";
                }
                if (is_array($ErrorLines) && $Line > -1) {
                    echo '<h3><strong>The error occurred on or near:</strong> ', $File, '</h3>
         <pre>';
                    $LineCount = count($ErrorLines);
                    $Padding = strlen($Line + 4);
                    for ($i = 0; $i < $LineCount; ++$i) {
                        if ($i > $Line - 6 && $i < $Line + 4) {
                            echo str_pad($i, $Padding, " ", STR_PAD_LEFT), ': ', htmlentities($ErrorLines[$i], ENT_COMPAT, 'UTF-8');
                        }
                    }
                    echo "</pre>\n";
                }
                echo '<h2>Need Help?</h2>
      <p>If you are a user of this website, you can report this message to a website administrator.</p>
      <p>If you are an administrator of this website, you can get help at the <a href="http://vanillaforums.org/discussions/" target="_blank">Vanilla Community Forums</a>.</p>
      <h2>Additional information for support personnel:</h2>
      <ul>
         <li><strong>Application:</strong> ', APPLICATION, '</li>
         <li><strong>Application Version:</strong> ', APPLICATION_VERSION, '</li>
         <li><strong>PHP Version:</strong> ', PHP_VERSION, '</li>
         <li><strong>Operating System:</strong> ', PHP_OS, "</li>\n";
                if (array_key_exists('SERVER_SOFTWARE', $_SERVER)) {
                    echo '<li><strong>Server Software:</strong> ', $_SERVER['SERVER_SOFTWARE'], "</li>\n";
                }
                if (array_key_exists('HTTP_REFERER', $_SERVER)) {
                    echo '<li><strong>Referer:</strong> ', $_SERVER['HTTP_REFERER'], "</li>\n";
                }
                if (array_key_exists('HTTP_USER_AGENT', $_SERVER)) {
                    echo '<li><strong>User Agent:</strong> ', $_SERVER['HTTP_USER_AGENT'], "</li>\n";
                }
                if (array_key_exists('REQUEST_URI', $_SERVER)) {
                    echo '<li><strong>Request Uri:</strong> ', $_SERVER['REQUEST_URI'], "</li>\n";
                }
                echo '</ul>
   </body>
   </html>';
            }
        }
        // Attempt to log an error message no matter what.
        LogException($Exception);
    } catch (Exception $e) {
        print get_class($e) . " thrown within the exception handler.<br/>Message: " . $e->getMessage() . " in " . $e->getFile() . " on line " . $e->getLine();
        exit;
    }
}