/** * * * @param int $UserID * @param array $RoleIDs * @param bool $RecordEvent */ public function saveRoles($UserID, $RoleIDs, $RecordEvent) { if (is_string($RoleIDs) && !is_numeric($RoleIDs)) { // The $RoleIDs are a comma delimited list of role names. $RoleNames = array_map('trim', explode(',', $RoleIDs)); $RoleIDs = $this->SQL->select('r.RoleID')->from('Role r')->whereIn('r.Name', $RoleNames)->get()->resultArray(); $RoleIDs = array_column($RoleIDs, 'RoleID'); } if (!is_array($RoleIDs)) { $RoleIDs = [$RoleIDs]; } // Get the current roles. $OldRoleIDs = []; $OldRoleData = $this->SQL->select('ur.RoleID, r.Name')->from('UserRole ur')->join('Role r', 'r.RoleID = ur.RoleID', 'left')->where('ur.UserID', $UserID)->get()->resultArray(); if ($OldRoleData !== false) { $OldRoleIDs = array_column($OldRoleData, 'RoleID'); } // 1a) Figure out which roles to delete. $DeleteRoleIDs = []; foreach ($OldRoleData as $row) { // The role should be deleted if it is an orphan or the user has not been assigned the role. if ($row['Name'] === null || !in_array($row['RoleID'], $RoleIDs)) { $DeleteRoleIDs[] = $row['RoleID']; } } // 1b) Remove old role associations for this user. if (!empty($DeleteRoleIDs)) { $this->SQL->whereIn('RoleID', $DeleteRoleIDs)->delete('UserRole', ['UserID' => $UserID]); } // 2a) Figure out which roles to insert. $InsertRoleIDs = array_diff($RoleIDs, $OldRoleIDs); // 2b) Insert the new role associations for this user. foreach ($InsertRoleIDs as $InsertRoleID) { if (is_numeric($InsertRoleID)) { $this->SQL->insert('UserRole', ['UserID' => $UserID, 'RoleID' => $InsertRoleID]); } } $this->clearCache($UserID, ['roles', 'permissions']); if ($RecordEvent) { $User = $this->getID($UserID); $OldRoles = []; foreach ($DeleteRoleIDs as $deleteRoleID) { $role = RoleModel::roles($deleteRoleID); $OldRoles[] = val('Name', $role, t('Unknown') . ' (' . $deleteRoleID . ')'); } $NewRoles = []; foreach ($InsertRoleIDs as $insertRoleID) { $role = RoleModel::roles($insertRoleID); $NewRoles[] = val('Name', $role, t('Unknown') . ' (' . $insertRoleID . ')'); } $RemovedRoles = array_diff($OldRoles, $NewRoles); $NewRoles = array_diff($NewRoles, $OldRoles); foreach ($RemovedRoles as $RoleName) { Logger::event('role_remove', Logger::INFO, "{username} removed {toUsername} from the {role} role.", ['touserid' => $User->UserID, 'toUsername' => $User->Name, 'role' => $RoleName]); } foreach ($NewRoles as $RoleName) { Logger::event('role_add', Logger::INFO, "{username} added {toUsername} to the {role} role.", ['touserid' => $User->UserID, 'toUsername' => $User->Name, 'role' => $RoleName]); } } }
/** * * * @param $PluginName * @return bool * @throws Exception */ public function disablePlugin($PluginName) { // Get the plugin and make sure its name is the correct case. $Plugin = $this->getPluginInfo($PluginName); if ($Plugin) { $PluginName = $Plugin['Index']; } Gdn_Autoloader::smartFree(Gdn_Autoloader::CONTEXT_PLUGIN, $Plugin); $enabled = $this->isEnabled($PluginName); // 1. Check to make sure that no other enabled plugins rely on this one // Get all available plugins and compile their requirements foreach ($this->enabledPlugins() as $CheckingName => $Trash) { $CheckingInfo = $this->getPluginInfo($CheckingName); $RequiredPlugins = ArrayValue('RequiredPlugins', $CheckingInfo, false); if (is_array($RequiredPlugins) && array_key_exists($PluginName, $RequiredPlugins) === true) { throw new Exception(sprintf(T('You cannot disable the %1$s plugin because the %2$s plugin requires it in order to function.'), $PluginName, $CheckingName)); } } // 2. Perform necessary hook action $this->pluginHook($PluginName, self::ACTION_DISABLE, true); // 3. Disable it. SaveToConfig("EnabledPlugins.{$PluginName}", false); unset($this->EnabledPlugins[$PluginName]); if ($enabled) { Logger::event('addon_disabled', LogLevel::NOTICE, 'The {addonName} plugin was disabled.', array('addonName' => $PluginName)); } // Redefine the locale manager's settings $Locale->Set($CurrentLocale, $EnabledApps, $EnabledPlugins, TRUE); Gdn::locale()->refresh(); $this->EventArguments['AddonName'] = $PluginName; $this->fireEvent('AddonDisabled'); return true; }
/** * * * @param $UserID * @param $RoleIDs * @param $RecordEvent */ public function saveRoles($UserID, $RoleIDs, $RecordEvent) { if (is_string($RoleIDs) && !is_numeric($RoleIDs)) { // The $RoleIDs are a comma delimited list of role names. $RoleNames = array_map('trim', explode(',', $RoleIDs)); $RoleIDs = $this->SQL->select('r.RoleID')->from('Role r')->whereIn('r.Name', $RoleNames)->get()->resultArray(); $RoleIDs = array_column($RoleIDs, 'RoleID'); } if (!is_array($RoleIDs)) { $RoleIDs = array($RoleIDs); } // Get the current roles. $OldRoleIDs = array(); $OldRoleData = $this->SQL->select('ur.RoleID, r.Name')->from('Role r')->join('UserRole ur', 'r.RoleID = ur.RoleID')->where('ur.UserID', $UserID)->get()->resultArray(); if ($OldRoleData !== false) { $OldRoleIDs = array_column($OldRoleData, 'RoleID'); } // 1a) Figure out which roles to delete. $DeleteRoleIDs = array_diff($OldRoleIDs, $RoleIDs); // 1b) Remove old role associations for this user. if (count($DeleteRoleIDs) > 0) { $this->SQL->whereIn('RoleID', $DeleteRoleIDs)->delete('UserRole', array('UserID' => $UserID)); } // 2a) Figure out which roles to insert. $InsertRoleIDs = array_diff($RoleIDs, $OldRoleIDs); // 2b) Insert the new role associations for this user. foreach ($InsertRoleIDs as $InsertRoleID) { if (is_numeric($InsertRoleID)) { $this->SQL->insert('UserRole', array('UserID' => $UserID, 'RoleID' => $InsertRoleID)); } } $this->clearCache($UserID, array('roles', 'permissions')); if ($RecordEvent && (count($DeleteRoleIDs) > 0 || count($InsertRoleIDs) > 0)) { $User = $this->getID($UserID); $Session = Gdn::session(); $OldRoles = false; if ($OldRoleData !== false) { $OldRoles = array_column($OldRoleData, 'Name'); } $NewRoles = false; $NewRoleData = $this->SQL->select('r.RoleID, r.Name')->from('Role r')->join('UserRole ur', 'r.RoleID = ur.RoleID')->where('ur.UserID', $UserID)->get()->resultArray(); if ($NewRoleData !== false) { $NewRoles = array_column($NewRoleData, 'Name'); } $RemovedRoles = array_diff($OldRoles, $NewRoles); $NewRoles = array_diff($NewRoles, $OldRoles); foreach ($RemovedRoles as $RoleName) { Logger::event('role_remove', Logger::INFO, "{username} removed {toUsername} from the {role} role.", array('toUsername' => $User->Name, 'role' => $RoleName)); } foreach ($NewRoles as $RoleName) { Logger::event('role_add', Logger::INFO, "{username} added {toUsername} to the {role} role.", array('toUsername' => $User->Name, 'role' => $RoleName)); } $RemovedCount = count($RemovedRoles); $NewCount = count($NewRoles); $Story = ''; if ($RemovedCount > 0 && $NewCount > 0) { $Story = sprintf(t('%1$s was removed from the %2$s %3$s and added to the %4$s %5$s.'), $User->Name, implode(', ', $RemovedRoles), plural($RemovedCount, 'role', 'roles'), implode(', ', $NewRoles), plural($NewCount, 'role', 'roles')); } elseif ($RemovedCount > 0) { $Story = sprintf(t('%1$s was removed from the %2$s %3$s.'), $User->Name, implode(', ', $RemovedRoles), plural($RemovedCount, 'role', 'roles')); } elseif ($NewCount > 0) { $Story = sprintf(t('%1$s was added to the %2$s %3$s.'), $User->Name, implode(', ', $NewRoles), plural($NewCount, 'role', 'roles')); } } }
public function EnableTheme($ThemeName, $IsMobile = FALSE) { // Make sure to run the setup $this->TestTheme($ThemeName); // Set the theme. $ThemeInfo = $this->GetThemeInfo($ThemeName); $ThemeFolder = GetValue('Folder', $ThemeInfo, ''); $oldTheme = $IsMobile ? C('Garden.MobileTheme', 'mobile') : C('Garden.Theme', 'default'); if ($ThemeFolder == '') { throw new Exception(T('The theme folder was not properly defined.')); } else { $Options = GetValueR("{$ThemeName}.Options", $this->AvailableThemes()); if ($Options) { if ($IsMobile) { SaveToConfig(array('Garden.MobileTheme' => $ThemeName, 'Garden.MobileThemeOptions.Name' => GetValueR("{$ThemeName}.Name", $this->AvailableThemes(), $ThemeFolder))); } else { SaveToConfig(array('Garden.Theme' => $ThemeName, 'Garden.ThemeOptions.Name' => GetValueR("{$ThemeName}.Name", $this->AvailableThemes(), $ThemeFolder))); } } else { if ($IsMobile) { SaveToConfig('Garden.MobileTheme', $ThemeName); RemoveFromConfig('Garden.MobileThemeOptions'); } else { SaveToConfig('Garden.Theme', $ThemeName); RemoveFromConfig('Garden.ThemeOptions'); } } } Logger::event('theme_changed', LogLevel::NOTICE, 'The {themeType} theme changed from {oldTheme} to {newTheme}.', array('themeType' => $IsMobile ? 'mobile' : 'desktop', 'oldTheme' => $oldTheme, 'newTheme' => $ThemeName)); // Tell the locale cache to refresh itself. Gdn::Locale()->Refresh(); return TRUE; }
/** * Do password reset. * * @access public * @since 2.0.0 * * @param int $UserID Unique. * @param string $PasswordResetKey Authenticate with unique, 1-time code sent via email. */ public function passwordReset($UserID = '', $PasswordResetKey = '') { $PasswordResetKey = trim($PasswordResetKey); if (!is_numeric($UserID) || $PasswordResetKey == '' || $this->UserModel->getAttribute($UserID, 'PasswordResetKey', '') != $PasswordResetKey) { $this->Form->addError('Failed to authenticate your password reset request. Try using the reset request form again.'); Logger::event('password_reset_failure', Logger::NOTICE, '{username} failed to authenticate password reset request.'); } $Expires = $this->UserModel->getAttribute($UserID, 'PasswordResetExpires'); if ($this->Form->errorCount() === 0 && $Expires < time()) { $this->Form->addError('@' . t('Your password reset token has expired.', 'Your password reset token has expired. Try using the reset request form again.')); Logger::event('password_reset_failure', Logger::NOTICE, '{username} has an expired reset token.'); } if ($this->Form->errorCount() == 0) { $User = $this->UserModel->getID($UserID, DATASET_TYPE_ARRAY); if ($User) { $User = arrayTranslate($User, array('UserID', 'Name', 'Email')); $this->setData('User', $User); } } else { $this->setData('Fatal', true); } if ($this->Form->errorCount() == 0 && $this->Form->isPostBack() === true) { $Password = $this->Form->getFormValue('Password', ''); $Confirm = $this->Form->getFormValue('Confirm', ''); if ($Password == '') { $this->Form->addError('Your new password is invalid'); Logger::event('password_reset_failure', Logger::NOTICE, 'Failed to reset the password for {username}. Password is invalid.'); } elseif ($Password != $Confirm) { $this->Form->addError('Your passwords did not match.'); } Logger::event('password_reset_failure', Logger::NOTICE, 'Failed to reset the password for {username}. Passwords did not match.'); if ($this->Form->errorCount() == 0) { $User = $this->UserModel->passwordReset($UserID, $Password); Logger::event('password_reset', Logger::NOTICE, '{username} has reset their password.'); Gdn::session()->start($User->UserID, true); // $Authenticator = Gdn::authenticator()->AuthenticateWith('password'); // $Authenticator->FetchData($Authenticator, array('Email' => $User->Email, 'Password' => $Password, 'RememberMe' => FALSE)); // $AuthUserID = $Authenticator->Authenticate(); redirect('/'); } } $this->render(); }
/** * Validates that $ForeignKey was generated by the current user. * * @param string $ForeignKey The key to validate. * @return bool */ public function validateTransientKey($ForeignKey, $ValidateUser = true) { static $ForceValid = false; if ($ForeignKey === true) { $ForceValid = true; } if (!$ForceValid && $ValidateUser && $this->UserID <= 0) { $Return = false; } if (!isset($Return)) { // Checking the postback here is a kludge, but is absolutely necessary until we can test the ValidatePostBack more. $Return = $ForceValid && Gdn::request()->isPostBack() || $ForeignKey === $this->_TransientKey && $this->_TransientKey !== false; } if (!$Return) { if (Gdn::session()->User) { Logger::event('csrf_failure', Logger::ERROR, 'Invalid transient key for {username}.'); } else { Logger::event('csrf_failure', Logger::ERROR, 'Invalid transient key.'); } } return $Return; }
/** * Send a request and receive the response * * Options: * 'URL' => NULL, * 'Host' => NULL, // Override the Host: header * 'Method' => 'GET', // HTTP Method * 'ConnectTimeout' => 5, // Connection timeout * 'Timeout' => 5, // Request timeout * 'TransferMode' => 'normal', // or 'binary' * 'SaveAs' => NULL, // Download the response to this file * 'Redirects' => TRUE, // Allow 302 and 302 redirects * 'SSLNoVerify' => FALSE, // Verify the remote SSL cert * 'PreEncodePost' => TRUE, // * 'Cookies' => TRUE, // Send user's browser cookies? * 'CookieJar' => FALSE, // Create a cURL CookieJar? * 'CookieSession' => FALSE, // Should old cookies be trashed starting now? * 'CloseSession' => TRUE, // Whether to close the session. Should always do this. * 'Redirected' => FALSE, // Is this a redirected request? * 'Debug' => FALSE, // Debug output * 'Simulate' => FALSE // Don't actually request, just set up * * @param array/string $Options URL, or array options * @param array $QueryParams GET/POST parameters * @param array $Files List of files to upload * @param array $ExtraHeaders Any additional headers to tack on * @return type */ public function Request($Options = NULL, $QueryParams = NULL, $Files = NULL, $ExtraHeaders = NULL) { /* * Allow requests that just want to use defaults to provide a string instead * of an optionlist. */ if (is_string($Options)) { $Options = array('URL' => $Options); } if (is_null($Options)) { $Options = array(); } $this->Options = $Options = array_merge($this->RequestDefaults, $Options); $this->ResponseHeaders = array(); $this->ResponseStatus = ""; $this->ResponseBody = ""; $this->RequestBody = ""; $this->ResponseTime = 0; $this->ContentLength = 0; $this->ContentType = ''; $this->ConnectionMode = ''; $this->ActionLog = array(); if (is_string($Files)) { $Files = array($Files); } if (!is_array($Files)) { $Files = array(); } if (!is_array($ExtraHeaders)) { $ExtraHeaders = array(); } // Get the URL $RelativeURL = GetValue('URL', $Options, NULL); if (is_null($RelativeURL)) { $RelativeURL = GetValue('Url', $Options, NULL); } if (is_null($RelativeURL)) { throw new Exception("No URL provided"); } $RequestMethod = GetValue('Method', $Options); $ForceHost = GetValue('Host', $Options); $FollowRedirects = GetValue('Redirects', $Options); $ConnectTimeout = GetValue('ConnectTimeout', $Options); $Timeout = GetValue('Timeout', $Options); $SaveAs = GetValue('SaveAs', $Options); $TransferMode = GetValue('TransferMode', $Options); $SSLNoVerify = GetValue('SSLNoVerify', $Options); $PreEncodePost = GetValue('PreEncodePost', $Options); $SendCookies = GetValue('Cookies', $Options); $CookieJar = GetValue('CookieJar', $Options); $CookieSession = GetValue('CookieSession', $Options); $CloseSesssion = GetValue('CloseSession', $Options); $Redirected = GetValue('Redirected', $Options); $Debug = GetValue('Debug', $Options, FALSE); $Simulate = GetValue('Simulate', $Options); $OldVolume = $this->Loud; if ($Debug) { $this->Loud = TRUE; } $Url = $RelativeURL; $PostData = $QueryParams; /* * If files were provided, preprocess the list and exclude files that don't * exist. Also, change the method to POST if it is currently GET and there * are valid files to send. */ $SendFiles = array(); foreach ($Files as $File => $FilePath) { if (file_exists($FilePath)) { $SendFiles[$File] = $FilePath; } } $this->FileTransfer = (bool) sizeof($SendFiles); if ($this->FileTransfer && $RequestMethod != "PUT") { $this->Options['Method'] = 'POST'; $RequestMethod = GetValue('Method', $Options); } /* * If extra headers were provided, preprocess the list into the correct * format for inclusion into both cURL and fsockopen header queues. */ // Tack on Host header if forced if (!is_null($ForceHost)) { $ExtraHeaders['Host'] = $ForceHost; } $SendExtraHeaders = array(); foreach ($ExtraHeaders as $ExtraHeader => $ExtraHeaderValue) { $SendExtraHeaders[] = "{$ExtraHeader}: {$ExtraHeaderValue}"; } /* * If the request is being saved to a file, prepare to save to the * filesystem. */ $this->SaveFile = FALSE; if ($SaveAs) { $SavePath = dirname($SaveAs); $CanSave = @mkdir($SavePath, 0775, TRUE); if (!is_writable($SavePath)) { throw new Exception("Cannot write to save path: {$SavePath}"); } $this->SaveFile = $SaveAs; } /* * Parse Query Parameters and collapse into a querystring in the case of * GETs. */ $RequestMethod = strtoupper($RequestMethod); switch ($RequestMethod) { case 'PUT': case 'POST': break; case 'GET': default: $PostData = is_array($PostData) ? http_build_query($PostData) : $PostData; if (strlen($PostData)) { if (stristr($RelativeURL, '?')) { $Url .= '&'; } else { $Url .= '?'; } $Url .= $PostData; } break; } $this->Action("Requesting {$Url}"); $UrlParts = parse_url($Url); // Extract scheme $Scheme = strtolower(GetValue('scheme', $UrlParts, 'http')); $this->Action(" scheme: {$Scheme}"); // Extract hostname $Host = GetValue('host', $UrlParts, ''); $this->Action(" host: {$Host}"); // Extract / deduce port $Port = GetValue('port', $UrlParts, NULL); if (empty($Port)) { $Port = $Scheme == 'https' ? 443 : 80; } $this->Action(" port: {$Port}"); // Extract Path&Query $Path = GetValue('path', $UrlParts, ''); $Query = GetValue('query', $UrlParts, ''); $this->UseSSL = $Scheme == 'https' ? TRUE : FALSE; $this->Action(" transfer mode: {$TransferMode}"); $logContext = array('url' => $Url, 'method' => $RequestMethod); /* * ProxyRequest can masquerade as the current user, so collect and encode * their current cookies as the default case is to send them. */ $Cookie = ''; $EncodeCookies = TRUE; foreach ($_COOKIE as $Key => $Value) { if (strncasecmp($Key, 'XDEBUG', 6) == 0) { continue; } if (strlen($Cookie) > 0) { $Cookie .= '; '; } $EncodedValue = $EncodeCookies ? urlencode($Value) : $Value; $Cookie .= "{$Key}={$EncodedValue}"; } // This prevents problems for sites that use sessions. if ($CloseSesssion) { @session_write_close(); } $Response = ''; $this->Action("Parameters: " . print_r($PostData, true)); // We need cURL if (!function_exists('curl_init')) { throw new Exception('Encountered an error while making a request to the remote server: Your PHP configuration does not allow cURL requests.'); } $Handler = curl_init(); curl_setopt($Handler, CURLOPT_HEADER, FALSE); curl_setopt($Handler, CURLINFO_HEADER_OUT, TRUE); curl_setopt($Handler, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($Handler, CURLOPT_USERAGENT, GetValue('HTTP_USER_AGENT', $_SERVER, 'Vanilla/2.0')); curl_setopt($Handler, CURLOPT_CONNECTTIMEOUT, $ConnectTimeout); curl_setopt($Handler, CURLOPT_HEADERFUNCTION, array($this, 'CurlHeader')); if ($TransferMode == 'binary') { curl_setopt($Handler, CURLOPT_BINARYTRANSFER, TRUE); } if ($RequestMethod != 'GET' && $RequestMethod != 'POST') { curl_setopt($Handler, CURLOPT_CUSTOMREQUEST, $RequestMethod); } if ($CookieJar) { curl_setopt($Handler, CURLOPT_COOKIEJAR, $this->CookieJar); curl_setopt($Handler, CURLOPT_COOKIEFILE, $this->CookieJar); } if ($CookieSession) { curl_setopt($Handler, CURLOPT_COOKIESESSION, TRUE); } if ($FollowRedirects) { curl_setopt($Handler, CURLOPT_FOLLOWLOCATION, TRUE); curl_setopt($Handler, CURLOPT_AUTOREFERER, TRUE); curl_setopt($Handler, CURLOPT_MAXREDIRS, 10); } if ($this->UseSSL) { $this->Action(" Using SSL"); curl_setopt($Handler, CURLOPT_SSL_VERIFYPEER, !$SSLNoVerify); curl_setopt($Handler, CURLOPT_SSL_VERIFYHOST, $SSLNoVerify ? 0 : 2); } if ($Timeout > 0) { curl_setopt($Handler, CURLOPT_TIMEOUT, $Timeout); } if ($Cookie != '' && $SendCookies) { $this->Action(" Sending client cookies"); curl_setopt($Handler, CURLOPT_COOKIE, $Cookie); } if ($this->SaveFile) { $this->Action(" Saving to file: {$this->SaveFile}"); $FileHandle = fopen($this->SaveFile, 'w+'); curl_setopt($Handler, CURLOPT_FILE, $FileHandle); } // Allow POST if ($RequestMethod == 'POST') { if ($this->FileTransfer) { $this->Action(" POSTing files"); foreach ($SendFiles as $File => $FilePath) { $PostData[$File] = "@{$FilePath}"; } } else { if ($PreEncodePost && is_array($PostData)) { $PostData = http_build_query($PostData); } } curl_setopt($Handler, CURLOPT_POST, TRUE); curl_setopt($Handler, CURLOPT_POSTFIELDS, $PostData); if (!is_array($PostData) && !is_object($PostData)) { $SendExtraHeaders['Content-Length'] = strlen($PostData); } $this->RequestBody = $PostData; } // Allow PUT if ($RequestMethod == 'PUT') { if ($this->FileTransfer) { $SendFile = GetValue('0', $SendFiles); $SendFileSize = filesize($SendFile); $this->Action(" PUTing file: {$SendFile}"); $SendFileObject = fopen($SendFile, 'r'); curl_setopt($Handler, CURLOPT_PUT, TRUE); curl_setopt($Handler, CURLOPT_INFILE, $SendFileObject); curl_setopt($Handler, CURLOPT_INFILESIZE, $SendFileSize); $SendExtraHeaders[] = "Content-Length: {$SendFileSize}"; } else { curl_setopt($Handler, CURLOPT_CUSTOMREQUEST, 'PUT'); curl_setopt($Handler, CURLOPT_POSTFIELDS, $PostData); if (!is_array($PostData) && !is_object($PostData)) { $SendExtraHeaders['Content-Length'] = strlen($PostData); } else { $TempPostData = http_build_str($PostData); $SendExtraHeaders['Content-Length'] = strlen($TempPostData); } $this->RequestBody = $PostData; } } // Any extra needed headers if (sizeof($SendExtraHeaders)) { curl_setopt($Handler, CURLOPT_HTTPHEADER, $SendExtraHeaders); } // Set URL curl_setopt($Handler, CURLOPT_URL, $Url); curl_setopt($Handler, CURLOPT_PORT, $Port); if (val('Log', $Options, TRUE)) { Logger::event('http_request', Logger::DEBUG, '{method} {url}', $logContext); } $this->CurlReceive($Handler); if ($Simulate) { return NULL; } curl_close($Handler); $logContext['responseCode'] = $this->ResponseStatus; $logContext['responseTime'] = $this->ResponseTime; if (Debug()) { if ($this->ContentType == 'application/json') { $body = @json_decode($this->ResponseBody, true); if (!$body) { $body = $this->ResponseBody; } $logContext['responseBody'] = $body; } else { $logContext['responseBody'] = $this->ResponseBody; } } if (val('Log', $Options, TRUE)) { if ($this->ResponseClass('2xx')) { Logger::event('http_response', Logger::DEBUG, '{responseCode} {method} {url} in {responseTime}s', $logContext); } else { Logger::event('http_response_error', Logger::DEBUG, '{responseCode} {method} {url} in {responseTime}s', $logContext); } } $this->Loud = $OldVolume; return $this->ResponseBody; }
/** * * * @param $ThemeName * @param bool $IsMobile * @return bool * @throws Exception */ public function enableTheme($ThemeName, $IsMobile = false) { // Make sure to run the setup $this->testTheme($ThemeName); // Set the theme. $ThemeInfo = $this->getThemeInfo($ThemeName); $ThemeFolder = val('Folder', $ThemeInfo, ''); $oldTheme = $IsMobile ? c('Garden.MobileTheme', 'mobile') : c('Garden.Theme', 'default'); if ($ThemeFolder == '') { throw new Exception(t('The theme folder was not properly defined.')); } else { $Options = valr("{$ThemeName}.Options", $this->AvailableThemes()); if ($Options) { if ($IsMobile) { saveToConfig(array('Garden.MobileTheme' => $ThemeName, 'Garden.MobileThemeOptions.Name' => valr("{$ThemeName}.Name", $this->availableThemes(), $ThemeFolder))); } else { saveToConfig(array('Garden.Theme' => $ThemeName, 'Garden.ThemeOptions.Name' => valr("{$ThemeName}.Name", $this->availableThemes(), $ThemeFolder))); } } else { if ($IsMobile) { saveToConfig('Garden.MobileTheme', $ThemeName); removeFromConfig('Garden.MobileThemeOptions'); } else { saveToConfig('Garden.Theme', $ThemeName); removeFromConfig('Garden.ThemeOptions'); } } } if ($oldTheme !== $ThemeName) { $this->themeHook($ThemeName, self::ACTION_ENABLE, true); Logger::event('theme_changed', Logger::NOTICE, 'The {themeType} theme changed from {oldTheme} to {newTheme}.', array('themeType' => $IsMobile ? 'mobile' : 'desktop', 'oldTheme' => $oldTheme, 'newTheme' => $ThemeName)); } // Tell the locale cache to refresh itself. Gdn::locale()->refresh(); return true; }
/** * Run the structure for all addons. * * The structure runs the addons in priority order so that higher priority addons override lower priority ones. * * @param bool $captureOnly Run the structure or just capture the SQL changes. * @throws Exception Throws an exception if in debug mode and something goes wrong. */ public function runStructure($captureOnly = false) { $addons = array_reverse(Gdn::addonManager()->getEnabled()); // These variables are required for included structure files. $Database = Gdn::database(); $SQL = $this->SQL; $SQL->CaptureModifications = $captureOnly; $Structure = Gdn::structure(); $Structure->CaptureOnly = $captureOnly; /* @var Addon $addon */ foreach ($addons as $addon) { // Look for a structure file. if ($structure = $addon->getSpecial('structure')) { Logger::event('addon_structure', Logger::INFO, "Executing structure for {addonKey}.", ['addonKey' => $addon->getKey(), 'structureType' => 'file']); try { include $addon->path($structure); } catch (\Exception $ex) { if (debug()) { throw $ex; } } } // Look for a structure method on the plugin. if ($addon->getPluginClass()) { $plugin = Gdn::pluginManager()->getPluginInstance($addon->getPluginClass(), Gdn_PluginManager::ACCESS_CLASSNAME); if (is_object($plugin) && method_exists($plugin, 'structure')) { Logger::event('addon_structure', Logger::INFO, "Executing structure for {addonKey}.", ['addonKey' => $addon->getKey(), 'structureType' => 'method']); try { call_user_func([$plugin, 'structure']); } catch (\Exception $ex) { if (debug()) { throw $ex; } } } } // Register permissions. $permissions = $addon->getInfoValue('registerPermissions'); if (!empty($permissions)) { Logger::event('addon_permissions', Logger::INFO, "Defining permissions for {addonKey}.", ['addonKey' => $addon->getKey(), 'permissions' => $permissions]); Gdn::permissionModel()->define($permissions); } } $this->fireEvent('AfterStructure'); if ($captureOnly && property_exists($Structure->Database, 'CapturedSql')) { return $Structure->Database->CapturedSql; } return []; }
/** * Disable an application. * * @param string $applicationName The name of the application to disable. * @throws \Exception Throws an exception if the application can't be disabled. */ public function disableApplication($applicationName) { // 1. Check to make sure that this application is allowed to be disabled $ApplicationInfo = (array) arrayValueI($applicationName, $this->availableApplications(), array()); $applicationName = $ApplicationInfo['Index']; if (!val('AllowDisable', $ApplicationInfo, true)) { throw new Exception(sprintf(t('You cannot disable the %s application.'), $applicationName)); } // 2. Check to make sure that no other enabled applications rely on this one foreach ($this->enabledApplications() as $CheckingName => $CheckingInfo) { $RequiredApplications = val('RequiredApplications', $CheckingInfo, false); if (is_array($RequiredApplications) && array_key_exists($applicationName, $RequiredApplications) === true) { throw new Exception(sprintf(t('You cannot disable the %1$s application because the %2$s application requires it in order to function.'), $applicationName, $CheckingName)); } } // 3. Check to make sure that no other enabled plugins rely on this one $DependendPlugins = array(); foreach (Gdn::pluginManager()->enabledPlugins() as $CheckingName => $CheckingInfo) { $RequiredApplications = val('RequiredApplications', $CheckingInfo, false); if (is_array($RequiredApplications) && array_key_exists($applicationName, $RequiredApplications) === true) { $DependendPlugins[] = $CheckingName; } } if (!empty($DependendPlugins)) { throw new Exception(sprintf(t('You cannot disable the %1$s application because the following plugins require it in order to function: %2$s'), $applicationName, implode(', ', $DependendPlugins))); } // 2. Disable it removeFromConfig("EnabledApplications.{$applicationName}"); Logger::event('addon_disabled', Logger::NOTICE, 'The {addonName} application was disabled.', array('addonName' => $applicationName)); // Clear the object caches. Gdn_Autoloader::smartFree(Gdn_Autoloader::CONTEXT_APPLICATION, $ApplicationInfo); // Redefine the locale manager's settings $Locale->Set($CurrentLocale, $EnabledApps, $EnabledPlugins, true); $Locale = Gdn::locale(); $Locale->set($Locale->current(), $this->enabledApplicationFolders(), Gdn::pluginManager()->enabledPluginFolders(), true); $this->EventArguments['AddonName'] = $applicationName; Gdn::pluginManager()->callEventHandlers($this, 'ApplicationManager', 'AddonDisabled'); }
/** * Set new password for current user. * * @since 2.0.0 * @access public */ public function password() { $this->permission('Garden.SignIn.Allow'); // Don't allow password editing if using SSO Connect ONLY. // This is for security. We encountered the case where a customer charges // for membership using their external application and use SSO to let // their customers into Vanilla. If you allow those people to change their // password in Vanilla, they will then be able to log into Vanilla using // Vanilla's login form regardless of the state of their membership in the // external app. if (c('Garden.Registration.Method') == 'Connect') { Gdn::dispatcher()->dispatch('DefaultPermission'); exit; } Gdn::userModel()->addPasswordStrength($this); // Get user data and set up form $this->getUserInfo(); $this->Form->setModel($this->UserModel); $this->addDefinition('Username', $this->User->Name); if ($this->Form->authenticatedPostBack() === true) { $this->Form->setFormValue('UserID', $this->User->UserID); $this->UserModel->defineSchema(); // $this->UserModel->Validation->AddValidationField('OldPassword', $this->Form->formValues()); // No password may have been set if they have only signed in with a connect plugin if (!$this->User->HashMethod || $this->User->HashMethod == "Vanilla") { $this->UserModel->Validation->applyRule('OldPassword', 'Required'); $this->UserModel->Validation->applyRule('OldPassword', 'OldPassword', 'Your old password was incorrect.'); } $this->UserModel->Validation->applyRule('Password', 'Required'); $this->UserModel->Validation->applyRule('Password', 'Strength'); $this->UserModel->Validation->applyRule('Password', 'Match'); if ($this->Form->save()) { $this->informMessage(sprite('Check', 'InformSprite') . t('Your password has been changed.'), 'Dismissable AutoDismiss HasSprite'); $this->Form->clearInputs(); Logger::event('password_change', Logger::INFO, '{InsertName} changed password.'); } else { Logger::event('password_change_failure', Logger::INFO, '{InsertName} failed to change password.', array('Error' => $this->Form->errorString())); } } $this->title(t('Change My Password')); $this->_setBreadcrumbs(t('Change My Password'), '/profile/password'); $this->render(); }
/** * Enable an addon and do all the stuff that's entailed there. * * @param Addon $addon The addon to enable. * @param bool $setup Whether or not to set the plugin up. * @throws Exception Throws an exception if something goes bonkers during the process. */ private function enableAddon(Addon $addon, $setup) { if ($setup) { $this->addonManager->startAddon($addon); $this->pluginHook($addon->getRawKey(), self::ACTION_ENABLE, true); // If setup succeeded, register any specified permissions $permissions = $addon->getInfoValue('registerPermissions'); if (!empty($permissions)) { $PermissionModel = Gdn::permissionModel(); $PermissionModel->define($permissions); } // Write enabled state to config. saveToConfig("EnabledPlugins." . $addon->getRawKey(), true); Logger::event('addon_enabled', Logger::INFO, 'The {addonName} plugin was enabled.', array('addonName' => $addon->getRawKey())); } $pluginClassName = $addon->getPluginClass(); $this->registerPlugin($pluginClassName); }
public function log($message, $data) { if (c('Vanilla.SSO.Debug')) { Logger::event('sso_logging', Logger::INFO, $message, $data); } }
/** * Send a query to the database and return the result. * * @param string $sql The sql to execute. * @param bool $checkThreshold Whether or not to check the alter table threshold before altering the table. * @return bool Whether or not the query succeeded. */ public function query($sql, $checkThreshold = false) { if ($this->CaptureOnly) { if (!property_exists($this->Database, 'CapturedSql')) { $this->Database->CapturedSql = array(); } $this->Database->CapturedSql[] = $sql; return true; } elseif ($checkThreshold && $this->getAlterTableThreshold() && $this->getRowCountEstimate($this->tableName()) >= $this->getAlterTableThreshold()) { $this->addIssue("The table was past its threshold. Run the alter manually.", $sql); // Log an event to be captured and analysed later. Logger::event('structure_threshold', Logger::ALERT, "Cannot alter table {tableName}. Its count of {rowCount,number} is past the {rowThreshold,number} threshold.", ['tableName' => $this->tableName(), 'rowCount' => $this->getRowCountEstimate($this->tableName()), 'rowThreshold' => $this->getAlterTableThreshold(), 'alterSql' => $sql]); return true; } else { $Result = $this->Database->query($sql); return $Result; } }
/** * Undocumented method. * * @param string $ApplicationName Undocumented variable. * @todo Document DisableApplication() method. */ public function DisableApplication($ApplicationName) { // 1. Check to make sure that this application is allowed to be disabled $ApplicationInfo = ArrayValueI($ApplicationName, $this->AvailableApplications(), array()); $ApplicationName = $ApplicationInfo['Index']; if (!ArrayValue('AllowDisable', $ApplicationInfo, TRUE)) { throw new Exception(sprintf(T('You cannot disable the %s application.'), $ApplicationName)); } // 2. Check to make sure that no other enabled applications rely on this one foreach ($this->EnabledApplications() as $CheckingName => $CheckingInfo) { $RequiredApplications = ArrayValue('RequiredApplications', $CheckingInfo, FALSE); if (is_array($RequiredApplications) && array_key_exists($ApplicationName, $RequiredApplications) === TRUE) { throw new Exception(sprintf(T('You cannot disable the %1$s application because the %2$s application requires it in order to function.'), $ApplicationName, $CheckingName)); } } // 2. Disable it RemoveFromConfig("EnabledApplications.{$ApplicationName}"); Logger::event('addon_disabled', LogLevel::NOTICE, 'The {addonName} application was disabled.', array('addonName' => $ApplicationName)); // Clear the object caches. Gdn_Autoloader::SmartFree(Gdn_Autoloader::CONTEXT_APPLICATION, $ApplicationInfo); // Redefine the locale manager's settings $Locale->Set($CurrentLocale, $EnabledApps, $EnabledPlugins, TRUE); $Locale = Gdn::Locale(); $Locale->Set($Locale->Current(), $this->EnabledApplicationFolders(), Gdn::PluginManager()->EnabledPluginFolders(), TRUE); $this->EventArguments['AddonName'] = $ApplicationName; Gdn::PluginManager()->CallEventHandlers($this, 'ApplicationManager', 'AddonDisabled'); }
/** * Disable an application. * * @param string $applicationName The name of the application to disable. * @throws \Exception Throws an exception if the application can't be disabled. */ public function disableApplication($applicationName) { $addon = $this->addonManager->lookupAddon($applicationName); if (!$addon) { throw notFoundException('Application'); } $applicationName = $addon->getRawKey(); // 1. Check to make sure that this application is allowed to be disabled if (!$addon->getInfoValue('allowDisable', true)) { throw new Exception(sprintf(t('You cannot disable the %s application.'), $applicationName)); } // 2. Check to make sure that no other enabled applications rely on this one. try { $this->addonManager->checkDependants($addon, true); } catch (Exception $ex) { throw new Gdn_UserException($ex->getMessage(), $ex->getCode()); } // 2. Disable it removeFromConfig("EnabledApplications.{$applicationName}"); Logger::event('addon_disabled', Logger::NOTICE, 'The {addonName} application was disabled.', array('addonName' => $applicationName)); // Clear the object caches. $this->addonManager->stopAddonsByKey([$applicationName], \Vanilla\Addon::TYPE_ADDON); }