summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README3
-rw-r--r--actions/finishopenidlogin.php33
-rw-r--r--actions/grouprss.php2
-rw-r--r--actions/profilesettings.php343
-rw-r--r--actions/register.php401
-rw-r--r--actions/showgroup.php4
-rw-r--r--actions/subscribers.php10
-rw-r--r--actions/subscriptions.php10
-rw-r--r--db/laconica.sql1
-rw-r--r--js/util.js28
-rw-r--r--lib/personalgroupnav.php68
-rw-r--r--lib/searchaction.php2
-rw-r--r--lib/subpeopletagcloudsection.php76
-rw-r--r--lib/subscriberspeopleselftagcloudsection.php54
-rw-r--r--lib/subscriberspeopletagcloudsection.php60
-rw-r--r--lib/subscriptionspeopleselftagcloudsection.php54
-rw-r--r--lib/subscriptionspeopletagcloudsection.php59
-rw-r--r--lib/twitterapi.php2
-rw-r--r--lib/util.php1
-rwxr-xr-xscripts/jabberqueuehandler.php9
-rwxr-xr-xscripts/publicqueuehandler.php7
-rwxr-xr-xscripts/xmppconfirmhandler.php7
-rwxr-xr-xscripts/xmppdaemon.php7
-rw-r--r--theme/earthy/css/base.css1188
-rw-r--r--theme/earthy/css/display.css251
-rw-r--r--theme/earthy/css/ie.css9
-rw-r--r--theme/earthy/default-avatar-mini.pngbin0 -> 646 bytes
-rw-r--r--theme/earthy/default-avatar-profile.pngbin0 -> 2853 bytes
-rw-r--r--theme/earthy/default-avatar-stream.pngbin0 -> 1487 bytes
-rw-r--r--theme/earthy/logo.pngbin0 -> 4988 bytes
-rw-r--r--theme/otalk/css/base.css1205
-rw-r--r--theme/otalk/css/display.css293
-rw-r--r--theme/otalk/css/ie.css9
-rw-r--r--theme/otalk/default-avatar-mini.pngbin0 -> 646 bytes
-rw-r--r--theme/otalk/default-avatar-profile.pngbin0 -> 2853 bytes
-rw-r--r--theme/otalk/default-avatar-stream.pngbin0 -> 1487 bytes
-rw-r--r--theme/otalk/images/illustrations/illu_arrow-left-01.gifbin0 -> 75 bytes
-rw-r--r--theme/otalk/images/illustrations/illu_pattern-01.pngbin0 -> 3218 bytes
-rw-r--r--theme/otalk/logo.pngbin0 -> 4988 bytes
39 files changed, 3793 insertions, 403 deletions
diff --git a/README b/README
index 29a1e157a..4f9382960 100644
--- a/README
+++ b/README
@@ -1133,6 +1133,9 @@ welcome: nickname of a user account that sends welcome messages to new
busy servers it may be a good idea to keep that one just for
'urgent' messages. Default is null; no message.
+If either of these special user accounts are specified, the users should
+be created before the configuration is updated.
+
Troubleshooting
===============
diff --git a/actions/finishopenidlogin.php b/actions/finishopenidlogin.php
index 952185742..b08b96df6 100644
--- a/actions/finishopenidlogin.php
+++ b/actions/finishopenidlogin.php
@@ -191,11 +191,28 @@ class FinishopenidloginAction extends Action
{
# FIXME: save invite code before redirect, and check here
- if (common_config('site', 'closed') || common_config('site', 'inviteonly')) {
+ if (common_config('site', 'closed')) {
$this->clientError(_('Registration not allowed.'));
return;
}
+ $invite = null;
+
+ if (common_config('site', 'inviteonly')) {
+ $code = $_SESSION['invitecode'];
+ if (empty($code)) {
+ $this->clientError(_('Registration not allowed.'));
+ return;
+ }
+
+ $invite = Invitation::staticGet($code);
+
+ if (empty($invite)) {
+ $this->clientError(_('Not a valid invitation code.'));
+ return;
+ }
+ }
+
$nickname = $this->trimmed('newname');
if (!Validate::string($nickname, array('min_length' => 1,
@@ -257,10 +274,16 @@ class FinishopenidloginAction extends Action
# XXX: add language
# XXX: add timezone
- $user = User::register(array('nickname' => $nickname,
- 'email' => $email,
- 'fullname' => $fullname,
- 'location' => $location));
+ $args = array('nickname' => $nickname,
+ 'email' => $email,
+ 'fullname' => $fullname,
+ 'location' => $location);
+
+ if (!empty($invite)) {
+ $args['code'] = $invite->code;
+ }
+
+ $user = User::register($args);
$result = oid_link_user($user->id, $canonical, $display);
diff --git a/actions/grouprss.php b/actions/grouprss.php
index a9a2eef87..0b7280a11 100644
--- a/actions/grouprss.php
+++ b/actions/grouprss.php
@@ -34,7 +34,7 @@ if (!defined('LACONICA')) {
require_once INSTALLDIR.'/lib/rssaction.php';
-define('MEMBERS_PER_SECTION', 81);
+define('MEMBERS_PER_SECTION', 27);
/**
* Group RSS feed
diff --git a/actions/profilesettings.php b/actions/profilesettings.php
index 60f7c0796..fb847680b 100644
--- a/actions/profilesettings.php
+++ b/actions/profilesettings.php
@@ -91,67 +91,68 @@ class ProfilesettingsAction extends AccountSettingsAction
$this->element('legend', null, _('Profile information'));
$this->hidden('token', common_session_token());
- # too much common patterns here... abstractable?
-
+ // too much common patterns here... abstractable?
$this->elementStart('ul', 'form_data');
- $this->elementStart('li');
- $this->input('nickname', _('Nickname'),
- ($this->arg('nickname')) ? $this->arg('nickname') : $profile->nickname,
- _('1-64 lowercase letters or numbers, no punctuation or spaces'));
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->input('fullname', _('Full name'),
- ($this->arg('fullname')) ? $this->arg('fullname') : $profile->fullname);
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->input('homepage', _('Homepage'),
- ($this->arg('homepage')) ? $this->arg('homepage') : $profile->homepage,
- _('URL of your homepage, blog, or profile on another site'));
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->textarea('bio', _('Bio'),
- ($this->arg('bio')) ? $this->arg('bio') : $profile->bio,
- _('Describe yourself and your interests in 140 chars'));
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->input('location', _('Location'),
- ($this->arg('location')) ? $this->arg('location') : $profile->location,
- _('Where you are, like "City, State (or Region), Country"'));
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->input('tags', _('Tags'),
- ($this->arg('tags')) ? $this->arg('tags') : implode(' ', $user->getSelfTags()),
- _('Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated'));
- $this->elementEnd('li');
- $this->elementStart('li');
- $language = common_language();
- $this->dropdown('language', _('Language'),
- get_nice_language_list(), _('Preferred language'),
- true, $language);
- $this->elementEnd('li');
- $timezone = common_timezone();
- $timezones = array();
- foreach(DateTimeZone::listIdentifiers() as $k => $v) {
- $timezones[$v] = $v;
+ if (Event::handle('StartProfileFormData', array($this))) {
+ $this->elementStart('li');
+ $this->input('nickname', _('Nickname'),
+ ($this->arg('nickname')) ? $this->arg('nickname') : $profile->nickname,
+ _('1-64 lowercase letters or numbers, no punctuation or spaces'));
+ $this->elementEnd('li');
+ $this->elementStart('li');
+ $this->input('fullname', _('Full name'),
+ ($this->arg('fullname')) ? $this->arg('fullname') : $profile->fullname);
+ $this->elementEnd('li');
+ $this->elementStart('li');
+ $this->input('homepage', _('Homepage'),
+ ($this->arg('homepage')) ? $this->arg('homepage') : $profile->homepage,
+ _('URL of your homepage, blog, or profile on another site'));
+ $this->elementEnd('li');
+ $this->elementStart('li');
+ $this->textarea('bio', _('Bio'),
+ ($this->arg('bio')) ? $this->arg('bio') : $profile->bio,
+ _('Describe yourself and your interests in 140 chars'));
+ $this->elementEnd('li');
+ $this->elementStart('li');
+ $this->input('location', _('Location'),
+ ($this->arg('location')) ? $this->arg('location') : $profile->location,
+ _('Where you are, like "City, State (or Region), Country"'));
+ $this->elementEnd('li');
+ Event::handle('EndProfileFormData', array($this));
+ $this->elementStart('li');
+ $this->input('tags', _('Tags'),
+ ($this->arg('tags')) ? $this->arg('tags') : implode(' ', $user->getSelfTags()),
+ _('Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated'));
+ $this->elementEnd('li');
+ $this->elementStart('li');
+ $language = common_language();
+ $this->dropdown('language', _('Language'),
+ get_nice_language_list(), _('Preferred language'),
+ false, $language);
+ $this->elementEnd('li');
+ $timezone = common_timezone();
+ $timezones = array();
+ foreach(DateTimeZone::listIdentifiers() as $k => $v) {
+ $timezones[$v] = $v;
+ }
+ $this->elementStart('li');
+ $this->dropdown('timezone', _('Timezone'),
+ $timezones, _('What timezone are you normally in?'),
+ true, $timezone);
+ $this->elementEnd('li');
+ $this->elementStart('li');
+ $this->checkbox('autosubscribe',
+ _('Automatically subscribe to whoever '.
+ 'subscribes to me (best for non-humans)'),
+ ($this->arg('autosubscribe')) ?
+ $this->boolean('autosubscribe') : $user->autosubscribe);
+ $this->elementEnd('li');
}
- $this->elementStart('li');
- $this->dropdown('timezone', _('Timezone'),
- $timezones, _('What timezone are you normally in?'),
- true, $timezone);
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->checkbox('autosubscribe',
- _('Automatically subscribe to whoever '.
- 'subscribes to me (best for non-humans)'),
- ($this->arg('autosubscribe')) ?
- $this->boolean('autosubscribe') : $user->autosubscribe);
- $this->elementEnd('li');
$this->elementEnd('ul');
$this->submit('save', _('Save'));
$this->elementEnd('fieldset');
$this->elementEnd('form');
-
}
/**
@@ -165,158 +166,158 @@ class ProfilesettingsAction extends AccountSettingsAction
function handlePost()
{
- # CSRF protection
-
+ // CSRF protection
$token = $this->trimmed('token');
if (!$token || $token != common_session_token()) {
$this->showForm(_('There was a problem with your session token. '.
- 'Try again, please.'));
+ 'Try again, please.'));
return;
}
- $nickname = $this->trimmed('nickname');
- $fullname = $this->trimmed('fullname');
- $homepage = $this->trimmed('homepage');
- $bio = $this->trimmed('bio');
- $location = $this->trimmed('location');
- $autosubscribe = $this->boolean('autosubscribe');
- $language = $this->trimmed('language');
- $timezone = $this->trimmed('timezone');
- $tagstring = $this->trimmed('tags');
-
- # Some validation
-
- if (!Validate::string($nickname, array('min_length' => 1,
- 'max_length' => 64,
- 'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
- $this->showForm(_('Nickname must have only lowercase letters and numbers and no spaces.'));
- return;
- } else if (!User::allowed_nickname($nickname)) {
- $this->showForm(_('Not a valid nickname.'));
- return;
- } else if (!is_null($homepage) && (strlen($homepage) > 0) &&
- !Validate::uri($homepage, array('allowed_schemes' => array('http', 'https')))) {
- $this->showForm(_('Homepage is not a valid URL.'));
- return;
- } else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
- $this->showForm(_('Full name is too long (max 255 chars).'));
- return;
- } else if (!is_null($bio) && mb_strlen($bio) > 140) {
- $this->showForm(_('Bio is too long (max 140 chars).'));
- return;
- } else if (!is_null($location) && mb_strlen($location) > 255) {
- $this->showForm(_('Location is too long (max 255 chars).'));
- return;
- } else if (is_null($timezone) || !in_array($timezone, DateTimeZone::listIdentifiers())) {
- $this->showForm(_('Timezone not selected.'));
- return;
- } else if ($this->nicknameExists($nickname)) {
- $this->showForm(_('Nickname already in use. Try another one.'));
- return;
- } else if (!is_null($language) && strlen($language) > 50) {
- $this->showForm(_('Language is too long (max 50 chars).'));
- return;
- }
+ if (Event::handle('StartProfileSaveForm', array($this))) {
+
+ $nickname = $this->trimmed('nickname');
+ $fullname = $this->trimmed('fullname');
+ $homepage = $this->trimmed('homepage');
+ $bio = $this->trimmed('bio');
+ $location = $this->trimmed('location');
+ $autosubscribe = $this->boolean('autosubscribe');
+ $language = $this->trimmed('language');
+ $timezone = $this->trimmed('timezone');
+ $tagstring = $this->trimmed('tags');
+
+ // Some validation
+ if (!Validate::string($nickname, array('min_length' => 1,
+ 'max_length' => 64,
+ 'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
+ $this->showForm(_('Nickname must have only lowercase letters and numbers and no spaces.'));
+ return;
+ } else if (!User::allowed_nickname($nickname)) {
+ $this->showForm(_('Not a valid nickname.'));
+ return;
+ } else if (!is_null($homepage) && (strlen($homepage) > 0) &&
+ !Validate::uri($homepage, array('allowed_schemes' => array('http', 'https')))) {
+ $this->showForm(_('Homepage is not a valid URL.'));
+ return;
+ } else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
+ $this->showForm(_('Full name is too long (max 255 chars).'));
+ return;
+ } else if (!is_null($bio) && mb_strlen($bio) > 140) {
+ $this->showForm(_('Bio is too long (max 140 chars).'));
+ return;
+ } else if (!is_null($location) && mb_strlen($location) > 255) {
+ $this->showForm(_('Location is too long (max 255 chars).'));
+ return;
+ } else if (is_null($timezone) || !in_array($timezone, DateTimeZone::listIdentifiers())) {
+ $this->showForm(_('Timezone not selected.'));
+ return;
+ } else if ($this->nicknameExists($nickname)) {
+ $this->showForm(_('Nickname already in use. Try another one.'));
+ return;
+ } else if (!is_null($language) && strlen($language) > 50) {
+ $this->showForm(_('Language is too long (max 50 chars).'));
+ return;
+ }
- if ($tagstring) {
- $tags = array_map('common_canonical_tag', preg_split('/[\s,]+/', $tagstring));
- } else {
- $tags = array();
- }
+ if ($tagstring) {
+ $tags = array_map('common_canonical_tag', preg_split('/[\s,]+/', $tagstring));
+ } else {
+ $tags = array();
+ }
- foreach ($tags as $tag) {
- if (!common_valid_profile_tag($tag)) {
- $this->showForm(sprintf(_('Invalid tag: "%s"'), $tag));
- return;
+ foreach ($tags as $tag) {
+ if (!common_valid_profile_tag($tag)) {
+ $this->showForm(sprintf(_('Invalid tag: "%s"'), $tag));
+ return;
+ }
}
- }
- $user = common_current_user();
+ $user = common_current_user();
- $user->query('BEGIN');
+ $user->query('BEGIN');
- if ($user->nickname != $nickname ||
- $user->language != $language ||
- $user->timezone != $timezone) {
+ if ($user->nickname != $nickname ||
+ $user->language != $language ||
+ $user->timezone != $timezone) {
- common_debug('Updating user nickname from ' . $user->nickname . ' to ' . $nickname,
- __FILE__);
- common_debug('Updating user language from ' . $user->language . ' to ' . $language,
- __FILE__);
- common_debug('Updating user timezone from ' . $user->timezone . ' to ' . $timezone,
- __FILE__);
+ common_debug('Updating user nickname from ' . $user->nickname . ' to ' . $nickname,
+ __FILE__);
+ common_debug('Updating user language from ' . $user->language . ' to ' . $language,
+ __FILE__);
+ common_debug('Updating user timezone from ' . $user->timezone . ' to ' . $timezone,
+ __FILE__);
- $original = clone($user);
+ $original = clone($user);
- $user->nickname = $nickname;
- $user->language = $language;
- $user->timezone = $timezone;
+ $user->nickname = $nickname;
+ $user->language = $language;
+ $user->timezone = $timezone;
- $result = $user->updateKeys($original);
+ $result = $user->updateKeys($original);
- if ($result === false) {
- common_log_db_error($user, 'UPDATE', __FILE__);
- $this->serverError(_('Couldn\'t update user.'));
- return;
- } else {
- # Re-initialize language environment if it changed
- common_init_language();
+ if ($result === false) {
+ common_log_db_error($user, 'UPDATE', __FILE__);
+ $this->serverError(_('Couldn\'t update user.'));
+ return;
+ } else {
+ // Re-initialize language environment if it changed
+ common_init_language();
+ }
}
- }
-
- # XXX: XOR
- if ($user->autosubscribe ^ $autosubscribe) {
+// XXX: XOR
+ if ($user->autosubscribe ^ $autosubscribe) {
- $original = clone($user);
+ $original = clone($user);
- $user->autosubscribe = $autosubscribe;
+ $user->autosubscribe = $autosubscribe;
- $result = $user->update($original);
+ $result = $user->update($original);
- if ($result === false) {
- common_log_db_error($user, 'UPDATE', __FILE__);
- $this->serverError(_('Couldn\'t update user for autosubscribe.'));
- return;
+ if ($result === false) {
+ common_log_db_error($user, 'UPDATE', __FILE__);
+ $this->serverError(_('Couldn\'t update user for autosubscribe.'));
+ return;
+ }
}
- }
-
- $profile = $user->getProfile();
- $orig_profile = clone($profile);
+ $profile = $user->getProfile();
- $profile->nickname = $user->nickname;
- $profile->fullname = $fullname;
- $profile->homepage = $homepage;
- $profile->bio = $bio;
- $profile->location = $location;
- $profile->profileurl = common_profile_url($nickname);
+ $orig_profile = clone($profile);
- common_debug('Old profile: ' . common_log_objstring($orig_profile), __FILE__);
- common_debug('New profile: ' . common_log_objstring($profile), __FILE__);
+ $profile->nickname = $user->nickname;
+ $profile->fullname = $fullname;
+ $profile->homepage = $homepage;
+ $profile->bio = $bio;
+ $profile->location = $location;
+ $profile->profileurl = common_profile_url($nickname);
- $result = $profile->update($orig_profile);
+ common_debug('Old profile: ' . common_log_objstring($orig_profile), __FILE__);
+ common_debug('New profile: ' . common_log_objstring($profile), __FILE__);
- if (!$result) {
- common_log_db_error($profile, 'UPDATE', __FILE__);
- $this->serverError(_('Couldn\'t save profile.'));
- return;
- }
+ $result = $profile->update($orig_profile);
- # Set the user tags
+ if (!$result) {
+ common_log_db_error($profile, 'UPDATE', __FILE__);
+ $this->serverError(_('Couldn\'t save profile.'));
+ return;
+ }
- $result = $user->setSelfTags($tags);
+ // Set the user tags
+ $result = $user->setSelfTags($tags);
- if (!$result) {
- $this->serverError(_('Couldn\'t save tags.'));
- return;
- }
+ if (!$result) {
+ $this->serverError(_('Couldn\'t save tags.'));
+ return;
+ }
- $user->query('COMMIT');
+ $user->query('COMMIT');
+ Event::handle('EndProfileSaveForm', array($this));
+ common_broadcast_profile($profile);
- common_broadcast_profile($profile);
+ $this->showForm(_('Settings saved.'), true);
- $this->showForm(_('Settings saved.'), true);
+ }
}
function nicknameExists($nickname)
diff --git a/actions/register.php b/actions/register.php
index 5c6fe39d3..dcbbbdb6a 100644
--- a/actions/register.php
+++ b/actions/register.php
@@ -56,6 +56,45 @@ class RegisterAction extends Action
var $registered = false;
/**
+ * Prepare page to run
+ *
+ *
+ * @param $args
+ * @return string title
+ */
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+ $this->code = $this->trimmed('code');
+
+ if (empty($this->code)) {
+ common_ensure_session();
+ if (array_key_exists('invitecode', $_SESSION)) {
+ $this->code = $_SESSION['invitecode'];
+ }
+ }
+
+ if (common_config('site', 'inviteonly') && empty($this->code)) {
+ $this->clientError(_('Sorry, only invited people can register.'));
+ return false;
+ }
+
+ if (!empty($this->code)) {
+ $this->invite = Invitation::staticGet('code', $this->code);
+ if (empty($this->invite)) {
+ $this->clientError(_('Sorry, invalid invitation code.'));
+ return false;
+ }
+ // Store this in case we need it
+ common_ensure_session();
+ $_SESSION['invitecode'] = $this->code;
+ }
+
+ return true;
+ }
+
+ /**
* Title of the page
*
* @return string title
@@ -108,109 +147,109 @@ class RegisterAction extends Action
function tryRegister()
{
- $token = $this->trimmed('token');
- if (!$token || $token != common_session_token()) {
- $this->showForm(_('There was a problem with your session token. '.
- 'Try again, please.'));
- return;
- }
-
- $nickname = $this->trimmed('nickname');
- $email = $this->trimmed('email');
- $fullname = $this->trimmed('fullname');
- $homepage = $this->trimmed('homepage');
- $bio = $this->trimmed('bio');
- $location = $this->trimmed('location');
-
- // We don't trim these... whitespace is OK in a password!
-
- $password = $this->arg('password');
- $confirm = $this->arg('confirm');
+ if (Event::handle('StartRegistrationTry', array($this))) {
+ $token = $this->trimmed('token');
+ if (!$token || $token != common_session_token()) {
+ $this->showForm(_('There was a problem with your session token. '.
+ 'Try again, please.'));
+ return;
+ }
- // invitation code, if any
+ $nickname = $this->trimmed('nickname');
+ $email = $this->trimmed('email');
+ $fullname = $this->trimmed('fullname');
+ $homepage = $this->trimmed('homepage');
+ $bio = $this->trimmed('bio');
+ $location = $this->trimmed('location');
- $code = $this->trimmed('code');
+ // We don't trim these... whitespace is OK in a password!
+ $password = $this->arg('password');
+ $confirm = $this->arg('confirm');
- $invite = null;
-
- if ($code) {
- $invite = Invitation::staticGet($code);
- }
+ // invitation code, if any
+ $code = $this->trimmed('code');
- if (common_config('site', 'inviteonly') && !($code && !empty($invite))) {
- $this->clientError(_('Sorry, only invited people can register.'));
- return;
- }
+ if ($code) {
+ $invite = Invitation::staticGet($code);
+ }
- // Input scrubbing
-
- $nickname = common_canonical_nickname($nickname);
- $email = common_canonical_email($email);
-
- if (!$this->boolean('license')) {
- $this->showForm(_('You can\'t register if you don\'t '.
- 'agree to the license.'));
- } else if ($email && !Validate::email($email, true)) {
- $this->showForm(_('Not a valid email address.'));
- } else if (!Validate::string($nickname, array('min_length' => 1,
- 'max_length' => 64,
- 'format' => NICKNAME_FMT))) {
- $this->showForm(_('Nickname must have only lowercase letters '.
- 'and numbers and no spaces.'));
- } else if ($this->nicknameExists($nickname)) {
- $this->showForm(_('Nickname already in use. Try another one.'));
- } else if (!User::allowed_nickname($nickname)) {
- $this->showForm(_('Not a valid nickname.'));
- } else if ($this->emailExists($email)) {
- $this->showForm(_('Email address already exists.'));
- } else if (!is_null($homepage) && (strlen($homepage) > 0) &&
- !Validate::uri($homepage,
- array('allowed_schemes' =>
- array('http', 'https')))) {
- $this->showForm(_('Homepage is not a valid URL.'));
- return;
- } else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
- $this->showForm(_('Full name is too long (max 255 chars).'));
- return;
- } else if (!is_null($bio) && mb_strlen($bio) > 140) {
- $this->showForm(_('Bio is too long (max 140 chars).'));
- return;
- } else if (!is_null($location) && mb_strlen($location) > 255) {
- $this->showForm(_('Location is too long (max 255 chars).'));
- return;
- } else if (strlen($password) < 6) {
- $this->showForm(_('Password must be 6 or more characters.'));
- return;
- } else if ($password != $confirm) {
- $this->showForm(_('Passwords don\'t match.'));
- } else if ($user = User::register(array('nickname' => $nickname,
- 'password' => $password,
- 'email' => $email,
- 'fullname' => $fullname,
- 'homepage' => $homepage,
- 'bio' => $bio,
- 'location' => $location,
- 'code' => $code))) {
- if (!$user) {
- $this->showForm(_('Invalid username or password.'));
+ if (common_config('site', 'inviteonly') && !($code && $invite)) {
+ $this->clientError(_('Sorry, only invited people can register.'));
return;
}
- // success!
- if (!common_set_user($user)) {
- $this->serverError(_('Error setting user.'));
+
+ // Input scrubbing
+ $nickname = common_canonical_nickname($nickname);
+ $email = common_canonical_email($email);
+
+ if (!$this->boolean('license')) {
+ $this->showForm(_('You can\'t register if you don\'t '.
+ 'agree to the license.'));
+ } else if ($email && !Validate::email($email, true)) {
+ $this->showForm(_('Not a valid email address.'));
+ } else if (!Validate::string($nickname, array('min_length' => 1,
+ 'max_length' => 64,
+ 'format' => NICKNAME_FMT))) {
+ $this->showForm(_('Nickname must have only lowercase letters '.
+ 'and numbers and no spaces.'));
+ } else if ($this->nicknameExists($nickname)) {
+ $this->showForm(_('Nickname already in use. Try another one.'));
+ } else if (!User::allowed_nickname($nickname)) {
+ $this->showForm(_('Not a valid nickname.'));
+ } else if ($this->emailExists($email)) {
+ $this->showForm(_('Email address already exists.'));
+ } else if (!is_null($homepage) && (strlen($homepage) > 0) &&
+ !Validate::uri($homepage,
+ array('allowed_schemes' =>
+ array('http', 'https')))) {
+ $this->showForm(_('Homepage is not a valid URL.'));
return;
+ } else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
+ $this->showForm(_('Full name is too long (max 255 chars).'));
+ return;
+ } else if (!is_null($bio) && mb_strlen($bio) > 140) {
+ $this->showForm(_('Bio is too long (max 140 chars).'));
+ return;
+ } else if (!is_null($location) && mb_strlen($location) > 255) {
+ $this->showForm(_('Location is too long (max 255 chars).'));
+ return;
+ } else if (strlen($password) < 6) {
+ $this->showForm(_('Password must be 6 or more characters.'));
+ return;
+ } else if ($password != $confirm) {
+ $this->showForm(_('Passwords don\'t match.'));
+ } else if ($user = User::register(array('nickname' => $nickname,
+ 'password' => $password,
+ 'email' => $email,
+ 'fullname' => $fullname,
+ 'homepage' => $homepage,
+ 'bio' => $bio,
+ 'location' => $location,
+ 'code' => $code))) {
+ if (!$user) {
+ $this->showForm(_('Invalid username or password.'));
+ return;
+ }
+ // success!
+ if (!common_set_user($user)) {
+ $this->serverError(_('Error setting user.'));
+ return;
+ }
+ // this is a real login
+ common_real_login(true);
+ if ($this->boolean('rememberme')) {
+ common_debug('Adding rememberme cookie for ' . $nickname);
+ common_rememberme($user);
+ }
+
+ Event::handle('EndRegistrationTry', array($this));
+
+ // Re-init language env in case it changed (not yet, but soon)
+ common_init_language();
+ $this->showSuccess();
+ } else {
+ $this->showForm(_('Invalid username or password.'));
}
- // this is a real login
- common_real_login(true);
- if ($this->boolean('rememberme')) {
- common_debug('Adding rememberme cookie for ' . $nickname);
- common_rememberme($user);
- }
- // Re-init language env in case it changed (not yet, but soon)
- common_init_language();
- $this->showSuccess();
- } else {
- $this->showForm(_('Invalid username or password.'));
}
}
@@ -252,22 +291,24 @@ class RegisterAction extends Action
// overrrided to add entry-title class
function showPageTitle() {
- $this->element('h1', array('class' => 'entry-title'), $this->title());
+ if (Event::handle('StartShowPageTitle', array($this))) {
+ $this->element('h1', array('class' => 'entry-title'), $this->title());
+ }
}
// overrided to add hentry, and content-inner class
function showContentBlock()
- {
- $this->elementStart('div', array('id' => 'content', 'class' => 'hentry'));
- $this->showPageTitle();
- $this->showPageNoticeBlock();
- $this->elementStart('div', array('id' => 'content_inner',
- 'class' => 'entry-content'));
- // show the actual content (forms, lists, whatever)
- $this->showContent();
- $this->elementEnd('div');
- $this->elementEnd('div');
- }
+ {
+ $this->elementStart('div', array('id' => 'content', 'class' => 'hentry'));
+ $this->showPageTitle();
+ $this->showPageNoticeBlock();
+ $this->elementStart('div', array('id' => 'content_inner',
+ 'class' => 'entry-content'));
+ // show the actual content (forms, lists, whatever)
+ $this->showContent();
+ $this->elementEnd('div');
+ $this->elementEnd('div');
+ }
/**
* Instructions or a notice for the page
@@ -362,82 +403,85 @@ class RegisterAction extends Action
$this->element('legend', null, 'Account settings');
$this->hidden('token', common_session_token());
- if ($code) {
- $this->hidden('code', $code);
+ if ($this->code) {
+ $this->hidden('code', $this->code);
}
$this->elementStart('ul', 'form_data');
- $this->elementStart('li');
- $this->input('nickname', _('Nickname'), $this->trimmed('nickname'),
- _('1-64 lowercase letters or numbers, '.
- 'no punctuation or spaces. Required.'));
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->password('password', _('Password'),
- _('6 or more characters. Required.'));
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->password('confirm', _('Confirm'),
- _('Same as password above. Required.'));
- $this->elementEnd('li');
- $this->elementStart('li');
- if (!empty($invite) && $invite->address_type == 'email') {
- $this->input('email', _('Email'), $invite->address,
- _('Used only for updates, announcements, '.
- 'and password recovery'));
- } else {
- $this->input('email', _('Email'), $this->trimmed('email'),
- _('Used only for updates, announcements, '.
- 'and password recovery'));
- }
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->input('fullname', _('Full name'),
- $this->trimmed('fullname'),
- _('Longer name, preferably your "real" name'));
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->input('homepage', _('Homepage'),
- $this->trimmed('homepage'),
- _('URL of your homepage, blog, '.
- 'or profile on another site'));
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->textarea('bio', _('Bio'),
- $this->trimmed('bio'),
- _('Describe yourself and your '.
- 'interests in 140 chars'));
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->input('location', _('Location'),
- $this->trimmed('location'),
- _('Where you are, like "City, '.
- 'State (or Region), Country"'));
- $this->elementEnd('li');
- $this->elementStart('li', array('id' => 'settings_rememberme'));
- $this->checkbox('rememberme', _('Remember me'),
- $this->boolean('rememberme'),
- _('Automatically login in the future; '.
- 'not for shared computers!'));
- $this->elementEnd('li');
- $attrs = array('type' => 'checkbox',
- 'id' => 'license',
- 'class' => 'checkbox',
- 'name' => 'license',
- 'value' => 'true');
- if ($this->boolean('license')) {
- $attrs['checked'] = 'checked';
+ if (Event::handle('StartRegistrationFormData', array($this))) {
+ $this->elementStart('li');
+ $this->input('nickname', _('Nickname'), $this->trimmed('nickname'),
+ _('1-64 lowercase letters or numbers, '.
+ 'no punctuation or spaces. Required.'));
+ $this->elementEnd('li');
+ $this->elementStart('li');
+ $this->password('password', _('Password'),
+ _('6 or more characters. Required.'));
+ $this->elementEnd('li');
+ $this->elementStart('li');
+ $this->password('confirm', _('Confirm'),
+ _('Same as password above. Required.'));
+ $this->elementEnd('li');
+ $this->elementStart('li');
+ if ($this->invite && $this->invite->address_type == 'email') {
+ $this->input('email', _('Email'), $this->invite->address,
+ _('Used only for updates, announcements, '.
+ 'and password recovery'));
+ } else {
+ $this->input('email', _('Email'), $this->trimmed('email'),
+ _('Used only for updates, announcements, '.
+ 'and password recovery'));
+ }
+ $this->elementEnd('li');
+ $this->elementStart('li');
+ $this->input('fullname', _('Full name'),
+ $this->trimmed('fullname'),
+ _('Longer name, preferably your "real" name'));
+ $this->elementEnd('li');
+ $this->elementStart('li');
+ $this->input('homepage', _('Homepage'),
+ $this->trimmed('homepage'),
+ _('URL of your homepage, blog, '.
+ 'or profile on another site'));
+ $this->elementEnd('li');
+ $this->elementStart('li');
+ $this->textarea('bio', _('Bio'),
+ $this->trimmed('bio'),
+ _('Describe yourself and your '.
+ 'interests in 140 chars'));
+ $this->elementEnd('li');
+ $this->elementStart('li');
+ $this->input('location', _('Location'),
+ $this->trimmed('location'),
+ _('Where you are, like "City, '.
+ 'State (or Region), Country"'));
+ $this->elementEnd('li');
+ Event::handle('EndRegistrationFormData', array($this));
+ $this->elementStart('li', array('id' => 'settings_rememberme'));
+ $this->checkbox('rememberme', _('Remember me'),
+ $this->boolean('rememberme'),
+ _('Automatically login in the future; '.
+ 'not for shared computers!'));
+ $this->elementEnd('li');
+ $attrs = array('type' => 'checkbox',
+ 'id' => 'license',
+ 'class' => 'checkbox',
+ 'name' => 'license',
+ 'value' => 'true');
+ if ($this->boolean('license')) {
+ $attrs['checked'] = 'checked';
+ }
+ $this->elementStart('li');
+ $this->element('input', $attrs);
+ $this->elementStart('label', array('class' => 'checkbox', 'for' => 'license'));
+ $this->text(_('My text and files are available under '));
+ $this->element('a', array('href' => common_config('license', 'url')),
+ common_config('license', 'title'), _("Creative Commons Attribution 3.0"));
+ $this->text(_(' except this private data: password, '.
+ 'email address, IM address, and phone number.'));
+ $this->elementEnd('label');
+ $this->elementEnd('li');
}
- $this->elementStart('li');
- $this->element('input', $attrs);
- $this->elementStart('label', array('class' => 'checkbox', 'for' => 'license'));
- $this->text(_('My text and files are available under '));
- $this->element('a', array('href' => common_config('license', 'url')),
- common_config('license', 'title'), _("Creative Commons Attribution 3.0"));
- $this->text(_(' except this private data: password, '.
- 'email address, IM address, and phone number.'));
- $this->elementEnd('label');
- $this->elementEnd('li');
$this->elementEnd('ul');
$this->submit('submit', _('Register'));
$this->elementEnd('fieldset');
@@ -519,3 +563,4 @@ class RegisterAction extends Action
$nav->show();
}
}
+
diff --git a/actions/showgroup.php b/actions/showgroup.php
index 025f8383a..a7df39727 100644
--- a/actions/showgroup.php
+++ b/actions/showgroup.php
@@ -35,7 +35,7 @@ if (!defined('LACONICA')) {
require_once INSTALLDIR.'/lib/noticelist.php';
require_once INSTALLDIR.'/lib/feedlist.php';
-define('MEMBERS_PER_SECTION', 81);
+define('MEMBERS_PER_SECTION', 27);
/**
* Group main page
@@ -361,7 +361,7 @@ class ShowgroupAction extends Action
$this->element('p', null, _('(None)'));
}
- if ($cnt == MEMBERS_PER_SECTION) {
+ if ($cnt > MEMBERS_PER_SECTION) {
$this->element('a', array('href' => common_local_url('groupmembers',
array('nickname' => $this->group->nickname))),
_('All members'));
diff --git a/actions/subscribers.php b/actions/subscribers.php
index d91a7d4fd..4482de9a7 100644
--- a/actions/subscribers.php
+++ b/actions/subscribers.php
@@ -118,6 +118,16 @@ class SubscribersAction extends GalleryAction
$this->raw(common_markup_to_html($message));
$this->elementEnd('div');
}
+
+ function showSections()
+ {
+ parent::showSections();
+ $cloud = new SubscribersPeopleTagCloudSection($this);
+ $cloud->show();
+
+ $cloud2 = new SubscribersPeopleSelfTagCloudSection($this);
+ $cloud2->show();
+ }
}
class SubscribersList extends ProfileList
diff --git a/actions/subscriptions.php b/actions/subscriptions.php
index e6f3c54db..095b18ad8 100644
--- a/actions/subscriptions.php
+++ b/actions/subscriptions.php
@@ -125,6 +125,16 @@ class SubscriptionsAction extends GalleryAction
$this->raw(common_markup_to_html($message));
$this->elementEnd('div');
}
+
+ function showSections()
+ {
+ parent::showSections();
+ $cloud = new SubscriptionsPeopleTagCloudSection($this);
+ $cloud->show();
+
+ $cloud2 = new SubscriptionsPeopleSelfTagCloudSection($this);
+ $cloud2->show();
+ }
}
class SubscriptionsList extends ProfileList
diff --git a/db/laconica.sql b/db/laconica.sql
index 20f0cabd1..83d610f0d 100644
--- a/db/laconica.sql
+++ b/db/laconica.sql
@@ -119,6 +119,7 @@ create table notice (
index notice_profile_id_idx (profile_id),
index notice_conversation_idx (conversation),
index notice_created_idx (created),
+ index notice_replyto_idx (reply_to),
FULLTEXT(content)
) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci;
diff --git a/js/util.js b/js/util.js
index 81139744f..53e6eb792 100644
--- a/js/util.js
+++ b/js/util.js
@@ -166,28 +166,36 @@ $(document).ready(function(){
$("#notice_action-submit").addClass("disabled");
return true;
},
- success: function(xml) { if ($("#error", xml).length > 0 || $("#command_result", xml).length > 0) {
+ success: function(xml) { if ($("#error", xml).length > 0) {
var result = document._importNode($("p", xml).get(0), true);
result = result.textContent || result.innerHTML;
alert(result);
}
else {
- $("#notices_primary .notices").prepend(document._importNode($("li", xml).get(0), true));
+ if ($("#command_result", xml).length > 0) {
+ var result = document._importNode($("p", xml).get(0), true);
+ result = result.textContent || result.innerHTML;
+ alert(result);
+ }
+ else {
+ $("#notices_primary .notices").prepend(document._importNode($("li", xml).get(0), true));
+ $("#notices_primary .notice:first").css({display:"none"});
+ $("#notices_primary .notice:first").fadeIn(2500);
+ NoticeHover();
+ NoticeReply();
+ }
$("#notice_data-text").val("");
- counter();
- $("#notices_primary .notice:first").css({display:"none"});
- $("#notices_primary .notice:first").fadeIn(2500);
- NoticeHover();
- NoticeReply();
+ counter();
}
$("#form_notice").removeClass("processing");
$("#notice_action-submit").removeAttr("disabled");
$("#notice_action-submit").removeClass("disabled");
}
};
- $("#form_notice").ajaxForm(PostNotice);
- $("#form_notice").each(addAjaxHidden);
-
+ if (document.body.id != 'inbox' && document.body.id != 'outbox') {
+ $("#form_notice").ajaxForm(PostNotice);
+ $("#form_notice").each(addAjaxHidden);
+ }
NoticeHover();
NoticeReply();
});
diff --git a/lib/personalgroupnav.php b/lib/personalgroupnav.php
index 63e6138df..acc033667 100644
--- a/lib/personalgroupnav.php
+++ b/lib/personalgroupnav.php
@@ -93,43 +93,45 @@ class PersonalGroupNav extends Widget
$this->out->elementStart('ul', array('class' => 'nav'));
- $this->out->menuItem(common_local_url('all', array('nickname' =>
- $nickname)),
- _('Personal'),
- sprintf(_('%s and friends'), (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)),
- $action == 'all', 'nav_timeline_personal');
- $this->out->menuItem(common_local_url('replies', array('nickname' =>
- $nickname)),
- _('Replies'),
- sprintf(_('Replies to %s'), (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)),
- $action == 'replies', 'nav_timeline_replies');
- $this->out->menuItem(common_local_url('showstream', array('nickname' =>
- $nickname)),
- _('Profile'),
- ($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname,
- $action == 'showstream', 'nav_profile');
- $this->out->menuItem(common_local_url('showfavorites', array('nickname' =>
- $nickname)),
- _('Favorites'),
- sprintf(_('%s\'s favorite notices'), ($user_profile) ? $user_profile->getBestName() : _('User')),
- $action == 'showfavorites', 'nav_timeline_favorites');
+ if (Event::handle('StartPersonalGroupNav', array($this))) {
+ $this->out->menuItem(common_local_url('all', array('nickname' =>
+ $nickname)),
+ _('Personal'),
+ sprintf(_('%s and friends'), (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)),
+ $action == 'all', 'nav_timeline_personal');
+ $this->out->menuItem(common_local_url('replies', array('nickname' =>
+ $nickname)),
+ _('Replies'),
+ sprintf(_('Replies to %s'), (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)),
+ $action == 'replies', 'nav_timeline_replies');
+ $this->out->menuItem(common_local_url('showstream', array('nickname' =>
+ $nickname)),
+ _('Profile'),
+ ($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname,
+ $action == 'showstream', 'nav_profile');
+ $this->out->menuItem(common_local_url('showfavorites', array('nickname' =>
+ $nickname)),
+ _('Favorites'),
+ sprintf(_('%s\'s favorite notices'), ($user_profile) ? $user_profile->getBestName() : _('User')),
+ $action == 'showfavorites', 'nav_timeline_favorites');
- $cur = common_current_user();
+ $cur = common_current_user();
- if ($cur && $cur->id == $user->id) {
+ if ($cur && $cur->id == $user->id) {
- $this->out->menuItem(common_local_url('inbox', array('nickname' =>
- $nickname)),
- _('Inbox'),
- _('Your incoming messages'),
- $action == 'inbox');
- $this->out->menuItem(common_local_url('outbox', array('nickname' =>
- $nickname)),
- _('Outbox'),
- _('Your sent messages'),
- $action == 'outbox');
+ $this->out->menuItem(common_local_url('inbox', array('nickname' =>
+ $nickname)),
+ _('Inbox'),
+ _('Your incoming messages'),
+ $action == 'inbox');
+ $this->out->menuItem(common_local_url('outbox', array('nickname' =>
+ $nickname)),
+ _('Outbox'),
+ _('Your sent messages'),
+ $action == 'outbox');
+ }
+ Event::handle('EndPersonalGroupNav', array($this));
}
-
$this->out->elementEnd('ul');
}
}
diff --git a/lib/searchaction.php b/lib/searchaction.php
index e74450e11..e7ad4affd 100644
--- a/lib/searchaction.php
+++ b/lib/searchaction.php
@@ -51,7 +51,7 @@ class SearchAction extends Action
*
* @return boolean true
*/
- function isReadOnly($args)
+ function isReadOnly()
{
return true;
}
diff --git a/lib/subpeopletagcloudsection.php b/lib/subpeopletagcloudsection.php
new file mode 100644
index 000000000..d98f28afa
--- /dev/null
+++ b/lib/subpeopletagcloudsection.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Laconica, the distributed open-source microblogging tool
+ *
+ * Personal tag cloud section
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Widget
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @copyright 2009 Control Yourself, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+if (!defined('LACONICA')) {
+ exit(1);
+}
+
+/**
+ * Personal tag cloud section
+ *
+ * @category Widget
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+class SubPeopleTagCloudSection extends TagCloudSection
+{
+ function getTags()
+ {
+ $qry = $this->query();
+ $limit = TAGS_PER_SECTION;
+ $offset = 0;
+
+ if (common_config('db','type') == 'pgsql') {
+ $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
+ } else {
+ $qry .= ' LIMIT ' . $offset . ', ' . $limit;
+ }
+
+ $profile_tag = Memcached_DataObject::cachedQuery('Profile_tag',
+ sprintf($qry,
+ $this->out->user->id));
+ return $profile_tag;
+ }
+
+ function tagUrl($tag) {
+ return common_local_url('peopletag', array('tag' => $tag));
+ }
+
+ function showTag($tag, $weight, $relative) {
+ $rel = 'tag-cloud-';
+ $rel .= 1+intval(7 * $relative * $weight - 0.01);
+
+ $this->out->elementStart('li', $rel);
+ $this->out->element('a', array('href' => $this->tagUrl($tag)), $tag);
+ $this->out->elementEnd('li');
+ }
+}
diff --git a/lib/subscriberspeopleselftagcloudsection.php b/lib/subscriberspeopleselftagcloudsection.php
new file mode 100644
index 000000000..b5a39c6de
--- /dev/null
+++ b/lib/subscriberspeopleselftagcloudsection.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Laconica, the distributed open-source microblogging tool
+ *
+ * Personal tag cloud section
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Widget
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @copyright 2009 Control Yourself, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+if (!defined('LACONICA')) {
+ exit(1);
+}
+
+/**
+ * Personal tag cloud section
+ *
+ * @category Widget
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+class SubscribersPeopleSelfTagCloudSection extends SubPeopleTagCloudSection
+{
+ function title()
+ {
+ return _('People Tagcloud as self-tagged');
+ }
+
+ function query() {
+ return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged group by tag order by weight desc';
+ }
+}
diff --git a/lib/subscriberspeopletagcloudsection.php b/lib/subscriberspeopletagcloudsection.php
new file mode 100644
index 000000000..23011efdd
--- /dev/null
+++ b/lib/subscriberspeopletagcloudsection.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Laconica, the distributed open-source microblogging tool
+ *
+ * Personal tag cloud section
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Widget
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @copyright 2009 Control Yourself, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+if (!defined('LACONICA')) {
+ exit(1);
+}
+
+/**
+ * Personal tag cloud section
+ *
+ * @category Widget
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+class SubscribersPeopleTagCloudSection extends SubPeopleTagCloudSection
+{
+ function title()
+ {
+ return _('People Tagcloud as tagged');
+ }
+
+ function tagUrl($tag) {
+ $nickname = $this->out->profile->nickname;
+ return common_local_url('subscribers', array('nickname' => $nickname, 'tag' => $tag));
+ }
+
+
+ function query() {
+ return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagged and subscribed=tagger where subscribed=%d and subscriber != subscribed group by tag order by weight desc';
+ }
+}
diff --git a/lib/subscriptionspeopleselftagcloudsection.php b/lib/subscriptionspeopleselftagcloudsection.php
new file mode 100644
index 000000000..8ac65adb0
--- /dev/null
+++ b/lib/subscriptionspeopleselftagcloudsection.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Laconica, the distributed open-source microblogging tool
+ *
+ * Personal tag cloud section
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Widget
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @copyright 2009 Control Yourself, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+if (!defined('LACONICA')) {
+ exit(1);
+}
+
+/**
+ * Personal tag cloud section
+ *
+ * @category Widget
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+class SubscriptionsPeopleSelfTagCloudSection extends SubPeopleTagCloudSection
+{
+ function title()
+ {
+ return _('People Tagcloud as self-tagged');
+ }
+
+ function query() {
+ return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscriber != subscribed and tagger = tagged group by tag order by weight desc';
+ }
+}
diff --git a/lib/subscriptionspeopletagcloudsection.php b/lib/subscriptionspeopletagcloudsection.php
new file mode 100644
index 000000000..c3f7d1763
--- /dev/null
+++ b/lib/subscriptionspeopletagcloudsection.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Laconica, the distributed open-source microblogging tool
+ *
+ * Personal tag cloud section
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Widget
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @copyright 2009 Control Yourself, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+if (!defined('LACONICA')) {
+ exit(1);
+}
+
+/**
+ * Personal tag cloud section
+ *
+ * @category Widget
+ * @package Laconica
+ * @author Evan Prodromou <evan@controlyourself.ca>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+class SubscriptionsPeopleTagCloudSection extends SubPeopleTagCloudSection
+{
+ function title()
+ {
+ return _('People Tagcloud as tagged');
+ }
+
+ function tagUrl($tag) {
+ $nickname = $this->out->profile->nickname;
+ return common_local_url('subscriptions', array('nickname' => $nickname, 'tag' => $tag));
+ }
+
+ function query() {
+ return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagger and subscribed=tagged where subscriber=%d and subscriber != subscribed group by tag order by weight desc';
+ }
+}
diff --git a/lib/twitterapi.php b/lib/twitterapi.php
index b8357c688..6a90b4e28 100644
--- a/lib/twitterapi.php
+++ b/lib/twitterapi.php
@@ -418,7 +418,7 @@ class TwitterapiAction extends Action
function date_twitter($dt)
{
$t = strtotime($dt);
- return date("D M d G:i:s O Y", $t);
+ return date("D M d H:i:s O Y", $t);
}
// XXX: Candidate for a general utility method somewhere?
diff --git a/lib/util.php b/lib/util.php
index 888765548..da009682b 100644
--- a/lib/util.php
+++ b/lib/util.php
@@ -1392,3 +1392,4 @@ function common_database_tablename($tablename)
//table prefixes could be added here later
return $tablename;
}
+
diff --git a/scripts/jabberqueuehandler.php b/scripts/jabberqueuehandler.php
index 924fc4545..8b6e974c0 100755
--- a/scripts/jabberqueuehandler.php
+++ b/scripts/jabberqueuehandler.php
@@ -54,6 +54,13 @@ class JabberQueueHandler extends XmppQueueHandler
}
}
+// Abort immediately if xmpp is not enabled, otherwise the daemon chews up
+// lots of CPU trying to connect to unconfigured servers
+if (common_config('xmpp','enabled')==false) {
+ print "Aborting daemon - xmpp is disabled\n";
+ exit();
+}
+
ini_set("max_execution_time", "0");
ini_set("max_input_time", "0");
set_time_limit(0);
@@ -63,4 +70,4 @@ $resource = ($argc > 1) ? $argv[1] : (common_config('xmpp','resource') . '-queue
$handler = new JabberQueueHandler($resource);
-$handler->runOnce(); \ No newline at end of file
+$handler->runOnce();
diff --git a/scripts/publicqueuehandler.php b/scripts/publicqueuehandler.php
index 5075c12df..b0fa22d43 100755
--- a/scripts/publicqueuehandler.php
+++ b/scripts/publicqueuehandler.php
@@ -52,6 +52,13 @@ class PublicQueueHandler extends XmppQueueHandler
}
}
+// Abort immediately if xmpp is not enabled, otherwise the daemon chews up
+// lots of CPU trying to connect to unconfigured servers
+if (common_config('xmpp','enabled')==false) {
+ print "Aborting daemon - xmpp is disabled\n";
+ exit();
+}
+
ini_set("max_execution_time", "0");
ini_set("max_input_time", "0");
set_time_limit(0);
diff --git a/scripts/xmppconfirmhandler.php b/scripts/xmppconfirmhandler.php
index 2b8b085ce..7f39235fe 100755
--- a/scripts/xmppconfirmhandler.php
+++ b/scripts/xmppconfirmhandler.php
@@ -140,6 +140,13 @@ class XmppConfirmHandler extends XmppQueueHandler
}
}
+// Abort immediately if xmpp is not enabled, otherwise the daemon chews up
+// lots of CPU trying to connect to unconfigured servers
+if (common_config('xmpp','enabled')==false) {
+ print "Aborting daemon - xmpp is disabled\n";
+ exit();
+}
+
ini_set("max_execution_time", "0");
ini_set("max_input_time", "0");
set_time_limit(0);
diff --git a/scripts/xmppdaemon.php b/scripts/xmppdaemon.php
index ef3f8c63d..0ce2f2a28 100755
--- a/scripts/xmppdaemon.php
+++ b/scripts/xmppdaemon.php
@@ -321,6 +321,13 @@ class XMPPDaemon extends Daemon
}
}
+// Abort immediately if xmpp is not enabled, otherwise the daemon chews up
+// lots of CPU trying to connect to unconfigured servers
+if (common_config('xmpp','enabled')==false) {
+ print "Aborting daemon - xmpp is disabled\n";
+ exit();
+}
+
ini_set("max_execution_time", "0");
ini_set("max_input_time", "0");
set_time_limit(0);
diff --git a/theme/earthy/css/base.css b/theme/earthy/css/base.css
new file mode 100644
index 000000000..6f46eef97
--- /dev/null
+++ b/theme/earthy/css/base.css
@@ -0,0 +1,1188 @@
+/** theme: earthy base
+ *
+ * @package Laconica
+ * @author Sarven Capadisli <csarven@controlyourself.ca>
+ * @copyright 2009 Control Yourself, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+* { margin:0; padding:0; }
+img { display:block; border:0; }
+a abbr { cursor: pointer; border-bottom:0; }
+table { border-collapse:collapse; }
+ol { list-style-position:inside; }
+html { background-color:#fff; height:100%; }
+body {
+background-color:#fff;
+color:#000;
+font-family:sans-serif;
+font-size:1em;
+line-height:1.65;
+position:relative;
+}
+h1,h2,h3,h4,h5,h6 {
+margin-bottom:7px;
+overflow:hidden;
+}
+h1 {
+font-size:1.4em;
+margin-bottom:18px;
+text-align:right;
+}
+#showstream h1 { display:none; }
+h2 { font-size:1.3em; }
+h3 { font-size:1.2em; }
+h4 { font-size:1.1em; }
+h5 { font-size:1em; }
+h6 { font-size:0.9em; }
+
+caption {
+font-weight:bold;
+}
+legend {
+font-weight:bold;
+font-size:1.3em;
+}
+input, textarea, select, option {
+padding:4px;
+font-family:sans-serif;
+font-size:1em;
+}
+input, textarea, select {
+border-width:2px;
+border-style: solid;
+border-radius:4px;
+-moz-border-radius:4px;
+-webkit-border-radius:4px;
+}
+
+input.submit {
+font-weight:bold;
+cursor:pointer;
+}
+textarea {
+overflow:auto;
+}
+option {
+padding-bottom:0;
+}
+fieldset {
+padding:0;
+border:0;
+}
+form ul li {
+list-style-type:none;
+margin:0 0 18px 0;
+}
+form label {
+font-weight:bold;
+}
+input.checkbox {
+position:relative;
+top:2px;
+left:0;
+border:0;
+}
+
+.error,
+.success {
+padding:4px 7px;
+border-radius:4px;
+-moz-border-radius:4px;
+-webkit-border-radius:4px;
+margin-bottom:18px;
+}
+form label.submit {
+display:none;
+}
+
+.form_settings {
+clear:both;
+}
+
+.form_settings fieldset {
+margin-bottom:29px;
+}
+.form_settings input.remove {
+margin-left:11px;
+}
+.form_settings .form_data li {
+width:100%;
+float:left;
+}
+.form_settings .form_data label {
+float:left;
+}
+.form_settings .form_data textarea,
+.form_settings .form_data select,
+.form_settings .form_data input {
+margin-left:11px;
+float:left;
+}
+.form_settings .form_data input.submit {
+margin-left:0;
+}
+
+.form_settings label {
+margin-top:2px;
+width:152px;
+}
+
+.form_actions label {
+display:none;
+}
+.form_guide {
+font-style:italic;
+}
+
+.form_settings #settings_autosubscribe label {
+display:inline;
+font-weight:bold;
+}
+
+#form_settings_profile legend,
+#form_login legend,
+#form_register legend,
+#form_password legend,
+#form_settings_avatar legend,
+#newgroup legend,
+#editgroup legend,
+#form_tag_user legend,
+#form_remote_subscribe legend,
+#form_openid_login legend,
+#form_search legend,
+#form_invite legend,
+#form_notice_delete legend,
+#form_password_recover legend,
+#form_password_change legend {
+display:none;
+}
+
+.form_settings .form_data p.form_guide {
+clear:both;
+margin-left:163px;
+margin-bottom:0;
+}
+
+.form_settings p {
+margin-bottom:11px;
+}
+
+.form_settings input.checkbox {
+margin-top:3px;
+margin-left:0;
+}
+.form_settings label.checkbox {
+font-weight:normal;
+margin-top:0;
+margin-right:0;
+margin-left:11px;
+float:left;
+width:90%;
+}
+
+
+#form_login p.form_guide,
+#form_register #settings_rememberme p.form_guide,
+#form_openid_login #settings_rememberme p.form_guide,
+#settings_twitter_remove p.form_guide,
+#form_search ul.form_data #q {
+margin-left:0;
+}
+
+.form_settings .form_note {
+border-radius:4px;
+-moz-border-radius:4px;
+-webkit-border-radius:4px;
+padding:0 7px;
+}
+
+
+.form_settings input.form_action-secondary {
+margin-left:29px;
+padding:0;
+}
+
+#form_search .submit {
+margin-left:11px;
+}
+
+address {
+float:left;
+margin-bottom:18px;
+margin-left:18px;
+}
+address.vcard img.logo {
+margin-right:0;
+}
+address .fn {
+font-weight:bold;
+}
+address img + .fn {
+display:none;
+}
+
+#header {
+width:100%;
+position:relative;
+float:left;
+padding-top:18px;
+margin-bottom:29px;
+}
+
+#site_nav_global_primary {
+float:right;
+margin-right:18px;
+margin-bottom:11px;
+margin-left:18px;
+}
+#site_nav_global_primary ul li {
+display:inline;
+margin-left:11px;
+}
+
+.system_notice dt {
+font-weight:bold;
+text-transform:uppercase;
+display:none;
+}
+
+#site_notice {
+position:absolute;
+top:65px;
+right:18px;
+width:250px;
+width:24%;
+}
+#page_notice {
+clear:both;
+margin-bottom:18px;
+}
+
+
+#anon_notice {
+float:left;
+width:43.2%;
+padding:1.1%;
+border-radius:7px;
+-moz-border-radius:7px;
+-webkit-border-radius:7px;
+border-width:2px;
+border-style:solid;
+line-height:1.5;
+font-size:1.1em;
+font-weight:bold;
+}
+
+
+#footer {
+float:left;
+width:64%;
+padding:18px;
+}
+
+#site_nav_local_views {
+float:right;
+}
+#site_nav_local_views dt {
+display:none;
+}
+#site_nav_local_views li {
+float:right;
+margin-left:11px;
+list-style-type:none;
+}
+#site_nav_local_views a {
+float:left;
+text-decoration:none;
+padding:4px 11px;
+-moz-border-radius-topleft:4px;
+-moz-border-radius-topright:4px;
+-webkit-border-top-left-radius:4px;
+-webkit-border-top-right-radius:4px;
+border-width:1px;
+border-style:solid;
+border-bottom:0;
+text-shadow: 2px 2px 2px #ddd;
+font-weight:bold;
+}
+#site_nav_local_views .nav {
+float:left;
+width:100%;
+border-bottom-width:1px;
+border-bottom-style:solid;
+}
+
+#site_nav_global_primary dt,
+#site_nav_global_secondary dt {
+display:none;
+}
+
+#site_nav_global_secondary {
+margin-bottom:11px;
+}
+
+#site_nav_global_secondary ul li {
+display:inline;
+margin-right:11px;
+}
+#export_data li a {
+padding-left:20px;
+}
+#export_data li a.foaf {
+padding-left:30px;
+}
+#export_data li a.export_vcard {
+padding-left:28px;
+}
+
+#export_data ul {
+display:inline;
+}
+#export_data li {
+list-style-type:none;
+display:inline;
+margin-left:11px;
+}
+#export_data li:first-child {
+margin-left:0;
+}
+
+#licenses {
+font-size:0.9em;
+}
+
+#licenses dt {
+font-weight:bold;
+display:none;
+}
+#licenses dd {
+margin-bottom:11px;
+line-height:1.5;
+}
+
+#site_content_license_cc {
+margin-bottom:0;
+}
+#site_content_license_cc img {
+display:inline;
+vertical-align:top;
+margin-right:4px;
+}
+
+#wrap {
+margin:0 auto;
+width:100%;
+min-width:760px;
+max-width:1003px;
+overflow:hidden;
+}
+
+#core {
+position:relative;
+width:100%;
+float:left;
+margin-bottom:1em;
+}
+
+#content {
+width:63.009%;
+min-height:259px;
+padding-top:1.795%;
+padding-bottom:1.795%;
+float:right;
+clear:both;
+border-radius:7px;
+border-style:solid;
+border-width:0;
+}
+
+#content_inner {
+position:relative;
+width:100%;
+float:left;
+}
+
+#aside_primary {
+width:27.917%;
+min-height:259px;
+float:right;
+margin-right:4.385%;
+margin-top:73px;
+padding:1.795%;
+border-radius:7px;
+-moz-border-radius:7px;
+-webkit-border-radius:7px;
+border-width:1px;
+border-style:solid;
+}
+
+#form_notice {
+width:45.664%;
+float:left;
+position:relative;
+line-height:1;
+}
+#form_notice fieldset {
+border:0;
+padding:0;
+}
+#form_notice legend {
+display:none;
+}
+#form_notice textarea {
+float:left;
+border-radius:7px;
+-moz-border-radius:7px;
+-webkit-border-radius:7px;
+width:80.789%;
+height:67px;
+line-height:1.5;
+padding:7px 7px 16px 7px;
+}
+#form_notice label {
+display:block;
+float:left;
+font-size:1.3em;
+margin-bottom:7px;
+}
+#form_notice #notice_submit label {
+display:none;
+}
+#form_notice .form_note {
+position:absolute;
+top:99px;
+right:98px;
+z-index:9;
+}
+#form_notice .form_note dt {
+font-weight:bold;
+display:none;
+}
+#notice_text-count {
+font-weight:bold;
+line-height:1.15;
+padding:1px 2px;
+}
+#form_notice #notice_action-submit {
+width:14%;
+height:47px;
+padding:0;
+position:absolute;
+bottom:0;
+right:0;
+}
+#form_notice label[for=to] {
+margin-top:7px;
+}
+#form_notice select[id=to] {
+margin-bottom:7px;
+margin-left:18px;
+float:left;
+}
+
+
+/* entity_profile */
+.entity_profile {
+position:relative;
+width:67.702%;
+min-height:123px;
+float:left;
+margin-bottom:18px;
+margin-left:0;
+overflow:hidden;
+}
+.entity_profile dt,
+#entity_statistics dt {
+font-weight:bold;
+}
+.entity_profile dd {
+display:inline;
+}
+
+.entity_profile .entity_depiction {
+float:left;
+width:96px;
+margin-right:18px;
+margin-bottom:18px;
+}
+
+.entity_profile .entity_fn,
+.entity_profile .entity_nickname,
+.entity_profile .entity_location,
+.entity_profile .entity_url,
+.entity_profile .entity_note,
+.entity_profile .entity_tags {
+margin-left:113px;
+margin-bottom:4px;
+}
+
+.entity_profile .entity_fn,
+.entity_profile .entity_nickname {
+margin-left:11px;
+display:inline;
+font-weight:bold;
+}
+.entity_profile .entity_nickname {
+margin-left:0;
+}
+
+.entity_profile .entity_fn dd:before {
+content: "(";
+font-weight:normal;
+}
+.entity_profile .entity_fn dd:after {
+content: ")";
+font-weight:normal;
+}
+
+.entity_profile dt {
+display:none;
+}
+.entity_profile h2 {
+display:none;
+}
+/* entity_profile */
+
+
+/*entity_actions*/
+.entity_actions {
+float:right;
+margin-left:4.35%;
+max-width:25%;
+}
+.entity_actions h2 {
+display:none;
+}
+.entity_actions ul {
+list-style-type:none;
+}
+.entity_actions li {
+margin-bottom:4px;
+}
+.entity_actions li:first-child {
+border-top:0;
+}
+.entity_actions fieldset {
+border:0;
+padding:0;
+}
+.entity_actions legend {
+display:none;
+}
+
+.entity_actions input.submit {
+display:block;
+text-align:left;
+width:100%;
+}
+.entity_actions a,
+.entity_nudge p,
+.entity_remote_subscribe {
+text-decoration:none;
+font-weight:bold;
+display:block;
+}
+
+.form_user_block input.submit,
+.form_user_unblock input.submit,
+.entity_send-a-message a,
+.entity_edit a,
+.form_user_nudge input.submit,
+.entity_nudge p {
+border:0;
+padding-left:20px;
+}
+
+.entity_edit a,
+.entity_send-a-message a,
+.entity_nudge p {
+padding:4px 4px 4px 23px;
+}
+
+.entity_remote_subscribe {
+padding:4px;
+border-width:2px;
+border-style:solid;
+border-radius:4px;
+-moz-border-radius:4px;
+-webkit-border-radius:4px;
+}
+.entity_actions .accept {
+margin-bottom:18px;
+}
+
+.entity_tags ul {
+list-style-type:none;
+display:inline;
+}
+.entity_tags li {
+display:inline;
+margin-right:4px;
+}
+
+.aside .section {
+margin-bottom:29px;
+clear:both;
+float:left;
+width:100%;
+}
+.aside .section h2 {
+text-transform:uppercase;
+font-size:1em;
+}
+
+#entity_statistics dt,
+#entity_statistics dd {
+display:inline;
+}
+#entity_statistics dt:after {
+content: ":";
+}
+
+.section ul.entities {
+float:left;
+width:100%;
+}
+.section .entities li {
+list-style-type:none;
+float:left;
+margin-right:7px;
+margin-bottom:7px;
+}
+.section .entities li .photo {
+margin-right:0;
+margin-bottom:0;
+}
+.section .entities li .fn {
+display:none;
+}
+
+.aside .section p,
+.aside .section .more {
+clear:both;
+}
+
+.profile .entity_profile {
+margin-bottom:0;
+min-height:60px;
+}
+
+
+.profile .form_group_join legend,
+.profile .form_group_leave legend,
+.profile .form_user_subscribe legend,
+.profile .form_user_unsubscribe legend {
+display:none;
+}
+
+.profiles {
+list-style-type:none;
+}
+.profile .entity_profile .entity_location {
+width:auto;
+clear:none;
+margin-left:11px;
+}
+.profile .entity_profile dl,
+.profile .entity_profile dd {
+display:inline;
+float:none;
+}
+.profile .entity_profile .entity_note,
+.profile .entity_profile .entity_url,
+.profile .entity_profile .entity_tags,
+.profile .entity_profile .form_subscription_edit {
+margin-left:59px;
+clear:none;
+display:block;
+width:auto;
+}
+.profile .entity_profile .entity_tags dt {
+display:inline;
+margin-right:11px;
+}
+
+
+.profile .entity_profile .form_subscription_edit label {
+font-weight:normal;
+margin-right:11px;
+}
+
+
+/* NOTICE */
+.notice,
+.profile {
+position:relative;
+clear:both;
+float:left;
+width:100%;
+border-width:1px;
+border-style:solid;
+border-radius:7px;
+-moz-border-radius:7px;
+-webkit-border-radius:7px;
+}
+#content .notice,
+#content .profile {
+padding:1.795%;
+margin-bottom:44px;
+}
+#content .notice {
+width:96.25%;
+}
+
+.notices li {
+list-style-type:none;
+}
+.notices li.hover {
+border-radius:4px;
+-moz-border-radius:4px;
+-webkit-border-radius:4px;
+}
+
+/* NOTICES */
+#notices_primary {
+float:left;
+width:100%;
+border-radius:7px;
+-moz-border-radius:7px;
+-webkit-border-radius:7px;
+}
+#notices_primary h2 {
+display:none;
+}
+.notice-data a span {
+display:block;
+padding-left:28px;
+}
+
+.notice .author {
+margin-right:11px;
+}
+
+.fn {
+overflow:hidden;
+}
+
+.notice .author .fn {
+font-weight:bold;
+}
+
+.notice .author .photo {
+margin-bottom:0;
+}
+
+.vcard .photo {
+display:inline;
+margin-right:11px;
+margin-bottom:11px;
+float:left;
+}
+.vcard .url {
+text-decoration:none;
+}
+.vcard .url:hover {
+text-decoration:underline;
+}
+
+.notice .entry-title {
+float:left;
+width:100%;
+overflow:hidden;
+}
+#shownotice .notice .entry-title {
+font-size:2.2em;
+}
+
+.notice p.entry-content {
+display:inline;
+}
+
+#content .notice p.entry-content a:visited {
+border-radius:4px;
+-moz-border-radius:4px;
+-webkit-border-radius:4px;
+}
+.notice p.entry-content .vcard a {
+border-radius:4px;
+-moz-border-radius:4px;
+-webkit-border-radius:4px;
+}
+
+.notice div.entry-content {
+clear:left;
+float:left;
+font-size:0.95em;
+margin-left:59px;
+width:70%;
+}
+#showstream .notice div.entry-content {
+margin-left:0;
+}
+
+.notice .notice-options a,
+.notice .notice-options input {
+float:left;
+font-size:1.025em;
+}
+
+.notice div.entry-content dl,
+.notice div.entry-content dt,
+.notice div.entry-content dd {
+display:inline;
+}
+
+.notice div.entry-content .timestamp dt,
+.notice div.entry-content .response dt {
+display:none;
+}
+.notice div.entry-content .timestamp a {
+display:inline-block;
+}
+.notice div.entry-content .device dt {
+text-transform:lowercase;
+}
+
+
+
+.notice-data {
+position:absolute;
+top:18px;
+right:0;
+min-height:50px;
+margin-bottom:4px;
+}
+.notice .entry-content .notice-data dt {
+display:none;
+}
+
+.notice-data a {
+display:block;
+outline:none;
+}
+
+.notice-options {
+padding-left:2%;
+float:left;
+width:50%;
+position:relative;
+font-size:0.95em;
+width:12.5%;
+float:right;
+}
+
+.notice-options a {
+float:left;
+}
+.notice-options .notice_delete,
+.notice-options .notice_reply,
+.notice-options .form_favor,
+.notice-options .form_disfavor {
+position:absolute;
+top:0;
+}
+.notice-options .form_favor,
+.notice-options .form_disfavor {
+left:0;
+}
+.notice-options .notice_reply {
+left:29px;
+}
+.notice-options .notice_delete {
+right:0;
+}
+.notice-options .notice_reply dt {
+display:none;
+}
+
+.notice-options input,
+.notice-options a {
+text-indent:-9999px;
+outline:none;
+}
+
+.notice-options .notice_reply a,
+.notice-options input.submit {
+display:block;
+border:0;
+}
+.notice-options .notice_reply a,
+.notice-options .notice_delete a {
+text-decoration:none;
+padding-left:16px;
+}
+
+.notice-options form input.submit {
+width:16px;
+padding:2px 0;
+}
+
+.notice-options .notice_delete dt,
+.notice-options .form_favor legend,
+.notice-options .form_disfavor legend {
+display:none;
+}
+.notice-options .notice_delete fieldset,
+.notice-options .form_favor fieldset,
+.notice-options .form_disfavor fieldset {
+border:0;
+padding:0;
+}
+
+
+#usergroups #new_group {
+float: left;
+margin-right: 2em;
+}
+#new_group, #group_search {
+margin-bottom:18px;
+}
+#new_group a {
+padding-left:20px;
+}
+
+
+#filter_tags {
+margin-bottom:11px;
+float:left;
+}
+#filter_tags dt {
+display:none;
+}
+#filter_tags ul {
+list-style-type:none;
+}
+#filter_tags ul li {
+float:left;
+margin-left:7px;
+padding-left:7px;
+border-left-width:1px;
+border-left-style:solid;
+}
+#filter_tags ul li.child_1 {
+margin-left:0;
+border-left:0;
+padding-left:0;
+}
+#filter_tags ul li#filter_tags_all a {
+font-weight:bold;
+margin-top:7px;
+float:left;
+}
+
+#filter_tags ul li#filter_tags_item label {
+margin-right:7px;
+}
+#filter_tags ul li#filter_tags_item label,
+#filter_tags ul li#filter_tags_item select {
+display:inline;
+}
+#filter_tags ul li#filter_tags_item p {
+float:left;
+margin-left:38px;
+}
+#filter_tags ul li#filter_tags_item input {
+position:relative;
+top:3px;
+left:3px;
+}
+
+
+
+.pagination {
+float:left;
+clear:both;
+width:100%;
+margin-top:18px;
+}
+
+.pagination dt {
+font-weight:bold;
+display:none;
+}
+
+.pagination .nav {
+float:left;
+width:100%;
+list-style-type:none;
+}
+
+.pagination .nav_prev {
+float:left;
+}
+.pagination .nav_next {
+float:right;
+}
+
+.pagination a {
+display:block;
+text-decoration:none;
+font-weight:bold;
+padding:7px;
+border-width:1px;
+border-style:solid;
+-moz-border-radius:7px;
+-webkit-border-radius:7px;
+border-radius:7px;
+}
+
+.pagination .nav_prev a {
+padding-left:30px;
+}
+.pagination .nav_next a {
+padding-right:30px;
+}
+/* END: NOTICE */
+
+
+.hentry .entry-content p {
+margin-bottom:18px;
+}
+.hentry entry-content ol,
+.hentry .entry-content ul {
+list-style-position:inside;
+}
+.hentry .entry-content li {
+margin-bottom:18px;
+}
+.hentry .entry-content li li {
+margin-left:18px;
+}
+
+
+
+
+/* TOP_POSTERS */
+.section tbody td {
+padding-right:11px;
+padding-bottom:11px;
+}
+.section .vcard .photo {
+margin-right:7px;
+margin-bottom:0;
+}
+
+.section .notice {
+padding-top:7px;
+padding-bottom:7px;
+border-top:0;
+}
+
+.section .notice:first-child {
+padding-top:0;
+}
+
+.section .notice .author {
+margin-right:0;
+}
+.section .notice .author .fn {
+display:none;
+}
+
+
+/* tagcloud */
+.tag-cloud {
+list-style-type:none;
+text-align:center;
+}
+.aside .tag-cloud {
+font-size:0.8em;
+}
+.tag-cloud li {
+display:inline;
+margin-right:7px;
+line-height:1.25;
+}
+.aside .tag-cloud li {
+line-height:1.5;
+}
+.tag-cloud li a {
+text-decoration:none;
+}
+#tagcloud.section dt {
+text-transform:uppercase;
+font-weight:bold;
+}
+.tag-cloud-1 {
+font-size:1em;
+}
+.tag-cloud-2 {
+font-size:1.25em;
+}
+.tag-cloud-3 {
+font-size:1.75em;
+}
+.tag-cloud-4 {
+font-size:2em;
+}
+.tag-cloud-5 {
+font-size:2.25em;
+}
+.tag-cloud-6 {
+font-size:2.75em;
+}
+.tag-cloud-7 {
+font-size:3.25em;
+}
+
+#publictagcloud #tagcloud.section dt {
+display:none;
+}
+
+#form_settings_photo .form_data {
+clear:both;
+}
+
+#form_settings_avatar li {
+width:auto;
+}
+#form_settings_avatar input {
+margin-left:0;
+}
+#avatar_original,
+#avatar_preview {
+float:left;
+}
+#avatar_preview {
+margin-left:29px;
+}
+#avatar_preview_view {
+height:96px;
+width:96px;
+margin-bottom:18px;
+overflow:hidden;
+}
+
+#settings_attach,
+#form_settings_avatar .form_actions {
+clear:both;
+}
+
+#form_settings_avatar .form_actions {
+margin-bottom:0;
+}
+
+#form_settings_design #settings_design_color .form_data,
+#form_settings_design #color-picker {
+float:left;
+}
+#form_settings_design #settings_design_color .form_data {
+width:400px;
+margin-right:28px;
+}
+
+.instructions ul {
+list-style-position:inside;
+}
+.instructions p,
+.instructions ul {
+margin-bottom:18px;
+}
+.help dt {
+display:none;
+}
+.guide {
+clear:both;
+}
diff --git a/theme/earthy/css/display.css b/theme/earthy/css/display.css
new file mode 100644
index 000000000..b67700f2d
--- /dev/null
+++ b/theme/earthy/css/display.css
@@ -0,0 +1,251 @@
+/** theme: earthy
+ *
+ * @package Laconica
+ * @author Sarven Capadisli <csarven@controlyourself.ca>
+ * @copyright 2009 Control Yourself, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+@import url(base.css);
+
+html,
+body,
+a:active {
+background-color:#665500;
+}
+body {
+font-family: Verdana, sans-serif;
+font-size:1em;
+}
+address {
+margin-right:7.18%;
+}
+
+h1 {
+color:#fff;
+}
+
+input, textarea, select, option {
+font-family: Verdana, sans-serif;
+}
+input, textarea, select,
+.entity_remote_subscribe {
+border-color:#aaa;
+}
+#filter_tags ul li {
+border-color:#ddd;
+}
+
+.form_settings input.form_action-secondary {
+background:none;
+}
+
+input.submit,
+#form_notice.warning #notice_text-count,
+.form_settings .form_note,
+.entity_remote_subscribe {
+background-color:#9BB43E;
+}
+
+input:focus, textarea:focus, select:focus,
+#form_notice.warning #notice_data-text {
+border-color:#9BB43E;
+}
+input.submit,
+.entity_remote_subscribe {
+color:#dddd33;
+}
+
+a,
+div.notice-options input,
+.form_user_block input.submit,
+.form_user_unblock input.submit,
+.entity_send-a-message a,
+.form_user_nudge input.submit,
+.entity_nudge p,
+.form_settings input.form_action-secondary {
+color:#ee4400;
+}
+
+.notice,
+.profile {
+border-color:#DDAA00;
+}
+.section .profile {
+border-top-color:#aaaa66;
+}
+
+#content .notice p.entry-content a:visited {
+background-color:#fcfcfc;
+}
+#content .notice p.entry-content .vcard a {
+background-color:#fcfffc;
+}
+
+#aside_primary {
+background-color:#DDAA00;
+}
+
+#notice_text-count {
+color:#333;
+}
+#form_notice.warning #notice_text-count {
+color:#000;
+}
+#form_notice.processing #notice_action-submit {
+background:#dddd33 url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%;
+cursor:wait;
+text-indent:-9999px;
+}
+
+#content,
+#site_nav_local_views .nav,
+#site_nav_local_views a,
+#aside_primary {
+border-color:#dddd33;
+}
+#content .notice,
+#content .profile,
+#site_nav_local_views .current a {
+background-color:#dddd33;
+}
+#site_nav_local_views .current a {
+color:#EE4400;
+}
+#site_nav_local_views a {
+background-color:rgba(255, 255, 255, 0.2);
+color:#fff;
+}
+#site_nav_local_views a:hover {
+background-color:rgba(255, 255, 255, 0.4);
+}
+
+.error {
+background-color:#F7E8E8;
+}
+.success {
+background-color:#EFF3DC;
+}
+
+#anon_notice {
+background-color:#aaaa66;
+color:#dddd33;
+border-color:#dddd33;
+}
+
+#showstream #anon_notice {
+background-color:#9BB43E;
+}
+
+#export_data li a {
+background-repeat:no-repeat;
+background-position:0 45%;
+}
+#export_data li a.rss {
+background-image:url(../../base/images/icons/icon_rss.png);
+}
+#export_data li a.atom {
+background-image:url(../../base/images/icons/icon_atom.png);
+}
+#export_data li a.foaf {
+background-image:url(../../base/images/icons/icon_foaf.gif);
+}
+
+.entity_edit a,
+.entity_send-a-message a,
+.form_user_nudge input.submit,
+.form_user_block input.submit,
+.form_user_unblock input.submit,
+.entity_nudge p {
+background-position: 0 40%;
+background-repeat: no-repeat;
+background-color:transparent;
+}
+.form_group_join input.submit,
+.form_group_leave input.submit
+.form_user_subscribe input.submit,
+.form_user_unsubscribe input.submit {
+background-color:#9BB43E;
+color:#dddd33;
+}
+.form_user_unsubscribe input.submit,
+.form_group_leave input.submit,
+.form_user_authorization input.reject {
+background-color:#aaaa66;
+}
+
+.entity_edit a {
+background-image:url(../../base/images/icons/twotone/green/edit.gif);
+}
+.entity_send-a-message a {
+background-image:url(../../base/images/icons/twotone/green/quote.gif);
+}
+.entity_nudge p,
+.form_user_nudge input.submit {
+background-image:url(../../base/images/icons/twotone/green/mail.gif);
+}
+.form_user_block input.submit,
+.form_user_unblock input.submit {
+background-image:url(../../base/images/icons/twotone/green/shield.gif);
+}
+
+/* NOTICES */
+.notices li.over {
+background-color:#fcfcfc;
+}
+
+.notice-options .notice_reply a,
+.notice-options form input.submit {
+background-color:transparent;
+}
+.notice-options .notice_reply a {
+background:transparent url(../../base/images/icons/twotone/green/reply.gif) no-repeat 0 45%;
+}
+.notice-options form.form_favor input.submit {
+background:transparent url(../../base/images/icons/twotone/green/favourite.gif) no-repeat 0 45%;
+}
+.notice-options form.form_disfavor input.submit {
+background:transparent url(../../base/images/icons/twotone/green/disfavourite.gif) no-repeat 0 45%;
+}
+.notice-options .notice_delete a {
+background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-repeat 0 45%;
+}
+
+.notices div.entry-content,
+.notices div.notice-options {
+opacity:0.4;
+}
+.notices li.hover div.entry-content,
+.notices li.hover div.notice-options {
+opacity:1;
+}
+div.entry-content {
+color:#333;
+}
+div.notice-options a,
+div.notice-options input {
+font-family:sans-serif;
+}
+.notices li.hover {
+/*background-color:#fcfcfc;*/
+}
+/*END: NOTICES */
+
+#new_group a {
+background:transparent url(../../base/images/icons/twotone/green/news.gif) no-repeat 0 45%;
+}
+
+.pagination .nav_prev a,
+.pagination .nav_next a {
+background-repeat:no-repeat;
+border-color:#DDAA00;
+}
+.pagination .nav_prev a {
+background-image:url(../../base/images/icons/twotone/green/arrow-left.gif);
+background-position:10% 45%;
+}
+.pagination .nav_next a {
+background-image:url(../../base/images/icons/twotone/green/arrow-right.gif);
+background-position:90% 45%;
+}
diff --git a/theme/earthy/css/ie.css b/theme/earthy/css/ie.css
new file mode 100644
index 000000000..2f463bb44
--- /dev/null
+++ b/theme/earthy/css/ie.css
@@ -0,0 +1,9 @@
+/* IE specific styles */
+
+.notice-options input.submit {
+color:#fff;
+}
+
+#site_nav_local_views a {
+background-color:#D0DFE7;
+}
diff --git a/theme/earthy/default-avatar-mini.png b/theme/earthy/default-avatar-mini.png
new file mode 100644
index 000000000..38b8692b4
--- /dev/null
+++ b/theme/earthy/default-avatar-mini.png
Binary files differ
diff --git a/theme/earthy/default-avatar-profile.png b/theme/earthy/default-avatar-profile.png
new file mode 100644
index 000000000..f8357d4fc
--- /dev/null
+++ b/theme/earthy/default-avatar-profile.png
Binary files differ
diff --git a/theme/earthy/default-avatar-stream.png b/theme/earthy/default-avatar-stream.png
new file mode 100644
index 000000000..6b63baa70
--- /dev/null
+++ b/theme/earthy/default-avatar-stream.png
Binary files differ
diff --git a/theme/earthy/logo.png b/theme/earthy/logo.png
new file mode 100644
index 000000000..7c68b34f6
--- /dev/null
+++ b/theme/earthy/logo.png
Binary files differ
diff --git a/theme/otalk/css/base.css b/theme/otalk/css/base.css
new file mode 100644
index 000000000..379590d30
--- /dev/null
+++ b/theme/otalk/css/base.css
@@ -0,0 +1,1205 @@
+/** theme: otalk base
+ *
+ * @package Laconica
+ * @author Sarven Capadisli <csarven@controlyourself.ca>
+ * @copyright 2009 Control Yourself, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+* { margin:0; padding:0; }
+img { display:block; border:0; }
+a abbr { cursor: pointer; border-bottom:0; }
+table { border-collapse:collapse; }
+ol { list-style-position:inside; }
+html { font-size: 87.5%; background-color:#fff; height:100%; }
+body {
+background-color:#fff;
+color:#000;
+font-family:sans-serif;
+font-size:1em;
+line-height:1.65;
+position:relative;
+}
+h1,h2,h3,h4,h5,h6 {
+margin-bottom:7px;
+overflow:hidden;
+}
+h1 {
+font-size:1.4em;
+margin-bottom:18px;
+}
+#showstream h1 { display:none; }
+h2 { font-size:1.3em; }
+h3 { font-size:1.2em; }
+h4 { font-size:1.1em; }
+h5 { font-size:1em; }
+h6 { font-size:0.9em; }
+
+caption {
+font-weight:bold;
+}
+legend {
+font-weight:bold;
+font-size:1.3em;
+}
+input, textarea, select, option {
+padding:4px;
+font-family:sans-serif;
+font-size:1em;
+}
+input, textarea, select {
+border-width:2px;
+border-style: solid;
+border-radius:4px;
+-moz-border-radius:4px;
+-webkit-border-radius:4px;
+}
+
+input.submit {
+font-weight:bold;
+cursor:pointer;
+}
+textarea {
+overflow:auto;
+}
+option {
+padding-bottom:0;
+}
+fieldset {
+padding:0;
+border:0;
+}
+form ul li {
+list-style-type:none;
+margin:0 0 18px 0;
+}
+form label {
+font-weight:bold;
+}
+input.checkbox {
+position:relative;
+top:2px;
+left:0;
+border:0;
+}
+
+.error,
+.success {
+padding:4px 7px;
+border-radius:4px;
+-moz-border-radius:4px;
+-webkit-border-radius:4px;
+margin-bottom:18px;
+}
+form label.submit {
+display:none;
+}
+
+.form_settings {
+clear:both;
+}
+
+.form_settings fieldset {
+margin-bottom:29px;
+}
+.form_settings input.remove {
+margin-left:11px;
+}
+.form_settings .form_data li {
+width:100%;
+float:left;
+}
+.form_settings .form_data label {
+float:left;
+}
+.form_settings .form_data textarea,
+.form_settings .form_data select,
+.form_settings .form_data input {
+margin-left:11px;
+float:left;
+}
+.form_settings .form_data input.submit {
+margin-left:0;
+}
+
+.form_settings label {
+margin-top:2px;
+width:152px;
+}
+
+.form_actions label {
+display:none;
+}
+.form_guide {
+font-style:italic;
+}
+
+.form_settings #settings_autosubscribe label {
+display:inline;
+font-weight:bold;
+}
+
+#form_settings_profile legend,
+#form_login legend,
+#form_register legend,
+#form_password legend,
+#form_settings_avatar legend,
+#newgroup legend,
+#editgroup legend,
+#form_tag_user legend,
+#form_remote_subscribe legend,
+#form_openid_login legend,
+#form_search legend,
+#form_invite legend,
+#form_notice_delete legend,
+#form_password_recover legend,
+#form_password_change legend {
+display:none;
+}
+
+.form_settings .form_data p.form_guide {
+clear:both;
+margin-left:163px;
+margin-bottom:0;
+}
+
+.form_settings p {
+margin-bottom:11px;
+}
+
+.form_settings input.checkbox {
+margin-top:3px;
+margin-left:0;
+}
+.form_settings label.checkbox {
+font-weight:normal;
+margin-top:0;
+margin-right:0;
+margin-left:11px;
+float:left;
+width:90%;
+}
+
+
+#form_login p.form_guide,
+#form_register #settings_rememberme p.form_guide,
+#form_openid_login #settings_rememberme p.form_guide,
+#settings_twitter_remove p.form_guide,
+#form_search ul.form_data #q {
+margin-left:0;
+}
+
+.form_settings .form_note {
+border-radius:4px;
+-moz-border-radius:4px;
+-webkit-border-radius:4px;
+padding:0 7px;
+}
+
+
+.form_settings input.form_action-secondary {
+margin-left:29px;
+padding:0;
+}
+
+#form_search .submit {
+margin-left:11px;
+}
+
+address {
+float:left;
+margin-bottom:18px;
+margin-left:18px;
+}
+address.vcard img.logo {
+margin-right:0;
+}
+address .fn {
+font-weight:bold;
+}
+address img + .fn {
+display:none;
+}
+
+#header {
+width:100%;
+position:relative;
+float:left;
+padding-top:18px;
+margin-bottom:29px;
+}
+
+#site_nav_global_primary {
+float:right;
+margin-right:18px;
+margin-bottom:11px;
+margin-left:18px;
+}
+#site_nav_global_primary ul li {
+display:inline;
+margin-left:11px;
+}
+
+.system_notice dt {
+font-weight:bold;
+text-transform:uppercase;
+display:none;
+}
+
+#site_notice {
+position:absolute;
+top:65px;
+right:18px;
+width:250px;
+width:24%;
+}
+#page_notice {
+clear:both;
+margin-bottom:18px;
+}
+
+
+#anon_notice {
+float:left;
+width:43.2%;
+padding:1.1%;
+border-radius:7px;
+-moz-border-radius:7px;
+-webkit-border-radius:7px;
+border-width:2px;
+border-style:solid;
+line-height:1.5;
+font-size:1.1em;
+font-weight:bold;
+}
+
+
+#footer {
+float:left;
+width:64%;
+padding:18px;
+}
+
+#site_nav_local_views {
+float:left;
+}
+#site_nav_local_views dt {
+display:none;
+}
+#site_nav_local_views li {
+float:left;
+margin-right:18px;
+list-style-type:none;
+}
+#site_nav_local_views a {
+float:left;
+text-decoration:none;
+padding:4px 11px;
+-moz-border-radius-topleft:4px;
+-moz-border-radius-topright:4px;
+-webkit-border-top-left-radius:4px;
+-webkit-border-top-right-radius:4px;
+border-width:0;
+border-style:solid;
+border-bottom:0;
+text-shadow: 2px 2px 2px #ddd;
+font-weight:bold;
+}
+#site_nav_local_views .nav {
+float:left;
+width:100%;
+border-bottom-width:1px;
+border-bottom-style:solid;
+}
+
+#site_nav_global_primary dt,
+#site_nav_global_secondary dt {
+display:none;
+}
+
+#site_nav_global_secondary {
+margin-bottom:11px;
+}
+
+#site_nav_global_secondary ul li {
+display:inline;
+margin-right:11px;
+}
+#export_data li a {
+padding-left:20px;
+}
+#export_data li a.foaf {
+padding-left:30px;
+}
+#export_data li a.export_vcard {
+padding-left:28px;
+}
+
+#export_data ul {
+display:inline;
+}
+#export_data li {
+list-style-type:none;
+display:inline;
+margin-left:11px;
+}
+#export_data li:first-child {
+margin-left:0;
+}
+
+#licenses {
+font-size:0.9em;
+}
+
+#licenses dt {
+font-weight:bold;
+display:none;
+}
+#licenses dd {
+margin-bottom:11px;
+line-height:1.5;
+}
+
+#site_content_license_cc {
+margin-bottom:0;
+}
+#site_content_license_cc img {
+display:inline;
+vertical-align:top;
+margin-right:4px;
+}
+
+#wrap {
+margin:0 auto;
+width:100%;
+min-width:760px;
+max-width:1003px;
+overflow:hidden;
+}
+
+#core {
+position:relative;
+width:100%;
+float:left;
+margin-bottom:1em;
+}
+
+#content {
+width:100%;
+min-height:259px;
+padding-top:1.795%;
+padding-bottom:1.795%;
+
+float:left;
+border-radius:7px;
+-moz-border-radius:7px;
+-moz-border-radius-topleft:0;
+-webkit-border-radius:7px;
+-webkit-border-top-left-radius:0;
+border-style:solid;
+border-width:0;
+margin-bottom:18px;
+}
+
+#content_inner {
+position:relative;
+width:100%;
+float:left;
+}
+
+#aside_primary {
+width:96.3%;
+min-height:259px;
+float:left;
+clear:both;
+padding:1.795%;
+border-radius:7px;
+-moz-border-radius:7px;
+-webkit-border-radius:7px;
+border-width:1px;
+border-style:solid;
+}
+
+#form_notice {
+width:45.664%;
+float:left;
+position:relative;
+line-height:1;
+}
+#form_notice fieldset {
+border:0;
+padding:0;
+}
+#form_notice legend {
+display:none;
+}
+#form_notice textarea {
+float:left;
+border-radius:7px;
+-moz-border-radius:7px;
+-webkit-border-radius:7px;
+width:80.789%;
+height:67px;
+line-height:1.5;
+padding:7px 7px 16px 7px;
+}
+#form_notice label {
+display:block;
+float:left;
+font-size:1.3em;
+margin-bottom:7px;
+}
+#form_notice #notice_submit label {
+display:none;
+}
+#form_notice .form_note {
+position:absolute;
+top:99px;
+right:98px;
+z-index:9;
+}
+#form_notice .form_note dt {
+font-weight:bold;
+display:none;
+}
+#notice_text-count {
+font-weight:bold;
+line-height:1.15;
+padding:1px 2px;
+}
+#form_notice #notice_action-submit {
+width:14%;
+height:47px;
+padding:0;
+position:absolute;
+bottom:0;
+right:0;
+}
+#form_notice label[for=to] {
+margin-top:7px;
+}
+#form_notice select[id=to] {
+margin-bottom:7px;
+margin-left:18px;
+float:left;
+}
+
+
+/* entity_profile */
+.entity_profile {
+position:relative;
+width:521px;
+min-height:123px;
+float:left;
+margin-bottom:18px;
+margin-left:0;
+overflow:hidden;
+}
+.entity_profile dt,
+#entity_statistics dt {
+font-weight:bold;
+}
+.entity_profile dd {
+display:inline;
+}
+
+.entity_profile .entity_depiction {
+float:left;
+width:96px;
+margin-right:18px;
+margin-bottom:18px;
+}
+
+.entity_profile .entity_fn,
+.entity_profile .entity_nickname,
+.entity_profile .entity_location,
+.entity_profile .entity_url,
+.entity_profile .entity_note,
+.entity_profile .entity_tags {
+margin-left:113px;
+margin-bottom:4px;
+}
+
+.entity_profile .entity_fn,
+.entity_profile .entity_nickname {
+margin-left:11px;
+display:inline;
+font-weight:bold;
+}
+.entity_profile .entity_nickname {
+margin-left:0;
+}
+
+.entity_profile .entity_fn dd:before {
+content: "(";
+font-weight:normal;
+}
+.entity_profile .entity_fn dd:after {
+content: ")";
+font-weight:normal;
+}
+
+.entity_profile dt {
+display:none;
+}
+.entity_profile h2 {
+display:none;
+}
+/* entity_profile */
+
+
+/*entity_actions*/
+.entity_actions {
+float:left;
+margin-left:4.35%;
+max-width:25%;
+}
+.entity_actions h2 {
+display:none;
+}
+.entity_actions ul {
+list-style-type:none;
+}
+.entity_actions li {
+margin-bottom:4px;
+}
+.entity_actions li:first-child {
+border-top:0;
+}
+.entity_actions fieldset {
+border:0;
+padding:0;
+}
+.entity_actions legend {
+display:none;
+}
+
+.entity_actions input.submit {
+display:block;
+text-align:left;
+width:100%;
+}
+.entity_actions a,
+.entity_nudge p,
+.entity_remote_subscribe {
+text-decoration:none;
+font-weight:bold;
+display:block;
+}
+
+.form_user_block input.submit,
+.form_user_unblock input.submit,
+.entity_send-a-message a,
+.entity_edit a,
+.form_user_nudge input.submit,
+.entity_nudge p {
+border:0;
+padding-left:20px;
+}
+
+.entity_edit a,
+.entity_send-a-message a,
+.entity_nudge p {
+padding:4px 4px 4px 23px;
+}
+
+.entity_remote_subscribe {
+padding:4px;
+border-width:2px;
+border-style:solid;
+border-radius:4px;
+-moz-border-radius:4px;
+-webkit-border-radius:4px;
+}
+.entity_actions .accept {
+margin-bottom:18px;
+}
+
+.entity_tags ul {
+list-style-type:none;
+display:inline;
+}
+.entity_tags li {
+display:inline;
+margin-right:4px;
+}
+
+.aside .section {
+margin-bottom:29px;
+clear:both;
+float:left;
+width:100%;
+}
+.aside .section h2 {
+text-transform:uppercase;
+font-size:1em;
+}
+
+#entity_statistics dt,
+#entity_statistics dd {
+display:inline;
+}
+#entity_statistics dt:after {
+content: ":";
+}
+
+.section ul.entities {
+float:left;
+width:100%;
+}
+.section .entities li {
+list-style-type:none;
+float:left;
+margin-right:7px;
+margin-bottom:7px;
+}
+.section .entities li .photo {
+margin-right:0;
+margin-bottom:0;
+}
+.section .entities li .fn {
+display:none;
+}
+
+.aside .section p,
+.aside .section .more {
+clear:both;
+}
+
+.profile .entity_profile {
+margin-bottom:0;
+min-height:60px;
+}
+
+
+.profile .form_group_join legend,
+.profile .form_group_leave legend,
+.profile .form_user_subscribe legend,
+.profile .form_user_unsubscribe legend {
+display:none;
+}
+
+.profiles {
+list-style-type:none;
+}
+.profile .entity_profile .entity_location {
+width:auto;
+clear:none;
+margin-left:11px;
+}
+.profile .entity_profile dl,
+.profile .entity_profile dd {
+display:inline;
+float:none;
+}
+.profile .entity_profile .entity_note,
+.profile .entity_profile .entity_url,
+.profile .entity_profile .entity_tags,
+.profile .entity_profile .form_subscription_edit {
+margin-left:59px;
+clear:none;
+display:block;
+width:auto;
+}
+.profile .entity_profile .entity_tags dt {
+display:inline;
+margin-right:11px;
+}
+
+
+.profile .entity_profile .form_subscription_edit label {
+font-weight:normal;
+margin-right:11px;
+}
+
+
+/* NOTICE */
+.notice,
+.profile {
+position:relative;
+clear:both;
+float:left;
+width:100%;
+border-width:0;
+border-style:solid;
+margin-bottom:29px;
+}
+.notices li {
+list-style-type:none;
+}
+
+#content .notice {
+width:25%;
+margin-left:17px;
+margin-bottom:47px;
+clear:none;
+overflow:hidden;
+padding: 0 0 0 65px;
+min-height:235px;
+}
+
+#aside_primary .notice {
+margin-bottom:18px;
+}
+
+
+/* NOTICES */
+#notices_primary {
+float:left;
+width:100%;
+border-radius:7px;
+-moz-border-radius:7px;
+-webkit-border-radius:7px;
+}
+#notices_primary h2 {
+display:none;
+}
+.notice-data a span {
+display:block;
+padding-left:28px;
+}
+
+.notice .author {
+margin-right:11px;
+}
+
+#content .notice .author {
+/*overflow:hidden;*/
+}
+
+.fn {
+overflow:hidden;
+}
+
+.notice .author .fn {
+font-weight:bold;
+}
+
+.notice .author .photo {
+margin-bottom:0;
+}
+
+#content .notice .author .photo {
+margin-left:-83px;
+padding-right:17px;
+}
+
+
+.vcard .photo {
+display:inline;
+margin-right:11px;
+margin-bottom:11px;
+float:left;
+}
+.vcard .url {
+text-decoration:none;
+}
+.vcard .url:hover {
+text-decoration:underline;
+}
+
+.notice .entry-title {
+float:left;
+width:100%;
+overflow:hidden;
+}
+#content .notice .entry-title {
+overflow:visible;
+margin-bottom:11px;
+padding:18px;
+width:85%;
+border-radius:7px;
+-moz-border-radius:7px;
+-webkit-border-radius:7px;
+min-height:161px;
+}
+
+#shownotice .notice .entry-title {
+font-size:2.2em;
+}
+
+.notice p.entry-content {
+display:inline;
+}
+
+#content .notice p.entry-content
+overflow:hidden;
+}
+
+.notice p.entry-content .vcard a {
+border-radius:4px;
+-moz-border-radius:4px;
+-webkit-border-radius:4px;
+}
+
+.notice div.entry-content {
+clear:left;
+float:left;
+font-size:0.95em;
+}
+#showstream .notice div.entry-content {
+margin-left:0;
+}
+
+.notice .notice-options a,
+.notice .notice-options input {
+float:left;
+font-size:1.025em;
+}
+
+.notice div.entry-content dl,
+.notice div.entry-content dt,
+.notice div.entry-content dd {
+display:inline;
+}
+
+.notice div.entry-content .timestamp dt,
+.notice div.entry-content .response dt {
+display:none;
+}
+.notice div.entry-content .timestamp a {
+display:inline-block;
+}
+.notice div.entry-content .device dt {
+text-transform:lowercase;
+}
+
+
+
+.notice-data {
+position:absolute;
+top:18px;
+right:0;
+min-height:50px;
+margin-bottom:4px;
+}
+.notice .entry-content .notice-data dt {
+display:none;
+}
+
+.notice-data a {
+display:block;
+outline:none;
+}
+
+.notice-options {
+position:absolute;
+top:120px;
+left:30px;
+font-size:0.95em;
+}
+
+.notice-options a {
+float:left;
+}
+.notice-options .notice_delete,
+.notice-options .notice_reply,
+.notice-options .form_favor,
+.notice-options .form_disfavor {
+position:absolute;
+left:0;
+}
+.notice-options .form_favor,
+.notice-options .form_disfavor {
+top:0;
+}
+.notice-options .notice_reply {
+top:29px;
+}
+.notice-options .notice_delete {
+top:58px;
+}
+.notice-options .notice_reply dt {
+display:none;
+}
+
+.notice-options input,
+.notice-options a {
+text-indent:-9999px;
+outline:none;
+}
+
+.notice-options .notice_reply a,
+.notice-options input.submit {
+display:block;
+border:0;
+}
+.notice-options .notice_reply a,
+.notice-options .notice_delete a {
+text-decoration:none;
+padding-left:16px;
+}
+
+.notice-options form input.submit {
+width:16px;
+padding:2px 0;
+}
+
+.notice-options .notice_delete dt,
+.notice-options .form_favor legend,
+.notice-options .form_disfavor legend {
+display:none;
+}
+.notice-options .notice_delete fieldset,
+.notice-options .form_favor fieldset,
+.notice-options .form_disfavor fieldset {
+border:0;
+padding:0;
+}
+
+
+#usergroups #new_group {
+float: left;
+margin-right: 2em;
+}
+#new_group, #group_search {
+margin-bottom:18px;
+}
+#new_group a {
+padding-left:20px;
+}
+
+
+#filter_tags {
+margin-bottom:11px;
+float:left;
+}
+#filter_tags dt {
+display:none;
+}
+#filter_tags ul {
+list-style-type:none;
+}
+#filter_tags ul li {
+float:left;
+margin-left:7px;
+padding-left:7px;
+border-left-width:1px;
+border-left-style:solid;
+}
+#filter_tags ul li.child_1 {
+margin-left:0;
+border-left:0;
+padding-left:0;
+}
+#filter_tags ul li#filter_tags_all a {
+font-weight:bold;
+margin-top:7px;
+float:left;
+}
+
+#filter_tags ul li#filter_tags_item label {
+margin-right:7px;
+}
+#filter_tags ul li#filter_tags_item label,
+#filter_tags ul li#filter_tags_item select {
+display:inline;
+}
+#filter_tags ul li#filter_tags_item p {
+float:left;
+margin-left:38px;
+}
+#filter_tags ul li#filter_tags_item input {
+position:relative;
+top:3px;
+left:3px;
+}
+
+
+
+.pagination {
+float:left;
+clear:both;
+width:100%;
+margin-top:18px;
+}
+
+.pagination dt {
+font-weight:bold;
+display:none;
+}
+
+.pagination .nav {
+float:left;
+width:100%;
+list-style-type:none;
+}
+
+.pagination .nav_prev {
+float:left;
+}
+.pagination .nav_next {
+float:right;
+}
+
+.pagination a {
+display:block;
+text-decoration:none;
+font-weight:bold;
+padding:7px;
+border-width:1px;
+border-style:solid;
+-moz-border-radius:7px;
+-webkit-border-radius:7px;
+border-radius:7px;
+}
+
+.pagination .nav_prev a {
+padding-left:30px;
+}
+.pagination .nav_next a {
+padding-right:30px;
+}
+/* END: NOTICE */
+
+
+.hentry .entry-content p {
+margin-bottom:18px;
+}
+.hentry entry-content ol,
+.hentry .entry-content ul {
+list-style-position:inside;
+}
+.hentry .entry-content li {
+margin-bottom:18px;
+}
+.hentry .entry-content li li {
+margin-left:18px;
+}
+
+
+
+
+/* TOP_POSTERS */
+.section tbody td {
+padding-right:11px;
+padding-bottom:11px;
+}
+.section .vcard .photo {
+margin-right:7px;
+margin-bottom:0;
+}
+
+.section .notice {
+padding-top:7px;
+padding-bottom:7px;
+border-top:0;
+}
+
+.section .notice:first-child {
+padding-top:0;
+}
+
+.section .notice .author {
+margin-right:0;
+}
+.section .notice .author .fn {
+display:none;
+}
+
+
+/* tagcloud */
+.tag-cloud {
+list-style-type:none;
+text-align:center;
+}
+.aside .tag-cloud {
+font-size:0.8em;
+}
+.tag-cloud li {
+display:inline;
+margin-right:7px;
+line-height:1.25;
+}
+.aside .tag-cloud li {
+line-height:1.5;
+}
+.tag-cloud li a {
+text-decoration:none;
+}
+#tagcloud.section dt {
+text-transform:uppercase;
+font-weight:bold;
+}
+.tag-cloud-1 {
+font-size:1em;
+}
+.tag-cloud-2 {
+font-size:1.25em;
+}
+.tag-cloud-3 {
+font-size:1.75em;
+}
+.tag-cloud-4 {
+font-size:2em;
+}
+.tag-cloud-5 {
+font-size:2.25em;
+}
+.tag-cloud-6 {
+font-size:2.75em;
+}
+.tag-cloud-7 {
+font-size:3.25em;
+}
+
+#publictagcloud #tagcloud.section dt {
+display:none;
+}
+
+#form_settings_photo .form_data {
+clear:both;
+}
+
+#form_settings_avatar li {
+width:auto;
+}
+#form_settings_avatar input {
+margin-left:0;
+}
+#avatar_original,
+#avatar_preview {
+float:left;
+}
+#avatar_preview {
+margin-left:29px;
+}
+#avatar_preview_view {
+height:96px;
+width:96px;
+margin-bottom:18px;
+overflow:hidden;
+}
+
+#settings_attach,
+#form_settings_avatar .form_actions {
+clear:both;
+}
+
+#form_settings_avatar .form_actions {
+margin-bottom:0;
+}
+
+#form_settings_design #settings_design_color .form_data,
+#form_settings_design #color-picker {
+float:left;
+}
+#form_settings_design #settings_design_color .form_data {
+width:400px;
+margin-right:28px;
+}
+
+.instructions ul {
+list-style-position:inside;
+}
+.instructions p,
+.instructions ul {
+margin-bottom:18px;
+}
+.help dt {
+display:none;
+}
+.guide {
+clear:both;
+}
diff --git a/theme/otalk/css/display.css b/theme/otalk/css/display.css
new file mode 100644
index 000000000..22e0530ec
--- /dev/null
+++ b/theme/otalk/css/display.css
@@ -0,0 +1,293 @@
+/** theme: otalk
+ *
+ * @package Laconica
+ * @author Sarven Capadisli <csarven@controlyourself.ca>
+ * @copyright 2009 Control Yourself, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://laconi.ca/
+ */
+
+@import url(base.css);
+
+html {
+}
+
+html,
+body,
+a:active {
+/*background-color:#F0F2F5;*/
+}
+body {
+font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
+font-size:1em;
+background:#ddd url(../images/illustrations/illu_pattern-01.png) repeat 0 0;
+background-color:rgba(127, 127, 127, 0.1);
+}
+address {
+margin-right:7.18%;
+}
+
+input, textarea, select, option {
+font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
+}
+input, textarea, select,
+.entity_remote_subscribe {
+border-color:#aaa;
+}
+#filter_tags ul li {
+border-color:#ddd;
+}
+
+.form_settings input.form_action-secondary {
+background:none;
+}
+
+input.submit,
+#form_notice.warning #notice_text-count,
+.form_settings .form_note,
+.entity_remote_subscribe {
+background-color:#9BB43E;
+}
+
+input:focus, textarea:focus, select:focus,
+#form_notice.warning #notice_data-text {
+border-color:#9BB43E;
+}
+input.submit,
+.entity_remote_subscribe {
+color:#fff;
+}
+
+a,
+div.notice-options input,
+.form_user_block input.submit,
+.form_user_unblock input.submit,
+.entity_send-a-message a,
+.form_user_nudge input.submit,
+.entity_nudge p,
+.form_settings input.form_action-secondary {
+color:#8F0000;
+}
+
+.notice,
+.profile {
+border-color:#CEE1E9;
+}
+#content .notice .entry-title,
+input, textarea, select, option,
+.pagination .nav_prev a,
+.pagination .nav_next a {
+background-color:rgba(255,255,255,0.8);
+}
+
+#content .notices li.hover .entry-title {
+background-color:rgba(255,255,255,0.9);
+}
+
+#content .notice:nth-child(1) .entry-title {
+background-color:rgba(255,255,255,0.95);
+}
+#content .notice:nth-child(2) .entry-title {
+background-color:rgba(255,255,255,0.9);
+}
+#content .notice:nth-child(3) .entry-title {
+background-color:rgba(255,255,255,0.8);
+}
+#content .notice:nth-child(4) .entry-title {
+background-color:rgba(255,255,255,0.7);
+}
+#content .notice:nth-child(5) .entry-title {
+background-color:rgba(255,255,255,0.6);
+}
+#content .notice:nth-child(6) .entry-title {
+background-color:rgba(255,255,255,0.5);
+}
+#content .notice:nth-child(7) .entry-title {
+background-color:rgba(255,255,255,0.4);
+}
+#content .notice:nth-child(8) .entry-title {
+background-color:rgba(255,255,255,0.3);
+}
+#content .notice:nth-child(9) .entry-title {
+background-color:rgba(255,255,255,0.2);
+}
+#content .notice:nth-child(10) {
+background-color:rgba(255,255,255,0.1);
+}
+
+
+#content .notice .author .photo {
+background:url(../images/illustrations/illu_arrow-left-01.gif) no-repeat 100% 0;
+}
+
+.section .profile {
+border-top-color:#87B4C8;
+}
+
+#aside_primary {
+background-color:rgba(206, 225, 233,0.5);
+}
+
+#notice_text-count {
+color:#333;
+}
+#form_notice.warning #notice_text-count {
+color:#000;
+}
+#form_notice.processing #notice_action-submit {
+background:#fff url(../../base/images/icons/icon_processing.gif) no-repeat 47% 47%;
+cursor:wait;
+text-indent:-9999px;
+}
+
+#content,
+#site_nav_local_views .nav,
+#site_nav_local_views a,
+#aside_primary {
+border-color:#fff;
+}
+#content,
+#site_nav_local_views .current a {
+background-color:transparent;
+/*background-color:red;*/
+}
+
+#site_nav_local_views .current a {
+background-color:transparent;
+}
+
+#site_nav_local_views a {
+background-color:rgba(127, 127, 127, 0.2);
+}
+#site_nav_local_views a:hover {
+background-color:rgba(255, 255, 255, 0.8);
+}
+
+.error {
+background-color:#F7E8E8;
+}
+.success {
+background-color:#EFF3DC;
+}
+
+#anon_notice {
+background-color:rgba(206, 225, 233, 0.7);
+color:#fff;
+border-color:#fff;
+}
+
+#showstream #anon_notice {
+background-color:rgba(155, 180, 62, 0.7);
+}
+
+#export_data li a {
+background-repeat:no-repeat;
+background-position:0 45%;
+}
+#export_data li a.rss {
+background-image:url(../../base/images/icons/icon_rss.png);
+}
+#export_data li a.atom {
+background-image:url(../../base/images/icons/icon_atom.png);
+}
+#export_data li a.foaf {
+background-image:url(../../base/images/icons/icon_foaf.gif);
+}
+
+.entity_edit a,
+.entity_send-a-message a,
+.form_user_nudge input.submit,
+.form_user_block input.submit,
+.form_user_unblock input.submit,
+.entity_nudge p {
+background-position: 0 40%;
+background-repeat: no-repeat;
+background-color:transparent;
+}
+.form_group_join input.submit,
+.form_group_leave input.submit
+.form_user_subscribe input.submit,
+.form_user_unsubscribe input.submit {
+background-color:#9BB43E;
+color:#fff;
+}
+.form_user_unsubscribe input.submit,
+.form_group_leave input.submit,
+.form_user_authorization input.reject {
+background-color:#87B4C8;
+}
+
+.entity_edit a {
+background-image:url(../../base/images/icons/twotone/green/edit.gif);
+}
+.entity_send-a-message a {
+background-image:url(../../base/images/icons/twotone/green/quote.gif);
+}
+.entity_nudge p,
+.form_user_nudge input.submit {
+background-image:url(../../base/images/icons/twotone/green/mail.gif);
+}
+.form_user_block input.submit,
+.form_user_unblock input.submit {
+background-image:url(../../base/images/icons/twotone/green/shield.gif);
+}
+
+/* NOTICES */
+.notices li.over {
+background-color:#fcfcfc;
+}
+
+.notice-options .notice_reply a,
+.notice-options form input.submit {
+background-color:transparent;
+}
+.notice-options .notice_reply a {
+background:transparent url(../../base/images/icons/twotone/green/reply.gif) no-repeat 0 45%;
+}
+.notice-options form.form_favor input.submit {
+background:transparent url(../../base/images/icons/twotone/green/favourite.gif) no-repeat 0 45%;
+}
+.notice-options form.form_disfavor input.submit {
+background:transparent url(../../base/images/icons/twotone/green/disfavourite.gif) no-repeat 0 45%;
+}
+.notice-options .notice_delete a {
+background:transparent url(../../base/images/icons/twotone/green/trash.gif) no-repeat 0 45%;
+}
+
+.notices div.entry-content,
+.notices div.notice-options {
+opacity:0.4;
+}
+.notices li.hover div.entry-content,
+.notices li.hover div.notice-options {
+opacity:1;
+}
+div.entry-content {
+color:#333;
+}
+div.notice-options a,
+div.notice-options input {
+font-family:sans-serif;
+}
+.notices li.hover {
+/*background-color:#fcfcfc;*/
+}
+/*END: NOTICES */
+
+#new_group a {
+background:transparent url(../../base/images/icons/twotone/green/news.gif) no-repeat 0 45%;
+}
+
+.pagination .nav_prev a,
+.pagination .nav_next a {
+background-repeat:no-repeat;
+border-color:#CEE1E9;
+}
+.pagination .nav_prev a {
+background-image:url(../../base/images/icons/twotone/green/arrow-left.gif);
+background-position:10% 45%;
+}
+.pagination .nav_next a {
+background-image:url(../../base/images/icons/twotone/green/arrow-right.gif);
+background-position:90% 45%;
+}
diff --git a/theme/otalk/css/ie.css b/theme/otalk/css/ie.css
new file mode 100644
index 000000000..2f463bb44
--- /dev/null
+++ b/theme/otalk/css/ie.css
@@ -0,0 +1,9 @@
+/* IE specific styles */
+
+.notice-options input.submit {
+color:#fff;
+}
+
+#site_nav_local_views a {
+background-color:#D0DFE7;
+}
diff --git a/theme/otalk/default-avatar-mini.png b/theme/otalk/default-avatar-mini.png
new file mode 100644
index 000000000..38b8692b4
--- /dev/null
+++ b/theme/otalk/default-avatar-mini.png
Binary files differ
diff --git a/theme/otalk/default-avatar-profile.png b/theme/otalk/default-avatar-profile.png
new file mode 100644
index 000000000..f8357d4fc
--- /dev/null
+++ b/theme/otalk/default-avatar-profile.png
Binary files differ
diff --git a/theme/otalk/default-avatar-stream.png b/theme/otalk/default-avatar-stream.png
new file mode 100644
index 000000000..6b63baa70
--- /dev/null
+++ b/theme/otalk/default-avatar-stream.png
Binary files differ
diff --git a/theme/otalk/images/illustrations/illu_arrow-left-01.gif b/theme/otalk/images/illustrations/illu_arrow-left-01.gif
new file mode 100644
index 000000000..197775976
--- /dev/null
+++ b/theme/otalk/images/illustrations/illu_arrow-left-01.gif
Binary files differ
diff --git a/theme/otalk/images/illustrations/illu_pattern-01.png b/theme/otalk/images/illustrations/illu_pattern-01.png
new file mode 100644
index 000000000..5a72eafcb
--- /dev/null
+++ b/theme/otalk/images/illustrations/illu_pattern-01.png
Binary files differ
diff --git a/theme/otalk/logo.png b/theme/otalk/logo.png
new file mode 100644
index 000000000..7c68b34f6
--- /dev/null
+++ b/theme/otalk/logo.png
Binary files differ