summaryrefslogtreecommitdiff
path: root/classes
diff options
context:
space:
mode:
authorEvan Prodromou <evan@status.net>2009-10-02 15:27:55 -0400
committerEvan Prodromou <evan@status.net>2009-10-02 15:27:55 -0400
commitb3b3af9a2eff10c272bb213eccd3dd3060bc5830 (patch)
treeff0ae9108bcb085015a8e9f286963ad9fe58c13c /classes
parent51ac34e80c5a99008b1a945b2c00b6dbfdde1529 (diff)
parent5309910b9b4dd2533ff5b2190f90bf415fd20113 (diff)
Merge branch '0.8.x' into deleteuser
Diffstat (limited to 'classes')
-rw-r--r--classes/Design.php101
-rw-r--r--classes/File.php24
-rw-r--r--classes/File_oembed.php6
-rw-r--r--classes/File_redirection.php10
-rw-r--r--classes/File_thumbnail.php6
-rw-r--r--classes/File_to_post.php6
-rw-r--r--classes/Foreign_link.php34
-rw-r--r--classes/Group_alias.php6
-rw-r--r--classes/Group_block.php6
-rw-r--r--classes/Memcached_DataObject.php75
-rw-r--r--classes/Notice.php193
-rw-r--r--classes/Notice_inbox.php6
-rw-r--r--classes/Notice_tag.php4
-rw-r--r--classes/Profile.php6
-rw-r--r--classes/Profile_block.php6
-rw-r--r--classes/Remote_profile.php6
-rw-r--r--classes/Session.php23
-rw-r--r--classes/Status_network.php10
-rw-r--r--classes/Subscription.php6
-rw-r--r--classes/User.php20
-rw-r--r--classes/User_group.php41
-rw-r--r--classes/laconica.ini500
-rw-r--r--classes/status_network.ini18
-rw-r--r--classes/statusnet.ini516
-rw-r--r--classes/statusnet.links.ini (renamed from classes/laconica.links.ini)0
25 files changed, 944 insertions, 685 deletions
diff --git a/classes/Design.php b/classes/Design.php
index 0927fcda7..89ae50c8c 100644
--- a/classes/Design.php
+++ b/classes/Design.php
@@ -1,7 +1,7 @@
<?php
/*
- * Laconica - the distributed open-source microblogging tool
- * Copyright (C) 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) {
+if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
@@ -55,26 +55,38 @@ class Design extends Memcached_DataObject
function showCSS($out)
{
- try {
+ $css = '';
- $bgcolor = new WebColor($this->backgroundcolor);
- $ccolor = new WebColor($this->contentcolor);
- $sbcolor = new WebColor($this->sidebarcolor);
- $tcolor = new WebColor($this->textcolor);
- $lcolor = new WebColor($this->linkcolor);
+ $bgcolor = Design::toWebColor($this->backgroundcolor);
- } catch (WebColorException $e) {
- // This shouldn't happen
- common_log(LOG_ERR, "Unable to create color for design $id.",
- __FILE__);
+ if (!empty($bgcolor)) {
+ $css .= 'body { background-color: #' . $bgcolor->hexValue() . ' }' . "\n";
}
- $css = 'body { background-color: #' . $bgcolor->hexValue() . ' }' . "\n";
- $css .= '#content, #site_nav_local_views .current a { background-color: #';
- $css .= $ccolor->hexValue() . '} '."\n";
- $css .= '#aside_primary { background-color: #'. $sbcolor->hexValue() . ' }' . "\n";
- $css .= 'html body { color: #'. $tcolor->hexValue() . ' }'. "\n";
- $css .= 'a { color: #' . $lcolor->hexValue() . ' }' . "\n";
+ $ccolor = Design::toWebColor($this->contentcolor);
+
+ if (!empty($ccolor)) {
+ $css .= '#content, #site_nav_local_views .current a { background-color: #';
+ $css .= $ccolor->hexValue() . '} '."\n";
+ }
+
+ $sbcolor = Design::toWebColor($this->sidebarcolor);
+
+ if (!empty($sbcolor)) {
+ $css .= '#aside_primary { background-color: #'. $sbcolor->hexValue() . ' }' . "\n";
+ }
+
+ $tcolor = Design::toWebColor($this->textcolor);
+
+ if (!empty($tcolor)) {
+ $css .= 'html body { color: #'. $tcolor->hexValue() . ' }'. "\n";
+ }
+
+ $lcolor = Design::toWebColor($this->linkcolor);
+
+ if (!empty($lcolor)) {
+ $css .= 'a { color: #' . $lcolor->hexValue() . ' }' . "\n";
+ }
if (!empty($this->backgroundimage) &&
$this->disposition & BACKGROUND_ON) {
@@ -88,8 +100,25 @@ class Design extends Memcached_DataObject
'); ' . $repeat . ' background-attachment:fixed; }' . "\n";
}
- $out->element('style', array('type' => 'text/css'), $css);
+ if (0 != mb_strlen($css)) {
+ $out->element('style', array('type' => 'text/css'), $css);
+ }
+ }
+
+ static function toWebColor($color)
+ {
+ if ($color == null) {
+ return null;
+ }
+ try {
+ return new WebColor($color);
+ } catch (WebColorException $e) {
+ // This shouldn't happen
+ common_log(LOG_ERR, "Unable to create web color for $color",
+ __FILE__);
+ return null;
+ }
}
static function filename($id, $extension, $extra=null)
@@ -152,4 +181,36 @@ class Design extends Memcached_DataObject
}
}
+ /**
+ * Return a design object based on the configured site design.
+ *
+ * @return Design a singleton design object for the site.
+ */
+
+ static function siteDesign()
+ {
+ static $siteDesign = null;
+
+ if (empty($siteDesign)) {
+
+ $siteDesign = new Design();
+
+ $attrs = array('backgroundcolor',
+ 'contentcolor',
+ 'sidebarcolor',
+ 'textcolor',
+ 'linkcolor',
+ 'backgroundimage',
+ 'disposition');
+
+ foreach ($attrs as $attr) {
+ $val = common_config('design', $attr);
+ if ($val !== false) {
+ $siteDesign->$attr = $val;
+ }
+ }
+ }
+
+ return $siteDesign;
+ }
}
diff --git a/classes/File.php b/classes/File.php
index 0c4fbf7e6..308d0a771 100644
--- a/classes/File.php
+++ b/classes/File.php
@@ -1,7 +1,7 @@
<?php
/*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
require_once INSTALLDIR.'/classes/File_redirection.php';
@@ -78,14 +78,14 @@ class File extends Memcached_DataObject
$file_id = $x->insert();
if (isset($redir_data['type'])
- && ('text/html' === substr($redir_data['type'], 0, 9))
+ && (('text/html' === substr($redir_data['type'], 0, 9) || 'application/xhtml+xml' === substr($redir_data['type'], 0, 21)))
&& ($oembed_data = File_oembed::_getOembed($given_url))) {
File_oembed::saveNew($oembed_data, $file_id);
}
return $x;
}
- function processNew($given_url, $notice_id) {
+ function processNew($given_url, $notice_id=null) {
if (empty($given_url)) return -1; // error, no url to process
$given_url = File_redirection::_canonUrl($given_url);
if (empty($given_url)) return -1; // error, no url to process
@@ -93,10 +93,10 @@ class File extends Memcached_DataObject
if (empty($file)) {
$file_redir = File_redirection::staticGet('url', $given_url);
if (empty($file_redir)) {
- common_debug("processNew() '$given_url' not a known redirect.\n");
$redir_data = File_redirection::where($given_url);
$redir_url = $redir_data['url'];
- if ($redir_url === $given_url) {
+ // TODO: max field length
+ if ($redir_url === $given_url || strlen($redir_url) > 255) {
$x = File::saveNew($redir_data, $given_url);
$file_id = $x->id;
} else {
@@ -114,10 +114,14 @@ class File extends Memcached_DataObject
if (empty($x)) {
$x = File::staticGet($file_id);
- if (empty($x)) die('Impossible!');
+ if (empty($x)) {
+ throw new ServerException("Robin thinks something is impossible.");
+ }
}
- File_to_post::processNew($file_id, $notice_id);
+ if (!empty($notice_id)) {
+ File_to_post::processNew($file_id, $notice_id);
+ }
return $x;
}
@@ -197,7 +201,7 @@ class File extends Memcached_DataObject
if(isset($this->filename)){
return true;
}
- $notEnclosureMimeTypes = array('text/html','application/xhtml+xml');
+ $notEnclosureMimeTypes = array('text/html','application/xhtml+xml',null);
$mimetype = strtolower($this->mimetype);
$semicolon = strpos($mimetype,';');
if($semicolon){
diff --git a/classes/File_oembed.php b/classes/File_oembed.php
index bbf112729..6be651815 100644
--- a/classes/File_oembed.php
+++ b/classes/File_oembed.php
@@ -1,7 +1,7 @@
<?php
/*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
diff --git a/classes/File_redirection.php b/classes/File_redirection.php
index d6fa0bcb6..76b18f672 100644
--- a/classes/File_redirection.php
+++ b/classes/File_redirection.php
@@ -1,7 +1,7 @@
<?php
/*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -17,13 +17,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
require_once INSTALLDIR.'/classes/File.php';
require_once INSTALLDIR.'/classes/File_oembed.php';
-define('USER_AGENT', 'Laconica user agent / file probe');
+define('USER_AGENT', 'StatusNet user agent / file probe');
/**
* Table Definition for file_redirection
@@ -182,7 +182,7 @@ class File_redirection extends Memcached_DataObject
}
}
- if (('ftp' == $p['scheme']) || ('http' == $p['scheme']) || ('https' == $p['scheme'])) {
+ if (('ftp' == $p['scheme']) || ('ftps' == $p['scheme']) || ('http' == $p['scheme']) || ('https' == $p['scheme'])) {
if (empty($p['host'])) return false;
if (empty($p['path'])) {
$out_url .= '/';
diff --git a/classes/File_thumbnail.php b/classes/File_thumbnail.php
index 0b09c6af8..f8b70356c 100644
--- a/classes/File_thumbnail.php
+++ b/classes/File_thumbnail.php
@@ -1,7 +1,7 @@
<?php
/*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
diff --git a/classes/File_to_post.php b/classes/File_to_post.php
index d35febb77..e3db91b20 100644
--- a/classes/File_to_post.php
+++ b/classes/File_to_post.php
@@ -1,7 +1,7 @@
<?php
/*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
diff --git a/classes/Foreign_link.php b/classes/Foreign_link.php
index c0b356ece..ae8c22fd8 100644
--- a/classes/Foreign_link.php
+++ b/classes/Foreign_link.php
@@ -29,34 +29,38 @@ class Foreign_link extends Memcached_DataObject
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
- // XXX: This only returns a 1->1 single obj mapping. Change? Or make
- // a getForeignUsers() that returns more than one? --Zach
static function getByUserID($user_id, $service)
{
+ if (empty($user_id) || empty($service)) {
+ return null;
+ }
+
$flink = new Foreign_link();
+
$flink->service = $service;
$flink->user_id = $user_id;
$flink->limit(1);
- if ($flink->find(true)) {
- return $flink;
- }
+ $result = $flink->find(true);
+
+ return empty($result) ? null : $flink;
- return null;
}
static function getByForeignID($foreign_id, $service)
{
- $flink = new Foreign_link();
- $flink->service = $service;
- $flink->foreign_id = $foreign_id;
- $flink->limit(1);
+ if (empty($foreign_id) || empty($service)) {
+ return null;
+ } else {
+ $flink = new Foreign_link();
+ $flink->service = $service;
+ $flink->foreign_id = $foreign_id;
+ $flink->limit(1);
- if ($flink->find(true)) {
- return $flink;
- }
+ $result = $flink->find(true);
- return null;
+ return empty($result) ? null : $flink;
+ }
}
function set_flags($noticesend, $noticerecv, $replysync, $friendsync)
@@ -66,7 +70,7 @@ class Foreign_link extends Memcached_DataObject
} else {
$this->noticesync &= ~FOREIGN_NOTICE_SEND;
}
-
+
if ($noticerecv) {
$this->noticesync |= FOREIGN_NOTICE_RECV;
} else {
diff --git a/classes/Group_alias.php b/classes/Group_alias.php
index e801e50e1..be3d0a6c6 100644
--- a/classes/Group_alias.php
+++ b/classes/Group_alias.php
@@ -2,8 +2,8 @@
/**
* Table Definition for group_alias
*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
diff --git a/classes/Group_block.php b/classes/Group_block.php
index 7922c19a9..de2cf5f6e 100644
--- a/classes/Group_block.php
+++ b/classes/Group_block.php
@@ -2,8 +2,8 @@
/**
* Table Definition for group_block
*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php
index f7cbb9d5b..9c2ac3e01 100644
--- a/classes/Memcached_DataObject.php
+++ b/classes/Memcached_DataObject.php
@@ -1,7 +1,7 @@
<?php
/*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
@@ -241,10 +241,19 @@ class Memcached_DataObject extends DB_DataObject
function _connect()
{
global $_DB_DATAOBJECT;
- $exists = !empty($this->_database_dsn_md5) &&
- isset($_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5]);
+
+ $sum = $this->_getDbDsnMD5();
+
+ if (!empty($_DB_DATAOBJECT['CONNECTIONS'][$sum]) &&
+ !PEAR::isError($_DB_DATAOBJECT['CONNECTIONS'][$sum])) {
+ $exists = true;
+ } else {
+ $exists = false;
+ }
+
$result = parent::_connect();
- if (!$exists) {
+
+ if ($result && !$exists) {
$DB = &$_DB_DATAOBJECT['CONNECTIONS'][$this->_database_dsn_md5];
if (common_config('db', 'type') == 'mysql' &&
common_config('db', 'utf8')) {
@@ -258,7 +267,61 @@ class Memcached_DataObject extends DB_DataObject
}
}
}
+
return $result;
}
+ // XXX: largely cadged from DB_DataObject
+
+ function _getDbDsnMD5()
+ {
+ if ($this->_database_dsn_md5) {
+ return $this->_database_dsn_md5;
+ }
+
+ $dsn = $this->_getDbDsn();
+
+ if (is_string($dsn)) {
+ $sum = md5($dsn);
+ } else {
+ /// support array based dsn's
+ $sum = md5(serialize($dsn));
+ }
+
+ return $sum;
+ }
+
+ function _getDbDsn()
+ {
+ global $_DB_DATAOBJECT;
+
+ if (empty($_DB_DATAOBJECT['CONFIG'])) {
+ DB_DataObject::_loadConfig();
+ }
+
+ $options = &$_DB_DATAOBJECT['CONFIG'];
+
+ // if the databse dsn dis defined in the object..
+
+ $dsn = isset($this->_database_dsn) ? $this->_database_dsn : null;
+
+ if (!$dsn) {
+
+ if (!$this->_database) {
+ $this->_database = isset($options["table_{$this->__table}"]) ? $options["table_{$this->__table}"] : null;
+ }
+
+ if ($this->_database && !empty($options["database_{$this->_database}"])) {
+ $dsn = $options["database_{$this->_database}"];
+ } else if (!empty($options['database'])) {
+ $dsn = $options['database'];
+ }
+ }
+
+ if (!$dsn) {
+ throw new Exception("No database name / dsn found anywhere");
+ }
+
+ return $dsn;
+ }
}
diff --git a/classes/Notice.php b/classes/Notice.php
index c2770edbe..7d0502626 100644
--- a/classes/Notice.php
+++ b/classes/Notice.php
@@ -1,7 +1,7 @@
<?php
/*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
/**
* Table Definition for notice
@@ -29,10 +29,6 @@ require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
define('NOTICE_CACHE_WINDOW', 61);
-define('NOTICE_LOCAL_PUBLIC', 1);
-define('NOTICE_REMOTE_OMB', 0);
-define('NOTICE_LOCAL_NONPUBLIC', -1);
-
define('MAX_BOXCARS', 128);
class Notice extends Memcached_DataObject
@@ -62,7 +58,11 @@ class Notice extends Memcached_DataObject
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
- const GATEWAY = -2;
+ /* Notice types */
+ const LOCAL_PUBLIC = 1;
+ const REMOTE_OMB = 0;
+ const LOCAL_NONPUBLIC = -1;
+ const GATEWAY = -2;
function getProfile()
{
@@ -102,15 +102,14 @@ class Notice extends Memcached_DataObject
if (!$count) {
return true;
}
-
+
//turn each into their canonical tag
//this is needed to remove dupes before saving e.g. #hash.tag = #hashtag
$hashtags = array();
for($i=0; $i<count($match[1]); $i++) {
- $hashtags[] = common_canonical_tag($match[1][$i]);
+ $hashtags[] = common_canonical_tag($match[1][$i]);
}
-
/* Add them to the database */
foreach(array_unique($hashtags) as $hashtag) {
/* elide characters we don't want in the tag */
@@ -135,7 +134,7 @@ class Notice extends Memcached_DataObject
}
static function saveNew($profile_id, $content, $source=null,
- $is_local=1, $reply_to=null, $uri=null, $created=null) {
+ $is_local=Notice::LOCAL_PUBLIC, $reply_to=null, $uri=null, $created=null) {
$profile = Profile::staticGet($profile_id);
@@ -178,34 +177,35 @@ class Notice extends Memcached_DataObject
if (($blacklist && in_array($profile_id, $blacklist)) ||
($source && $autosource && in_array($source, $autosource))) {
- $notice->is_local = -1;
+ $notice->is_local = Notice::LOCAL_NONPUBLIC;
} else {
$notice->is_local = $is_local;
}
- $notice->query('BEGIN');
-
- $notice->reply_to = $reply_to;
if (!empty($created)) {
$notice->created = $created;
} else {
$notice->created = common_sql_now();
}
+
$notice->content = $final;
$notice->rendered = common_render_content($final, $notice);
$notice->source = $source;
$notice->uri = $uri;
- if (!empty($reply_to)) {
- $reply_notice = Notice::staticGet('id', $reply_to);
- if (!empty($reply_notice)) {
- $notice->reply_to = $reply_to;
- $notice->conversation = $reply_notice->conversation;
- }
+ $notice->reply_to = self::getReplyTo($reply_to, $profile_id, $source, $final);
+
+ if (!empty($notice->reply_to)) {
+ $reply = Notice::staticGet('id', $notice->reply_to);
+ $notice->conversation = $reply->conversation;
}
if (Event::handle('StartNoticeSave', array(&$notice))) {
+ // XXX: some of these functions write to the DB
+
+ $notice->query('BEGIN');
+
$id = $notice->insert();
if (!$id) {
@@ -213,18 +213,33 @@ class Notice extends Memcached_DataObject
return _('Problem saving notice.');
}
- # Update the URI after the notice is in the database
- if (!$uri) {
- $orig = clone($notice);
+ // Update ID-dependent columns: URI, conversation
+
+ $orig = clone($notice);
+
+ $changed = false;
+
+ if (empty($uri)) {
$notice->uri = common_notice_uri($notice);
+ $changed = true;
+ }
+ // If it's not part of a conversation, it's
+ // the beginning of a new conversation.
+
+ if (empty($notice->conversation)) {
+ $notice->conversation = $notice->id;
+ $changed = true;
+ }
+
+ if ($changed) {
if (!$notice->update($orig)) {
common_log_db_error($notice, 'UPDATE', __FILE__);
return _('Problem saving notice.');
}
}
- # XXX: do we need to change this for remote users?
+ // XXX: do we need to change this for remote users?
$notice->saveReplies();
$notice->saveTags();
@@ -232,12 +247,6 @@ class Notice extends Memcached_DataObject
$notice->addToInboxes();
$notice->saveUrls();
- $orig2 = clone($notice);
- $notice->rendered = common_render_content($final, $notice);
- if (!$notice->update($orig2)) {
- common_log_db_error($notice, 'UPDATE', __FILE__);
- return _('Problem saving notice.');
- }
$notice->query('COMMIT');
@@ -290,9 +299,9 @@ class Notice extends Memcached_DataObject
$notice->profile_id = $profile_id;
$notice->content = $content;
if (common_config('db','type') == 'pgsql')
- $notice->whereAdd('extract(epoch from now() - created) < ' . common_config('site', 'dupelimit'));
+ $notice->whereAdd('extract(epoch from now() - created) < ' . common_config('site', 'dupelimit'));
else
- $notice->whereAdd('now() - created < ' . common_config('site', 'dupelimit'));
+ $notice->whereAdd('now() - created < ' . common_config('site', 'dupelimit'));
$cnt = $notice->count();
return ($cnt == 0);
@@ -489,7 +498,7 @@ class Notice extends Memcached_DataObject
function blowPublicCache($blowLast=false)
{
- if ($this->is_local == 1) {
+ if ($this->is_local == Notice::LOCAL_PUBLIC) {
$cache = common_memcache();
if ($cache) {
$cache->delete(common_cache_key('public'));
@@ -723,6 +732,10 @@ class Notice extends Memcached_DataObject
return new ArrayWrapper($notices);
} else {
$notice = new Notice();
+ if (empty($ids)) {
+ //if no IDs requested, just return the notice object
+ return $notice;
+ }
$notice->whereAdd('id in (' . implode(', ', $ids) . ')');
$notice->orderBy('id DESC');
@@ -755,10 +768,11 @@ class Notice extends Memcached_DataObject
}
if (common_config('public', 'localonly')) {
- $notice->whereAdd('is_local = 1');
+ $notice->whereAdd('is_local = ' . Notice::LOCAL_PUBLIC);
} else {
- # -1 == blacklisted
- $notice->whereAdd('is_local != -1');
+ # -1 == blacklisted, -2 == gateway (i.e. Twitter)
+ $notice->whereAdd('is_local !='. Notice::LOCAL_NONPUBLIC);
+ $notice->whereAdd('is_local !='. Notice::GATEWAY);
}
if ($since_id != 0) {
@@ -883,7 +897,8 @@ class Notice extends Memcached_DataObject
$qry .= '('.$id.', '.$this->id.', '.$source.", '".$this->created. "') ";
$cnt++;
if (rand() % NOTICE_INBOX_SOFT_LIMIT == 0) {
- Notice_inbox::gc($id);
+ // FIXME: Causes lag in replicated servers
+ // Notice_inbox::gc($id);
}
if ($cnt >= MAX_BOXCARS) {
$inbox = new Notice_inbox();
@@ -906,14 +921,14 @@ class Notice extends Memcached_DataObject
{
$user = new User();
- if(common_config('db','quote_identifiers'))
- $user_table = '"user"';
- else $user_table = 'user';
+ if(common_config('db','quote_identifiers'))
+ $user_table = '"user"';
+ else $user_table = 'user';
$qry =
'SELECT id ' .
- 'FROM '. $user_table .' JOIN subscription '.
- 'ON '. $user_table .'.id = subscription.subscriber ' .
+ 'FROM '. $user_table .' JOIN subscription '.
+ 'ON '. $user_table .'.id = subscription.subscriber ' .
'WHERE subscription.subscribed = %d ';
$user->query(sprintf($qry, $this->profile_id));
@@ -1031,16 +1046,6 @@ class Notice extends Memcached_DataObject
if (!$recipient) {
continue;
}
- if ($i == 0 && ($recipient->id != $sender->id) && !$this->reply_to) { // Don't save reply to self
- $reply_for = $recipient;
- $recipient_notice = $reply_for->getCurrentNotice();
- if ($recipient_notice) {
- $orig = clone($this);
- $this->reply_to = $recipient_notice->id;
- $this->conversation = $recipient_notice->conversation;
- $this->update($orig);
- }
- }
// Don't save replies from blocked profile to local user
$recipient_user = User::staticGet('id', $recipient->id);
if ($recipient_user && $recipient_user->hasBlocked($sender)) {
@@ -1087,14 +1092,6 @@ class Notice extends Memcached_DataObject
}
}
- // If it's not a reply, make it the root of a new conversation
-
- if (empty($this->conversation)) {
- $orig = clone($this);
- $this->conversation = $this->id;
- $this->update($orig);
- }
-
foreach (array_keys($replied) as $recipient) {
$user = User::staticGet('id', $recipient);
if ($user) {
@@ -1266,4 +1263,76 @@ class Notice extends Memcached_DataObject
return $ids;
}
+
+ /**
+ * Determine which notice, if any, a new notice is in reply to.
+ *
+ * For conversation tracking, we try to see where this notice fits
+ * in the tree. Rough algorithm is:
+ *
+ * if (reply_to is set and valid) {
+ * return reply_to;
+ * } else if ((source not API or Web) and (content starts with "T NAME" or "@name ")) {
+ * return ID of last notice by initial @name in content;
+ * }
+ *
+ * Note that all @nickname instances will still be used to save "reply" records,
+ * so the notice shows up in the mentioned users' "replies" tab.
+ *
+ * @param integer $reply_to ID passed in by Web or API
+ * @param integer $profile_id ID of author
+ * @param string $source Source tag, like 'web' or 'gwibber'
+ * @param string $content Final notice content
+ *
+ * @return integer ID of replied-to notice, or null for not a reply.
+ */
+
+ static function getReplyTo($reply_to, $profile_id, $source, $content)
+ {
+ static $lb = array('xmpp', 'mail', 'sms', 'omb');
+
+ // If $reply_to is specified, we check that it exists, and then
+ // return it if it does
+
+ if (!empty($reply_to)) {
+ $reply_notice = Notice::staticGet('id', $reply_to);
+ if (!empty($reply_notice)) {
+ return $reply_to;
+ }
+ }
+
+ // If it's not a "low bandwidth" source (one where you can't set
+ // a reply_to argument), we return. This is mostly web and API
+ // clients.
+
+ if (!in_array($source, $lb)) {
+ return null;
+ }
+
+ // Is there an initial @ or T?
+
+ if (preg_match('/^T ([A-Z0-9]{1,64}) /', $content, $match) ||
+ preg_match('/^@([a-z0-9]{1,64})\s+/', $content, $match)) {
+ $nickname = common_canonical_nickname($match[1]);
+ } else {
+ return null;
+ }
+
+ // Figure out who that is.
+
+ $sender = Profile::staticGet('id', $profile_id);
+ $recipient = common_relative_profile($sender, $nickname, common_sql_now());
+
+ if (empty($recipient)) {
+ return null;
+ }
+
+ // Get their last notice
+
+ $last = $recipient->getCurrentNotice();
+
+ if (!empty($last)) {
+ return $last->id;
+ }
+ }
}
diff --git a/classes/Notice_inbox.php b/classes/Notice_inbox.php
index 2af34b1a4..d3e7853b1 100644
--- a/classes/Notice_inbox.php
+++ b/classes/Notice_inbox.php
@@ -1,7 +1,7 @@
<?php
/*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
diff --git a/classes/Notice_tag.php b/classes/Notice_tag.php
index 4e52ef269..02740280f 100644
--- a/classes/Notice_tag.php
+++ b/classes/Notice_tag.php
@@ -1,7 +1,7 @@
<?php
/*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
diff --git a/classes/Profile.php b/classes/Profile.php
index 0ee6fa657..463802b4e 100644
--- a/classes/Profile.php
+++ b/classes/Profile.php
@@ -1,7 +1,7 @@
<?php
/*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
/**
* Table Definition for profile
diff --git a/classes/Profile_block.php b/classes/Profile_block.php
index feadea42d..2d87edaa0 100644
--- a/classes/Profile_block.php
+++ b/classes/Profile_block.php
@@ -1,7 +1,7 @@
<?php
/*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
/**
* Table Definition for profile_block
diff --git a/classes/Remote_profile.php b/classes/Remote_profile.php
index 975852dd9..9f7bfeadc 100644
--- a/classes/Remote_profile.php
+++ b/classes/Remote_profile.php
@@ -1,7 +1,7 @@
<?php
/*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
/**
* Table Definition for remote_profile
diff --git a/classes/Session.php b/classes/Session.php
index ac80279c5..d641edbbe 100644
--- a/classes/Session.php
+++ b/classes/Session.php
@@ -2,8 +2,8 @@
/**
* Table Definition for session
*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
@@ -108,11 +108,24 @@ class Session extends Memcached_DataObject
$epoch = common_sql_date(time() - $maxlifetime);
+ $ids = array();
+
$session = new Session();
$session->whereAdd('modified < "'.$epoch.'"');
- $result = $session->delete(DB_DATAOBJECT_WHEREADD_ONLY);
+ $session->selectAdd();
+ $session->selectAdd('id');
+
+ $session->find();
+
+ while ($session->fetch()) {
+ $ids[] = $session->id;
+ }
+
+ $session->free();
- self::logdeb("garbage collection result = $result");
+ foreach ($ids as $id) {
+ self::destroy($id);
+ }
}
static function setSaveHandler()
diff --git a/classes/Status_network.php b/classes/Status_network.php
index dbd722e88..fe4f0b0c5 100644
--- a/classes/Status_network.php
+++ b/classes/Status_network.php
@@ -2,8 +2,8 @@
/**
* Table Definition for status_network
*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
class Status_network extends DB_DataObject
{
@@ -54,7 +54,7 @@ class Status_network extends DB_DataObject
global $config;
$config['db']['database_'.$dbname] = "mysqli://$dbuser:$dbpass@$dbhost/$dbname";
- $config['db']['ini_'.$dbname] = INSTALLDIR.'/classes/statusnet.ini';
+ $config['db']['ini_'.$dbname] = INSTALLDIR.'/classes/status_network.ini';
$config['db']['table_status_network'] = $dbname;
self::$cache = new Memcache();
@@ -71,7 +71,7 @@ class Status_network extends DB_DataObject
}
static function cacheKey($k, $v) {
- return 'laconica:' . self::$base . ':status_network:'.$k.':'.$v;
+ return 'statusnet:' . self::$base . ':status_network:'.$k.':'.$v;
}
static function memGet($k, $v)
diff --git a/classes/Subscription.php b/classes/Subscription.php
index d4580fcba..fedfd5f19 100644
--- a/classes/Subscription.php
+++ b/classes/Subscription.php
@@ -1,7 +1,7 @@
<?php
/*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) { exit(1); }
+if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }
/**
* Table Definition for subscription
diff --git a/classes/User.php b/classes/User.php
index 991e9c18f..ef8434292 100644
--- a/classes/User.php
+++ b/classes/User.php
@@ -1,7 +1,7 @@
<?php
/*
- * Laconica - a distributed open-source microblogging tool
- * Copyright (C) 2008, 2009, Control Yourself, Inc.
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
@@ -17,7 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-if (!defined('LACONICA')) {
+if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
@@ -120,11 +120,15 @@ class User extends Memcached_DataObject
function allowed_nickname($nickname)
{
// XXX: should already be validated for size, content, etc.
- static $blacklist = array('rss', 'xrds', 'doc', 'main',
- 'settings', 'notice', 'user',
- 'search', 'avatar', 'tag', 'tags',
- 'api', 'message', 'group', 'groups',
- 'local');
+
+ $blacklist = array();
+
+ //all directory and file names should be blacklisted
+ $d = dir(INSTALLDIR);
+ while (false !== ($entry = $d->read())) {
+ $blacklist[]=$entry;
+ }
+ $d->close();
$merged = array_merge($blacklist, common_config('nickname', 'blacklist'));
return !in_array($nickname, $merged);
}
diff --git a/classes/User_group.php b/classes/User_group.php
index b1ab1c2d3..ea19cbb97 100644
--- a/classes/User_group.php
+++ b/classes/User_group.php
@@ -297,4 +297,45 @@ class User_group extends Memcached_DataObject
return $ids;
}
+
+ function asAtomEntry($namespace=false, $source=false)
+ {
+ $xs = new XMLStringer(true);
+
+ if ($namespace) {
+ $attrs = array('xmlns' => 'http://www.w3.org/2005/Atom',
+ 'xmlns:thr' => 'http://purl.org/syndication/thread/1.0');
+ } else {
+ $attrs = array();
+ }
+
+ $xs->elementStart('entry', $attrs);
+
+ if ($source) {
+ $xs->elementStart('source');
+ $xs->element('title', null, $profile->nickname . " - " . common_config('site', 'name'));
+ $xs->element('link', array('href' => $this->permalink()));
+ }
+
+ if ($source) {
+ $xs->elementEnd('source');
+ }
+
+ $xs->element('title', null, $this->nickname);
+ $xs->element('summary', null, $this->description);
+
+ $xs->element('link', array('rel' => 'alternate',
+ 'href' => $this->permalink()));
+
+ $xs->element('id', null, $this->permalink());
+
+ $xs->element('published', null, common_date_w3dtf($this->created));
+ $xs->element('updated', null, common_date_w3dtf($this->modified));
+
+ $xs->element('content', array('type' => 'html'), $this->description);
+
+ $xs->elementEnd('entry');
+
+ return $xs->getString();
+ }
}
diff --git a/classes/laconica.ini b/classes/laconica.ini
deleted file mode 100644
index 766bed75d..000000000
--- a/classes/laconica.ini
+++ /dev/null
@@ -1,500 +0,0 @@
-
-[avatar]
-profile_id = 129
-original = 17
-width = 129
-height = 129
-mediatype = 130
-filename = 2
-url = 2
-created = 142
-modified = 384
-
-[avatar__keys]
-profile_id = K
-width = K
-height = K
-url = U
-
-[confirm_address]
-code = 130
-user_id = 129
-address = 130
-address_extra = 130
-address_type = 130
-claimed = 14
-sent = 14
-modified = 384
-
-[confirm_address__keys]
-code = K
-
-[consumer]
-consumer_key = 130
-seed = 130
-created = 142
-modified = 384
-
-[consumer__keys]
-consumer_key = K
-
-[design]
-id = 129
-backgroundcolor = 1
-contentcolor = 1
-sidebarcolor = 1
-textcolor = 1
-linkcolor = 1
-backgroundimage = 2
-disposition = 17
-
-[design__keys]
-id = N
-
-[fave]
-notice_id = 129
-user_id = 129
-modified = 384
-
-[fave__keys]
-notice_id = K
-user_id = K
-
-[file]
-id = 129
-url = 2
-mimetype = 2
-size = 1
-title = 2
-date = 1
-protected = 1
-filename = 2
-modified = 384
-
-[file__keys]
-id = N
-
-[file_oembed]
-file_id = 129
-version = 2
-type = 2
-provider = 2
-provider_url = 2
-width = 1
-height = 1
-html = 34
-title = 2
-author_name = 2
-author_url = 2
-url = 2
-modified = 384
-
-[file_oembed__keys]
-file_id = K
-
-[file_redirection]
-url = 130
-file_id = 1
-redirections = 1
-httpcode = 1
-modified = 384
-
-[file_redirection__keys]
-url = K
-
-[file_thumbnail]
-file_id = 129
-url = 2
-width = 1
-height = 1
-modified = 384
-
-[file_thumbnail__keys]
-file_id = K
-url = U
-
-[file_to_post]
-file_id = 129
-post_id = 129
-modified = 384
-
-[file_to_post__keys]
-file_id = K
-post_id = K
-
-[foreign_link]
-user_id = 129
-foreign_id = 129
-service = 129
-credentials = 2
-noticesync = 145
-friendsync = 145
-profilesync = 145
-last_noticesync = 14
-last_friendsync = 14
-created = 142
-modified = 384
-
-[foreign_link__keys]
-user_id = K
-foreign_id = K
-service = K
-
-[foreign_service]
-id = 129
-name = 130
-description = 2
-created = 142
-modified = 384
-
-[foreign_service__keys]
-id = K
-name = U
-
-[foreign_subscription]
-service = 129
-subscriber = 129
-subscribed = 129
-created = 142
-
-[foreign_subscription__keys]
-service = K
-subscriber = K
-subscribed = K
-
-[foreign_user]
-id = 129
-service = 129
-uri = 130
-nickname = 2
-created = 142
-modified = 384
-
-[foreign_user__keys]
-id = K
-service = K
-uri = U
-
-[group_alias]
-alias = 130
-group_id = 129
-modified = 384
-
-[group_alias__keys]
-alias = K
-
-[group_block]
-group_id = 129
-blocked = 129
-blocker = 129
-modified = 384
-
-[group_block__keys]
-group_id = K
-blocked = K
-
-[group_inbox]
-group_id = 129
-notice_id = 129
-created = 142
-
-[group_inbox__keys]
-group_id = K
-notice_id = K
-
-[group_member]
-group_id = 129
-profile_id = 129
-is_admin = 17
-created = 142
-modified = 384
-
-[group_member__keys]
-group_id = K
-profile_id = K
-
-[invitation]
-code = 130
-user_id = 129
-address = 130
-address_type = 130
-created = 142
-
-[invitation__keys]
-code = K
-
-[message]
-id = 129
-uri = 2
-from_profile = 129
-to_profile = 129
-content = 2
-rendered = 34
-url = 2
-created = 142
-modified = 384
-source = 2
-
-[message__keys]
-id = N
-
-[nonce]
-consumer_key = 130
-tok = 2
-nonce = 130
-ts = 142
-created = 142
-modified = 384
-
-[nonce__keys]
-consumer_key = K
-nonce = K
-ts = K
-
-[notice]
-id = 129
-profile_id = 129
-uri = 2
-content = 2
-rendered = 34
-url = 2
-created = 142
-modified = 384
-reply_to = 1
-is_local = 17
-source = 2
-conversation = 1
-
-[notice__keys]
-id = N
-
-[notice_inbox]
-user_id = 129
-notice_id = 129
-created = 142
-source = 17
-
-[notice_inbox__keys]
-user_id = K
-notice_id = K
-
-[notice_source]
-code = 130
-name = 130
-url = 130
-created = 142
-modified = 384
-
-[notice_source__keys]
-code = K
-
-[notice_tag]
-tag = 130
-notice_id = 129
-created = 142
-
-[notice_tag__keys]
-tag = K
-notice_id = K
-
-[profile]
-id = 129
-nickname = 130
-fullname = 2
-profileurl = 2
-homepage = 2
-bio = 2
-location = 2
-created = 142
-modified = 384
-
-[profile__keys]
-id = N
-
-[profile_block]
-blocker = 129
-blocked = 129
-modified = 384
-
-[profile_block__keys]
-blocker = K
-blocked = K
-
-[profile_tag]
-tagger = 129
-tagged = 129
-tag = 130
-modified = 384
-
-[profile_tag__keys]
-tagger = K
-tagged = K
-tag = K
-
-[queue_item]
-notice_id = 129
-transport = 130
-created = 142
-claimed = 14
-
-[queue_item__keys]
-notice_id = K
-transport = K
-
-[related_group]
-group_id = 129
-related_group_id = 129
-created = 142
-
-[related_group__keys]
-group_id = K
-related_group_id = K
-
-[remember_me]
-code = 130
-user_id = 129
-modified = 384
-
-[remember_me__keys]
-code = K
-
-[remote_profile]
-id = 129
-uri = 2
-postnoticeurl = 2
-updateprofileurl = 2
-created = 142
-modified = 384
-
-[remote_profile__keys]
-id = K
-uri = U
-
-[reply]
-notice_id = 129
-profile_id = 129
-modified = 384
-replied_id = 1
-
-[reply__keys]
-notice_id = K
-profile_id = K
-
-[session]
-id = 130
-session_data = 34
-created = 142
-modified = 384
-
-[session__keys]
-id = K
-
-[sms_carrier]
-id = 129
-name = 2
-email_pattern = 130
-created = 142
-modified = 384
-
-[sms_carrier__keys]
-id = K
-name = U
-
-[subscription]
-subscriber = 129
-subscribed = 129
-jabber = 17
-sms = 17
-token = 2
-secret = 2
-created = 142
-modified = 384
-
-[subscription__keys]
-subscriber = K
-subscribed = K
-
-[token]
-consumer_key = 130
-tok = 130
-secret = 130
-type = 145
-state = 17
-created = 142
-modified = 384
-
-[token__keys]
-consumer_key = K
-tok = K
-
-[user]
-id = 129
-nickname = 2
-password = 2
-email = 2
-incomingemail = 2
-emailnotifysub = 17
-emailnotifyfav = 17
-emailnotifynudge = 17
-emailnotifymsg = 17
-emailnotifyattn = 17
-emailmicroid = 17
-language = 2
-timezone = 2
-emailpost = 17
-jabber = 2
-jabbernotify = 17
-jabberreplies = 17
-jabbermicroid = 17
-updatefrompresence = 17
-sms = 2
-carrier = 1
-smsnotify = 17
-smsreplies = 17
-smsemail = 2
-uri = 2
-autosubscribe = 17
-urlshorteningservice = 2
-inboxed = 17
-design_id = 1
-viewdesigns = 17
-created = 142
-modified = 384
-
-[user__keys]
-id = K
-nickname = U
-email = U
-incomingemail = U
-jabber = U
-sms = U
-uri = U
-
-[user_group]
-id = 129
-nickname = 2
-fullname = 2
-homepage = 2
-description = 2
-location = 2
-original_logo = 2
-homepage_logo = 2
-stream_logo = 2
-mini_logo = 2
-design_id = 1
-created = 142
-modified = 384
-
-[user_group__keys]
-id = N
-
-[user_openid]
-canonical = 130
-display = 130
-user_id = 129
-created = 142
-modified = 384
-
-[user_openid__keys]
-canonical = K
-display = U
diff --git a/classes/status_network.ini b/classes/status_network.ini
new file mode 100644
index 000000000..8123265e4
--- /dev/null
+++ b/classes/status_network.ini
@@ -0,0 +1,18 @@
+[status_network]
+nickname = 130
+hostname = 2
+pathname = 2
+dbhost = 2
+dbuser = 2
+dbpass = 2
+dbname = 2
+sitename = 2
+theme = 2
+logo = 2
+created = 142
+modified = 384
+
+[status_network__keys]
+nickname = K
+hostname = U
+pathname = U
diff --git a/classes/statusnet.ini b/classes/statusnet.ini
index 8123265e4..766bed75d 100644
--- a/classes/statusnet.ini
+++ b/classes/statusnet.ini
@@ -1,18 +1,500 @@
-[status_network]
+
+[avatar]
+profile_id = 129
+original = 17
+width = 129
+height = 129
+mediatype = 130
+filename = 2
+url = 2
+created = 142
+modified = 384
+
+[avatar__keys]
+profile_id = K
+width = K
+height = K
+url = U
+
+[confirm_address]
+code = 130
+user_id = 129
+address = 130
+address_extra = 130
+address_type = 130
+claimed = 14
+sent = 14
+modified = 384
+
+[confirm_address__keys]
+code = K
+
+[consumer]
+consumer_key = 130
+seed = 130
+created = 142
+modified = 384
+
+[consumer__keys]
+consumer_key = K
+
+[design]
+id = 129
+backgroundcolor = 1
+contentcolor = 1
+sidebarcolor = 1
+textcolor = 1
+linkcolor = 1
+backgroundimage = 2
+disposition = 17
+
+[design__keys]
+id = N
+
+[fave]
+notice_id = 129
+user_id = 129
+modified = 384
+
+[fave__keys]
+notice_id = K
+user_id = K
+
+[file]
+id = 129
+url = 2
+mimetype = 2
+size = 1
+title = 2
+date = 1
+protected = 1
+filename = 2
+modified = 384
+
+[file__keys]
+id = N
+
+[file_oembed]
+file_id = 129
+version = 2
+type = 2
+provider = 2
+provider_url = 2
+width = 1
+height = 1
+html = 34
+title = 2
+author_name = 2
+author_url = 2
+url = 2
+modified = 384
+
+[file_oembed__keys]
+file_id = K
+
+[file_redirection]
+url = 130
+file_id = 1
+redirections = 1
+httpcode = 1
+modified = 384
+
+[file_redirection__keys]
+url = K
+
+[file_thumbnail]
+file_id = 129
+url = 2
+width = 1
+height = 1
+modified = 384
+
+[file_thumbnail__keys]
+file_id = K
+url = U
+
+[file_to_post]
+file_id = 129
+post_id = 129
+modified = 384
+
+[file_to_post__keys]
+file_id = K
+post_id = K
+
+[foreign_link]
+user_id = 129
+foreign_id = 129
+service = 129
+credentials = 2
+noticesync = 145
+friendsync = 145
+profilesync = 145
+last_noticesync = 14
+last_friendsync = 14
+created = 142
+modified = 384
+
+[foreign_link__keys]
+user_id = K
+foreign_id = K
+service = K
+
+[foreign_service]
+id = 129
+name = 130
+description = 2
+created = 142
+modified = 384
+
+[foreign_service__keys]
+id = K
+name = U
+
+[foreign_subscription]
+service = 129
+subscriber = 129
+subscribed = 129
+created = 142
+
+[foreign_subscription__keys]
+service = K
+subscriber = K
+subscribed = K
+
+[foreign_user]
+id = 129
+service = 129
+uri = 130
+nickname = 2
+created = 142
+modified = 384
+
+[foreign_user__keys]
+id = K
+service = K
+uri = U
+
+[group_alias]
+alias = 130
+group_id = 129
+modified = 384
+
+[group_alias__keys]
+alias = K
+
+[group_block]
+group_id = 129
+blocked = 129
+blocker = 129
+modified = 384
+
+[group_block__keys]
+group_id = K
+blocked = K
+
+[group_inbox]
+group_id = 129
+notice_id = 129
+created = 142
+
+[group_inbox__keys]
+group_id = K
+notice_id = K
+
+[group_member]
+group_id = 129
+profile_id = 129
+is_admin = 17
+created = 142
+modified = 384
+
+[group_member__keys]
+group_id = K
+profile_id = K
+
+[invitation]
+code = 130
+user_id = 129
+address = 130
+address_type = 130
+created = 142
+
+[invitation__keys]
+code = K
+
+[message]
+id = 129
+uri = 2
+from_profile = 129
+to_profile = 129
+content = 2
+rendered = 34
+url = 2
+created = 142
+modified = 384
+source = 2
+
+[message__keys]
+id = N
+
+[nonce]
+consumer_key = 130
+tok = 2
+nonce = 130
+ts = 142
+created = 142
+modified = 384
+
+[nonce__keys]
+consumer_key = K
+nonce = K
+ts = K
+
+[notice]
+id = 129
+profile_id = 129
+uri = 2
+content = 2
+rendered = 34
+url = 2
+created = 142
+modified = 384
+reply_to = 1
+is_local = 17
+source = 2
+conversation = 1
+
+[notice__keys]
+id = N
+
+[notice_inbox]
+user_id = 129
+notice_id = 129
+created = 142
+source = 17
+
+[notice_inbox__keys]
+user_id = K
+notice_id = K
+
+[notice_source]
+code = 130
+name = 130
+url = 130
+created = 142
+modified = 384
+
+[notice_source__keys]
+code = K
+
+[notice_tag]
+tag = 130
+notice_id = 129
+created = 142
+
+[notice_tag__keys]
+tag = K
+notice_id = K
+
+[profile]
+id = 129
nickname = 130
-hostname = 2
-pathname = 2
-dbhost = 2
-dbuser = 2
-dbpass = 2
-dbname = 2
-sitename = 2
-theme = 2
-logo = 2
-created = 142
-modified = 384
-
-[status_network__keys]
-nickname = K
-hostname = U
-pathname = U
+fullname = 2
+profileurl = 2
+homepage = 2
+bio = 2
+location = 2
+created = 142
+modified = 384
+
+[profile__keys]
+id = N
+
+[profile_block]
+blocker = 129
+blocked = 129
+modified = 384
+
+[profile_block__keys]
+blocker = K
+blocked = K
+
+[profile_tag]
+tagger = 129
+tagged = 129
+tag = 130
+modified = 384
+
+[profile_tag__keys]
+tagger = K
+tagged = K
+tag = K
+
+[queue_item]
+notice_id = 129
+transport = 130
+created = 142
+claimed = 14
+
+[queue_item__keys]
+notice_id = K
+transport = K
+
+[related_group]
+group_id = 129
+related_group_id = 129
+created = 142
+
+[related_group__keys]
+group_id = K
+related_group_id = K
+
+[remember_me]
+code = 130
+user_id = 129
+modified = 384
+
+[remember_me__keys]
+code = K
+
+[remote_profile]
+id = 129
+uri = 2
+postnoticeurl = 2
+updateprofileurl = 2
+created = 142
+modified = 384
+
+[remote_profile__keys]
+id = K
+uri = U
+
+[reply]
+notice_id = 129
+profile_id = 129
+modified = 384
+replied_id = 1
+
+[reply__keys]
+notice_id = K
+profile_id = K
+
+[session]
+id = 130
+session_data = 34
+created = 142
+modified = 384
+
+[session__keys]
+id = K
+
+[sms_carrier]
+id = 129
+name = 2
+email_pattern = 130
+created = 142
+modified = 384
+
+[sms_carrier__keys]
+id = K
+name = U
+
+[subscription]
+subscriber = 129
+subscribed = 129
+jabber = 17
+sms = 17
+token = 2
+secret = 2
+created = 142
+modified = 384
+
+[subscription__keys]
+subscriber = K
+subscribed = K
+
+[token]
+consumer_key = 130
+tok = 130
+secret = 130
+type = 145
+state = 17
+created = 142
+modified = 384
+
+[token__keys]
+consumer_key = K
+tok = K
+
+[user]
+id = 129
+nickname = 2
+password = 2
+email = 2
+incomingemail = 2
+emailnotifysub = 17
+emailnotifyfav = 17
+emailnotifynudge = 17
+emailnotifymsg = 17
+emailnotifyattn = 17
+emailmicroid = 17
+language = 2
+timezone = 2
+emailpost = 17
+jabber = 2
+jabbernotify = 17
+jabberreplies = 17
+jabbermicroid = 17
+updatefrompresence = 17
+sms = 2
+carrier = 1
+smsnotify = 17
+smsreplies = 17
+smsemail = 2
+uri = 2
+autosubscribe = 17
+urlshorteningservice = 2
+inboxed = 17
+design_id = 1
+viewdesigns = 17
+created = 142
+modified = 384
+
+[user__keys]
+id = K
+nickname = U
+email = U
+incomingemail = U
+jabber = U
+sms = U
+uri = U
+
+[user_group]
+id = 129
+nickname = 2
+fullname = 2
+homepage = 2
+description = 2
+location = 2
+original_logo = 2
+homepage_logo = 2
+stream_logo = 2
+mini_logo = 2
+design_id = 1
+created = 142
+modified = 384
+
+[user_group__keys]
+id = N
+
+[user_openid]
+canonical = 130
+display = 130
+user_id = 129
+created = 142
+modified = 384
+
+[user_openid__keys]
+canonical = K
+display = U
diff --git a/classes/laconica.links.ini b/classes/statusnet.links.ini
index 95c63f3c0..95c63f3c0 100644
--- a/classes/laconica.links.ini
+++ b/classes/statusnet.links.ini