forked from GNUsocial/gnu-social
		
	Merge branch '0.7.x' into querybyid
This commit is contained in:
		
							
								
								
									
										3
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								README
									
									
									
									
									
								
							@@ -1129,6 +1129,9 @@ welcome: nickname of a user account that sends welcome messages to new
 | 
				
			|||||||
         busy servers it may be a good idea to keep that one just for
 | 
					         busy servers it may be a good idea to keep that one just for
 | 
				
			||||||
         'urgent' messages. Default is null; no message.
 | 
					         'urgent' messages. Default is null; no message.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If either of these special user accounts are specified, the users should
 | 
				
			||||||
 | 
					be created before the configuration is updated.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Troubleshooting
 | 
					Troubleshooting
 | 
				
			||||||
===============
 | 
					===============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -93,7 +93,7 @@ class AllAction extends ProfileAction
 | 
				
			|||||||
        if (common_logged_in()) {
 | 
					        if (common_logged_in()) {
 | 
				
			||||||
            $current_user = common_current_user();
 | 
					            $current_user = common_current_user();
 | 
				
			||||||
            if ($this->user->id === $current_user->id) {
 | 
					            if ($this->user->id === $current_user->id) {
 | 
				
			||||||
                $message .= _('Try subscribing to more people, [join a group](%%action.groups) or post something yourself.');
 | 
					                $message .= _('Try subscribing to more people, [join a group](%%action.groups%%) or post something yourself.');
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                $message .= sprintf(_('You can try to [nudge %s](../%s) from his profile or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname);
 | 
					                $message .= sprintf(_('You can try to [nudge %s](../%s) from his profile or [post something to his or her attention](%%%%action.newnotice%%%%?status_textarea=%s).'), $this->user->nickname, $this->user->nickname, '@' . $this->user->nickname);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -191,11 +191,28 @@ class FinishopenidloginAction extends Action
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        # FIXME: save invite code before redirect, and check here
 | 
					        # FIXME: save invite code before redirect, and check here
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (common_config('site', 'closed') || common_config('site', 'inviteonly')) {
 | 
					        if (common_config('site', 'closed')) {
 | 
				
			||||||
            $this->clientError(_('Registration not allowed.'));
 | 
					            $this->clientError(_('Registration not allowed.'));
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $invite = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (common_config('site', 'inviteonly')) {
 | 
				
			||||||
 | 
					            $code = $_SESSION['invitecode'];
 | 
				
			||||||
 | 
					            if (empty($code)) {
 | 
				
			||||||
 | 
					                $this->clientError(_('Registration not allowed.'));
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $invite = Invitation::staticGet($code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (empty($invite)) {
 | 
				
			||||||
 | 
					                $this->clientError(_('Not a valid invitation code.'));
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $nickname = $this->trimmed('newname');
 | 
					        $nickname = $this->trimmed('newname');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!Validate::string($nickname, array('min_length' => 1,
 | 
					        if (!Validate::string($nickname, array('min_length' => 1,
 | 
				
			||||||
@@ -257,10 +274,16 @@ class FinishopenidloginAction extends Action
 | 
				
			|||||||
        # XXX: add language
 | 
					        # XXX: add language
 | 
				
			||||||
        # XXX: add timezone
 | 
					        # XXX: add timezone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $user = User::register(array('nickname' => $nickname,
 | 
					        $args = array('nickname' => $nickname,
 | 
				
			||||||
                                     'email' => $email,
 | 
					                      'email' => $email,
 | 
				
			||||||
                                     'fullname' => $fullname,
 | 
					                      'fullname' => $fullname,
 | 
				
			||||||
                                     'location' => $location));
 | 
					                      'location' => $location);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!empty($invite)) {
 | 
				
			||||||
 | 
					            $args['code'] = $invite->code;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $user = User::register($args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $result = oid_link_user($user->id, $canonical, $display);
 | 
					        $result = oid_link_user($user->id, $canonical, $display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,7 +34,7 @@ if (!defined('LACONICA')) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
require_once INSTALLDIR.'/lib/rssaction.php';
 | 
					require_once INSTALLDIR.'/lib/rssaction.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
define('MEMBERS_PER_SECTION', 81);
 | 
					define('MEMBERS_PER_SECTION', 27);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Group RSS feed
 | 
					 * Group RSS feed
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -172,15 +172,54 @@ class NewmessageAction extends Action
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $this->notify($user, $this->other, $message);
 | 
					        $this->notify($user, $this->other, $message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $url = common_local_url('outbox', array('nickname' => $user->nickname));
 | 
					        if ($this->boolean('ajax')) {
 | 
				
			||||||
 | 
					            $this->startHTML('text/xml;charset=utf-8');
 | 
				
			||||||
 | 
					            $this->elementStart('head');
 | 
				
			||||||
 | 
					            $this->element('title', null, _('Message sent'));
 | 
				
			||||||
 | 
					            $this->elementEnd('head');
 | 
				
			||||||
 | 
					            $this->elementStart('body');
 | 
				
			||||||
 | 
					            $this->element('p', array('id' => 'command_result'),
 | 
				
			||||||
 | 
					                sprintf(_('Direct message to %s sent'),
 | 
				
			||||||
 | 
					                    $this->other->nickname));
 | 
				
			||||||
 | 
					            $this->elementEnd('body');
 | 
				
			||||||
 | 
					            $this->elementEnd('html');
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            $url = common_local_url('outbox',
 | 
				
			||||||
 | 
					                array('nickname' => $user->nickname));
 | 
				
			||||||
 | 
					            common_redirect($url, 303);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        common_redirect($url, 303);
 | 
					    /**
 | 
				
			||||||
 | 
					     * Show an Ajax-y error message
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Goes back to the browser, where it's shown in a popup.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param string $msg Message to show
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function ajaxErrorMsg($msg)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->startHTML('text/xml;charset=utf-8', true);
 | 
				
			||||||
 | 
					        $this->elementStart('head');
 | 
				
			||||||
 | 
					        $this->element('title', null, _('Ajax Error'));
 | 
				
			||||||
 | 
					        $this->elementEnd('head');
 | 
				
			||||||
 | 
					        $this->elementStart('body');
 | 
				
			||||||
 | 
					        $this->element('p', array('id' => 'error'), $msg);
 | 
				
			||||||
 | 
					        $this->elementEnd('body');
 | 
				
			||||||
 | 
					        $this->elementEnd('html');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function showForm($msg = null)
 | 
					    function showForm($msg = null)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $this->msg = $msg;
 | 
					        if ($msg && $this->boolean('ajax')) {
 | 
				
			||||||
 | 
					            $this->ajaxErrorMsg($msg);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->msg = $msg;
 | 
				
			||||||
        $this->showPage();
 | 
					        $this->showPage();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -91,67 +91,68 @@ class ProfilesettingsAction extends AccountSettingsAction
 | 
				
			|||||||
        $this->element('legend', null, _('Profile information'));
 | 
					        $this->element('legend', null, _('Profile information'));
 | 
				
			||||||
        $this->hidden('token', common_session_token());
 | 
					        $this->hidden('token', common_session_token());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # too much common patterns here... abstractable?
 | 
					        // too much common patterns here... abstractable?
 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->elementStart('ul', 'form_data');
 | 
					        $this->elementStart('ul', 'form_data');
 | 
				
			||||||
        $this->elementStart('li');
 | 
					        if (Event::handle('StartProfileFormData', array($this))) {
 | 
				
			||||||
        $this->input('nickname', _('Nickname'),
 | 
					            $this->elementStart('li');
 | 
				
			||||||
                     ($this->arg('nickname')) ? $this->arg('nickname') : $profile->nickname,
 | 
					            $this->input('nickname', _('Nickname'),
 | 
				
			||||||
                     _('1-64 lowercase letters or numbers, no punctuation or spaces'));
 | 
					                         ($this->arg('nickname')) ? $this->arg('nickname') : $profile->nickname,
 | 
				
			||||||
        $this->elementEnd('li');
 | 
					                         _('1-64 lowercase letters or numbers, no punctuation or spaces'));
 | 
				
			||||||
        $this->elementStart('li');
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
        $this->input('fullname', _('Full name'),
 | 
					            $this->elementStart('li');
 | 
				
			||||||
                     ($this->arg('fullname')) ? $this->arg('fullname') : $profile->fullname);
 | 
					            $this->input('fullname', _('Full name'),
 | 
				
			||||||
        $this->elementEnd('li');
 | 
					                         ($this->arg('fullname')) ? $this->arg('fullname') : $profile->fullname);
 | 
				
			||||||
        $this->elementStart('li');
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
        $this->input('homepage', _('Homepage'),
 | 
					            $this->elementStart('li');
 | 
				
			||||||
                     ($this->arg('homepage')) ? $this->arg('homepage') : $profile->homepage,
 | 
					            $this->input('homepage', _('Homepage'),
 | 
				
			||||||
                     _('URL of your homepage, blog, or profile on another site'));
 | 
					                         ($this->arg('homepage')) ? $this->arg('homepage') : $profile->homepage,
 | 
				
			||||||
        $this->elementEnd('li');
 | 
					                         _('URL of your homepage, blog, or profile on another site'));
 | 
				
			||||||
        $this->elementStart('li');
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
        $this->textarea('bio', _('Bio'),
 | 
					            $this->elementStart('li');
 | 
				
			||||||
                        ($this->arg('bio')) ? $this->arg('bio') : $profile->bio,
 | 
					            $this->textarea('bio', _('Bio'),
 | 
				
			||||||
                        _('Describe yourself and your interests in 140 chars'));
 | 
					                            ($this->arg('bio')) ? $this->arg('bio') : $profile->bio,
 | 
				
			||||||
        $this->elementEnd('li');
 | 
					                            _('Describe yourself and your interests in 140 chars'));
 | 
				
			||||||
        $this->elementStart('li');
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
        $this->input('location', _('Location'),
 | 
					            $this->elementStart('li');
 | 
				
			||||||
                     ($this->arg('location')) ? $this->arg('location') : $profile->location,
 | 
					            $this->input('location', _('Location'),
 | 
				
			||||||
                     _('Where you are, like "City, State (or Region), Country"'));
 | 
					                         ($this->arg('location')) ? $this->arg('location') : $profile->location,
 | 
				
			||||||
        $this->elementEnd('li');
 | 
					                         _('Where you are, like "City, State (or Region), Country"'));
 | 
				
			||||||
        $this->elementStart('li');
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
        $this->input('tags', _('Tags'),
 | 
					            Event::handle('EndProfileFormData', array($this));
 | 
				
			||||||
                     ($this->arg('tags')) ? $this->arg('tags') : implode(' ', $user->getSelfTags()),
 | 
					            $this->elementStart('li');
 | 
				
			||||||
                     _('Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated'));
 | 
					            $this->input('tags', _('Tags'),
 | 
				
			||||||
        $this->elementEnd('li');
 | 
					                         ($this->arg('tags')) ? $this->arg('tags') : implode(' ', $user->getSelfTags()),
 | 
				
			||||||
        $this->elementStart('li');
 | 
					                         _('Tags for yourself (letters, numbers, -, ., and _), comma- or space- separated'));
 | 
				
			||||||
        $language = common_language();
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
        $this->dropdown('language', _('Language'),
 | 
					            $this->elementStart('li');
 | 
				
			||||||
                        get_nice_language_list(), _('Preferred language'),
 | 
					            $language = common_language();
 | 
				
			||||||
                        true, $language);
 | 
					            $this->dropdown('language', _('Language'),
 | 
				
			||||||
        $this->elementEnd('li');
 | 
					                            get_nice_language_list(), _('Preferred language'),
 | 
				
			||||||
        $timezone = common_timezone();
 | 
					                            false, $language);
 | 
				
			||||||
        $timezones = array();
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
        foreach(DateTimeZone::listIdentifiers() as $k => $v) {
 | 
					            $timezone = common_timezone();
 | 
				
			||||||
            $timezones[$v] = $v;
 | 
					            $timezones = array();
 | 
				
			||||||
 | 
					            foreach(DateTimeZone::listIdentifiers() as $k => $v) {
 | 
				
			||||||
 | 
					                $timezones[$v] = $v;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            $this->elementStart('li');
 | 
				
			||||||
 | 
					            $this->dropdown('timezone', _('Timezone'),
 | 
				
			||||||
 | 
					                            $timezones, _('What timezone are you normally in?'),
 | 
				
			||||||
 | 
					                            true, $timezone);
 | 
				
			||||||
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
 | 
					            $this->elementStart('li');
 | 
				
			||||||
 | 
					            $this->checkbox('autosubscribe',
 | 
				
			||||||
 | 
					                            _('Automatically subscribe to whoever '.
 | 
				
			||||||
 | 
					                              'subscribes to me (best for non-humans)'),
 | 
				
			||||||
 | 
					                            ($this->arg('autosubscribe')) ?
 | 
				
			||||||
 | 
					                            $this->boolean('autosubscribe') : $user->autosubscribe);
 | 
				
			||||||
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        $this->elementStart('li');
 | 
					 | 
				
			||||||
        $this->dropdown('timezone', _('Timezone'),
 | 
					 | 
				
			||||||
                        $timezones, _('What timezone are you normally in?'),
 | 
					 | 
				
			||||||
                        true, $timezone);
 | 
					 | 
				
			||||||
        $this->elementEnd('li');
 | 
					 | 
				
			||||||
        $this->elementStart('li');
 | 
					 | 
				
			||||||
        $this->checkbox('autosubscribe',
 | 
					 | 
				
			||||||
                        _('Automatically subscribe to whoever '.
 | 
					 | 
				
			||||||
                          'subscribes to me (best for non-humans)'),
 | 
					 | 
				
			||||||
                        ($this->arg('autosubscribe')) ?
 | 
					 | 
				
			||||||
                        $this->boolean('autosubscribe') : $user->autosubscribe);
 | 
					 | 
				
			||||||
        $this->elementEnd('li');
 | 
					 | 
				
			||||||
        $this->elementEnd('ul');
 | 
					        $this->elementEnd('ul');
 | 
				
			||||||
        $this->submit('save', _('Save'));
 | 
					        $this->submit('save', _('Save'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->elementEnd('fieldset');
 | 
					        $this->elementEnd('fieldset');
 | 
				
			||||||
        $this->elementEnd('form');
 | 
					        $this->elementEnd('form');
 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -165,158 +166,158 @@ class ProfilesettingsAction extends AccountSettingsAction
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    function handlePost()
 | 
					    function handlePost()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        # CSRF protection
 | 
					        // CSRF protection
 | 
				
			||||||
 | 
					 | 
				
			||||||
        $token = $this->trimmed('token');
 | 
					        $token = $this->trimmed('token');
 | 
				
			||||||
        if (!$token || $token != common_session_token()) {
 | 
					        if (!$token || $token != common_session_token()) {
 | 
				
			||||||
            $this->showForm(_('There was a problem with your session token. '.
 | 
					            $this->showForm(_('There was a problem with your session token. '.
 | 
				
			||||||
                               'Try again, please.'));
 | 
					                        'Try again, please.'));
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $nickname = $this->trimmed('nickname');
 | 
					        if (Event::handle('StartProfileSaveForm', array($this))) {
 | 
				
			||||||
        $fullname = $this->trimmed('fullname');
 | 
					 | 
				
			||||||
        $homepage = $this->trimmed('homepage');
 | 
					 | 
				
			||||||
        $bio = $this->trimmed('bio');
 | 
					 | 
				
			||||||
        $location = $this->trimmed('location');
 | 
					 | 
				
			||||||
        $autosubscribe = $this->boolean('autosubscribe');
 | 
					 | 
				
			||||||
        $language = $this->trimmed('language');
 | 
					 | 
				
			||||||
        $timezone = $this->trimmed('timezone');
 | 
					 | 
				
			||||||
        $tagstring = $this->trimmed('tags');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Some validation
 | 
					            $nickname = $this->trimmed('nickname');
 | 
				
			||||||
 | 
					            $fullname = $this->trimmed('fullname');
 | 
				
			||||||
 | 
					            $homepage = $this->trimmed('homepage');
 | 
				
			||||||
 | 
					            $bio = $this->trimmed('bio');
 | 
				
			||||||
 | 
					            $location = $this->trimmed('location');
 | 
				
			||||||
 | 
					            $autosubscribe = $this->boolean('autosubscribe');
 | 
				
			||||||
 | 
					            $language = $this->trimmed('language');
 | 
				
			||||||
 | 
					            $timezone = $this->trimmed('timezone');
 | 
				
			||||||
 | 
					            $tagstring = $this->trimmed('tags');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!Validate::string($nickname, array('min_length' => 1,
 | 
					            // Some validation
 | 
				
			||||||
                                               'max_length' => 64,
 | 
					            if (!Validate::string($nickname, array('min_length' => 1,
 | 
				
			||||||
                                               'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
 | 
					                            'max_length' => 64,
 | 
				
			||||||
            $this->showForm(_('Nickname must have only lowercase letters and numbers and no spaces.'));
 | 
					                            'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
 | 
				
			||||||
            return;
 | 
					                $this->showForm(_('Nickname must have only lowercase letters and numbers and no spaces.'));
 | 
				
			||||||
        } else if (!User::allowed_nickname($nickname)) {
 | 
					                return;
 | 
				
			||||||
            $this->showForm(_('Not a valid nickname.'));
 | 
					            } else if (!User::allowed_nickname($nickname)) {
 | 
				
			||||||
            return;
 | 
					                $this->showForm(_('Not a valid nickname.'));
 | 
				
			||||||
        } else if (!is_null($homepage) && (strlen($homepage) > 0) &&
 | 
					                return;
 | 
				
			||||||
                   !Validate::uri($homepage, array('allowed_schemes' => array('http', 'https')))) {
 | 
					            } else if (!is_null($homepage) && (strlen($homepage) > 0) &&
 | 
				
			||||||
            $this->showForm(_('Homepage is not a valid URL.'));
 | 
					                    !Validate::uri($homepage, array('allowed_schemes' => array('http', 'https')))) {
 | 
				
			||||||
            return;
 | 
					                $this->showForm(_('Homepage is not a valid URL.'));
 | 
				
			||||||
        } else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
 | 
					                return;
 | 
				
			||||||
            $this->showForm(_('Full name is too long (max 255 chars).'));
 | 
					            } else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
 | 
				
			||||||
            return;
 | 
					                $this->showForm(_('Full name is too long (max 255 chars).'));
 | 
				
			||||||
        } else if (!is_null($bio) && mb_strlen($bio) > 140) {
 | 
					                return;
 | 
				
			||||||
            $this->showForm(_('Bio is too long (max 140 chars).'));
 | 
					            } else if (!is_null($bio) && mb_strlen($bio) > 140) {
 | 
				
			||||||
            return;
 | 
					                $this->showForm(_('Bio is too long (max 140 chars).'));
 | 
				
			||||||
        } else if (!is_null($location) && mb_strlen($location) > 255) {
 | 
					                return;
 | 
				
			||||||
            $this->showForm(_('Location is too long (max 255 chars).'));
 | 
					            } else if (!is_null($location) && mb_strlen($location) > 255) {
 | 
				
			||||||
            return;
 | 
					                $this->showForm(_('Location is too long (max 255 chars).'));
 | 
				
			||||||
        }  else if (is_null($timezone) || !in_array($timezone, DateTimeZone::listIdentifiers())) {
 | 
					                return;
 | 
				
			||||||
            $this->showForm(_('Timezone not selected.'));
 | 
					            }  else if (is_null($timezone) || !in_array($timezone, DateTimeZone::listIdentifiers())) {
 | 
				
			||||||
            return;
 | 
					                $this->showForm(_('Timezone not selected.'));
 | 
				
			||||||
        } else if ($this->nicknameExists($nickname)) {
 | 
					                return;
 | 
				
			||||||
            $this->showForm(_('Nickname already in use. Try another one.'));
 | 
					            } else if ($this->nicknameExists($nickname)) {
 | 
				
			||||||
            return;
 | 
					                $this->showForm(_('Nickname already in use. Try another one.'));
 | 
				
			||||||
        } else if (!is_null($language) && strlen($language) > 50) {
 | 
					                return;
 | 
				
			||||||
            $this->showForm(_('Language is too long (max 50 chars).'));
 | 
					            } else if (!is_null($language) && strlen($language) > 50) {
 | 
				
			||||||
            return;
 | 
					                $this->showForm(_('Language is too long (max 50 chars).'));
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($tagstring) {
 | 
					 | 
				
			||||||
            $tags = array_map('common_canonical_tag', preg_split('/[\s,]+/', $tagstring));
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            $tags = array();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        foreach ($tags as $tag) {
 | 
					 | 
				
			||||||
            if (!common_valid_profile_tag($tag)) {
 | 
					 | 
				
			||||||
                $this->showForm(sprintf(_('Invalid tag: "%s"'), $tag));
 | 
					 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $user = common_current_user();
 | 
					            if ($tagstring) {
 | 
				
			||||||
 | 
					                $tags = array_map('common_canonical_tag', preg_split('/[\s,]+/', $tagstring));
 | 
				
			||||||
        $user->query('BEGIN');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($user->nickname != $nickname ||
 | 
					 | 
				
			||||||
            $user->language != $language ||
 | 
					 | 
				
			||||||
            $user->timezone != $timezone) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            common_debug('Updating user nickname from ' . $user->nickname . ' to ' . $nickname,
 | 
					 | 
				
			||||||
                         __FILE__);
 | 
					 | 
				
			||||||
            common_debug('Updating user language from ' . $user->language . ' to ' . $language,
 | 
					 | 
				
			||||||
                         __FILE__);
 | 
					 | 
				
			||||||
            common_debug('Updating user timezone from ' . $user->timezone . ' to ' . $timezone,
 | 
					 | 
				
			||||||
                         __FILE__);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $original = clone($user);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $user->nickname = $nickname;
 | 
					 | 
				
			||||||
            $user->language = $language;
 | 
					 | 
				
			||||||
            $user->timezone = $timezone;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $result = $user->updateKeys($original);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if ($result === false) {
 | 
					 | 
				
			||||||
                common_log_db_error($user, 'UPDATE', __FILE__);
 | 
					 | 
				
			||||||
                $this->serverError(_('Couldn\'t update user.'));
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                # Re-initialize language environment if it changed
 | 
					                $tags = array();
 | 
				
			||||||
                common_init_language();
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # XXX: XOR
 | 
					            foreach ($tags as $tag) {
 | 
				
			||||||
 | 
					                if (!common_valid_profile_tag($tag)) {
 | 
				
			||||||
 | 
					                    $this->showForm(sprintf(_('Invalid tag: "%s"'), $tag));
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($user->autosubscribe ^ $autosubscribe) {
 | 
					            $user = common_current_user();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $original = clone($user);
 | 
					            $user->query('BEGIN');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $user->autosubscribe = $autosubscribe;
 | 
					            if ($user->nickname != $nickname ||
 | 
				
			||||||
 | 
					                    $user->language != $language ||
 | 
				
			||||||
 | 
					                    $user->timezone != $timezone) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $result = $user->update($original);
 | 
					                common_debug('Updating user nickname from ' . $user->nickname . ' to ' . $nickname,
 | 
				
			||||||
 | 
					                        __FILE__);
 | 
				
			||||||
 | 
					                common_debug('Updating user language from ' . $user->language . ' to ' . $language,
 | 
				
			||||||
 | 
					                        __FILE__);
 | 
				
			||||||
 | 
					                common_debug('Updating user timezone from ' . $user->timezone . ' to ' . $timezone,
 | 
				
			||||||
 | 
					                        __FILE__);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($result === false) {
 | 
					                $original = clone($user);
 | 
				
			||||||
                common_log_db_error($user, 'UPDATE', __FILE__);
 | 
					
 | 
				
			||||||
                $this->serverError(_('Couldn\'t update user for autosubscribe.'));
 | 
					                $user->nickname = $nickname;
 | 
				
			||||||
 | 
					                $user->language = $language;
 | 
				
			||||||
 | 
					                $user->timezone = $timezone;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                $result = $user->updateKeys($original);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if ($result === false) {
 | 
				
			||||||
 | 
					                    common_log_db_error($user, 'UPDATE', __FILE__);
 | 
				
			||||||
 | 
					                    $this->serverError(_('Couldn\'t update user.'));
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    // Re-initialize language environment if it changed
 | 
				
			||||||
 | 
					                    common_init_language();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// XXX: XOR
 | 
				
			||||||
 | 
					            if ($user->autosubscribe ^ $autosubscribe) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                $original = clone($user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                $user->autosubscribe = $autosubscribe;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                $result = $user->update($original);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if ($result === false) {
 | 
				
			||||||
 | 
					                    common_log_db_error($user, 'UPDATE', __FILE__);
 | 
				
			||||||
 | 
					                    $this->serverError(_('Couldn\'t update user for autosubscribe.'));
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $profile = $user->getProfile();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $orig_profile = clone($profile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $profile->nickname = $user->nickname;
 | 
				
			||||||
 | 
					            $profile->fullname = $fullname;
 | 
				
			||||||
 | 
					            $profile->homepage = $homepage;
 | 
				
			||||||
 | 
					            $profile->bio = $bio;
 | 
				
			||||||
 | 
					            $profile->location = $location;
 | 
				
			||||||
 | 
					            $profile->profileurl = common_profile_url($nickname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            common_debug('Old profile: ' . common_log_objstring($orig_profile), __FILE__);
 | 
				
			||||||
 | 
					            common_debug('New profile: ' . common_log_objstring($profile), __FILE__);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $result = $profile->update($orig_profile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!$result) {
 | 
				
			||||||
 | 
					                common_log_db_error($profile, 'UPDATE', __FILE__);
 | 
				
			||||||
 | 
					                $this->serverError(_('Couldn\'t save profile.'));
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Set the user tags
 | 
				
			||||||
 | 
					            $result = $user->setSelfTags($tags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!$result) {
 | 
				
			||||||
 | 
					                $this->serverError(_('Couldn\'t save tags.'));
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $user->query('COMMIT');
 | 
				
			||||||
 | 
					            Event::handle('EndProfileSaveForm', array($this));
 | 
				
			||||||
 | 
					            common_broadcast_profile($profile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $this->showForm(_('Settings saved.'), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        $profile = $user->getProfile();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $orig_profile = clone($profile);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $profile->nickname = $user->nickname;
 | 
					 | 
				
			||||||
        $profile->fullname = $fullname;
 | 
					 | 
				
			||||||
        $profile->homepage = $homepage;
 | 
					 | 
				
			||||||
        $profile->bio = $bio;
 | 
					 | 
				
			||||||
        $profile->location = $location;
 | 
					 | 
				
			||||||
        $profile->profileurl = common_profile_url($nickname);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        common_debug('Old profile: ' . common_log_objstring($orig_profile), __FILE__);
 | 
					 | 
				
			||||||
        common_debug('New profile: ' . common_log_objstring($profile), __FILE__);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $result = $profile->update($orig_profile);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!$result) {
 | 
					 | 
				
			||||||
            common_log_db_error($profile, 'UPDATE', __FILE__);
 | 
					 | 
				
			||||||
            $this->serverError(_('Couldn\'t save profile.'));
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Set the user tags
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $result = $user->setSelfTags($tags);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!$result) {
 | 
					 | 
				
			||||||
            $this->serverError(_('Couldn\'t save tags.'));
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $user->query('COMMIT');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        common_broadcast_profile($profile);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->showForm(_('Settings saved.'), true);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function nicknameExists($nickname)
 | 
					    function nicknameExists($nickname)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,6 +55,45 @@ class RegisterAction extends Action
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    var $registered = false;
 | 
					    var $registered = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Prepare page to run
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param $args
 | 
				
			||||||
 | 
					     * @return string title
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function prepare($args)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        parent::prepare($args);
 | 
				
			||||||
 | 
					        $this->code = $this->trimmed('code');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (empty($this->code)) {
 | 
				
			||||||
 | 
					            common_ensure_session();
 | 
				
			||||||
 | 
					            if (array_key_exists('invitecode', $_SESSION)) {
 | 
				
			||||||
 | 
					                $this->code = $_SESSION['invitecode'];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (common_config('site', 'inviteonly') && empty($this->code)) {
 | 
				
			||||||
 | 
					            $this->clientError(_('Sorry, only invited people can register.'));
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!empty($this->code)) {
 | 
				
			||||||
 | 
					            $this->invite = Invitation::staticGet('code', $this->code);
 | 
				
			||||||
 | 
					            if (empty($this->invite)) {
 | 
				
			||||||
 | 
					                $this->clientError(_('Sorry, invalid invitation code.'));
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // Store this in case we need it
 | 
				
			||||||
 | 
					            common_ensure_session();
 | 
				
			||||||
 | 
					            $_SESSION['invitecode'] = $this->code;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Title of the page
 | 
					     * Title of the page
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
@@ -108,107 +147,109 @@ class RegisterAction extends Action
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    function tryRegister()
 | 
					    function tryRegister()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $token = $this->trimmed('token');
 | 
					        if (Event::handle('StartRegistrationTry', array($this))) {
 | 
				
			||||||
        if (!$token || $token != common_session_token()) {
 | 
					            $token = $this->trimmed('token');
 | 
				
			||||||
            $this->showForm(_('There was a problem with your session token. '.
 | 
					            if (!$token || $token != common_session_token()) {
 | 
				
			||||||
                              'Try again, please.'));
 | 
					                $this->showForm(_('There was a problem with your session token. '.
 | 
				
			||||||
            return;
 | 
					                                  'Try again, please.'));
 | 
				
			||||||
        }
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $nickname = $this->trimmed('nickname');
 | 
					            $nickname = $this->trimmed('nickname');
 | 
				
			||||||
        $email    = $this->trimmed('email');
 | 
					            $email    = $this->trimmed('email');
 | 
				
			||||||
        $fullname = $this->trimmed('fullname');
 | 
					            $fullname = $this->trimmed('fullname');
 | 
				
			||||||
        $homepage = $this->trimmed('homepage');
 | 
					            $homepage = $this->trimmed('homepage');
 | 
				
			||||||
        $bio      = $this->trimmed('bio');
 | 
					            $bio      = $this->trimmed('bio');
 | 
				
			||||||
        $location = $this->trimmed('location');
 | 
					            $location = $this->trimmed('location');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // We don't trim these... whitespace is OK in a password!
 | 
					            // We don't trim these... whitespace is OK in a password!
 | 
				
			||||||
 | 
					            $password = $this->arg('password');
 | 
				
			||||||
 | 
					            $confirm  = $this->arg('confirm');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $password = $this->arg('password');
 | 
					            // invitation code, if any
 | 
				
			||||||
        $confirm  = $this->arg('confirm');
 | 
					            $code = $this->trimmed('code');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // invitation code, if any
 | 
					            if ($code) {
 | 
				
			||||||
 | 
					                $invite = Invitation::staticGet($code);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $code = $this->trimmed('code');
 | 
					            if (common_config('site', 'inviteonly') && !($code && $invite)) {
 | 
				
			||||||
 | 
					                $this->clientError(_('Sorry, only invited people can register.'));
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($code) {
 | 
					            // Input scrubbing
 | 
				
			||||||
            $invite = Invitation::staticGet($code);
 | 
					            $nickname = common_canonical_nickname($nickname);
 | 
				
			||||||
        }
 | 
					            $email    = common_canonical_email($email);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (common_config('site', 'inviteonly') && !($code && $invite)) {
 | 
					            if (!$this->boolean('license')) {
 | 
				
			||||||
            $this->clientError(_('Sorry, only invited people can register.'));
 | 
					                $this->showForm(_('You can\'t register if you don\'t '.
 | 
				
			||||||
            return;
 | 
					                                  'agree to the license.'));
 | 
				
			||||||
        }
 | 
					            } else if ($email && !Validate::email($email, true)) {
 | 
				
			||||||
 | 
					                $this->showForm(_('Not a valid email address.'));
 | 
				
			||||||
 | 
					            } else if (!Validate::string($nickname, array('min_length' => 1,
 | 
				
			||||||
 | 
					                                                          'max_length' => 64,
 | 
				
			||||||
 | 
					                                                          'format' => NICKNAME_FMT))) {
 | 
				
			||||||
 | 
					                $this->showForm(_('Nickname must have only lowercase letters '.
 | 
				
			||||||
 | 
					                                  'and numbers and no spaces.'));
 | 
				
			||||||
 | 
					            } else if ($this->nicknameExists($nickname)) {
 | 
				
			||||||
 | 
					                $this->showForm(_('Nickname already in use. Try another one.'));
 | 
				
			||||||
 | 
					            } else if (!User::allowed_nickname($nickname)) {
 | 
				
			||||||
 | 
					                $this->showForm(_('Not a valid nickname.'));
 | 
				
			||||||
 | 
					            } else if ($this->emailExists($email)) {
 | 
				
			||||||
 | 
					                $this->showForm(_('Email address already exists.'));
 | 
				
			||||||
 | 
					            } else if (!is_null($homepage) && (strlen($homepage) > 0) &&
 | 
				
			||||||
 | 
					                       !Validate::uri($homepage,
 | 
				
			||||||
 | 
					                                      array('allowed_schemes' =>
 | 
				
			||||||
 | 
					                                            array('http', 'https')))) {
 | 
				
			||||||
 | 
					                $this->showForm(_('Homepage is not a valid URL.'));
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            } else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
 | 
				
			||||||
 | 
					                $this->showForm(_('Full name is too long (max 255 chars).'));
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            } else if (!is_null($bio) && mb_strlen($bio) > 140) {
 | 
				
			||||||
 | 
					                $this->showForm(_('Bio is too long (max 140 chars).'));
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            } else if (!is_null($location) && mb_strlen($location) > 255) {
 | 
				
			||||||
 | 
					                $this->showForm(_('Location is too long (max 255 chars).'));
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            } else if (strlen($password) < 6) {
 | 
				
			||||||
 | 
					                $this->showForm(_('Password must be 6 or more characters.'));
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            } else if ($password != $confirm) {
 | 
				
			||||||
 | 
					                $this->showForm(_('Passwords don\'t match.'));
 | 
				
			||||||
 | 
					            } else if ($user = User::register(array('nickname' => $nickname,
 | 
				
			||||||
 | 
					                                                    'password' => $password,
 | 
				
			||||||
 | 
					                                                    'email' => $email,
 | 
				
			||||||
 | 
					                                                    'fullname' => $fullname,
 | 
				
			||||||
 | 
					                                                    'homepage' => $homepage,
 | 
				
			||||||
 | 
					                                                    'bio' => $bio,
 | 
				
			||||||
 | 
					                                                    'location' => $location,
 | 
				
			||||||
 | 
					                                                    'code' => $code))) {
 | 
				
			||||||
 | 
					                if (!$user) {
 | 
				
			||||||
 | 
					                    $this->showForm(_('Invalid username or password.'));
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                // success!
 | 
				
			||||||
 | 
					                if (!common_set_user($user)) {
 | 
				
			||||||
 | 
					                    $this->serverError(_('Error setting user.'));
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                // this is a real login
 | 
				
			||||||
 | 
					                common_real_login(true);
 | 
				
			||||||
 | 
					                if ($this->boolean('rememberme')) {
 | 
				
			||||||
 | 
					                    common_debug('Adding rememberme cookie for ' . $nickname);
 | 
				
			||||||
 | 
					                    common_rememberme($user);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Input scrubbing
 | 
					                Event::handle('EndRegistrationTry', array($this));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $nickname = common_canonical_nickname($nickname);
 | 
					                // Re-init language env in case it changed (not yet, but soon)
 | 
				
			||||||
        $email    = common_canonical_email($email);
 | 
					                common_init_language();
 | 
				
			||||||
 | 
					                $this->showSuccess();
 | 
				
			||||||
        if (!$this->boolean('license')) {
 | 
					            } else {
 | 
				
			||||||
            $this->showForm(_('You can\'t register if you don\'t '.
 | 
					 | 
				
			||||||
                              'agree to the license.'));
 | 
					 | 
				
			||||||
        } else if ($email && !Validate::email($email, true)) {
 | 
					 | 
				
			||||||
            $this->showForm(_('Not a valid email address.'));
 | 
					 | 
				
			||||||
        } else if (!Validate::string($nickname, array('min_length' => 1,
 | 
					 | 
				
			||||||
                                                      'max_length' => 64,
 | 
					 | 
				
			||||||
                                                      'format' => NICKNAME_FMT))) {
 | 
					 | 
				
			||||||
            $this->showForm(_('Nickname must have only lowercase letters '.
 | 
					 | 
				
			||||||
                              'and numbers and no spaces.'));
 | 
					 | 
				
			||||||
        } else if ($this->nicknameExists($nickname)) {
 | 
					 | 
				
			||||||
            $this->showForm(_('Nickname already in use. Try another one.'));
 | 
					 | 
				
			||||||
        } else if (!User::allowed_nickname($nickname)) {
 | 
					 | 
				
			||||||
            $this->showForm(_('Not a valid nickname.'));
 | 
					 | 
				
			||||||
        } else if ($this->emailExists($email)) {
 | 
					 | 
				
			||||||
            $this->showForm(_('Email address already exists.'));
 | 
					 | 
				
			||||||
        } else if (!is_null($homepage) && (strlen($homepage) > 0) &&
 | 
					 | 
				
			||||||
                   !Validate::uri($homepage,
 | 
					 | 
				
			||||||
                                  array('allowed_schemes' =>
 | 
					 | 
				
			||||||
                                        array('http', 'https')))) {
 | 
					 | 
				
			||||||
            $this->showForm(_('Homepage is not a valid URL.'));
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        } else if (!is_null($fullname) && mb_strlen($fullname) > 255) {
 | 
					 | 
				
			||||||
            $this->showForm(_('Full name is too long (max 255 chars).'));
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        } else if (!is_null($bio) && mb_strlen($bio) > 140) {
 | 
					 | 
				
			||||||
            $this->showForm(_('Bio is too long (max 140 chars).'));
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        } else if (!is_null($location) && mb_strlen($location) > 255) {
 | 
					 | 
				
			||||||
            $this->showForm(_('Location is too long (max 255 chars).'));
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        } else if (strlen($password) < 6) {
 | 
					 | 
				
			||||||
            $this->showForm(_('Password must be 6 or more characters.'));
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        } else if ($password != $confirm) {
 | 
					 | 
				
			||||||
            $this->showForm(_('Passwords don\'t match.'));
 | 
					 | 
				
			||||||
        } else if ($user = User::register(array('nickname' => $nickname,
 | 
					 | 
				
			||||||
                                                'password' => $password,
 | 
					 | 
				
			||||||
                                                'email' => $email,
 | 
					 | 
				
			||||||
                                                'fullname' => $fullname,
 | 
					 | 
				
			||||||
                                                'homepage' => $homepage,
 | 
					 | 
				
			||||||
                                                'bio' => $bio,
 | 
					 | 
				
			||||||
                                                'location' => $location,
 | 
					 | 
				
			||||||
                                                'code' => $code))) {
 | 
					 | 
				
			||||||
            if (!$user) {
 | 
					 | 
				
			||||||
                $this->showForm(_('Invalid username or password.'));
 | 
					                $this->showForm(_('Invalid username or password.'));
 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            // success!
 | 
					 | 
				
			||||||
            if (!common_set_user($user)) {
 | 
					 | 
				
			||||||
                $this->serverError(_('Error setting user.'));
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            // this is a real login
 | 
					 | 
				
			||||||
            common_real_login(true);
 | 
					 | 
				
			||||||
            if ($this->boolean('rememberme')) {
 | 
					 | 
				
			||||||
                common_debug('Adding rememberme cookie for ' . $nickname);
 | 
					 | 
				
			||||||
                common_rememberme($user);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            // Re-init language env in case it changed (not yet, but soon)
 | 
					 | 
				
			||||||
            common_init_language();
 | 
					 | 
				
			||||||
            $this->showSuccess();
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            $this->showForm(_('Invalid username or password.'));
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -250,22 +291,24 @@ class RegisterAction extends Action
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // overrrided to add entry-title class
 | 
					    // overrrided to add entry-title class
 | 
				
			||||||
    function showPageTitle() {
 | 
					    function showPageTitle() {
 | 
				
			||||||
        $this->element('h1', array('class' => 'entry-title'), $this->title());
 | 
					        if (Event::handle('StartShowPageTitle', array($this))) {
 | 
				
			||||||
 | 
					            $this->element('h1', array('class' => 'entry-title'), $this->title());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // overrided to add hentry, and content-inner class
 | 
					    // overrided to add hentry, and content-inner class
 | 
				
			||||||
    function showContentBlock()
 | 
					    function showContentBlock()
 | 
				
			||||||
     {
 | 
					    {
 | 
				
			||||||
         $this->elementStart('div', array('id' => 'content', 'class' => 'hentry'));
 | 
					        $this->elementStart('div', array('id' => 'content', 'class' => 'hentry'));
 | 
				
			||||||
         $this->showPageTitle();
 | 
					        $this->showPageTitle();
 | 
				
			||||||
         $this->showPageNoticeBlock();
 | 
					        $this->showPageNoticeBlock();
 | 
				
			||||||
         $this->elementStart('div', array('id' => 'content_inner',
 | 
					        $this->elementStart('div', array('id' => 'content_inner',
 | 
				
			||||||
             'class' => 'entry-content'));
 | 
					                                         'class' => 'entry-content'));
 | 
				
			||||||
         // show the actual content (forms, lists, whatever)
 | 
					        // show the actual content (forms, lists, whatever)
 | 
				
			||||||
         $this->showContent();
 | 
					        $this->showContent();
 | 
				
			||||||
         $this->elementEnd('div');
 | 
					        $this->elementEnd('div');
 | 
				
			||||||
         $this->elementEnd('div');
 | 
					        $this->elementEnd('div');
 | 
				
			||||||
     }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Instructions or a notice for the page
 | 
					     * Instructions or a notice for the page
 | 
				
			||||||
@@ -339,17 +382,6 @@ class RegisterAction extends Action
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    function showFormContent()
 | 
					    function showFormContent()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $code = $this->trimmed('code');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ($code) {
 | 
					 | 
				
			||||||
            $invite = Invitation::staticGet($code);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (common_config('site', 'inviteonly') && !($code && $invite)) {
 | 
					 | 
				
			||||||
            $this->clientError(_('Sorry, only invited people can register.'));
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->elementStart('form', array('method' => 'post',
 | 
					        $this->elementStart('form', array('method' => 'post',
 | 
				
			||||||
                                          'id' => 'form_register',
 | 
					                                          'id' => 'form_register',
 | 
				
			||||||
                                          'class' => 'form_settings',
 | 
					                                          'class' => 'form_settings',
 | 
				
			||||||
@@ -358,82 +390,85 @@ class RegisterAction extends Action
 | 
				
			|||||||
        $this->element('legend', null, 'Account settings');
 | 
					        $this->element('legend', null, 'Account settings');
 | 
				
			||||||
        $this->hidden('token', common_session_token());
 | 
					        $this->hidden('token', common_session_token());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($code) {
 | 
					        if ($this->code) {
 | 
				
			||||||
            $this->hidden('code', $code);
 | 
					            $this->hidden('code', $this->code);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->elementStart('ul', 'form_data');
 | 
					        $this->elementStart('ul', 'form_data');
 | 
				
			||||||
        $this->elementStart('li');
 | 
					        if (Event::handle('StartRegistrationFormData', array($this))) {
 | 
				
			||||||
        $this->input('nickname', _('Nickname'), $this->trimmed('nickname'),
 | 
					            $this->elementStart('li');
 | 
				
			||||||
                     _('1-64 lowercase letters or numbers, '.
 | 
					            $this->input('nickname', _('Nickname'), $this->trimmed('nickname'),
 | 
				
			||||||
                       'no punctuation or spaces. Required.'));
 | 
					                         _('1-64 lowercase letters or numbers, '.
 | 
				
			||||||
        $this->elementEnd('li');
 | 
					                           'no punctuation or spaces. Required.'));
 | 
				
			||||||
        $this->elementStart('li');
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
        $this->password('password', _('Password'),
 | 
					            $this->elementStart('li');
 | 
				
			||||||
                        _('6 or more characters. Required.'));
 | 
					            $this->password('password', _('Password'),
 | 
				
			||||||
        $this->elementEnd('li');
 | 
					                            _('6 or more characters. Required.'));
 | 
				
			||||||
        $this->elementStart('li');
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
        $this->password('confirm', _('Confirm'),
 | 
					            $this->elementStart('li');
 | 
				
			||||||
                        _('Same as password above. Required.'));
 | 
					            $this->password('confirm', _('Confirm'),
 | 
				
			||||||
        $this->elementEnd('li');
 | 
					                            _('Same as password above. Required.'));
 | 
				
			||||||
        $this->elementStart('li');
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
        if ($invite && $invite->address_type == 'email') {
 | 
					            $this->elementStart('li');
 | 
				
			||||||
            $this->input('email', _('Email'), $invite->address,
 | 
					            if ($this->invite && $this->invite->address_type == 'email') {
 | 
				
			||||||
                         _('Used only for updates, announcements, '.
 | 
					                $this->input('email', _('Email'), $this->invite->address,
 | 
				
			||||||
                           'and password recovery'));
 | 
					                             _('Used only for updates, announcements, '.
 | 
				
			||||||
        } else {
 | 
					                               'and password recovery'));
 | 
				
			||||||
            $this->input('email', _('Email'), $this->trimmed('email'),
 | 
					            } else {
 | 
				
			||||||
                         _('Used only for updates, announcements, '.
 | 
					                $this->input('email', _('Email'), $this->trimmed('email'),
 | 
				
			||||||
                           'and password recovery'));
 | 
					                             _('Used only for updates, announcements, '.
 | 
				
			||||||
 | 
					                               'and password recovery'));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
 | 
					            $this->elementStart('li');
 | 
				
			||||||
 | 
					            $this->input('fullname', _('Full name'),
 | 
				
			||||||
 | 
					                         $this->trimmed('fullname'),
 | 
				
			||||||
 | 
					                         _('Longer name, preferably your "real" name'));
 | 
				
			||||||
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
 | 
					            $this->elementStart('li');
 | 
				
			||||||
 | 
					            $this->input('homepage', _('Homepage'),
 | 
				
			||||||
 | 
					                         $this->trimmed('homepage'),
 | 
				
			||||||
 | 
					                         _('URL of your homepage, blog, '.
 | 
				
			||||||
 | 
					                           'or profile on another site'));
 | 
				
			||||||
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
 | 
					            $this->elementStart('li');
 | 
				
			||||||
 | 
					            $this->textarea('bio', _('Bio'),
 | 
				
			||||||
 | 
					                            $this->trimmed('bio'),
 | 
				
			||||||
 | 
					                            _('Describe yourself and your '.
 | 
				
			||||||
 | 
					                              'interests in 140 chars'));
 | 
				
			||||||
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
 | 
					            $this->elementStart('li');
 | 
				
			||||||
 | 
					            $this->input('location', _('Location'),
 | 
				
			||||||
 | 
					                         $this->trimmed('location'),
 | 
				
			||||||
 | 
					                         _('Where you are, like "City, '.
 | 
				
			||||||
 | 
					                           'State (or Region), Country"'));
 | 
				
			||||||
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
 | 
					            Event::handle('EndRegistrationFormData', array($this));
 | 
				
			||||||
 | 
					            $this->elementStart('li', array('id' => 'settings_rememberme'));
 | 
				
			||||||
 | 
					            $this->checkbox('rememberme', _('Remember me'),
 | 
				
			||||||
 | 
					                            $this->boolean('rememberme'),
 | 
				
			||||||
 | 
					                            _('Automatically login in the future; '.
 | 
				
			||||||
 | 
					                              'not for shared computers!'));
 | 
				
			||||||
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
 | 
					            $attrs = array('type' => 'checkbox',
 | 
				
			||||||
 | 
					                           'id' => 'license',
 | 
				
			||||||
 | 
					                           'class' => 'checkbox',
 | 
				
			||||||
 | 
					                           'name' => 'license',
 | 
				
			||||||
 | 
					                           'value' => 'true');
 | 
				
			||||||
 | 
					            if ($this->boolean('license')) {
 | 
				
			||||||
 | 
					                $attrs['checked'] = 'checked';
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            $this->elementStart('li');
 | 
				
			||||||
 | 
					            $this->element('input', $attrs);
 | 
				
			||||||
 | 
					            $this->elementStart('label', array('class' => 'checkbox', 'for' => 'license'));
 | 
				
			||||||
 | 
					            $this->text(_('My text and files are available under '));
 | 
				
			||||||
 | 
					            $this->element('a', array('href' => common_config('license', 'url')),
 | 
				
			||||||
 | 
					                           common_config('license', 'title'), _("Creative Commons Attribution 3.0"));
 | 
				
			||||||
 | 
					            $this->text(_(' except this private data: password, '.
 | 
				
			||||||
 | 
					                          'email address, IM address, and phone number.'));
 | 
				
			||||||
 | 
					            $this->elementEnd('label');
 | 
				
			||||||
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        $this->elementEnd('li');
 | 
					 | 
				
			||||||
        $this->elementStart('li');
 | 
					 | 
				
			||||||
        $this->input('fullname', _('Full name'),
 | 
					 | 
				
			||||||
                     $this->trimmed('fullname'),
 | 
					 | 
				
			||||||
                     _('Longer name, preferably your "real" name'));
 | 
					 | 
				
			||||||
        $this->elementEnd('li');
 | 
					 | 
				
			||||||
        $this->elementStart('li');
 | 
					 | 
				
			||||||
        $this->input('homepage', _('Homepage'),
 | 
					 | 
				
			||||||
                     $this->trimmed('homepage'),
 | 
					 | 
				
			||||||
                     _('URL of your homepage, blog, '.
 | 
					 | 
				
			||||||
                       'or profile on another site'));
 | 
					 | 
				
			||||||
        $this->elementEnd('li');
 | 
					 | 
				
			||||||
        $this->elementStart('li');
 | 
					 | 
				
			||||||
        $this->textarea('bio', _('Bio'),
 | 
					 | 
				
			||||||
                        $this->trimmed('bio'),
 | 
					 | 
				
			||||||
                        _('Describe yourself and your '.
 | 
					 | 
				
			||||||
                          'interests in 140 chars'));
 | 
					 | 
				
			||||||
        $this->elementEnd('li');
 | 
					 | 
				
			||||||
        $this->elementStart('li');
 | 
					 | 
				
			||||||
        $this->input('location', _('Location'),
 | 
					 | 
				
			||||||
                     $this->trimmed('location'),
 | 
					 | 
				
			||||||
                     _('Where you are, like "City, '.
 | 
					 | 
				
			||||||
                       'State (or Region), Country"'));
 | 
					 | 
				
			||||||
        $this->elementEnd('li');
 | 
					 | 
				
			||||||
        $this->elementStart('li', array('id' => 'settings_rememberme'));
 | 
					 | 
				
			||||||
        $this->checkbox('rememberme', _('Remember me'),
 | 
					 | 
				
			||||||
                        $this->boolean('rememberme'),
 | 
					 | 
				
			||||||
                        _('Automatically login in the future; '.
 | 
					 | 
				
			||||||
                          'not for shared computers!'));
 | 
					 | 
				
			||||||
        $this->elementEnd('li');
 | 
					 | 
				
			||||||
        $attrs = array('type' => 'checkbox',
 | 
					 | 
				
			||||||
                       'id' => 'license',
 | 
					 | 
				
			||||||
                       'class' => 'checkbox',
 | 
					 | 
				
			||||||
                       'name' => 'license',
 | 
					 | 
				
			||||||
                       'value' => 'true');
 | 
					 | 
				
			||||||
        if ($this->boolean('license')) {
 | 
					 | 
				
			||||||
            $attrs['checked'] = 'checked';
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        $this->elementStart('li');
 | 
					 | 
				
			||||||
        $this->element('input', $attrs);
 | 
					 | 
				
			||||||
        $this->elementStart('label', array('class' => 'checkbox', 'for' => 'license'));
 | 
					 | 
				
			||||||
        $this->text(_('My text and files are available under '));
 | 
					 | 
				
			||||||
        $this->element('a', array('href' => common_config('license', 'url')),
 | 
					 | 
				
			||||||
                       common_config('license', 'title'), _("Creative Commons Attribution 3.0"));
 | 
					 | 
				
			||||||
        $this->text(_(' except this private data: password, '.
 | 
					 | 
				
			||||||
                      'email address, IM address, and phone number.'));
 | 
					 | 
				
			||||||
        $this->elementEnd('label');
 | 
					 | 
				
			||||||
        $this->elementEnd('li');
 | 
					 | 
				
			||||||
        $this->elementEnd('ul');
 | 
					        $this->elementEnd('ul');
 | 
				
			||||||
        $this->submit('submit', _('Register'));
 | 
					        $this->submit('submit', _('Register'));
 | 
				
			||||||
        $this->elementEnd('fieldset');
 | 
					        $this->elementEnd('fieldset');
 | 
				
			||||||
@@ -515,3 +550,4 @@ class RegisterAction extends Action
 | 
				
			|||||||
        $nav->show();
 | 
					        $nav->show();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,7 +35,7 @@ if (!defined('LACONICA')) {
 | 
				
			|||||||
require_once INSTALLDIR.'/lib/noticelist.php';
 | 
					require_once INSTALLDIR.'/lib/noticelist.php';
 | 
				
			||||||
require_once INSTALLDIR.'/lib/feedlist.php';
 | 
					require_once INSTALLDIR.'/lib/feedlist.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
define('MEMBERS_PER_SECTION', 81);
 | 
					define('MEMBERS_PER_SECTION', 27);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Group main page
 | 
					 * Group main page
 | 
				
			||||||
@@ -361,7 +361,7 @@ class ShowgroupAction extends Action
 | 
				
			|||||||
             $this->element('p', null, _('(None)'));
 | 
					             $this->element('p', null, _('(None)'));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($cnt == MEMBERS_PER_SECTION) {
 | 
					        if ($cnt > MEMBERS_PER_SECTION) {
 | 
				
			||||||
            $this->element('a', array('href' => common_local_url('groupmembers',
 | 
					            $this->element('a', array('href' => common_local_url('groupmembers',
 | 
				
			||||||
                                                                 array('nickname' => $this->group->nickname))),
 | 
					                                                                 array('nickname' => $this->group->nickname))),
 | 
				
			||||||
                           _('All members'));
 | 
					                           _('All members'));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -118,6 +118,16 @@ class SubscribersAction extends GalleryAction
 | 
				
			|||||||
        $this->raw(common_markup_to_html($message));
 | 
					        $this->raw(common_markup_to_html($message));
 | 
				
			||||||
        $this->elementEnd('div');
 | 
					        $this->elementEnd('div');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function showSections()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        parent::showSections();
 | 
				
			||||||
 | 
					        $cloud = new SubscribersPeopleTagCloudSection($this);
 | 
				
			||||||
 | 
					        $cloud->show();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $cloud2 = new SubscribersPeopleSelfTagCloudSection($this);
 | 
				
			||||||
 | 
					        $cloud2->show();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SubscribersList extends ProfileList
 | 
					class SubscribersList extends ProfileList
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -125,6 +125,16 @@ class SubscriptionsAction extends GalleryAction
 | 
				
			|||||||
        $this->raw(common_markup_to_html($message));
 | 
					        $this->raw(common_markup_to_html($message));
 | 
				
			||||||
        $this->elementEnd('div');
 | 
					        $this->elementEnd('div');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function showSections()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        parent::showSections();
 | 
				
			||||||
 | 
					        $cloud = new SubscriptionsPeopleTagCloudSection($this);
 | 
				
			||||||
 | 
					        $cloud->show();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $cloud2 = new SubscriptionsPeopleSelfTagCloudSection($this);
 | 
				
			||||||
 | 
					        $cloud2->show();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SubscriptionsList extends ProfileList
 | 
					class SubscriptionsList extends ProfileList
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -133,11 +133,7 @@ class TwitapifriendshipsAction extends TwitterapiAction
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($user_a->isSubscribed($user_b)) {
 | 
					        $result = $user_a->isSubscribed($user_b);
 | 
				
			||||||
            $result = 'true';
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            $result = 'false';
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        switch ($apidata['content-type']) {
 | 
					        switch ($apidata['content-type']) {
 | 
				
			||||||
         case 'xml':
 | 
					         case 'xml':
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -82,8 +82,8 @@ class TwitapiusersAction extends TwitterapiAction
 | 
				
			|||||||
		$twitter_user['profile_text_color'] = '';
 | 
							$twitter_user['profile_text_color'] = '';
 | 
				
			||||||
		$twitter_user['profile_link_color'] = '';
 | 
							$twitter_user['profile_link_color'] = '';
 | 
				
			||||||
		$twitter_user['profile_sidebar_fill_color'] = '';
 | 
							$twitter_user['profile_sidebar_fill_color'] = '';
 | 
				
			||||||
        $twitter_user['profile_sidebar_border_color'] = '';
 | 
							$twitter_user['profile_sidebar_border_color'] = '';
 | 
				
			||||||
        $twitter_user['profile_background_tile'] = 'false';
 | 
							$twitter_user['profile_background_tile'] = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		$faves = DB_DataObject::factory('fave');
 | 
							$faves = DB_DataObject::factory('fave');
 | 
				
			||||||
		$faves->user_id = $user->id;
 | 
							$faves->user_id = $user->id;
 | 
				
			||||||
@@ -103,24 +103,16 @@ class TwitapiusersAction extends TwitterapiAction
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		if (isset($apidata['user'])) {
 | 
							if (isset($apidata['user'])) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if ($apidata['user']->isSubscribed($profile)) {
 | 
								$twitter_user['following'] = $apidata['user']->isSubscribed($profile);
 | 
				
			||||||
				$twitter_user['following'] = 'true';
 | 
					            
 | 
				
			||||||
			} else {
 | 
								// Notifications on?
 | 
				
			||||||
				$twitter_user['following'] = 'false';
 | 
								$sub = Subscription::pkeyGet(array('subscriber' =>
 | 
				
			||||||
 | 
									$apidata['user']->id, 'subscribed' => $profile->id));
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
								if ($sub) {
 | 
				
			||||||
 | 
									$twitter_user['notifications'] = ($sub->jabber || $sub->sms);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
            
 | 
							}
 | 
				
			||||||
            // Notifications on?
 | 
					 | 
				
			||||||
		    $sub = Subscription::pkeyGet(array('subscriber' =>
 | 
					 | 
				
			||||||
		        $apidata['user']->id, 'subscribed' => $profile->id));
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            if ($sub) {
 | 
					 | 
				
			||||||
                if ($sub->jabber || $sub->sms) {
 | 
					 | 
				
			||||||
                    $twitter_user['notifications'] = 'true';
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    $twitter_user['notifications'] = 'false';
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
		if ($apidata['content-type'] == 'xml') {
 | 
							if ($apidata['content-type'] == 'xml') {
 | 
				
			||||||
			$this->init_document('xml');
 | 
								$this->init_document('xml');
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -197,7 +197,12 @@ class Notice extends Memcached_DataObject
 | 
				
			|||||||
            $notice->saveTags();
 | 
					            $notice->saveTags();
 | 
				
			||||||
            $notice->saveGroups();
 | 
					            $notice->saveGroups();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $notice->addToInboxes();
 | 
					            if (common_config('queue', 'enabled')) {
 | 
				
			||||||
 | 
					                $notice->addToAuthorInbox();
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                $notice->addToInboxes();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $notice->query('COMMIT');
 | 
					            $notice->query('COMMIT');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Event::handle('EndNoticeSave', array($notice));
 | 
					            Event::handle('EndNoticeSave', array($notice));
 | 
				
			||||||
@@ -207,7 +212,11 @@ class Notice extends Memcached_DataObject
 | 
				
			|||||||
        # XXX: someone clever could prepend instead of clearing the cache
 | 
					        # XXX: someone clever could prepend instead of clearing the cache
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (common_config('memcached', 'enabled')) {
 | 
					        if (common_config('memcached', 'enabled')) {
 | 
				
			||||||
            $notice->blowCaches();
 | 
					            if (common_config('queue', 'enabled')) {
 | 
				
			||||||
 | 
					                $notice->blowAuthorCaches();
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                $notice->blowCaches();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $notice;
 | 
					        return $notice;
 | 
				
			||||||
@@ -271,6 +280,17 @@ class Notice extends Memcached_DataObject
 | 
				
			|||||||
        $this->blowGroupCache($blowLast);
 | 
					        $this->blowGroupCache($blowLast);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function blowAuthorCaches($blowLast=false)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Clear the user's cache
 | 
				
			||||||
 | 
					        $cache = common_memcache();
 | 
				
			||||||
 | 
					        if (!empty($cache)) {
 | 
				
			||||||
 | 
					            $cache->delete(common_cache_key('user:notices_with_friends:' . $this->profile_id));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        $this->blowNoticeCache($blowLast);
 | 
				
			||||||
 | 
					        $this->blowPublicCache($blowLast);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function blowGroupCache($blowLast=false)
 | 
					    function blowGroupCache($blowLast=false)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $cache = common_memcache();
 | 
					        $cache = common_memcache();
 | 
				
			||||||
@@ -639,6 +659,33 @@ class Notice extends Memcached_DataObject
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function addToAuthorInbox()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $enabled = common_config('inboxes', 'enabled');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($enabled === true || $enabled === 'transitional') {
 | 
				
			||||||
 | 
					            $user = User::staticGet('id', $this->profile_id);
 | 
				
			||||||
 | 
					            if (empty($user)) {
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            $inbox = new Notice_inbox();
 | 
				
			||||||
 | 
					            $UT = common_config('db','type')=='pgsql'?'"user"':'user';
 | 
				
			||||||
 | 
					            $qry = 'INSERT INTO notice_inbox (user_id, notice_id, created) ' .
 | 
				
			||||||
 | 
					              "SELECT $UT.id, " . $this->id . ", '" . $this->created . "' " .
 | 
				
			||||||
 | 
					              "FROM $UT " .
 | 
				
			||||||
 | 
					              "WHERE $UT.id = " . $this->profile_id . ' ' .
 | 
				
			||||||
 | 
					              'AND NOT EXISTS (SELECT user_id, notice_id ' .
 | 
				
			||||||
 | 
					              'FROM notice_inbox ' .
 | 
				
			||||||
 | 
					              "WHERE user_id = " . $this->profile_id . ' '.
 | 
				
			||||||
 | 
					              'AND notice_id = ' . $this->id . ' )';
 | 
				
			||||||
 | 
					            if ($enabled === 'transitional') {
 | 
				
			||||||
 | 
					                $qry .= " AND $UT.inboxed = 1";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            $inbox->query($qry);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function saveGroups()
 | 
					    function saveGroups()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $enabled = common_config('inboxes', 'enabled');
 | 
					        $enabled = common_config('inboxes', 'enabled');
 | 
				
			||||||
@@ -691,24 +738,29 @@ class Notice extends Memcached_DataObject
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                // FIXME: do this in an offline daemon
 | 
					                // FIXME: do this in an offline daemon
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                $inbox = new Notice_inbox();
 | 
					                $this->addToGroupInboxes($group);
 | 
				
			||||||
                $UT = common_config('db','type')=='pgsql'?'"user"':'user';
 | 
					 | 
				
			||||||
                $qry = 'INSERT INTO notice_inbox (user_id, notice_id, created, source) ' .
 | 
					 | 
				
			||||||
                  "SELECT $UT.id, " . $this->id . ", '" . $this->created . "', 2 " .
 | 
					 | 
				
			||||||
                  "FROM $UT JOIN group_member ON $UT.id = group_member.profile_id " .
 | 
					 | 
				
			||||||
                  'WHERE group_member.group_id = ' . $group->id . ' ' .
 | 
					 | 
				
			||||||
                  'AND NOT EXISTS (SELECT user_id, notice_id ' .
 | 
					 | 
				
			||||||
                  'FROM notice_inbox ' .
 | 
					 | 
				
			||||||
                  "WHERE user_id = $UT.id " .
 | 
					 | 
				
			||||||
                  'AND notice_id = ' . $this->id . ' )';
 | 
					 | 
				
			||||||
                if ($enabled === 'transitional') {
 | 
					 | 
				
			||||||
                    $qry .= " AND $UT.inboxed = 1";
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                $result = $inbox->query($qry);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function addToGroupInboxes($group)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $inbox = new Notice_inbox();
 | 
				
			||||||
 | 
					        $UT = common_config('db','type')=='pgsql'?'"user"':'user';
 | 
				
			||||||
 | 
					        $qry = 'INSERT INTO notice_inbox (user_id, notice_id, created, source) ' .
 | 
				
			||||||
 | 
					          "SELECT $UT.id, " . $this->id . ", '" . $this->created . "', 2 " .
 | 
				
			||||||
 | 
					          "FROM $UT JOIN group_member ON $UT.id = group_member.profile_id " .
 | 
				
			||||||
 | 
					          'WHERE group_member.group_id = ' . $group->id . ' ' .
 | 
				
			||||||
 | 
					          'AND NOT EXISTS (SELECT user_id, notice_id ' .
 | 
				
			||||||
 | 
					          'FROM notice_inbox ' .
 | 
				
			||||||
 | 
					          "WHERE user_id = $UT.id " .
 | 
				
			||||||
 | 
					          'AND notice_id = ' . $this->id . ' )';
 | 
				
			||||||
 | 
					        if ($enabled === 'transitional') {
 | 
				
			||||||
 | 
					            $qry .= " AND $UT.inboxed = 1";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        $result = $inbox->query($qry);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function saveReplies()
 | 
					    function saveReplies()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Alternative reply format
 | 
					        // Alternative reply format
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -117,6 +117,7 @@ create table notice (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    index notice_profile_id_idx (profile_id),
 | 
					    index notice_profile_id_idx (profile_id),
 | 
				
			||||||
    index notice_created_idx (created),
 | 
					    index notice_created_idx (created),
 | 
				
			||||||
 | 
					    index notice_replyto_idx (reply_to),
 | 
				
			||||||
    FULLTEXT(content)
 | 
					    FULLTEXT(content)
 | 
				
			||||||
) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci;
 | 
					) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@ VALUES
 | 
				
			|||||||
    ('deskbar','Deskbar-Applet','http://www.gnome.org/projects/deskbar-applet/', now()),
 | 
					    ('deskbar','Deskbar-Applet','http://www.gnome.org/projects/deskbar-applet/', now()),
 | 
				
			||||||
    ('Do','Gnome Do','http://do.davebsd.com/wiki/index.php?title=Microblog_Plugin', now()),
 | 
					    ('Do','Gnome Do','http://do.davebsd.com/wiki/index.php?title=Microblog_Plugin', now()),
 | 
				
			||||||
    ('Facebook','Facebook','http://apps.facebook.com/identica/', now()),
 | 
					    ('Facebook','Facebook','http://apps.facebook.com/identica/', now()),
 | 
				
			||||||
 | 
					    ('feed2omb','feed2omb','http://projects.ciarang.com/p/feed2omb/', now()),
 | 
				
			||||||
    ('Gwibber','Gwibber','http://launchpad.net/gwibber', now()),
 | 
					    ('Gwibber','Gwibber','http://launchpad.net/gwibber', now()),
 | 
				
			||||||
    ('HelloTxt','HelloTxt','http://hellotxt.com/', now()),
 | 
					    ('HelloTxt','HelloTxt','http://hellotxt.com/', now()),
 | 
				
			||||||
    ('identicatools','Laconica Tools','http://bitbucketlabs.net/laconica-tools/', now()),
 | 
					    ('identicatools','Laconica Tools','http://bitbucketlabs.net/laconica-tools/', now()),
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										36
									
								
								js/util.js
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								js/util.js
									
									
									
									
									
								
							@@ -166,19 +166,40 @@ $(document).ready(function(){
 | 
				
			|||||||
																		   $("#notice_action-submit").addClass("disabled");
 | 
																							   $("#notice_action-submit").addClass("disabled");
 | 
				
			||||||
																		   return true;
 | 
																							   return true;
 | 
				
			||||||
												 						 },
 | 
																	 						 },
 | 
				
			||||||
					   success: function(xml) {	if ($("#error", xml).length > 0 || $("#command_result", xml).length > 0) {
 | 
										   error: function (xhr, textStatus, errorThrown) {	$("#form_notice").removeClass("processing");
 | 
				
			||||||
 | 
																							$("#notice_action-submit").removeAttr("disabled");
 | 
				
			||||||
 | 
																							$("#notice_action-submit").removeClass("disabled");
 | 
				
			||||||
 | 
																							if ($(".error", xhr.responseXML).length > 0) {
 | 
				
			||||||
 | 
																								$('#form_notice').append(document._importNode($(".error", xhr.responseXML).get(0), true));
 | 
				
			||||||
 | 
																							}
 | 
				
			||||||
 | 
																							else {
 | 
				
			||||||
 | 
																								alert("Sorry! We had trouble sending your notice ("+xhr.status+" "+xhr.statusText+"). Please report the problem to the site administrator if this happens again.");
 | 
				
			||||||
 | 
																							}
 | 
				
			||||||
 | 
																						  },
 | 
				
			||||||
 | 
										   success: function(xml) {	if ($("#error", xml).length > 0) {
 | 
				
			||||||
													var result = document._importNode($("p", xml).get(0), true);
 | 
																		var result = document._importNode($("p", xml).get(0), true);
 | 
				
			||||||
													result = result.textContent || result.innerHTML;
 | 
																		result = result.textContent || result.innerHTML;
 | 
				
			||||||
													alert(result);
 | 
																		alert(result);
 | 
				
			||||||
												}
 | 
																	}
 | 
				
			||||||
												else {
 | 
																	else {
 | 
				
			||||||
													$("#notices_primary .notices").prepend(document._importNode($("li", xml).get(0), true));
 | 
																	    if ($("#command_result", xml).length > 0) {
 | 
				
			||||||
 | 
																		    var result = document._importNode($("p", xml).get(0), true);
 | 
				
			||||||
 | 
																		    result = result.textContent || result.innerHTML;
 | 
				
			||||||
 | 
																		    alert(result);
 | 
				
			||||||
 | 
					                                                    }
 | 
				
			||||||
 | 
					                                                    else {
 | 
				
			||||||
 | 
					                                                         li = $("li", xml).get(0);
 | 
				
			||||||
 | 
					                                                         id = li.id;
 | 
				
			||||||
 | 
					                                                         if ($("#"+li.id).length == 0) {
 | 
				
			||||||
 | 
					                                                              $("#notices_primary .notices").prepend(document._importNode(li, true));
 | 
				
			||||||
 | 
					                                                              $("#notices_primary .notice:first").css({display:"none"});
 | 
				
			||||||
 | 
					                                                              $("#notices_primary .notice:first").fadeIn(2500);
 | 
				
			||||||
 | 
					                                                              NoticeHover();
 | 
				
			||||||
 | 
					                                                              NoticeReply();
 | 
				
			||||||
 | 
					                                                         }
 | 
				
			||||||
 | 
																		}
 | 
				
			||||||
													$("#notice_data-text").val("");
 | 
																		$("#notice_data-text").val("");
 | 
				
			||||||
													counter();
 | 
					                                                    counter();
 | 
				
			||||||
													$("#notices_primary .notice:first").css({display:"none"});
 | 
					 | 
				
			||||||
													$("#notices_primary .notice:first").fadeIn(2500);
 | 
					 | 
				
			||||||
													NoticeHover();
 | 
					 | 
				
			||||||
													NoticeReply();
 | 
					 | 
				
			||||||
												}
 | 
																	}
 | 
				
			||||||
												$("#form_notice").removeClass("processing");
 | 
																	$("#form_notice").removeClass("processing");
 | 
				
			||||||
												$("#notice_action-submit").removeAttr("disabled");
 | 
																	$("#notice_action-submit").removeAttr("disabled");
 | 
				
			||||||
@@ -187,7 +208,6 @@ $(document).ready(function(){
 | 
				
			|||||||
					   };
 | 
										   };
 | 
				
			||||||
	$("#form_notice").ajaxForm(PostNotice);
 | 
						$("#form_notice").ajaxForm(PostNotice);
 | 
				
			||||||
	$("#form_notice").each(addAjaxHidden);
 | 
						$("#form_notice").each(addAjaxHidden);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    NoticeHover();
 | 
					    NoticeHover();
 | 
				
			||||||
    NoticeReply();
 | 
					    NoticeReply();
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -192,7 +192,7 @@ $_config_files[] = INSTALLDIR.'/config.php';
 | 
				
			|||||||
$_have_a_config = false;
 | 
					$_have_a_config = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
foreach ($_config_files as $_config_file) {
 | 
					foreach ($_config_files as $_config_file) {
 | 
				
			||||||
    if (file_exists($_config_file)) {
 | 
					    if (@file_exists($_config_file)) {
 | 
				
			||||||
        include_once($_config_file);
 | 
					        include_once($_config_file);
 | 
				
			||||||
        $_have_a_config = true;
 | 
					        $_have_a_config = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -134,9 +134,11 @@ class GalleryAction extends Action
 | 
				
			|||||||
            $this->elementStart('li', array('id'=>'filter_tags_item'));
 | 
					            $this->elementStart('li', array('id'=>'filter_tags_item'));
 | 
				
			||||||
            $this->elementStart('form', array('name' => 'bytag',
 | 
					            $this->elementStart('form', array('name' => 'bytag',
 | 
				
			||||||
                                               'id' => 'bytag',
 | 
					                                               'id' => 'bytag',
 | 
				
			||||||
 | 
					                                               'action' => common_path('?action=' . $this->trimmed('action')),
 | 
				
			||||||
                                               'method' => 'post'));
 | 
					                                               'method' => 'post'));
 | 
				
			||||||
            $this->dropdown('tag', _('Tag'), $content,
 | 
					            $this->dropdown('tag', _('Tag'), $content,
 | 
				
			||||||
                            _('Choose a tag to narrow list'), false, $tag);
 | 
					                            _('Choose a tag to narrow list'), false, $tag);
 | 
				
			||||||
 | 
					            $this->hidden('nickname', $this->user->nickname);
 | 
				
			||||||
            $this->submit('submit', _('Go'));
 | 
					            $this->submit('submit', _('Go'));
 | 
				
			||||||
            $this->elementEnd('form');
 | 
					            $this->elementEnd('form');
 | 
				
			||||||
            $this->elementEnd('li');
 | 
					            $this->elementEnd('li');
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -93,43 +93,45 @@ class PersonalGroupNav extends Widget
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $this->out->elementStart('ul', array('class' => 'nav'));
 | 
					        $this->out->elementStart('ul', array('class' => 'nav'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->out->menuItem(common_local_url('all', array('nickname' =>
 | 
					        if (Event::handle('StartPersonalGroupNav', array($this))) {
 | 
				
			||||||
                                                       $nickname)),
 | 
					            $this->out->menuItem(common_local_url('all', array('nickname' =>
 | 
				
			||||||
                         _('Personal'),
 | 
					                                                           $nickname)),
 | 
				
			||||||
                         sprintf(_('%s and friends'), (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)),
 | 
					                             _('Personal'),
 | 
				
			||||||
                         $action == 'all', 'nav_timeline_personal');
 | 
					                             sprintf(_('%s and friends'), (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)),
 | 
				
			||||||
        $this->out->menuItem(common_local_url('replies', array('nickname' =>
 | 
					                             $action == 'all', 'nav_timeline_personal');
 | 
				
			||||||
                                                              $nickname)),
 | 
					            $this->out->menuItem(common_local_url('replies', array('nickname' =>
 | 
				
			||||||
                         _('Replies'),
 | 
					                                                                  $nickname)),
 | 
				
			||||||
                         sprintf(_('Replies to %s'), (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)),
 | 
					                             _('Replies'),
 | 
				
			||||||
                         $action == 'replies', 'nav_timeline_replies');
 | 
					                             sprintf(_('Replies to %s'), (($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname)),
 | 
				
			||||||
        $this->out->menuItem(common_local_url('showstream', array('nickname' =>
 | 
					                             $action == 'replies', 'nav_timeline_replies');
 | 
				
			||||||
                                                              $nickname)),
 | 
					            $this->out->menuItem(common_local_url('showstream', array('nickname' =>
 | 
				
			||||||
                         _('Profile'),
 | 
					                                                                  $nickname)),
 | 
				
			||||||
                         ($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname,
 | 
					                             _('Profile'),
 | 
				
			||||||
                         $action == 'showstream', 'nav_profile');
 | 
					                             ($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname,
 | 
				
			||||||
        $this->out->menuItem(common_local_url('showfavorites', array('nickname' =>
 | 
					                             $action == 'showstream', 'nav_profile');
 | 
				
			||||||
                                                              $nickname)),
 | 
					            $this->out->menuItem(common_local_url('showfavorites', array('nickname' =>
 | 
				
			||||||
                         _('Favorites'),
 | 
					                                                                  $nickname)),
 | 
				
			||||||
                         sprintf(_('%s\'s favorite notices'), ($user_profile) ? $user_profile->getBestName() : _('User')),
 | 
					                             _('Favorites'),
 | 
				
			||||||
                         $action == 'showfavorites', 'nav_timeline_favorites');
 | 
					                             sprintf(_('%s\'s favorite notices'), ($user_profile) ? $user_profile->getBestName() : _('User')),
 | 
				
			||||||
 | 
					                             $action == 'showfavorites', 'nav_timeline_favorites');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $cur = common_current_user();
 | 
					            $cur = common_current_user();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($cur && $cur->id == $user->id) {
 | 
					            if ($cur && $cur->id == $user->id) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $this->out->menuItem(common_local_url('inbox', array('nickname' =>
 | 
					                $this->out->menuItem(common_local_url('inbox', array('nickname' =>
 | 
				
			||||||
                                                                     $nickname)),
 | 
					                                                                         $nickname)),
 | 
				
			||||||
                             _('Inbox'),
 | 
					                                 _('Inbox'),
 | 
				
			||||||
                             _('Your incoming messages'),
 | 
					                                 _('Your incoming messages'),
 | 
				
			||||||
                             $action == 'inbox');
 | 
					                                 $action == 'inbox');
 | 
				
			||||||
            $this->out->menuItem(common_local_url('outbox', array('nickname' =>
 | 
					                $this->out->menuItem(common_local_url('outbox', array('nickname' =>
 | 
				
			||||||
                                                                     $nickname)),
 | 
					                                                                         $nickname)),
 | 
				
			||||||
                             _('Outbox'),
 | 
					                                 _('Outbox'),
 | 
				
			||||||
                             _('Your sent messages'),
 | 
					                                 _('Your sent messages'),
 | 
				
			||||||
                             $action == 'outbox');
 | 
					                                 $action == 'outbox');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Event::handle('EndPersonalGroupNav', array($this));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        $this->out->elementEnd('ul');
 | 
					        $this->out->elementEnd('ul');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -80,8 +80,8 @@ class QueueHandler extends Daemon
 | 
				
			|||||||
        if (!$this->start()) {
 | 
					        if (!$this->start()) {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        $this->log(LOG_INFO, 'checking for queued notices');
 | 
					 | 
				
			||||||
        $transport = $this->transport();
 | 
					        $transport = $this->transport();
 | 
				
			||||||
 | 
					        $this->log(LOG_INFO, 'checking for queued notices for "' . $transport . '"');
 | 
				
			||||||
        do {
 | 
					        do {
 | 
				
			||||||
            $qi = Queue_item::top($transport);
 | 
					            $qi = Queue_item::top($transport);
 | 
				
			||||||
            if ($qi) {
 | 
					            if ($qi) {
 | 
				
			||||||
@@ -143,4 +143,3 @@ class QueueHandler extends Daemon
 | 
				
			|||||||
        common_log($level, $this->class_name() . ' ('. $this->get_id() .'): '.$msg);
 | 
					        common_log($level, $this->class_name() . ' ('. $this->get_id() .'): '.$msg);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
@@ -51,7 +51,7 @@ class SearchAction extends Action
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return boolean true
 | 
					     * @return boolean true
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    function isReadOnly($args)
 | 
					    function isReadOnly()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										77
									
								
								lib/subpeopletagcloudsection.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								lib/subpeopletagcloudsection.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Laconica, the distributed open-source microblogging tool
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Personal tag cloud section
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * PHP version 5
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * LICENCE: This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @category  Widget
 | 
				
			||||||
 | 
					 * @package   Laconica
 | 
				
			||||||
 | 
					 * @author    Evan Prodromou <evan@controlyourself.ca>
 | 
				
			||||||
 | 
					 * @copyright 2009 Control Yourself, Inc.
 | 
				
			||||||
 | 
					 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 | 
				
			||||||
 | 
					 * @link      http://laconi.ca/
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!defined('LACONICA')) {
 | 
				
			||||||
 | 
					    exit(1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Personal tag cloud section
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @category Widget
 | 
				
			||||||
 | 
					 * @package  Laconica
 | 
				
			||||||
 | 
					 * @author   Evan Prodromou <evan@controlyourself.ca>
 | 
				
			||||||
 | 
					 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 | 
				
			||||||
 | 
					 * @link     http://laconi.ca/
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SubPeopleTagCloudSection extends TagCloudSection
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    function getTags()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $qry = $this->query();
 | 
				
			||||||
 | 
					        $limit = TAGS_PER_SECTION;
 | 
				
			||||||
 | 
					        $offset = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (common_config('db','type') == 'pgsql') {
 | 
				
			||||||
 | 
					            $qry .= ' LIMIT ' . $limit . ' OFFSET ' . $offset;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            $qry .= ' LIMIT ' . $offset . ', ' . $limit;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $profile_tag = Memcached_DataObject::cachedQuery('Profile_tag',
 | 
				
			||||||
 | 
					                                                 sprintf($qry,
 | 
				
			||||||
 | 
					                                                         $this->out->user->id));
 | 
				
			||||||
 | 
					        return $profile_tag;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function tagUrl($tag) {
 | 
				
			||||||
 | 
					        return common_local_url('peopletag', array('tag' => $tag));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function showTag($tag, $weight, $relative) {
 | 
				
			||||||
 | 
					        $rel = 'tag-cloud-';
 | 
				
			||||||
 | 
					        $rel .= 1+intval(7 * $relative * $weight - 0.01);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->out->elementStart('li', $rel);
 | 
				
			||||||
 | 
					        $this->out->element('a', array('href' => $this->tagUrl($tag)), $tag);
 | 
				
			||||||
 | 
					        $this->out->elementEnd('li');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										62
									
								
								lib/subscriberspeopleselftagcloudsection.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								lib/subscriberspeopleselftagcloudsection.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Laconica, the distributed open-source microblogging tool
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Personal tag cloud section
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * PHP version 5
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * LICENCE: This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @category  Widget
 | 
				
			||||||
 | 
					 * @package   Laconica
 | 
				
			||||||
 | 
					 * @author    Evan Prodromou <evan@controlyourself.ca>
 | 
				
			||||||
 | 
					 * @copyright 2009 Control Yourself, Inc.
 | 
				
			||||||
 | 
					 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 | 
				
			||||||
 | 
					 * @link      http://laconi.ca/
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!defined('LACONICA')) {
 | 
				
			||||||
 | 
					    exit(1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Personal tag cloud section
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @category Widget
 | 
				
			||||||
 | 
					 * @package  Laconica
 | 
				
			||||||
 | 
					 * @author   Evan Prodromou <evan@controlyourself.ca>
 | 
				
			||||||
 | 
					 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 | 
				
			||||||
 | 
					 * @link     http://laconi.ca/
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SubscribersPeopleSelfTagCloudSection extends SubPeopleTagCloudSection
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    function title()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return _('People Tagcloud as self-tagged');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function query() {
 | 
				
			||||||
 | 
					//        return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged group by tag order by weight desc';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//        return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscribed where subscriber=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										61
									
								
								lib/subscriberspeopletagcloudsection.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								lib/subscriberspeopletagcloudsection.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Laconica, the distributed open-source microblogging tool
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Personal tag cloud section
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * PHP version 5
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * LICENCE: This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @category  Widget
 | 
				
			||||||
 | 
					 * @package   Laconica
 | 
				
			||||||
 | 
					 * @author    Evan Prodromou <evan@controlyourself.ca>
 | 
				
			||||||
 | 
					 * @copyright 2009 Control Yourself, Inc.
 | 
				
			||||||
 | 
					 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 | 
				
			||||||
 | 
					 * @link      http://laconi.ca/
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!defined('LACONICA')) {
 | 
				
			||||||
 | 
					    exit(1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Personal tag cloud section
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @category Widget
 | 
				
			||||||
 | 
					 * @package  Laconica
 | 
				
			||||||
 | 
					 * @author   Evan Prodromou <evan@controlyourself.ca>
 | 
				
			||||||
 | 
					 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 | 
				
			||||||
 | 
					 * @link     http://laconi.ca/
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SubscribersPeopleTagCloudSection extends SubPeopleTagCloudSection
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    function title()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return _('People Tagcloud as tagged');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function tagUrl($tag) {
 | 
				
			||||||
 | 
					        $nickname = $this->out->profile->nickname;
 | 
				
			||||||
 | 
					        return common_local_url('subscribers', array('nickname' => $nickname, 'tag' => $tag));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function query() {
 | 
				
			||||||
 | 
					//        return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagged and subscribed=tagger where subscribed=%d and subscriber != subscribed group by tag order by weight desc';
 | 
				
			||||||
 | 
					        return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagged and subscribed=tagger where subscribed=%d and subscriber != subscribed and tag is not null group by tag order by weight desc';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										61
									
								
								lib/subscriptionspeopleselftagcloudsection.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								lib/subscriptionspeopleselftagcloudsection.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Laconica, the distributed open-source microblogging tool
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Personal tag cloud section
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * PHP version 5
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * LICENCE: This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @category  Widget
 | 
				
			||||||
 | 
					 * @package   Laconica
 | 
				
			||||||
 | 
					 * @author    Evan Prodromou <evan@controlyourself.ca>
 | 
				
			||||||
 | 
					 * @copyright 2009 Control Yourself, Inc.
 | 
				
			||||||
 | 
					 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 | 
				
			||||||
 | 
					 * @link      http://laconi.ca/
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!defined('LACONICA')) {
 | 
				
			||||||
 | 
					    exit(1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Personal tag cloud section
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @category Widget
 | 
				
			||||||
 | 
					 * @package  Laconica
 | 
				
			||||||
 | 
					 * @author   Evan Prodromou <evan@controlyourself.ca>
 | 
				
			||||||
 | 
					 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 | 
				
			||||||
 | 
					 * @link     http://laconi.ca/
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SubscriptionsPeopleSelfTagCloudSection extends SubPeopleTagCloudSection
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    function title()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return _('People Tagcloud as self-tagged');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function query() {
 | 
				
			||||||
 | 
					//        return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscriber != subscribed and tagger = tagged group by tag order by weight desc';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscribed where subscriber=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//        return 'select tag, count(tag) as weight from subscription left join profile_tag on tagger = subscriber where subscribed=%d and subscribed != subscriber and tagger = tagged and tag is not null group by tag order by weight desc';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										61
									
								
								lib/subscriptionspeopletagcloudsection.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								lib/subscriptionspeopletagcloudsection.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Laconica, the distributed open-source microblogging tool
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Personal tag cloud section
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * PHP version 5
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * LICENCE: This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @category  Widget
 | 
				
			||||||
 | 
					 * @package   Laconica
 | 
				
			||||||
 | 
					 * @author    Evan Prodromou <evan@controlyourself.ca>
 | 
				
			||||||
 | 
					 * @copyright 2009 Control Yourself, Inc.
 | 
				
			||||||
 | 
					 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 | 
				
			||||||
 | 
					 * @link      http://laconi.ca/
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!defined('LACONICA')) {
 | 
				
			||||||
 | 
					    exit(1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Personal tag cloud section
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @category Widget
 | 
				
			||||||
 | 
					 * @package  Laconica
 | 
				
			||||||
 | 
					 * @author   Evan Prodromou <evan@controlyourself.ca>
 | 
				
			||||||
 | 
					 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 | 
				
			||||||
 | 
					 * @link     http://laconi.ca/
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SubscriptionsPeopleTagCloudSection extends SubPeopleTagCloudSection
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    function title()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return _('People Tagcloud as tagged');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function tagUrl($tag) {
 | 
				
			||||||
 | 
					        $nickname = $this->out->profile->nickname;
 | 
				
			||||||
 | 
					        return common_local_url('subscriptions', array('nickname' => $nickname, 'tag' => $tag));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function query() {
 | 
				
			||||||
 | 
					//        return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagger and subscribed=tagged where subscriber=%d and subscriber != subscribed group by tag order by weight desc';
 | 
				
			||||||
 | 
					        return 'select tag, count(tag) as weight from subscription left join profile_tag on subscriber=tagger and subscribed=tagged where subscriber=%d and subscriber != subscribed and tag is not null group by tag order by weight desc';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -51,6 +51,26 @@ class TwitterapiAction extends Action
 | 
				
			|||||||
        parent::handle($args);
 | 
					        parent::handle($args);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Overrides XMLOutputter::element to write booleans as strings (true|false).
 | 
				
			||||||
 | 
					     * See that method's documentation for more info.
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @param string $tag     Element type or tagname
 | 
				
			||||||
 | 
					     * @param array  $attrs   Array of element attributes, as
 | 
				
			||||||
 | 
					     *                        key-value pairs
 | 
				
			||||||
 | 
					     * @param string $content string content of the element
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @return void
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    function element($tag, $attrs=null, $content=null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (is_bool($content)) {
 | 
				
			||||||
 | 
					            $content = ($content ? 'true' : 'false');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return parent::element($tag, $attrs, $content);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    function twitter_user_array($profile, $get_notice=false)
 | 
					    function twitter_user_array($profile, $get_notice=false)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -66,7 +86,7 @@ class TwitterapiAction extends Action
 | 
				
			|||||||
        $avatar = $profile->getAvatar(AVATAR_STREAM_SIZE);
 | 
					        $avatar = $profile->getAvatar(AVATAR_STREAM_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $twitter_user['profile_image_url'] = ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_STREAM_SIZE);
 | 
					        $twitter_user['profile_image_url'] = ($avatar) ? $avatar->displayUrl() : Avatar::defaultImage(AVATAR_STREAM_SIZE);
 | 
				
			||||||
        $twitter_user['protected'] = 'false'; # not supported by Laconica yet
 | 
					        $twitter_user['protected'] = false; # not supported by Laconica yet
 | 
				
			||||||
        $twitter_user['url'] = ($profile->homepage) ? $profile->homepage : null;
 | 
					        $twitter_user['url'] = ($profile->homepage) ? $profile->homepage : null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($get_notice) {
 | 
					        if ($get_notice) {
 | 
				
			||||||
@@ -86,7 +106,7 @@ class TwitterapiAction extends Action
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        $twitter_status = array();
 | 
					        $twitter_status = array();
 | 
				
			||||||
        $twitter_status['text'] = $notice->content;
 | 
					        $twitter_status['text'] = $notice->content;
 | 
				
			||||||
        $twitter_status['truncated'] = 'false'; # Not possible on Laconica
 | 
					        $twitter_status['truncated'] = false; # Not possible on Laconica
 | 
				
			||||||
        $twitter_status['created_at'] = $this->date_twitter($notice->created);
 | 
					        $twitter_status['created_at'] = $this->date_twitter($notice->created);
 | 
				
			||||||
        $twitter_status['in_reply_to_status_id'] = ($notice->reply_to) ?
 | 
					        $twitter_status['in_reply_to_status_id'] = ($notice->reply_to) ?
 | 
				
			||||||
            intval($notice->reply_to) : null;
 | 
					            intval($notice->reply_to) : null;
 | 
				
			||||||
@@ -108,10 +128,9 @@ class TwitterapiAction extends Action
 | 
				
			|||||||
            ($replier_profile) ? $replier_profile->nickname : null;
 | 
					            ($replier_profile) ? $replier_profile->nickname : null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (isset($this->auth_user)) {
 | 
					        if (isset($this->auth_user)) {
 | 
				
			||||||
            $twitter_status['favorited'] =
 | 
					            $twitter_status['favorited'] = $this->auth_user->hasFave($notice);
 | 
				
			||||||
                ($this->auth_user->hasFave($notice)) ? 'true' : 'false';
 | 
					 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            $twitter_status['favorited'] = 'false';
 | 
					            $twitter_status['favorited'] = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($include_user) {
 | 
					        if ($include_user) {
 | 
				
			||||||
@@ -418,7 +437,7 @@ class TwitterapiAction extends Action
 | 
				
			|||||||
    function date_twitter($dt)
 | 
					    function date_twitter($dt)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $t = strtotime($dt);
 | 
					        $t = strtotime($dt);
 | 
				
			||||||
        return date("D M d G:i:s O Y", $t);
 | 
					        return date("D M d H:i:s O Y", $t);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // XXX: Candidate for a general utility method somewhere?
 | 
					    // XXX: Candidate for a general utility method somewhere?
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										27
									
								
								lib/util.php
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								lib/util.php
									
									
									
									
									
								
							@@ -519,11 +519,16 @@ function common_shorten_links($text)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
function common_shorten_link($url, $reverse = false)
 | 
					function common_shorten_link($url, $reverse = false)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static $url_cache = array();
 | 
					    static $url_cache = array();
 | 
				
			||||||
    if ($reverse) return isset($url_cache[$url]) ? $url_cache[$url] : $url;
 | 
					    if ($reverse) return isset($url_cache[$url]) ? $url_cache[$url] : $url;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $user = common_current_user();
 | 
					    $user = common_current_user();
 | 
				
			||||||
 | 
					    if (!isset($user)) {
 | 
				
			||||||
 | 
					      // common current user does not find a user when called from the XMPP daemon
 | 
				
			||||||
 | 
					      // therefore we'll set one here fix, so that XMPP given URLs may be shortened
 | 
				
			||||||
 | 
					      $user->urlshorteningservice = 'ur1.ca';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    $curlh = curl_init();
 | 
					    $curlh = curl_init();
 | 
				
			||||||
    curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait
 | 
					    curl_setopt($curlh, CURLOPT_CONNECTTIMEOUT, 20); // # seconds to wait
 | 
				
			||||||
    curl_setopt($curlh, CURLOPT_USERAGENT, 'Laconica');
 | 
					    curl_setopt($curlh, CURLOPT_USERAGENT, 'Laconica');
 | 
				
			||||||
@@ -874,7 +879,23 @@ function common_broadcast_notice($notice, $remote=false)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
function common_enqueue_notice($notice)
 | 
					function common_enqueue_notice($notice)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    foreach (array('jabber', 'omb', 'sms', 'public', 'twitter', 'facebook', 'ping') as $transport) {
 | 
					    $transports = array('omb', 'sms', 'twitter', 'facebook', 'ping');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (common_config('xmpp', 'enabled')) {
 | 
				
			||||||
 | 
					        $transports = array_merge($transports, array('jabber', 'public'));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (common_config('memcached', 'enabled')) {
 | 
				
			||||||
 | 
					        // Note: limited to 8 chars
 | 
				
			||||||
 | 
					        $transports[] = 'memcache';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (common_config('inboxes', 'enabled') === true ||
 | 
				
			||||||
 | 
					        common_config('inboxes', 'enabled') === 'transitional') {
 | 
				
			||||||
 | 
					        $transports[] = 'inbox';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    foreach ($transports as $transport) {
 | 
				
			||||||
        $qi = new Queue_item();
 | 
					        $qi = new Queue_item();
 | 
				
			||||||
        $qi->notice_id = $notice->id;
 | 
					        $qi->notice_id = $notice->id;
 | 
				
			||||||
        $qi->transport = $transport;
 | 
					        $qi->transport = $transport;
 | 
				
			||||||
@@ -961,7 +982,7 @@ function common_root_url($ssl=false)
 | 
				
			|||||||
function common_good_rand($bytes)
 | 
					function common_good_rand($bytes)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // XXX: use random.org...?
 | 
					    // XXX: use random.org...?
 | 
				
			||||||
    if (file_exists('/dev/urandom')) {
 | 
					    if (@file_exists('/dev/urandom')) {
 | 
				
			||||||
        return common_urandom($bytes);
 | 
					        return common_urandom($bytes);
 | 
				
			||||||
    } else { // FIXME: this is probably not good enough
 | 
					    } else { // FIXME: this is probably not good enough
 | 
				
			||||||
        return common_mtrand($bytes);
 | 
					        return common_mtrand($bytes);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										180
									
								
								plugins/Comet/CometPlugin.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								plugins/Comet/CometPlugin.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,180 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Laconica, the distributed open-source microblogging tool
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Plugin to do "real time" updates using Comet/Bayeux
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * PHP version 5
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * LICENCE: This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Affero General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @category  Plugin
 | 
				
			||||||
 | 
					 * @package   Laconica
 | 
				
			||||||
 | 
					 * @author    Evan Prodromou <evan@controlyourself.ca>
 | 
				
			||||||
 | 
					 * @copyright 2009 Control Yourself, Inc.
 | 
				
			||||||
 | 
					 * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 | 
				
			||||||
 | 
					 * @link      http://laconi.ca/
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!defined('LACONICA')) {
 | 
				
			||||||
 | 
					    exit(1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Plugin to do realtime updates using Comet
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @category Plugin
 | 
				
			||||||
 | 
					 * @package  Laconica
 | 
				
			||||||
 | 
					 * @author   Evan Prodromou <evan@controlyourself.ca>
 | 
				
			||||||
 | 
					 * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
 | 
				
			||||||
 | 
					 * @link     http://laconi.ca/
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CometPlugin extends Plugin
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    var $server = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function __construct($server=null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->server = $server;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        parent::__construct();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function onEndShowScripts($action)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $timeline = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->log(LOG_DEBUG, 'got action ' . $action->trimmed('action'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch ($action->trimmed('action')) {
 | 
				
			||||||
 | 
					         case 'public':
 | 
				
			||||||
 | 
					            $timeline = '/timelines/public';
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					         case 'tag':
 | 
				
			||||||
 | 
					            $tag = $action->trimmed('tag');
 | 
				
			||||||
 | 
					            if (!empty($tag)) {
 | 
				
			||||||
 | 
					                $timeline = '/timelines/tag/'.$tag;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					         default:
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $scripts = array('jquery.comet.js', 'json2.js', 'updatetimeline.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        foreach ($scripts as $script) {
 | 
				
			||||||
 | 
					            $action->element('script', array('type' => 'text/javascript',
 | 
				
			||||||
 | 
					                                             'src' => common_path('plugins/Comet/'.$script)),
 | 
				
			||||||
 | 
					                         ' ');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $action->elementStart('script', array('type' => 'text/javascript'));
 | 
				
			||||||
 | 
					        $action->raw("$(document).ready(function() { updater.init(\"$this->server\", \"$timeline\");});");
 | 
				
			||||||
 | 
					        $action->elementEnd('script');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function onEndNoticeSave($notice)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->log(LOG_INFO, "Called for save notice.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $timelines = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // XXX: Add other timelines; this is just for the public one
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($notice->is_local ||
 | 
				
			||||||
 | 
					            ($notice->is_local == 0 && !common_config('public', 'localonly'))) {
 | 
				
			||||||
 | 
					            $timelines[] = '/timelines/public';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $tags = $this->getNoticeTags($notice);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!empty($tags)) {
 | 
				
			||||||
 | 
					            foreach ($tags as $tag) {
 | 
				
			||||||
 | 
					                $timelines[] = '/timelines/tag/' . $tag;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (count($timelines) > 0) {
 | 
				
			||||||
 | 
					            // Require this, since we need it
 | 
				
			||||||
 | 
					            require_once(INSTALLDIR.'/plugins/Comet/bayeux.class.inc.php');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $json = $this->noticeAsJson($notice);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Bayeux? Comet? Huh? These terms confuse me
 | 
				
			||||||
 | 
					            $bay = new Bayeux($this->server);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            foreach ($timelines as $timeline) {
 | 
				
			||||||
 | 
					                $this->log(LOG_INFO, "Posting notice $notice->id to '$timeline'.");
 | 
				
			||||||
 | 
					                $bay->publish($timeline, $json);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $bay = NULL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function noticeAsJson($notice)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // FIXME: this code should be abstracted to a neutral third
 | 
				
			||||||
 | 
					        // party, like Notice::asJson(). I'm not sure of the ethics
 | 
				
			||||||
 | 
					        // of refactoring from within a plugin, so I'm just abusing
 | 
				
			||||||
 | 
					        // the TwitterApiAction method. Don't do this unless you're me!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        require_once(INSTALLDIR.'/lib/twitterapi.php');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $act = new TwitterApiAction('/dev/null');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $arr = $act->twitter_status_array($notice, true);
 | 
				
			||||||
 | 
					        $arr['url'] = $notice->bestUrl();
 | 
				
			||||||
 | 
					        $arr['html'] = htmlspecialchars($notice->rendered);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $profile = $notice->getProfile();
 | 
				
			||||||
 | 
					        $arr['user']['profile_url'] = $profile->profileurl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $arr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function getNoticeTags($notice)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $tags = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $nt = new Notice_tag();
 | 
				
			||||||
 | 
					        $nt->notice_id = $notice->id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($nt->find()) {
 | 
				
			||||||
 | 
					            $tags = array();
 | 
				
			||||||
 | 
					            while ($nt->fetch()) {
 | 
				
			||||||
 | 
					                $tags[] = $nt->tag;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $nt->free();
 | 
				
			||||||
 | 
					        $nt = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $tags;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Push this up to Plugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function log($level, $msg)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        common_log($level, get_class($this) . ': '.$msg);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								plugins/Comet/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								plugins/Comet/README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					This is a plugin to automatically load notices in the browser no
 | 
				
			||||||
 | 
					matter who creates them -- the kind of thing we see with
 | 
				
			||||||
 | 
					search.twitter.com, rejaw.com, or FriendFeed's "real time" news.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NOTE: this is an insecure version; don't roll it out on a production
 | 
				
			||||||
 | 
					server.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It requires a cometd server. I've only had the cometd-java server work
 | 
				
			||||||
 | 
					correctly; something's wiggy with the Twisted-based server.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					After you have a cometd server installed, just add this code to your
 | 
				
			||||||
 | 
					config.php:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    require_once(INSTALLDIR.'/plugins/Comet/CometPlugin.php');
 | 
				
			||||||
 | 
					    $cp = new CometPlugin('http://example.com:8080/cometd/');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Change 'example.com:8080' to the name and port of the server you
 | 
				
			||||||
 | 
					installed cometd on.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TODO:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Needs to be tested with Ajax submission. Probably messes everything
 | 
				
			||||||
 | 
					  up.
 | 
				
			||||||
 | 
					* Add more timelines: personal inbox and tags would be great.
 | 
				
			||||||
 | 
					* Add security. In particular, only let the PHP code publish notices
 | 
				
			||||||
 | 
					  to the cometd server. Currently, it doesn't try to authenticate.
 | 
				
			||||||
							
								
								
									
										127
									
								
								plugins/Comet/bayeux.class.inc.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								plugins/Comet/bayeux.class.inc.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,127 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Phomet: a php comet client
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2008 Morgan 'ARR!' Allen <morganrallen@gmail.com> http://morglog.alleycatracing.com
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This library is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					 * modify it under the terms of the GNU Lesser General Public
 | 
				
			||||||
 | 
					 * License as published by the Free Software Foundation; either
 | 
				
			||||||
 | 
					 * version 2.1 of the License, or (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This library is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
				
			||||||
 | 
					 * Lesser General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Lesser General Public
 | 
				
			||||||
 | 
					 * License along with this library; if not, write to the Free Software
 | 
				
			||||||
 | 
					 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Bayeux
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    private $oCurl = '';
 | 
				
			||||||
 | 
					    private $nNextId = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public $sUrl = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function __construct($sUrl)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->sUrl = $sUrl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->oCurl = curl_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $aHeaders = array();
 | 
				
			||||||
 | 
					        $aHeaders[] = 'Connection: Keep-Alive';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        curl_setopt($this->oCurl, CURLOPT_URL, $sUrl);
 | 
				
			||||||
 | 
					        curl_setopt($this->oCurl, CURLOPT_HTTPHEADER, $aHeaders);
 | 
				
			||||||
 | 
					        curl_setopt($this->oCurl, CURLOPT_HEADER, 0);
 | 
				
			||||||
 | 
					        curl_setopt($this->oCurl, CURLOPT_POST, 1);
 | 
				
			||||||
 | 
					        curl_setopt($this->oCurl, CURLOPT_RETURNTRANSFER,1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->handShake();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function __destruct()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->disconnect();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function handShake()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $msgHandshake = array();
 | 
				
			||||||
 | 
					        $msgHandshake['channel'] = '/meta/handshake';
 | 
				
			||||||
 | 
					        $msgHandshake['version'] = "1.0";
 | 
				
			||||||
 | 
					        $msgHandshake['minimumVersion'] = "0.9";
 | 
				
			||||||
 | 
					        $msgHandshake['supportedConnectionTypes'] = array('long-polling');
 | 
				
			||||||
 | 
					        $msgHandshake['id'] = $this->nNextId++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        curl_setopt($this->oCurl, CURLOPT_POSTFIELDS, "message=".urlencode(str_replace('\\', '', json_encode(array($msgHandshake)))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = curl_exec($this->oCurl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(curl_errno($this->oCurl))
 | 
				
			||||||
 | 
					          die("Error: " . curl_error($this->oCurl));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $oReturn = json_decode($data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (is_array($oReturn)) {
 | 
				
			||||||
 | 
					            $oReturn = $oReturn[0];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $bSuccessful = ($oReturn->successful) ? true : false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if($bSuccessful)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            $this->clientId = $oReturn->clientId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $this->connect();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function connect()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $aMsg['channel'] = '/meta/connect';
 | 
				
			||||||
 | 
					        $aMsg['id'] = $this->nNextId++;
 | 
				
			||||||
 | 
					        $aMsg['clientId'] = $this->clientId;
 | 
				
			||||||
 | 
					        $aMsg['connectionType'] = 'long-polling';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        curl_setopt($this->oCurl, CURLOPT_POSTFIELDS, "message=".urlencode(str_replace('\\', '', json_encode(array($aMsg)))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = curl_exec($this->oCurl);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function disconnect()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $msgHandshake = array();
 | 
				
			||||||
 | 
					        $msgHandshake['channel'] = '/meta/disconnect';
 | 
				
			||||||
 | 
					        $msgHandshake['id'] = $this->nNextId++;
 | 
				
			||||||
 | 
					        $msgHandshake['clientId'] = $this->clientId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        curl_setopt($this->oCurl, CURLOPT_POSTFIELDS, "message=".urlencode(str_replace('\\', '', json_encode(array($msgHandshake)))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        curl_exec($this->oCurl);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function publish($sChannel, $oData)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(!$sChannel || !$oData)
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $aMsg = array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $aMsg['channel'] = $sChannel;
 | 
				
			||||||
 | 
					        $aMsg['id'] = $this->nNextId++;
 | 
				
			||||||
 | 
					        $aMsg['data'] = $oData;
 | 
				
			||||||
 | 
					        $aMsg['clientId'] = $this->clientId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        curl_setopt($this->oCurl, CURLOPT_POSTFIELDS, "message=".urlencode(str_replace('\\', '', json_encode(array($aMsg)))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $data = curl_exec($this->oCurl);
 | 
				
			||||||
 | 
					//        var_dump($data);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1451
									
								
								plugins/Comet/jquery.comet.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1451
									
								
								plugins/Comet/jquery.comet.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										478
									
								
								plugins/Comet/json2.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										478
									
								
								plugins/Comet/json2.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,478 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					    http://www.JSON.org/json2.js
 | 
				
			||||||
 | 
					    2009-04-16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Public Domain.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    See http://www.JSON.org/js.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This file creates a global JSON object containing two methods: stringify
 | 
				
			||||||
 | 
					    and parse.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        JSON.stringify(value, replacer, space)
 | 
				
			||||||
 | 
					            value       any JavaScript value, usually an object or array.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            replacer    an optional parameter that determines how object
 | 
				
			||||||
 | 
					                        values are stringified for objects. It can be a
 | 
				
			||||||
 | 
					                        function or an array of strings.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            space       an optional parameter that specifies the indentation
 | 
				
			||||||
 | 
					                        of nested structures. If it is omitted, the text will
 | 
				
			||||||
 | 
					                        be packed without extra whitespace. If it is a number,
 | 
				
			||||||
 | 
					                        it will specify the number of spaces to indent at each
 | 
				
			||||||
 | 
					                        level. If it is a string (such as '\t' or ' '),
 | 
				
			||||||
 | 
					                        it contains the characters used to indent at each level.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            This method produces a JSON text from a JavaScript value.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            When an object value is found, if the object contains a toJSON
 | 
				
			||||||
 | 
					            method, its toJSON method will be called and the result will be
 | 
				
			||||||
 | 
					            stringified. A toJSON method does not serialize: it returns the
 | 
				
			||||||
 | 
					            value represented by the name/value pair that should be serialized,
 | 
				
			||||||
 | 
					            or undefined if nothing should be serialized. The toJSON method
 | 
				
			||||||
 | 
					            will be passed the key associated with the value, and this will be
 | 
				
			||||||
 | 
					            bound to the object holding the key.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            For example, this would serialize Dates as ISO strings.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Date.prototype.toJSON = function (key) {
 | 
				
			||||||
 | 
					                    function f(n) {
 | 
				
			||||||
 | 
					                        // Format integers to have at least two digits.
 | 
				
			||||||
 | 
					                        return n < 10 ? '0' + n : n;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    return this.getUTCFullYear()   + '-' +
 | 
				
			||||||
 | 
					                         f(this.getUTCMonth() + 1) + '-' +
 | 
				
			||||||
 | 
					                         f(this.getUTCDate())      + 'T' +
 | 
				
			||||||
 | 
					                         f(this.getUTCHours())     + ':' +
 | 
				
			||||||
 | 
					                         f(this.getUTCMinutes())   + ':' +
 | 
				
			||||||
 | 
					                         f(this.getUTCSeconds())   + 'Z';
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            You can provide an optional replacer method. It will be passed the
 | 
				
			||||||
 | 
					            key and value of each member, with this bound to the containing
 | 
				
			||||||
 | 
					            object. The value that is returned from your method will be
 | 
				
			||||||
 | 
					            serialized. If your method returns undefined, then the member will
 | 
				
			||||||
 | 
					            be excluded from the serialization.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            If the replacer parameter is an array of strings, then it will be
 | 
				
			||||||
 | 
					            used to select the members to be serialized. It filters the results
 | 
				
			||||||
 | 
					            such that only members with keys listed in the replacer array are
 | 
				
			||||||
 | 
					            stringified.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Values that do not have JSON representations, such as undefined or
 | 
				
			||||||
 | 
					            functions, will not be serialized. Such values in objects will be
 | 
				
			||||||
 | 
					            dropped; in arrays they will be replaced with null. You can use
 | 
				
			||||||
 | 
					            a replacer function to replace those with JSON values.
 | 
				
			||||||
 | 
					            JSON.stringify(undefined) returns undefined.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            The optional space parameter produces a stringification of the
 | 
				
			||||||
 | 
					            value that is filled with line breaks and indentation to make it
 | 
				
			||||||
 | 
					            easier to read.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            If the space parameter is a non-empty string, then that string will
 | 
				
			||||||
 | 
					            be used for indentation. If the space parameter is a number, then
 | 
				
			||||||
 | 
					            the indentation will be that many spaces.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            text = JSON.stringify(['e', {pluribus: 'unum'}]);
 | 
				
			||||||
 | 
					            // text is '["e",{"pluribus":"unum"}]'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
 | 
				
			||||||
 | 
					            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            text = JSON.stringify([new Date()], function (key, value) {
 | 
				
			||||||
 | 
					                return this[key] instanceof Date ?
 | 
				
			||||||
 | 
					                    'Date(' + this[key] + ')' : value;
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            // text is '["Date(---current time---)"]'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        JSON.parse(text, reviver)
 | 
				
			||||||
 | 
					            This method parses a JSON text to produce an object or array.
 | 
				
			||||||
 | 
					            It can throw a SyntaxError exception.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            The optional reviver parameter is a function that can filter and
 | 
				
			||||||
 | 
					            transform the results. It receives each of the keys and values,
 | 
				
			||||||
 | 
					            and its return value is used instead of the original value.
 | 
				
			||||||
 | 
					            If it returns what it received, then the structure is not modified.
 | 
				
			||||||
 | 
					            If it returns undefined then the member is deleted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Parse the text. Values that look like ISO date strings will
 | 
				
			||||||
 | 
					            // be converted to Date objects.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            myData = JSON.parse(text, function (key, value) {
 | 
				
			||||||
 | 
					                var a;
 | 
				
			||||||
 | 
					                if (typeof value === 'string') {
 | 
				
			||||||
 | 
					                    a =
 | 
				
			||||||
 | 
					/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
 | 
				
			||||||
 | 
					                    if (a) {
 | 
				
			||||||
 | 
					                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
 | 
				
			||||||
 | 
					                            +a[5], +a[6]));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return value;
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
 | 
				
			||||||
 | 
					                var d;
 | 
				
			||||||
 | 
					                if (typeof value === 'string' &&
 | 
				
			||||||
 | 
					                        value.slice(0, 5) === 'Date(' &&
 | 
				
			||||||
 | 
					                        value.slice(-1) === ')') {
 | 
				
			||||||
 | 
					                    d = new Date(value.slice(5, -1));
 | 
				
			||||||
 | 
					                    if (d) {
 | 
				
			||||||
 | 
					                        return d;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return value;
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This is a reference implementation. You are free to copy, modify, or
 | 
				
			||||||
 | 
					    redistribute.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    This code should be minified before deployment.
 | 
				
			||||||
 | 
					    See http://javascript.crockford.com/jsmin.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
 | 
				
			||||||
 | 
					    NOT CONTROL.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*jslint evil: true */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*global JSON */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
 | 
				
			||||||
 | 
					    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
 | 
				
			||||||
 | 
					    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
 | 
				
			||||||
 | 
					    lastIndex, length, parse, prototype, push, replace, slice, stringify,
 | 
				
			||||||
 | 
					    test, toJSON, toString, valueOf
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Create a JSON object only if one does not already exist. We create the
 | 
				
			||||||
 | 
					// methods in a closure to avoid creating global variables.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!this.JSON) {
 | 
				
			||||||
 | 
					    JSON = {};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					(function () {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function f(n) {
 | 
				
			||||||
 | 
					        // Format integers to have at least two digits.
 | 
				
			||||||
 | 
					        return n < 10 ? '0' + n : n;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (typeof Date.prototype.toJSON !== 'function') {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Date.prototype.toJSON = function (key) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return this.getUTCFullYear()   + '-' +
 | 
				
			||||||
 | 
					                 f(this.getUTCMonth() + 1) + '-' +
 | 
				
			||||||
 | 
					                 f(this.getUTCDate())      + 'T' +
 | 
				
			||||||
 | 
					                 f(this.getUTCHours())     + ':' +
 | 
				
			||||||
 | 
					                 f(this.getUTCMinutes())   + ':' +
 | 
				
			||||||
 | 
					                 f(this.getUTCSeconds())   + 'Z';
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        String.prototype.toJSON =
 | 
				
			||||||
 | 
					        Number.prototype.toJSON =
 | 
				
			||||||
 | 
					        Boolean.prototype.toJSON = function (key) {
 | 
				
			||||||
 | 
					            return this.valueOf();
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
 | 
				
			||||||
 | 
					        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
 | 
				
			||||||
 | 
					        gap,
 | 
				
			||||||
 | 
					        indent,
 | 
				
			||||||
 | 
					        meta = {    // table of character substitutions
 | 
				
			||||||
 | 
					            '\b': '\\b',
 | 
				
			||||||
 | 
					            '\t': '\\t',
 | 
				
			||||||
 | 
					            '\n': '\\n',
 | 
				
			||||||
 | 
					            '\f': '\\f',
 | 
				
			||||||
 | 
					            '\r': '\\r',
 | 
				
			||||||
 | 
					            '"' : '\\"',
 | 
				
			||||||
 | 
					            '\\': '\\\\'
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        rep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function quote(string) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// If the string contains no control characters, no quote characters, and no
 | 
				
			||||||
 | 
					// backslash characters, then we can safely slap some quotes around it.
 | 
				
			||||||
 | 
					// Otherwise we must also replace the offending characters with safe escape
 | 
				
			||||||
 | 
					// sequences.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        escapable.lastIndex = 0;
 | 
				
			||||||
 | 
					        return escapable.test(string) ?
 | 
				
			||||||
 | 
					            '"' + string.replace(escapable, function (a) {
 | 
				
			||||||
 | 
					                var c = meta[a];
 | 
				
			||||||
 | 
					                return typeof c === 'string' ? c :
 | 
				
			||||||
 | 
					                    '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
 | 
				
			||||||
 | 
					            }) + '"' :
 | 
				
			||||||
 | 
					            '"' + string + '"';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function str(key, holder) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Produce a string from holder[key].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var i,          // The loop counter.
 | 
				
			||||||
 | 
					            k,          // The member key.
 | 
				
			||||||
 | 
					            v,          // The member value.
 | 
				
			||||||
 | 
					            length,
 | 
				
			||||||
 | 
					            mind = gap,
 | 
				
			||||||
 | 
					            partial,
 | 
				
			||||||
 | 
					            value = holder[key];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// If the value has a toJSON method, call it to obtain a replacement value.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (value && typeof value === 'object' &&
 | 
				
			||||||
 | 
					                typeof value.toJSON === 'function') {
 | 
				
			||||||
 | 
					            value = value.toJSON(key);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// If we were called with a replacer function, then call the replacer to
 | 
				
			||||||
 | 
					// obtain a replacement value.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (typeof rep === 'function') {
 | 
				
			||||||
 | 
					            value = rep.call(holder, key, value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// What happens next depends on the value's type.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch (typeof value) {
 | 
				
			||||||
 | 
					        case 'string':
 | 
				
			||||||
 | 
					            return quote(value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case 'number':
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// JSON numbers must be finite. Encode non-finite numbers as null.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return isFinite(value) ? String(value) : 'null';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case 'boolean':
 | 
				
			||||||
 | 
					        case 'null':
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// If the value is a boolean or null, convert it to a string. Note:
 | 
				
			||||||
 | 
					// typeof null does not produce 'null'. The case is included here in
 | 
				
			||||||
 | 
					// the remote chance that this gets fixed someday.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return String(value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// If the type is 'object', we might be dealing with an object or an array or
 | 
				
			||||||
 | 
					// null.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case 'object':
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Due to a specification blunder in ECMAScript, typeof null is 'object',
 | 
				
			||||||
 | 
					// so watch out for that case.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!value) {
 | 
				
			||||||
 | 
					                return 'null';
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Make an array to hold the partial results of stringifying this object value.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            gap += indent;
 | 
				
			||||||
 | 
					            partial = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Is the value an array?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (Object.prototype.toString.apply(value) === '[object Array]') {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The value is an array. Stringify every element. Use null as a placeholder
 | 
				
			||||||
 | 
					// for non-JSON values.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                length = value.length;
 | 
				
			||||||
 | 
					                for (i = 0; i < length; i += 1) {
 | 
				
			||||||
 | 
					                    partial[i] = str(i, value) || 'null';
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Join all of the elements together, separated with commas, and wrap them in
 | 
				
			||||||
 | 
					// brackets.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                v = partial.length === 0 ? '[]' :
 | 
				
			||||||
 | 
					                    gap ? '[\n' + gap +
 | 
				
			||||||
 | 
					                            partial.join(',\n' + gap) + '\n' +
 | 
				
			||||||
 | 
					                                mind + ']' :
 | 
				
			||||||
 | 
					                          '[' + partial.join(',') + ']';
 | 
				
			||||||
 | 
					                gap = mind;
 | 
				
			||||||
 | 
					                return v;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// If the replacer is an array, use it to select the members to be stringified.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (rep && typeof rep === 'object') {
 | 
				
			||||||
 | 
					                length = rep.length;
 | 
				
			||||||
 | 
					                for (i = 0; i < length; i += 1) {
 | 
				
			||||||
 | 
					                    k = rep[i];
 | 
				
			||||||
 | 
					                    if (typeof k === 'string') {
 | 
				
			||||||
 | 
					                        v = str(k, value);
 | 
				
			||||||
 | 
					                        if (v) {
 | 
				
			||||||
 | 
					                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Otherwise, iterate through all of the keys in the object.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for (k in value) {
 | 
				
			||||||
 | 
					                    if (Object.hasOwnProperty.call(value, k)) {
 | 
				
			||||||
 | 
					                        v = str(k, value);
 | 
				
			||||||
 | 
					                        if (v) {
 | 
				
			||||||
 | 
					                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Join all of the member texts together, separated with commas,
 | 
				
			||||||
 | 
					// and wrap them in braces.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            v = partial.length === 0 ? '{}' :
 | 
				
			||||||
 | 
					                gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
 | 
				
			||||||
 | 
					                        mind + '}' : '{' + partial.join(',') + '}';
 | 
				
			||||||
 | 
					            gap = mind;
 | 
				
			||||||
 | 
					            return v;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// If the JSON object does not yet have a stringify method, give it one.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (typeof JSON.stringify !== 'function') {
 | 
				
			||||||
 | 
					        JSON.stringify = function (value, replacer, space) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The stringify method takes a value and an optional replacer, and an optional
 | 
				
			||||||
 | 
					// space parameter, and returns a JSON text. The replacer can be a function
 | 
				
			||||||
 | 
					// that can replace values, or an array of strings that will select the keys.
 | 
				
			||||||
 | 
					// A default replacer method can be provided. Use of the space parameter can
 | 
				
			||||||
 | 
					// produce text that is more easily readable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var i;
 | 
				
			||||||
 | 
					            gap = '';
 | 
				
			||||||
 | 
					            indent = '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// If the space parameter is a number, make an indent string containing that
 | 
				
			||||||
 | 
					// many spaces.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (typeof space === 'number') {
 | 
				
			||||||
 | 
					                for (i = 0; i < space; i += 1) {
 | 
				
			||||||
 | 
					                    indent += ' ';
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// If the space parameter is a string, it will be used as the indent string.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            } else if (typeof space === 'string') {
 | 
				
			||||||
 | 
					                indent = space;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// If there is a replacer, it must be a function or an array.
 | 
				
			||||||
 | 
					// Otherwise, throw an error.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            rep = replacer;
 | 
				
			||||||
 | 
					            if (replacer && typeof replacer !== 'function' &&
 | 
				
			||||||
 | 
					                    (typeof replacer !== 'object' ||
 | 
				
			||||||
 | 
					                     typeof replacer.length !== 'number')) {
 | 
				
			||||||
 | 
					                throw new Error('JSON.stringify');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Make a fake root object containing our value under the key of ''.
 | 
				
			||||||
 | 
					// Return the result of stringifying the value.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return str('', {'': value});
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// If the JSON object does not yet have a parse method, give it one.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (typeof JSON.parse !== 'function') {
 | 
				
			||||||
 | 
					        JSON.parse = function (text, reviver) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The parse method takes a text and an optional reviver function, and returns
 | 
				
			||||||
 | 
					// a JavaScript value if the text is a valid JSON text.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var j;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            function walk(holder, key) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The walk method is used to recursively walk the resulting structure so
 | 
				
			||||||
 | 
					// that modifications can be made.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                var k, v, value = holder[key];
 | 
				
			||||||
 | 
					                if (value && typeof value === 'object') {
 | 
				
			||||||
 | 
					                    for (k in value) {
 | 
				
			||||||
 | 
					                        if (Object.hasOwnProperty.call(value, k)) {
 | 
				
			||||||
 | 
					                            v = walk(value, k);
 | 
				
			||||||
 | 
					                            if (v !== undefined) {
 | 
				
			||||||
 | 
					                                value[k] = v;
 | 
				
			||||||
 | 
					                            } else {
 | 
				
			||||||
 | 
					                                delete value[k];
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return reviver.call(holder, key, value);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Parsing happens in four stages. In the first stage, we replace certain
 | 
				
			||||||
 | 
					// Unicode characters with escape sequences. JavaScript handles many characters
 | 
				
			||||||
 | 
					// incorrectly, either silently deleting them, or treating them as line endings.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            cx.lastIndex = 0;
 | 
				
			||||||
 | 
					            if (cx.test(text)) {
 | 
				
			||||||
 | 
					                text = text.replace(cx, function (a) {
 | 
				
			||||||
 | 
					                    return '\\u' +
 | 
				
			||||||
 | 
					                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// In the second stage, we run the text against regular expressions that look
 | 
				
			||||||
 | 
					// for non-JSON patterns. We are especially concerned with '()' and 'new'
 | 
				
			||||||
 | 
					// because they can cause invocation, and '=' because it can cause mutation.
 | 
				
			||||||
 | 
					// But just to be safe, we want to reject all unexpected forms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// We split the second stage into 4 regexp operations in order to work around
 | 
				
			||||||
 | 
					// crippling inefficiencies in IE's and Safari's regexp engines. First we
 | 
				
			||||||
 | 
					// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
 | 
				
			||||||
 | 
					// replace all simple value tokens with ']' characters. Third, we delete all
 | 
				
			||||||
 | 
					// open brackets that follow a colon or comma or that begin the text. Finally,
 | 
				
			||||||
 | 
					// we look to see that the remaining characters are only whitespace or ']' or
 | 
				
			||||||
 | 
					// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (/^[\],:{}\s]*$/.
 | 
				
			||||||
 | 
					test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
 | 
				
			||||||
 | 
					replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
 | 
				
			||||||
 | 
					replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// In the third stage we use the eval function to compile the text into a
 | 
				
			||||||
 | 
					// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
 | 
				
			||||||
 | 
					// in JavaScript: it can begin a block or an object literal. We wrap the text
 | 
				
			||||||
 | 
					// in parens to eliminate the ambiguity.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                j = eval('(' + text + ')');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// In the optional fourth stage, we recursively walk the new structure, passing
 | 
				
			||||||
 | 
					// each name/value pair to a reviver function for possible transformation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return typeof reviver === 'function' ?
 | 
				
			||||||
 | 
					                    walk({'': j}, '') : j;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// If the text is not JSON parseable, then a SyntaxError is thrown.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            throw new SyntaxError('JSON.parse');
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}());
 | 
				
			||||||
							
								
								
									
										77
									
								
								plugins/Comet/updatetimeline.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								plugins/Comet/updatetimeline.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					// update the local timeline from a Comet server
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var updater = function()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					     var _cometd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     return {
 | 
				
			||||||
 | 
					          init: function(server, timeline)
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					               _cometd = $.cometd; // Uses the default Comet object
 | 
				
			||||||
 | 
					               _cometd.setLogLevel('debug');
 | 
				
			||||||
 | 
					               _cometd.init(server);
 | 
				
			||||||
 | 
					               _cometd.subscribe(timeline, receive);
 | 
				
			||||||
 | 
					               $(window).unload(leave);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     function leave()
 | 
				
			||||||
 | 
					     {
 | 
				
			||||||
 | 
					          _cometd.disconnect();
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     function receive(message)
 | 
				
			||||||
 | 
					     {
 | 
				
			||||||
 | 
					          id = message.data.id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          // Don't add it if it already exists
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if ($("#notice-"+id).length > 0) {
 | 
				
			||||||
 | 
					               return;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          var noticeItem = makeNoticeItem(message.data);
 | 
				
			||||||
 | 
					          $("#notices_primary .notices").prepend(noticeItem, true);
 | 
				
			||||||
 | 
					          $("#notices_primary .notice:first").css({display:"none"});
 | 
				
			||||||
 | 
					          $("#notices_primary .notice:first").fadeIn(2500);
 | 
				
			||||||
 | 
					          NoticeHover();
 | 
				
			||||||
 | 
					          NoticeReply();
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     function makeNoticeItem(data)
 | 
				
			||||||
 | 
					     {
 | 
				
			||||||
 | 
					          user = data['user'];
 | 
				
			||||||
 | 
					          html = data['html'].replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          ni = "<li class=\"hentry notice\" id=\"notice-"+data['id']+"\">"+
 | 
				
			||||||
 | 
					               "<div class=\"entry-title\">"+
 | 
				
			||||||
 | 
					               "<span class=\"vcard author\">"+
 | 
				
			||||||
 | 
					               "<a href=\""+user['profile_url']+"\" class=\"url\">"+
 | 
				
			||||||
 | 
					               "<img src=\""+user['profile_image_url']+"\" class=\"avatar photo\" width=\"48\" height=\"48\" alt=\""+user['screen_name']+"\"/>"+
 | 
				
			||||||
 | 
					               "<span class=\"nickname fn\">"+user['screen_name']+"</span>"+
 | 
				
			||||||
 | 
					               "</a>"+
 | 
				
			||||||
 | 
					               "</span>"+
 | 
				
			||||||
 | 
					               "<p class=\"entry-content\">"+html+"</p>"+
 | 
				
			||||||
 | 
					               "</div>"+
 | 
				
			||||||
 | 
					               "<div class=\"entry-content\">"+
 | 
				
			||||||
 | 
					               "<dl class=\"timestamp\">"+
 | 
				
			||||||
 | 
					               "<dt>Published</dt>"+
 | 
				
			||||||
 | 
					               "<dd>"+
 | 
				
			||||||
 | 
					               "<a rel=\"bookmark\" href=\""+data['url']+"\" >"+
 | 
				
			||||||
 | 
					               "<abbr class=\"published\" title=\""+data['created_at']+"\">a few seconds ago</abbr>"+
 | 
				
			||||||
 | 
					               "</a> "+
 | 
				
			||||||
 | 
					               "</dd>"+
 | 
				
			||||||
 | 
					               "</dl>"+
 | 
				
			||||||
 | 
					               "<dl class=\"device\">"+
 | 
				
			||||||
 | 
					               "<dt>From</dt> "+
 | 
				
			||||||
 | 
					               "<dd>"+data['source']+"</dd>"+
 | 
				
			||||||
 | 
					               "</dl>"+
 | 
				
			||||||
 | 
					               "</div>"+
 | 
				
			||||||
 | 
					               "<div class=\"notice-options\">"+
 | 
				
			||||||
 | 
					               "</div>"+
 | 
				
			||||||
 | 
					               "</li>";
 | 
				
			||||||
 | 
					          return ni;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					}();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -121,6 +121,12 @@ class LinkbackPlugin extends Plugin
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        $args = array($this->notice->uri, $url);
 | 
					        $args = array($this->notice->uri, $url);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!extension_loaded('xmlrpc')) {
 | 
				
			||||||
 | 
					            if (!dl('xmlrpc.so')) {
 | 
				
			||||||
 | 
					                common_log(LOG_ERR, "Can't pingback; xmlrpc extension not available.");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $request = xmlrpc_encode_request('pingback.ping', $args);
 | 
					        $request = xmlrpc_encode_request('pingback.ping', $args);
 | 
				
			||||||
        $context = stream_context_create(array('http' => array('method' => "POST",
 | 
					        $context = stream_context_create(array('http' => array('method' => "POST",
 | 
				
			||||||
                                                               'header' =>
 | 
					                                                               'header' =>
 | 
				
			||||||
@@ -141,7 +147,7 @@ class LinkbackPlugin extends Plugin
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Largely cadged from trackback_cls.php by
 | 
					    // Largely cadged from trackback_cls.php by
 | 
				
			||||||
    // Ran Aroussi <ran@blogish.org>, GPL2
 | 
					    // Ran Aroussi <ran@blogish.org>, GPL2 or any later version
 | 
				
			||||||
    // http://phptrackback.sourceforge.net/
 | 
					    // http://phptrackback.sourceforge.net/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function getTrackback($text, $url)
 | 
					    function getTrackback($text, $url)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										69
									
								
								scripts/inboxqueuehandler.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										69
									
								
								scripts/inboxqueuehandler.php
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env php
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Laconica - a distributed open-source microblogging tool
 | 
				
			||||||
 | 
					 * 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
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Abort if called from a web server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
 | 
				
			||||||
 | 
					    print "This script must be run from the command line\n";
 | 
				
			||||||
 | 
					    exit();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
 | 
				
			||||||
 | 
					define('LACONICA', true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require_once(INSTALLDIR . '/lib/common.php');
 | 
				
			||||||
 | 
					require_once(INSTALLDIR . '/lib/queuehandler.php');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set_error_handler('common_error_handler');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class InboxQueueHandler extends QueueHandler
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    function transport()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return 'inbox';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function start() {
 | 
				
			||||||
 | 
							$this->log(LOG_INFO, "INITIALIZE");
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function handle_notice($notice)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $this->log(LOG_INFO, "Distributing notice to inboxes for $notice->id");
 | 
				
			||||||
 | 
					        $notice->addToInboxes();
 | 
				
			||||||
 | 
					        $notice->blowSubsCache();
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function finish() {
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ini_set("max_execution_time", "0");
 | 
				
			||||||
 | 
					ini_set("max_input_time", "0");
 | 
				
			||||||
 | 
					set_time_limit(0);
 | 
				
			||||||
 | 
					mb_internal_encoding('UTF-8');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$id = ($argc > 1) ? $argv[1] : null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$handler = new InboxQueueHandler($id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$handler->runOnce();
 | 
				
			||||||
@@ -54,6 +54,13 @@ class JabberQueueHandler extends XmppQueueHandler
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Abort immediately if xmpp is not enabled, otherwise the daemon chews up
 | 
				
			||||||
 | 
					// lots of CPU trying to connect to unconfigured servers
 | 
				
			||||||
 | 
					if (common_config('xmpp','enabled')==false) {
 | 
				
			||||||
 | 
					    print "Aborting daemon - xmpp is disabled\n";
 | 
				
			||||||
 | 
					    exit();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ini_set("max_execution_time", "0");
 | 
					ini_set("max_execution_time", "0");
 | 
				
			||||||
ini_set("max_input_time", "0");
 | 
					ini_set("max_input_time", "0");
 | 
				
			||||||
set_time_limit(0);
 | 
					set_time_limit(0);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										70
									
								
								scripts/memcachedqueuehandler.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										70
									
								
								scripts/memcachedqueuehandler.php
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,70 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env php
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Laconica - a distributed open-source microblogging tool
 | 
				
			||||||
 | 
					 * 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
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Affero General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Affero General Public License
 | 
				
			||||||
 | 
					 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Abort if called from a web server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
 | 
				
			||||||
 | 
					    print "This script must be run from the command line\n";
 | 
				
			||||||
 | 
					    exit();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
 | 
				
			||||||
 | 
					define('LACONICA', true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require_once(INSTALLDIR . '/lib/common.php');
 | 
				
			||||||
 | 
					require_once(INSTALLDIR . '/lib/queuehandler.php');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set_error_handler('common_error_handler');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MemcachedQueueHandler extends QueueHandler
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    function transport()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return 'memcache';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function start() {
 | 
				
			||||||
 | 
							$this->log(LOG_INFO, "INITIALIZE");
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function handle_notice($notice)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // XXX: fork here
 | 
				
			||||||
 | 
					        $this->log(LOG_INFO, "Blowing memcached for $notice->id");
 | 
				
			||||||
 | 
					        $notice->blowCaches();
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function finish() {
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ini_set("max_execution_time", "0");
 | 
				
			||||||
 | 
					ini_set("max_input_time", "0");
 | 
				
			||||||
 | 
					set_time_limit(0);
 | 
				
			||||||
 | 
					mb_internal_encoding('UTF-8');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$id = ($argc > 1) ? $argv[1] : null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$handler = new MemcachedQueueHandler($id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$handler->runOnce();
 | 
				
			||||||
@@ -52,6 +52,13 @@ class PublicQueueHandler extends XmppQueueHandler
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Abort immediately if xmpp is not enabled, otherwise the daemon chews up
 | 
				
			||||||
 | 
					// lots of CPU trying to connect to unconfigured servers
 | 
				
			||||||
 | 
					if (common_config('xmpp','enabled')==false) {
 | 
				
			||||||
 | 
					    print "Aborting daemon - xmpp is disabled\n";
 | 
				
			||||||
 | 
					    exit();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ini_set("max_execution_time", "0");
 | 
					ini_set("max_execution_time", "0");
 | 
				
			||||||
ini_set("max_input_time", "0");
 | 
					ini_set("max_input_time", "0");
 | 
				
			||||||
set_time_limit(0);
 | 
					set_time_limit(0);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,7 +24,8 @@ DIR=`dirname $0`
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
for f in xmppdaemon.php jabberqueuehandler.php publicqueuehandler.php \
 | 
					for f in xmppdaemon.php jabberqueuehandler.php publicqueuehandler.php \
 | 
				
			||||||
         xmppconfirmhandler.php smsqueuehandler.php ombqueuehandler.php \
 | 
					         xmppconfirmhandler.php smsqueuehandler.php ombqueuehandler.php \
 | 
				
			||||||
         twitterqueuehandler.php facebookqueuehandler.php pingqueuehandler.php; do
 | 
					         twitterqueuehandler.php facebookqueuehandler.php pingqueuehandler.php \
 | 
				
			||||||
 | 
						 memcachedqueuehandler.php inboxqueuehandler.php; do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
         echo -n "Starting $f...";
 | 
					         echo -n "Starting $f...";
 | 
				
			||||||
	 php $DIR/$f
 | 
						 php $DIR/$f
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,7 +24,8 @@ SDIR=`dirname $0`
 | 
				
			|||||||
DIR=`php $SDIR/getpiddir.php`
 | 
					DIR=`php $SDIR/getpiddir.php`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
for f in jabberhandler ombhandler publichandler smshandler pinghandler \
 | 
					for f in jabberhandler ombhandler publichandler smshandler pinghandler \
 | 
				
			||||||
	 xmppconfirmhandler xmppdaemon twitterhandler facebookhandler ; do
 | 
						 xmppconfirmhandler xmppdaemon twitterhandler facebookhandler \
 | 
				
			||||||
 | 
					         memcachedhandler inboxhandler; do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	FILES="$DIR/$f.*.pid"
 | 
						FILES="$DIR/$f.*.pid"
 | 
				
			||||||
	for ff in "$FILES" ; do
 | 
						for ff in "$FILES" ; do
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -140,6 +140,13 @@ class XmppConfirmHandler extends XmppQueueHandler
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Abort immediately if xmpp is not enabled, otherwise the daemon chews up
 | 
				
			||||||
 | 
					// lots of CPU trying to connect to unconfigured servers
 | 
				
			||||||
 | 
					if (common_config('xmpp','enabled')==false) {
 | 
				
			||||||
 | 
					    print "Aborting daemon - xmpp is disabled\n";
 | 
				
			||||||
 | 
					    exit();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ini_set("max_execution_time", "0");
 | 
					ini_set("max_execution_time", "0");
 | 
				
			||||||
ini_set("max_input_time", "0");
 | 
					ini_set("max_input_time", "0");
 | 
				
			||||||
set_time_limit(0);
 | 
					set_time_limit(0);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -152,11 +152,6 @@ class XMPPDaemon extends Daemon
 | 
				
			|||||||
            $body = preg_replace('/d[\ ]*('. $to .')[\ ]*/', '', $pl['body']);
 | 
					            $body = preg_replace('/d[\ ]*('. $to .')[\ ]*/', '', $pl['body']);
 | 
				
			||||||
            $this->add_direct($user, $body, $to, $from);
 | 
					            $this->add_direct($user, $body, $to, $from);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            $len = mb_strlen($pl['body']);
 | 
					 | 
				
			||||||
            if($len > 140) {
 | 
					 | 
				
			||||||
                $this->from_site($from, 'Message too long - maximum is 140 characters, you sent ' . $len);
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            $this->add_notice($user, $pl);
 | 
					            $this->add_notice($user, $pl);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -255,15 +250,13 @@ class XMPPDaemon extends Daemon
 | 
				
			|||||||
    function add_notice(&$user, &$pl)
 | 
					    function add_notice(&$user, &$pl)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $body = trim($pl['body']);
 | 
					        $body = trim($pl['body']);
 | 
				
			||||||
        $content_shortened = common_shorten_link($body);
 | 
					        $content_shortened = common_shorten_links($body);
 | 
				
			||||||
        if (mb_strlen($content_shortened) > 140) {
 | 
					        if (mb_strlen($content_shortened) > 140) {
 | 
				
			||||||
            $content = trim(mb_substr($body, 0, 140));
 | 
					          $from = jabber_normalize_jid($pl['from']);
 | 
				
			||||||
            $content_shortened = common_shorten_link($content);
 | 
					          $this->from_site($from, "Message too long - maximum is 140 characters, you sent ".mb_strlen($content_shortened));
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        $notice = Notice::saveNew($user->id, $content_shortened, 'xmpp');
 | 
				
			||||||
            $content = $body;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        $notice = Notice::saveNew($user->id, $content, 'xmpp');
 | 
					 | 
				
			||||||
        if (is_string($notice)) {
 | 
					        if (is_string($notice)) {
 | 
				
			||||||
            $this->log(LOG_ERR, $notice);
 | 
					            $this->log(LOG_ERR, $notice);
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
@@ -321,6 +314,13 @@ class XMPPDaemon extends Daemon
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Abort immediately if xmpp is not enabled, otherwise the daemon chews up
 | 
				
			||||||
 | 
					// lots of CPU trying to connect to unconfigured servers
 | 
				
			||||||
 | 
					if (common_config('xmpp','enabled')==false) {
 | 
				
			||||||
 | 
					    print "Aborting daemon - xmpp is disabled\n";
 | 
				
			||||||
 | 
					    exit();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ini_set("max_execution_time", "0");
 | 
					ini_set("max_execution_time", "0");
 | 
				
			||||||
ini_set("max_input_time", "0");
 | 
					ini_set("max_input_time", "0");
 | 
				
			||||||
set_time_limit(0);
 | 
					set_time_limit(0);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -86,7 +86,7 @@ border:0;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.error,
 | 
					.error,
 | 
				
			||||||
.success {
 | 
					.success {
 | 
				
			||||||
padding:4px 7px;
 | 
					padding:4px 1.55%;
 | 
				
			||||||
border-radius:4px;
 | 
					border-radius:4px;
 | 
				
			||||||
-moz-border-radius:4px;
 | 
					-moz-border-radius:4px;
 | 
				
			||||||
-webkit-border-radius:4px;
 | 
					-webkit-border-radius:4px;
 | 
				
			||||||
@@ -426,6 +426,7 @@ line-height:1;
 | 
				
			|||||||
#form_notice fieldset {
 | 
					#form_notice fieldset {
 | 
				
			||||||
border:0;
 | 
					border:0;
 | 
				
			||||||
padding:0;
 | 
					padding:0;
 | 
				
			||||||
 | 
					position:relative;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#form_notice legend {
 | 
					#form_notice legend {
 | 
				
			||||||
display:none;
 | 
					display:none;
 | 
				
			||||||
@@ -480,7 +481,13 @@ margin-bottom:7px;
 | 
				
			|||||||
margin-left:18px;
 | 
					margin-left:18px;
 | 
				
			||||||
float:left;
 | 
					float:left;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					#form_notice .error {
 | 
				
			||||||
 | 
					float:left;
 | 
				
			||||||
 | 
					clear:both;
 | 
				
			||||||
 | 
					width:96.9%;
 | 
				
			||||||
 | 
					margin-bottom:0;
 | 
				
			||||||
 | 
					line-height:1.618;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* entity_profile */
 | 
					/* entity_profile */
 | 
				
			||||||
.entity_profile {
 | 
					.entity_profile {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user