diff options
30 files changed, 535 insertions, 240 deletions
@@ -877,7 +877,7 @@ This section is a catch-all for site-wide variables. name: the name of your site, like 'YourCompany Microblog'. server: the server part of your site's URLs, like 'example.net'. -path: The path part of your site's URLs, like 'mublog' or '/' +path: The path part of your site's URLs, like 'mublog' or '' (installed in root). fancy: whether or not your site uses fancy URLs (see Fancy URLs section above). Default is false. @@ -925,6 +925,16 @@ dupelimit: Time in which it's not OK for the same person to post the same notice; default = 60 seconds. logo: URL of an image file to use as the logo for the site. Overrides the logo in the theme, if any. +ssl: Whether to use SSL and https:// URLs for some or all pages. + Possible values are 'always' (use it for all pages), 'never' + (don't use it for any pages), or 'sometimes' (use it for + sensitive pages that include passwords like login and registration, + but not for regular pages). Default to 'never'. +sslserver: use an alternate server name for SSL URLs, like + 'secure.example.org'. You should be careful to set cookie + parameters correctly so that both the SSL server and the + "normal" server can access the session cookie and + preferably other cookies as well. db -- @@ -1169,6 +1179,20 @@ banned: an array of usernames and/or profile IDs of 'banned' profiles. not be accepted at all. (Compare with blacklisted users above, whose posts just won't show up in the public stream.) +newuser +------- + +Options with new users. + +subscribe: nickname of a user account to automatically subscribe new + users to. Typically this would be system account for e.g. + service updates or announcements. Users are able to unsub + if they want. Default is null; no auto subscribe. +welcome: nickname of a user account that sends welcome messages to new + users. Can be the same as 'subscribe' account, although on + busy servers it may be a good idea to keep that one just for + 'urgent' messages. Default is null; no message. + Troubleshooting =============== diff --git a/actions/public.php b/actions/public.php index a20ae4032..9b22e0a2c 100644 --- a/actions/public.php +++ b/actions/public.php @@ -207,9 +207,14 @@ class PublicAction extends Action function showAnonymousMessage() { - $m = _('This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' . - 'based on the Free Software [Laconica](http://laconi.ca/) tool. ' . - '[Join now](%%action.register%%) to share notices about yourself with friends, family, and colleagues! ([Read more](%%doc.help%%))'); + if (! (common_config('site','closed') || common_config('site','inviteonly'))) { + $m = _('This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' . + 'based on the Free Software [Laconica](http://laconi.ca/) tool. ' . + '[Join now](%%action.register%%) to share notices about yourself with friends, family, and colleagues! ([Read more](%%doc.help%%))'); + } else { + $m = _('This is %%site.name%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' . + 'based on the Free Software [Laconica](http://laconi.ca/) tool.'); + } $this->elementStart('div', array('id' => 'anon_notice')); $this->raw(common_markup_to_html($m)); $this->elementEnd('div'); diff --git a/actions/recoverpassword.php b/actions/recoverpassword.php index eeb6b2516..620fe7eb8 100644 --- a/actions/recoverpassword.php +++ b/actions/recoverpassword.php @@ -181,13 +181,21 @@ class RecoverpasswordAction extends Action function showRecoverForm() { $this->elementStart('form', array('method' => 'post', - 'id' => 'recoverpassword', + 'id' => 'form_password_recover', + 'class' => 'form_settings', 'action' => common_local_url('recoverpassword'))); + $this->elementStart('fieldset'); + $this->element('legend', null, _('Password recover')); + $this->elementStart('ul', 'form_data'); + $this->elementStart('li'); $this->input('nicknameoremail', _('Nickname or email'), $this->trimmed('nicknameoremail'), _('Your nickname on this server, ' . 'or your registered email address.')); + $this->elementEnd('li'); + $this->elementEnd('ul'); $this->submit('recover', _('Recover')); + $this->elementEnd('fieldset'); $this->elementEnd('form'); } @@ -213,14 +221,24 @@ class RecoverpasswordAction extends Action function showResetForm() { $this->elementStart('form', array('method' => 'post', - 'id' => 'recoverpassword', + 'id' => 'form_password_change', + 'class' => 'form_settings', 'action' => common_local_url('recoverpassword'))); + $this->elementStart('fieldset'); + $this->element('legend', null, _('Password change')); $this->hidden('token', common_session_token()); + $this->elementStart('ul', 'form_data'); + $this->elementStart('li'); $this->password('newpassword', _('New password'), _('6 or more characters, and don\'t forget it!')); + $this->elementEnd('li'); + $this->elementStart('li'); $this->password('confirm', _('Confirm'), _('Same as password above')); + $this->elementEnd('li'); + $this->elementEnd('ul'); $this->submit('reset', _('Reset')); + $this->elementEnd('fieldset'); $this->elementEnd('form'); } diff --git a/actions/showgroup.php b/actions/showgroup.php index 95d2914ba..79445851f 100644 --- a/actions/showgroup.php +++ b/actions/showgroup.php @@ -396,11 +396,18 @@ class ShowgroupAction extends Action function showAnonymousMessage() { - $m = sprintf(_('**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' . - 'based on the Free Software [Laconica](http://laconi.ca/) tool. Its members share ' . - 'short messages about their life and interests. '. - '[Join now](%%%%action.register%%%%) to become part of this group and many more! ([Read more](%%%%doc.help%%%%))'), + if (!(common_config('site','closed') || common_config('site','inviteonly'))) { + $m = sprintf(_('**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' . + 'based on the Free Software [Laconica](http://laconi.ca/) tool. Its members share ' . + 'short messages about their life and interests. '. + '[Join now](%%%%action.register%%%%) to become part of this group and many more! ([Read more](%%%%doc.help%%%%))'), $this->group->nickname); + } else { + $m = sprintf(_('**%s** is a user group on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' . + 'based on the Free Software [Laconica](http://laconi.ca/) tool. Its members share ' . + 'short messages about their life and interests. '), + $this->group->nickname); + } $this->elementStart('div', array('id' => 'anon_notice')); $this->raw(common_markup_to_html($m)); $this->elementEnd('div'); diff --git a/actions/showstream.php b/actions/showstream.php index 9b6536293..f5886f3d3 100644 --- a/actions/showstream.php +++ b/actions/showstream.php @@ -535,10 +535,16 @@ class ShowstreamAction extends Action function showAnonymousMessage() { - $m = sprintf(_('**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' . - 'based on the Free Software [Laconica](http://laconi.ca/) tool. ' . - '[Join now](%%%%action.register%%%%) to follow **%s**\'s notices and many more! ([Read more](%%%%doc.help%%%%))'), - $this->user->nickname, $this->user->nickname); + if (!(common_config('site','closed') || common_config('site','inviteonly'))) { + $m = sprintf(_('**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' . + 'based on the Free Software [Laconica](http://laconi.ca/) tool. ' . + '[Join now](%%%%action.register%%%%) to follow **%s**\'s notices and many more! ([Read more](%%%%doc.help%%%%))'), + $this->user->nickname, $this->user->nickname); + } else { + $m = sprintf(_('**%s** has an account on %%%%site.name%%%%, a [micro-blogging](http://en.wikipedia.org/wiki/Micro-blogging) service ' . + 'based on the Free Software [Laconica](http://laconi.ca/) tool. '), + $this->user->nickname, $this->user->nickname); + } $this->elementStart('div', array('id' => 'anon_notice')); $this->raw(common_markup_to_html($m)); $this->elementEnd('div'); diff --git a/apple-touch-icon.png b/apple-touch-icon.png Binary files differnew file mode 100644 index 000000000..d129298d4 --- /dev/null +++ b/apple-touch-icon.png diff --git a/classes/Notice.php b/classes/Notice.php index 3087e39a7..44a6aeb98 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -799,4 +799,98 @@ class Notice extends Memcached_DataObject } } } + + function asAtomEntry($namespace=false, $source=false) + { + $profile = $this->getProfile(); + + $xs = new XMLStringer(true); + + if ($namespace) { + $attrs = array('xmlns' => 'http://www.w3.org/2005/Atom', + 'xmlns:thr' => 'http://purl.org/syndication/thread/1.0'); + } else { + $attrs = array(); + } + + $xs->elementStart('entry', $attrs); + + if ($source) { + $xs->elementStart('source'); + $xs->element('title', null, $profile->nickname . " - " . common_config('site', 'name')); + $xs->element('link', array('href' => $profile->profileurl)); + $user = User::staticGet('id', $profile->id); + if (!empty($user)) { + $atom_feed = common_local_url('api', + array('apiaction' => 'statuses', + 'method' => 'user_timeline', + 'argument' => $profile->nickname.'.atom')); + $xs->element('link', array('rel' => 'self', + 'type' => 'application/atom+xml', + 'href' => $profile->profileurl)); + $xs->element('link', array('rel' => 'license', + 'href' => common_config('license', 'url'))); + } + + $xs->element('icon', null, $profile->avatarUrl(AVATAR_PROFILE_SIZE)); + } + + $xs->elementStart('author'); + $xs->element('name', null, $profile->nickname); + $xs->element('uri', null, $profile->profileurl); + $xs->elementEnd('author'); + + if ($source) { + $xs->elementEnd('source'); + } + + $xs->element('title', null, $this->content); + $xs->element('summary', null, $this->content); + + $xs->element('link', array('rel' => 'alternate', + 'href' => $this->bestUrl())); + + $xs->element('id', null, $this->uri); + + $xs->element('published', null, common_date_w3dtf($this->created)); + $xs->element('updated', null, common_date_w3dtf($this->modified)); + + if ($this->reply_to) { + $reply_notice = Notice::staticGet('id', $this->reply_to); + if (!empty($reply_notice)) { + $xs->element('link', array('rel' => 'related', + 'href' => $reply_notice->bestUrl())); + $xs->element('thr:in-reply-to', + array('ref' => $reply_notice->uri, + 'href' => $reply_notice->bestUrl())); + } + } + + $xs->element('content', array('type' => 'html'), $this->rendered); + + $tag = new Notice_tag(); + $tag->notice_id = $this->id; + if ($tag->find()) { + while ($tag->fetch()) { + $xs->element('category', array('term' => $tag->tag)); + } + } + $tag->free(); + + $xs->elementEnd('entry'); + + return $xs->getString(); + } + + function bestUrl() + { + if (!empty($this->url)) { + return $this->url; + } else if (!empty($this->uri) && preg_match('/^https?:/', $this->uri)) { + return $this->uri; + } else { + return common_local_url('shownotice', + array('notice' => $this->id)); + } + } } diff --git a/classes/User.php b/classes/User.php index d9f30bec5..3b9b5cd83 100644 --- a/classes/User.php +++ b/classes/User.php @@ -1,7 +1,7 @@ <?php /* * Laconica - a distributed open-source microblogging tool - * Copyright (C) 2008, Controlez-Vous, Inc. + * Copyright (C) 2008, 2009, Control Yourself, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -17,11 +17,14 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -if (!defined('LACONICA')) { exit(1); } +if (!defined('LACONICA')) { + exit(1); +} /** * Table Definition for user */ + require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; require_once 'Validate.php'; @@ -79,13 +82,13 @@ class User extends Memcached_DataObject function isSubscribed($other) { assert(!is_null($other)); - # XXX: cache results of this query + // XXX: cache results of this query $sub = Subscription::pkeyGet(array('subscriber' => $this->id, 'subscribed' => $other->id)); return (is_null($sub)) ? false : true; } - # 'update' won't write key columns, so we have to do it ourselves. + // 'update' won't write key columns, so we have to do it ourselves. function updateKeys(&$orig) { @@ -96,7 +99,7 @@ class User extends Memcached_DataObject } } if (count($parts) == 0) { - # No changes + // No changes return true; } $toupdate = implode(', ', $parts); @@ -117,7 +120,7 @@ class User extends Memcached_DataObject function allowed_nickname($nickname) { - # XXX: should already be validated for size, content, etc. + // XXX: should already be validated for size, content, etc. static $blacklist = array('rss', 'xrds', 'doc', 'main', 'settings', 'notice', 'user', 'search', 'avatar', 'tag', 'tags', @@ -147,7 +150,7 @@ class User extends Memcached_DataObject $sub->subscriber = $this->id; $sub->subscribed = $other->id; - $sub->created = common_sql_now(); # current time + $sub->created = common_sql_now(); // current time if (!$sub->insert()) { return false; @@ -173,7 +176,7 @@ class User extends Memcached_DataObject static function register($fields) { - # MAGICALLY put fields into current scope + // MAGICALLY put fields into current scope extract($fields); @@ -211,11 +214,11 @@ class User extends Memcached_DataObject $user->id = $id; $user->nickname = $nickname; - if (!empty($password)) { # may not have a password for OpenID users + if (!empty($password)) { // may not have a password for OpenID users $user->password = common_munge_password($password, $id); } - # Users who respond to invite email have proven their ownership of that address + // Users who respond to invite email have proven their ownership of that address if (!empty($code)) { $invite = Invitation::staticGet($code); @@ -240,7 +243,7 @@ class User extends Memcached_DataObject return false; } - # Everyone is subscribed to themself + // Everyone is subscribed to themself $subscription = new Subscription(); $subscription->subscriber = $user->id; @@ -273,16 +276,58 @@ class User extends Memcached_DataObject $user->emailChanged(); } + // Default system subscription + + $defnick = common_config('newuser', 'default'); + + if (!empty($defnick)) { + $defuser = User::staticGet('nickname', $defnick); + if (empty($defuser)) { + common_log(LOG_WARNING, sprintf("Default user %s does not exist.", $defnick), + __FILE__); + } else { + $defsub = new Subscription(); + $defsub->subscriber = $user->id; + $defsub->subscribed = $defuser->id; + $defsub->created = $user->created; + + $result = $defsub->insert(); + + if (!$result) { + common_log_db_error($defsub, 'INSERT', __FILE__); + return false; + } + } + } + $profile->query('COMMIT'); if ($email && !$user->email) { mail_confirm_address($user, $confirm->code, $profile->nickname, $email); } + // Welcome message + + $welcome = common_config('newuser', 'welcome'); + + if (!empty($welcome)) { + $welcomeuser = User::staticGet('nickname', $welcome); + if (empty($welcomeuser)) { + common_log(LOG_WARNING, sprintf("Welcome user %s does not exist.", $defnick), + __FILE__); + } else { + $notice = Notice::saveNew($welcomeuser->id, + sprintf(_('Welcome to %1$s, @%2$s!'), + common_config('site', 'name'), + $user->nickname), + 'system'); + } + } + return $user; } - # Things we do when the email changes + // Things we do when the email changes function emailChanged() { @@ -303,46 +348,46 @@ class User extends Memcached_DataObject { $cache = common_memcache(); - # XXX: Kind of a hack. + // XXX: Kind of a hack. if ($cache) { - # This is the stream of favorite notices, in rev chron - # order. This forces it into cache. + // This is the stream of favorite notices, in rev chron + // order. This forces it into cache. $faves = $this->favoriteNotices(0, NOTICE_CACHE_WINDOW); $cnt = 0; while ($faves->fetch()) { if ($faves->id < $notice->id) { - # If we passed it, it's not a fave + // If we passed it, it's not a fave return false; } else if ($faves->id == $notice->id) { - # If it matches a cached notice, then it's a fave + // If it matches a cached notice, then it's a fave return true; } $cnt++; } - # If we're not past the end of the cache window, - # then the cache has all available faves, so this one - # is not a fave. + // If we're not past the end of the cache window, + // then the cache has all available faves, so this one + // is not a fave. if ($cnt < NOTICE_CACHE_WINDOW) { return false; } - # Otherwise, cache doesn't have all faves; - # fall through to the default + // Otherwise, cache doesn't have all faves; + // fall through to the default } $fave = Fave::pkeyGet(array('user_id' => $this->id, 'notice_id' => $notice->id)); return ((is_null($fave)) ? false : true); } + function mutuallySubscribed($other) { return $this->isSubscribed($other) && $other->isSubscribed($this); } - function mutuallySubscribedUsers() - { - - # 3-way join; probably should get cached - $UT = common_config('db','type')=='pgsql'?'"user"':'user'; + function mutuallySubscribedUsers() + { + // 3-way join; probably should get cached + $UT = common_config('db','type')=='pgsql'?'"user"':'user'; $qry = "SELECT $UT.* " . "FROM subscription sub1 JOIN $UT ON sub1.subscribed = $UT.id " . "JOIN subscription sub2 ON $UT.id = sub2.subscriber " . @@ -365,8 +410,8 @@ class User extends Memcached_DataObject $offset, $limit, $since_id, $before_id, null, $since); } - function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) - { + function getNotices($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) + { $profile = $this->getProfile(); if (!$profile) { return null; @@ -375,8 +420,8 @@ class User extends Memcached_DataObject } } - function favoriteNotices($offset=0, $limit=NOTICES_PER_PAGE) - { + function favoriteNotices($offset=0, $limit=NOTICES_PER_PAGE) + { $qry = 'SELECT notice.* ' . 'FROM notice JOIN fave ON notice.id = fave.notice_id ' . @@ -386,12 +431,12 @@ class User extends Memcached_DataObject $offset, $limit); } - function noticesWithFriends($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) - { + function noticesWithFriends($offset=0, $limit=NOTICES_PER_PAGE, $since_id=0, $before_id=0, $since=null) + { $enabled = common_config('inboxes', 'enabled'); - # Complicated code, depending on whether we support inboxes yet - # XXX: make this go away when inboxes become mandatory + // Complicated code, depending on whether we support inboxes yet + // XXX: make this go away when inboxes become mandatory if ($enabled === false || ($enabled == 'transitional' && $this->inboxed == 0)) { @@ -401,13 +446,13 @@ class User extends Memcached_DataObject 'WHERE subscription.subscriber = %d '; $order = null; } else if ($enabled === true || - ($enabled == 'transitional' && $this->inboxed == 1)) { + ($enabled == 'transitional' && $this->inboxed == 1)) { $qry = 'SELECT notice.* ' . 'FROM notice JOIN notice_inbox ON notice.id = notice_inbox.notice_id ' . 'WHERE notice_inbox.user_id = %d '; - # NOTE: we override ORDER + // NOTE: we override ORDER $order = null; } return Notice::getStream(sprintf($qry, $this->id), @@ -416,35 +461,34 @@ class User extends Memcached_DataObject $order, $since); } - function blowFavesCache() - { + function blowFavesCache() + { $cache = common_memcache(); if ($cache) { - # Faves don't happen chronologically, so we need to blow - # ;last cache, too + // Faves don't happen chronologically, so we need to blow + // ;last cache, too $cache->delete(common_cache_key('user:faves:'.$this->id)); $cache->delete(common_cache_key('user:faves:'.$this->id).';last'); } } - function getSelfTags() - { + function getSelfTags() + { return Profile_tag::getTags($this->id, $this->id); } - function setSelfTags($newtags) - { + function setSelfTags($newtags) + { return Profile_tag::setTags($this->id, $this->id, $newtags); } function block($other) { - - # Add a new block record + // Add a new block record $block = new Profile_block(); - # Begin a transaction + // Begin a transaction $block->query('BEGIN'); @@ -458,7 +502,7 @@ class User extends Memcached_DataObject return false; } - # Cancel their subscription, if it exists + // Cancel their subscription, if it exists $sub = Subscription::pkeyGet(array('subscriber' => $other->id, 'subscribed' => $this->id)); @@ -478,8 +522,7 @@ class User extends Memcached_DataObject function unblock($other) { - - # Get the block record + // Get the block record $block = Profile_block::get($this->id, $other->id); diff --git a/config.php.sample b/config.php.sample index 529e86f15..d62a54fe7 100644 --- a/config.php.sample +++ b/config.php.sample @@ -174,3 +174,13 @@ $config['sphinx']['port'] = 3312; #http://taguri.org/ Examples: #$config['integration']['taguri'] = 'example.net,2008'; #$config['integration']['taguri'] = 'admin@example.net,2009-03-09' + +#Don't use SSL +#$config['site']['ssl'] = 'never'; +#Use SSL only for sensitive pages (like login, password change) +#$config['site']['ssl'] = 'sometimes'; +#Use SSL for all pages +#$config['site']['ssl'] = 'always'; + +#Use a different hostname for SSL-encrypted pages +#$config['site']['sslserver'] = 'secure.example.org'; diff --git a/db/notice_source.sql b/db/notice_source.sql index 5e2d413c0..d28a09383 100644 --- a/db/notice_source.sql +++ b/db/notice_source.sql @@ -19,6 +19,7 @@ VALUES ('identichat','identichat','http://identichat.prosody.im/', now()), ('identitwitch','IdentiTwitch','http://richfish.org/identitwitch/', now()), ('mbpidgin','mbpidgin','http://code.google.com/p/microblog-purple/', now()), + ('Mobidentica', 'Mobidentica', 'http://www.substanceofcode.com/software/mobidentica/', now()), ('moconica','Moconica','http://moconica.com/', now()), ('pocketwit','PockeTwit','http://code.google.com/p/pocketwit/', now()), ('posty','Posty','http://spreadingfunkyness.com/posty/', now()), @@ -44,4 +45,4 @@ VALUES ('twitux','Twitux','http://live.gnome.org/DanielMorales/Twitux', now()), ('twitvim','TwitVim','http://vim.sourceforge.net/scripts/script.php?script_id=2204', now()), ('urfastr','urfastr','http://urfastr.net/', now()), - ('adium', 'Adium', 'http://www.adiumx.com/', now())); + ('adium', 'Adium', 'http://www.adiumx.com/', now()); diff --git a/js/util.js b/js/util.js index 3ad038612..81139744f 100644 --- a/js/util.js +++ b/js/util.js @@ -161,6 +161,7 @@ $(document).ready(function(){ $("#form_notice").addClass("warning"); return false; } + $("#form_notice").addClass("processing"); $("#notice_action-submit").attr("disabled", "disabled"); $("#notice_action-submit").addClass("disabled"); return true; @@ -179,6 +180,7 @@ $(document).ready(function(){ NoticeHover(); NoticeReply(); } + $("#form_notice").removeClass("processing"); $("#notice_action-submit").removeAttr("disabled"); $("#notice_action-submit").removeClass("disabled"); } diff --git a/lib/action.php b/lib/action.php index 975c2bfcb..f0baa062c 100644 --- a/lib/action.php +++ b/lib/action.php @@ -112,6 +112,7 @@ class Action extends HTMLOutputter // lawsuit // XXX: attributes (profile?) $this->elementStart('head'); $this->showTitle(); + $this->showShortcutIcon(); $this->showStylesheets(); $this->showScripts(); $this->showOpenSearch(); @@ -148,6 +149,32 @@ class Action extends HTMLOutputter // lawsuit } /** + * Show themed shortcut icon + * + * @return nothing + */ + function showShortcutIcon() + { + if (is_readable(INSTALLDIR . '/theme/' . common_config('site', 'theme') . '/favicon.ico')) { + $this->element('link', array('rel' => 'shortcut icon', + 'href' => theme_path('favicon.ico'))); + } else { + $this->element('link', array('rel' => 'shortcut icon', + 'href' => common_path('favicon.ico'))); + } + + if (common_config('site', 'mobile')) { + if (is_readable(INSTALLDIR . '/theme/' . common_config('site', 'theme') . '/apple-touch-icon.png')) { + $this->element('link', array('rel' => 'apple-touch-icon', + 'href' => theme_path('apple-touch-icon.png'))); + } else { + $this->element('link', array('rel' => 'apple-touch-icon', + 'href' => common_path('apple-touch-icon.png'))); + } + } + } + + /** * Show stylesheets * * @return nothing diff --git a/lib/common.php b/lib/common.php index 1ca9e521b..c2037c3ad 100644 --- a/lib/common.php +++ b/lib/common.php @@ -87,6 +87,8 @@ $config = 'closed' => false, 'inviteonly' => false, 'private' => false, + 'ssl' => 'never', + 'sslserver' => null, 'dupelimit' => 60), # default for same person saying the same thing 'syslog' => array('appname' => 'laconica', # for syslog @@ -151,6 +153,9 @@ $config = array('notify' => array()), 'inboxes' => array('enabled' => true), # on by default for new sites + 'newuser' => + array('subscribe' => null, + 'welcome' => null), ); $config['db'] = &PEAR::getStaticProperty('DB_DataObject','options'); diff --git a/lib/jabber.php b/lib/jabber.php index 3cd3b0d37..7d584ad01 100644 --- a/lib/jabber.php +++ b/lib/jabber.php @@ -163,50 +163,25 @@ function jabber_send_notice($to, $notice) function jabber_format_entry($profile, $notice) { - // FIXME: notice url might be remote - - $noticeurl = common_local_url('shownotice', - array('notice' => $notice->id)); - - $msg = jabber_format_notice($profile, $notice); - - $self_url = common_local_url('userrss', array('nickname' => $profile->nickname)); - - $entry = "\n<entry xmlns='http://www.w3.org/2005/Atom'>\n"; - $entry .= "<source>\n"; - $entry .= "<title>" . $profile->nickname . " - " . common_config('site', 'name') . "</title>\n"; - $entry .= "<link href='" . htmlspecialchars($profile->profileurl) . "'/>\n"; - $entry .= "<link rel='self' type='application/rss+xml' href='" . $self_url . "'/>\n"; - $entry .= "<author><name>" . $profile->nickname . "</name></author>\n"; - $entry .= "<icon>" . $profile->avatarUrl(AVATAR_PROFILE_SIZE) . "</icon>\n"; - $entry .= "</source>\n"; - $entry .= "<title>" . htmlspecialchars($msg) . "</title>\n"; - $entry .= "<summary>" . htmlspecialchars($msg) . "</summary>\n"; - $entry .= "<link rel='alternate' href='" . $noticeurl . "' />\n"; - $entry .= "<id>". $notice->uri . "</id>\n"; - $entry .= "<published>".common_date_w3dtf($notice->created)."</published>\n"; - $entry .= "<updated>".common_date_w3dtf($notice->modified)."</updated>\n"; - if ($notice->reply_to) { - $replyurl = common_local_url('shownotice', - array('notice' => $notice->reply_to)); - $entry .= "<link rel='related' href='" . $replyurl . "'/>\n"; + $entry = $notice->asAtomEntry(true, true); + + $xs = new XMLStringer(); + $xs->elementStart('html', array('xmlns' => 'http://jabber.org/protocol/xhtml-im')); + $xs->elementStart('body', array('xmlns' => 'http://www.w3.org/1999/xhtml')); + $xs->element('a', array('href' => $profile->profileurl), + $profile->nickname); + $xs->text(": "); + if (!empty($notice->rendered)) { + $xs->raw($notice->rendered); + } else { + $xs->raw(common_render_content($notice->content, $notice)); } - $entry .= "</entry>\n"; - - $html = "\n<html xmlns='http://jabber.org/protocol/xhtml-im'>\n"; - $html .= "<body xmlns='http://www.w3.org/1999/xhtml'>\n"; - $html .= "<a href='".htmlspecialchars($profile->profileurl)."'>".$profile->nickname."</a>: "; - $html .= ($notice->rendered) ? $notice->rendered : common_render_content($notice->content, $notice); - $html .= "\n</body>\n"; - $html .= "\n</html>\n"; - - $address = "<addresses xmlns='http://jabber.org/protocol/address'>\n"; - $address .= "<address type='replyto' jid='" . jabber_daemon_address() . "' />\n"; - $address .= "</addresses>\n"; + $xs->elementEnd('body'); + $xs->elementEnd('html'); - // FIXME: include a pubsub event, too. + $html = $xs->getString(); - return $html . $entry . $address; + return $html . ' ' . $entry; } /** diff --git a/lib/language.php b/lib/language.php index 6791df699..cd6498d30 100644 --- a/lib/language.php +++ b/lib/language.php @@ -115,7 +115,7 @@ function get_all_languages() { 'he' => array('q' => 0.5, 'lang' => 'he_IL', 'name' => 'Hebrew', 'direction' => 'rtl'), 'it' => array('q' => 1, 'lang' => 'it_IT', 'name' => 'Italian', 'direction' => 'ltr'), 'jp' => array('q' => 0.5, 'lang' => 'ja_JP', 'name' => 'Japanese', 'direction' => 'ltr'), - 'ko' => array('q' => 0.9, 'lang' => 'ko', 'name' => 'Korean', 'direction' => 'ltr'), + 'ko' => array('q' => 0.9, 'lang' => 'ko_KR', 'name' => 'Korean', 'direction' => 'ltr'), 'mk' => array('q' => 0.5, 'lang' => 'mk_MK', 'name' => 'Macedonian', 'direction' => 'ltr'), 'nb' => array('q' => 0.1, 'lang' => 'nb_NO', 'name' => 'Norwegian (Bokmål)', 'direction' => 'ltr'), 'no' => array('q' => 0.1, 'lang' => 'nb_NO', 'name' => 'Norwegian (Bokmål)', 'direction' => 'ltr'), diff --git a/lib/logingroupnav.php b/lib/logingroupnav.php index fd909581f..f23985f3a 100644 --- a/lib/logingroupnav.php +++ b/lib/logingroupnav.php @@ -70,16 +70,16 @@ class LoginGroupNav extends Widget function show() { // action => array('prompt', 'title') - $menu = - array('login' => - array(_('Login'), - _('Login with a username and password')), - 'register' => - array(_('Register'), - _('Sign up for a new account')), - 'openidlogin' => - array(_('OpenID'), - _('Login or register with OpenID'))); + $menu = array(); + + $menu['login'] = array(_('Login'), + _('Login with a username and password')); + if (!(common_config('site','closed') || common_config('site','inviteonly'))) { + $menu['register'] = array(_('Register'), + _('Sign up for a new account')); + } + $menu['openidlogin'] = array(_('OpenID'), + _('Login or register with OpenID')); $action_name = $this->action->trimmed('action'); $this->action->elementStart('ul', array('class' => 'nav')); diff --git a/lib/messageform.php b/lib/messageform.php index f41508305..b8878ec1f 100644 --- a/lib/messageform.php +++ b/lib/messageform.php @@ -132,20 +132,14 @@ class MessageForm extends Form $mutual_users->free(); unset($mutual_users); - $this->out->elementStart('ul', 'form_data'); - $this->out->elementStart('li', array('id' => 'notice_to')); $this->out->dropdown('to', _('To'), $mutual, null, false, ($this->to) ? $this->to->id : null); - $this->out->elementEnd('li'); - $this->out->elementStart('li', array('id' => 'notice_text')); $this->out->element('textarea', array('id' => 'notice_data-text', 'cols' => 35, 'rows' => 4, 'name' => 'content'), ($this->content) ? $this->content : ''); - $this->out->elementEnd('li'); - $this->out->elementEnd('ul'); } /** @@ -156,14 +150,10 @@ class MessageForm extends Form function formActions() { - $this->out->elementStart('ul', 'form_actions'); - $this->out->elementStart('li', array('id' => 'notice_submit')); $this->out->element('input', array('id' => 'notice_action-submit', 'class' => 'submit', 'name' => 'message_send', 'type' => 'submit', 'value' => _('Send'))); - $this->out->elementEnd('li'); - $this->out->elementEnd('ul'); } } diff --git a/lib/noticeform.php b/lib/noticeform.php index 0c991c969..606b5d028 100644 --- a/lib/noticeform.php +++ b/lib/noticeform.php @@ -134,9 +134,6 @@ class NoticeForm extends Form function formData() { - - $this->out->elementStart('ul', 'form_data'); - $this->out->elementStart('li', array('id' => 'notice_text')); $this->out->element('label', array('for' => 'notice_data-text'), sprintf(_('What\'s up, %s?'), $this->user->nickname)); // XXX: vary by defined max size @@ -145,8 +142,6 @@ class NoticeForm extends Form 'rows' => 4, 'name' => 'status_textarea'), ($this->content) ? $this->content : ''); - $this->out->elementEnd('li'); - $this->out->elementEnd('ul'); $this->out->elementStart('dl', 'form_note'); $this->out->element('dt', null, _('Available characters')); @@ -168,14 +163,10 @@ class NoticeForm extends Form function formActions() { - $this->out->elementStart('ul', 'form_actions'); - $this->out->elementStart('li', array('id' => 'notice_submit')); $this->out->element('input', array('id' => 'notice_action-submit', 'class' => 'submit', 'name' => 'status_submit', 'type' => 'submit', 'value' => _('Send'))); - $this->out->elementEnd('li'); - $this->out->elementEnd('ul'); } } diff --git a/lib/noticelist.php b/lib/noticelist.php index 8523f2e63..4182d8808 100644 --- a/lib/noticelist.php +++ b/lib/noticelist.php @@ -391,6 +391,7 @@ class NoticeListItem extends Widget case 'xmpp': case 'mail': case 'omb': + case 'system': case 'api': $this->out->element('dd', null, $source_name); break; diff --git a/lib/router.php b/lib/router.php index 135e07a0f..ae5b5e16b 100644 --- a/lib/router.php +++ b/lib/router.php @@ -68,8 +68,8 @@ class Router } } - function initialize() { - + function initialize() + { $m = Net_URL_Mapper::getInstance(); // In the "root" @@ -136,10 +136,17 @@ class Router foreach (array('group', 'people', 'notice') as $s) { $m->connect('search/'.$s, array('action' => $s.'search')); - $m->connect('search/'.$s.'?q=:q', array('action' => $s.'search'), array('q' => '.+')); + $m->connect('search/'.$s.'?q=:q', + array('action' => $s.'search'), + array('q' => '.+')); } + // The second of these is needed to make the link work correctly + // when inserted into the page. The first is needed to match the + // route on the way in. Seems to be another Net_URL_Mapper bug to me. $m->connect('search/notice/rss', array('action' => 'noticesearchrss')); + $m->connect('search/notice/rss?q=:q', array('action' => 'noticesearchrss'), + array('q' => '.+')); // notice @@ -259,8 +266,8 @@ class Router foreach (array('xml', 'json', 'rss', 'atom') as $e) { $m->connect('api/direct_messages/sent.'.$e, array('action' => 'api', - 'apiaction' => 'direct_messages', - 'method' => 'sent.'.$e)); + 'apiaction' => 'direct_messages', + 'method' => 'sent.'.$e)); } $m->connect('api/direct_messages/destroy/:argument', @@ -324,9 +331,9 @@ class Router foreach (array('xml', 'json', 'rss', 'atom') as $e) { $m->connect('api/favorites.'.$e, - array('action' => 'api', - 'apiaction' => 'favorites', - 'method' => 'favorites.'.$e)); + array('action' => 'api', + 'apiaction' => 'favorites', + 'method' => 'favorites.'.$e)); } // notifications @@ -411,7 +418,7 @@ class Router $match = $this->m->match($path); } catch (Net_URL_Mapper_InvalidException $e) { common_log(LOG_ERR, "Problem getting route for $path - " . - $e->getMessage()); + $e->getMessage()); $cac = new ClientErrorAction("Page not found.", 404); $cac->showPage(); } @@ -434,10 +441,11 @@ class Router // Due to a bug in the Net_URL_Mapper code, the returned URL may // contain a malformed query of the form ?p1=v1?p2=v2?p3=v3. We // repair that here rather than modifying the upstream code... - $qpos = strpos($url,'?'); + + $qpos = strpos($url, '?'); if ($qpos !== false) { $url = substr($url, 0, $qpos+1) . - str_replace('?', '&', substr($url, $qpos+1)); + str_replace('?', '&', substr($url, $qpos+1)); } return $url; } diff --git a/lib/rssaction.php b/lib/rssaction.php index 66c2d9e8c..ddba862dc 100644 --- a/lib/rssaction.php +++ b/lib/rssaction.php @@ -94,11 +94,11 @@ class Rss10Action extends Action function handle($args) { - // Get the list of notices - $this->notices = $this->getNotices(); // Parent handling, including cache check parent::handle($args); - $this->showRss($this->limit); + // Get the list of notices + $this->notices = $this->getNotices($this->limit); + $this->showRss(); } /** @@ -132,15 +132,13 @@ class Rss10Action extends Action return null; } - function showRss($limit=0) + function showRss() { - $notices = $this->getNotices($limit); - $this->initRss(); - $this->showChannel($notices); + $this->showChannel(); $this->showImage(); - foreach ($notices as $n) { + foreach ($this->notices as $n) { $this->showItem($n); } @@ -148,7 +146,7 @@ class Rss10Action extends Action $this->endRss(); } - function showChannel($notices) + function showChannel() { $channel = $this->getChannel(); @@ -167,7 +165,7 @@ class Rss10Action extends Action $this->elementStart('items'); $this->elementStart('rdf:Seq'); - foreach ($notices as $notice) { + foreach ($this->notices as $notice) { $this->element('sioct:MicroblogPost', array('rdf:resource' => $notice->uri)); } diff --git a/lib/twitterapi.php b/lib/twitterapi.php index e7239acd5..b8357c688 100644 --- a/lib/twitterapi.php +++ b/lib/twitterapi.php @@ -238,21 +238,6 @@ class TwitterapiAction extends Action $this->elementEnd('item'); } - function show_twitter_atom_entry($entry) - { - $this->elementStart('entry'); - $this->element('title', null, $entry['title']); - $this->element('content', array('type' => 'html'), $entry['content']); - $this->element('id', null, $entry['id']); - $this->element('published', null, $entry['published']); - $this->element('updated', null, $entry['updated']); - $this->element('link', array('href' => $entry['link'], 'rel' => 'alternate', 'type' => 'text/html'), null); - $this->elementStart('author'); - $this->element('name', null, $entry['author']); - $this->elementEnd('author'); - $this->elementEnd('entry'); - } - function show_json_objects($objects) { print(json_encode($objects)); @@ -383,7 +368,7 @@ class TwitterapiAction extends Action } if (!is_null($selfuri)) { - $this->element('link', array('href' => $selfuri, + $this->element('link', array('href' => $selfuri, 'rel' => 'self', 'type' => 'application/atom+xml'), null); } @@ -392,13 +377,11 @@ class TwitterapiAction extends Action if (is_array($notice)) { foreach ($notice as $n) { - $entry = $this->twitter_rss_entry_array($n); - $this->show_twitter_atom_entry($entry); + $this->raw($n->asAtomEntry()); } } else { while ($notice->fetch()) { - $entry = $this->twitter_rss_entry_array($notice); - $this->show_twitter_atom_entry($entry); + $this->raw($notice->asAtomEntry()); } } @@ -578,13 +561,16 @@ class TwitterapiAction extends Action function init_twitter_atom() { $this->startXML(); - $this->elementStart('feed', array('xmlns' => 'http://www.w3.org/2005/Atom', 'xml:lang' => 'en-US')); + // FIXME: don't hardcode the language here! + $this->elementStart('feed', array('xmlns' => 'http://www.w3.org/2005/Atom', + 'xml:lang' => 'en-US', + 'xmlns:thr' => 'http://purl.org/syndication/thread/1.0')); } function end_twitter_atom() { - $this->endXML(); $this->elementEnd('feed'); + $this->endXML(); } function show_profile($profile, $content_type='xml', $notice=null) diff --git a/lib/util.php b/lib/util.php index ef73adc36..fdcae0aca 100644 --- a/lib/util.php +++ b/lib/util.php @@ -721,25 +721,46 @@ function common_relative_profile($sender, $nickname, $dt=null) function common_local_url($action, $args=null, $params=null, $fragment=null) { + static $sensitive = array('login', 'register', 'passwordsettings', + 'twittersettings', 'finishopenidlogin', + 'api'); + $r = Router::get(); $path = $r->build($action, $args, $params, $fragment); + $ssl = in_array($action, $sensitive); + if (common_config('site','fancy')) { - $url = common_path(mb_substr($path, 1)); + $url = common_path(mb_substr($path, 1), $ssl); } else { if (mb_strpos($path, '/index.php') === 0) { - $url = common_path(mb_substr($path, 1)); + $url = common_path(mb_substr($path, 1), $ssl); } else { - $url = common_path('index.php'.$path); + $url = common_path('index.php'.$path, $ssl); } } return $url; } -function common_path($relative) +function common_path($relative, $ssl=false) { $pathpart = (common_config('site', 'path')) ? common_config('site', 'path')."/" : ''; - return "http://".common_config('site', 'server').'/'.$pathpart.$relative; + + if (($ssl && (common_config('site', 'ssl') === 'sometimes')) + || common_config('site', 'ssl') === 'always') { + $proto = 'https'; + if (is_string(common_config('site', 'sslserver')) && + mb_strlen(common_config('site', 'sslserver')) > 0) { + $serverpart = common_config('site', 'sslserver'); + } else { + $serverpart = common_config('site', 'server'); + } + } else { + $proto = 'http'; + $serverpart = common_config('site', 'server'); + } + + return $proto.'://'.$serverpart.'/'.$pathpart.$relative; } function common_date_string($dt) diff --git a/plugins/LinkbackPlugin.php b/plugins/LinkbackPlugin.php index 1b5365100..56a26176b 100644 --- a/plugins/LinkbackPlugin.php +++ b/plugins/LinkbackPlugin.php @@ -105,12 +105,13 @@ class LinkbackPlugin extends Plugin $pb = $match[1]; } - $tb = $this->getTrackback($result->body, $result->final_url); - - if (!empty($tb)) { - $this->trackback($result->final_url, $tb); - } else if (!empty($pb)) { + if (!empty($pb)) { $this->pingback($result->final_url, $pb); + } else { + $tb = $this->getTrackback($result->body, $result->final_url); + if (!empty($tb)) { + $this->trackback($result->final_url, $tb); + } } return $orig; diff --git a/plugins/PiwikAnalyticsPlugin.php b/plugins/PiwikAnalyticsPlugin.php new file mode 100644 index 000000000..d2c52354e --- /dev/null +++ b/plugins/PiwikAnalyticsPlugin.php @@ -0,0 +1,104 @@ +<?php +/** + * Laconica, the distributed open-source microblogging tool + * + * Plugin to use Piwik Analytics + * + * 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 Plugin + * @package Laconica + * @author Evan Prodromou <evan@controlyourself.ca> + * @author Tobias Diekershoff <tobias.diekershoff@gmx.net> + * @copyright 2008 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); +} + +/** + * Plugin to use Piwik Analytics (based on the Google Analytics plugin by Evan) + * + * This plugin will spoot out the correct JavaScript spell to invoke + * Piwik Analytics on a page. + * + * To use this plugin please add the following three lines to your config.php + * + * require_once('plugins/PiwikAnalyticsPlugin.php'); + * $pa = new PiwikAnalyticsPlugin("example.com/piwik/","id"); + * + * exchange example.com/piwik/ with the url to your piwik installation and + * make sure you don't forget the final / + * exchange id with the ID your laconica installation has in your Piwik analytics + * + * @category Plugin + * @package Laconica + * @author Tobias Diekershoff <tobias.diekershoff@gmx.net> + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://laconi.ca/ + * + * @see Event + */ + +class PiwikAnalyticsPlugin extends Plugin +{ + /** the base of your Piwik installation */ + var $piwikroot = null; + /** the Piwik Id of your laconica installation */ + var $piwikId = null; + + /** + * constructor + * + * @param string $root Piwik root URL + * @param string $id Piwik ID of this app + */ + + function __construct($root=null, $id=null) + { + $this->piwikroot = $root; + $this->piwikid = $id; + parent::__construct(); + } + + /** + * Called when all scripts have been shown + * + * @param Action $action Current action + * + * @return boolean ignored + */ + + function onEndShowScripts($action) + { + $js1 = 'var pkBaseURL = (("https:" == document.location.protocol) ? "https://'. + $this->piwikroot.'" : "http://'.$this->piwikroot. + '"); document.write(unescape("%3Cscript src=\'" + pkBaseURL + "piwik.js\''. + ' type=\'text/javascript\'%3E%3C/script%3E"));'; + $js2 = 'piwik_action_name = ""; piwik_idsite = '.$this->piwikid. + '; piwik_url = pkBaseURL + "piwik.php"; piwik_log(piwik_action_name, piwik_idsite, piwik_url);'; + $action->elementStart('script', array('type' => 'text/javascript')); + $action->raw($js1); + $action->elementEnd('script'); + $action->elementStart('script', array('type' => 'text/javascript')); + $action->raw($js2); + $action->elementEnd('script'); + return true; + } +}
\ No newline at end of file diff --git a/theme/base/css/display.css b/theme/base/css/display.css index c741ed4cb..997342429 100644 --- a/theme/base/css/display.css +++ b/theme/base/css/display.css @@ -150,7 +150,9 @@ font-weight:bold; #form_openid_login legend, #form_search legend, #form_invite legend, -#form_notice_delete legend { +#form_notice_delete legend, +#form_password_recover legend, +#form_password_change legend { display:none; } @@ -214,6 +216,9 @@ margin-right:0; address .fn { font-weight:bold; } +address img + .fn { +display:none; +} #header { width:100%; @@ -419,6 +424,7 @@ padding:0; display:none; } #form_notice textarea { +float:left; border-radius:7px; -moz-border-radius:7px; -webkit-border-radius:7px; @@ -429,30 +435,19 @@ padding:7px 7px 16px 7px; } #form_notice label { display:block; +float:left; font-size:1.3em; margin-bottom:7px; } -#form_notice .form_data li { -float:left; -} - -#form_notice #notice_attach_file label, #form_notice #notice_submit label { display:none; } - -#form_notice #notice_attachment { -margin-top:25px; -margin-left:4px; -} - #form_notice .form_note { position:absolute; top:99px; right:98px; z-index:9; } - #form_notice .form_note dt { font-weight:bold; display:none; @@ -462,42 +457,19 @@ font-weight:bold; line-height:1.15; padding:1px 2px; } - -#form_notice #notice_data-attach_view { -position:absolute; -top:25px; -right:30px; -margin-left:4px; -padding:0; -width:16px; -height:16px; -border:0; -text-indent:-9999px; -} -#form_notice .form_actions { +#form_notice #notice_action-submit { +width:60px; +padding:8px; position:absolute; bottom:0; right:0; } -#form_notice .form_actions input.submit { -width:60px; -padding:8px; -} - -#form_notice li { -margin-bottom:0; -} - -#form_notice #notice_to { -margin-bottom:7px; -} - -#notice_to label { -float:left; -margin-right:18px; +#form_notice label[for=to] { margin-top:11px; } -#notice_to select { +#form_notice select[id=to] { +margin-bottom:7px; +margin-left:18px; float:left; } /*end FORM NOTICE*/ diff --git a/theme/base/css/ie6.css b/theme/base/css/ie6.css index 10b31cbcb..fa6ec92d2 100644 --- a/theme/base/css/ie6.css +++ b/theme/base/css/ie6.css @@ -9,3 +9,6 @@ margin-left:0; .entity_profile .entity_depiction { margin-bottom:123px; } +.notice div.entry-content { +width:63%; +} diff --git a/theme/base/images/icons/icon_processing.gif b/theme/base/images/icons/icon_processing.gif Binary files differnew file mode 100644 index 000000000..d0bce1542 --- /dev/null +++ b/theme/base/images/icons/icon_processing.gif diff --git a/theme/default/css/display.css b/theme/default/css/display.css index 85b5aa13e..12303dd68 100644 --- a/theme/default/css/display.css +++ b/theme/default/css/display.css @@ -19,9 +19,6 @@ font-size:1em; address { margin-right:71px; } -address .fn { -display:none; -} input, textarea, select, option { font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; @@ -94,6 +91,11 @@ 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; +} #nav_register a { diff --git a/theme/identica/css/display.css b/theme/identica/css/display.css index 576a2e14b..5235c34a4 100644 --- a/theme/identica/css/display.css +++ b/theme/identica/css/display.css @@ -19,9 +19,6 @@ font-size:1em; address { margin-right:71px; } -address .fn { -display:none; -} input, textarea, select, option { font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif; @@ -94,7 +91,11 @@ 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; +} #nav_register a { text-decoration:none; |