diff options
Diffstat (limited to 'classes')
-rw-r--r-- | classes/Consumer.php | 30 | ||||
-rw-r--r-- | classes/File.php | 17 | ||||
-rw-r--r-- | classes/Memcached_DataObject.php | 53 | ||||
-rw-r--r-- | classes/Notice.php | 35 | ||||
-rw-r--r-- | classes/Oauth_application.php | 17 | ||||
-rw-r--r-- | classes/Profile_role.php | 1 | ||||
-rw-r--r-- | classes/Session.php | 43 | ||||
-rw-r--r-- | classes/User.php | 204 | ||||
-rw-r--r-- | classes/status_network.ini | 1 | ||||
-rw-r--r-- | classes/statusnet.ini | 3 |
10 files changed, 305 insertions, 99 deletions
diff --git a/classes/Consumer.php b/classes/Consumer.php index ad64a8491..ce399f278 100644 --- a/classes/Consumer.php +++ b/classes/Consumer.php @@ -36,4 +36,34 @@ class Consumer extends Memcached_DataObject return $cons; } + /** + * Delete a Consumer and related tokens and nonces + * + * XXX: Should this happen in an OAuthDataStore instead? + * + */ + function delete() + { + // XXX: Is there any reason NOT to do this kind of cleanup? + + $this->_deleteTokens(); + $this->_deleteNonces(); + + parent::delete(); + } + + function _deleteTokens() + { + $token = new Token(); + $token->consumer_key = $this->consumer_key; + $token->delete(); + } + + function _deleteNonces() + { + $nonce = new Nonce(); + $nonce->consumer_key = $this->consumer_key; + $nonce->delete(); + } + } diff --git a/classes/File.php b/classes/File.php index 34e4632a8..307fdb686 100644 --- a/classes/File.php +++ b/classes/File.php @@ -176,8 +176,22 @@ class File extends Memcached_DataObject return "$nickname-$datestamp-$random.$ext"; } + /** + * Validation for as-saved base filenames + */ + static function validFilename($filename) + { + return preg_match('/^[A-Za-z0-9._-]+$/', $filename); + } + + /** + * @throws ClientException on invalid filename + */ static function path($filename) { + if (!self::validFilename($filename)) { + throw new ClientException("Invalid filename"); + } $dir = common_config('attachments', 'dir'); if ($dir[strlen($dir)-1] != '/') { @@ -189,6 +203,9 @@ class File extends Memcached_DataObject static function url($filename) { + if (!self::validFilename($filename)) { + throw new ClientException("Invalid filename"); + } if(common_config('site','private')) { return common_local_url('getfile', diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index 2cc6377f8..ab65c30ce 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -147,6 +147,7 @@ class Memcached_DataObject extends DB_DataObject { $result = parent::insert(); if ($result) { + $this->fixupTimestamps(); $this->encache(); // in case of cached negative lookups } return $result; @@ -159,6 +160,7 @@ class Memcached_DataObject extends DB_DataObject } $result = parent::update($orig); if ($result) { + $this->fixupTimestamps(); $this->encache(); } return $result; @@ -366,7 +368,7 @@ class Memcached_DataObject extends DB_DataObject } /** - * sends query to database - this is the private one that must work + * sends query to database - this is the private one that must work * - internal functions use this rather than $this->query() * * Overridden to do logging. @@ -428,7 +430,7 @@ class Memcached_DataObject extends DB_DataObject // // WARNING WARNING if we end up actually using multiple DBs at a time // we'll need some fancier logic here. - if (!$exists && !empty($_DB_DATAOBJECT['CONNECTIONS'])) { + if (!$exists && !empty($_DB_DATAOBJECT['CONNECTIONS']) && php_sapi_name() == 'cli') { foreach ($_DB_DATAOBJECT['CONNECTIONS'] as $index => $conn) { if (!empty($conn)) { $conn->disconnect(); @@ -529,4 +531,51 @@ class Memcached_DataObject extends DB_DataObject return $c->delete($cacheKey); } + + function fixupTimestamps() + { + // Fake up timestamp columns + $columns = $this->table(); + foreach ($columns as $name => $type) { + if ($type & DB_DATAOBJECT_MYSQLTIMESTAMP) { + $this->$name = common_sql_now(); + } + } + } + + function debugDump() + { + common_debug("debugDump: " . common_log_objstring($this)); + } + + function raiseError($message, $type = null, $behaviour = null) + { + throw new ServerException("DB_DataObject error [$type]: $message"); + } + + static function cacheGet($keyPart) + { + $c = self::memcache(); + + if (empty($c)) { + return false; + } + + $cacheKey = common_cache_key($keyPart); + + return $c->get($cacheKey); + } + + static function cacheSet($keyPart, $value) + { + $c = self::memcache(); + + if (empty($c)) { + return false; + } + + $cacheKey = common_cache_key($keyPart); + + return $c->set($cacheKey, $value); + } } diff --git a/classes/Notice.php b/classes/Notice.php index 0966697e2..42878d94f 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -140,7 +140,7 @@ class Notice extends Memcached_DataObject foreach(array_unique($hashtags) as $hashtag) { /* elide characters we don't want in the tag */ $this->saveTag($hashtag); - self::blow('profile:notice_ids_tagged:%d:%s', $this->profile_id, $tag->tag); + self::blow('profile:notice_ids_tagged:%d:%s', $this->profile_id, $hashtag); } return true; } @@ -326,9 +326,7 @@ class Notice extends Memcached_DataObject # XXX: someone clever could prepend instead of clearing the cache $notice->blowOnInsert(); - $qm = QueueManager::get(); - - $qm->enqueue($notice, 'distrib'); + $notice->distribute(); return $notice; } @@ -1374,8 +1372,6 @@ class Notice extends Memcached_DataObject } $reply->free(); - - return $ids; } function clearRepeats() @@ -1445,4 +1441,31 @@ class Notice extends Memcached_DataObject $gi->free(); } + + function distribute() + { + if (common_config('queue', 'inboxes')) { + // If there's a failure, we want to _force_ + // distribution at this point. + try { + $qm = QueueManager::get(); + $qm->enqueue($this, 'distrib'); + } catch (Exception $e) { + // If the exception isn't transient, this + // may throw more exceptions as DQH does + // its own enqueueing. So, we ignore them! + try { + $handler = new DistribQueueHandler(); + $handler->handle($this); + } catch (Exception $e) { + common_log(LOG_ERR, "emergency redistribution resulted in " . $e->getMessage()); + } + // Re-throw so somebody smarter can handle it. + throw $e; + } + } else { + $handler = new DistribQueueHandler(); + $handler->handle($this); + } + } } diff --git a/classes/Oauth_application.php b/classes/Oauth_application.php index a6b539087..748b64220 100644 --- a/classes/Oauth_application.php +++ b/classes/Oauth_application.php @@ -137,4 +137,21 @@ class Oauth_application extends Memcached_DataObject } } + function delete() + { + $this->_deleteAppUsers(); + + $consumer = $this->getConsumer(); + $consumer->delete(); + + parent::delete(); + } + + function _deleteAppUsers() + { + $oauser = new Oauth_application_user(); + $oauser->application_id = $this->id; + $oauser->delete(); + } + } diff --git a/classes/Profile_role.php b/classes/Profile_role.php index 74aca3730..bf2c453ed 100644 --- a/classes/Profile_role.php +++ b/classes/Profile_role.php @@ -48,6 +48,7 @@ class Profile_role extends Memcached_DataObject return Memcached_DataObject::pkeyGet('Profile_role', $kv); } + const OWNER = 'owner'; const MODERATOR = 'moderator'; const ADMINISTRATOR = 'administrator'; const SANDBOXED = 'sandboxed'; diff --git a/classes/Session.php b/classes/Session.php index 79a69a96e..2422f8b68 100644 --- a/classes/Session.php +++ b/classes/Session.php @@ -64,8 +64,12 @@ class Session extends Memcached_DataObject $session = Session::staticGet('id', $id); if (empty($session)) { + self::logdeb("Couldn't find '$id'"); return ''; } else { + self::logdeb("Found '$id', returning " . + strlen($session->session_data) . + " chars of data"); return (string)$session->session_data; } } @@ -77,14 +81,24 @@ class Session extends Memcached_DataObject $session = Session::staticGet('id', $id); if (empty($session)) { + self::logdeb("'$id' doesn't yet exist; inserting."); $session = new Session(); $session->id = $id; $session->session_data = $session_data; $session->created = common_sql_now(); - return $session->insert(); + $result = $session->insert(); + + if (!$result) { + common_log_db_error($session, 'INSERT', __FILE__); + self::logdeb("Failed to insert '$id'."); + } else { + self::logdeb("Successfully inserted '$id' (result = $result)."); + } + return $result; } else { + self::logdeb("'$id' already exists; updating."); if (strcmp($session->session_data, $session_data) == 0) { self::logdeb("Not writing session '$id'; unchanged"); return true; @@ -95,7 +109,16 @@ class Session extends Memcached_DataObject $session->session_data = $session_data; - return $session->update($orig); + $result = $session->update($orig); + + if (!$result) { + common_log_db_error($session, 'UPDATE', __FILE__); + self::logdeb("Failed to update '$id'."); + } else { + self::logdeb("Successfully updated '$id' (result = $result)."); + } + + return $result; } } } @@ -106,8 +129,17 @@ class Session extends Memcached_DataObject $session = Session::staticGet('id', $id); - if (!empty($session)) { - return $session->delete(); + if (empty($session)) { + self::logdeb("Can't find '$id' to delete."); + } else { + $result = $session->delete(); + if (!$result) { + common_log_db_error($session, 'DELETE', __FILE__); + self::logdeb("Failed to delete '$id'."); + } else { + self::logdeb("Successfully deleted '$id' (result = $result)."); + } + return $result; } } @@ -132,7 +164,10 @@ class Session extends Memcached_DataObject $session->free(); + self::logdeb("Found " . count($ids) . " ids to delete."); + foreach ($ids as $id) { + self::logdeb("Destroying session '$id'."); self::destroy($id); } } diff --git a/classes/User.php b/classes/User.php index 6ea975202..0ab816b57 100644 --- a/classes/User.php +++ b/classes/User.php @@ -209,8 +209,6 @@ class User extends Memcached_DataObject $profile = new Profile(); - $profile->query('BEGIN'); - if(!empty($email)) { $email = common_canonical_email($email); @@ -220,7 +218,7 @@ class User extends Memcached_DataObject $profile->nickname = $nickname; if(! User::allowed_nickname($nickname)){ common_log(LOG_WARNING, sprintf("Attempted to register a nickname that is not allowed: %s", $profile->nickname), - __FILE__); + __FILE__); } $profile->profileurl = common_profile_url($nickname); @@ -248,22 +246,10 @@ class User extends Memcached_DataObject $profile->created = common_sql_now(); - $id = $profile->insert(); - - if (empty($id)) { - common_log_db_error($profile, 'INSERT', __FILE__); - return false; - } - $user = new User(); - $user->id = $id; $user->nickname = $nickname; - if (!empty($password)) { // may not have a password for OpenID users - $user->password = common_munge_password($password, $id); - } - // Users who respond to invite email have proven their ownership of that address if (!empty($code)) { @@ -282,109 +268,129 @@ class User extends Memcached_DataObject $user->inboxed = 1; $user->created = common_sql_now(); - $user->uri = common_user_uri($user); - - $result = $user->insert(); - if (!$result) { - common_log_db_error($user, 'INSERT', __FILE__); - return false; - } - - // Everyone gets an inbox + if (Event::handle('StartUserRegister', array(&$user, &$profile))) { - $inbox = new Inbox(); + $profile->query('BEGIN'); - $inbox->user_id = $user->id; - $inbox->notice_ids = ''; + $id = $profile->insert(); - $result = $inbox->insert(); + if (empty($id)) { + common_log_db_error($profile, 'INSERT', __FILE__); + return false; + } - if (!$result) { - common_log_db_error($inbox, 'INSERT', __FILE__); - return false; - } + $user->id = $id; + $user->uri = common_user_uri($user); + if (!empty($password)) { // may not have a password for OpenID users + $user->password = common_munge_password($password, $id); + } - // Everyone is subscribed to themself + $result = $user->insert(); - $subscription = new Subscription(); - $subscription->subscriber = $user->id; - $subscription->subscribed = $user->id; - $subscription->created = $user->created; + if (!$result) { + common_log_db_error($user, 'INSERT', __FILE__); + return false; + } - $result = $subscription->insert(); + // Everyone gets an inbox - if (!$result) { - common_log_db_error($subscription, 'INSERT', __FILE__); - return false; - } + $inbox = new Inbox(); - if (!empty($email) && !$user->email) { + $inbox->user_id = $user->id; + $inbox->notice_ids = ''; - $confirm = new Confirm_address(); - $confirm->code = common_confirmation_code(128); - $confirm->user_id = $user->id; - $confirm->address = $email; - $confirm->address_type = 'email'; + $result = $inbox->insert(); - $result = $confirm->insert(); if (!$result) { - common_log_db_error($confirm, 'INSERT', __FILE__); + common_log_db_error($inbox, 'INSERT', __FILE__); return false; } - } - if (!empty($code) && $user->email) { - $user->emailChanged(); - } + // Everyone is subscribed to themself - // Default system subscription + $subscription = new Subscription(); + $subscription->subscriber = $user->id; + $subscription->subscribed = $user->id; + $subscription->created = $user->created; - $defnick = common_config('newuser', 'default'); + $result = $subscription->insert(); - if (!empty($defnick)) { - $defuser = User::staticGet('nickname', $defnick); - if (empty($defuser)) { - common_log(LOG_WARNING, sprintf("Default user %s does not exist.", $defnick), - __FILE__); - } else { - $defsub = new Subscription(); - $defsub->subscriber = $user->id; - $defsub->subscribed = $defuser->id; - $defsub->created = $user->created; + if (!$result) { + common_log_db_error($subscription, 'INSERT', __FILE__); + return false; + } + + if (!empty($email) && !$user->email) { + + $confirm = new Confirm_address(); + $confirm->code = common_confirmation_code(128); + $confirm->user_id = $user->id; + $confirm->address = $email; + $confirm->address_type = 'email'; - $result = $defsub->insert(); + $result = $confirm->insert(); if (!$result) { - common_log_db_error($defsub, 'INSERT', __FILE__); + common_log_db_error($confirm, 'INSERT', __FILE__); return false; } } - } - $profile->query('COMMIT'); + if (!empty($code) && $user->email) { + $user->emailChanged(); + } + + // Default system subscription - if (!empty($email) && !$user->email) { - mail_confirm_address($user, $confirm->code, $profile->nickname, $email); - } + $defnick = common_config('newuser', 'default'); - // Welcome message + if (!empty($defnick)) { + $defuser = User::staticGet('nickname', $defnick); + if (empty($defuser)) { + common_log(LOG_WARNING, sprintf("Default user %s does not exist.", $defnick), + __FILE__); + } else { + $defsub = new Subscription(); + $defsub->subscriber = $user->id; + $defsub->subscribed = $defuser->id; + $defsub->created = $user->created; - $welcome = common_config('newuser', 'welcome'); + $result = $defsub->insert(); - if (!empty($welcome)) { - $welcomeuser = User::staticGet('nickname', $welcome); - if (empty($welcomeuser)) { - common_log(LOG_WARNING, sprintf("Welcome user %s does not exist.", $defnick), - __FILE__); - } else { - $notice = Notice::saveNew($welcomeuser->id, - sprintf(_('Welcome to %1$s, @%2$s!'), - common_config('site', 'name'), - $user->nickname), - 'system'); + if (!$result) { + common_log_db_error($defsub, 'INSERT', __FILE__); + return false; + } + } + } + $profile->query('COMMIT'); + + if (!empty($email) && !$user->email) { + mail_confirm_address($user, $confirm->code, $profile->nickname, $email); + } + + // Welcome message + + $welcome = common_config('newuser', 'welcome'); + + if (!empty($welcome)) { + $welcomeuser = User::staticGet('nickname', $welcome); + if (empty($welcomeuser)) { + common_log(LOG_WARNING, sprintf("Welcome user %s does not exist.", $defnick), + __FILE__); + } else { + $notice = Notice::saveNew($welcomeuser->id, + sprintf(_('Welcome to %1$s, @%2$s!'), + common_config('site', 'name'), + $user->nickname), + 'system'); + + } } + + Event::handle('EndUserRegister', array(&$profile, &$user)); } return $user; @@ -925,4 +931,30 @@ class User extends Memcached_DataObject return $share; } } + + static function siteOwner() + { + $owner = self::cacheGet('user:site_owner'); + + if ($owner === false) { // cache miss + + $pr = new Profile_role(); + + $pr->role = Profile_role::OWNER; + + $pr->orderBy('created'); + + $pr->limit(1); + + if ($pr->find(true)) { + $owner = User::staticGet('id', $pr->profile_id); + } else { + $owner = null; + } + + self::cacheSet('user:site_owner', $owner); + } + + return $owner; + } } diff --git a/classes/status_network.ini b/classes/status_network.ini index 8123265e4..adb71cba7 100644 --- a/classes/status_network.ini +++ b/classes/status_network.ini @@ -11,6 +11,7 @@ theme = 2 logo = 2 created = 142 modified = 384 +tags = 34 [status_network__keys] nickname = K diff --git a/classes/statusnet.ini b/classes/statusnet.ini index 6203650a6..4ace4407b 100644 --- a/classes/statusnet.ini +++ b/classes/statusnet.ini @@ -353,7 +353,7 @@ notice_id = K id = 129 owner = 129 consumer_key = 130 -name = 130 +name = 2 description = 2 icon = 130 source_url = 2 @@ -367,6 +367,7 @@ modified = 384 [oauth_application__keys] id = N +name = U [oauth_application_user] profile_id = 129 |