コード例 #1
0
 /**
  *
  *
  * @return LightOpenID
  */
 public function getOpenID()
 {
     $OpenID = new LightOpenID();
     if ($url = Gdn::request()->get('url')) {
         if (!filter_var($url, FILTER_VALIDATE_URL)) {
             throw new Gdn_UserException(sprintf(t('ValidateUrl'), 'OpenID'), 400);
         }
         // Don't allow open ID on a non-standard scheme.
         $scheme = parse_url($url, PHP_URL_SCHEME);
         if (!in_array($scheme, array('http', 'https'))) {
             throw new Gdn_UserException(sprintf(t('ValidateUrl'), 'OpenID'), 400);
         }
         // Don't allow open ID on a non-standard port.
         $port = parse_url($url, PHP_URL_PORT);
         if ($port && !in_array($port, array(80, 8080, 443))) {
             throw new Gdn_UserException(t('OpenID is not allowed on non-standard ports.'));
         }
         $OpenID->identity = $url;
     }
     $Url = url('/entry/connect/openid', true);
     $UrlParts = explode('?', $Url);
     parse_str(val(1, $UrlParts, ''), $Query);
     $Query = array_merge($Query, arrayTranslate($_GET, array('display', 'Target')));
     $OpenID->returnUrl = $UrlParts[0] . '?' . http_build_query($Query);
     $OpenID->required = array('contact/email', 'namePerson/first', 'namePerson/last', 'pref/language');
     $this->EventArguments['OpenID'] = $OpenID;
     $this->fireEvent('GetOpenID');
     return $OpenID;
 }
コード例 #2
0
/**
 * Render a breadcrumb trail for the user based on the page they are on.
 *
 * @param array $Params
 * @param object $Smarty
 * @return string
 */
function smarty_function_breadcrumbs($Params, &$Smarty)
{
    $Breadcrumbs = $Smarty->Controller->data('Breadcrumbs');
    if (!is_array($Breadcrumbs)) {
        $Breadcrumbs = array();
    }
    $Options = arrayTranslate($Params, array('homeurl' => 'HomeUrl', 'hidelast' => 'HideLast'));
    return Gdn_Theme::breadcrumbs($Breadcrumbs, val('homelink', $Params, true), $Options);
}
コード例 #3
0
ファイル: class.categorymodel.php プロジェクト: R-J/vanilla
 /**
  * Modifies category data before it is returned.
  *
  * Adds CountAllDiscussions column to each category representing the sum of
  * discussions within this category as well as all subcategories.
  *
  * @since 2.0.17
  * @access public
  *
  * @param object $Data SQL result.
  */
 public static function addCategoryColumns($Data)
 {
     $Result =& $Data->result();
     $Result2 = $Result;
     foreach ($Result as &$Category) {
         if (!property_exists($Category, 'CountAllDiscussions')) {
             $Category->CountAllDiscussions = $Category->CountDiscussions;
         }
         if (!property_exists($Category, 'CountAllComments')) {
             $Category->CountAllComments = $Category->CountComments;
         }
         // Calculate the following field.
         $Following = !((bool) val('Archived', $Category) || (bool) val('Unfollow', $Category));
         $Category->Following = $Following;
         $DateMarkedRead = val('DateMarkedRead', $Category);
         $UserDateMarkedRead = val('UserDateMarkedRead', $Category);
         if (!$DateMarkedRead) {
             $DateMarkedRead = $UserDateMarkedRead;
         } elseif ($UserDateMarkedRead && Gdn_Format::toTimestamp($UserDateMarkedRead) > Gdn_Format::ToTimeStamp($DateMarkedRead)) {
             $DateMarkedRead = $UserDateMarkedRead;
         }
         // Set appropriate Last* columns.
         setValue('LastTitle', $Category, val('LastDiscussionTitle', $Category, null));
         $LastDateInserted = val('LastDateInserted', $Category, null);
         if (val('LastCommentUserID', $Category) == null) {
             setValue('LastCommentUserID', $Category, val('LastDiscussionUserID', $Category, null));
             setValue('DateLastComment', $Category, val('DateLastDiscussion', $Category, null));
             setValue('LastUserID', $Category, val('LastDiscussionUserID', $Category, null));
             $LastDiscussion = arrayTranslate($Category, array('LastDiscussionID' => 'DiscussionID', 'CategoryID' => 'CategoryID', 'LastTitle' => 'Name'));
             setValue('LastUrl', $Category, DiscussionUrl($LastDiscussion, false, '/') . '#latest');
             if (is_null($LastDateInserted)) {
                 setValue('LastDateInserted', $Category, val('DateLastDiscussion', $Category, null));
             }
         } else {
             $LastDiscussion = arrayTranslate($Category, array('LastDiscussionID' => 'DiscussionID', 'CategoryID' => 'CategoryID', 'LastTitle' => 'Name'));
             setValue('LastUserID', $Category, val('LastCommentUserID', $Category, null));
             setValue('LastUrl', $Category, DiscussionUrl($LastDiscussion, false, '/') . '#latest');
             if (is_null($LastDateInserted)) {
                 setValue('LastDateInserted', $Category, val('DateLastComment', $Category, null));
             }
         }
         $LastDateInserted = val('LastDateInserted', $Category, null);
         if ($DateMarkedRead) {
             if ($LastDateInserted) {
                 $Category->Read = Gdn_Format::toTimestamp($DateMarkedRead) >= Gdn_Format::toTimestamp($LastDateInserted);
             } else {
                 $Category->Read = true;
             }
         } else {
             $Category->Read = false;
         }
         foreach ($Result2 as $Category2) {
             if ($Category2->TreeLeft > $Category->TreeLeft && $Category2->TreeRight < $Category->TreeRight) {
                 $Category->CountAllDiscussions += $Category2->CountDiscussions;
                 $Category->CountAllComments += $Category2->CountComments;
             }
         }
     }
 }
コード例 #4
0
ファイル: class.updatemodel.php プロジェクト: vanilla/vanilla
 /**
  * Check an addon's file to extract the addon information out of it.
  *
  * @param string $Path The path to the file.
  * @param bool $ThrowError Whether or not to throw an exception if there is a problem analyzing the addon.
  * @return array An array of addon information.
  */
 public static function analyzeAddon($Path, $ThrowError = true)
 {
     if (!file_exists($Path)) {
         if ($ThrowError) {
             throw new Exception("{$Path} not found.", 404);
         }
         return false;
     }
     $Addon = [];
     $Result = [];
     $InfoPaths = array('/settings/about.php', '/default.php', '/class.*.plugin.php', '/about.php', '/definitions.php', '/index.php', 'vanilla2export.php');
     // Get the list of potential files to analyze.
     if (is_dir($Path)) {
         $Entries = self::getInfoFiles($Path, $InfoPaths);
         $DeleteEntries = false;
     } else {
         $Entries = self::getInfoZip($Path, $InfoPaths, false, $ThrowError);
         $DeleteEntries = true;
     }
     foreach ($Entries as $Entry) {
         if ($Entry['Name'] == '/index.php') {
             // This could be the core vanilla package.
             $Version = self::parseCoreVersion($Entry['Path']);
             if (!$Version) {
                 continue;
             }
             // The application was confirmed.
             $Addon = array('AddonKey' => 'vanilla', 'AddonTypeID' => ADDON_TYPE_CORE, 'Name' => 'Vanilla', 'Description' => 'Vanilla is an open-source, standards-compliant, multi-lingual, fully extensible discussion forum for the web. Anyone who has web-space that meets the requirements can download and use Vanilla for free!', 'Version' => $Version, 'License' => 'GPLv2', 'Path' => $Entry['Path']);
             break;
         } elseif ($Entry['Name'] == 'vanilla2export.php') {
             // This could be the vanilla porter.
             $Version = self::parseCoreVersion($Entry['Path']);
             if (!$Version) {
                 continue;
             }
             $Addon = array('AddonKey' => 'porter', 'AddonTypeID' => ADDON_TYPE_CORE, 'Name' => 'Vanilla Porter', 'Description' => 'Drop this script in your existing site and navigate to it in your web browser to export your existing forum data to the Vanilla 2 import format.', 'Version' => $Version, 'License' => 'GPLv2', 'Path' => $Entry['Path']);
             break;
         } else {
             // This could be an addon.
             $Info = self::parseInfoArray($Entry['Path']);
             if (!is_array($Info) && count($Info)) {
                 continue;
             }
             $Key = key($Info);
             $Variable = $Info['Variable'];
             $Info = $Info[$Key];
             // Validate the addon.
             $Name = $Entry['Name'];
             $Valid = true;
             if (!val('Name', $Info)) {
                 $Info['Name'] = $Key;
             }
             // Validate basic fields.
             $checkResult = self::checkRequiredFields($Info);
             if (count($checkResult)) {
                 $Result = array_merge($Result, $checkResult);
                 $Valid = false;
             }
             // Validate folder name matches key.
             if (isset($Entry['Base']) && strcasecmp($Entry['Base'], $Key) != 0 && $Variable != 'ThemeInfo') {
                 $Result[] = "{$Name}: The addon's key is not the same as its folder name.";
                 $Valid = false;
             }
             if (!$Valid) {
                 continue;
             }
             // The addon is valid.
             $Addon = array_merge(array('AddonKey' => $Key, 'AddonTypeID' => ''), $Info);
             switch ($Variable) {
                 case 'ApplicationInfo':
                     $Addon['AddonTypeID'] = ADDON_TYPE_APPLICATION;
                     break;
                 case 'LocaleInfo':
                     $Addon['AddonTypeID'] = ADDON_TYPE_LOCALE;
                     break;
                 case 'PluginInfo':
                     $Addon['AddonTypeID'] = ADDON_TYPE_PLUGIN;
                     break;
                 case 'ThemeInfo':
                     $Addon['AddonTypeID'] = ADDON_TYPE_THEME;
                     break;
             }
         }
     }
     if ($DeleteEntries) {
         $FolderPath = substr($Path, 0, -4);
         Gdn_FileSystem::removeFolder($FolderPath);
     }
     // Add the addon requirements.
     if (!empty($Addon)) {
         $Requirements = arrayTranslate($Addon, ['RequiredApplications' => 'Applications', 'RequiredPlugins' => 'Plugins', 'RequiredThemes' => 'Themes']);
         foreach ($Requirements as $Type => $Items) {
             if (!is_array($Items)) {
                 unset($Requirements[$Type]);
             }
         }
         $Addon['Requirements'] = dbencode($Requirements);
         $Addon['Checked'] = true;
         $Addon['Path'] = $Path;
         $UploadsPath = PATH_UPLOADS . '/';
         if (stringBeginsWith($Addon['Path'], $UploadsPath)) {
             $Addon['File'] = substr($Addon['Path'], strlen($UploadsPath));
         }
         if (is_file($Path)) {
             $Addon['MD5'] = md5_file($Path);
             $Addon['FileSize'] = filesize($Path);
         }
     } elseif ($ThrowError) {
         $Msg = implode("\n", $Result);
         throw new Gdn_UserException($Msg, 400);
     } else {
         return false;
     }
     return $Addon;
 }
コード例 #5
0
 /**
  * An intermediate page for jsConnect that checks SSO against and then posts the information to /entry/connect.
  *
  * @param EntryController $Sender
  * @param string $Action A specific action. It can be one of the following:
  *
  * - blank: The default action.
  * - guest: There is no user signed in.
  * -
  * @param string $Target The url to redirect to after a successful connect.
  * @throws /Exception Throws an exception when the jsConnect provider is not found.
  */
 public function entryController_jsConnect_create($Sender, $Action = '', $Target = '')
 {
     $Sender->setData('_NoMessages', true);
     if ($Action) {
         if ($Action == 'guest') {
             $Sender->addDefinition('CheckPopup', true);
             $Target = $Sender->Form->getFormValue('Target', '/');
             $Sender->RedirectUrl = $Target;
             $Sender->render('JsConnect', '', 'plugins/jsconnect');
         } else {
             parse_str($Sender->Form->getFormValue('JsConnect'), $JsData);
             $Error = val('error', $JsData);
             $Message = val('message', $JsData);
             if ($Error === 'timeout' && !$Message) {
                 $Message = t('Your sso timed out.', 'Your sso timed out during the request. Please try again.');
             }
             Gdn::dispatcher()->passData('Exception', $Message ? htmlspecialchars($Message) : htmlspecialchars($Error))->dispatch('home/error');
         }
     } else {
         $client_id = $Sender->setData('client_id', $Sender->Request->get('client_id', 0));
         $Provider = self::getProvider($client_id);
         if (empty($Provider)) {
             throw NotFoundException('Provider');
         }
         $Get = arrayTranslate($Sender->Request->get(), ['client_id', 'display']);
         $Sender->addDefinition('JsAuthenticateUrl', self::connectUrl($Provider, true));
         $Sender->addJsFile('jsconnect.js', 'plugins/jsconnect');
         $Sender->setData('Title', t('Connecting...'));
         $Sender->Form->Action = url('/entry/connect/jsconnect?' . http_build_query($Get));
         $Sender->Form->addHidden('JsConnect', '');
         $Sender->Form->addHidden('Target', $Target);
         $Sender->MasterView = 'empty';
         $Sender->Render('JsConnect', '', 'plugins/jsconnect');
     }
 }
コード例 #6
0
 /**
  * Check an addon's file to extract the addon information out of it.
  *
  * @param string $Path The path to the file.
  * @param bool $Fix Whether or not to fix files that have been zipped incorrectly.
  * @return array An array of addon information.
  */
 public static function analyzeAddon($Path, $ThrowError = true)
 {
     if (!file_exists($Path)) {
         if ($ThrowError) {
             throw new Exception("{$Path} not found.", 404);
         }
         return false;
     }
     $Result = array();
     $InfoPaths = array('/settings/about.php', '/default.php', '/class.*.plugin.php', '/about.php', '/definitions.php', '/index.php', 'vanilla2export.php');
     // Get the list of potential files to analyze.
     if (is_dir($Path)) {
         $Entries = self::_GetInfoFiles($Path, $InfoPaths);
     } else {
         $Entries = self::_GetInfoZip($Path, $InfoPaths, false, $ThrowError);
         $DeleteEntries = true;
     }
     foreach ($Entries as $Entry) {
         if ($Entry['Name'] == '/index.php') {
             // This could be the core vanilla package.
             $Version = self::ParseCoreVersion($Entry['Path']);
             if (!$Version) {
                 continue;
             }
             // The application was confirmed.
             $Addon = array('AddonKey' => 'vanilla', 'AddonTypeID' => ADDON_TYPE_CORE, 'Name' => 'Vanilla', 'Description' => 'Vanilla is an open-source, standards-compliant, multi-lingual, fully extensible discussion forum for the web. Anyone who has web-space that meets the requirements can download and use Vanilla for free!', 'Version' => $Version, 'Path' => $Entry['Path']);
             break;
         } elseif ($Entry['Name'] == 'vanilla2export.php') {
             // This could be the vanilla porter.
             $Version = self::ParseCoreVersion($Entry['Path']);
             if (!$Version) {
                 continue;
             }
             $Addon = array('AddonKey' => 'porter', 'AddonTypeID' => ADDON_TYPE_CORE, 'Name' => 'Vanilla Porter', 'Description' => 'Drop this script in your existing site and navigate to it in your web browser to export your existing forum data to the Vanilla 2 import format.', 'Version' => $Version, 'Path' => $Entry['Path']);
             break;
         } else {
             // This could be an addon.
             $Info = self::ParseInfoArray($Entry['Path']);
             if (!is_array($Info) && count($Info)) {
                 continue;
             }
             $Key = key($Info);
             $Variable = $Info['Variable'];
             $Info = $Info[$Key];
             // Validate the addon.
             $Name = $Entry['Name'];
             $Valid = true;
             if (!val('Name', $Info)) {
                 $Info['Name'] = $Key;
             }
             if (!val('Description', $Info)) {
                 $Result[] = $Name . ': ' . sprintf(t('ValidateRequired'), t('Description'));
                 $Valid = false;
             }
             if (!val('Version', $Info)) {
                 $Result[] = $Name . ': ' . sprintf(t('ValidateRequired'), t('Version'));
                 $Valid = false;
             }
             if (isset($Entry['Base']) && strcasecmp($Entry['Base'], $Key) != 0 && $Variable != 'ThemeInfo') {
                 $Result[] = "{$Name}: The addon's key is not the same as its folder name.";
                 $Valid = false;
             }
             if (!$Valid) {
                 continue;
             }
             // The addon is valid.
             $Addon = array_merge(array('AddonKey' => $Key, 'AddonTypeID' => ''), $Info);
             switch ($Variable) {
                 case 'ApplicationInfo':
                     $Addon['AddonTypeID'] = ADDON_TYPE_APPLICATION;
                     break;
                 case 'LocaleInfo':
                     $Addon['AddonTypeID'] = ADDON_TYPE_LOCALE;
                     break;
                 case 'PluginInfo':
                     $Addon['AddonTypeID'] = ADDON_TYPE_PLUGIN;
                     break;
                 case 'ThemeInfo':
                     $Addon['AddonTypeID'] = ADDON_TYPE_THEME;
                     break;
             }
         }
     }
     if ($DeleteEntries) {
         $FolderPath = substr($Path, 0, -4);
         Gdn_FileSystem::RemoveFolder($FolderPath);
     }
     // Add the addon requirements.
     if ($Addon) {
         $Requirements = arrayTranslate($Addon, array('RequiredApplications' => 'Applications', 'RequiredPlugins' => 'Plugins', 'RequiredThemes' => 'Themes'));
         foreach ($Requirements as $Type => $Items) {
             if (!is_array($Items)) {
                 unset($Requirements[$Type]);
             }
         }
         $Addon['Requirements'] = serialize($Requirements);
         $Addon['Checked'] = true;
         $Addon['Path'] = $Path;
         $UploadsPath = PATH_UPLOADS . '/';
         if (stringBeginsWith($Addon['Path'], $UploadsPath)) {
             $Addon['File'] = substr($Addon['Path'], strlen($UploadsPath));
         }
         if (is_file($Path)) {
             $Addon['MD5'] = md5_file($Path);
             $Addon['FileSize'] = filesize($Path);
         }
     } elseif ($ThrowError) {
         $Msg = implode("\n", $Result);
         throw new Gdn_UserException($Msg, 400);
     } else {
         return false;
     }
     return $Addon;
     // Figure out what kind of addon this is.
     $Root = '';
     $NewRoot = '';
     $Addon = false;
     foreach ($Entries as $Entry) {
         $Name = '/' . ltrim($Entry['name'], '/');
         $Filename = basename($Name);
         $Folder = substr($Name, 0, -strlen($Filename));
         $NewRoot = '';
         // Check to see if the entry is a plugin file.
         if ($Filename == 'default.php' || StringEndsWith($Filename, '.plugin.php')) {
             if (count(explode('/', $Folder)) > 3) {
                 // The file is too deep to be a plugin file.
                 continue;
             }
             // This could be a plugin file, but we have to examine its info array.
             $Zip->extractTo($FolderPath, $Entry['name']);
             $FilePath = CombinePaths(array($FolderPath, $Name));
             $Info = self::ParseInfoArray($FilePath, 'PluginInfo');
             Gdn_FileSystem::RemoveFolder(dirname($FilePath));
             if (!is_array($Info) || !count($Info)) {
                 continue;
             }
             // Check to see if the info array conforms to a plugin spec.
             $Key = key($Info);
             $Info = $Info[$Key];
             $Root = trim($Folder, '/');
             $Valid = true;
             // Make sure the key matches the folder name.
             if ($Root && strcasecmp($Root, $Key) != 0) {
                 $Result[] = "{$Name}: The plugin's key is not the same as its folder name.";
                 $Valid = false;
             } else {
                 $NewRoot = $Root;
             }
             if (!val('Description', $Info)) {
                 $Result[] = $Name . ': ' . sprintf(t('ValidateRequired'), t('Description'));
                 $Valid = false;
             }
             if (!val('Version', $Info)) {
                 $Result[] = $Name . ': ' . sprintf(t('ValidateRequired'), t('Version'));
                 $Valid = false;
             }
             if ($Valid) {
                 // The plugin was confirmed.
                 $Addon = array('AddonKey' => $Key, 'AddonTypeID' => ADDON_TYPE_PLUGIN, 'Name' => val('Name', $Info) ? $Info['Name'] : $Key, 'Description' => $Info['Description'], 'Version' => $Info['Version'], 'Path' => $Path);
                 break;
             }
             continue;
         }
         // Check to see if the entry is an application file.
         if (StringEndsWith($Name, '/settings/about.php')) {
             if (count(explode('/', $Folder)) > 4) {
                 $Result[] = "{$Name}: The application's info array was not in the correct location.";
                 // The file is too deep to be a plugin file.
                 continue;
             }
             // This could be a plugin file, but we have to examine its info array.
             $Zip->extractTo($FolderPath, $Entry['name']);
             $FilePath = CombinePaths(array($FolderPath, $Name));
             $Info = self::ParseInfoArray($FilePath, 'ApplicationInfo');
             Gdn_FileSystem::RemoveFolder(dirname($FilePath));
             if (!is_array($Info) || !count($Info)) {
                 $Result[] = "{$Name}: The application's info array could not be parsed.";
                 continue;
             }
             $Key = key($Info);
             $Info = $Info[$Key];
             $Root = trim(substr($Name, 0, -strlen('/settings/about.php')), '/');
             $Valid = true;
             // Make sure the key matches the folder name.
             if ($Root && strcasecmp($Root, $Key) != 0) {
                 $Result[] = "{$Name}: The application's key is not the same as its folder name.";
                 $Valid = false;
             } else {
                 $NewRoot = $Root;
             }
             if (!val('Description', $Info)) {
                 $Result[] = $Name . ': ' . sprintf(t('ValidateRequired'), t('Description'));
                 $Valid = false;
             }
             if (!val('Version', $Info)) {
                 $Result[] = $Name . ': ' . sprintf(t('ValidateRequired'), t('Version'));
                 $Valid = false;
             }
             if ($Valid) {
                 // The application was confirmed.
                 $Addon = array('AddonKey' => $Key, 'AddonTypeID' => ADDON_TYPE_APPLICATION, 'Name' => val('Name', $Info) ? $Info['Name'] : $Key, 'Description' => $Info['Description'], 'Version' => $Info['Version'], 'Path' => $Path);
                 break;
             }
             continue;
         }
         // Check to see if the entry is a theme file.
         if (StringEndsWith($Name, '/about.php')) {
             if (count(explode('/', $Folder)) > 3) {
                 // The file is too deep to be a plugin file.
                 continue;
             }
             // This could be a theme file, but we have to examine its info array.
             $Zip->extractTo($FolderPath, $Entry['name']);
             $FilePath = CombinePaths(array($FolderPath, $Name));
             $Info = self::ParseInfoArray($FilePath, 'ThemeInfo');
             Gdn_FileSystem::RemoveFolder(dirname($FilePath));
             if (!is_array($Info) || !count($Info)) {
                 continue;
             }
             $Key = key($Info);
             $Info = $Info[$Key];
             $Valid = true;
             $Root = trim(substr($Name, 0, -strlen('/about.php')), '/');
             // Make sure the theme is at least one folder deep.
             if (strlen($Root) == 0) {
                 $Result[] = $Name . ': The theme must be in a folder.';
                 $Valid = false;
             }
             if (!val('Description', $Info)) {
                 $Result[] = $Name . ': ' . sprintf(t('ValidateRequired'), t('Description'));
                 $Valid = false;
             }
             if (!val('Version', $Info)) {
                 $Result[] = $Name . ': ' . sprintf(t('ValidateRequired'), t('Version'));
                 $Valid = false;
             }
             if ($Valid) {
                 // The application was confirmed.
                 $Addon = array('AddonKey' => $Key, 'AddonTypeID' => ADDON_TYPE_THEME, 'Name' => val('Name', $Info) ? $Info['Name'] : $Key, 'Description' => $Info['Description'], 'Version' => $Info['Version'], 'Path' => $Path);
                 break;
             }
         }
         if (StringEndsWith($Name, '/definitions.php')) {
             if (count(explode('/', $Folder)) > 3) {
                 // The file is too deep to be a plugin file.
                 continue;
             }
             // This could be a locale pack, but we have to examine its info array.
             $Zip->extractTo($FolderPath, $Entry['name']);
             $FilePath = CombinePaths(array($FolderPath, $Name));
             $Info = self::ParseInfoArray($FilePath, 'LocaleInfo');
             Gdn_FileSystem::RemoveFolder(dirname($FilePath));
             if (!is_array($Info) || !count($Info)) {
                 continue;
             }
             $Key = key($Info);
             $Info = $Info[$Key];
             $Valid = true;
             $Root = trim(substr($Name, 0, -strlen('/definitions.php')), '/');
             // Make sure the locale is at least one folder deep.
             if ($Root != $Key) {
                 $Result[] = $Name . ': The locale pack\'s key must be the same as its folder name.';
                 $Valid = false;
             }
             if (!val('Locale', $Info)) {
                 $Result[] = $Name . ': ' . sprintf(t('ValidateRequired'), t('Locale'));
                 $Valud = false;
             } elseif (strcasecmp($Info['Locale'], $Key) == 0) {
                 $Result[] = $Name . ': ' . t('The locale\'s key cannot be the same as the name of the locale.');
                 $Valid = false;
             }
             if (!val('Description', $Info)) {
                 $Result[] = $Name . ': ' . sprintf(t('ValidateRequired'), t('Description'));
                 $Valid = false;
             }
             if (!val('Version', $Info)) {
                 $Result[] = $Name . ': ' . sprintf(t('ValidateRequired'), t('Version'));
                 $Valid = false;
             }
             if ($Valid) {
                 // The locale pack was confirmed.
                 $Addon = array('AddonKey' => $Key, 'AddonTypeID' => ADDON_TYPE_LOCALE, 'Name' => val('Name', $Info) ? $Info['Name'] : $Key, 'Description' => $Info['Description'], 'Version' => $Info['Version'], 'Path' => $Path);
                 break;
             }
         }
         // Check to see if the entry is a core file.
         if (StringEndsWith($Name, '/index.php')) {
             if (count(explode('/', $Folder)) != 3) {
                 // The file is too deep to be the core's index.php
                 continue;
             }
             // This could be a theme file, but we have to examine its info array.
             $Zip->extractTo($FolderPath, $Entry['name']);
             $FilePath = CombinePaths(array($FolderPath, $Name));
             // Get the version number from the core.
             $Version = self::ParseCoreVersion($FilePath);
             if (!$Version) {
                 continue;
             }
             // The application was confirmed.
             $Addon = array('AddonKey' => 'vanilla', 'AddonTypeID' => ADDON_TYPE_CORE, 'Name' => 'Vanilla', 'Description' => 'Vanilla is an open-source, standards-compliant, multi-lingual, fully extensible discussion forum for the web. Anyone who has web-space that meets the requirements can download and use Vanilla for free!', 'Version' => $Version, 'Path' => $Path);
             $Info = array();
             break;
         }
     }
     if ($Addon) {
         // Add the requirements.
         $Requirements = arrayTranslate($Info, array('RequiredApplications' => 'Applications', 'RequiredPlugins' => 'Plugins', 'RequiredThemes' => 'Themes'));
         foreach ($Requirements as $Type => $Items) {
             if (!is_array($Items)) {
                 unset($Requirements[$Type]);
             }
         }
         $Addon['Requirements'] = serialize($Requirements);
         $Addon['Checked'] = true;
         $UploadsPath = PATH_ROOT . '/uploads/';
         if (stringBeginsWith($Addon['Path'], $UploadsPath)) {
             $Addon['File'] = substr($Addon['Path'], strlen($UploadsPath));
         }
         if ($Fix) {
             // Delete extraneous files.
             foreach ($Deletes as $Delete) {
                 $Zip->deleteName($Delete['name']);
             }
         }
     }
     $Zip->close();
     if (file_exists($FolderPath)) {
         Gdn_FileSystem::RemoveFolder($FolderPath);
     }
     if ($Addon) {
         $Addon['MD5'] = md5_file($Path);
         $Addon['FileSize'] = filesize($Path);
         return $Addon;
     } else {
         if ($ThrowError) {
             $Msg = implode("\n", $Result);
             throw new Exception($Msg, 400);
         } else {
             return false;
         }
     }
 }
コード例 #7
0
ファイル: class.usermodel.php プロジェクト: vanilla/vanilla
 /**
  * Send welcome email to user.
  *
  * @param int $UserID
  * @param string $Password
  * @param string $RegisterType
  * @param array|null $AdditionalData
  * @throws Exception
  */
 public function sendWelcomeEmail($UserID, $Password, $RegisterType = 'Add', $AdditionalData = null)
 {
     $Session = Gdn::session();
     $Sender = $this->getID($Session->UserID);
     $User = $this->getID($UserID);
     if (!ValidateEmail($User->Email)) {
         return;
     }
     $AppTitle = Gdn::config('Garden.Title');
     $Email = new Gdn_Email();
     $Email->subject(sprintf(t('[%s] Welcome Aboard!'), $AppTitle));
     $Email->to($User->Email);
     $emailTemplate = $Email->getEmailTemplate();
     $Data = [];
     $Data['User'] = arrayTranslate((array) $User, ['UserID', 'Name', 'Email']);
     $Data['Sender'] = arrayTranslate((array) $Sender, ['Name', 'Email']);
     $Data['Title'] = $AppTitle;
     if (is_array($AdditionalData)) {
         $Data = array_merge($Data, $AdditionalData);
     }
     $Data['EmailKey'] = valr('Attributes.EmailKey', $User);
     $message = '<p>' . formatString(t('Hello {User.Name}!'), $Data) . ' ';
     $message .= $this->getEmailWelcome($RegisterType, $User, $Data, $Password);
     // Add the email confirmation key.
     if ($Data['EmailKey']) {
         $emailUrlFormat = '{/entry/emailconfirm,exurl,domain}/{User.UserID,rawurlencode}/{EmailKey,rawurlencode}';
         $url = formatString($emailUrlFormat, $Data);
         $message .= '<p>' . t('You need to confirm your email address before you can continue.') . '</p>';
         $emailTemplate->setButton($url, t('Confirm My Email Address'));
     } else {
         $emailTemplate->setButton(externalUrl('/'), t('Access the Site'));
     }
     $emailTemplate->setMessage($message);
     $emailTemplate->setTitle(t('Welcome Aboard!'));
     $Email->setEmailTemplate($emailTemplate);
     try {
         $Email->send();
     } catch (Exception $e) {
         if (debug()) {
             throw $e;
         }
     }
 }
コード例 #8
0
 /**
  *
  *
  * @param $Sender
  * @param string $Dir
  */
 public function entryController_twauthorize_create($Sender, $Dir = '')
 {
     $Query = arrayTranslate($Sender->Request->get(), array('display', 'Target'));
     $Query = http_build_query($Query);
     if ($Dir == 'profile') {
         // This is a profile connection.
         $this->redirectUri(self::profileConnecUrl());
     }
     $this->authorize($Query);
 }
コード例 #9
0
 /**
  * Get meta data of a single conversation.
  *
  * @param int $ConversationID Unique ID of conversation.
  * @param string $datasetType The format of the resulting conversation.
  * @param array $options Options to modify the get. Currently supports `viewingUserID`.
  * @return array|stdClass Returns a conversation.
  */
 public function getID($ConversationID, $datasetType = false, $options = [])
 {
     if (is_numeric($datasetType)) {
         deprecated('ConversationModel->getID(int, int)', 'ConversationModel->getID(int, string, array)');
         $viewingUserID = $datasetType;
         $datasetType = false;
     } else {
         $viewingUserID = val('viewingUserID', $options);
     }
     $datasetType = $datasetType ?: DATASET_TYPE_OBJECT;
     // Get the conversation.
     $Conversation = $this->getWhere(array('ConversationID' => $ConversationID))->firstRow(DATASET_TYPE_ARRAY);
     if ($viewingUserID) {
         $Data = $this->SQL->getWhere('UserConversation', array('ConversationID' => $ConversationID, 'UserID' => $viewingUserID))->firstRow(DATASET_TYPE_ARRAY);
         // Convert the array.
         $UserConversation = arrayTranslate($Data, array('LastMessageID', 'CountReadMessages', 'DateLastViewed', 'Bookmarked'));
         $UserConversation['CountNewMessages'] = $Conversation['CountMessages'] - $Data['CountReadMessages'];
     } else {
         $UserConversation = array('CountNewMessages' => 0, 'CountReadMessages' => $Conversation['CountMessages'], 'DateLastViewed' => $Conversation['DateUpdated']);
     }
     $Conversation = array_merge($Conversation, $UserConversation);
     if ($datasetType === DATASET_TYPE_OBJECT) {
         $Conversation = (object) $Conversation;
     }
     return $Conversation;
 }
コード例 #10
0
ファイル: locales.php プロジェクト: caidongyun/vanilla
    echo val('Description', $Info, '');
    ?>
</td>
        </tr>
        <tr class="<?php 
    echo $RowClass;
    ?>
">
            <td class="Info"><?php 
    echo anchor(t($ToggleText), '/settings/locales/' . strtolower($ToggleText) . '/' . urlencode($Key) . '/' . $Session->TransientKey(), $ToggleText . 'Addon SmallButton');
    ?>
</td>
            <td class="Alt Info"><?php 
    $RequiredApplications = val('RequiredApplications', $Info, false);
    $RequiredPlugins = val('RequiredPlugins', $Info, false);
    $InfoItems = arrayTranslate($Info, array('Locale' => t('Locale'), 'Version' => t('Version')));
    $InfoString = ImplodeAssoc(': ', '<span>|</span>', $InfoItems);
    //            if (is_array($RequiredApplications) || is_array($RequiredPlugins)) {
    //               if ($Info != '')
    //                  $Info .= '<span>|</span>';
    //
    //               $Info .= t('Requires: ');
    //            }
    //            $i = 0;
    //            if (is_array($RequiredApplications)) {
    //               if ($i > 0)
    //                  $Info .= ', ';
    //
    //               foreach ($RequiredApplications as $RequiredApplication => $VersionInfo) {
    //                  $Info .= sprintf(t('%1$s Version %2$s'), $RequiredApplication, $VersionInfo);
    //                  ++$i;
コード例 #11
0
ファイル: class.banmodel.php プロジェクト: sitexa/vanilla
 /**
  * Change ban data on a user (ban or unban them).
  *
  * @since 2.0.18
  * @access public
  *
  * @param array $User
  * @param bool $BannedValue Whether user is banned.
  * @param array|false $Ban An array representing the specific auto-ban.
  */
 public function saveUser($User, $BannedValue, $Ban = false)
 {
     $BannedValue = (bool) $BannedValue;
     $Banned = $User['Banned'];
     if (static::isBanned($Banned, self::BAN_AUTOMATIC) === $BannedValue) {
         return;
     }
     $NewBanned = static::setBanned($Banned, $BannedValue, self::BAN_AUTOMATIC);
     Gdn::userModel()->setField($User['UserID'], 'Banned', $NewBanned);
     $BanningUserID = Gdn::session()->UserID;
     // This is true when a session is started and the session user has a new ip address and it matches a banning rule ip address
     if ($User['UserID'] == $BanningUserID) {
         $BanningUserID = val('InsertUserID', $Ban, Gdn::userModel()->GetSystemUserID());
     }
     // Add the activity.
     $ActivityModel = new ActivityModel();
     $Activity = array('ActivityType' => 'Ban', 'ActivityUserID' => $User['UserID'], 'RegardingUserID' => $BanningUserID, 'NotifyUserID' => ActivityModel::NOTIFY_MODS);
     $BannedString = $BannedValue ? 'banned' : 'unbanned';
     if ($Ban) {
         $Activity['HeadlineFormat'] = '{ActivityUserID,user} was ' . $BannedString . ' (based on {Data.BanType}: {Data.BanValue}).';
         $Activity['Data'] = arrayTranslate($Ban, array('BanType', 'BanValue'));
         $Activity['Story'] = $Ban['Notes'];
         $Activity['RecordType'] = 'Ban';
         if (isset($Ban['BanID'])) {
             $Activity['BanID'] = $Ban['BanID'];
         }
     } else {
         $Activity['HeadlineFormat'] = '{ActivityUserID,user} was ' . $BannedString . '.';
     }
     $ActivityModel->save($Activity);
 }
コード例 #12
0
ファイル: class.oauth2.php プロジェクト: vanilla/vanilla
 /**
  *   Allow the admin to input the keys that their service uses to send data.
  *
  * @param array $rawProfile profile as it is returned from the provider.
  *
  * @return array Profile array transformed by child class or as is.
  */
 public function translateProfileResults($rawProfile = [])
 {
     $provider = $this->provider();
     $email = val('ProfileKeyEmail', $provider, 'email');
     $translatedKeys = [val('ProfileKeyEmail', $provider, 'email') => 'Email', val('ProfileKeyPhoto', $provider, 'picture') => 'Photo', val('ProfileKeyName', $provider, 'displayname') => 'Name', val('ProfileKeyFullName', $provider, 'name') => 'FullName', val('ProfileKeyUniqueID', $provider, 'user_id') => 'UniqueID'];
     $profile = arrayTranslate($rawProfile, $translatedKeys, true);
     $profile['Provider'] = $this->providerKey;
     return $profile;
 }
コード例 #13
0
 /**
  *
  *
  * @param null $Schema
  * @throws Exception
  */
 public function initialize($Schema = null)
 {
     if ($Schema !== null) {
         $this->Schema($Schema);
     }
     $Form = $this->Form();
     if ($Form->authenticatedPostBack()) {
         // Grab the data from the form.
         $Data = array();
         $Post = $Form->formValues();
         foreach ($this->_Schema as $Row) {
             $Name = $Row['Name'];
             $Config = $Row['Config'];
             // For API calls make this a sparse save.
             if ($this->Controller()->deliveryType() === DELIVERY_TYPE_DATA && !array_key_exists($Name, $Post)) {
                 continue;
             }
             if (strtolower(val('Control', $Row)) == 'imageupload') {
                 $Form->SaveImage($Name, arrayTranslate($Row, array('Prefix', 'Size')));
             }
             $Value = $Form->getFormValue($Name);
             if ($Value == val('Default', $Value, '')) {
                 $Value = '';
             }
             $Data[$Config] = $Value;
             $this->Controller()->setData($Name, $Value);
         }
         // Save it to the config.
         saveToConfig($Data, array('RemoveEmpty' => true));
         $this->_Sender->informMessage(t('Saved'));
     } else {
         // Load the form data from the config.
         $Data = array();
         foreach ($this->_Schema as $Row) {
             $Data[$Row['Name']] = c($Row['Config'], val('Default', $Row, ''));
         }
         $Form->setData($Data);
         $this->Controller()->Data = $Data;
     }
 }
コード例 #14
0
 /**
  *
  *
  * @param array $Data
  * @param bool $Preference
  * @param array $Options
  * @return array
  * @throws Exception
  */
 public function save($Data, $Preference = false, $Options = array())
 {
     trace('ActivityModel->save()');
     $Activity = $Data;
     $this->_touch($Activity);
     if ($Activity['ActivityUserID'] == $Activity['NotifyUserID'] && !val('Force', $Options)) {
         trace('Skipping activity because it would notify the user of something they did.');
         return;
         // don't notify users of something they did.
     }
     // Check the user's preference.
     if ($Preference) {
         list($Popup, $Email) = self::notificationPreference($Preference, $Activity['NotifyUserID'], 'both');
         if ($Popup && !$Activity['Notified']) {
             $Activity['Notified'] = self::SENT_PENDING;
         }
         if ($Email && !$Activity['Emailed']) {
             $Activity['Emailed'] = self::SENT_PENDING;
         }
         if (!$Activity['Notified'] && !$Activity['Emailed'] && !val('Force', $Options)) {
             trace("Skipping activity because the user has no preference set.");
             return;
         }
     }
     $ActivityType = self::getActivityType($Activity['ActivityType']);
     $ActivityTypeID = val('ActivityTypeID', $ActivityType);
     if (!$ActivityTypeID) {
         trace("There is no {$ActivityType} activity type.", TRACE_WARNING);
         $ActivityType = self::getActivityType('Default');
         $ActivityTypeID = val('ActivityTypeID', $ActivityType);
     }
     $Activity['ActivityTypeID'] = $ActivityTypeID;
     $NotificationInc = 0;
     if ($Activity['NotifyUserID'] > 0 && $Activity['Notified']) {
         $NotificationInc = 1;
     }
     // Check to see if we are sharing this activity with another one.
     if ($CommentActivityID = val('CommentActivityID', $Activity['Data'])) {
         $CommentActivity = $this->getID($CommentActivityID);
         $Activity['Data']['CommentNotifyUserID'] = $CommentActivity['NotifyUserID'];
     }
     // Make sure this activity isn't a duplicate.
     if (val('CheckRecord', $Options)) {
         // Check to see if this record already notified so we don't notify multiple times.
         $Where = arrayTranslate($Activity, array('NotifyUserID', 'RecordType', 'RecordID'));
         $Where['DateUpdated >'] = Gdn_Format::toDateTime(strtotime('-2 days'));
         // index hint
         $CheckActivity = $this->SQL->getWhere('Activity', $Where)->firstRow();
         if ($CheckActivity) {
             return false;
         }
     }
     // Check to share the activity.
     if (val('Share', $Options)) {
         $this->Share($Activity);
     }
     // Group he activity.
     if ($GroupBy = val('GroupBy', $Options)) {
         $GroupBy = (array) $GroupBy;
         $Where = array();
         foreach ($GroupBy as $ColumnName) {
             $Where[$ColumnName] = $Activity[$ColumnName];
         }
         $Where['NotifyUserID'] = $Activity['NotifyUserID'];
         // Make sure to only group activities by day.
         $Where['DateInserted >'] = Gdn_Format::toDateTime(strtotime('-1 day'));
         // See if there is another activity to group these into.
         $GroupActivity = $this->SQL->getWhere('Activity', $Where)->firstRow(DATASET_TYPE_ARRAY);
         if ($GroupActivity) {
             $GroupActivity['Data'] = @unserialize($GroupActivity['Data']);
             $Activity = $this->mergeActivities($GroupActivity, $Activity);
             $NotificationInc = 0;
         }
     }
     $Delete = false;
     if ($Activity['Emailed'] == self::SENT_PENDING) {
         $this->email($Activity);
         $Delete = val('_Delete', $Activity);
     }
     $ActivityData = $Activity['Data'];
     if (isset($Activity['Data']) && is_array($Activity['Data'])) {
         $Activity['Data'] = serialize($Activity['Data']);
     }
     $this->defineSchema();
     $Activity = $this->filterSchema($Activity);
     $ActivityID = val('ActivityID', $Activity);
     if (!$ActivityID) {
         if (!$Delete) {
             $this->addInsertFields($Activity);
             touchValue('DateUpdated', $Activity, $Activity['DateInserted']);
             $this->EventArguments['Activity'] =& $Activity;
             $this->EventArguments['ActivityID'] = null;
             $Handled = false;
             $this->EventArguments['Handled'] =& $Handled;
             $this->fireEvent('BeforeSave');
             if (count($this->validationResults()) > 0) {
                 return false;
             }
             if ($Handled) {
                 // A plugin handled this activity so don't save it.
                 return $Activity;
             }
             if (val('CheckSpam', $Options)) {
                 // Check for spam
                 $Spam = SpamModel::isSpam('Activity', $Activity);
                 if ($Spam) {
                     return SPAM;
                 }
                 // Check for approval
                 $ApprovalRequired = CheckRestriction('Vanilla.Approval.Require');
                 if ($ApprovalRequired && !val('Verified', Gdn::session()->User)) {
                     LogModel::insert('Pending', 'Activity', $Activity);
                     return UNAPPROVED;
                 }
             }
             $ActivityID = $this->SQL->insert('Activity', $Activity);
             $Activity['ActivityID'] = $ActivityID;
         }
     } else {
         $Activity['DateUpdated'] = Gdn_Format::toDateTime();
         unset($Activity['ActivityID']);
         $this->EventArguments['Activity'] =& $Activity;
         $this->EventArguments['ActivityID'] = $ActivityID;
         $this->fireEvent('BeforeSave');
         if (count($this->validationResults()) > 0) {
             return false;
         }
         $this->SQL->put('Activity', $Activity, array('ActivityID' => $ActivityID));
         $Activity['ActivityID'] = $ActivityID;
     }
     $Activity['Data'] = $ActivityData;
     if (isset($CommentActivity)) {
         $CommentActivity['Data']['SharedActivityID'] = $Activity['ActivityID'];
         $CommentActivity['Data']['SharedNotifyUserID'] = $Activity['NotifyUserID'];
         $this->setField($CommentActivity['ActivityID'], 'Data', $CommentActivity['Data']);
     }
     if ($NotificationInc > 0) {
         $CountNotifications = Gdn::userModel()->getID($Activity['NotifyUserID'])->CountNotifications + $NotificationInc;
         Gdn::userModel()->setField($Activity['NotifyUserID'], 'CountNotifications', $CountNotifications);
     }
     // If this is a wall post then we need to notify on that.
     if (val('Name', $ActivityType) == 'WallPost' && $Activity['NotifyUserID'] == self::NOTIFY_PUBLIC) {
         $this->notifyWallPost($Activity);
     }
     return $Activity;
 }
コード例 #15
0
ファイル: class.usermodel.php プロジェクト: bahill/vanilla
 /**
  * Send welcome email to user.
  *
  * @param $UserID
  * @param $Password
  * @param string $RegisterType
  * @param null $AdditionalData
  * @throws Exception
  */
 public function sendWelcomeEmail($UserID, $Password, $RegisterType = 'Add', $AdditionalData = null)
 {
     $Session = Gdn::session();
     $Sender = $this->getID($Session->UserID);
     $User = $this->getID($UserID);
     if (!ValidateEmail($User->Email)) {
         return;
     }
     $AppTitle = Gdn::config('Garden.Title');
     $Email = new Gdn_Email();
     $Email->subject(sprintf(t('[%s] Welcome Aboard!'), $AppTitle));
     $Email->to($User->Email);
     $emailTemplate = $Email->getEmailTemplate();
     $Data = array();
     $Data['User'] = arrayTranslate((array) $User, array('UserID', 'Name', 'Email'));
     $Data['Sender'] = arrayTranslate((array) $Sender, array('Name', 'Email'));
     $Data['Title'] = $AppTitle;
     if (is_array($AdditionalData)) {
         $Data = array_merge($Data, $AdditionalData);
     }
     $Data['EmailKey'] = valr('Attributes.EmailKey', $User);
     $message = '<p>' . formatString(t('Hello {User.Name}!'), $Data) . ' ';
     switch ($RegisterType) {
         case 'Connect':
             $message .= formatString(t('You have successfully connected to {Title}.'), $Data) . ' ' . t('Find your account information below.') . '<br></p>' . '<p>' . sprintf(t('%s: %s'), t('Username'), val('Name', $User)) . '<br>' . formatString(t('Connected With: {ProviderName}'), $Data) . '</p>';
             break;
         case 'Register':
             $message .= formatString(t('You have successfully registered for an account at {Title}.'), $Data) . ' ' . t('Find your account information below.') . '<br></p>' . '<p>' . sprintf(t('%s: %s'), t('Username'), val('Name', $User)) . '<br>' . sprintf(t('%s: %s'), t('Email'), val('Email', $User)) . '</p>';
             break;
         default:
             $message .= sprintf(t('%s has created an account for you at %s.'), val('Name', $Sender), $AppTitle) . ' ' . t('Find your account information below.') . '<br></p>' . '<p>' . sprintf(t('%s: %s'), t('Email'), val('Email', $User)) . '<br>' . sprintf(t('%s: %s'), t('Password'), $Password) . '</p>';
     }
     // Add the email confirmation key.
     if ($Data['EmailKey']) {
         $emailUrlFormat = '{/entry/emailconfirm,exurl,domain}/{User.UserID,rawurlencode}/{EmailKey,rawurlencode}';
         $url = formatString($emailUrlFormat, $Data);
         $message .= '<p>' . t('You need to confirm your email address before you can continue.') . '</p>';
         $emailTemplate->setButton($url, t('Confirm My Email Address'));
     } else {
         $emailTemplate->setButton(externalUrl('/'), t('Access the Site'));
     }
     $emailTemplate->setMessage($message);
     $emailTemplate->setTitle(t('Welcome Aboard!'));
     $Email->setEmailTemplate($emailTemplate);
     $Email->send();
 }
コード例 #16
0
 /**
  * Pre-populate the form with values from the query string.
  *
  * @param Gdn_Form $Form
  * @param bool $LimitCategories Whether to turn off the category dropdown if there is only one category to show.
  */
 protected function populateForm($Form)
 {
     $Get = $this->Request->get();
     $Get = array_change_key_case($Get);
     $Values = arrayTranslate($Get, array('name' => 'Name', 'tags' => 'Tags', 'body' => 'Body'));
     foreach ($Values as $Key => $Value) {
         $Form->setValue($Key, $Value);
     }
     if (isset($Get['category'])) {
         $Category = CategoryModel::categories($Get['category']);
         if ($Category && $Category['PermsDiscussionsAdd']) {
             $Form->setValue('CategoryID', $Category['CategoryID']);
         }
     }
 }
コード例 #17
0
 /**
  * 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();
 }
コード例 #18
0
 /**
  * Render basic data about user.
  *
  * @since 2.0.?
  * @access public
  * @param int $UserID Unique ID.
  */
 public function get($UserID = false)
 {
     if (!$UserID) {
         $UserID = Gdn::session()->UserID;
     }
     if (($UserID != Gdn::session()->UserID || !Gdn::session()->UserID) && !checkPermission('Garden.Users.Edit')) {
         throw new Exception(t('You do not have permission to view other profiles.'), 401);
     }
     $UserModel = new UserModel();
     // Get the user.
     $User = $UserModel->getID($UserID, DATASET_TYPE_ARRAY);
     if (!$User) {
         throw notFoundException('User');
     }
     $PhotoUrl = $User['Photo'];
     if ($PhotoUrl && strpos($PhotoUrl, '//') == false) {
         $PhotoUrl = url('/uploads/' . changeBasename($PhotoUrl, 'n%s'), true);
     }
     $User['Photo'] = $PhotoUrl;
     // Remove unwanted fields.
     $this->Data = arrayTranslate($User, array('UserID', 'Name', 'Email', 'Photo'));
     $this->render();
 }
コード例 #19
0
ファイル: class.usermodel.php プロジェクト: RodSloan/vanilla
 /**
  * Send password email.
  *
  * @param $UserID
  * @param $Password
  * @throws Exception
  */
 public function sendPasswordEmail($UserID, $Password)
 {
     $Session = Gdn::session();
     $Sender = $this->getID($Session->UserID);
     $User = $this->getID($UserID);
     $AppTitle = Gdn::config('Garden.Title');
     $Email = new Gdn_Email();
     $Email->subject(sprintf(t('[%s] Password Reset'), $AppTitle));
     $Email->to($User->Email);
     $Data = array();
     $Data['User'] = arrayTranslate((array) $User, array('Name', 'Email'));
     $Data['Sender'] = arrayTranslate((array) $Sender, array('Name', 'Email'));
     $Data['Title'] = $AppTitle;
     $EmailFormat = t('EmailPassword');
     if (strpos($EmailFormat, '{') !== false) {
         $Message = formatString($EmailFormat, $Data);
     } else {
         $Message = sprintf($EmailFormat, $User->Name, $Sender->Name, $AppTitle, ExternalUrl('/'), $Password, $User->Email);
     }
     $Message = $this->_addEmailHeaderFooter($Message, $Data);
     $Email->message($Message);
     $Email->send();
 }
コード例 #20
0
 /**
  *
  *
  * @param $Search
  * @param int $Offset
  * @param int $Limit
  * @return array|null
  * @throws Exception
  */
 public function search($Search, $Offset = 0, $Limit = 20)
 {
     // If there are no searches then return an empty array.
     if (trim($Search) == '') {
         return array();
     }
     // Figure out the exact search mode.
     if ($this->ForceSearchMode) {
         $SearchMode = $this->ForceSearchMode;
     } else {
         $SearchMode = strtolower(c('Garden.Search.Mode', 'matchboolean'));
     }
     if ($SearchMode == 'matchboolean') {
         if (strpos($Search, '+') !== false || strpos($Search, '-') !== false) {
             $SearchMode = 'boolean';
         } else {
             $SearchMode = 'match';
         }
     } else {
         $this->_SearchMode = $SearchMode;
     }
     if ($ForceDatabaseEngine = c('Database.ForceStorageEngine')) {
         if (strcasecmp($ForceDatabaseEngine, 'myisam') != 0) {
             $SearchMode = 'like';
         }
     }
     if (strlen($Search) <= 4) {
         $SearchMode = 'like';
     }
     $this->_SearchMode = $SearchMode;
     $this->EventArguments['Search'] = $Search;
     $this->fireEvent('Search');
     if (count($this->_SearchSql) == 0) {
         return array();
     }
     // Perform the search by unioning all of the sql together.
     $Sql = $this->SQL->select()->from('_TBL_ s')->orderBy('s.DateInserted', 'desc')->limit($Limit, $Offset)->GetSelect();
     $Sql = str_replace($this->Database->DatabasePrefix . '_TBL_', "(\n" . implode("\nunion all\n", $this->_SearchSql) . "\n)", $Sql);
     $this->fireEvent('AfterBuildSearchQuery');
     if ($this->_SearchMode == 'like') {
         $Search = '%' . $Search . '%';
     }
     foreach ($this->_Parameters as $Key => $Value) {
         $this->_Parameters[$Key] = $Search;
     }
     $Parameters = $this->_Parameters;
     $this->reset();
     $this->SQL->reset();
     $Result = $this->Database->query($Sql, $Parameters)->resultArray();
     foreach ($Result as $Key => $Value) {
         if (isset($Value['Summary'])) {
             $Value['Summary'] = Condense(Gdn_Format::to($Value['Summary'], $Value['Format']));
             $Result[$Key] = $Value;
         }
         switch ($Value['RecordType']) {
             case 'Discussion':
                 $Discussion = arrayTranslate($Value, array('PrimaryID' => 'DiscussionID', 'Title' => 'Name', 'CategoryID'));
                 $Result[$Key]['Url'] = DiscussionUrl($Discussion, 1);
                 break;
         }
     }
     return $Result;
 }
コード例 #21
0
 /**
  * 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);
     // Make sure none of the selected discussions are ghost redirects.
     $discussionTypes = array_column($Discussions, 'Type');
     if (in_array('redirect', $discussionTypes)) {
         throw Gdn_UserException('You cannot merge redirects.', 400);
     }
     // 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 = val('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');
 }
コード例 #22
0
ファイル: class.logmodel.php プロジェクト: sitexa/vanilla
 /**
  * Log an operation into the log table.
  *
  * @param string $Operation The operation being performed. This is usually one of:
  *  - Delete: The record has been deleted.
  *  - Edit: The record has been edited.
  *  - Spam: The record has been marked spam.
  *  - Moderate: The record requires moderation.
  *  - Pending: The record needs pre-moderation.
  * @param string $RecordType The type of record being logged. This usually correspond to the tablename of the record.
  * @param array $Data The record data.
  *  - If you are logging just one row then pass the row as an array.
  *  - You can pass an additional _New element to tell the logger what the new data is.
  * @return int The log id.
  */
 public static function insert($Operation, $RecordType, $Data, $Options = array())
 {
     if ($Operation === false) {
         return;
     }
     // Check to see if we are storing two versions of the data.
     if (($InsertUserID = self::_LogValue($Data, 'Log_InsertUserID')) === null) {
         $InsertUserID = Gdn::session()->UserID;
     }
     if (($InsertIPAddress = self::_LogValue($Data, 'Log_InsertIPAddress')) == null) {
         $InsertIPAddress = Gdn::request()->IPAddress();
     }
     // Do some known translations for the parent record ID.
     if (($ParentRecordID = self::_LogValue($Data, 'ParentRecordID')) === null) {
         switch ($RecordType) {
             case 'Activity':
                 $ParentRecordID = self::_LogValue($Data, 'CommentActivityID', 'CommentActivityID');
                 break;
             case 'Comment':
                 $ParentRecordID = self::_LogValue($Data, 'DiscussionID', 'DiscussionID');
                 break;
         }
     }
     // Get the row information from the data or determine it based on the type.
     $LogRow = array('Operation' => $Operation, 'RecordType' => $RecordType, 'RecordID' => self::_LogValue($Data, 'RecordID', $RecordType . 'ID'), 'RecordUserID' => self::_LogValue($Data, 'RecordUserID', 'UpdateUserID', 'InsertUserID'), 'RecordIPAddress' => self::_LogValue($Data, 'RecordIPAddress', 'LastIPAddress', 'InsertIPAddress'), 'RecordDate' => self::_LogValue($Data, 'RecordDate', 'DateUpdated', 'DateInserted'), 'InsertUserID' => $InsertUserID, 'InsertIPAddress' => $InsertIPAddress, 'DateInserted' => Gdn_Format::toDateTime(), 'ParentRecordID' => $ParentRecordID, 'CategoryID' => self::_LogValue($Data, 'CategoryID'), 'OtherUserIDs' => implode(',', val('OtherUserIDs', $Options, array())), 'Data' => serialize($Data));
     if ($LogRow['RecordDate'] == null) {
         $LogRow['RecordDate'] = Gdn_Format::toDateTime();
     }
     $GroupBy = val('GroupBy', $Options);
     // Make sure we aren't grouping by null values.
     if (is_array($GroupBy)) {
         foreach ($GroupBy as $Name) {
             if (val($Name, $LogRow) === null) {
                 $GroupBy = false;
                 break;
             }
         }
     }
     if ($GroupBy) {
         $GroupBy[] = 'Operation';
         $GroupBy[] = 'RecordType';
         // Check to see if there is a record already logged here.
         $Where = array_combine($GroupBy, arrayTranslate($LogRow, $GroupBy));
         $LogRow2 = Gdn::sql()->getWhere('Log', $Where)->firstRow(DATASET_TYPE_ARRAY);
         if ($LogRow2) {
             $LogID = $LogRow2['LogID'];
             $Set = array();
             $Data = array_merge(unserialize($LogRow2['Data']), $Data);
             $OtherUserIDs = explode(',', $LogRow2['OtherUserIDs']);
             if (!is_array($OtherUserIDs)) {
                 $OtherUserIDs = array();
             }
             if (!$LogRow2['InsertUserID']) {
                 $Set['InsertUserID'] = $InsertUserID;
             } elseif ($InsertUserID != $LogRow2['InsertUserID'] && !in_array($InsertUserID, $OtherUserIDs)) {
                 $OtherUserIDs[] = $InsertUserID;
             }
             if (array_key_exists('OtherUserIDs', $Options)) {
                 $OtherUserIDs = array_merge($OtherUserIDs, $Options['OtherUserIDs']);
                 $OtherUserIDs = array_unique($OtherUserIDs);
                 $OtherUserIDs = array_diff($OtherUserIDs, array($InsertUserID));
                 $Count = count($OtherUserIDs) + 1;
             } else {
                 $Count = (int) $LogRow2['CountGroup'] + 1;
             }
             $Set['OtherUserIDs'] = implode(',', $OtherUserIDs);
             $Set['CountGroup'] = $Count;
             $Set['Data'] = serialize($Data);
             $Set['DateUpdated'] = Gdn_Format::toDateTime();
             if (self::$_TransactionID > 0) {
                 $Set['TransactionLogID'] = self::$_TransactionID;
             } elseif (self::$_TransactionID === true) {
                 if ($LogRow2['TransactionLogID']) {
                     self::$_TransactionID = $LogRow2['TransactionLogID'];
                 } else {
                     self::$_TransactionID = $LogID;
                     $Set['TransactionLogID'] = $LogID;
                 }
             }
             Gdn::sql()->put('Log', $Set, array('LogID' => $LogID));
         } else {
             $L = self::_Instance();
             $L->EventArguments['Log'] =& $LogRow;
             $L->fireEvent('BeforeInsert');
             if (self::$_TransactionID > 0) {
                 $LogRow['TransactionLogID'] = self::$_TransactionID;
             }
             $LogID = Gdn::sql()->insert('Log', $LogRow);
             if (self::$_TransactionID === true) {
                 // A new transaction was started and needs to assigned.
                 self::$_TransactionID = $LogID;
                 Gdn::sql()->put('Log', array('TransactionLogID' => $LogID), array('LogID' => $LogID));
             }
             $L->EventArguments['LogID'] = $LogID;
             $L->fireEvent('AfterInsert');
         }
     } else {
         if (self::$_TransactionID > 0) {
             $LogRow['TransactionLogID'] = self::$_TransactionID;
         }
         // Insert the log entry.
         $L = self::_Instance();
         $L->EventArguments['Log'] =& $LogRow;
         $L->fireEvent('BeforeInsert');
         $LogID = Gdn::sql()->insert('Log', $LogRow);
         if (self::$_TransactionID === true) {
             // A new transaction was started and needs to assigned.
             self::$_TransactionID = $LogID;
             Gdn::sql()->put('Log', array('TransactionLogID' => $LogID), array('LogID' => $LogID));
         }
         $L->EventArguments['LogID'] = $LogID;
         $L->fireEvent('AfterInsert');
     }
     return $LogID;
 }
コード例 #23
0
 /**
  * Inserts or updates the discussion via form values.
  *
  * Events: BeforeSaveDiscussion, AfterSaveDiscussion.
  *
  * @since 2.0.0
  * @access public
  *
  * @param array $FormPostValues Data sent from the form model.
  * @param array $Settings Currently unused.
  * @return int $DiscussionID Unique ID of the discussion.
  */
 public function save($FormPostValues, $Settings = false)
 {
     $Session = Gdn::session();
     // Define the primary key in this model's table.
     $this->defineSchema();
     // Add & apply any extra validation rules:
     $this->Validation->applyRule('Body', 'Required');
     $this->Validation->addRule('MeAction', 'function:ValidateMeAction');
     $this->Validation->applyRule('Body', 'MeAction');
     $MaxCommentLength = Gdn::config('Vanilla.Comment.MaxLength');
     if (is_numeric($MaxCommentLength) && $MaxCommentLength > 0) {
         $this->Validation->SetSchemaProperty('Body', 'Length', $MaxCommentLength);
         $this->Validation->applyRule('Body', 'Length');
     }
     // Validate category permissions.
     $CategoryID = val('CategoryID', $FormPostValues);
     if ($CategoryID > 0) {
         $Category = CategoryModel::categories($CategoryID);
         if ($Category && !$Session->checkPermission('Vanilla.Discussions.Add', true, 'Category', val('PermissionCategoryID', $Category))) {
             $this->Validation->addValidationResult('CategoryID', 'You do not have permission to post in this category');
         }
     }
     // Get the DiscussionID from the form so we know if we are inserting or updating.
     $DiscussionID = val('DiscussionID', $FormPostValues, '');
     // See if there is a source ID.
     if (val('SourceID', $FormPostValues)) {
         $DiscussionID = $this->SQL->getWhere('Discussion', arrayTranslate($FormPostValues, array('Source', 'SourceID')))->value('DiscussionID');
         if ($DiscussionID) {
             $FormPostValues['DiscussionID'] = $DiscussionID;
         }
     } elseif (val('ForeignID', $FormPostValues)) {
         $DiscussionID = $this->SQL->getWhere('Discussion', array('ForeignID' => $FormPostValues['ForeignID']))->value('DiscussionID');
         if ($DiscussionID) {
             $FormPostValues['DiscussionID'] = $DiscussionID;
         }
     }
     $Insert = $DiscussionID == '' ? true : false;
     $this->EventArguments['Insert'] = $Insert;
     if ($Insert) {
         unset($FormPostValues['DiscussionID']);
         // If no categoryid is defined, grab the first available.
         if (!val('CategoryID', $FormPostValues) && !c('Vanilla.Categories.Use')) {
             $FormPostValues['CategoryID'] = val('CategoryID', CategoryModel::defaultCategory(), -1);
         }
         $this->addInsertFields($FormPostValues);
         // The UpdateUserID used to be required. Just add it if it still is.
         if (!$this->Schema->getProperty('UpdateUserID', 'AllowNull', true)) {
             $FormPostValues['UpdateUserID'] = $FormPostValues['InsertUserID'];
         }
         // $FormPostValues['LastCommentUserID'] = $Session->UserID;
         $FormPostValues['DateLastComment'] = $FormPostValues['DateInserted'];
     } else {
         // Add the update fields.
         $this->addUpdateFields($FormPostValues);
     }
     // Set checkbox values to zero if they were unchecked
     if (val('Announce', $FormPostValues, '') === false) {
         $FormPostValues['Announce'] = 0;
     }
     if (val('Closed', $FormPostValues, '') === false) {
         $FormPostValues['Closed'] = 0;
     }
     if (val('Sink', $FormPostValues, '') === false) {
         $FormPostValues['Sink'] = 0;
     }
     //	Prep and fire event
     $this->EventArguments['FormPostValues'] =& $FormPostValues;
     $this->EventArguments['DiscussionID'] = $DiscussionID;
     $this->fireEvent('BeforeSaveDiscussion');
     // Validate the form posted values
     $this->validate($FormPostValues, $Insert);
     $ValidationResults = $this->validationResults();
     // If the body is not required, remove it's validation errors.
     $BodyRequired = c('Vanilla.DiscussionBody.Required', true);
     if (!$BodyRequired && array_key_exists('Body', $ValidationResults)) {
         unset($ValidationResults['Body']);
     }
     if (count($ValidationResults) == 0) {
         // If the post is new and it validates, make sure the user isn't spamming
         if (!$Insert || !$this->checkForSpam('Discussion')) {
             // Get all fields on the form that relate to the schema
             $Fields = $this->Validation->schemaValidationFields();
             // Check for spam.
             $spam = SpamModel::isSpam('Discussion', $Fields);
             if ($spam) {
                 return SPAM;
             }
             // Get DiscussionID if one was sent
             $DiscussionID = intval(val('DiscussionID', $Fields, 0));
             // Remove the primary key from the fields for saving.
             unset($Fields['DiscussionID']);
             $StoredCategoryID = false;
             if ($DiscussionID > 0) {
                 // Updating
                 $Stored = $this->getID($DiscussionID, DATASET_TYPE_OBJECT);
                 // Block Format change if we're forcing the formatter.
                 if (c('Garden.ForceInputFormatter')) {
                     unset($Fields['Format']);
                 }
                 // Clear the cache if necessary.
                 $CacheKeys = array();
                 if (val('Announce', $Stored) != val('Announce', $Fields)) {
                     $CacheKeys[] = $this->getAnnouncementCacheKey();
                     $CacheKeys[] = $this->getAnnouncementCacheKey(val('CategoryID', $Stored));
                 }
                 if (val('CategoryID', $Stored) != val('CategoryID', $Fields)) {
                     $CacheKeys[] = $this->getAnnouncementCacheKey(val('CategoryID', $Fields));
                 }
                 foreach ($CacheKeys as $CacheKey) {
                     Gdn::cache()->remove($CacheKey);
                 }
                 self::serializeRow($Fields);
                 $this->SQL->put($this->Name, $Fields, array($this->PrimaryKey => $DiscussionID));
                 setValue('DiscussionID', $Fields, $DiscussionID);
                 LogModel::logChange('Edit', 'Discussion', (array) $Fields, $Stored);
                 if (val('CategoryID', $Stored) != val('CategoryID', $Fields)) {
                     $StoredCategoryID = val('CategoryID', $Stored);
                 }
             } else {
                 // Inserting.
                 if (!val('Format', $Fields) || c('Garden.ForceInputFormatter')) {
                     $Fields['Format'] = c('Garden.InputFormatter', '');
                 }
                 if (c('Vanilla.QueueNotifications')) {
                     $Fields['Notified'] = ActivityModel::SENT_PENDING;
                 }
                 // Check for approval
                 $ApprovalRequired = checkRestriction('Vanilla.Approval.Require');
                 if ($ApprovalRequired && !val('Verified', Gdn::session()->User)) {
                     LogModel::insert('Pending', 'Discussion', $Fields);
                     return UNAPPROVED;
                 }
                 // Create discussion
                 $this->serializeRow($Fields);
                 $DiscussionID = $this->SQL->insert($this->Name, $Fields);
                 $Fields['DiscussionID'] = $DiscussionID;
                 // Update the cache.
                 if ($DiscussionID && Gdn::cache()->activeEnabled()) {
                     $CategoryCache = array('LastDiscussionID' => $DiscussionID, 'LastCommentID' => null, 'LastTitle' => Gdn_Format::text($Fields['Name']), 'LastUserID' => $Fields['InsertUserID'], 'LastDateInserted' => $Fields['DateInserted'], 'LastUrl' => DiscussionUrl($Fields));
                     CategoryModel::setCache($Fields['CategoryID'], $CategoryCache);
                     // Clear the cache if necessary.
                     if (val('Announce', $Fields)) {
                         Gdn::cache()->remove($this->getAnnouncementCacheKey(val('CategoryID', $Fields)));
                         if (val('Announce', $Fields) == 1) {
                             Gdn::cache()->remove($this->getAnnouncementCacheKey());
                         }
                     }
                 }
                 // Update the user's discussion count.
                 $InsertUser = Gdn::userModel()->getID($Fields['InsertUserID']);
                 $this->updateUserDiscussionCount($Fields['InsertUserID'], val('CountDiscussions', $InsertUser, 0) > 100);
                 // Mark the user as participated.
                 $this->SQL->replace('UserDiscussion', array('Participated' => 1), array('DiscussionID' => $DiscussionID, 'UserID' => val('InsertUserID', $Fields)));
                 // Assign the new DiscussionID to the comment before saving.
                 $FormPostValues['IsNewDiscussion'] = true;
                 $FormPostValues['DiscussionID'] = $DiscussionID;
                 // Do data prep.
                 $DiscussionName = val('Name', $Fields, '');
                 $Story = val('Body', $Fields, '');
                 $NotifiedUsers = array();
                 $UserModel = Gdn::userModel();
                 $ActivityModel = new ActivityModel();
                 if (val('Type', $FormPostValues)) {
                     $Code = 'HeadlineFormat.Discussion.' . $FormPostValues['Type'];
                 } else {
                     $Code = 'HeadlineFormat.Discussion';
                 }
                 $HeadlineFormat = t($Code, '{ActivityUserID,user} started a new discussion: <a href="{Url,html}">{Data.Name,text}</a>');
                 $Category = CategoryModel::categories(val('CategoryID', $Fields));
                 $Activity = array('ActivityType' => 'Discussion', 'ActivityUserID' => $Fields['InsertUserID'], 'HeadlineFormat' => $HeadlineFormat, 'RecordType' => 'Discussion', 'RecordID' => $DiscussionID, 'Route' => DiscussionUrl($Fields), 'Data' => array('Name' => $DiscussionName, 'Category' => val('Name', $Category)));
                 // Allow simple fulltext notifications
                 if (c('Vanilla.Activity.ShowDiscussionBody', false)) {
                     $Activity['Story'] = $Story;
                 }
                 // Notify all of the users that were mentioned in the discussion.
                 $Usernames = getMentions($DiscussionName . ' ' . $Story);
                 // Use our generic Activity for events, not mentions
                 $this->EventArguments['Activity'] = $Activity;
                 // Notify everyone that has advanced notifications.
                 if (!c('Vanilla.QueueNotifications')) {
                     try {
                         $Fields['DiscussionID'] = $DiscussionID;
                         $this->notifyNewDiscussion($Fields, $ActivityModel, $Activity);
                     } catch (Exception $Ex) {
                         throw $Ex;
                     }
                 }
                 // Notifications for mentions
                 foreach ($Usernames as $Username) {
                     $User = $UserModel->getByUsername($Username);
                     if (!$User) {
                         continue;
                     }
                     // Check user can still see the discussion.
                     if (!$this->canView($Fields, $User->UserID)) {
                         continue;
                     }
                     $Activity['HeadlineFormat'] = t('HeadlineFormat.Mention', '{ActivityUserID,user} mentioned you in <a href="{Url,html}">{Data.Name,text}</a>');
                     $Activity['NotifyUserID'] = val('UserID', $User);
                     $ActivityModel->queue($Activity, 'Mention');
                 }
                 // Throw an event for users to add their own events.
                 $this->EventArguments['Discussion'] = $Fields;
                 $this->EventArguments['NotifiedUsers'] = $NotifiedUsers;
                 $this->EventArguments['MentionedUsers'] = $Usernames;
                 $this->EventArguments['ActivityModel'] = $ActivityModel;
                 $this->fireEvent('BeforeNotification');
                 // Send all notifications.
                 $ActivityModel->saveQueue();
             }
             // Get CategoryID of this discussion
             $Discussion = $this->getID($DiscussionID, DATASET_TYPE_OBJECT);
             $CategoryID = val('CategoryID', $Discussion, false);
             // Update discussion counter for affected categories.
             if ($Insert || $StoredCategoryID) {
                 $this->incrementNewDiscussion($Discussion);
             }
             if ($StoredCategoryID) {
                 $this->updateDiscussionCount($StoredCategoryID);
             }
             // Fire an event that the discussion was saved.
             $this->EventArguments['FormPostValues'] = $FormPostValues;
             $this->EventArguments['Fields'] = $Fields;
             $this->EventArguments['DiscussionID'] = $DiscussionID;
             $this->fireEvent('AfterSaveDiscussion');
         }
     }
     return $DiscussionID;
 }
コード例 #24
0
 /**
  * Do code checks on an uploaded addon.
  *
  * @param int $AddonID Addon to check.
  * @param bool|false $SaveVersionID Whether to save the version id.
  * @throws Exception Addon not found.
  */
 public function check($AddonID, $SaveVersionID = false)
 {
     $this->permission('Addons.Addon.Manage');
     if ($SaveVersionID !== false) {
         // Get the version data.
         $Version = $this->AddonModel->SQL->getWhere('AddonVersion', array('AddonVersionID' => $SaveVersionID))->firstRow(DATASET_TYPE_ARRAY);
         $this->AddonModel->save($Version);
         $this->Form->setValidationResults($this->AddonModel->validationResults());
     }
     $Addon = $this->AddonModel->getID($AddonID, false, ['GetVersions' => true]);
     $AddonTypes = Gdn::sql()->get('AddonType')->resultArray();
     $AddonTypes = Gdn_DataSet::index($AddonTypes, 'AddonTypeID');
     if (!$Addon) {
         throw notFoundException('Addon');
     }
     // Get the data for the most recent version of the addon.
     $upload = new Gdn_Upload();
     // Also used per version below.
     $Path = $upload->copyLocal($Addon['File']);
     $AddonData = arrayTranslate((array) $Addon, array('AddonID', 'AddonKey', 'Name', 'Type', 'Description', 'Requirements', 'Checked'));
     try {
         $FileAddonData = UpdateModel::analyzeAddon($Path);
         if ($FileAddonData) {
             $AddonData = array_merge($AddonData, arrayTranslate($FileAddonData, array('AddonKey' => 'File_AddonKey', 'Name' => 'File_Name', 'File_Type', 'Description' => 'File_Description', 'Requirements' => 'File_Requirements', 'Checked' => 'File_Checked')));
             $AddonData['File_Type'] = valr($FileAddonData['AddonTypeID'] . '.Label', $AddonTypes, 'Unknown');
         }
         $upload->delete($Path);
     } catch (Exception $Ex) {
         $AddonData['File_Error'] = $Ex->getMessage();
     }
     $this->setData('Addon', $AddonData);
     // Go through the versions and make sure we get the versions to check out.
     $Versions = array();
     foreach ($Addon['Versions'] as $Version) {
         $Version = $Version;
         $Path = $upload->copyLocal($Version['File']);
         try {
             $VersionData = arrayTranslate((array) $Version, array('AddonVersionID', 'Version', 'AddonKey', 'Name', 'MD5', 'FileSize', 'Checked'));
             $FileVersionData = UpdateModel::analyzeAddon($Path);
             $FileVersionData = arrayTranslate($FileVersionData, array('Version' => 'File_Version', 'AddonKey' => 'File_AddonKey', 'Name' => 'File_Name', 'MD5' => 'File_MD5', 'FileSize' => 'File_FileSize', 'Checked' => 'File_Checked'));
             $upload->delete($Path);
         } catch (Exception $Ex) {
             $FileVersionData = array('File_Error' => $Ex->getMessage());
         }
         $Versions[] = array_merge($VersionData, $FileVersionData);
     }
     $this->setData('Versions', $Versions);
     $this->addModule('AddonHelpModule');
     $this->render();
 }
コード例 #25
0
 /**
  *
  *
  * @throws Exception
  * @throws Gdn_UserException
  */
 public function save()
 {
     $this->permission('Garden.Users.Edit');
     if (!Gdn::request()->isAuthenticatedPostBack()) {
         throw new Exception('Requires POST', 405);
     }
     $Form = new Gdn_Form();
     if ($SSOString = $Form->getFormValue('SSOString')) {
         $Parts = explode(' ', $SSOString);
         $String = $Parts[0];
         $Data = json_decode(base64_decode($String), true);
         $User = arrayTranslate($Data, array('name' => 'Name', 'email' => 'Email', 'photourl' => 'Photo', 'client_id' => 'ClientID', 'uniqueid' => 'UniqueID'));
     } else {
         $User = $Form->formValues();
     }
     if (!isset($User['UserID']) && isset($User['UniqueID'])) {
         // Try and find the user based on SSO.
         $Auth = Gdn::userModel()->getAuthentication($User['UniqueID'], $User['ClientID']);
         if ($Auth) {
             $User['UserID'] = $Auth['UserID'];
         }
     }
     if (!isset($User['UserID'])) {
         // Add some default values to make saving easier.
         if (!isset($User['RoleID'])) {
             $DefaultRoles = RoleModel::getDefaultRoles(RoleModel::TYPE_MEMBER);
             $User['RoleID'] = $DefaultRoles;
         } elseif (is_numeric($User['RoleID'])) {
             // UserModel->save() demands an array for RoleID.
             $User['RoleID'] = array($User['RoleID']);
         }
         if (!isset($User['Password'])) {
             $User['Password'] = md5(microtime());
             $User['HashMethod'] = 'Random';
         }
     }
     $UserID = Gdn::userModel()->save($User, array('SaveRoles' => isset($User['RoleID']), 'NoConfirmEmail' => true));
     if ($UserID) {
         if (!isset($User['UserID'])) {
             $User['UserID'] = $UserID;
         }
         if (isset($User['ClientID']) && isset($User['UniqueID'])) {
             Gdn::userModel()->saveAuthentication(array('UserID' => $User['UserID'], 'Provider' => $User['ClientID'], 'UniqueID' => $User['UniqueID']));
         }
         $this->setData('User', $User);
     } else {
         throw new Gdn_UserException(Gdn::userModel()->Validation->resultsText());
     }
     $this->render('Blank', 'Utility');
 }
コード例 #26
0
 /**
  * Get meta data of a single conversation.
  *
  * @since 2.0.0
  * @access public
  *
  * @param int $ConversationID Unique ID of conversation.
  * @param int $ViewingUserID Unique ID of current user.
  * @return Gdn_DataSet SQL result (single row).
  */
 public function getID($ConversationID, $ViewingUserID = false)
 {
     // Get the conversation.
     $Conversation = $this->getWhere(array('ConversationID' => $ConversationID))->firstRow(DATASET_TYPE_ARRAY);
     if ($ViewingUserID) {
         $Data = $this->SQL->getWhere('UserConversation', array('ConversationID' => $ConversationID, 'UserID' => $ViewingUserID))->firstRow(DATASET_TYPE_ARRAY);
         // Convert the array.
         $UserConversation = arrayTranslate($Data, array('LastMessageID', 'CountReadMessages', 'DateLastViewed', 'Bookmarked'));
         $UserConversation['CountNewMessages'] = $Conversation['CountMessages'] - $Data['CountReadMessages'];
     } else {
         $UserConversation = array('CountNewMessages' => 0, 'CountReadMessages' => $Conversation['CountMessages'], 'DateLastViewed' => $Conversation['DateUpdated']);
     }
     $Conversation = array_merge($Conversation, $UserConversation);
     return (object) $Conversation;
 }