public function __construct($Sender = '') { if (!CheckPermission('Conversations.Conversations.Add')) { throw PermissionException(); } $Session = Gdn::Session(); if (property_exists($Sender, 'Conversation')) { $this->Conversation = $Sender->Conversation; } $this->Form = Gdn::Factory('Form', 'AddPeople'); // $this->Form->Action = $Sender->SelfUrl; // If the form was posted back, check for people to add to the conversation if ($this->Form->AuthenticatedPostBack()) { $NewRecipientUserIDs = array(); $NewRecipients = explode(',', $this->Form->GetFormValue('AddPeople', '')); $UserModel = Gdn::Factory("UserModel"); foreach ($NewRecipients as $Name) { if (trim($Name) != '') { $User = $UserModel->GetByUsername(trim($Name)); if (is_object($User)) { $NewRecipientUserIDs[] = $User->UserID; } } } $Sender->ConversationModel->AddUserToConversation($this->Conversation->ConversationID, $NewRecipientUserIDs); // if ($Sender->DeliveryType() == DELIVERY_TYPE_ALL) // Redirect('/messages/'.$this->Conversation->ConversationID); $Sender->InformMessage(T('Your changes were saved.')); $Sender->RedirectUrl = Url('/messages/' . $this->Conversation->ConversationID); } $this->_ApplicationFolder = $Sender->Application; $this->_ThemeFolder = $Sender->Theme; }
public function Permission() { if ($this->DeliveryMethod() == DELIVERY_METHOD_XHTML) { $this->Render(); } else { $this->RenderException(PermissionException()); } }
/** * This determines if the current user can react on this item with this action * * @param string $Type valid options are 'discussion', 'comment', and 'activity' * @param int $ID * @param int $ActionID * @throws Gdn_UserException */ public function Index($Type, $ID, $ActionID) { $Type = strtolower($Type); $Action = $this->ActionModel->GetByID($ActionID); // Make sure the action exists and the user is allowed to react if (!$Action) { throw new Gdn_UserException(T('Yaga.Action.Invalid')); } if (!Gdn::Session()->CheckPermission($Action->Permission)) { throw PermissionException(); } switch ($Type) { case 'discussion': $Model = new DiscussionModel(); $AnchorID = '#Discussion_'; break; case 'comment': $Model = new CommentModel(); $AnchorID = '#Comment_'; break; case 'activity': $Model = new ActivityModel(); $AnchorID = '#Activity_'; break; default: throw new Gdn_UserException(T('Yaga.Action.InvalidTargetType')); break; } $Item = $Model->GetID($ID); if ($Item) { $Anchor = $AnchorID . $ID . ' .ReactMenu'; } else { throw new Gdn_UserException(T('Yaga.Action.InvalidTargetID')); } $UserID = Gdn::Session()->UserID; switch ($Type) { case 'comment': case 'discussion': $ItemOwnerID = $Item->InsertUserID; break; case 'activity': $ItemOwnerID = $Item['RegardingUserID']; break; default: throw new Gdn_UserException(T('Yaga.Action.InvalidTargetType')); break; } if ($ItemOwnerID == $UserID) { throw new Gdn_UserException(T('Yaga.Error.ReactToOwn')); } // It has passed through the gauntlet $this->ReactionModel->Set($ID, $Type, $ItemOwnerID, $UserID, $ActionID); $this->JsonTarget($Anchor, RenderReactionList($ID, $Type, FALSE), 'ReplaceWith'); // Don't render anything $this->Render('Blank', 'Utility', 'Dashboard'); }
public function DiscussionController_AutoExpire_Create($Sender, $Args) { $DiscussionID = intval($Args[0]); $DiscussionModel = new DiscussionModel(); $Discussion = $DiscussionModel->GetID($DiscussionID); if (!Gdn::Session()->CheckPermission('Vanilla.Discussions.Close', TRUE, 'Category', $Discussion->PermissionCategoryID)) { throw PermissionException('Vanilla.Discussions.Close'); } if (strtolower($Args[1]) == 'reset') { Gdn::SQL()->Put('Discussion', array('AutoExpire' => 1, 'Closed' => 0, 'DateReOpened' => Gdn_Format::ToDateTime()), array('DiscussionID' => $DiscussionID)); } else { $Expire = strtolower($Args[1]) == 'on' ? 1 : 0; Gdn::SQL()->Put('Discussion', array('AutoExpire' => $Expire), array('DiscussionID' => $DiscussionID)); } Redirect('discussion/' . $DiscussionID . '/' . Gdn_Format::Url($Discussion->Name)); }
public function Archives($Category, $Month, $Page = FALSE) { $Category = CategoryModel::Categories($Category); if (!$Category) { throw NotFoundException($Category); } if (!$Category['PermsDiscussionsView']) { throw PermissionException(); } $Timestamp = strtotime($Month); if (!$Timestamp) { throw new Gdn_UserException("{$Month} is not a valid date."); } $this->SetData('Category', $Category); // Round the month to the first day. $From = gmdate('Y-m-01', $Timestamp); $To = gmdate('Y-m-01', strtotime('+1 month', strtotime($From))); // Grab the discussions. list($Offset, $Limit) = OffsetLimit($Page, C('Vanilla.Discussions.PerPage', 30)); $Where = array('CategoryID' => $Category['CategoryID'], 'Announce' => 'all', 'DateInserted >=' => $From, 'DateInserted <' => $To); SaveToConfig('Vanilla.Discussions.SortField', 'd.DateInserted', FALSE); $DiscussionModel = new DiscussionModel(); $Discussions = $DiscussionModel->GetWhere($Where, $Offset, $Limit); $this->DiscussionData = $this->SetData('Discussions', $Discussions); $this->SetData('_CurrentRecords', count($Discussions)); $this->SetData('_Limit', $Limit); $Canonical = '/categories/archives/' . rawurlencode($Category['UrlCode']) . '/' . gmdate('Y-m', $Timestamp); $Page = PageNumber($Offset, $Limit, TRUE, FALSE); $this->CanonicalUrl(Url($Canonical . ($Page ? '?page=' . $Page : ''), TRUE)); PagerModule::Current()->Configure($Offset, $Limit, FALSE, $Canonical . '?page={Page}'); // PagerModule::Current()->Offset = $Offset; // PagerModule::Current()->Url = '/categories/archives'.rawurlencode($Category['UrlCode']).'?page={Page}'; Gdn_Theme::Section(GetValue('CssClass', $Category)); Gdn_Theme::Section('DiscussionList'); $this->Title(htmlspecialchars(GetValue('Name', $Category, ''))); $this->Description(sprintf(T("Archives for %s"), gmdate('F Y', strtotime($From))), TRUE); $this->AddJsFile('discussions.js'); $this->Head->AddTag('meta', array('name' => 'robots', 'content' => 'noindex')); $this->ControllerName = 'DiscussionsController'; $this->CssClass = 'Discussions'; $this->Render(); }
/** * Validates the current user's permissions & transientkey and then marks a user as a troll. * * @param UserController $sender */ public function userController_markTroll_create($sender, $userID, $troll = true) { $sender->permission('Garden.Moderation.Manage'); $trollUserID = $userID; // Validate the transient key && permissions // Make sure we are posting back. if (!$sender->Request->isAuthenticatedPostBack()) { throw PermissionException('Javascript'); } $trolls = self::getTrolls(); // Toggle troll value in DB if (in_array($trollUserID, $trolls)) { Gdn::sql()->update('User', ['Troll' => 0], ['UserID' => $trollUserID])->put(); unset($trolls[array_search($trollUserID, $trolls)]); } else { Gdn::sql()->update('User', ['Troll' => 1], ['UserID' => $trollUserID])->put(); $trolls[] = $trollUserID; } self::setTrolls($trolls); $sender->jsonTarget('', '', 'Refresh'); $sender->render('Blank', 'Utility', 'Dashboard'); }
/** * Add a method to the ModerationController to handle merging discussions. * @param Gdn_Controller $Sender */ public function ModerationController_MergeDiscussions_Create($Sender) { $Session = Gdn::Session(); $Sender->Form = new Gdn_Form(); $Sender->Title(T('Merge Discussions')); $DiscussionModel = new DiscussionModel(); $CheckedDiscussions = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedDiscussions', array()); if (!is_array($CheckedDiscussions)) { $CheckedDiscussions = array(); } $DiscussionIDs = $CheckedDiscussions; $Sender->SetData('DiscussionIDs', $DiscussionIDs); $CountCheckedDiscussions = count($DiscussionIDs); $Sender->SetData('CountCheckedDiscussions', $CountCheckedDiscussions); $Discussions = $DiscussionModel->SQL->WhereIn('DiscussionID', $DiscussionIDs)->Get('Discussion')->ResultArray(); $Sender->SetData('Discussions', $Discussions); // Perform the merge if ($Sender->Form->AuthenticatedPostBack()) { // Create a new discussion record $MergeDiscussion = FALSE; $MergeDiscussionID = $Sender->Form->GetFormValue('MergeDiscussionID'); foreach ($Discussions as $Discussion) { if ($Discussion['DiscussionID'] == $MergeDiscussionID) { $MergeDiscussion = $Discussion; break; } } $RedirectLink = $Sender->Form->GetFormValue('RedirectLink'); if ($MergeDiscussion) { $ErrorCount = 0; // Verify that the user has permission to perform the merge. $Category = CategoryModel::Categories($MergeDiscussion['CategoryID']); if ($Category && !$Category['PermsDiscussionsEdit']) { throw PermissionException('Vanilla.Discussions.Edit'); } $DiscussionModel->DefineSchema(); $MaxNameLength = GetValue('Length', $DiscussionModel->Schema->GetField('Name')); // Assign the comments to the new discussion record $DiscussionModel->SQL->Update('Comment')->Set('DiscussionID', $MergeDiscussionID)->WhereIn('DiscussionID', $DiscussionIDs)->Put(); $CommentModel = new CommentModel(); foreach ($Discussions as $Discussion) { if ($Discussion['DiscussionID'] == $MergeDiscussionID) { continue; } // Create a comment out of the discussion. $Comment = ArrayTranslate($Discussion, array('Body', 'Format', 'DateInserted', 'InsertUserID', 'InsertIPAddress', 'DateUpdated', 'UpdateUserID', 'UpdateIPAddress', 'Attributes', 'Spam', 'Likes', 'Abuse')); $Comment['DiscussionID'] = $MergeDiscussionID; $CommentModel->Validation->Results(TRUE); $CommentID = $CommentModel->Save($Comment); if ($CommentID) { // Move any attachments (FileUpload plugin awareness) if (class_exists('MediaModel')) { $MediaModel = new MediaModel(); $MediaModel->Reassign($Discussion['DiscussionID'], 'discussion', $CommentID, 'comment'); } if ($RedirectLink) { // The discussion needs to be changed to a moved link. $RedirectDiscussion = array('Name' => SliceString(sprintf(T('Merged: %s'), $Discussion['Name']), $MaxNameLength), 'Type' => 'redirect', 'Body' => FormatString(T('This discussion has been <a href="{url,html}">merged</a>.'), array('url' => DiscussionUrl($MergeDiscussion))), 'Format' => 'Html'); $DiscussionModel->SetField($Discussion['DiscussionID'], $RedirectDiscussion); $CommentModel->UpdateCommentCount($Discussion['DiscussionID']); $CommentModel->RemovePageCache($Discussion['DiscussionID']); } else { // Delete discussion that was merged. $DiscussionModel->Delete($Discussion['DiscussionID']); } } else { $Sender->InformMessage($CommentModel->Validation->ResultsText()); $ErrorCount++; } } // Update counts on all affected discussions. $CommentModel->UpdateCommentCount($MergeDiscussionID); $CommentModel->RemovePageCache($MergeDiscussionID); // Clear selections Gdn::UserModel()->SaveAttribute($Session->UserID, 'CheckedDiscussions', FALSE); ModerationController::InformCheckedDiscussions($Sender); if ($ErrorCount == 0) { $Sender->JsonTarget('', '', 'Refresh'); } } } $Sender->Render('MergeDiscussions', '', 'plugins/SplitMerge'); }
public function SetHourOffset() { $Form = new Gdn_Form(); if ($Form->AuthenticatedPostBack()) { if (!Gdn::Session()->IsValid()) { throw PermissionException('Garden.SignIn.Allow'); } $HourOffset = $Form->GetFormValue('HourOffset'); Gdn::UserModel()->SetField(Gdn::Session()->UserID, 'HourOffset', $HourOffset); $this->SetData('Result', TRUE); $this->SetData('HourOffset', $HourOffset); $time = time(); $this->SetData('UTCDateTime', gmdate('r', $time)); $this->SetData('UserDateTime', gmdate('r', $time + $HourOffset * 3600)); } else { throw ForbiddenException('GET'); } $this->Render('Blank'); }
/** * Run a structure update on the database. * * @since 2.0.? * @access public */ public function Update() { // Check for permission or flood control. // These settings are loaded/saved to the database because we don't want the config file storing non/config information. $Now = time(); $LastTime = Gdn::Get('Garden.Update.LastTimestamp', 0); if ($LastTime + 60 * 60 * 24 > $Now) { // Check for flood control. $Count = Gdn::Get('Garden.Update.Count', 0) + 1; if ($Count > 5) { if (!Gdn::Session()->CheckPermission('Garden.Settings.Manage')) { // We are only allowing an update of 5 times every 24 hours. throw PermissionException(); } } } else { $Count = 1; } Gdn::Set('Garden.Update.LastTimestamp', $Now); Gdn::Set('Garden.Update.Count', $Count); try { // Run the structure. $UpdateModel = new UpdateModel(); $UpdateModel->RunStructure(); $this->SetData('Success', TRUE); } catch (Exception $Ex) { $this->SetData('Success', FALSE); } if (Gdn::Session()->CheckPermission('Garden.Settings.Manage')) { SaveToConfig('Garden.Version', APPLICATION_VERSION); } if ($Target = $this->Request->Get('Target')) { Redirect($Target); } $this->MasterView = 'empty'; $this->CssClass = 'Home'; $this->Render(); }
/** * * * @param DiscussionController $Sender */ public function discussionController_download_create($Sender) { if (!$this->CanDownload) { throw PermissionException("File could not be streamed: Access is denied"); } list($MediaID) = $Sender->RequestArgs; $Media = $this->mediaModel()->getID($MediaID); if (!$Media) { return; } $Filename = Gdn::request()->filename(); if (!$Filename || $Filename == 'default') { $Filename = $Media->Name; } $DownloadPath = combinePaths(array(MediaModel::pathUploads(), val('Path', $Media))); if (in_array(strtolower(pathinfo($Filename, PATHINFO_EXTENSION)), array('bmp', 'gif', 'jpg', 'jpeg', 'png'))) { $ServeMode = 'inline'; } else { $ServeMode = 'attachment'; } $Served = false; $this->EventArguments['DownloadPath'] = $DownloadPath; $this->EventArguments['ServeMode'] = $ServeMode; $this->EventArguments['Media'] = $Media; $this->EventArguments['Served'] =& $Served; $this->fireEvent('BeforeDownload'); if (!$Served) { return Gdn_FileSystem::serveFile($DownloadPath, $Filename, $Media->Type, $ServeMode); throw new Exception('File could not be streamed: missing file (' . $DownloadPath . ').'); } exit; }
public function Verify($UserID, $Verified) { $this->Permission('Garden.Moderation.Manage'); if (!$this->Request->IsAuthenticatedPostBack()) { throw PermissionException('Javascript'); } // First, set the field value. Gdn::UserModel()->SetField($UserID, 'Verified', $Verified); $User = Gdn::UserModel()->GetID($UserID); if (!$User) { throw NotFoundException('User'); } // Send back the verified button. require_once $this->FetchViewLocation('helper_functions', 'Profile', 'Dashboard'); $this->JsonTarget('.User-Verified', UserVerified($User), 'ReplaceWith'); $this->Render('Blank', 'Utility', 'Dashboard'); }
/** * Redirect, but only to a safe domain. * * @param string $Destination Where to redirect. * @param int $StatusCode The status of the redirect. Defaults to 302. */ function safeRedirect($Destination = false, $StatusCode = null) { if (!$Destination) { $Destination = Url('', true); } else { $Destination = Url($Destination, true); } $Domain = parse_url($Destination, PHP_URL_HOST); if (in_array($Domain, TrustedDomains())) { Redirect($Destination, $StatusCode); } else { throw PermissionException(); } }
/** * Add a method to the ModerationController to handle merging discussions. * @param Gdn_Controller $Sender */ public function ModerationController_MergeDiscussions_Create($Sender) { $Session = Gdn::Session(); $Sender->Form = new Gdn_Form(); $Sender->Title(T('Merge Discussions')); $DiscussionModel = new DiscussionModel(); $CheckedDiscussions = Gdn::UserModel()->GetAttribute($Session->User->UserID, 'CheckedDiscussions', array()); if (!is_array($CheckedDiscussions)) { $CheckedDiscussions = array(); } $DiscussionIDs = $CheckedDiscussions; $Sender->SetData('DiscussionIDs', $DiscussionIDs); $CountCheckedDiscussions = count($DiscussionIDs); $Sender->SetData('CountCheckedDiscussions', $CountCheckedDiscussions); $Discussions = $DiscussionModel->SQL->WhereIn('DiscussionID', $DiscussionIDs)->Get('Discussion')->ResultArray(); $Sender->SetData('Discussions', $Discussions); // Perform the merge if ($Sender->Form->AuthenticatedPostBack()) { // Create a new discussion record $MergeDiscussion = FALSE; $MergeDiscussionID = $Sender->Form->GetFormValue('MergeDiscussionID'); foreach ($Discussions as $Discussion) { if ($Discussion['DiscussionID'] == $MergeDiscussionID) { $MergeDiscussion = $Discussion; break; } } if ($MergeDiscussion) { $ErrorCount = 0; // Verify that the user has permission to perform the merge. $Category = CategoryModel::Categories($MergeDiscussion['CategoryID']); if ($Category && !$Category['PermsDiscussionsEdit']) { throw PermissionException('Vanilla.Discussions.Edit'); } // Assign the comments to the new discussion record $DiscussionModel->SQL->Update('Comment')->Set('DiscussionID', $MergeDiscussionID)->WhereIn('DiscussionID', $DiscussionIDs)->Put(); $CommentModel = new CommentModel(); foreach ($Discussions as $Discussion) { if ($Discussion['DiscussionID'] == $MergeDiscussionID) { continue; } // Create a comment out of the discussion. $Comment = ArrayTranslate($Discussion, array('Body', 'Format', 'DateInserted', 'InsertUserID', 'InsertIPAddress', 'DateUpdated', 'UpdateUserID', 'UpdateIPAddress', 'Attributes', 'Spam', 'Likes', 'Abuse')); $Comment['DiscussionID'] = $MergeDiscussionID; $CommentModel->Validation->Results(TRUE); $CommentID = $CommentModel->Save($Comment); if ($CommentID) { // Move any attachments (FileUpload plugin awareness) if (class_exists('MediaModel')) { $MediaModel = new MediaModel(); $MediaModel->Reassign($Discussion['DiscussionID'], 'discussion', $CommentID, 'comment'); } // Delete discussion that was merged $DiscussionModel->Delete($Discussion['DiscussionID']); } else { $Sender->InformMessage($CommentModel->Validation->ResultsText()); $ErrorCount++; } } // Update counts on all affected discussions. $CommentModel->UpdateCommentCount($MergeDiscussionID); $CommentModel->RemovePageCache($MergeDiscussionID); // Clear selections Gdn::UserModel()->SaveAttribute($Session->UserID, 'CheckedDiscussions', FALSE); ModerationController::InformCheckedDiscussions($Sender); if ($ErrorCount == 0) { $Sender->RedirectUrl = Url("/discussion/{$MergeDiscussionID}/" . Gdn_Format::Url($MergeDiscussion['Name'])); } } } $Sender->Render('MergeDiscussions', '', 'plugins/SplitMerge'); }
/** * Retrieve the user to be manipulated. Defaults to current user. * * @since 2.0.0 * @access public * @param mixed $User Unique identifier, possibly username or ID. * @param string $Username. * @param int $UserID Unique ID. * @param bool $CheckPermissions Whether or not to check user permissions. * @return bool Always true. */ public function GetUserInfo($UserReference = '', $Username = '', $UserID = '', $CheckPermissions = FALSE) { if ($this->_UserInfoRetrieved) { return; } if (!C('Garden.Profile.Public') && !Gdn::Session()->IsValid()) { throw PermissionException(); } // If a UserID was provided as a querystring parameter, use it over anything else: if ($UserID) { $UserReference = $UserID; $Username = '******'; // Fill this with a value so the $UserReference is assumed to be an integer/userid. } $this->Roles = array(); if ($UserReference == '') { if ($Username) { $this->User = $this->UserModel->GetByUsername($Username); } else { $this->User = $this->UserModel->GetID(Gdn::Session()->UserID); } } elseif (is_numeric($UserReference) && $Username != '') { $this->User = $this->UserModel->GetID($UserReference); } else { $this->User = $this->UserModel->GetByUsername($UserReference); } if ($this->User === FALSE) { throw NotFoundException('User'); } else { if ($this->User->Deleted == 1) { Redirect('dashboard/home/deleted'); } else { $this->RoleData = $this->UserModel->GetRoles($this->User->UserID); if ($this->RoleData !== FALSE && $this->RoleData->NumRows(DATASET_TYPE_ARRAY) > 0) { $this->Roles = ConsolidateArrayValuesByKey($this->RoleData->Result(), 'Name'); } if (Gdn::Session()->CheckPermission('Garden.Settings.Manage') || Gdn::Session()->UserID == $this->User->UserID) { $this->User->Transient = GetValueR('Attributes.TransientKey', $this->User); } // Hide personal info roles if (!CheckPermission('Garden.PersonalInfo.View')) { $this->Roles = array_filter($this->Roles, 'RoleModel::FilterPersonalInfo'); } $this->SetData('Profile', $this->User); $this->SetData('UserRoles', $this->Roles); if ($CssClass = GetValue('_CssClass', $this->User)) { $this->CssClass .= ' ' . $CssClass; } } } if ($CheckPermissions && Gdn::Session()->UserID != $this->User->UserID) { $this->Permission(array('Garden.Users.Edit', 'Moderation.Profiles.Edit'), FALSE); } $this->AddSideMenu(); $this->_UserInfoRetrieved = TRUE; return TRUE; }
/** * Allow user to set their preferred locale via link-click. */ public function ProfileController_SetLocale_Create($Sender, $locale, $TK) { if (!Gdn::Session()->UserID) { throw PermissionException('Garden.SignIn.Allow'); } // Check intent. if (!Gdn::Session()->ValidateTransientKey($TK)) { Redirect($_SERVER['HTTP_REFERER']); } // If we got a valid locale, save their preference if (isset($locale)) { $locale = $this->ValidateLocale($locale); if ($locale) { $this->SetUserMeta(Gdn::Session()->UserID, 'Locale', $locale); } } // Back from whence we came. Redirect($_SERVER['HTTP_REFERER']); }
/** * Synchronizes the user based on a given UserKey. * * @param string $UserKey A string that uniquely identifies this user. * @param array $Data Information to put in the user table. * @return int The ID of the user. */ public function Synchronize($UserKey, $Data) { $UserID = 0; $Attributes = ArrayValue('Attributes', $Data); if (is_string($Attributes)) { $Attributes = @unserialize($Attributes); } if (!is_array($Attributes)) { $Attributes = array(); } // If the user didnt log in, they won't have a UserID yet. That means they want a new // account. So create one for them. if (!isset($Data['UserID']) || $Data['UserID'] <= 0) { // Prepare the user data. $UserData['Name'] = $Data['Name']; $UserData['Password'] = RandomString(16); $UserData['Email'] = ArrayValue('Email', $Data, '*****@*****.**'); $UserData['Gender'] = strtolower(substr(ArrayValue('Gender', $Data, 'u'), 0, 1)); $UserData['HourOffset'] = ArrayValue('HourOffset', $Data, 0); $UserData['DateOfBirth'] = ArrayValue('DateOfBirth', $Data, ''); $UserData['CountNotifications'] = 0; $UserData['Attributes'] = $Attributes; $UserData['InsertIPAddress'] = Gdn::Request()->IpAddress(); if ($UserData['DateOfBirth'] == '') { $UserData['DateOfBirth'] = '1975-09-16'; } // Make sure there isn't another user with this username. if ($this->ValidateUniqueFields($UserData['Name'], $UserData['Email'])) { if (!BanModel::CheckUser($UserData, $this->Validation, TRUE)) { throw PermissionException('Banned'); } // Insert the new user. $this->AddInsertFields($UserData); $UserID = $this->_Insert($UserData); } if ($UserID) { $NewUserRoleIDs = $this->NewUserRoleIDs(); // Save the roles. $Roles = GetValue('Roles', $Data, FALSE); if (empty($Roles)) { $Roles = $NewUserRoleIDs; } $this->SaveRoles($UserID, $Roles, FALSE); } } else { $UserID = $Data['UserID']; } // Synchronize the transientkey from the external user data source if it is present (eg. WordPress' wpnonce). if (array_key_exists('TransientKey', $Attributes) && $Attributes['TransientKey'] != '' && $UserID > 0) { $this->SetTransientKey($UserID, $Attributes['TransientKey']); } return $UserID; }
/** * Redirect, but only to a safe domain. * * @param string $Destination Where to redirect. * @param int $StatusCode */ function SafeRedirect($Destination = FALSE, $StatusCode = NULL) { if (!$Destination) { $Destination = Url('', TRUE); } else { $Destination = Url($Destination, TRUE); } $Domain = parse_url($Destination, PHP_URL_HOST); if (in_array($Domain, TrustedDomains())) { Redirect($Destination, $StatusCode); } else { throw PermissionException(); } }
/** * 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()); } }
/** * Retrieve the user to be manipulated. Defaults to current user. * * @since 2.0.0 * @access public * @param mixed $UserReference Unique identifier, possibly username or ID. * @param string $Username. * @param int $UserID Unique ID. * @param bool $CheckPermissions Whether or not to check user permissions. * @return bool Always true. */ public function GetUserInfo($UserReference = '', $Username = '', $UserID = '', $CheckPermissions = FALSE) { if ($this->_UserInfoRetrieved) { return; } if (!C('Garden.Profile.Public') && !Gdn::Session()->IsValid()) { throw PermissionException(); } // If a UserID was provided as a querystring parameter, use it over anything else: if ($UserID) { $UserReference = $UserID; $Username = '******'; // Fill this with a value so the $UserReference is assumed to be an integer/userid. } $this->Roles = array(); if ($UserReference == '') { $this->User = $this->UserModel->GetID(Gdn::Session()->UserID); } else { if (is_numeric($UserReference) && $Username != '') { $this->User = $this->UserModel->GetID($UserReference); } else { $this->User = $this->UserModel->GetByUsername($UserReference); } } if ($this->User === FALSE) { throw NotFoundException(); } else { if ($this->User->Deleted == 1) { Redirect('dashboard/home/deleted'); } else { $this->RoleData = $this->UserModel->GetRoles($this->User->UserID); if ($this->RoleData !== FALSE && $this->RoleData->NumRows(DATASET_TYPE_ARRAY) > 0) { $this->Roles = ConsolidateArrayValuesByKey($this->RoleData->Result(), 'Name'); } $this->SetData('Profile', $this->User); $this->SetData('UserRoles', $this->Roles); } } if ($CheckPermissions && Gdn::Session()->UserID != $this->User->UserID) { $this->Permission('Garden.Users.Edit'); } // Make sure the userphoto module gets added to the page $UserPhotoModule = new UserPhotoModule($this); $UserPhotoModule->User = $this->User; $this->AddModule($UserPhotoModule); $this->AddSideMenu(); $this->_UserInfoRetrieved = TRUE; return TRUE; }
/** * Set user preference for sorting discussions. */ public function Sort($Target = '') { if (!Gdn::Session()->IsValid()) { throw PermissionException(); } if (!$this->Request->IsAuthenticatedPostBack()) { throw ForbiddenException('GET'); } // Get param $SortField = Gdn::Request()->Post('DiscussionSort'); $SortField = 'd.' . StringBeginsWith($SortField, 'd.', TRUE, TRUE); // Use whitelist here too to keep database clean if (!in_array($SortField, DiscussionModel::AllowedSortFields())) { throw new Gdn_UserException("Unknown sort {$SortField}."); } // Set user pref Gdn::UserModel()->SavePreference(Gdn::Session()->UserID, 'Discussions.SortField', $SortField); if ($Target) { Redirect($Target); } // Send sorted discussions. $this->DeliveryMethod(DELIVERY_METHOD_JSON); $this->Render(); }
/** * * @param DiscussionController $Sender * @param array $Args */ public function DiscussionController_QnA_Create($Sender, $Args = array()) { $Comment = Gdn::SQL()->GetWhere('Comment', array('CommentID' => $Sender->Request->Get('commentid')))->FirstRow(DATASET_TYPE_ARRAY); if (!$Comment) { throw NotFoundException('Comment'); } $Discussion = Gdn::SQL()->GetWhere('Discussion', array('DiscussionID' => $Comment['DiscussionID']))->FirstRow(DATASET_TYPE_ARRAY); // Check for permission. if (!(Gdn::Session()->UserID == GetValue('InsertUserID', $Discussion) || Gdn::Session()->CheckPermission('Garden.Moderation.Manage'))) { throw PermissionException('Garden.Moderation.Manage'); } if (!Gdn::Session()->ValidateTransientKey($Sender->Request->Get('tkey'))) { throw PermissionException(); } switch ($Args[0]) { case 'accept': $QnA = 'Accepted'; break; case 'reject': $QnA = 'Rejected'; break; } if (isset($QnA)) { $DiscussionSet = array('QnA' => $QnA); $CommentSet = array('QnA' => $QnA); if ($QnA == 'Accepted') { $CommentSet['DateAccepted'] = Gdn_Format::ToDateTime(); $CommentSet['AcceptedUserID'] = Gdn::Session()->UserID; if (!$Discussion['DateAccepted']) { $DiscussionSet['DateAccepted'] = Gdn_Format::ToDateTime(); $DiscussionSet['DateOfAnswer'] = $Comment['DateInserted']; } } // Update the comment. Gdn::SQL()->Put('Comment', $CommentSet, array('CommentID' => $Comment['CommentID'])); // Update the discussion. if ($Discussion['QnA'] != $QnA && (!$Discussion['QnA'] || in_array($Discussion['QnA'], array('Unanswered', 'Answered', 'Rejected')))) { Gdn::SQL()->Put('Discussion', $DiscussionSet, array('DiscussionID' => $Comment['DiscussionID'])); } // Determine QnA change if ($Comment['QnA'] != $QnA) { $Change = 0; switch ($QnA) { case 'Rejected': $Change = -1; if ($Comment['QnA'] != 'Accepted') { $Change = 0; } break; case 'Accepted': $Change = 1; break; default: if ($Comment['QnA'] == 'Rejected') { $Change = 0; } if ($Comment['QnA'] == 'Accepted') { $Change = -1; } break; } } // Apply change effects if ($Change) { // Update the user $UserID = GetValue('InsertUserID', $Comment); $this->RecalculateUserQnA($UserID); // Update reactions if ($this->Reactions) { include_once Gdn::Controller()->FetchViewLocation('reaction_functions', '', 'plugins/Reactions'); $Rm = new ReactionModel(); // If there's change, reactions will take care of it $Rm->React('Comment', $Comment['CommentID'], 'AcceptAnswer'); } } // Record the activity. if ($QnA == 'Accepted') { $Activity = array('ActivityType' => 'AnswerAccepted', 'NotifyUserID' => $Comment['InsertUserID'], 'HeadlineFormat' => '{ActivityUserID,You} accepted {NotifyUserID,your} answer.', 'RecordType' => 'Comment', 'RecordID' => $Comment['CommentID'], 'Route' => CommentUrl($Comment, '/'), 'Emailed' => ActivityModel::SENT_PENDING, 'Notified' => ActivityModel::SENT_PENDING); $ActivityModel = new ActivityModel(); $ActivityModel->Save($Activity); } } Redirect("/discussion/comment/{$Comment['CommentID']}#Comment_{$Comment['CommentID']}"); }
/** * Delete an activity item. * * @since 2.0.0 * @access public * * @param int $ActivityID Unique ID of item to delete. * @param string $TransientKey Verify intent. */ public function Delete($ActivityID = '', $TransientKey = '') { $Session = Gdn::Session(); if (!$Session->ValidateTransientKey($TransientKey)) { throw PermissionException(); } if (!is_numeric($ActivityID)) { throw Gdn_UserException('Invalid activity ID'); } $HasPermission = $Session->CheckPermission('Garden.Activity.Delete'); if (!$HasPermission) { $Activity = $this->ActivityModel->GetID($ActivityID); if (!$Activity) { throw NotFoundException('Activity'); } $HasPermission = $Activity['InsertUserID'] == $Session->UserID; } if (!$HasPermission) { throw PermissionException(); } $this->ActivityModel->Delete($ActivityID); if ($this->_DeliveryType === DELIVERY_TYPE_ALL) { Redirect(GetIncomingValue('Target', $this->SelfUrl)); } // Still here? Getting a 404. $this->ControllerName = 'Home'; $this->View = 'FileNotFound'; $this->Render(); }
/** * * @param PostController $Sender * @param type $RecordType * @param type $ID * @throws type */ public function PostController_Twitter_Create($Sender, $RecordType, $ID) { if (!$this->SocialReactions()) { throw PermissionException(); } // if (!Gdn::Request()->IsPostBack()) // throw PermissionException('Javascript'); $Row = GetRecord($RecordType, $ID); if ($Row) { // Grab the tweet message. switch (strtolower($RecordType)) { case 'discussion': $Message = Gdn_Format::PlainText($Row['Name'], 'Text'); break; case 'comment': default: $Message = Gdn_Format::PlainText($Row['Body'], $Row['Format']); } $Elips = '...'; $Message = preg_replace('`\\s+`', ' ', $Message); // if (function_exists('normalizer_is_normalized')) { // // Slice the string to 119 characters (21 reservered for the url. // if (!normalizer_is_normalized($Message)) // $Message = Normalizer::normalize($Message, Normalizer::FORM_D); // $Elips = Normalizer::normalize($Elips, Normalizer::FORM_D); // } $Max = 140; $LinkLen = 22; $Max -= $LinkLen; $Message = SliceParagraph($Message, $Max); if (strlen($Message) > $Max) { $Message = substr($Message, 0, $Max - strlen($Elips)) . $Elips; } // echo $Message.strlen($Message); if ($this->AccessToken()) { Gdn::Controller()->SetData('Message', $Message); $Message .= ' ' . $Row['ShareUrl']; $R = $this->API('/statuses/update.json', array('status' => $Message), 'POST'); $Sender->SetJson('R', $R); $Sender->InformMessage(T('Thanks for sharing!')); } else { $Get = array('text' => $Message, 'url' => $Row['ShareUrl']); $Url = "http://twitter.com/share?" . http_build_query($Get); Redirect($Url); } } $Sender->Render('Blank', 'Utility', 'Dashboard'); }
public function PluginController_ReceiveUpload_Create($Sender) { $IncomingTransientKey = GetPostValue('TransientKey', Gdn::Session()->TransientKey()); $IncomingUserID = GetPostValue('SessionUserID', Gdn::Session()->UserID); $Folder = GetPostValue('Folder'); $User = Gdn::UserModel()->GetID($IncomingUserID); $UserTransientKey = GetValueR('Attributes.TransientKey', $User); if (!($IncomingTransientKey && $IncomingTransientKey == $UserTransientKey)) { throw PermissionException(); } if (!self::HasPermission($User)) { throw PermissionException(); } $Folder = trim($Folder, '/\\'); if (substr($Folder, 0, 7) == 'uploads') { $Folder = trim(substr($Folder, 7), '/\\'); } if (!$Folder || $Folder == 'false') { $Folder = 'i'; $_POST['AddYear'] = True; $_POST['AddMonth'] = True; } if (GetPostValue('Debug')) { $DEBUG = array('$_POST' => $_POST, '$IncomingTransientKey' => $IncomingTransientKey, '$IncomingUserID' => $IncomingUserID, '$Sender->DeliveryType()' => $Sender->DeliveryType(), '$Sender->DeliveryMethod()' => $Sender->DeliveryMethod(), 'Uploadify' => GetPostValue('Uploadify')); file_put_contents(__DIR__ . '/post_' . rand(0, 99999) . '.txt', var_export($DEBUG, True)); } //$TargetFolder = PATH_UPLOADS . DS . $Folder; $TargetFolder = 'uploads' . DS . $Folder; if (GetPostValue('AddYear')) { $TargetFolder .= DS . date('Y'); } if (GetPostValue('AddMonth')) { $TargetFolder .= DS . date('m'); } $Result = UploadFile($TargetFolder, 'File', array('WebTarget' => True)); if (GetPostValue('Asset')) { $Result = Asset($Result); } if (GetPostValue('Uploadify')) { echo $Result; return; } $Sender->SetData('Result', $Result); $Sender->Render(); }
public function Update() { // Check for permission or flood control. // These settings are loaded/saved to the database because we don't want the config file storing non/config information. $Now = time(); $LastTime = Gdn::Get('Garden.Update.LastTimestamp', 0); if ($LastTime + (60 * 60 * 24) > $Now) { // Check for flood control. $Count = Gdn::Get('Garden.Update.Count', 0) + 1; if ($Count > 5) { if (!Gdn::Session()->CheckPermission('Garden.Settings.Manage')) { // We are only allowing an update of 5 times every 24 hours. throw PermissionException(); } } } else { $Count = 1; } Gdn::Set('Garden.Update.LastTimestamp', $Now); Gdn::Set('Garden.Update.Count', $Count); // Run the structure. $UpdateModel = new UpdateModel(); $UpdateModel->RunStructure(); $this->SetData('Success', TRUE); $this->MasterView = 'none'; $this->Render(); }
/** * Edit a discussion (wrapper for PostController::Discussion). * * Will throw an error if both params are blank. * * @since 2.0.0 * @access public * * @param int $DiscussionID Unique ID of the discussion to edit. * @param int $DraftID Unique ID of draft discussion to edit. */ public function EditDiscussion($DiscussionID = '', $DraftID = '') { if ($DraftID != '') { $this->Draft = $this->DraftModel->GetID($DraftID); $this->CategoryID = $this->Draft->CategoryID; // Verify this is their draft if (GetValue('InsertUserID', $this->Draft) != Gdn::Session()->UserID) { throw PermissionException(); } } else { $this->SetData('Discussion', $this->DiscussionModel->GetID($DiscussionID), TRUE); $this->CategoryID = $this->Discussion->CategoryID; } if (C('Garden.ForceInputFormatter')) { $this->Form->RemoveFormValue('Format'); } // Set view and render $this->View = 'Discussion'; $this->Discussion($this->CategoryID); }
public function NotSpam($LogIDs) { $this->Permission('Garden.Moderation.Manage'); if (!$this->Request->IsPostBack()) { throw PermissionException('Javascript'); } $Logs = array(); // Verify the appropriate users. $UserIDs = $this->Form->GetFormValue('UserID', array()); if (!is_array($UserIDs)) { $UserIDs = array(); } foreach ($UserIDs as $UserID) { Gdn::UserModel()->SetField($UserID, 'Verified', TRUE); $Logs = array_merge($Logs, $this->LogModel->GetWhere(array('Operation' => 'Spam', 'RecordUserID' => $UserID))); } // Grab the logs. $Logs = array_merge($Logs, $this->LogModel->GetIDs($LogIDs)); // try { foreach ($Logs as $Log) { $this->LogModel->Restore($Log); } // } catch (Exception $Ex) { // $this->Form->AddError($Ex->getMessage()); // } $this->LogModel->Recalculate(); $this->SetData('Complete'); $this->SetData('Count', count($Logs)); $this->Render('Blank', 'Utility'); }
/** * Re-fetch a discussion's content based on its foreign url. * @param type $DiscussionID */ public function RefetchPageInfo($DiscussionID) { // Make sure we are posting back. if (!$this->Request->IsPostBack()) { throw PermissionException('Javascript'); } // Grab the discussion. $Discussion = $this->DiscussionModel->GetID($DiscussionID); if (!$Discussion) { throw NotFoundException('Discussion'); } // Make sure the user has permission to edit this discussion. $this->Permission('Vanilla.Discussions.Edit', TRUE, 'Category', $Discussion->PermissionCategoryID); $ForeignUrl = GetValueR('Attributes.ForeignUrl', $Discussion); if (!$ForeignUrl) { throw new Gdn_UserException(T("This discussion isn't associated with a url.")); } $Stub = $this->DiscussionModel->FetchPageInfo($ForeignUrl, TRUE); // Save the stub. $this->DiscussionModel->SetField($DiscussionID, (array) $Stub); // Send some of the stuff back. if (isset($Stub['Name'])) { $this->JsonTarget('.PageTitle h1', Gdn_Format::Text($Stub['Name'])); } if (isset($Stub['Body'])) { $this->JsonTarget("#Discussion_{$DiscussionID} .Message", Gdn_Format::To($Stub['Body'], $Stub['Format'])); } $this->InformMessage('The page was successfully fetched.'); $this->Render('Blank', 'Utility', 'Dashboard'); }
public function Controller_Delete($Sender) { $Session = Gdn::Session(); $DPModel = new DiscussionPollsModel(); $DiscussionModel = new DiscussionModel(); $Poll = $DPModel->Get($Sender->RequestArgs[1]); $Discussion = $DiscussionModel->GetID($Poll->DiscussionID); $PollOwnerID = $Discussion->InsertUserID; if ($Session->CheckPermission('Plugins.DiscussionPolls.Manage') || $PollOwnerID == $Session->UserID) { $DPModel = new DiscussionPollsModel(); $DPModel->Delete($Sender->RequestArgs[1]); $Result = 'Removed poll with id ' . $Sender->RequestArgs[1]; if ($Sender->DeliveryType() == DELIVERY_TYPE_VIEW) { $Data = array('html' => $Result); echo json_encode($Data); } else { $Sender->SetData('PollString', $Result); $Sender->Render($this->ThemView('poll')); } } else { // throw permission exception throw PermissionException(); } }
/** * Handle discussion option menu Resolve action. * * @throws Exception Throws an exception when the discussion is not found, or the request is not a POST * @return void */ public function discussionController_resolve_create($sender, $args) { $sender->permission('Plugins.Resolved.Manage'); $discussionID = $sender->Request->get('discussionid'); $resolve = $sender->Request->get('resolve'); // Make sure we are posting back. if (!$sender->Request->isPostBack()) { throw PermissionException('Javascript'); } $discussion = $sender->DiscussionModel->getID($discussionID); if (!$discussion) { throw NotFoundException('Discussion'); } // Resolve the discussion. $this->resolve($discussion, $resolve); $sender->sendOptions($discussion); if (!$resolve) { require_once $sender->fetchViewLocation('helper_functions', 'Discussions'); $sender->jsonTarget(".Section-DiscussionList #Discussion_{$discussionID} .Meta-Discussion", '<span class="Tag Tag-Unresolved" title="Unresolved">' . T('Unresolved') . '</span>', 'Prepend'); $sender->jsonTarget(".Section-DiscussionList #Discussion_{$discussionID}", 'Unresolved', 'AddClass'); } else { $sender->jsonTarget(".Section-DiscussionList #Discussion_{$discussionID} .Tag-Unresolved", null, 'Remove'); $sender->jsonTarget(".Section-DiscussionList #Discussion_{$discussionID}", 'Unresolved', 'RemoveClass'); } $sender->jsonTarget("#Discussion_{$discussionID}", null, 'Highlight'); $sender->jsonTarget(".Discussion #Item_0", null, 'Highlight'); $sender->render('Blank', 'Utility', 'Dashboard'); }