diff --git a/README b/README
index 8fb4a941cf..57ff72f665 100644
--- a/README
+++ b/README
@@ -1008,6 +1008,12 @@ avatar
For configuring avatar access.
+dir: Directory to look for avatar files and to put them into.
+ Defaults to avatar subdirectory of install directory; if
+ you change it, make sure to change path, too.
+path: Path to avatars. Defaults to path for avatar subdirectory,
+ but you can change it if you wish. Note that this will
+ be included with the avatar server, too.
server: If set, defines another server where avatars are stored in the
root directory. Note that the 'avatar' subdir still has to be
writeable. You'd typically use this to split HTTP requests on
@@ -1100,6 +1106,13 @@ database data in memcached .
enabled: Set to true to enable. Default false.
server: a string with the hostname of the memcached server. Can also
be an array of hostnames, if you've got more than one server.
+base: memcached uses key-value pairs to store data. We build long,
+ funny-looking keys to make sure we don't have any conflicts. The
+ base of the key is usually a simplified version of the site name
+ (like "Identi.ca" => "identica"), but you can overwrite this if
+ you need to. You can safely ignore it if you only have one
+ Laconica site using your memcached server.
+port: Port to connect to; defaults to 11211.
sphinx
------
diff --git a/actions/groups.php b/actions/groups.php
index 26b52a5fcd..b49d80f377 100644
--- a/actions/groups.php
+++ b/actions/groups.php
@@ -100,11 +100,13 @@ class GroupsAction extends Action
function showContent()
{
- $this->elementStart('p', array('id' => 'new_group'));
- $this->element('a', array('href' => common_local_url('newgroup'),
- 'class' => 'more'),
- _('Create a new group'));
- $this->elementEnd('p');
+ if (common_logged_in()) {
+ $this->elementStart('p', array('id' => 'new_group'));
+ $this->element('a', array('href' => common_local_url('newgroup'),
+ 'class' => 'more'),
+ _('Create a new group'));
+ $this->elementEnd('p');
+ }
$offset = ($this->page-1) * GROUPS_PER_PAGE;
$limit = GROUPS_PER_PAGE + 1;
diff --git a/actions/twitapiusers.php b/actions/twitapiusers.php
index 13a8746cd0..21a56a9a58 100644
--- a/actions/twitapiusers.php
+++ b/actions/twitapiusers.php
@@ -58,7 +58,7 @@ class TwitapiusersAction extends TwitterapiAction
return;
}
- $twitter_user = $this->twitter_user_array($profile, true);
+ $twitter_user = $this->twitter_user_array($user->getProfile(), true);
if ($apidata['content-type'] == 'xml') {
$this->init_document('xml');
diff --git a/classes/Avatar.php b/classes/Avatar.php
index db9d78e47f..5e8b315fe6 100644
--- a/classes/Avatar.php
+++ b/classes/Avatar.php
@@ -55,19 +55,43 @@ class Avatar extends Memcached_DataObject
static function path($filename)
{
- return INSTALLDIR . '/avatar/' . $filename;
+ $dir = common_config('avatar', 'dir');
+
+ if ($dir[strlen($dir)-1] != '/') {
+ $dir .= '/';
+ }
+
+ return $dir . $filename;
}
static function url($filename)
{
- return common_path('avatar/'.$filename);
+ $path = common_config('avatar', 'path');
+
+ if ($path[strlen($path)-1] != '/') {
+ $path .= '/';
+ }
+
+ if ($path[0] != '/') {
+ $path = '/'.$path;
+ }
+
+ $server = common_config('avatar', 'server');
+
+ if (empty($server)) {
+ $server = common_config('site', 'server');
+ }
+
+ // XXX: protocol
+
+ return 'http://'.$server.$path.$filename;
}
function displayUrl()
{
$server = common_config('avatar', 'server');
if ($server) {
- return 'http://'.$server.'/'.$this->filename;
+ return Avatar::url($this->filename);
} else {
return $this->url;
}
diff --git a/classes/Status_network.php b/classes/Status_network.php
index d2b942bfb1..17b6887408 100644
--- a/classes/Status_network.php
+++ b/classes/Status_network.php
@@ -43,17 +43,27 @@ class Status_network extends DB_DataObject
{
global $config;
+ $sn = null;
+
// XXX I18N, probably not crucial for hostnames
// XXX This probably needs a tune up
if (0 == strncasecmp(strrev($wildcard), strrev($servername), strlen($wildcard))) {
- $parts = explode('.', $servername);
- $sn = Status_network::staticGet('nickname', strtolower($parts[0]));
+ // special case for exact match
+ if (0 == strcasecmp($servername, $wildcard)) {
+ $sn = Status_network::staticGet('nickname', '');
+ } else {
+ $parts = explode('.', $servername);
+ $sn = Status_network::staticGet('nickname', strtolower($parts[0]));
+ }
} else {
$sn = Status_network::staticGet('hostname', strtolower($servername));
}
if (!empty($sn)) {
+ if (!empty($sn->hostname) && 0 != strcasecmp($sn->hostname, $servername)) {
+ $sn->redirectToHostname();
+ }
$dbhost = (empty($sn->dbhost)) ? 'localhost' : $sn->dbhost;
$dbuser = (empty($sn->dbuser)) ? $sn->nickname : $sn->dbuser;
$dbpass = $sn->dbpass;
@@ -70,9 +80,37 @@ class Status_network extends DB_DataObject
$config['site']['logo'] = $sn->logo;
}
- return true;
+ return $sn;
} else {
- return false;
+ return null;
}
}
+
+ // Code partially mooked from http://www.richler.de/en/php-redirect/
+ // (C) 2006 by Heiko Richler http://www.richler.de/
+ // LGPL
+
+ function redirectToHostname()
+ {
+ $destination = 'http://'.$this->hostname;
+ $destination .= $_SERVER['REQUEST_URI'];
+
+ $old = 'http'.
+ (($_SERVER['HTTPS'] == 'on') ? 'S' : '').
+ '://'.
+ $_SERVER['HTTP_HOST'].
+ $_SERVER['REQUEST_URI'].
+ $_SERVER['QUERY_STRING'];
+ if ($old == $destination) { // this would be a loop!
+ // error_log(...) ?
+ return false;
+ }
+
+ header('HTTP/1.1 301 Moved Permanently');
+ header("Location: $destination");
+
+ print "$destination\n";
+
+ exit;
+ }
}
diff --git a/lib/common.php b/lib/common.php
index eb3bf4e4dc..1381d80477 100644
--- a/lib/common.php
+++ b/lib/common.php
@@ -116,7 +116,9 @@ $config =
'profile' =>
array('banned' => array()),
'avatar' =>
- array('server' => null),
+ array('server' => null,
+ 'dir' => INSTALLDIR . '/avatar/',
+ 'path' => $_path . '/avatar/'),
'public' =>
array('localonly' => true,
'blacklist' => array(),
@@ -158,6 +160,7 @@ $config =
'memcached' =>
array('enabled' => false,
'server' => 'localhost',
+ 'base' => null,
'port' => 11211),
'ping' =>
array('notify' => array()),
diff --git a/lib/util.php b/lib/util.php
index 49c6ae108e..1d5708bd69 100644
--- a/lib/util.php
+++ b/lib/util.php
@@ -1322,7 +1322,13 @@ function common_session_token()
function common_cache_key($extra)
{
- return 'laconica:' . common_keyize(common_config('site', 'name')) . ':' . $extra;
+ $base_key = common_config('memcached', 'base');
+
+ if (empty($base_key)) {
+ $base_key = common_keyize(common_config('site', 'name'));
+ }
+
+ return 'laconica:' . $base_key . ':' . $extra;
}
function common_keyize($str)
diff --git a/scripts/setup.cfg.sample b/scripts/setup.cfg.sample
new file mode 100644
index 0000000000..4194bc146d
--- /dev/null
+++ b/scripts/setup.cfg.sample
@@ -0,0 +1,11 @@
+# CONFIGURATION FILE for setup_status_network.sh
+
+# Base database name; full name will include nickname
+
+export DBBASE=_example_net
+export USERBASE=_example_net
+export ADMIN=root
+export ADMINPASS=yourpassword
+export SITEDB=example_net_site
+export AVATARBASE=/var/www/avatar.example.net
+
diff --git a/scripts/setup_status_network.sh b/scripts/setup_status_network.sh
new file mode 100755
index 0000000000..d80612b940
--- /dev/null
+++ b/scripts/setup_status_network.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+source ./setup.cfg
+
+export nickname=$1
+export sitename=$2
+
+export password=`pwgen 20`
+export database=$nickname$DBBASE
+export username=$nickname$USERBASE
+
+# Create the db
+
+mysqladmin -u $ADMIN --password=$ADMINPASS create $database
+
+for f in laconica.sql sms_carrier.sql foreign_services.sql notice_source.sql; do
+ mysql -u $ADMIN --password=$ADMINPASS $database < ../db/$f;
+done
+
+mysql -u $ADMIN --password=$ADMINPASS $SITEDB << ENDOFCOMMANDS
+
+GRANT INSERT,SELECT,UPDATE,DELETE ON $database.* TO '$username'@'localhost' IDENTIFIED BY '$password';
+GRANT INSERT,SELECT,UPDATE,DELETE ON $database.* TO '$username'@'%' IDENTIFIED BY '$password';
+INSERT INTO status_network (nickname, dbhost, dbuser, dbpass, dbname, sitename, created)
+VALUES ('$nickname', '$DBHOST', '$username', '$password', '$database', '$sitename', now());
+
+ENDOFCOMMANDS
+
+mkdir $AVATARBASE/$nickname
+chmod a+w $AVATARBASE/$nickname