/pivotx_2.2.5-sqlite/pivotx/objects.php
PHP | 2403 lines | 1863 code | 240 blank | 300 comment | 124 complexity | ea19077f3dfc4f78f132908cecf41260 MD5 | raw file
Possible License(s): AGPL-1.0, LGPL-2.1, BSD-3-Clause
- <?php
- // ---------------------------------------------------------------------------
- //
- // PIVOTX - LICENSE:
- //
- // This file is part of PivotX. PivotX and all its parts are licensed under
- // the GPL version 2. see: http://docs.pivotx.net/doku.php?id=help_about_gpl
- // for more information.
- //
- // $Id: objects.php 3501 2011-02-11 08:48:13Z hansfn $
- //
- // ---------------------------------------------------------------------------
- /**
- * Takes care of all configuration settings. The configuration is stored in
- * pivotx/db/ser_config.php, but is completely accessible through this object.
- * Saving is automagical and only when something has changed.
- *
- */
- class Config {
- var $configfile;
- function Config($sites_path = '') {
- $this->configfile = dirname(__FILE__) . '/' . $sites_path . 'db/ser_config.php';
- $this->data = loadSerialize($this->configfile, true);
- if (count($this->data)<5) {
- // hmm, couldn't find the data.. Perhaps try to import it from old Pivot 1.x
- $this->readOld();
- $this->save();
- }
- $this->checkConfig();
- }
- /**
- * Check if all required fields in the config are set. If not, we add them.
- *
- */
- function checkConfig() {
- $mustsave = false;
- $default = getDefaultConfig();
- foreach($default as $key=>$value) {
- if (!isset($this->data[$key])) {
- $this->data[$key] = $value;
- $mustsave = true;
- }
- }
- // Seperate check for 'server_spam_key' since it is different for all PivotX install
- if (!isset($this->data['server_spam_key']) || empty($this->data['server_spam_key'])) {
- $server_spam_key = '';
- $possible_server_keys = array('SERVER_SIGNATURE','SERVER_ADDR','PHP_SELF','DOCUMENT_ROOT');
- foreach ($possible_server_keys as $key) {
- if (isset($_SERVER[$key])) {
- $server_spam_key .= $_SERVER[$key];
- }
- }
- $server_spam_key .= time();
- $this->data['server_spam_key'] = md5($server_spam_key);
- $mustsave = true;
- }
- if ($mustsave) {
- $this->save();
- }
- // If there's a file called 'pivotxdebugmode.txt', we'll enable debugging
- if (file_exists(dirname(__FILE__)."/pivotxdebugmode.txt")) {
- $this->data['debug'] = 1;
- }
- }
- /**
- * If the config file is missing, we check if there's a pivot 1.x config
- * file that we can use. This function does some comversions to get it up
- * to date, and sets it in $this->data
- *
- */
- function readOld() {
- global $pivotx_path;
- // If the old config file doesn't exist or it isn't readable, we return false..
- if (!file_exists($pivotx_path.'pv_cfg_settings.php') || (!is_readable($pivotx_path.'pv_cfg_settings.php'))) {
- return false;
- }
- // get the config file
- $fh = file($pivotx_path.'pv_cfg_settings.php');
- foreach ($fh as $fh_this) {
- @list($name, $val) = explode("!", $fh_this);
- $Cfg[trim($name)] = trim($val);
- }
- //GetUserInfo();
- //ExpandSessions();
- @$Cfg['ping_urls']=str_replace("|", "\n", $Cfg['ping_urls']);
- @$Cfg['default_introduction']=str_replace("|", "\n", $Cfg['default_introduction']);
- if (!isset($Cfg['selfreg'])) { $Cfg['selfreg']= 0; }
- if (!isset($Cfg['xmlrpc'])) { $Cfg['xmlrpc']= 0; }
- if (!isset($Cfg['hashcash'])) { $Cfg['hashcash']= 0; }
- if (!isset($Cfg['spamquiz'])) { $Cfg['spamquiz']= 0; }
- if (!isset($Cfg['hardened_trackback'])) { $Cfg['hardened_trackback']= 0; }
- if (!isset($Cfg['moderate_comments'])) { $Cfg['moderate_comments']= 0; }
- if (!isset($Cfg['lastcomm_amount_max'])) { $Cfg['lastcomm_amount_max'] = 60; }
- if (!isset($Cfg['tag_cache_timeout'])) { $Cfg['tag_cache_timeout'] = 60; }
- if (!isset($Cfg['tag_flickr_enabled'])) { $Cfg['tag_flickr_enabled'] = 1; }
- if (!isset($Cfg['tag_flickr_amount'])) { $Cfg['tag_flickr_amount'] = 6; }
- if (!isset($Cfg['tag_fetcher_enabled'])) { $Cfg['tag_fetcher_enabled'] = 1; }
- if (!isset($Cfg['tag_fetcher_amount'])) { $Cfg['tag_fetcher_amount'] = 10; }
- if (!isset($Cfg['tag_min_font'])) { $Cfg['tag_min_font'] = 9; }
- if (!isset($Cfg['tag_max_font'])) { $Cfg['tag_max_font'] = 42; }
- if(!isset($Cfg['server_spam_key'])) {
- $key = $_SERVER['SERVER_SIGNATURE'].$_SERVER['SERVER_ADDR'].$_SERVER['SCRIPT_URI'].$_SERVER['DOCUMENT_ROOT'].time();
- $Cfg['server_spam_key'] = md5($key);
- }
- // Remove stuff we don't need:
- unset($Cfg['session_length']);
- unset($Cfg['sessions']);
- unset($Cfg['users']);
- unset($Cfg['userfields']);
- unset($Cfg['<?php']);
- unset($Cfg['?>']);
- foreach ($Cfg as $key => $val) {
- if ( (strpos($key,'uf-')===0) || (strpos($key,'user-')===0) ) {
- unset($Cfg[$key]);
- }
- }
- $this->data = $Cfg;
- }
- /**
- * Save the config to disk.
- *
- */
- function save() {
- if (is_array($this->data)) {
- ksort($this->data);
- }
- saveSerialize($this->configfile, $this->data);
- }
- /**
- * Return the entire config as a big array.. It's probable better to use
- * $PIVOTX['config']->get() if you only need one or few items.
- *
- * @see $this->get
- * @return array
- */
- function getConfigArray() {
- return $this->data;
- }
- /**
- * Sets a configuration value, and then saves it.
- *
- * @param string $key
- * @param unknown_type $value
- */
- function set($key, $value) {
- // Empty checkboxes are passed by jQuery as string 'undefined', but we want to store them as integer '0'
- if ($value==="undefined") { $value=0; }
- // Offline configuration is not saved in the normal configuration file
- if (substr($key,0,8) == 'offline_') {
- PivotxOffline::setConfig(substr($key,8),$value);
- return;
- }
- // Only set (and save) if the value has actually changed.
- if (empty($this->data[safeString($key)]) || $value !== $this->data[safeString($key)] ) {
- $this->data[safeString($key)] = $value;
- $this->save();
-
- }
- }
- /**
- * Delete a configuration value. Use with extreme caution. Saves the
- * configuration afterwards
- *
- * @param string $key
- */
- function del($key) {
- // Old pre PivotX 2.0 configuration didn't use safe_string
- // on the key - we are handling it here.
- if (isset($this->data[safeString($key)])) {
- unset($this->data[safeString($key)]);
- } else {
- unset($this->data[$key]);
- }
- $this->save();
- }
- /**
- * Gets a single value from the configuration.
- *
- * @param string $key
- * @return string
- */
- function get($key) {
- if (isset($this->data[$key])) {
- return $this->data[$key];
- } else {
- return false;
- }
- }
- }
- /**
- * Since PHP4 doesn't allow class constants, we define the userlevels as
- * global constants.
- */
- define("PIVOTX_UL_NOBODY", -1);
- define("PIVOTX_UL_MOBLOGGER", 0);
- define("PIVOTX_UL_NORMAL", 1);
- define("PIVOTX_UL_ADVANCED", 2);
- define("PIVOTX_UL_ADMIN", 3);
- define("PIVOTX_UL_SUPERADMIN", 4);
- /**
- * Portable PHP password hashing framework (phpass) for PivotX:
- *
- * The framework can be completely disabled by setting "disable_phpass" to 1
- * in the advanced configuration. This is not recommended. If it is disabled,
- * a salted md5 sum is used for password hashing.
- *
- * 1) The standard log2 number of iterations for password stretching. This
- * should be increased from time to time to counteract increases in the speed
- * and power of computers available to crack the hashes. However, since the
- * current hashing algorithms aren't capable of running in parallell in PHP,
- * it shouldn't be increased too often. (It should never exceed 31.)
- */
- define('PIVOTX_PASSWORD_HASH_COUNT', 9);
- /**
- * 2) By default, portable hashes are used for maximum portability. Portable
- * hashes can be disabled by setting "password_non_portable_hashes"
- * to 1 in the advanced configuration. Non-portable hashes are more secure,
- * but can be a problem on shared hosting or if you need to move your site
- * between different servers.
- */
- define('PIVOTX_PASSWORD_PORTABLE_HASHES', true);
- /**
- * This Class handles all operations with regard to users: adding, deleting,
- * getting info, etc.
- *
- */
- class Users {
- /**
- * Initialisation
- *
- */
- function Users() {
- global $PIVOTX;
- $this->data = loadSerialize($PIVOTX['paths']['db_path'] . "ser_users.php", true);
- if ($this->count()<1) {
- // hmm, couldn't find the data.. Perhaps try to import it from old Pivot 1.x
- $this->readOld();
- $this->save();
- }
- // Make sure the users are sorted as intended.
- uasort($this->data, array($this, 'sort'));
- }
- function readOld() {
- global $pivotx_path;
- // If the old config file doesn't exist or it isn't readable, we return false..
- if (!file_exists($pivotx_path.'pv_cfg_settings.php') || (!is_readable($pivotx_path.'pv_cfg_settings.php'))) {
- return false;
- }
- // get the config file
- $fh = file($pivotx_path.'pv_cfg_settings.php');
- foreach ($fh as $fh_this) {
- @list($name, $val) = explode("!", $fh_this);
- $Cfg[trim($name)] = trim($val);
- }
- if(isset($Cfg['users'])) {
- foreach(explode('|', trim($Cfg['users'])) as $inc => $user){
- $userdata = array();
- $userdata['username'] = $user;
- foreach(explode('|-|' , $Cfg['user-' . $user]) as $var => $val){
- list($Nvar, $Nval) = explode('|', $val);
- if ($Nvar == 'nick') {
- $userdata['nickname'] = $Nval;
- } elseif ($Nvar == 'pass') {
- $userdata['md5_pass'] = $Nval;
- } else {
- $userdata[$Nvar] = $Nval;
- }
- }
- list($userdata['language']) = explode("_",$userdata['language']);
- $this->addUser($userdata);
- }
- }
- }
- /**
- * Get the count of users
- *
- * @return int
- */
- function count() {
- return ( is_array($this->data) && count($this->data) );
- }
- /**
- * Print a comprehensible representation of the users
- *
- */
- function print_r() {
- echo "<pre>\n";
- print_r($this->data);
- echo "</pre>\n";
- }
- /**
- * Add a user to Pivot
- *
- * @param array $user
- */
- function addUser($user) {
- global $PIVOTX;
- // Make sure the username is OK..
- $user['username'] = strtolower(safeString($user['username']));
- if ($this->getUser($user['username'])!==false) {
- // this username is already taken..
- return false;
- }
- $newuser = array(
- 'username' => $user['username'],
- 'email' => $user['email'],
- 'userlevel' => $user['userlevel'],
- 'nickname' => $user['nickname'],
- 'language' => $user['language'],
- 'image' => $user['image'],
- 'text_processing' => $user['text_processing']
- );
- if (!isset($user['pass1']) && isset($user['md5_pass'])) {
- // User comes from old (1.x) config so we don't have the clear text password.
- $newuser['password'] = $user['md5_pass'];
- $newuser['salt'] = '';
- } else {
- $newuser = $this->hashPassword($newuser, $user['pass1']);
- }
- $this->data[] = $newuser;
- $this->save();
- }
- function deleteUser($username) {
- foreach($this->data as $key=>$user) {
- if ($username == $user['username']) {
- unset($this->data[$key]);
- }
- }
- $this->save();
- }
- /**
- * Update a given property of a user
- *
- * @param string $username
- * @param array $properties
- * @see $this->save
- */
- function updateUser($username, $properties) {
- // Select the correct user
- foreach ($this->data as $key=>$user) {
- if ($username == $user['username']) {
- // Set the properties
- foreach($properties as $property => $value) {
- switch ($property) {
- case "email":
- case "nickname":
- case "language":
- case "text_processing":
- case "lastseen":
- case "userlevel":
- case "image":
- $this->data[$key][$property] = $value;
- break;
- case "reset_id":
- if ($value!="") {
- $this->data[$key][$property] = $value;
- } else {
- unset($this->data[$key][$property]);
- }
- break;
- case "pass1":
- if ( ($value!="") && ($value!="******")) {
- $this->data[$key] = $this->hashPassword($user, $value);
- }
- default:
- break;
- }
- }
- }
- }
- $this->save();
- }
- /**
- * Saves the Users to the filesystem.
- *
- */
- function save() {
- global $PIVOTX;
- // Make sure the users are sorted as intended.
- uasort($this->data, array($this, 'sort'));
- saveSerialize($PIVOTX['paths']['db_path'] . "ser_users.php", $this->data);
- }
- /**
- * Check if a given password matches the one stored.
- *
- * @param string $username
- * @param string $password
- * @return boolean
- */
- function checkPassword($username, $password) {
- global $PIVOTX;
- foreach($this->data as $user) {
- if ($username==$user['username']) {
- if ($user['salt'] == 'phpass') {
- require_once($PIVOTX['paths']['pivotx_path'] . 'includes/PasswordHash.php');
- // We don't really need to set portability correctly when checking
- // the password (since the hashing method is stored in the hash),
- // but it's clearer to use the same code everywhere.
- if ($PIVOTX['config']->get('password_non_portable_hashes')) {
- $portable = false;
- } else {
- $portable = PIVOTX_PASSWORD_PORTABLE_HASHES;
- }
- $phpass = new PasswordHash(PIVOTX_PASSWORD_HASH_COUNT, $portable);
- return $phpass->CheckPassword($password, $user['password']);
- } else {
- if (md5($password . $user['salt']) == $user['password']) {
- return true;
- }
- }
- break;
- }
- }
- return false;
- }
- /**
- * Hash a given password (for a given user).
- *
- * @param array $user
- * @param string $password
- * @return boolean
- */
- function hashPassword($user, $password) {
- global $PIVOTX;
- if (!$PIVOTX['config']->get('disable_phpass')) {
- require_once($PIVOTX['paths']['pivotx_path'] . 'includes/PasswordHash.php');
- if ($PIVOTX['config']->get('password_non_portable_hashes')) {
- $portable = false;
- } else {
- $portable = PIVOTX_PASSWORD_PORTABLE_HASHES;
- }
- $phpass = new PasswordHash(PIVOTX_PASSWORD_HASH_COUNT, $portable);
- $user['salt'] = 'phpass';
- $user['password'] = $phpass->HashPassword($password);
- } else {
- $user['salt'] = md5(rand(1,999999) . mktime());
- $user['password'] = md5( $password . $user['salt']);
- }
- return $user;
- }
- /**
- * Check if a given $username is a user.
- *
- * @param string $name
- * @return boolean
- */
- function isUser($username) {
- if ($this->getUser($username) === false) {
- return false;
- } else {
- return true;
- }
- }
- /**
- * Get the specifics for a given user by its username.
- *
- * @param string $username
- * @return array
- */
- function getUser($username) {
- foreach($this->data as $user) {
- if ( ($username==$user['username']) ) {
- return $user;
- }
- }
- return false;
- }
- /**
- * Get the specifics for a given user by its nickname.
- *
- * @param string $username
- * @return array
- */
- function getUserByNickname($username) {
- foreach($this->data as $user) {
- if ( strtolower($username) == strtolower($user['nickname']) ) {
- return $user;
- }
- }
- return false;
- }
- /**
- * Get a list of the Usernames
- *
- * @return array
- */
- function getUsernames() {
- $res = array();
- foreach($this->data as $user) {
- $res[]=$user['username'];
- }
- return $res;
- }
- /**
- * Get a list of the Users Nicknames
- *
- * @return array
- */
- function getUserNicknames() {
- $res = array();
- foreach($this->data as $user) {
- $res[ $user['username'] ] = $user['nickname'];
- }
- return $res;
- }
- /**
- * Get a list of the Users Email adresses
- *
- * @return array
- */
- function getUserEmail() {
- $res = array();
- foreach($this->data as $user) {
- $res[ $user['username'] ] = $user['email'];
- }
- return $res;
- }
- /**
- * Get all users as an array
- *
- * @return array
- */
- function getUsers() {
- return $this->data;
- }
-
-
- /**
- * Determines if $currentuser (or 'the current user', if left empty) is allowed
- * to edit a page or entry that's owned by $contentowner.
- *
- * @param string $contentowner
- * @param string $currentuser
- * @return boolean
- */
- function allowEdit($contenttype, $contentowner="", $currentuser="") {
- global $PIVOTX;
- // Default to the current logged in user.
- if (empty($currentuser)) {
- $currentuser = $PIVOTX['session']->currentUsername();
- }
- // Fetch the current user..
- $currentuser = $PIVOTX['users']->getUser( $currentuser );
- $currentuserlevel = (!$currentuser?PIVOTX_UL_NOBODY:$currentuser['userlevel']);
-
- // Always allow editing for superadmins - no matter content type.
- if ($currentuserlevel==PIVOTX_UL_SUPERADMIN) {
- return true;
- }
- // Fetch the owner..
- $contentowner = $PIVOTX['users']->getUser( $contentowner );
- $contentownerlevel = (!$contentowner?PIVOTX_UL_NOBODY:$contentowner['userlevel']);
- // Now run the checks for different content types
- if ($contenttype == 'chapter') {
- // Only sdministrator and superadmins can add, edit and delete chapters.
- if ($currentuserlevel>=PIVOTX_UL_ADMIN) {
- return true;
- }
- } else if (($contenttype == 'entry') || ($contenttype == 'page')) {
- // Get the value (if any) of allow_edit_for_own_userlevel setting
- $allowsamelevel = getDefault( $PIVOTX['config']->get('allow_edit_for_own_userlevel'), PIVOTX_UL_SUPERADMIN);
- if ($contentowner['username']==$currentuser['username']) {
- // Always allow editing of your own content..
- return true;
- } else if ($currentuserlevel > $contentownerlevel) {
- // Allow editing content for items owned by lower levels.
- return true;
- } else if ( ($currentuserlevel == $contentownerlevel) && ( $currentuserlevel >= $allowsamelevel) ) {
- // Allow if userlevel is the same, and greater than or equal to $allowsamelevel
- return true;
- }
- } else if (($contenttype == 'comment') || ($contenttype == 'trackback')) {
- if ($contentowner['username']==$currentuser['username']) {
- // Always allow editing of comments/trackback on your own entries.
- return true;
- } else if ($currentuserlevel >= PIVOTX_UL_ADVANCED) {
- return true;
- }
- } else {
- debug('Unknown content type');
- }
- // Disallow editing
- return false;
-
- }
-
- /**
- * Sort the users based on string comparison of username.
- *
- * @param array $a
- * @param array $b
- * @return int
- */
- function sort($a, $b) {
- global $PIVOTX;
- return strcmp($a['username'],$b['username']);
- }
- }
- /**
- * This class deals with the Weblogs.
- *
- */
- class Weblogs {
- var $default;
- var $current;
- /**
- * Initialisation
- *
- * @return Weblogs
- */
- function Weblogs() {
- global $PIVOTX;
- $this->data = loadSerialize($PIVOTX['paths']['db_path'] . "ser_weblogs.php", true);
- if ($this->count()<1) {
- // hmm, couldn't find the data.. Perhaps try to import it from old Pivot 1.x
- $this->readOld();
- $this->save();
- }
- if ($this->count()<1) {
- // No weblogs, create one from scratch
- $this->add('weblog', __('My weblog'), 'pivotxdefault');
- }
- foreach ($this->data as $key => $weblog) {
-
- // Unset '$subkey' weblog -> compensates for an old bug
- if (!empty($this->data[$key]['sub_weblog']['$subkey'])) {
- unset($this->data[$key]['sub_weblog']['$subkey']);
- }
-
- // Make sure all categories are arrays.
- foreach ($weblog['sub_weblog'] as $subkey => $subweblog) {
- if (!is_array($subweblog['categories'])) {
- $this->data[$key]['sub_weblog'][$subkey]['categories'] = array($subweblog['categories']);
- }
- }
-
- // Set the correct link to the weblog.
- if (empty($this->data[$key]['site_url'])) {
- $this->data[$key]['site_url'] = "";
- }
- $this->data[$key]['link'] = $this->_getLink($key, $this->data[$key]['site_url']);
-
- // Set the 'categories' for the combined subweblogs..
- $this->data[$key]['categories'] = $this->getCategories($key);
- }
- // Make sure the weblogs are sorted as intended.
- uasort($this->data, array($this, 'sort'));
- // Set default weblog either as specified by the root in the config
- // or just by selecting the first in the weblo
- list($type, $root) = explode(":", $PIVOTX['config']->get('root'));
- if ($type=="w" && !empty($root) && isset($this->data[$root]) ) {
- $this->default = $root;
- } else {
- // Nothing to do but fall back to the first available weblog..
- reset($this->data);
- $this->default = key($this->data);
- }
- }
- /**
- * Return all weblogs as an array
- *
- * @return array
- */
- function getWeblogs() {
- return $this->data;
- }
- /**
- * Returns an array with the weblog names.
- *
- * @return array
- */
- function getWeblogNames() {
- $names = array();
- foreach($this->data as $name=>$data) {
- $names[] = $name;
- }
- return $names;
- }
- /**
- * Check if a given $name is a weblog.
- *
- * @param string $name
- * @return boolean
- */
- function isWeblog($weblogname) {
- foreach ($this->data as $name=>$data) {
- if ($weblogname==$name) { return true; }
- }
- return false;
- }
- /**
- * Return the weblogs that have the given category or categories assigned
- * to them.
- *
- * @param array $categories
- */
- function getWeblogsWithCat($categories) {
- // $cats might be a string with one cat, if so, convert to array
- if (is_string($categories)) {
- $categories= array($categories);
- }
- $res=array();
- // search every weblog for all cats
- foreach ($this->data as $key => $weblog) {
- $weblogcategories = $this->getCategories($key);
- foreach ($categories as $cat) {
- if (in_array($cat, $weblogcategories)) {
- $res[]=$key;
- }
- }
- }
- return array_unique($res);
- }
- /**
- * Get the categories from a certain weblog.
- *
- * @param string $weblogname
- * @return array
- */
- function getCategories($weblogname='') {
- // if no weblogname was given, use the 'current'..
- if (empty($weblogname)) { $weblogname = $this->getCurrent(); }
- $results = array();
- // Group the categories from the subweblogs together..
- foreach ($this->data[$weblogname]['sub_weblog'] as $key=>$sub) {
- $cats = $sub['categories'];
- // $cats might be a string with one cat, if so, convert to array
- if (is_string($cats)) {
- $cats= array($cats);
- }
- // Add them to results
- foreach($cats as $cat) {
- $results[] = $cat;
- }
- }
- return array_unique($results);
- }
- /**
- * Returns the given weblog as an array. If no weblogname was given, use
- * the current weblog.
- *
- * @param string $weblogname
- * @return array
- */
- function getWeblog($weblogname='') {
- // if no weblogname was given, use the 'current'..
- if (empty($weblogname)) { $weblogname = $this->getCurrent(); }
- return $this->data[$weblogname];
- }
- /**
- * Return a subweblog as an array
- *
- * @param string $weblogname
- * @return array
- */
- function getSubweblog($weblogname='', $subweblogname) {
- // if no weblogname was given, use the 'current'..
- if (empty($weblogname)) { $weblogname = $this->getCurrent(); }
- return $this->data[$weblogname]['sub_weblog'][$subweblogname];
- }
- /**
- * Return the subweblogs of a given weblog as an array. It does this
- * by grabbing all [[weblog]] and [[ subweblog ]] tags from the templates
- * in the same folder as the template that was selected as the frontpage
- * template. Updates the subweblog info in the weblogs object.
- *
- * @param string $weblogname
- * @return array
- */
- function getSubweblogs($weblogname='') {
- global $PIVOTX;
- // if no weblogname was given, use the 'current'..
- if (empty($weblogname)) {
- $weblogname = $this->getCurrent();
- }
- $results = array();
- $weblog = $this->getWeblog($weblogname);
- $dirname = dirname($weblog['front_template']);
- if ( !is_dir($PIVOTX['paths']['templates_path'] . $dirname) || !is_readable($PIVOTX['paths']['templates_path'] . $dirname) ) {
- debug("Template folder $dirname doesn't exist or isn't readable");
- return array();
- }
- $dir = dir($PIVOTX['paths']['templates_path'] . $dirname);
- // Iterate through the files in the folder..
- while (false !== ($filename = $dir->read())) {
- $ext = getExtension($filename);
- if (in_array($ext, array('html', 'htm', 'tpl'))) {
- $template_html = loadTemplate($dirname . "/" . $filename);
- preg_match_all("/\[\[\s?(sub)?weblog([: ])(.*)?\]\]/mUi", $template_html, $matches);
- foreach($matches[3] as $key=>$match) {
- // if $matches[2][$key] was a ':', we know it's an old pivot 1.x style [[ subweblog:name ]]
- // We also must handle optional arguments to the subweblog.
- if ($matches[2][$key]==":") {
- $name = explode(':',$match);
- $results[] = trim($name[0]);
- } else {
- preg_match("/name=['\"]([^'\"]*)/mi", $match, $name);
- if ($name[1]!="") {
- $results[] = $name[1];
- }
- }
- }
- }
- }
- $dir->close();
- $results = array_unique($results);
- // Remove any subweblogs that no longer exists from the weblog data.
- $updated = false;
- foreach ($this->data[$weblogname]['sub_weblog'] as $name => $value) {
- if (!in_array($name,$results)) {
- unset($this->data[$weblogname]['sub_weblog'][$name]);
- $updated = true;
- }
- }
- if ($updated) {
- $this->save();
- }
- return $results;
- }
- /**
- * Sets a given weblog as 'current' and returns false if the weblog
- * doesn't exist.
- *
- * @param string $weblogname
- * @return boolean
- */
- function setCurrent($weblogname='') {
- global $PIVOTX;
-
- $exists = true;
- if ( !isset($this->data[$weblogname]) ) {
- $exists = false;
- $weblogname = '';
- }
- if (empty($weblogname)) {
- $this->current = $this->default;
- } else {
- $this->current = $weblogname;
- }
- return $exists;
- }
- /**
- * Sets a given weblog as 'current' based on a given category and returns false
- * if no matching weblog could be set.
- *
- * @param string $weblogname
- * @return boolean
- */
- function setCurrentFromCategory($categories) {
- // $cats might be a string with concatenated categories..
- if (strpos($categories, ",") > 0 ) {
- $categories = explode(",", $categories);
- $categories = array_map('trim', $categories);
- }
-
- // $cats might be a string with one cat, if so, convert to array
- if (is_string($categories)) {
- $categories= array($categories);
- }
- // Check categories in current weblog first (if set) and then the
- // default weblog
- if (!empty($this->current)) {
- $weblogcategories = $this->data[$this->current]['categories'];
- foreach ($categories as $cat) {
- if (in_array($cat, $weblogcategories)) {
- return true;
- }
- }
- } else {
- $weblogcategories = $this->data[$this->default]['categories'];
- foreach ($categories as $cat) {
- if (in_array($cat, $weblogcategories)) {
- $this->setCurrent($this->default);
- return true;
- }
- }
- }
- $skip_weblogs = array($this->current, $this->default);
- // search every weblog for all cats
- foreach ($this->data as $key => $weblog) {
- // Skip current and default since we checked them above
- if (in_array($key, $skip_weblogs)) {
- continue;
- }
- $weblogcategories = $this->getCategories($key);
- foreach ($categories as $cat) {
- if (in_array($cat, $weblogcategories)) {
- $this->setCurrent($key);
- return true;
- }
- }
- }
- return false;
-
- }
- /**
- * Gets the currently active weblog.
- *
- * @return
- */
- function getCurrent() {
- // Set the current weblog, just to be sure.
- if (empty($this->current)) { $this->setCurrent(""); }
- return $this->current;
- }
- /**
- * Gets the default weblog.
- *
- * @return
- */
- function getDefault() {
- return $this->default;
- }
- /**
- * Add a new weblog, based on $theme. returns the internal name used for
- * the weblog.
- *
- * @param string $internal
- * @param string $name
- * @param string $theme
- * @return string
- */
- function add($internal, $name, $theme) {
- if ( ($internal=="") || isset($this->data[$internal])) {
- // Make a new 'name'..
- for($i=1;$i<1000;$i++) {
- if (!isset($this->data[$internal . "_" . $i])) {
- $internal = $internal . "_" . $i;
- break;
- }
- }
- }
- if ($theme=="blank") {
- $this->data[$internal]['name']=$name;
- $this->save();
- } else if ($theme=="pivotxdefault") {
- $weblog = getDefaultWeblog();
- $weblog['name'] = $name;
- if (empty($weblog['sortorder'])) { $weblog['sortorder'] = 10; }
- $this->data[$internal] = $weblog;
- $this->save();
- } else {
- $weblog = loadSerialize($theme, true);
- $weblog['name'] = $name;
- if (empty($weblog['sortorder'])) { $weblog['sortorder'] = 10; }
- $this->data[$internal] = $weblog;
- $this->save();
- }
- return $internal;
- }
- /**
- * Delete a weblog
- *
- * @param string $weblogname
- */
- function delete($weblogname) {
- unset($this->data[$weblogname]);
- $this->save();
- }
- /**
- * Export a weblog as a theme file. The file is saved in the same folder as
- * the weblog's frontpage template.
- *
- * @param string $weblogname
- */
- function export($weblogname) {
- $weblog = $this->data[$weblogname];
- $filename = dirname("./templates/".$weblog['front_template'])."/".$weblogname.".theme";
- saveSerialize($filename, $weblog);
- }
- /**
- * Read old weblogs data..
- */
- function readOld() {
- $oldweblogs = loadSerialize(dirname(__FILE__)."/pv_cfg_weblogs.php", true);
- // Looping over old weblogs. For each old weblog, add a new one with
- // defaults values and then override the ones already set in the
- // old config. This way we remove settings no longer present in
- // PivotX. We also make sure the categories are all 'safe strings'..
- if(is_array($oldweblogs)) {
- foreach($oldweblogs as $weblogkey => $weblog) {
- $newweblogkey = safeString($weblogkey,true);
- $this->add($newweblogkey, $oldweblogs[$weblogkey]['name'], 'pivotxdefault');
- foreach ($this->data[$newweblogkey] as $key => $value) {
- if (isset($weblog[$key])) {
- $this->data[$newweblogkey][$key] = $weblog[$key];
- }
- }
- foreach($this->data[$newweblogkey]['sub_weblog'] as $subweblogkey => $subweblog) {
- foreach($subweblog['categories'] as $categorykey => $category) {
- $this->data[$newweblogkey]['sub_weblog'][$subweblogkey]['categories'][$categorykey] =
- safeString($category, true);
- }
- }
- foreach($this->data[$newweblogkey]['categories'] as $categorykey => $category) {
- $this->data[$newweblogkey]['categories'][$categorykey] = safeString($category, true);
- }
- }
- }
- }
- /**
- * Get the count of weblogs
- *
- * @return int
- */
- function count() {
- return ( is_array($this->data) && count($this->data) );
- }
- /**
- * Sets a property of a given weblog
- *
- * @param string $weblogname
- * @param string $key
- * @param string $value
- */
- function set($weblogname, $key, $value) {
- if (isset($this->data[$weblogname])) {
- if (strpos($key, "#")>0) {
- // we're setting something in a subweblog
- // we get these as linkdump#categories = linkdump,books,movies
- list($sub, $key) = explode("#", str_replace("[]", "", $key));
- if (strpos($value, ",")>0) {
- $value = explode(",", $value);
- }
- $this->data[$weblogname]['sub_weblog'][$sub][$key] = $value;
-
- // we must update the list of categories for the weblog
- $categories = array();
- foreach ($this->data[$weblogname]['sub_weblog'] as $subweblog) {
- $categories = array_merge($categories,$subweblog['categories']);
- }
- $this->data[$weblogname]['categories'] = array_unique($categories);
- } else {
- if ($key == 'site_url') {
- $this->data[$weblogname]['link'] = $this->_getLink($weblogname, $value);
- }
- $this->data[$weblogname][$key] = $value;
- }
- $this->save();
- } else {
- debug('tried to set a setting without passing a weblogname, or non-existing weblog');
- }
- }
- /**
- * Gets a property of a given weblog
- *
- * @param string $weblogname
- * @param string $key
- */
- function get($weblogname, $key) {
- if ($weblogname=="") {
- $weblogname = $this->getCurrent();
- }
- if (empty($this->data[$weblogname])) {
- debug("Weblog '$weblogname' doesn't exist!");
- $weblogname = key($this->data);
- }
- return $this->data[$weblogname][$key];
- }
- /**
- * Calculates the link for a given weblog
- *
- * @param string $value
- * @param string $weblogname
- */
- function _getLink($weblogname, $value) {
- global $PIVOTX;
-
- $link = trim($value);
- if ($link == '') {
- if ($PIVOTX['config']->get('mod_rewrite')==0) {
- $link = $PIVOTX['paths']['site_url'] . '?w=' . $weblogname;
- } else {
- $prefix = getDefault( $PIVOTX['config']->get('localised_weblog_prefix'), "weblog");
- $link = $PIVOTX['paths']['site_url'] . $prefix . "/" . $weblogname;
- }
- } else {
- $ext = getExtension(basename($link));
- if ($ext == '') {
- $link = addTrailingSlash($link);
- }
- }
- return $link;
- }
- /**
- * Save the weblogs to disk
- *
- */
- function save() {
- global $PIVOTX;
- saveSerialize($PIVOTX['paths']['db_path'] . "ser_weblogs.php", $this->data);
- }
- /**
- * Sort the weblogs based on string comparison of name.
- *
- * @param array $a
- * @param array $b
- * @return int
- */
- function sort($a, $b) {
- global $PIVOTX;
- if ( (empty($a['sortorder']) && empty($b['sortorder'])) || ($a['sortorder'] == $b['sortorder']) ) {
- return strcmp($a['name'],$b['name']);
- } else {
- return ($a['sortorder'] < $b['sortorder']) ? -1 : 1;
- }
- }
- }
- /**
- * This class deals with the categories
- *
- */
- class Categories {
- /**
- * Initialisation
- *
- * @return Categories
- */
- function Categories() {
- global $PIVOTX;
- $this->data = loadSerialize($PIVOTX['paths']['db_path']."ser_categories.php", true);
- if ($this->count()<1) {
- // hmm, couldn't find the data.. Perhaps try to import it from old Pivot 1.x
- $this->readOld();
- $this->saveCategories();
- }
- if ($this->count()<1) {
- // if there still are no categories, load the defaults
- $this->data = getDefaultCategories();
- $this->saveCategories();
- }
- // Make sure the categories are sorted as intended.
- usort($this->data, array($this, 'sort'));
- }
- /**
- * Get the count of categories
- *
- * @return int
- */
- function count() {
- return ( is_array($this->data) && count($this->data) );
- }
- function readOld() {
- global $pivotx_path;
- // If the old config file doesn't exist or it isn't readable, we return false..
- if (!file_exists($pivotx_path.'pv_cfg_settings.php') || (!is_readable($pivotx_path.'pv_cfg_settings.php'))) {
- return false;
- }
- // get the config file
- $fh = file($pivotx_path.'pv_cfg_settings.php');
- foreach ($fh as $fh_this) {
- @list($name, $val) = explode("!", $fh_this);
- $Cfg[trim($name)] = trim($val);
- }
- //GetUserInfo();
- //ExpandSessions();
- $catnames = explode("|",$Cfg['cats']);
- // Check which categories are "hidden"..
- if (isset($Cfg['cats-searchexclusion'])) {
- $hiddenarray = explode('|', strtolower($Cfg['cats-searchexclusion']));
- } else {
- $hiddenarray = array();
- }
- // Check the category order..
- if (isset($Cfg['cats-order'])) {
- $temp = explode('|-|', strtolower($Cfg['cats-order']));
- foreach($temp as $item) {
- list($catname, $order) = explode("|", $item);
- $orderarray[strtolower($catname)] = $order;
- }
- } else {
- $orderarray = array();
- }
- $cats = array();
- foreach ($catnames as $cat) {
- // Skip empty category names.
- $catname = trim($cat);
- if ($catname == '') {
- continue;
- }
-
- $catname = strtolower($catname);
- if (isset($Cfg['cat-'.$cat])) {
- $users = explode('|', strtolower($Cfg['cat-'.$cat]));
- } else {
- $users = array();
- }
- // Make sure the users are 'safe strings'
- foreach($users as $key=>$user) {
- $users[$key] = safeString($user, true);
- }
- $cats[] = array (
- 'name' => safeString($catname, true),
- 'display' => $cat,
- 'users' => $users,
- 'hidden' => (in_array($catname, $hiddenarray)) ? 1 : 0,
- 'order' => (isset($orderarray[$catname])) ? $orderarray[$catname] : 110,
- );
- }
- $this->data = $cats;
- }
- /**
- * change the settings for an existing category, or modify an existing one.
- *
- * @param string $name
- * @param array $cat
- */
- function setCategory($name, $cat) {
- $name = strtolower(safeString($name));
- $cat['name'] = strtolower(safeString($cat['name']));
- foreach($this->data as $key=>$val) {
- if ($name==$val['name']) {
- $this->data[$key] = $cat;
- $this->saveCategories();
- return;
- }
- }
- // Otherwise it must be a new one, let's add it:
- if(!empty($cat['name'])){
- $this->data[] = $cat;
- $this->saveCategories();
- }
- }
- /**
- * Save the categories to disk
- *
- */
- function saveCategories() {
- global $PIVOTX;
- // If $this->data is empty, make it an empty array.
- if (empty($this->data)) {
- $this->data = array();
- }
- usort($this->data, array($this, 'sort'));
- saveSerialize($PIVOTX['paths']['db_path'] . "ser_categories.php", $this->data);
- }
- /**
- * Get an array with all the categories. We filter the users to make sure we only
- * return users that still exist
- *
- * @return array
- */
- function getCategories() {
- global $PIVOTX;
- $results = $this->data;
-
- $users = $PIVOTX['users']->getUsernames();
-
- // Filter only existing users..
- foreach ($results as $key=>$value) {
- // Categories doesn't have to be assigned to any users.
- if (isset($results[$key]['users']) && is_array($results[$key]['users'])) {
- $results[$key]['users'] = array_intersect($results[$key]['users'], $users);
- } else {
- $results[$key]['users'] = array();
- }
- }
- return $results;
- }
-
-
- /**
- * Get a list of categories the user is allowed to post into
- */
- function allowedCategories($username) {
- $allowed = array();
- foreach($this->data as $cat) {
- if (in_array($username, $cat['users'])) {
- $allowed[$cat['name']] = $cat['name'];
- }
- }
- return $allowed;
- }
- /**
- * Allow a user to post in this category
- *
- * @param string $catname
- * @param string $username
- */
- function allowUser($catname, $username) {
- // Loop through all available categories
- foreach($this->data as $key=>$cat) {
- if ($cat['name']==$catname) {
- // Add the username
- $this->data[$key]['users'][] = $username;
- // But remove duplicates
- $this->data[$key]['users'] = array_unique($this->data[$key]['users']);
- }
- }
- }
- /**
- * Disallow a user to post in this category
- *
- * @param string $catname
- * @param string $username
- */
- function disallowUser($catname, $username) {
- // Loop through all available categories
- foreach($this->data as $key=>$cat) {
- if ($cat['name']==$catname) {
- // Loop through the users, and remove $username if present.
- foreach($cat['users'] as $userkey=>$catuser){
- if ($catuser==$username) {
- unset($this->data[$key]['users'][$userkey]);
- }
- }
- }
- }
- }
- /**
- * Get a single category
- *
- * @param string $name
- * @return array
- */
- function getCategory($name) {
- foreach($this->data as $key=>$cat) {
- if ($cat['name']==$name) {
- return $cat;
- }
- }
- return array();
- }
- /**
- * Get a list of all category names
- *
- * @return array
- */
- function getCategorynames() {
- $names = array();
- foreach($this->data as $cat) {
- $names[]=$cat['name'];
- }
- return $names;
- }
- /**
- * Check if a given $name is a category.
- *
- * @param string $name
- * @return boolean
- */
- function isCategory($name) {
- foreach($this->data as $cat) {
- if($name==$cat['name']) { return true; }
- }
- return false;
- }
- /**
- * Get a list of all category names in which we should NOT search
- *
- * @return array
- */
- function getSearchCategorynames() {
- $names = array();
- foreach($this->data as $cat) {
- if ($cat['hidden']!=1) {
- $names[]=$cat['name'];
- }
- }
- return $names;
- }
- /**
- * Delete a single category
- *
- * @param string $name
- */
- function deleteCategory($name) {
- global $PIVOTX;
- foreach($this->data as $key=>$cat) {
- if ($cat['name']==$name) {
- unset($this->data[$key]);
- $this->saveCategories();
- break;
- }
- }
-
- // Remove it from all weblogs as well.
- $weblogs = $PIVOTX['weblogs']->getWeblogs();
- foreach($weblogs as $weblogkey=>$weblog) {
- foreach($weblog['sub_weblog'] as $subweblogkey=>$subweblog) {
- foreach($subweblog['categories'] as $catkey => $cat) {
- if ($cat==$name) {
- unset($weblogs[$weblogkey]['sub_weblog'][$subweblogkey]['categories'][$catkey]);
- }
- }
-
- }
- foreach($weblogs[$weblogkey]['categories'] as $catkey => $cat) {
- if ($cat==$name) {
- unset($weblogs[$weblogkey]['categories'][$catkey]);
- }
- }
- }
-
- $PIVOTX['weblogs']->data = $weblogs;
- $PIVOTX['weblogs']->save();
- }
- /**
- * Sort the categories based on the order and string comparison
- * of display name if order is identical.
- *
- * @param array $a
- * @param array $b
- * @return int
- */
- function sort($a, $b) {
- global $PIVOTX;
- if ($PIVOTX['config']->get('sort_categories_by_alphabet')==true) {
- // If we set 'sort_categories_by_alphabet' to true, always sort by alphabet..
- return strcmp($a['display'],$b['display']);
- } else if ($a['order'] == $b['order']) {
- // Else sort by alphabet, if order is the same..
- return strcmp($a['display'],$b['display']);
- } else {
- // else sort by order..
- return ($a['order'] < $b['order']) ? -1 : 1;
- }
- }
- }
- /**
- * This class deals with Sessions: logging in, logging out, saving sessions
- * and performing checks for required userlevels.
- *
- * This class protects the cookie/session against standard XSS attacks and
- * sidejacking.
- *
- */
- class Session {
- var $permsessions, $logins, $maxlogins, $message;
- /**
- * Initialisation
- *
- * @return Session
- */
- function Session() {
- global $PIVOTX;
- $this->cookie_lifespan = 60*60*24*30; // 30 days
- $this->cookie_name = "pivotxsession";
- $this->maxlogins = getDefault($PIVOTX['config']->get('loginlog_length'), 200);
- if (intval($this->maxlogins) < 10) {
- $this->maxlogins = 200;
- }
- // Select the secure bit for the session cookie. Setting it to true if
- // using HTTPS which stops sidejacking / session hijacking.
- // If we're on regular HTTP, $_SERVER['HTTPS'] will be 'empty' on Apache
- // servers, and have a value of 'off' on IIS servers.
- if (empty($_SERVER['HTTPS']) || strtolower($_SERVER['HTTPS'])=="off" ) {
- $this->cookie_secure = false;
- } else {
- $this->cookie_secure = true;
- }
-
- // Force cookie to be "HTTP only" to make cookie stealing harder - stops
- // standard XSS attacks. (Introduced in PHP 5.2.0.)
- if (checkVersion(phpversion(), '5.2.0')) {
- $this->cookie_httponly = true;
- } else {
- $this->cookie_httponly = false;
- }
- // On second thought, our CSRF check (that uses the double cookie submit
- // test) needs to access the cookie ... We just can't use "HTTP only".
- $this->cookie_httponly = false;
- // Set to 'site url' instead of 'pivotx_url', because then we
- // can use 'edit this entry' and the like.
- $this->cookie_path = $PIVOTX['paths']['site_url'];
- // Don't set the domain for a cookie on a "TLD" - like localhost ...
- if (strpos($_SERVER["SERVER_NAME"], ".") > 0) {
- if (preg_match("/^www./",$_SERVER["SERVER_NAME"])) {
- $this->cookie_domain = "." . preg_replace("/^www./", "", $_SERVER["SERVER_NAME"]);
- } else {
- $this->cookie_domain = $_SERVER["SERVER_NAME"];
- }
- } else {
- $this->cookie_domain = "";
- }
- // Only set "HTTP only" if supported
- if ($this->cookie_httponly) {
- session_set_cookie_params($this->cookie_lifespan,
- $this->cookie_path, $this->cookie_domain, $this->cookie_secure, $this->cookie_httponly);
- } else {
- session_set_cookie_params($this->cookie_lifespan,
- $this->cookie_path, $this->cookie_domain, $this->cookie_secure);
- }
- session_start();
- }
- /**
- * Sets a cookie taking into account the path, domain, secure connection
- * and if "HTTP only" is supported. Basically a wrapper around setcookie.
- *
- * @param string $name
- * @param string $value
- * @param string $time
- */
- function setCookie($name, $value, $time='') {
- if ($time == '') {
- $time = time() + $this->cookie_lifespan;
- }
- if ($this->cookie_httponly) {
- $res = setcookie($name, $value, $time, $this->cookie_path,
- $this->cookie_domain, $this->cookie_secure, $this->cookie_httponly );
- } else {
- $res = setcookie($name, $value, $time, $this->cookie_path,
- $this->cookie_domain, $this->cookie_secure );
- }
-
- // Add some debug output, if we couldn't set the cookie.
- if ($res==false) {
- debug("Couldn't set cookies! (probably because output has already started)");
- if (headers_sent($filename, $linenum)) {
- debug("Headers already sent in $filename on line $linenum");
- } else {
- debug("Headers have not been sent yet. Something's wonky.");
- }
- }
-
- }
- /**
- * Verify if whomever requested the current page is logged in as a user,
- * or else attempt to (transparently) continue from a saved session.
- *
- * @return boolean
- */
- function isLoggedIn() {
- global $PIVOTX;
-
- $this->loadPermsessions();
- $sessioncookie = (!empty($_COOKIE['pivotxsession'])) ? $_COOKIE['pivotxsession'] : $_POST['pivotxsession'];
- if (isset($_SESSION['user']) && isset($_SESSION['user']['username']) && ($_SESSION['user']['username']!="") ) {
- // User is logged in!
-
- // Check if we're in the saved sessions..
- if (!empty($sessioncookie) && !isset($this->permsessions[$sessioncookie])) {
-
- $this->permsessions[ $sessioncookie ] = array(
- 'username' => $_SESSION['user']['username'],
- 'ip' => $_SERVER['REMOTE_ADDR'],
- 'lastseen' => time()
- );
- $this->savePermsessions();
- }
-
- return true;
- } else {
- // See if we can continue a stored session..
- // Check if we have a pivotxsession cookie that matches a saved session..
- if ( (!empty($sessioncookie)) && (isset($this->permsessions[$sessioncookie])) ) {
- $savedsess = $this->permsessions[ $sessioncookie ];
-
- // Check if the IP in the saved session matches the IP of the user..
- if ($_SERVER['REMOTE_ADDR'] == $savedsess['ip']) {
- // Check if the 'lastseen' wasn't too long ago..
- if (time() < ($savedsess['lastseen'] + $this->cookie_lifespan) ) {
- // Finally check if the user in the stored session still exists.
- if (!$PIVOTX['users']->isUser($savedsess['username'])) {
- return false;
- }
- // If we get here, we can restore the session!
- $_SESSION['user']= $PIVOTX['users']->getUser($savedsess['username']);
- // Update the 'lastseen' in permanent sessions.
- $this->permsessions[ $sessioncookie ]['lastseen'] = time();
- $this->savePermsessions();
- // Add the 'lastseen' to the user settings.
- $PIVOTX['users']->updateUser($savedsess['username'], array('lastseen'=>time()) );
- $_SESSION['user']['lastseen'] = time();
- // Set the session cookie as session variable.
- $_SESSION['pivotxsession'] = $sessioncookie;
- return true;
- }
- }
- }
- return false;
- }
- }
- /**
- * Attempt to log in a user, using the passed credentials. If succesfull,
- * the session info is updated and 'true' is returned. When unsuccesful
- * the session remains unaltered, and false is returned
- *
- *
- * @param string $username
- * @param string $password
- * @param int $stay
- * @return boolean
- */
- function login($username, $password, $stay) {
- global $PIVOTX;
- $this->loadLogins();
- if (!$this->checkFailedLogins()) {
- debug(sprintf(__("Blocked login attempt from '%s'."), $_SERVER['REMOTE_ADDR']));
- $this->message = __('Too many failed login attempts from this IP address. ' .
- 'Please contact your site administrator to unblock your account.');
- return false;
- }
- $username = strtolower($username);
- $match = $PIVOTX['users']->checkPassword($username, $password);
- if (!$match) {
- $this->message = __('Incorrect username/password');
- $this->logFailedLogin();
- return false;
- } else {
- $this->message = __('Successfully logged in');
- $key = makeKey(16);
- $_SESSION['pivotxsession'] = $key;
- // Add the 'lastseen' to the user settings and remove and reset_ids.
- $PIVOTX['users']->updateUser($username, array('lastseen'=>time(), 'reset_id'=>'') );
- // Keep track of people logging in (and remove any failed logins
- // for IP if any).
- $this->logins['succeeded'][] = array(
- 'username' => $username,
- 'time' => time(),
- 'ip' => $_SERVER['REMOTE_ADDR']
- );
- unset($this->logins['failed'][$_SERVER['REMOTE_ADDR']]);
- $this->saveLogins();
- $_SESSION['user']= $PIVOTX['users']->getUser($username);
- $path = $PIVOTX['paths']['site_url']; // Set to 'site url' instead of 'pivotx_url', because then we
- // can use 'edit this entry' and the like.
- if ($stay==1) {
- $this->setCookie($this->cookie_name, $key);
- } else {
- $this->setCookie($this->cookie_name, $key, 0);
- }
- $this->permsessions[ $key ] = array(
- 'username' => $username,
- 'ip' => $_SERVER['REMOTE_ADDR'],
- 'lastseen' => time()
- );
- $this->savePermsessions();
- return true;
- }
- }
- /**
- * Logs failed login attempts so PivotX can block brute force attacks.
- *
- */
- function logFailedLogin() {
- global $PIVOTX;
- $ip = $_SERVER['REMOTE_ADDR'];
-
- $this->logins['failed'][ $ip ] = array(
- 'attempts' => $this->logins['failed'][ $ip ]['attempts'] + 1,
- 'time' => mktime()
- );
-
- $this->saveLogins();
- debug(sprintf(__("Failed login attempt from '%s'."), $_SERVER['REMOTE_ADDR']));
- }
- /**
- * Checks failed login attempts so PivotX can block brute force attacks.
- *
- */
- function checkFailedLogins() {
- global $PIVOTX;
-
- $limit = getDefault($PIVOTX['config']->get('failed_logins_limit'), 8);
- $ip = $_SERVER['REMOTE_ADDR'];
-
- if ($this->logins['failed'][ $ip ]['attempts'] > $limit) {
- return false;
- } else {
- return true;
- }
- }
- /**
- * Log out a user: clear the session, and delete the cookie
- *
- */
- function logout() {
- global $PIVOTX;
- $this->loadPermsessions();
- // remove current session (by username, so if the user logs out on
- // one location, he logs out everywhere)..
- foreach ($this->permsessions as $key => $session) {
- if ($session['username']==$_SESSION['user']['username']) {
- unset($this->permsessions[$key]);
- }
- }
- $PIVOTX['events']->add('logout');
- $this->savePermsessions();
- // End the session..
- unset($_SESSION['user']);
- $this->setCookie($this->cookie_name, '', time()-10000 );
- session_destroy();
- }
- /**
- * Returns the latest/current message.
- *
- * @return array
- */
- function getMessage() {
- return $this->message;
- }
- /**
- * Returns the current user.
- *
- * @return array
- */
- function currentUser() {
- return $_SESSION['user'];
- }
- /**
- * Sets the specifics for the current user..
- *
- * @param array $user
- */
- function setUser($user) {
- $_SESSION['user'] = $user;
- }
- /**
- * Returns the username of the current user.
- *
- * @return array
- */
- function currentUsername() {
- return $_SESSION['user']['username'];
- }
- /**
- * Checks if the currently logged in user has at least the required level
- * to view the page he/she is trying to access.
- *
- * If not, the user is logged out of the system.
- *
- * @param int $level
- */
- function minLevel($level) {
- $this->isLoggedIn();
- if ($level>$_SESSION['user']['userlevel']) {
- debug("logged out because the user's level was too low, or not logged in at all");
- pageLogout();
- die();
- }
- }
- /**
- * Checks if the current request is accompanied by the correct
- * CSRF check.
- *
- * If not, the user is logged out of the system.
- *
- * @param int $value
- */
- function checkCSRF($value) {
- if ($value != $_SESSION['pivotxsession']) {
- debug( sprintf("CSRF check failed: '%s..' vs. '%s..'",
- substr($value,0,8), substr($_SESSION['pivotxsession'],0,8) ));
- pageLogout();
- die();
- }
- }
- /**
- * Get the key to use in the CSRF checks.
- *
- */
- function getCSRF() {
- return $_SESSION['pivotxsession'];
- }
- /**
- * Save permanent sessions to the filesystem, for users that check 'keep
- * me logged in'.
- *
- * The sessions are saved in db/ser_sessions.php, and they look somewhat like
- * Array
- * (
- * [8nkvr62i3s37] => Array
- * (
- * [username] => admin
- * [ip] => 127.0.0.1
- * [lastseen] => 1168177821
- * )
- * )
- *
- */
- function savePermsessions() {
- global $PIVOTX;
- saveSerialize($PIVOTX['paths']['db_path'] . "ser_sessions.php", $this->permsessions);
- }
- /**
- * Load the permanent sessions from the filesystem.
- *
- */
- function loadPermsessions() {
- global $PIVOTX;
- $this->permsessions = loadSerialize($PIVOTX['paths']['db_path'] . "ser_sessions.php", true);
- // Remove stale sessions after loading.
- foreach ($this->permsessions as $key=>$session) {
- if(($session['lastseen']+ $this->cookie_lifespan) < time() ) {
- unset($this->permsessions[$key]);
- }
- }
- }
- /**
- * Save login attempts from the filesystem.
- */
- function saveLogins() {
- global $PIVOTX;
- // Trim the logins log, if it's too long.
- if (count($this->logins['failed']) > $this->maxlogins) {
- $this->logins['failed'] = array_slice($this->logins['failed'], -$this->maxlogins);
- }
- if (count($this->logins['succeeded']) > $this->maxlogins) {
- $this->logins['succeeded'] = array_slice($this->logins['succeeded'], -$this->maxlogins);
- }
- saveSerialize($PIVOTX['paths']['db_path'] . "ser_logins.php", $this->logins);
- }
- /**
- * Load stored login attempts from the filesystem.
- */
- function loadLogins() {
- global $PIVOTX;
- $timeout = getDefault($PIVOTX['config']->get('failed_logins_timeout'), 24);
-
- $this->logins = loadSerialize($PIVOTX['paths']['db_path'] . "ser_logins.php", true);
- // Set timeout to the timestamp at which the block needs to be dropped.
- $timeout = mktime() - ($timeout*3600);
- // Iterate over the failed attempts, to see if they need to be dropped.
- foreach ($this->logins['failed'] as $ip => $item) {
- if ($item['time']<$timeout) {
- unset($this->logins['failed'][$ip]);
- }
- }
- }
- /**
- * Sets a session value, and then saves it.
- *
- * @param string $key
- * @param unknown_type $value
- */
- function setValue($key, $value=false) {
- if($value) {
- $_SESSION[$key] = $value;
- } else {
- unset($_SESSION[$key]);
-
- }
- }
- /**
- * Gets a single session value
- *
- * @param string $key
- *