Merge branch '0.7.x' of git@gitorious.org:laconica/dev into 0.7.x
This commit is contained in:
commit
590cc0c9a4
24
README
24
README
@ -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.
|
||||
|
||||
default: 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
|
||||
===============
|
||||
|
||||
|
@ -93,7 +93,8 @@ class BlockAction extends Action
|
||||
if ($this->arg('no')) {
|
||||
$cur = common_current_user();
|
||||
$other = Profile::staticGet('id', $this->arg('blockto'));
|
||||
common_redirect(common_local_url('showstream', array('nickname' => $other->nickname)));
|
||||
common_redirect(common_local_url('showstream', array('nickname' => $other->nickname)),
|
||||
303);
|
||||
} elseif ($this->arg('yes')) {
|
||||
$this->blockProfile();
|
||||
} elseif ($this->arg('blockto')) {
|
||||
@ -102,7 +103,6 @@ class BlockAction extends Action
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function showContent() {
|
||||
$this->areYouSureForm();
|
||||
}
|
||||
@ -110,7 +110,7 @@ class BlockAction extends Action
|
||||
function title() {
|
||||
return _('Block user');
|
||||
}
|
||||
|
||||
|
||||
function showNoticeForm() {
|
||||
// nop
|
||||
}
|
||||
@ -178,10 +178,11 @@ class BlockAction extends Action
|
||||
}
|
||||
|
||||
if ($action) {
|
||||
common_redirect(common_local_url($action, $args));
|
||||
common_redirect(common_local_url($action, $args), 303);
|
||||
} else {
|
||||
common_redirect(common_local_url('subscriptions',
|
||||
array('nickname' => $cur->nickname)));
|
||||
array('nickname' => $cur->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -141,6 +141,6 @@ class DeletenoticeAction extends DeleteAction
|
||||
$url = common_local_url('public');
|
||||
}
|
||||
|
||||
common_redirect($url);
|
||||
common_redirect($url, 303);
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ class DisfavorAction extends Action
|
||||
{
|
||||
/**
|
||||
* Class handler.
|
||||
*
|
||||
*
|
||||
* @param array $args query arguments
|
||||
*
|
||||
* @return void
|
||||
@ -100,7 +100,8 @@ class DisfavorAction extends Action
|
||||
$this->elementEnd('html');
|
||||
} else {
|
||||
common_redirect(common_local_url('showfavorites',
|
||||
array('nickname' => $user->nickname)));
|
||||
array('nickname' => $user->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -166,7 +166,6 @@ class EditgroupAction extends Action
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
$nickname = common_canonical_nickname($this->trimmed('nickname'));
|
||||
$fullname = $this->trimmed('fullname');
|
||||
$homepage = $this->trimmed('homepage');
|
||||
@ -221,7 +220,7 @@ class EditgroupAction extends Action
|
||||
if ($this->group->nickname != $orig->nickname) {
|
||||
common_redirect(common_local_url('editgroup',
|
||||
array('nickname' => $nickname)),
|
||||
307);
|
||||
303);
|
||||
} else {
|
||||
$this->showForm(_('Options saved.'));
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ class FavorAction extends Action
|
||||
{
|
||||
/**
|
||||
* Class handler.
|
||||
*
|
||||
*
|
||||
* @param array $args query arguments
|
||||
*
|
||||
* @return void
|
||||
@ -100,13 +100,14 @@ class FavorAction extends Action
|
||||
$this->elementEnd('html');
|
||||
} else {
|
||||
common_redirect(common_local_url('showfavorites',
|
||||
array('nickname' => $user->nickname)));
|
||||
array('nickname' => $user->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies a user when his notice is favorited.
|
||||
*
|
||||
*
|
||||
* @param class $notice favorited notice
|
||||
* @param class $user user declaring a favorite
|
||||
*
|
||||
|
@ -139,7 +139,7 @@ class FinishaddopenidAction extends Action
|
||||
|
||||
oid_set_last($display);
|
||||
|
||||
common_redirect(common_local_url('openidsettings'));
|
||||
common_redirect(common_local_url('openidsettings'), 303);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -271,7 +271,8 @@ class FinishopenidloginAction extends Action
|
||||
common_rememberme($user);
|
||||
}
|
||||
unset($_SESSION['openid_rememberme']);
|
||||
common_redirect(common_local_url('showstream', array('nickname' => $user->nickname)));
|
||||
common_redirect(common_local_url('showstream', array('nickname' => $user->nickname)),
|
||||
303);
|
||||
}
|
||||
|
||||
function connectUser()
|
||||
@ -324,7 +325,7 @@ class FinishopenidloginAction extends Action
|
||||
array('nickname' =>
|
||||
$nickname));
|
||||
}
|
||||
common_redirect($url);
|
||||
common_redirect($url, 303);
|
||||
}
|
||||
|
||||
function bestNewNickname($display, $sreg)
|
||||
|
@ -230,7 +230,8 @@ class FinishremotesubscribeAction extends Action
|
||||
# show up close to the top of the page
|
||||
|
||||
common_redirect(common_local_url('subscribers', array('nickname' =>
|
||||
$user->nickname)));
|
||||
$user->nickname)),
|
||||
303);
|
||||
}
|
||||
|
||||
function add_avatar($profile, $url)
|
||||
|
@ -33,7 +33,24 @@ class FoafAction extends Action
|
||||
function prepare($args)
|
||||
{
|
||||
parent::prepare($args);
|
||||
$this->nickname = $this->trimmed('nickname');
|
||||
|
||||
$nickname_arg = $this->arg('nickname');
|
||||
|
||||
if (empty($nickname_arg)) {
|
||||
$this->clientError(_('No such user.'), 404);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->nickname = common_canonical_nickname($nickname_arg);
|
||||
|
||||
// Permanent redirect on non-canonical nickname
|
||||
|
||||
if ($nickname_arg != $this->nickname) {
|
||||
common_redirect(common_local_url('foaf',
|
||||
array('nickname' => $this->nickname)),
|
||||
301);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->user = User::staticGet('nickname', $this->nickname);
|
||||
|
||||
@ -122,20 +139,30 @@ class FoafAction extends Action
|
||||
|
||||
if ($sub->find()) {
|
||||
while ($sub->fetch()) {
|
||||
if ($sub->token) {
|
||||
if (!empty($sub->token)) {
|
||||
$other = Remote_profile::staticGet('id', $sub->subscribed);
|
||||
} else {
|
||||
$other = User::staticGet('id', $sub->subscribed);
|
||||
}
|
||||
if (!$other) {
|
||||
if (empty($other)) {
|
||||
common_debug('Got a bad subscription: '.print_r($sub,true));
|
||||
continue;
|
||||
}
|
||||
$this->element('knows', array('rdf:resource' => $other->uri));
|
||||
$person[$other->uri] = array(LISTENEE, $other);
|
||||
$person[$other->uri] = array(LISTENEE,
|
||||
$other->id,
|
||||
$other->nickname,
|
||||
(empty($sub->token)) ? 'User' : 'Remote_profile');
|
||||
$other->free();
|
||||
$other = null;
|
||||
unset($other);
|
||||
}
|
||||
}
|
||||
|
||||
$sub->free();
|
||||
$sub = null;
|
||||
unset($sub);
|
||||
|
||||
// Get people who subscribe to user
|
||||
|
||||
$sub = new Subscription();
|
||||
@ -156,25 +183,36 @@ class FoafAction extends Action
|
||||
if (array_key_exists($other->uri, $person)) {
|
||||
$person[$other->uri][0] = BOTH;
|
||||
} else {
|
||||
$person[$other->uri] = array(LISTENER, $other);
|
||||
$person[$other->uri] = array(LISTENER,
|
||||
$other->id,
|
||||
$other->nickname,
|
||||
(empty($sub->token)) ? 'User' : 'Remote_profile');
|
||||
}
|
||||
$other->free();
|
||||
$other = null;
|
||||
unset($other);
|
||||
}
|
||||
}
|
||||
|
||||
$sub->free();
|
||||
$sub = null;
|
||||
unset($sub);
|
||||
|
||||
$this->elementEnd('Person');
|
||||
|
||||
foreach ($person as $uri => $p) {
|
||||
$foaf_url = null;
|
||||
if ($p[1] instanceof User) {
|
||||
$foaf_url = common_local_url('foaf', array('nickname' => $p[1]->nickname));
|
||||
list($type, $id, $nickname, $cls) = $p;
|
||||
if ($cls == 'User') {
|
||||
$foaf_url = common_local_url('foaf', array('nickname' => $nickname));
|
||||
}
|
||||
$this->profile = Profile::staticGet($p[1]->id);
|
||||
$profile = Profile::staticGet($id);
|
||||
$this->elementStart('Person', array('rdf:about' => $uri));
|
||||
if ($p[0] == LISTENER || $p[0] == BOTH) {
|
||||
if ($type == LISTENER || $type == BOTH) {
|
||||
$this->element('knows', array('rdf:resource' => $this->user->uri));
|
||||
}
|
||||
$this->showMicrobloggingAccount($this->profile, ($p[1] instanceof User) ?
|
||||
common_root_url() : null);
|
||||
$this->showMicrobloggingAccount($profile, ($cls == 'User') ?
|
||||
common_root_url() : null);
|
||||
if ($foaf_url) {
|
||||
$this->element('rdfs:seeAlso', array('rdf:resource' => $foaf_url));
|
||||
}
|
||||
@ -182,6 +220,9 @@ class FoafAction extends Action
|
||||
if ($foaf_url) {
|
||||
$this->showPpd($foaf_url, $uri);
|
||||
}
|
||||
$profile->free();
|
||||
$profile = null;
|
||||
unset($profile);
|
||||
}
|
||||
|
||||
$this->elementEnd('rdf:RDF');
|
||||
|
@ -143,7 +143,8 @@ class JoingroupAction extends Action
|
||||
$this->elementEnd('html');
|
||||
} else {
|
||||
common_redirect(common_local_url('groupmembers', array('nickname' =>
|
||||
$this->group->nickname)));
|
||||
$this->group->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
}
|
@ -147,7 +147,8 @@ class LeavegroupAction extends Action
|
||||
$this->elementEnd('html');
|
||||
} else {
|
||||
common_redirect(common_local_url('groupmembers', array('nickname' =>
|
||||
$this->group->nickname)));
|
||||
$this->group->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ class LoginAction extends Action
|
||||
$nickname));
|
||||
}
|
||||
|
||||
common_redirect($url);
|
||||
common_redirect($url, 303);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -46,10 +46,10 @@ require_once INSTALLDIR.'/lib/openid.php';
|
||||
*/
|
||||
class LogoutAction extends Action
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* This is read only.
|
||||
*
|
||||
*
|
||||
* @return boolean true
|
||||
*/
|
||||
function isReadOnly()
|
||||
@ -59,7 +59,7 @@ class LogoutAction extends Action
|
||||
|
||||
/**
|
||||
* Class handler.
|
||||
*
|
||||
*
|
||||
* @param array $args array of arguments
|
||||
*
|
||||
* @return nothing
|
||||
@ -73,7 +73,7 @@ class LogoutAction extends Action
|
||||
common_set_user(null);
|
||||
common_real_login(false); // not logged in
|
||||
common_forgetme(); // don't log back in!
|
||||
common_redirect(common_local_url('public'));
|
||||
common_redirect(common_local_url('public'), 303);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ class NewgroupAction extends Action
|
||||
|
||||
$group->query('COMMIT');
|
||||
|
||||
common_redirect($group->homeUrl(), 307);
|
||||
common_redirect($group->homeUrl(), 303);
|
||||
}
|
||||
|
||||
function nicknameExists($nickname)
|
||||
|
@ -122,9 +122,10 @@ class NoticesearchAction extends SearchAction
|
||||
|
||||
$cnt = $nl->show();
|
||||
|
||||
$this->pagination($this->page > 1, $cnt > NOTICES_PER_PAGE,
|
||||
$this->page, 'noticesearch', array('q' => $q));
|
||||
$this->pagination($page > 1, $cnt > NOTICES_PER_PAGE,
|
||||
$page, 'noticesearch', array('q' => $q));
|
||||
}
|
||||
|
||||
function isReadOnly()
|
||||
{
|
||||
return true;
|
||||
|
@ -50,7 +50,7 @@ class NudgeAction extends Action
|
||||
{
|
||||
/**
|
||||
* Class handler.
|
||||
*
|
||||
*
|
||||
* @param array $args array of arguments
|
||||
*
|
||||
* @return nothing
|
||||
@ -75,7 +75,7 @@ class NudgeAction extends Action
|
||||
|
||||
// CSRF protection
|
||||
$token = $this->trimmed('token');
|
||||
|
||||
|
||||
if (!$token || $token != common_session_token()) {
|
||||
$this->clientError(_('There was a problem with your session token. Try again, please.'));
|
||||
return;
|
||||
@ -100,7 +100,8 @@ class NudgeAction extends Action
|
||||
} else {
|
||||
// display a confirmation to the user
|
||||
common_redirect(common_local_url('showstream',
|
||||
array('nickname' => $other->nickname)));
|
||||
array('nickname' => $other->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,6 +166,34 @@ class PublicAction extends Action
|
||||
$nav->show();
|
||||
}
|
||||
|
||||
function showPageNotice()
|
||||
{
|
||||
$notice = Notice::publicStream(0, 1);
|
||||
|
||||
if (!$notice) {
|
||||
$this->serverError(_('Could not retrieve public stream.'));
|
||||
return;
|
||||
}
|
||||
|
||||
// no notices in the public stream, let's get out of here
|
||||
if ($notice->count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$message = _('This is the public timeline for %%site.name%% but noone has posted anything yet.') . ' ';
|
||||
|
||||
if (common_logged_in()) {
|
||||
$message .= _('Be the first to post!');
|
||||
}
|
||||
else {
|
||||
$message .= _('Why not [register an account](%%action.register%%) and be the first to post!');
|
||||
}
|
||||
|
||||
$this->elementStart('div', 'blankfiller');
|
||||
$this->raw(common_markup_to_html($message));
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the content area
|
||||
*
|
||||
|
@ -62,6 +62,24 @@ class PublictagcloudAction extends Action
|
||||
$this->element('p', 'instructions',
|
||||
sprintf(_('These are most popular recent tags on %s '),
|
||||
common_config('site', 'name')));
|
||||
|
||||
$tags = new Notice_tag();
|
||||
if ($tags->count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$message = _('Noone has posted a notice with a [hashtag](%%doc.tags%%) yet.') . ' ';
|
||||
|
||||
if (common_logged_in()) {
|
||||
$message .= _('Be the first to post one!');
|
||||
}
|
||||
else {
|
||||
$message .= _('Why not [register an account](%%action.register%%) and be the first to post one!');
|
||||
}
|
||||
|
||||
$this->elementStart('div', 'blankfiller');
|
||||
$this->raw(common_markup_to_html($message));
|
||||
$this->elementEnd('div');
|
||||
}
|
||||
|
||||
function showLocalNav()
|
||||
|
@ -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');
|
||||
}
|
||||
|
||||
|
@ -97,9 +97,9 @@ class RemotesubscribeAction extends Action
|
||||
'class' => 'form_settings',
|
||||
'action' => common_local_url('remotesubscribe')));
|
||||
$this->elementStart('fieldset');
|
||||
$this->element('legend', 'Subscribe to a remote user');
|
||||
$this->element('legend', _('Subscribe to a remote user'));
|
||||
$this->hidden('token', common_session_token());
|
||||
|
||||
|
||||
$this->elementStart('ul', 'form_data');
|
||||
$this->elementStart('li');
|
||||
$this->input('nickname', _('User nickname'), $this->nickname,
|
||||
@ -407,7 +407,7 @@ class RemotesubscribeAction extends Action
|
||||
|
||||
# Redirect to authorization service
|
||||
|
||||
common_redirect($req->to_url());
|
||||
common_redirect($req->to_url(), 303);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -73,11 +73,17 @@ class ShowgroupAction extends Action
|
||||
|
||||
function title()
|
||||
{
|
||||
if (!empty($this->group->fullname)) {
|
||||
$base = $this->group->fullname . ' (' . $this->group->nickname . ')';
|
||||
} else {
|
||||
$base = $this->group->nickname;
|
||||
}
|
||||
|
||||
if ($this->page == 1) {
|
||||
return sprintf(_("%s group"), $this->group->nickname);
|
||||
return sprintf(_("%s group"), $base);
|
||||
} else {
|
||||
return sprintf(_("%s group, page %d"),
|
||||
$this->group->nickname,
|
||||
$base,
|
||||
$this->page);
|
||||
}
|
||||
}
|
||||
|
@ -67,11 +67,17 @@ class ShowstreamAction extends Action
|
||||
|
||||
function title()
|
||||
{
|
||||
if (!empty($this->profile->fullname)) {
|
||||
$base = $this->profile->fullname . ' (' . $this->user->nickname . ') ';
|
||||
} else {
|
||||
$base = $this->user->nickname;
|
||||
}
|
||||
|
||||
if ($this->page == 1) {
|
||||
return $this->user->nickname;
|
||||
return $base;
|
||||
} else {
|
||||
return sprintf(_("%s, page %d"),
|
||||
$this->user->nickname,
|
||||
$base,
|
||||
$this->page);
|
||||
}
|
||||
}
|
||||
@ -140,16 +146,6 @@ class ShowstreamAction extends Action
|
||||
$nav->show();
|
||||
}
|
||||
|
||||
function showPageTitle()
|
||||
{
|
||||
$user =& common_current_user();
|
||||
if ($user && ($user->id == $this->profile->id)) {
|
||||
$this->element('h1', NULL, _("Your profile"));
|
||||
} else {
|
||||
$this->element('h1', NULL, sprintf(_('%s\'s profile'), $this->profile->nickname));
|
||||
}
|
||||
}
|
||||
|
||||
function showPageNoticeBlock()
|
||||
{
|
||||
return;
|
||||
|
@ -488,7 +488,8 @@ class SmssettingsAction extends ConnectSettingsAction
|
||||
}
|
||||
|
||||
common_redirect(common_local_url('confirmaddress',
|
||||
array('code' => $code)));
|
||||
array('code' => $code)),
|
||||
303);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,7 +85,8 @@ class SubeditAction extends Action
|
||||
}
|
||||
|
||||
common_redirect(common_local_url('subscriptions',
|
||||
array('nickname' => $cur->nickname)));
|
||||
array('nickname' => $cur->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,8 @@ class SubscribeAction extends Action
|
||||
$this->elementEnd('html');
|
||||
} else {
|
||||
common_redirect(common_local_url('subscriptions', array('nickname' =>
|
||||
$user->nickname)));
|
||||
$user->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ class SupAction extends Action
|
||||
function availablePeriods()
|
||||
{
|
||||
static $periods = array(86400, 43200, 21600, 7200,
|
||||
3600, 1800, 600, 300, 120,
|
||||
3600, 1800, 600, 300, 120,
|
||||
60, 30, 15);
|
||||
$available = array();
|
||||
foreach ($periods as $period) {
|
||||
|
@ -33,7 +33,9 @@ class TagAction extends Action
|
||||
}
|
||||
|
||||
if ($this->tag != $taginput) {
|
||||
common_redirect(common_local_url('tag', array('tag' => $this->tag)));
|
||||
common_redirect(common_local_url('tag', array('tag' => $this->tag)),
|
||||
301);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->page = ($this->arg('page')) ? ($this->arg('page')+0) : 1;
|
||||
|
@ -221,7 +221,8 @@ class TagotherAction extends Action
|
||||
$this->elementEnd('html');
|
||||
} else {
|
||||
common_redirect(common_local_url($action, array('nickname' =>
|
||||
$user->nickname)));
|
||||
$user->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,10 +116,11 @@ class UnblockAction extends Action
|
||||
}
|
||||
}
|
||||
if ($action) {
|
||||
common_redirect(common_local_url($action, $args));
|
||||
common_redirect(common_local_url($action, $args), 303);
|
||||
} else {
|
||||
common_redirect(common_local_url('subscriptions',
|
||||
array('nickname' => $cur->nickname)));
|
||||
array('nickname' => $cur->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +77,8 @@ class UnsubscribeAction extends Action
|
||||
$this->elementEnd('html');
|
||||
} else {
|
||||
common_redirect(common_local_url('subscriptions', array('nickname' =>
|
||||
$user->nickname)));
|
||||
$user->nickname)),
|
||||
303);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
145
classes/User.php
145
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);
|
||||
|
||||
|
@ -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';
|
||||
|
@ -13,7 +13,7 @@ create table profile (
|
||||
|
||||
index profile_nickname_idx (nickname),
|
||||
FULLTEXT(nickname, fullname, location, bio, homepage)
|
||||
) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
create table avatar (
|
||||
profile_id integer not null comment 'foreign key to profile table' references profile (id),
|
||||
@ -73,7 +73,7 @@ create table user (
|
||||
modified timestamp comment 'date this record was modified',
|
||||
|
||||
index user_smsemail_idx (smsemail)
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
/* remote people */
|
||||
|
||||
@ -103,7 +103,6 @@ create table subscription (
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
||||
create table notice (
|
||||
|
||||
id integer auto_increment primary key comment 'unique identifier',
|
||||
profile_id integer not null comment 'who made the update' references profile (id),
|
||||
uri varchar(255) unique key comment 'universally unique identifier, usually a tag URI',
|
||||
@ -119,7 +118,7 @@ create table notice (
|
||||
index notice_profile_id_idx (profile_id),
|
||||
index notice_created_idx (created),
|
||||
FULLTEXT(content)
|
||||
) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
create table notice_source (
|
||||
code varchar(32) primary key not null comment 'source code',
|
||||
@ -130,7 +129,6 @@ create table notice_source (
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
||||
create table reply (
|
||||
|
||||
notice_id integer not null comment 'notice that is the reply' references notice (id),
|
||||
profile_id integer not null comment 'profile replied to' references profile (id),
|
||||
modified timestamp not null comment 'date this record was modified',
|
||||
@ -144,7 +142,6 @@ create table reply (
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
||||
create table fave (
|
||||
|
||||
notice_id integer not null comment 'notice that is the favorite' references notice (id),
|
||||
user_id integer not null comment 'user who likes this notice' references user (id),
|
||||
modified timestamp not null comment 'date this record was modified',
|
||||
@ -321,7 +318,6 @@ create table invitation (
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
||||
create table message (
|
||||
|
||||
id integer auto_increment primary key comment 'unique identifier',
|
||||
uri varchar(255) unique key comment 'universally unique identifier',
|
||||
from_profile integer not null comment 'who the message is from' references profile (id),
|
||||
@ -336,10 +332,9 @@ create table message (
|
||||
index message_from_idx (from_profile),
|
||||
index message_to_idx (to_profile),
|
||||
index message_created_idx (created)
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
create table notice_inbox (
|
||||
|
||||
user_id integer not null comment 'user receiving the message' references user (id),
|
||||
notice_id integer not null comment 'notice received' references notice (id),
|
||||
created datetime not null comment 'date the notice was created',
|
||||
@ -362,7 +357,6 @@ create table profile_tag (
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
||||
create table profile_block (
|
||||
|
||||
blocker integer not null comment 'user making the block' references user (id),
|
||||
blocked integer not null comment 'profile that is blocked' references profile (id),
|
||||
modified timestamp comment 'date of blocking',
|
||||
@ -372,7 +366,6 @@ create table profile_block (
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
||||
create table user_group (
|
||||
|
||||
id integer auto_increment primary key comment 'unique identifier',
|
||||
|
||||
nickname varchar(64) unique key comment 'nickname for addressing',
|
||||
@ -391,10 +384,9 @@ create table user_group (
|
||||
|
||||
index user_group_nickname_idx (nickname)
|
||||
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
create table group_member (
|
||||
|
||||
group_id integer not null comment 'foreign key to user_group' references user_group (id),
|
||||
profile_id integer not null comment 'foreign key to profile table' references profile (id),
|
||||
is_admin boolean default false comment 'is this user an admin?',
|
||||
@ -409,7 +401,6 @@ create table group_member (
|
||||
) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin;
|
||||
|
||||
create table related_group (
|
||||
|
||||
group_id integer not null comment 'foreign key to user_group' references user_group (id),
|
||||
related_group_id integer not null comment 'foreign key to user_group' references user_group (id),
|
||||
|
||||
|
@ -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());
|
||||
|
499
js/jquery.js
vendored
499
js/jquery.js
vendored
@ -1,13 +1,13 @@
|
||||
/*!
|
||||
* jQuery JavaScript Library v1.3.1
|
||||
* jQuery JavaScript Library v1.3.2
|
||||
* http://jquery.com/
|
||||
*
|
||||
* Copyright (c) 2009 John Resig
|
||||
* Dual licensed under the MIT and GPL licenses.
|
||||
* http://docs.jquery.com/License
|
||||
*
|
||||
* Date: 2009-01-21 20:42:16 -0500 (Wed, 21 Jan 2009)
|
||||
* Revision: 6158
|
||||
* Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
|
||||
* Revision: 6246
|
||||
*/
|
||||
(function(){
|
||||
|
||||
@ -88,14 +88,16 @@ jQuery.fn = jQuery.prototype = {
|
||||
this.context = selector.context;
|
||||
}
|
||||
|
||||
return this.setArray(jQuery.makeArray(selector));
|
||||
return this.setArray(jQuery.isArray( selector ) ?
|
||||
selector :
|
||||
jQuery.makeArray(selector));
|
||||
},
|
||||
|
||||
// Start with an empty selector
|
||||
selector: "",
|
||||
|
||||
// The current version of jQuery being used
|
||||
jquery: "1.3.1",
|
||||
jquery: "1.3.2",
|
||||
|
||||
// The number of elements contained in the matched element set
|
||||
size: function() {
|
||||
@ -108,7 +110,7 @@ jQuery.fn = jQuery.prototype = {
|
||||
return num === undefined ?
|
||||
|
||||
// Return a 'clean' array
|
||||
jQuery.makeArray( this ) :
|
||||
Array.prototype.slice.call( this ) :
|
||||
|
||||
// Return just the object
|
||||
this[ num ];
|
||||
@ -278,23 +280,21 @@ jQuery.fn = jQuery.prototype = {
|
||||
},
|
||||
|
||||
// For internal use only.
|
||||
// Behaves like an Array's .push method, not like a jQuery method.
|
||||
// Behaves like an Array's method, not like a jQuery method.
|
||||
push: [].push,
|
||||
sort: [].sort,
|
||||
splice: [].splice,
|
||||
|
||||
find: function( selector ) {
|
||||
if ( this.length === 1 && !/,/.test(selector) ) {
|
||||
if ( this.length === 1 ) {
|
||||
var ret = this.pushStack( [], "find", selector );
|
||||
ret.length = 0;
|
||||
jQuery.find( selector, this[0], ret );
|
||||
return ret;
|
||||
} else {
|
||||
var elems = jQuery.map(this, function(elem){
|
||||
return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){
|
||||
return jQuery.find( selector, elem );
|
||||
});
|
||||
|
||||
return this.pushStack( /[^+>] [^+>]/.test( selector ) ?
|
||||
jQuery.unique( elems ) :
|
||||
elems, "find", selector );
|
||||
})), "find", selector );
|
||||
}
|
||||
},
|
||||
|
||||
@ -310,33 +310,37 @@ jQuery.fn = jQuery.prototype = {
|
||||
// attributes in IE that are actually only stored
|
||||
// as properties will not be copied (such as the
|
||||
// the name attribute on an input).
|
||||
var clone = this.cloneNode(true),
|
||||
container = document.createElement("div");
|
||||
container.appendChild(clone);
|
||||
return jQuery.clean([container.innerHTML])[0];
|
||||
var html = this.outerHTML;
|
||||
if ( !html ) {
|
||||
var div = this.ownerDocument.createElement("div");
|
||||
div.appendChild( this.cloneNode(true) );
|
||||
html = div.innerHTML;
|
||||
}
|
||||
|
||||
return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0];
|
||||
} else
|
||||
return this.cloneNode(true);
|
||||
});
|
||||
|
||||
// Need to set the expando to null on the cloned set if it exists
|
||||
// removeData doesn't work here, IE removes it from the original as well
|
||||
// this is primarily for IE but the data expando shouldn't be copied over in any browser
|
||||
var clone = ret.find("*").andSelf().each(function(){
|
||||
if ( this[ expando ] !== undefined )
|
||||
this[ expando ] = null;
|
||||
});
|
||||
|
||||
// Copy the events from the original to the clone
|
||||
if ( events === true )
|
||||
this.find("*").andSelf().each(function(i){
|
||||
if (this.nodeType == 3)
|
||||
return;
|
||||
var events = jQuery.data( this, "events" );
|
||||
if ( events === true ) {
|
||||
var orig = this.find("*").andSelf(), i = 0;
|
||||
|
||||
for ( var type in events )
|
||||
for ( var handler in events[ type ] )
|
||||
jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
|
||||
ret.find("*").andSelf().each(function(){
|
||||
if ( this.nodeName !== orig[i].nodeName )
|
||||
return;
|
||||
|
||||
var events = jQuery.data( orig[i], "events" );
|
||||
|
||||
for ( var type in events ) {
|
||||
for ( var handler in events[ type ] ) {
|
||||
jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
});
|
||||
}
|
||||
|
||||
// Return the cloned set
|
||||
return ret;
|
||||
@ -355,14 +359,18 @@ jQuery.fn = jQuery.prototype = {
|
||||
},
|
||||
|
||||
closest: function( selector ) {
|
||||
var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null;
|
||||
var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null,
|
||||
closer = 0;
|
||||
|
||||
return this.map(function(){
|
||||
var cur = this;
|
||||
while ( cur && cur.ownerDocument ) {
|
||||
if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) )
|
||||
if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
|
||||
jQuery.data(cur, "closest", closer);
|
||||
return cur;
|
||||
}
|
||||
cur = cur.parentNode;
|
||||
closer++;
|
||||
}
|
||||
});
|
||||
},
|
||||
@ -475,7 +483,7 @@ jQuery.fn = jQuery.prototype = {
|
||||
html: function( value ) {
|
||||
return value === undefined ?
|
||||
(this[0] ?
|
||||
this[0].innerHTML :
|
||||
this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :
|
||||
null) :
|
||||
this.empty().append( value );
|
||||
},
|
||||
@ -507,13 +515,13 @@ jQuery.fn = jQuery.prototype = {
|
||||
if ( this[0] ) {
|
||||
var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
|
||||
scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
|
||||
first = fragment.firstChild,
|
||||
extra = this.length > 1 ? fragment.cloneNode(true) : fragment;
|
||||
first = fragment.firstChild;
|
||||
|
||||
if ( first )
|
||||
for ( var i = 0, l = this.length; i < l; i++ )
|
||||
callback.call( root(this[i], first), i > 0 ? extra.cloneNode(true) : fragment );
|
||||
|
||||
callback.call( root(this[i], first), this.length > 1 || i > 0 ?
|
||||
fragment.cloneNode(true) : fragment );
|
||||
|
||||
if ( scripts )
|
||||
jQuery.each( scripts, evalScript );
|
||||
}
|
||||
@ -636,9 +644,7 @@ jQuery.extend({
|
||||
|
||||
// Evalulates a script in a global context
|
||||
globalEval: function( data ) {
|
||||
data = jQuery.trim( data );
|
||||
|
||||
if ( data ) {
|
||||
if ( data && /\S/.test(data) ) {
|
||||
// Inspired by code by Andrea Giammarchi
|
||||
// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
|
||||
var head = document.getElementsByTagName("head")[0] || document.documentElement,
|
||||
@ -741,26 +747,32 @@ jQuery.extend({
|
||||
elem.style[ name ] = old[ name ];
|
||||
},
|
||||
|
||||
css: function( elem, name, force ) {
|
||||
css: function( elem, name, force, extra ) {
|
||||
if ( name == "width" || name == "height" ) {
|
||||
var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
|
||||
|
||||
function getWH() {
|
||||
val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
|
||||
var padding = 0, border = 0;
|
||||
|
||||
if ( extra === "border" )
|
||||
return;
|
||||
|
||||
jQuery.each( which, function() {
|
||||
padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
|
||||
border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
|
||||
if ( !extra )
|
||||
val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
|
||||
if ( extra === "margin" )
|
||||
val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
|
||||
else
|
||||
val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
|
||||
});
|
||||
val -= Math.round(padding + border);
|
||||
}
|
||||
|
||||
if ( jQuery(elem).is(":visible") )
|
||||
if ( elem.offsetWidth !== 0 )
|
||||
getWH();
|
||||
else
|
||||
jQuery.swap( elem, props, getWH );
|
||||
|
||||
return Math.max(0, val);
|
||||
return Math.max(0, Math.round(val));
|
||||
}
|
||||
|
||||
return jQuery.curCSS( elem, name, force );
|
||||
@ -866,7 +878,7 @@ jQuery.extend({
|
||||
});
|
||||
|
||||
// Trim whitespace, otherwise indexOf won't work as expected
|
||||
var tags = jQuery.trim( elem ).toLowerCase();
|
||||
var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
|
||||
|
||||
var wrap =
|
||||
// option or optgroup
|
||||
@ -906,11 +918,12 @@ jQuery.extend({
|
||||
if ( !jQuery.support.tbody ) {
|
||||
|
||||
// String was a <table>, *may* have spurious <tbody>
|
||||
var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
|
||||
div.firstChild && div.firstChild.childNodes :
|
||||
var hasBody = /<tbody/i.test(elem),
|
||||
tbody = !tags.indexOf("<table") && !hasBody ?
|
||||
div.firstChild && div.firstChild.childNodes :
|
||||
|
||||
// String was a bare <thead> or <tfoot>
|
||||
wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
|
||||
wrap[1] == "<table>" && !hasBody ?
|
||||
div.childNodes :
|
||||
[];
|
||||
|
||||
@ -1189,13 +1202,16 @@ jQuery.each({
|
||||
insertAfter: "after",
|
||||
replaceAll: "replaceWith"
|
||||
}, function(name, original){
|
||||
jQuery.fn[ name ] = function() {
|
||||
var args = arguments;
|
||||
jQuery.fn[ name ] = function( selector ) {
|
||||
var ret = [], insert = jQuery( selector );
|
||||
|
||||
return this.each(function(){
|
||||
for ( var i = 0, length = args.length; i < length; i++ )
|
||||
jQuery( args[ i ] )[ original ]( this );
|
||||
});
|
||||
for ( var i = 0, l = insert.length; i < l; i++ ) {
|
||||
var elems = (i > 0 ? this.clone(true) : this).get();
|
||||
jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
|
||||
ret = ret.concat( elems );
|
||||
}
|
||||
|
||||
return this.pushStack( ret, name, selector );
|
||||
};
|
||||
});
|
||||
|
||||
@ -1234,7 +1250,7 @@ jQuery.each({
|
||||
|
||||
empty: function() {
|
||||
// Remove element nodes and prevent memory leaks
|
||||
jQuery( ">*", this ).remove();
|
||||
jQuery(this).children().remove();
|
||||
|
||||
// Remove any remaining nodes
|
||||
while ( this.firstChild )
|
||||
@ -1402,7 +1418,7 @@ jQuery.fn.extend({
|
||||
*/
|
||||
(function(){
|
||||
|
||||
var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]+['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])(\s*,\s*)?/g,
|
||||
var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,
|
||||
done = 0,
|
||||
toString = Object.prototype.toString;
|
||||
|
||||
@ -1507,6 +1523,19 @@ var Sizzle = function(selector, context, results, seed) {
|
||||
|
||||
if ( extra ) {
|
||||
Sizzle( extra, context, results, seed );
|
||||
|
||||
if ( sortOrder ) {
|
||||
hasDuplicate = false;
|
||||
results.sort(sortOrder);
|
||||
|
||||
if ( hasDuplicate ) {
|
||||
for ( var i = 1; i < results.length; i++ ) {
|
||||
if ( results[i] === results[i-1] ) {
|
||||
results.splice(i--, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
@ -1548,7 +1577,8 @@ Sizzle.find = function(expr, context, isXML){
|
||||
};
|
||||
|
||||
Sizzle.filter = function(expr, set, inplace, not){
|
||||
var old = expr, result = [], curLoop = set, match, anyFound;
|
||||
var old = expr, result = [], curLoop = set, match, anyFound,
|
||||
isXMLFilter = set && set[0] && isXML(set[0]);
|
||||
|
||||
while ( expr && set.length ) {
|
||||
for ( var type in Expr.filter ) {
|
||||
@ -1561,7 +1591,7 @@ Sizzle.filter = function(expr, set, inplace, not){
|
||||
}
|
||||
|
||||
if ( Expr.preFilter[ type ] ) {
|
||||
match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not );
|
||||
match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
|
||||
|
||||
if ( !match ) {
|
||||
anyFound = found = true;
|
||||
@ -1606,8 +1636,6 @@ Sizzle.filter = function(expr, set, inplace, not){
|
||||
}
|
||||
}
|
||||
|
||||
expr = expr.replace(/\s*,\s*/, "");
|
||||
|
||||
// Improper expression
|
||||
if ( expr == old ) {
|
||||
if ( anyFound == null ) {
|
||||
@ -1645,26 +1673,33 @@ var Expr = Sizzle.selectors = {
|
||||
}
|
||||
},
|
||||
relative: {
|
||||
"+": function(checkSet, part){
|
||||
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
|
||||
var elem = checkSet[i];
|
||||
if ( elem ) {
|
||||
var cur = elem.previousSibling;
|
||||
while ( cur && cur.nodeType !== 1 ) {
|
||||
cur = cur.previousSibling;
|
||||
}
|
||||
checkSet[i] = typeof part === "string" ?
|
||||
cur || false :
|
||||
cur === part;
|
||||
"+": function(checkSet, part, isXML){
|
||||
var isPartStr = typeof part === "string",
|
||||
isTag = isPartStr && !/\W/.test(part),
|
||||
isPartStrNotTag = isPartStr && !isTag;
|
||||
|
||||
if ( isTag && !isXML ) {
|
||||
part = part.toUpperCase();
|
||||
}
|
||||
|
||||
for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
|
||||
if ( (elem = checkSet[i]) ) {
|
||||
while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
|
||||
|
||||
checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
|
||||
elem || false :
|
||||
elem === part;
|
||||
}
|
||||
}
|
||||
|
||||
if ( typeof part === "string" ) {
|
||||
if ( isPartStrNotTag ) {
|
||||
Sizzle.filter( part, checkSet, true );
|
||||
}
|
||||
},
|
||||
">": function(checkSet, part, isXML){
|
||||
if ( typeof part === "string" && !/\W/.test(part) ) {
|
||||
var isPartStr = typeof part === "string";
|
||||
|
||||
if ( isPartStr && !/\W/.test(part) ) {
|
||||
part = isXML ? part : part.toUpperCase();
|
||||
|
||||
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
|
||||
@ -1678,19 +1713,19 @@ var Expr = Sizzle.selectors = {
|
||||
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
|
||||
var elem = checkSet[i];
|
||||
if ( elem ) {
|
||||
checkSet[i] = typeof part === "string" ?
|
||||
checkSet[i] = isPartStr ?
|
||||
elem.parentNode :
|
||||
elem.parentNode === part;
|
||||
}
|
||||
}
|
||||
|
||||
if ( typeof part === "string" ) {
|
||||
if ( isPartStr ) {
|
||||
Sizzle.filter( part, checkSet, true );
|
||||
}
|
||||
}
|
||||
},
|
||||
"": function(checkSet, part, isXML){
|
||||
var doneName = "done" + (done++), checkFn = dirCheck;
|
||||
var doneName = done++, checkFn = dirCheck;
|
||||
|
||||
if ( !part.match(/\W/) ) {
|
||||
var nodeCheck = part = isXML ? part : part.toUpperCase();
|
||||
@ -1700,7 +1735,7 @@ var Expr = Sizzle.selectors = {
|
||||
checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
|
||||
},
|
||||
"~": function(checkSet, part, isXML){
|
||||
var doneName = "done" + (done++), checkFn = dirCheck;
|
||||
var doneName = done++, checkFn = dirCheck;
|
||||
|
||||
if ( typeof part === "string" && !part.match(/\W/) ) {
|
||||
var nodeCheck = part = isXML ? part : part.toUpperCase();
|
||||
@ -1718,8 +1753,16 @@ var Expr = Sizzle.selectors = {
|
||||
}
|
||||
},
|
||||
NAME: function(match, context, isXML){
|
||||
if ( typeof context.getElementsByName !== "undefined" && !isXML ) {
|
||||
return context.getElementsByName(match[1]);
|
||||
if ( typeof context.getElementsByName !== "undefined" ) {
|
||||
var ret = [], results = context.getElementsByName(match[1]);
|
||||
|
||||
for ( var i = 0, l = results.length; i < l; i++ ) {
|
||||
if ( results[i].getAttribute("name") === match[1] ) {
|
||||
ret.push( results[i] );
|
||||
}
|
||||
}
|
||||
|
||||
return ret.length === 0 ? null : ret;
|
||||
}
|
||||
},
|
||||
TAG: function(match, context){
|
||||
@ -1727,13 +1770,16 @@ var Expr = Sizzle.selectors = {
|
||||
}
|
||||
},
|
||||
preFilter: {
|
||||
CLASS: function(match, curLoop, inplace, result, not){
|
||||
CLASS: function(match, curLoop, inplace, result, not, isXML){
|
||||
match = " " + match[1].replace(/\\/g, "") + " ";
|
||||
|
||||
var elem;
|
||||
for ( var i = 0; (elem = curLoop[i]) != null; i++ ) {
|
||||
if ( isXML ) {
|
||||
return match;
|
||||
}
|
||||
|
||||
for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
|
||||
if ( elem ) {
|
||||
if ( not ^ (" " + elem.className + " ").indexOf(match) >= 0 ) {
|
||||
if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
|
||||
if ( !inplace )
|
||||
result.push( elem );
|
||||
} else if ( inplace ) {
|
||||
@ -1764,14 +1810,14 @@ var Expr = Sizzle.selectors = {
|
||||
}
|
||||
|
||||
// TODO: Move to normal caching system
|
||||
match[0] = "done" + (done++);
|
||||
match[0] = done++;
|
||||
|
||||
return match;
|
||||
},
|
||||
ATTR: function(match){
|
||||
ATTR: function(match, curLoop, inplace, result, not, isXML){
|
||||
var name = match[1].replace(/\\/g, "");
|
||||
|
||||
if ( Expr.attrMap[name] ) {
|
||||
if ( !isXML && Expr.attrMap[name] ) {
|
||||
match[1] = Expr.attrMap[name];
|
||||
}
|
||||
|
||||
@ -1784,7 +1830,7 @@ var Expr = Sizzle.selectors = {
|
||||
PSEUDO: function(match, curLoop, inplace, result, not){
|
||||
if ( match[1] === "not" ) {
|
||||
// If we're dealing with a complex expression, or a simple one
|
||||
if ( match[3].match(chunker).length > 1 ) {
|
||||
if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) {
|
||||
match[3] = Sizzle(match[3], null, null, curLoop);
|
||||
} else {
|
||||
var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
|
||||
@ -1793,7 +1839,7 @@ var Expr = Sizzle.selectors = {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else if ( Expr.match.POS.test( match[0] ) ) {
|
||||
} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1890,47 +1936,6 @@ var Expr = Sizzle.selectors = {
|
||||
}
|
||||
},
|
||||
filter: {
|
||||
CHILD: function(elem, match){
|
||||
var type = match[1], parent = elem.parentNode;
|
||||
|
||||
var doneName = match[0];
|
||||
|
||||
if ( parent && (!parent[ doneName ] || !elem.nodeIndex) ) {
|
||||
var count = 1;
|
||||
|
||||
for ( var node = parent.firstChild; node; node = node.nextSibling ) {
|
||||
if ( node.nodeType == 1 ) {
|
||||
node.nodeIndex = count++;
|
||||
}
|
||||
}
|
||||
|
||||
parent[ doneName ] = count - 1;
|
||||
}
|
||||
|
||||
if ( type == "first" ) {
|
||||
return elem.nodeIndex == 1;
|
||||
} else if ( type == "last" ) {
|
||||
return elem.nodeIndex == parent[ doneName ];
|
||||
} else if ( type == "only" ) {
|
||||
return parent[ doneName ] == 1;
|
||||
} else if ( type == "nth" ) {
|
||||
var add = false, first = match[2], last = match[3];
|
||||
|
||||
if ( first == 1 && last == 0 ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( first == 0 ) {
|
||||
if ( elem.nodeIndex == last ) {
|
||||
add = true;
|
||||
}
|
||||
} else if ( (elem.nodeIndex - last) % first == 0 && (elem.nodeIndex - last) / first >= 0 ) {
|
||||
add = true;
|
||||
}
|
||||
|
||||
return add;
|
||||
}
|
||||
},
|
||||
PSEUDO: function(elem, match, i, array){
|
||||
var name = match[1], filter = Expr.filters[ name ];
|
||||
|
||||
@ -1950,6 +1955,49 @@ var Expr = Sizzle.selectors = {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
CHILD: function(elem, match){
|
||||
var type = match[1], node = elem;
|
||||
switch (type) {
|
||||
case 'only':
|
||||
case 'first':
|
||||
while (node = node.previousSibling) {
|
||||
if ( node.nodeType === 1 ) return false;
|
||||
}
|
||||
if ( type == 'first') return true;
|
||||
node = elem;
|
||||
case 'last':
|
||||
while (node = node.nextSibling) {
|
||||
if ( node.nodeType === 1 ) return false;
|
||||
}
|
||||
return true;
|
||||
case 'nth':
|
||||
var first = match[2], last = match[3];
|
||||
|
||||
if ( first == 1 && last == 0 ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var doneName = match[0],
|
||||
parent = elem.parentNode;
|
||||
|
||||
if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
|
||||
var count = 0;
|
||||
for ( node = parent.firstChild; node; node = node.nextSibling ) {
|
||||
if ( node.nodeType === 1 ) {
|
||||
node.nodeIndex = ++count;
|
||||
}
|
||||
}
|
||||
parent.sizcache = doneName;
|
||||
}
|
||||
|
||||
var diff = elem.nodeIndex - last;
|
||||
if ( first == 0 ) {
|
||||
return diff == 0;
|
||||
} else {
|
||||
return ( diff % first == 0 && diff / first >= 0 );
|
||||
}
|
||||
}
|
||||
},
|
||||
ID: function(elem, match){
|
||||
return elem.nodeType === 1 && elem.getAttribute("id") === match;
|
||||
},
|
||||
@ -1957,10 +2005,20 @@ var Expr = Sizzle.selectors = {
|
||||
return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
|
||||
},
|
||||
CLASS: function(elem, match){
|
||||
return match.test( elem.className );
|
||||
return (" " + (elem.className || elem.getAttribute("class")) + " ")
|
||||
.indexOf( match ) > -1;
|
||||
},
|
||||
ATTR: function(elem, match){
|
||||
var result = Expr.attrHandle[ match[1] ] ? Expr.attrHandle[ match[1] ]( elem ) : elem[ match[1] ] || elem.getAttribute( match[1] ), value = result + "", type = match[2], check = match[4];
|
||||
var name = match[1],
|
||||
result = Expr.attrHandle[ name ] ?
|
||||
Expr.attrHandle[ name ]( elem ) :
|
||||
elem[ name ] != null ?
|
||||
elem[ name ] :
|
||||
elem.getAttribute( name ),
|
||||
value = result + "",
|
||||
type = match[2],
|
||||
check = match[4];
|
||||
|
||||
return result == null ?
|
||||
type === "!=" :
|
||||
type === "=" ?
|
||||
@ -1969,8 +2027,8 @@ var Expr = Sizzle.selectors = {
|
||||
value.indexOf(check) >= 0 :
|
||||
type === "~=" ?
|
||||
(" " + value + " ").indexOf(check) >= 0 :
|
||||
!match[4] ?
|
||||
result :
|
||||
!check ?
|
||||
value && result !== false :
|
||||
type === "!=" ?
|
||||
value != check :
|
||||
type === "^=" ?
|
||||
@ -2036,6 +2094,39 @@ try {
|
||||
};
|
||||
}
|
||||
|
||||
var sortOrder;
|
||||
|
||||
if ( document.documentElement.compareDocumentPosition ) {
|
||||
sortOrder = function( a, b ) {
|
||||
var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
|
||||
if ( ret === 0 ) {
|
||||
hasDuplicate = true;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
} else if ( "sourceIndex" in document.documentElement ) {
|
||||
sortOrder = function( a, b ) {
|
||||
var ret = a.sourceIndex - b.sourceIndex;
|
||||
if ( ret === 0 ) {
|
||||
hasDuplicate = true;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
} else if ( document.createRange ) {
|
||||
sortOrder = function( a, b ) {
|
||||
var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
|
||||
aRange.selectNode(a);
|
||||
aRange.collapse(true);
|
||||
bRange.selectNode(b);
|
||||
bRange.collapse(true);
|
||||
var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
|
||||
if ( ret === 0 ) {
|
||||
hasDuplicate = true;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
// Check to see if the browser returns elements by name when
|
||||
// querying by getElementById (and provide a workaround)
|
||||
(function(){
|
||||
@ -2099,7 +2190,8 @@ try {
|
||||
|
||||
// Check to see if an attribute returns normalized href attributes
|
||||
div.innerHTML = "<a href='#'></a>";
|
||||
if ( div.firstChild && div.firstChild.getAttribute("href") !== "#" ) {
|
||||
if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
|
||||
div.firstChild.getAttribute("href") !== "#" ) {
|
||||
Expr.attrHandle.href = function(elem){
|
||||
return elem.getAttribute("href", 2);
|
||||
};
|
||||
@ -2136,29 +2228,50 @@ if ( document.querySelectorAll ) (function(){
|
||||
Sizzle.matches = oldSizzle.matches;
|
||||
})();
|
||||
|
||||
if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) {
|
||||
if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
|
||||
var div = document.createElement("div");
|
||||
div.innerHTML = "<div class='test e'></div><div class='test'></div>";
|
||||
|
||||
// Opera can't find a second classname (in 9.6)
|
||||
if ( div.getElementsByClassName("e").length === 0 )
|
||||
return;
|
||||
|
||||
// Safari caches class attributes, doesn't catch changes (in 3.2)
|
||||
div.lastChild.className = "e";
|
||||
|
||||
if ( div.getElementsByClassName("e").length === 1 )
|
||||
return;
|
||||
|
||||
Expr.order.splice(1, 0, "CLASS");
|
||||
Expr.find.CLASS = function(match, context) {
|
||||
return context.getElementsByClassName(match[1]);
|
||||
Expr.find.CLASS = function(match, context, isXML) {
|
||||
if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
|
||||
return context.getElementsByClassName(match[1]);
|
||||
}
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
||||
function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
|
||||
var sibDir = dir == "previousSibling" && !isXML;
|
||||
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
|
||||
var elem = checkSet[i];
|
||||
if ( elem ) {
|
||||
if ( sibDir && elem.nodeType === 1 ){
|
||||
elem.sizcache = doneName;
|
||||
elem.sizset = i;
|
||||
}
|
||||
elem = elem[dir];
|
||||
var match = false;
|
||||
|
||||
while ( elem && elem.nodeType ) {
|
||||
var done = elem[doneName];
|
||||
if ( done ) {
|
||||
match = checkSet[ done ];
|
||||
while ( elem ) {
|
||||
if ( elem.sizcache === doneName ) {
|
||||
match = checkSet[elem.sizset];
|
||||
break;
|
||||
}
|
||||
|
||||
if ( elem.nodeType === 1 && !isXML )
|
||||
elem[doneName] = i;
|
||||
if ( elem.nodeType === 1 && !isXML ){
|
||||
elem.sizcache = doneName;
|
||||
elem.sizset = i;
|
||||
}
|
||||
|
||||
if ( elem.nodeName === cur ) {
|
||||
match = elem;
|
||||
@ -2174,22 +2287,28 @@ function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
|
||||
}
|
||||
|
||||
function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
|
||||
var sibDir = dir == "previousSibling" && !isXML;
|
||||
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
|
||||
var elem = checkSet[i];
|
||||
if ( elem ) {
|
||||
if ( sibDir && elem.nodeType === 1 ) {
|
||||
elem.sizcache = doneName;
|
||||
elem.sizset = i;
|
||||
}
|
||||
elem = elem[dir];
|
||||
var match = false;
|
||||
|
||||
while ( elem && elem.nodeType ) {
|
||||
if ( elem[doneName] ) {
|
||||
match = checkSet[ elem[doneName] ];
|
||||
while ( elem ) {
|
||||
if ( elem.sizcache === doneName ) {
|
||||
match = checkSet[elem.sizset];
|
||||
break;
|
||||
}
|
||||
|
||||
if ( elem.nodeType === 1 ) {
|
||||
if ( !isXML )
|
||||
elem[doneName] = i;
|
||||
|
||||
if ( !isXML ) {
|
||||
elem.sizcache = doneName;
|
||||
elem.sizset = i;
|
||||
}
|
||||
if ( typeof cur !== "string" ) {
|
||||
if ( elem === cur ) {
|
||||
match = true;
|
||||
@ -2248,15 +2367,11 @@ jQuery.expr = Sizzle.selectors;
|
||||
jQuery.expr[":"] = jQuery.expr.filters;
|
||||
|
||||
Sizzle.selectors.filters.hidden = function(elem){
|
||||
return "hidden" === elem.type ||
|
||||
jQuery.css(elem, "display") === "none" ||
|
||||
jQuery.css(elem, "visibility") === "hidden";
|
||||
return elem.offsetWidth === 0 || elem.offsetHeight === 0;
|
||||
};
|
||||
|
||||
Sizzle.selectors.filters.visible = function(elem){
|
||||
return "hidden" !== elem.type &&
|
||||
jQuery.css(elem, "display") !== "none" &&
|
||||
jQuery.css(elem, "visibility") !== "hidden";
|
||||
return elem.offsetWidth > 0 || elem.offsetHeight > 0;
|
||||
};
|
||||
|
||||
Sizzle.selectors.filters.animated = function(elem){
|
||||
@ -2552,7 +2667,8 @@ jQuery.event = {
|
||||
var all, handlers;
|
||||
|
||||
event = arguments[0] = jQuery.event.fix( event || window.event );
|
||||
|
||||
event.currentTarget = this;
|
||||
|
||||
// Namespaced event handlers
|
||||
var namespaces = event.type.split(".");
|
||||
event.type = namespaces.shift();
|
||||
@ -2883,9 +2999,13 @@ function liveHandler( event ){
|
||||
}
|
||||
});
|
||||
|
||||
elems.sort(function(a,b) {
|
||||
return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest");
|
||||
});
|
||||
|
||||
jQuery.each(elems, function(){
|
||||
if ( this.fn.call(this.elem, event, this.fn.data) === false )
|
||||
stop = false;
|
||||
return (stop = false);
|
||||
});
|
||||
|
||||
return stop;
|
||||
@ -2949,7 +3069,7 @@ function bindReady(){
|
||||
|
||||
// If IE and not an iframe
|
||||
// continually check to see if the document is ready
|
||||
if ( document.documentElement.doScroll && typeof window.frameElement === "undefined" ) (function(){
|
||||
if ( document.documentElement.doScroll && window == window.top ) (function(){
|
||||
if ( jQuery.isReady ) return;
|
||||
|
||||
try {
|
||||
@ -3079,12 +3199,11 @@ jQuery( window ).bind( 'unload', function(){
|
||||
// document.body must exist before we can do this
|
||||
jQuery(function(){
|
||||
var div = document.createElement("div");
|
||||
div.style.width = "1px";
|
||||
div.style.paddingLeft = "1px";
|
||||
div.style.width = div.style.paddingLeft = "1px";
|
||||
|
||||
document.body.appendChild( div );
|
||||
jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
|
||||
document.body.removeChild( div );
|
||||
document.body.removeChild( div ).style.display = 'none';
|
||||
});
|
||||
})();
|
||||
|
||||
@ -3175,7 +3294,7 @@ jQuery.fn.extend({
|
||||
.filter(function(){
|
||||
return this.name && !this.disabled &&
|
||||
(this.checked || /select|textarea/i.test(this.nodeName) ||
|
||||
/text|hidden|password/i.test(this.type));
|
||||
/text|hidden|password|search/i.test(this.type));
|
||||
})
|
||||
.map(function(i, elem){
|
||||
var val = jQuery(this).val();
|
||||
@ -3371,6 +3490,9 @@ jQuery.extend({
|
||||
done = true;
|
||||
success();
|
||||
complete();
|
||||
|
||||
// Handle memory leak in IE
|
||||
script.onload = script.onreadystatechange = null;
|
||||
head.removeChild( script );
|
||||
}
|
||||
};
|
||||
@ -3686,9 +3808,15 @@ jQuery.fn.extend({
|
||||
elemdisplay[ tagName ] = display;
|
||||
}
|
||||
|
||||
this[i].style.display = jQuery.data(this[i], "olddisplay", display);
|
||||
jQuery.data(this[i], "olddisplay", display);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the display of the elements in a second loop
|
||||
// to avoid the constant reflow
|
||||
for ( var i = 0, l = this.length; i < l; i++ ){
|
||||
this[i].style.display = jQuery.data(this[i], "olddisplay") || "";
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
@ -3702,8 +3830,14 @@ jQuery.fn.extend({
|
||||
var old = jQuery.data(this[i], "olddisplay");
|
||||
if ( !old && old !== "none" )
|
||||
jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
|
||||
}
|
||||
|
||||
// Set the display of the elements in a second loop
|
||||
// to avoid the constant reflow
|
||||
for ( var i = 0, l = this.length; i < l; i++ ){
|
||||
this[i].style.display = "none";
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
},
|
||||
@ -3915,7 +4049,7 @@ jQuery.fx.prototype = {
|
||||
|
||||
t.elem = this.elem;
|
||||
|
||||
if ( t() && jQuery.timers.push(t) == 1 ) {
|
||||
if ( t() && jQuery.timers.push(t) && !timerId ) {
|
||||
timerId = setInterval(function(){
|
||||
var timers = jQuery.timers;
|
||||
|
||||
@ -3925,6 +4059,7 @@ jQuery.fx.prototype = {
|
||||
|
||||
if ( !timers.length ) {
|
||||
clearInterval( timerId );
|
||||
timerId = undefined;
|
||||
}
|
||||
}, 13);
|
||||
}
|
||||
@ -4193,22 +4328,21 @@ jQuery.each( ['Left', 'Top'], function(i, name) {
|
||||
jQuery.each([ "Height", "Width" ], function(i, name){
|
||||
|
||||
var tl = i ? "Left" : "Top", // top or left
|
||||
br = i ? "Right" : "Bottom"; // bottom or right
|
||||
br = i ? "Right" : "Bottom", // bottom or right
|
||||
lower = name.toLowerCase();
|
||||
|
||||
// innerHeight and innerWidth
|
||||
jQuery.fn["inner" + name] = function(){
|
||||
return this[ name.toLowerCase() ]() +
|
||||
num(this, "padding" + tl) +
|
||||
num(this, "padding" + br);
|
||||
return this[0] ?
|
||||
jQuery.css( this[0], lower, false, "padding" ) :
|
||||
null;
|
||||
};
|
||||
|
||||
// outerHeight and outerWidth
|
||||
jQuery.fn["outer" + name] = function(margin) {
|
||||
return this["inner" + name]() +
|
||||
num(this, "border" + tl + "Width") +
|
||||
num(this, "border" + br + "Width") +
|
||||
(margin ?
|
||||
num(this, "margin" + tl) + num(this, "margin" + br) : 0);
|
||||
return this[0] ?
|
||||
jQuery.css( this[0], lower, false, margin ? "margin" : "border" ) :
|
||||
null;
|
||||
};
|
||||
|
||||
var type = name.toLowerCase();
|
||||
@ -4238,4 +4372,5 @@ jQuery.each([ "Height", "Width" ], function(i, name){
|
||||
this.css( type, typeof size === "string" ? size : size + "px" );
|
||||
};
|
||||
|
||||
});})();
|
||||
});
|
||||
})();
|
||||
|
10
js/jquery.min.js
vendored
10
js/jquery.min.js
vendored
File diff suppressed because one or more lines are too long
@ -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");
|
||||
}
|
||||
|
@ -326,7 +326,9 @@ class Action extends HTMLOutputter // lawsuit
|
||||
*/
|
||||
function showBody()
|
||||
{
|
||||
$this->elementStart('body', array('id' => $this->trimmed('action')));
|
||||
$this->elementStart('body', (common_current_user()) ? array('id' => $this->trimmed('action'),
|
||||
'class' => 'user_in')
|
||||
: array('id' => $this->trimmed('action')));
|
||||
$this->elementStart('div', array('id' => 'wrap'));
|
||||
if (Event::handle('StartShowHeader', array($this))) {
|
||||
$this->showHeader();
|
||||
|
@ -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');
|
||||
|
@ -163,50 +163,25 @@ function jabber_send_notice($to, $notice)
|
||||
|
||||
function jabber_format_entry($profile, $notice)
|
||||
{
|
||||
// FIXME: notice url might be remote
|
||||
$entry = $notice->asAtomEntry(true, true);
|
||||
|
||||
$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";
|
||||
$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";
|
||||
$xs->elementEnd('body');
|
||||
$xs->elementEnd('html');
|
||||
|
||||
$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";
|
||||
$html = $xs->getString();
|
||||
|
||||
$address = "<addresses xmlns='http://jabber.org/protocol/address'>\n";
|
||||
$address .= "<address type='replyto' jid='" . jabber_daemon_address() . "' />\n";
|
||||
$address .= "</addresses>\n";
|
||||
|
||||
// FIXME: include a pubsub event, too.
|
||||
|
||||
return $html . $entry . $address;
|
||||
return $html . ' ' . $entry;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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'),
|
||||
|
10
lib/mail.php
10
lib/mail.php
@ -554,17 +554,19 @@ function mail_notify_fave($other, $user, $notice)
|
||||
|
||||
$body = sprintf(_("%1\$s just added your notice from %2\$s".
|
||||
" as one of their favorites.\n\n" .
|
||||
"In case you forgot, you can see the text".
|
||||
" of your notice here:\n\n" .
|
||||
"The URL of your notice is:\n\n" .
|
||||
"%3\$s\n\n" .
|
||||
"You can see the list of %1\$s's favorites here:\n\n" .
|
||||
"The text of your notice is:\n\n" .
|
||||
"%4\$s\n\n" .
|
||||
"You can see the list of %1\$s's favorites here:\n\n" .
|
||||
"%5\$s\n\n" .
|
||||
"Faithfully yours,\n" .
|
||||
"%5\$s\n"),
|
||||
"%6\$s\n"),
|
||||
$bestname,
|
||||
common_exact_date($notice->created),
|
||||
common_local_url('shownotice',
|
||||
array('notice' => $notice->id)),
|
||||
$notice->content,
|
||||
common_local_url('showfavorites',
|
||||
array('nickname' => $user->nickname)),
|
||||
common_config('site', 'name'));
|
||||
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
@ -258,8 +258,12 @@ class NoticeListItem extends Widget
|
||||
function showAuthor()
|
||||
{
|
||||
$this->out->elementStart('span', 'vcard author');
|
||||
$this->out->elementStart('a', array('href' => $this->profile->profileurl,
|
||||
'class' => 'url'));
|
||||
$attrs = array('href' => $this->profile->profileurl,
|
||||
'class' => 'url');
|
||||
if (!empty($this->profile->fullname)) {
|
||||
$attrs['title'] = $this->profile->fullname . ' (' . $this->profile->nickname . ') ';
|
||||
}
|
||||
$this->out->elementStart('a', $attrs);
|
||||
$this->showAvatar();
|
||||
$this->showNickname();
|
||||
$this->out->elementEnd('a');
|
||||
@ -387,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;
|
||||
|
@ -160,7 +160,7 @@ function oid_authenticate($openid_url, $returnto, $immediate=false)
|
||||
$auth_request->addExtension($sreg_request);
|
||||
}
|
||||
|
||||
$trust_root = common_path('');
|
||||
$trust_root = common_root_url(true);
|
||||
$process_url = common_local_url($returnto);
|
||||
|
||||
if ($auth_request->shouldSendRedirect()) {
|
||||
@ -171,7 +171,7 @@ function oid_authenticate($openid_url, $returnto, $immediate=false)
|
||||
} else if (Auth_OpenID::isFailure($redirect_url)) {
|
||||
return sprintf(_('Could not redirect to server: %s'), $redirect_url->message);
|
||||
} else {
|
||||
common_redirect($redirect_url);
|
||||
common_redirect($redirect_url, 303);
|
||||
}
|
||||
} else {
|
||||
// Generate form markup and render it.
|
||||
|
10
lib/ping.php
10
lib/ping.php
@ -48,9 +48,17 @@ function ping_broadcast_notice($notice) {
|
||||
'header' =>
|
||||
"Content-Type: text/xml\r\n".
|
||||
"User-Agent: Laconica/".LACONICA_VERSION."\r\n",
|
||||
'content' => $request)));
|
||||
'content' => $req)));
|
||||
$file = file_get_contents($notify_url, false, $context);
|
||||
|
||||
if ($file === false || mb_strlen($file) == 0) {
|
||||
common_log(LOG_WARNING,
|
||||
"XML-RPC empty results for ping ($notify_url, $notice->id) ");
|
||||
continue;
|
||||
}
|
||||
|
||||
$response = xmlrpc_decode($file);
|
||||
|
||||
if (xmlrpc_is_fault($response)) {
|
||||
common_log(LOG_WARNING,
|
||||
"XML-RPC error for ping ($notify_url, $notice->id) ".
|
||||
|
@ -109,7 +109,7 @@ class ProfileList extends Widget
|
||||
$this->out->elementEnd('span');
|
||||
$this->out->elementEnd('a');
|
||||
|
||||
if ($this->profile->fullname !== '') {
|
||||
if (!empty($this->profile->fullname)) {
|
||||
$this->out->elementStart('dl', 'entity_fn');
|
||||
$this->out->element('dt', null, 'Full name');
|
||||
$this->out->elementStart('dd');
|
||||
@ -119,7 +119,7 @@ class ProfileList extends Widget
|
||||
$this->out->elementEnd('dd');
|
||||
$this->out->elementEnd('dl');
|
||||
}
|
||||
if ($this->profile->location !== '') {
|
||||
if (!empty($this->profile->location)) {
|
||||
$this->out->elementStart('dl', 'entity_location');
|
||||
$this->out->element('dt', null, _('Location'));
|
||||
$this->out->elementStart('dd', 'label');
|
||||
@ -127,7 +127,7 @@ class ProfileList extends Widget
|
||||
$this->out->elementEnd('dd');
|
||||
$this->out->elementEnd('dl');
|
||||
}
|
||||
if ($this->profile->homepage !== '') {
|
||||
if (!empty($this->profile->homepage)) {
|
||||
$this->out->elementStart('dl', 'entity_url');
|
||||
$this->out->element('dt', null, _('URL'));
|
||||
$this->out->elementStart('dd');
|
||||
@ -138,7 +138,7 @@ class ProfileList extends Widget
|
||||
$this->out->elementEnd('dd');
|
||||
$this->out->elementEnd('dl');
|
||||
}
|
||||
if ($this->profile->bio !== '') {
|
||||
if (!empty($this->profile->bio)) {
|
||||
$this->out->elementStart('dl', 'entity_note');
|
||||
$this->out->element('dt', null, _('Note'));
|
||||
$this->out->elementStart('dd', 'note');
|
||||
@ -194,11 +194,12 @@ class ProfileList extends Widget
|
||||
|
||||
$this->out->elementStart('ul');
|
||||
|
||||
if (!$is_own) {
|
||||
# XXX: special-case for user looking at own
|
||||
# subscriptions page
|
||||
// Is this a logged-in user, looking at someone else's
|
||||
// profile?
|
||||
|
||||
if (!empty($user) && $this->profile->id != $user->id) {
|
||||
$this->out->elementStart('li', 'entity_subscribe');
|
||||
if (!is_null($user) && $user->isSubscribed($this->profile)) {
|
||||
if ($user->isSubscribed($this->profile)) {
|
||||
$usf = new UnsubscribeForm($this->out, $this->profile);
|
||||
$usf->show();
|
||||
} else {
|
||||
@ -207,6 +208,9 @@ class ProfileList extends Widget
|
||||
}
|
||||
$this->out->elementEnd('li');
|
||||
$this->out->elementStart('li', 'entity_block');
|
||||
if ($user->id == $this->owner->id) {
|
||||
$this->showBlockForm();
|
||||
}
|
||||
$this->out->elementEnd('li');
|
||||
}
|
||||
|
||||
|
@ -68,8 +68,8 @@ class Router
|
||||
}
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
|
||||
function initialize()
|
||||
{
|
||||
$m = Net_URL_Mapper::getInstance();
|
||||
|
||||
// In the "root"
|
||||
@ -107,6 +107,9 @@ class Router
|
||||
$m->connect('main/'.$a, array('action' => $a));
|
||||
}
|
||||
|
||||
$m->connect('main/sup/:seconds', array('action' => 'sup'),
|
||||
array('seconds' => '[0-9]+'));
|
||||
|
||||
$m->connect('main/tagother/:id', array('action' => 'tagother'));
|
||||
|
||||
// these take a code
|
||||
@ -136,10 +139,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 +269,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 +334,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 +421,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();
|
||||
}
|
||||
@ -429,6 +439,17 @@ class Router
|
||||
$args = $action_arg;
|
||||
}
|
||||
|
||||
return $this->m->generate($args, $params, $fragment);
|
||||
$url = $this->m->generate($args, $params, $fragment);
|
||||
|
||||
// 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, '?');
|
||||
if ($qpos !== false) {
|
||||
$url = substr($url, 0, $qpos+1) .
|
||||
str_replace('?', '&', substr($url, $qpos+1));
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -78,9 +78,9 @@ class SettingsAction extends Action
|
||||
common_set_returnto($this->selfUrl());
|
||||
$user = common_current_user();
|
||||
if ($user->hasOpenID()) {
|
||||
common_redirect(common_local_url('openidlogin'));
|
||||
common_redirect(common_local_url('openidlogin'), 303);
|
||||
} else {
|
||||
common_redirect(common_local_url('login'));
|
||||
common_redirect(common_local_url('login'), 303);
|
||||
}
|
||||
} else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
$this->handlePost();
|
||||
|
@ -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)
|
||||
|
53
lib/util.php
53
lib/util.php
@ -620,9 +620,13 @@ function common_at_link($sender_id, $nickname)
|
||||
$url = $recipient->profileurl;
|
||||
}
|
||||
$xs = new XMLStringer(false);
|
||||
$attrs = array('href' => $url,
|
||||
'class' => 'url');
|
||||
if (!empty($recipient->fullname)) {
|
||||
$attrs['title'] = $recipient->fullname . ' (' . $recipient->nickname . ')';
|
||||
}
|
||||
$xs->elementStart('span', 'vcard');
|
||||
$xs->elementStart('a', array('href' => $url,
|
||||
'class' => 'url'));
|
||||
$xs->elementStart('a', $attrs);
|
||||
$xs->element('span', 'fn nickname', $nickname);
|
||||
$xs->elementEnd('a');
|
||||
$xs->elementEnd('span');
|
||||
@ -637,10 +641,14 @@ function common_group_link($sender_id, $nickname)
|
||||
$sender = Profile::staticGet($sender_id);
|
||||
$group = User_group::staticGet('nickname', common_canonical_nickname($nickname));
|
||||
if ($group && $sender->isMember($group)) {
|
||||
$attrs = array('href' => $group->permalink(),
|
||||
'class' => 'url');
|
||||
if (!empty($group->fullname)) {
|
||||
$attrs['title'] = $group->fullname . ' (' . $group->nickname . ')';
|
||||
}
|
||||
$xs = new XMLStringer();
|
||||
$xs->elementStart('span', 'vcard');
|
||||
$xs->elementStart('a', array('href' => $group->permalink(),
|
||||
'class' => 'url'));
|
||||
$xs->elementStart('a', $attrs);
|
||||
$xs->element('span', 'fn nickname', $nickname);
|
||||
$xs->elementEnd('a');
|
||||
$xs->elementEnd('span');
|
||||
@ -711,25 +719,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',
|
||||
'finishaddopenid', '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)
|
||||
@ -819,7 +848,7 @@ function common_redirect($url, $code=307)
|
||||
303 => "See Other",
|
||||
307 => "Temporary Redirect");
|
||||
|
||||
header("Status: ${code} $status[$code]");
|
||||
header('HTTP/1.1 '.$code.' '.$status[$code]);
|
||||
header("Location: $url");
|
||||
|
||||
$xo = new XMLOutputter();
|
||||
@ -921,9 +950,9 @@ function common_profile_url($nickname)
|
||||
|
||||
// Should make up a reasonable root URL
|
||||
|
||||
function common_root_url()
|
||||
function common_root_url($ssl=false)
|
||||
{
|
||||
return common_path('');
|
||||
return common_path('', $ssl);
|
||||
}
|
||||
|
||||
// returns $bytes bytes of random data as a hexadecimal string
|
||||
|
@ -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;
|
||||
|
@ -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%;
|
||||
@ -245,6 +250,7 @@ position:absolute;
|
||||
top:65px;
|
||||
right:18px;
|
||||
width:250px;
|
||||
width:24%;
|
||||
}
|
||||
#page_notice {
|
||||
clear:both;
|
||||
@ -254,9 +260,8 @@ margin-bottom:18px;
|
||||
|
||||
#anon_notice {
|
||||
float:left;
|
||||
width:432px;
|
||||
width:28.052em;
|
||||
padding:11px;
|
||||
width:43.2%;
|
||||
padding:1.1%;
|
||||
border-radius:7px;
|
||||
-moz-border-radius:7px;
|
||||
-webkit-border-radius:7px;
|
||||
@ -364,7 +369,9 @@ margin-right:4px;
|
||||
|
||||
#wrap {
|
||||
margin:0 auto;
|
||||
width:1003px;
|
||||
width:100%;
|
||||
min-width:760px;
|
||||
max-width:1003px;
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
@ -376,14 +383,16 @@ margin-bottom:1em;
|
||||
}
|
||||
|
||||
#content {
|
||||
width:644px;
|
||||
padding:18px;
|
||||
width:64.009%;
|
||||
padding: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:1px;
|
||||
}
|
||||
|
||||
#content_inner {
|
||||
@ -393,10 +402,10 @@ float:left;
|
||||
}
|
||||
|
||||
#aside_primary {
|
||||
width:280px;
|
||||
width:27.917%;
|
||||
float:left;
|
||||
margin-left:4px;
|
||||
padding:18px;
|
||||
margin-left:0.395%;
|
||||
padding:1.795%;
|
||||
border-radius:7px;
|
||||
-moz-border-radius:7px;
|
||||
-webkit-border-radius:7px;
|
||||
@ -404,9 +413,8 @@ border-width:1px;
|
||||
border-style:solid;
|
||||
}
|
||||
|
||||
/*Start: FORM NOTICE*/
|
||||
#form_notice {
|
||||
width:458px;
|
||||
width:45.664%;
|
||||
float:left;
|
||||
position:relative;
|
||||
line-height:1;
|
||||
@ -419,40 +427,30 @@ padding:0;
|
||||
display:none;
|
||||
}
|
||||
#form_notice textarea {
|
||||
float:left;
|
||||
border-radius:7px;
|
||||
-moz-border-radius:7px;
|
||||
-webkit-border-radius:7px;
|
||||
width:370px;
|
||||
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 .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,51 +460,28 @@ 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;
|
||||
#form_notice #notice_action-submit {
|
||||
width:14%;
|
||||
height:47px;
|
||||
padding:0;
|
||||
width:16px;
|
||||
height:16px;
|
||||
border:0;
|
||||
text-indent:-9999px;
|
||||
}
|
||||
#form_notice .form_actions {
|
||||
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*/
|
||||
|
||||
|
||||
/* entity_profile */
|
||||
.entity_profile {
|
||||
position:relative;
|
||||
width:475px;
|
||||
width:67.702%;
|
||||
min-height:123px;
|
||||
float:left;
|
||||
margin-bottom:18px;
|
||||
@ -536,7 +511,6 @@ margin-bottom:18px;
|
||||
.entity_profile .entity_tags {
|
||||
margin-left:113px;
|
||||
margin-bottom:4px;
|
||||
width:322px;
|
||||
}
|
||||
|
||||
.entity_profile .entity_fn,
|
||||
@ -564,14 +538,14 @@ display:none;
|
||||
.entity_profile h2 {
|
||||
display:none;
|
||||
}
|
||||
|
||||
/* entity_profile */
|
||||
|
||||
|
||||
/*entity_actions*/
|
||||
.entity_actions {
|
||||
float:right;
|
||||
margin-left:28px;
|
||||
margin-left:4.35%;
|
||||
max-width:25%;
|
||||
}
|
||||
.entity_actions h2 {
|
||||
display:none;
|
||||
@ -939,8 +913,6 @@ display:none;
|
||||
border:0;
|
||||
padding:0;
|
||||
}
|
||||
/*END: NOTICES */
|
||||
|
||||
|
||||
|
||||
#new_group, #group_search {
|
||||
|
@ -1,8 +1,21 @@
|
||||
/* IE specific styles */
|
||||
|
||||
#aside_primary {
|
||||
padding-left:11px;
|
||||
legend {
|
||||
margin-left:-7px;
|
||||
}
|
||||
input.checkbox {
|
||||
top:0;
|
||||
}
|
||||
#form_notice textarea {
|
||||
width:78%;
|
||||
}
|
||||
#form_notice #notice_action-submit {
|
||||
width:17%;
|
||||
max-width:17%;
|
||||
}
|
||||
#anon_notice {
|
||||
max-width:39%;
|
||||
}
|
||||
|
||||
.notice-options input.submit {
|
||||
font-size:0;
|
||||
margin-top:3px;
|
||||
@ -11,15 +24,9 @@ text-align:right;
|
||||
text-indent:0;
|
||||
width:24px;
|
||||
}
|
||||
|
||||
input.checkbox {
|
||||
top:0;
|
||||
}
|
||||
|
||||
legend {
|
||||
margin-left:-7px;
|
||||
}
|
||||
|
||||
.notice div.entry-content .timestamp a {
|
||||
margin-right:4px;
|
||||
}
|
||||
.entity_profile {
|
||||
width:64%;
|
||||
}
|
||||
|
@ -1,4 +1,17 @@
|
||||
/* IE6 specific styles */
|
||||
address {
|
||||
margin-left:7px;
|
||||
}
|
||||
address .fn {
|
||||
display:none;
|
||||
}
|
||||
#content {
|
||||
width:70%;
|
||||
}
|
||||
#aside_primary {
|
||||
padding:5%;
|
||||
width:29.5%;
|
||||
}
|
||||
.entity_profile .entity_nickname,
|
||||
.entity_profile .entity_location,
|
||||
.entity_profile .entity_url,
|
||||
@ -9,3 +22,9 @@ margin-left:0;
|
||||
.entity_profile .entity_depiction {
|
||||
margin-bottom:123px;
|
||||
}
|
||||
.entity_actions {
|
||||
width:20%;
|
||||
}
|
||||
.notice div.entry-content {
|
||||
width:63%;
|
||||
}
|
||||
|
BIN
theme/base/images/icons/icon_processing.gif
Normal file
BIN
theme/base/images/icons/icon_processing.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 673 B |
@ -17,10 +17,7 @@ font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
|
||||
font-size:1em;
|
||||
}
|
||||
address {
|
||||
margin-right:71px;
|
||||
}
|
||||
address .fn {
|
||||
display:none;
|
||||
margin-right:7.18%;
|
||||
}
|
||||
|
||||
input, textarea, select, option {
|
||||
@ -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 {
|
||||
|
@ -17,10 +17,7 @@ font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
|
||||
font-size:1em;
|
||||
}
|
||||
address {
|
||||
margin-right:71px;
|
||||
}
|
||||
address .fn {
|
||||
display:none;
|
||||
margin-right:7.18%;
|
||||
}
|
||||
|
||||
input, textarea, select, option {
|
||||
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user