return;
}
$type = $confirm->address_type;
- if (!in_array($type, array('email', 'jabber', 'sms'))) {
- // TRANS: Server error for an unknow address type, which can be 'email', 'jabber', or 'sms'.
- $this->serverError(sprintf(_('Unrecognized address type %s.'), $type));
+ $transports = array();
+ Event::handle('GetImTransports', array(&$transports));
+ if (!in_array($type, array('email', 'sms')) && !in_array($type, array_keys($transports))) {
++ // TRANS: Server error for an unknown address type, which can be 'email', 'sms', or the name of an IM network (such as 'xmpp' or 'aim')
+ $this->serverError(sprintf(_('Unrecognized address type %s'), $type));
return;
}
- if ($cur->$type == $confirm->address) {
- // TRANS: Client error for an already confirmed email/jabbel/sms address.
- $this->clientError(_('That address has already been confirmed.'));
- return;
- }
-
+ $this->address = $confirm->address;
$cur->query('BEGIN');
+ if (in_array($type, array('email', 'sms')))
+ {
+ if ($cur->$type == $confirm->address) {
+ $this->clientError(_('That address has already been confirmed.'));
+ return;
+ }
+
+ $orig_user = clone($cur);
+
+ $cur->$type = $confirm->address;
+
+ if ($type == 'sms') {
+ $cur->carrier = ($confirm->address_extra)+0;
+ $carrier = Sms_carrier::staticGet($cur->carrier);
+ $cur->smsemail = $carrier->toEmailAddress($cur->sms);
+ }
+
+ $result = $cur->updateKeys($orig_user);
+
+ if (!$result) {
+ common_log_db_error($cur, 'UPDATE', __FILE__);
+ $this->serverError(_('Couldn\'t update user.'));
+ return;
+ }
+
+ if ($type == 'email') {
+ $cur->emailChanged();
+ }
+
+ } else {
+
+ $user_im_prefs = new User_im_prefs();
+ $user_im_prefs->transport = $confirm->address_type;
+ $user_im_prefs->user_id = $cur->id;
+ if ($user_im_prefs->find() && $user_im_prefs->fetch()) {
+ if($user_im_prefs->screenname == $confirm->address){
+ $this->clientError(_('That address has already been confirmed.'));
+ return;
+ }
+ $user_im_prefs->screenname = $confirm->address;
+ $result = $user_im_prefs->update();
+
+ if (!$result) {
+ common_log_db_error($user_im_prefs, 'UPDATE', __FILE__);
+ $this->serverError(_('Couldn\'t update user im preferences.'));
+ return;
+ }
+ }else{
+ $user_im_prefs = new User_im_prefs();
+ $user_im_prefs->screenname = $confirm->address;
+ $user_im_prefs->transport = $confirm->address_type;
+ $user_im_prefs->user_id = $cur->id;
+ $result = $user_im_prefs->insert();
+
+ if (!$result) {
+ common_log_db_error($user_im_prefs, 'INSERT', __FILE__);
+ $this->serverError(_('Couldn\'t insert user im preferences.'));
+ return;
+ }
+ }
- $orig_user = clone($cur);
-
- $cur->$type = $confirm->address;
-
- if ($type == 'sms') {
- $cur->carrier = ($confirm->address_extra)+0;
- $carrier = Sms_carrier::staticGet($cur->carrier);
- $cur->smsemail = $carrier->toEmailAddress($cur->sms);
- }
-
- $result = $cur->updateKeys($orig_user);
-
- if (!$result) {
- common_log_db_error($cur, 'UPDATE', __FILE__);
- $this->serverError(_('Couldn\'t update user.'));
- return;
- }
-
- if ($type == 'email') {
- $cur->emailChanged();
}
$result = $confirm->delete();
function getInstructions()
{
+ // TRANS: Instant messaging settings page instructions.
+ // TRANS: [instant messages] is link text, "(%%doc.im%%)" is the link.
+ // TRANS: the order and formatting of link text and link should remain unchanged.
return _('You can send and receive notices through '.
- 'Jabber/GTalk [instant messages](%%doc.im%%). '.
- 'Configure your address and settings below.');
+ 'instant messaging [instant messages](%%doc.im%%). '.
+ 'Configure your addresses and settings below.');
}
/**
function showContent()
{
- if (!common_config('xmpp', 'enabled')) {
+ $transports = array();
+ Event::handle('GetImTransports', array(&$transports));
+ if (! $transports) {
$this->element('div', array('class' => 'error'),
- // TRANS: Message given in the IM settings if XMPP is not enabled on the site.
++ // TRANS: Message given in the IM settings if IM is not enabled on the site.
_('IM is not available.'));
return;
}
$user = common_current_user();
- $this->elementStart('form', array('method' => 'post',
- 'id' => 'form_settings_im',
- 'class' => 'form_settings',
- 'action' =>
- common_local_url('imsettings')));
- $this->elementStart('fieldset', array('id' => 'settings_im_address'));
- // TRANS: Form legend for IM settings form.
- $this->element('legend', null, _('IM address'));
- $this->hidden('token', common_session_token());
-
- if ($user->jabber) {
- $this->element('p', 'form_confirmed', $user->jabber);
- // TRANS: Form note in IM settings form.
- $this->element('p', 'form_note',
- _('Current confirmed Jabber/GTalk address.'));
- $this->hidden('jabber', $user->jabber);
- // TRANS: Button label to remove a confirmed IM address.
- $this->submit('remove', _m('BUTTON','Remove'));
- } else {
- $confirm = $this->getConfirmation();
- if ($confirm) {
- $this->element('p', 'form_unconfirmed', $confirm->address);
+
+ $user_im_prefs_by_transport = array();
+
+ foreach($transports as $transport=>$transport_info)
+ {
+ $this->elementStart('form', array('method' => 'post',
+ 'id' => 'form_settings_im',
+ 'class' => 'form_settings',
+ 'action' =>
+ common_local_url('imsettings')));
+ $this->elementStart('fieldset', array('id' => 'settings_im_address'));
++ // TRANS: Form legend for IM settings form.
+ $this->element('legend', null, $transport_info['display']);
+ $this->hidden('token', common_session_token());
+ $this->hidden('transport', $transport);
+
+ if ($user_im_prefs = User_im_prefs::pkeyGet( array('transport' => $transport, 'user_id' => $user->id) )) {
+ $user_im_prefs_by_transport[$transport] = $user_im_prefs;
+ $this->element('p', 'form_confirmed', $user_im_prefs->screenname);
++ // TRANS: Form note in IM settings form.
$this->element('p', 'form_note',
- // TRANS: Form note in IM settings form.
- // TRANS: %s is the IM address set for the site.
- sprintf(_('Awaiting confirmation on this address. '.
- 'Check your Jabber/GTalk account for a '.
- 'message with further instructions. '.
- '(Did you add %s to your buddy list?)'),
- jabber_daemon_address()));
- $this->hidden('jabber', $confirm->address);
- // TRANS: Button label to cancel an IM address confirmation procedure.
- $this->submit('cancel', _m('BUTTON','Cancel'));
+ sprintf(_('Current confirmed %s address.'),$transport_info['display']));
+ $this->hidden('screenname', $user_im_prefs->screenname);
- $this->submit('remove', _('Remove'));
++ // TRANS: Button label to remove a confirmed IM address.
++ $this->submit('remove', _m('BUTTON','Remove'));
} else {
- $this->elementStart('ul', 'form_data');
- $this->elementStart('li');
- // TRANS: Field label for IM address input in IM settings form.
- $this->input('jabber', _('IM address'),
- ($this->arg('jabber')) ? $this->arg('jabber') : null,
- // TRANS: IM address input field instructions in IM settings form.
- // TRANS: %s is the IM address set for the site.
- sprintf(_('Jabber or GTalk address, '.
- 'like "UserName@example.org". '.
- 'First, make sure to add %s to your '.
- 'buddy list in your IM client or on GTalk.'),
- jabber_daemon_address()));
- $this->elementEnd('li');
- $this->elementEnd('ul');
- // TRANS: Button label for adding an IM address in IM settings form.
- $this->submit('add', _m('BUTTON','Add'));
+ $confirm = $this->getConfirmation($transport);
+ if ($confirm) {
+ $this->element('p', 'form_unconfirmed', $confirm->address);
++ // TRANS: Form note in IM settings form.
+ $this->element('p', 'form_note',
++ // TRANS: Form note in IM settings form.
++ // TRANS: %s is the IM address set for the site.
+ sprintf(_('Awaiting confirmation on this address. '.
+ 'Check your %s account for a '.
- 'message with further instructions.'),
- $transport_info['display']));
++ 'message with further instructions. '.
++ '(Did you add %s to your buddy list?)'),
++ $transport_info['display'],
++ $transport_info['daemon_screenname'],
++ jabber_daemon_address()));
+ $this->hidden('screenname', $confirm->address);
- $this->submit('cancel', _('Cancel'));
++ // TRANS: Button label to cancel an IM address confirmation procedure.
++ $this->submit('cancel', _m('BUTTON','Cancel'));
+ } else {
+ $this->elementStart('ul', 'form_data');
+ $this->elementStart('li');
+ $this->input('screenname', _('IM address'),
+ ($this->arg('screenname')) ? $this->arg('screenname') : null,
+ sprintf(_('%s screenname.'),
+ $transport_info['display']));
+ $this->elementEnd('li');
+ $this->elementEnd('ul');
- $this->submit('add', _('Add'));
++ // TRANS: Button label for adding an IM address in IM settings form.
++ $this->submit('add', _m('BUTTON','Add'));
+ }
}
- $this->element('th', null, _('Preferences'));
+ $this->elementEnd('fieldset');
+ $this->elementEnd('form');
+ }
+
+ if($user_im_prefs_by_transport)
+ {
+ $this->elementStart('form', array('method' => 'post',
+ 'id' => 'form_settings_im',
+ 'class' => 'form_settings',
+ 'action' =>
+ common_local_url('imsettings')));
+ $this->elementStart('fieldset', array('id' => 'settings_im_preferences'));
+ $this->element('legend', null, _('Preferences'));
+ $this->hidden('token', common_session_token());
+ $this->elementStart('table');
+ $this->elementStart('tr');
- $this->submit('save', _('Save'));
++ // TRANS: Header for IM preferences form.
++ $this->element('th', null, _('IM Preferences'));
+ foreach($user_im_prefs_by_transport as $transport=>$user_im_prefs)
+ {
+ $this->element('th', null, $transports[$transport]['display']);
+ }
+ $this->elementEnd('tr');
+ $preferences = array(
++ // TRANS: Checkbox label in IM preferences form.
+ array('name'=>'notify', 'description'=>_('Send me notices')),
++ // TRANS: Checkbox label in IM preferences form.
+ array('name'=>'updatefrompresence', 'description'=>_('Post a notice when my status changes.')),
++ // TRANS: Checkbox label in IM preferences form.
+ array('name'=>'replies', 'description'=>_('Send me replies '.
+ 'from people I\'m not subscribed to.')),
++ // TRANS: Checkbox label in IM preferences form.
+ array('name'=>'microid', 'description'=>_('Publish a MicroID'))
+ );
+ foreach($preferences as $preference)
+ {
+ $this->elementStart('tr');
+ foreach($user_im_prefs_by_transport as $transport=>$user_im_prefs)
+ {
+ $preference_name = $preference['name'];
+ $this->elementStart('td');
+ $this->checkbox($transport . '_' . $preference['name'],
+ $preference['description'],
+ $user_im_prefs->$preference_name);
+ $this->elementEnd('td');
+ }
+ $this->elementEnd('tr');
+ }
+ $this->elementEnd('table');
++ // TRANS: Button label to save IM preferences.
++ $this->submit('save', _m('BUTTON','Save'));
+ $this->elementEnd('fieldset');
+ $this->elementEnd('form');
}
- $this->elementEnd('fieldset');
-
- $this->elementStart('fieldset', array('id' => 'settings_im_preferences'));
- // TRANS: Form legend for IM preferences form.
- $this->element('legend', null, _('IM preferences'));
- $this->elementStart('ul', 'form_data');
- $this->elementStart('li');
- $this->checkbox('jabbernotify',
- // TRANS: Checkbox label in IM preferences form.
- _('Send me notices through Jabber/GTalk.'),
- $user->jabbernotify);
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->checkbox('updatefrompresence',
- // TRANS: Checkbox label in IM preferences form.
- _('Post a notice when my Jabber/GTalk status changes.'),
- $user->updatefrompresence);
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->checkbox('jabberreplies',
- // TRANS: Checkbox label in IM preferences form.
- _('Send me replies through Jabber/GTalk '.
- 'from people I\'m not subscribed to.'),
- $user->jabberreplies);
- $this->elementEnd('li');
- $this->elementStart('li');
- $this->checkbox('jabbermicroid',
- // TRANS: Checkbox label in IM preferences form.
- _('Publish a MicroID for my Jabber/GTalk address.'),
- $user->jabbermicroid);
- $this->elementEnd('li');
- $this->elementEnd('ul');
- // TRANS: Button label to save IM preferences.
- $this->submit('save', _m('BUTTON','Save'));
- $this->elementEnd('fieldset');
- $this->elementEnd('form');
}
/**
function savePreferences()
{
- $jabbernotify = $this->boolean('jabbernotify');
- $updatefrompresence = $this->boolean('updatefrompresence');
- $jabberreplies = $this->boolean('jabberreplies');
- $jabbermicroid = $this->boolean('jabbermicroid');
-
$user = common_current_user();
- assert(!is_null($user)); // should already be checked
-
- $user->query('BEGIN');
-
- $original = clone($user);
-
- $user->jabbernotify = $jabbernotify;
- $user->updatefrompresence = $updatefrompresence;
- $user->jabberreplies = $jabberreplies;
- $user->jabbermicroid = $jabbermicroid;
-
- $result = $user->update($original);
-
- if ($result === false) {
- common_log_db_error($user, 'UPDATE', __FILE__);
- // TRANS: Server error thrown on database error updating IM preferences.
- $this->serverError(_('Couldn\'t update user.'));
- return;
+ $user_im_prefs = new User_im_prefs();
+ $user_im_prefs->user_id = $user->id;
+ if($user_im_prefs->find() && $user_im_prefs->fetch())
+ {
+ $preferences = array('notify', 'updatefrompresence', 'replies', 'microid');
+ $user_im_prefs->query('BEGIN');
+ do
+ {
+ $original = clone($user_im_prefs);
+ foreach($preferences as $preference)
+ {
+ $user_im_prefs->$preference = $this->boolean($user_im_prefs->transport . '_' . $preference);
+ }
+ $result = $user_im_prefs->update($original);
+
+ if ($result === false) {
+ common_log_db_error($user, 'UPDATE', __FILE__);
++ // TRANS: Server error thrown on database error updating IM preferences.
+ $this->serverError(_('Couldn\'t update IM preferences.'));
+ return;
+ }
+ }while($user_im_prefs->fetch());
+ $user_im_prefs->query('COMMIT');
}
-
- $user->query('COMMIT');
-
+ // TRANS: Confirmation message for successful IM preferences save.
$this->showForm(_('Preferences saved.'), true);
}
// Some validation
- if (!$jabber) {
+ if (!$screenname) {
+ // TRANS: Message given saving IM address without having provided one.
- $this->showForm(_('No Jabber ID.'));
+ $this->showForm(_('No screenname.'));
return;
}
- $jabber = jabber_normalize_jid($jabber);
+ if (!$transport) {
+ $this->showForm(_('No transport.'));
+ return;
+ }
- if (!$jabber) {
+ Event::handle('NormalizeImScreenname', array($transport, &$screenname));
+
+ if (!$screenname) {
+ // TRANS: Message given saving IM address that cannot be normalised.
- $this->showForm(_('Cannot normalize that Jabber ID'));
+ $this->showForm(_('Cannot normalize that screenname'));
return;
}
- if (!jabber_valid_base_jid($jabber, common_config('email', 'domain_check'))) {
+ $valid = false;
+ Event::handle('ValidateImScreenname', array($transport, $screenname, &$valid));
+ if (!$valid) {
+ // TRANS: Message given saving IM address that not valid.
- $this->showForm(_('Not a valid Jabber ID'));
- return;
- } else if ($user->jabber == $jabber) {
- // TRANS: Message given saving IM address that is already set.
- $this->showForm(_('That is already your Jabber ID.'));
+ $this->showForm(_('Not a valid screenname'));
return;
- } else if ($this->jabberExists($jabber)) {
+ } else if ($this->screennameExists($transport, $screenname)) {
+ // TRANS: Message given saving IM address that is already set for another user.
- $this->showForm(_('Jabber ID already belongs to another user.'));
+ $this->showForm(_('Screenname already belongs to another user.'));
return;
}
return;
}
- jabber_confirm_address($confirm->code,
- $user->nickname,
- $jabber);
+ Event::handle('SendImConfirmationCode', array($transport, $screenname, $confirm->code, $user));
- // TRANS: %s is the IM address set for the site.
- $msg = sprintf(_('A confirmation code was sent '.
- 'to the IM address you added. '.
- 'You must approve %s for '.
- 'sending messages to you.'),
- jabber_daemon_address());
+ // TRANS: Message given saving valid IM address that is to be confirmed.
+ $msg = _('A confirmation code was sent '.
+ 'to the IM address you added.');
$this->showForm($msg, true);
}
function cancelConfirmation()
{
- $jabber = $this->arg('jabber');
+ $screenname = $this->trimmed('screenname');
+ $transport = $this->trimmed('transport');
- $confirm = $this->getConfirmation();
+ $confirm = $this->getConfirmation($transport);
if (!$confirm) {
+ // TRANS: Message given canceling IM address confirmation that is not pending.
$this->showForm(_('No pending confirmation to cancel.'));
return;
}
- if ($confirm->address != $jabber) {
+ if ($confirm->address != $screenname) {
+ // TRANS: Message given canceling IM address confirmation for the wrong IM address.
$this->showForm(_('That is the wrong IM address.'));
return;
}
if (!$result) {
common_log_db_error($confirm, 'DELETE', __FILE__);
- $this->serverError(_('Couldn\'t delete IM confirmation.'));
+ // TRANS: Server error thrown on database error canceling IM address confirmation.
+ $this->serverError(_('Couldn\'t delete confirmation.'));
return;
}
// Maybe an old tab open...?
- if ($user->jabber != $jabber) {
+ $user_im_prefs = new User_im_prefs();
+ $user_im_prefs->user_id = $user->id;
+ if(! ($user_im_prefs->find() && $user_im_prefs->fetch())) {
+ // TRANS: Message given trying to remove an IM address that is not
+ // TRANS: registered for the active user.
- $this->showForm(_('That is not your Jabber ID.'));
+ $this->showForm(_('That is not your screenname.'));
return;
}
if (!$result) {
common_log_db_error($user, 'UPDATE', __FILE__);
+ // TRANS: Server error thrown on database error removing a registered IM address.
+ $this->serverError(_('Couldn\'t update user im prefs.'));
+ $this->serverError(_('Couldn\'t update user.'));
return;
}
- $user->query('COMMIT');
// XXX: unsubscribe to the old address
--- /dev/null
- $transports[$this->transport] = array('display' => $this->getDisplayName());
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Superclass for plugins that do instant messaging
+ *
+ * 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 StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+/**
+ * Superclass for plugins that do authentication
+ *
+ * Implementations will likely want to override onStartIoManagerClasses() so that their
+ * IO manager is used
+ *
+ * @category Plugin
+ * @package StatusNet
+ * @author Craig Andrews <candrews@integralblue.com>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+abstract class ImPlugin extends Plugin
+{
+ //name of this IM transport
+ public $transport = null;
+ //list of screennames that should get all public notices
+ public $public = array();
+
+ /**
+ * normalize a screenname for comparison
+ *
+ * @param string $screenname screenname to normalize
+ *
+ * @return string an equivalent screenname in normalized form
+ */
+ abstract function normalize($screenname);
+
+
+ /**
+ * validate (ensure the validity of) a screenname
+ *
+ * @param string $screenname screenname to validate
+ *
+ * @return boolean
+ */
+ abstract function validate($screenname);
+
+ /**
+ * get the internationalized/translated display name of this IM service
+ *
+ * @return string
+ */
+ abstract function getDisplayName();
+
+ /**
+ * send a single notice to a given screenname
+ * The implementation should put raw data, ready to send, into the outgoing
+ * queue using enqueue_outgoing_raw()
+ *
+ * @param string $screenname screenname to send to
+ * @param Notice $notice notice to send
+ *
+ * @return boolean success value
+ */
+ function send_notice($screenname, $notice)
+ {
+ return $this->send_message($screenname, $this->format_notice($notice));
+ }
+
+ /**
+ * send a message (text) to a given screenname
+ * The implementation should put raw data, ready to send, into the outgoing
+ * queue using enqueue_outgoing_raw()
+ *
+ * @param string $screenname screenname to send to
+ * @param Notice $body text to send
+ *
+ * @return boolean success value
+ */
+ abstract function send_message($screenname, $body);
+
+ /**
+ * receive a raw message
+ * Raw IM data is taken from the incoming queue, and passed to this function.
+ * It should parse the raw message and call handle_incoming()
+ *
+ * @param object $data raw IM data
+ *
+ * @return boolean success value
+ */
+ abstract function receive_raw_message($data);
+
+ /**
+ * get the screenname of the daemon that sends and receives message for this service
+ *
+ * @return string screenname of this plugin
+ */
+ abstract function daemon_screenname();
+
+ /**
+ * get the microid uri of a given screenname
+ *
+ * @param string $screenname screenname
+ *
+ * @return string microid uri
+ */
+ function microiduri($screenname)
+ {
+ return $this->transport . ':' . $screenname;
+ }
+ //========================UTILITY FUNCTIONS USEFUL TO IMPLEMENTATIONS - MISC ========================\
+
+ /**
+ * Put raw message data (ready to send) into the outgoing queue
+ *
+ * @param object $data
+ */
+ function enqueue_outgoing_raw($data)
+ {
+ $qm = QueueManager::get();
+ $qm->enqueue($data, $this->transport . '-out');
+ }
+
+ /**
+ * Put raw message data (received, ready to be processed) into the incoming queue
+ *
+ * @param object $data
+ */
+ function enqueue_incoming_raw($data)
+ {
+ $qm = QueueManager::get();
+ $qm->enqueue($data, $this->transport . '-in');
+ }
+
+ /**
+ * given a screenname, get the corresponding user
+ *
+ * @param string $screenname
+ *
+ * @return User user
+ */
+ function get_user($screenname)
+ {
+ $user_im_prefs = $this->get_user_im_prefs_from_screenname($screenname);
+ if($user_im_prefs){
+ $user = User::staticGet('id', $user_im_prefs->user_id);
+ $user_im_prefs->free();
+ return $user;
+ }else{
+ return false;
+ }
+ }
+
+
+ /**
+ * given a screenname, get the User_im_prefs object for this transport
+ *
+ * @param string $screenname
+ *
+ * @return User_im_prefs user_im_prefs
+ */
+ function get_user_im_prefs_from_screenname($screenname)
+ {
+ if($user_im_prefs = User_im_prefs::pkeyGet( array('transport' => $this->transport, 'screenname' => $screenname) )){
+ return $user_im_prefs;
+ }else{
+ return false;
+ }
+ }
+
+
+ /**
+ * given a User, get their screenname
+ *
+ * @param User $user
+ *
+ * @return string screenname of that user
+ */
+ function get_screenname($user)
+ {
+ $user_im_prefs = $this->get_user_im_prefs_from_user($user);
+ if($user_im_prefs){
+ return $user_im_prefs->screenname;
+ }else{
+ return false;
+ }
+ }
+
+
+ /**
+ * given a User, get their User_im_prefs
+ *
+ * @param User $user
+ *
+ * @return User_im_prefs user_im_prefs of that user
+ */
+ function get_user_im_prefs_from_user($user)
+ {
+ if($user_im_prefs = User_im_prefs::pkeyGet( array('transport' => $this->transport, 'user_id' => $user->id) )){
+ return $user_im_prefs;
+ }else{
+ return false;
+ }
+ }
+ //========================UTILITY FUNCTIONS USEFUL TO IMPLEMENTATIONS - SENDING ========================\
+ /**
+ * Send a message to a given screenname from the site
+ *
+ * @param string $screenname screenname to send the message to
+ * @param string $msg message contents to send
+ *
+ * @param boolean success
+ */
+ protected function send_from_site($screenname, $msg)
+ {
+ $text = '['.common_config('site', 'name') . '] ' . $msg;
+ $this->send_message($screenname, $text);
+ }
+
+ /**
+ * send a confirmation code to a user
+ *
+ * @param string $screenname screenname sending to
+ * @param string $code the confirmation code
+ * @param User $user user sending to
+ *
+ * @return boolean success value
+ */
+ function send_confirmation_code($screenname, $code, $user)
+ {
+ $body = sprintf(_('User "%s" on %s has said that your %s screenname belongs to them. ' .
+ 'If that\'s true, you can confirm by clicking on this URL: ' .
+ '%s' .
+ ' . (If you cannot click it, copy-and-paste it into the ' .
+ 'address bar of your browser). If that user isn\'t you, ' .
+ 'or if you didn\'t request this confirmation, just ignore this message.'),
+ $user->nickname, common_config('site', 'name'), $this->getDisplayName(), common_local_url('confirmaddress', array('code' => $code)));
+
+ return $this->send_message($screenname, $body);
+ }
+
+ /**
+ * send a notice to all public listeners
+ *
+ * For notices that are generated on the local system (by users), we can optionally
+ * forward them to remote listeners by XMPP.
+ *
+ * @param Notice $notice notice to broadcast
+ *
+ * @return boolean success flag
+ */
+
+ function public_notice($notice)
+ {
+ // Now, users who want everything
+
+ // FIXME PRIV don't send out private messages here
+ // XXX: should we send out non-local messages if public,localonly
+ // = false? I think not
+
+ foreach ($this->public as $screenname) {
+ common_log(LOG_INFO,
+ 'Sending notice ' . $notice->id .
+ ' to public listener ' . $screenname,
+ __FILE__);
+ $this->send_notice($screenname, $notice);
+ }
+
+ return true;
+ }
+
+ /**
+ * broadcast a notice to all subscribers and reply recipients
+ *
+ * This function will send a notice to all subscribers on the local server
+ * who have IM addresses, and have IM notification enabled, and
+ * have this subscription enabled for IM. It also sends the notice to
+ * all recipients of @-replies who have IM addresses and IM notification
+ * enabled. This is really the heart of IM distribution in StatusNet.
+ *
+ * @param Notice $notice The notice to broadcast
+ *
+ * @return boolean success flag
+ */
+
+ function broadcast_notice($notice)
+ {
+
+ $ni = $notice->whoGets();
+
+ foreach ($ni as $user_id => $reason) {
+ $user = User::staticGet($user_id);
+ if (empty($user)) {
+ // either not a local user, or just not found
+ continue;
+ }
+ $user_im_prefs = $this->get_user_im_prefs_from_user($user);
+ if(!$user_im_prefs || !$user_im_prefs->notify){
+ continue;
+ }
+
+ switch ($reason) {
+ case NOTICE_INBOX_SOURCE_REPLY:
+ if (!$user_im_prefs->replies) {
+ continue 2;
+ }
+ break;
+ case NOTICE_INBOX_SOURCE_SUB:
+ $sub = Subscription::pkeyGet(array('subscriber' => $user->id,
+ 'subscribed' => $notice->profile_id));
+ if (empty($sub) || !$sub->jabber) {
+ continue 2;
+ }
+ break;
+ case NOTICE_INBOX_SOURCE_GROUP:
+ break;
+ default:
+ throw new Exception(sprintf(_("Unknown inbox source %d."), $reason));
+ }
+
+ common_log(LOG_INFO,
+ 'Sending notice ' . $notice->id . ' to ' . $user_im_prefs->screenname,
+ __FILE__);
+ $this->send_notice($user_im_prefs->screenname, $notice);
+ $user_im_prefs->free();
+ }
+
+ return true;
+ }
+
+ /**
+ * makes a plain-text formatted version of a notice, suitable for IM distribution
+ *
+ * @param Notice $notice notice being sent
+ *
+ * @return string plain-text version of the notice, with user nickname prefixed
+ */
+
+ function format_notice($notice)
+ {
+ $profile = $notice->getProfile();
+ return $profile->nickname . ': ' . $notice->content . ' [' . $notice->id . ']';
+ }
+ //========================UTILITY FUNCTIONS USEFUL TO IMPLEMENTATIONS - RECEIVING ========================\
+
+ /**
+ * Attempt to handle a message as a command
+ * @param User $user user the message is from
+ * @param string $body message text
+ * @return boolean true if the message was a command and was executed, false if it was not a command
+ */
+ protected function handle_command($user, $body)
+ {
+ $inter = new CommandInterpreter();
+ $cmd = $inter->handle_command($user, $body);
+ if ($cmd) {
+ $chan = new IMChannel($this);
+ $cmd->execute($chan);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Is some text an autoreply message?
+ * @param string $txt message text
+ * @return boolean true if autoreply
+ */
+ protected function is_autoreply($txt)
+ {
+ if (preg_match('/[\[\(]?[Aa]uto[-\s]?[Rr]e(ply|sponse)[\]\)]/', $txt)) {
+ return true;
+ } else if (preg_match('/^System: Message wasn\'t delivered. Offline storage size was exceeded.$/', $txt)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Is some text an OTR message?
+ * @param string $txt message text
+ * @return boolean true if OTR
+ */
+ protected function is_otr($txt)
+ {
+ if (preg_match('/^\?OTR/', $txt)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Helper for handling incoming messages
+ * Your incoming message handler will probably want to call this function
+ *
+ * @param string $from screenname the message was sent from
+ * @param string $message message contents
+ *
+ * @param boolean success
+ */
+ protected function handle_incoming($from, $notice_text)
+ {
+ $user = $this->get_user($from);
+ // For common_current_user to work
+ global $_cur;
+ $_cur = $user;
+
+ if (!$user) {
+ $this->send_from_site($from, 'Unknown user; go to ' .
+ common_local_url('imsettings') .
+ ' to add your address to your account');
+ common_log(LOG_WARNING, 'Message from unknown user ' . $from);
+ return;
+ }
+ if ($this->handle_command($user, $notice_text)) {
+ common_log(LOG_INFO, "Command message by $from handled.");
+ return;
+ } else if ($this->is_autoreply($notice_text)) {
+ common_log(LOG_INFO, 'Ignoring auto reply from ' . $from);
+ return;
+ } else if ($this->is_otr($notice_text)) {
+ common_log(LOG_INFO, 'Ignoring OTR from ' . $from);
+ return;
+ } else {
+
+ common_log(LOG_INFO, 'Posting a notice from ' . $user->nickname);
+
+ $this->add_notice($from, $user, $notice_text);
+ }
+
+ $user->free();
+ unset($user);
+ unset($_cur);
+ unset($message);
+ }
+
+ /**
+ * Helper for handling incoming messages
+ * Your incoming message handler will probably want to call this function
+ *
+ * @param string $from screenname the message was sent from
+ * @param string $message message contents
+ *
+ * @param boolean success
+ */
+ protected function add_notice($screenname, $user, $body)
+ {
+ $body = trim(strip_tags($body));
+ $content_shortened = common_shorten_links($body);
+ if (Notice::contentTooLong($content_shortened)) {
+ $this->send_from_site($screenname, sprintf(_('Message too long - maximum is %1$d characters, you sent %2$d.'),
+ Notice::maxContent(),
+ mb_strlen($content_shortened)));
+ return;
+ }
+
+ try {
+ $notice = Notice::saveNew($user->id, $content_shortened, $this->transport);
+ } catch (Exception $e) {
+ common_log(LOG_ERR, $e->getMessage());
+ $this->send_from_site($from, $e->getMessage());
+ return;
+ }
+
+ common_broadcast_notice($notice);
+ common_log(LOG_INFO,
+ 'Added notice ' . $notice->id . ' from user ' . $user->nickname);
+ $notice->free();
+ unset($notice);
+ }
+
+ //========================EVENT HANDLERS========================\
+
+ /**
+ * Register notice queue handler
+ *
+ * @param QueueManager $manager
+ *
+ * @return boolean hook return
+ */
+ function onEndInitializeQueueManager($manager)
+ {
+ $manager->connect($this->transport . '-in', new ImReceiverQueueHandler($this), 'im');
+ $manager->connect($this->transport, new ImQueueHandler($this));
+ $manager->connect($this->transport . '-out', new ImSenderQueueHandler($this), 'im');
+ return true;
+ }
+
+ function onStartImDaemonIoManagers(&$classes)
+ {
+ //$classes[] = new ImManager($this); // handles sending/receiving/pings/reconnects
+ return true;
+ }
+
+ function onStartEnqueueNotice($notice, &$transports)
+ {
+ $profile = Profile::staticGet($notice->profile_id);
+
+ if (!$profile) {
+ common_log(LOG_WARNING, 'Refusing to broadcast notice with ' .
+ 'unknown profile ' . common_log_objstring($notice),
+ __FILE__);
+ }else{
+ $transports[] = $this->transport;
+ }
+
+ return true;
+ }
+
+ function onEndShowHeadElements($action)
+ {
+ $aname = $action->trimmed('action');
+
+ if ($aname == 'shownotice') {
+
+ $user_im_prefs = new User_im_prefs();
+ $user_im_prefs->user_id = $action->profile->id;
+ $user_im_prefs->transport = $this->transport;
+
+ if ($user_im_prefs->find() && $user_im_prefs->fetch() && $user_im_prefs->microid && $action->notice->uri) {
+ $id = new Microid($this->microiduri($user_im_prefs->screenname),
+ $action->notice->uri);
+ $action->element('meta', array('name' => 'microid',
+ 'content' => $id->toString()));
+ }
+
+ } else if ($aname == 'showstream') {
+
+ $user_im_prefs = new User_im_prefs();
+ $user_im_prefs->user_id = $action->user->id;
+ $user_im_prefs->transport = $this->transport;
+
+ if ($user_im_prefs->find() && $user_im_prefs->fetch() && $user_im_prefs->microid && $action->profile->profileurl) {
+ $id = new Microid($this->microiduri($user_im_prefs->screenname),
+ $action->selfUrl());
+ $action->element('meta', array('name' => 'microid',
+ 'content' => $id->toString()));
+ }
+ }
+ }
+
+ function onNormalizeImScreenname($transport, &$screenname)
+ {
+ if($transport == $this->transport)
+ {
+ $screenname = $this->normalize($screenname);
+ return false;
+ }
+ }
+
+ function onValidateImScreenname($transport, $screenname, &$valid)
+ {
+ if($transport == $this->transport)
+ {
+ $valid = $this->validate($screenname);
+ return false;
+ }
+ }
+
+ function onGetImTransports(&$transports)
+ {
++ $transports[$this->transport] = array(
++ 'display' => $this->getDisplayName(),
++ 'daemon_screenname' => $this->daemon_screenname());
+ }
+
+ function onSendImConfirmationCode($transport, $screenname, $code, $user)
+ {
+ if($transport == $this->transport)
+ {
+ $this->send_confirmation_code($screenname, $code, $user);
+ return false;
+ }
+ }
+
+ function onUserDeleteRelated($user, &$tables)
+ {
+ $tables[] = 'User_im_prefs';
+ return true;
+ }
+
+ function initialize()
+ {
+ if(is_null($this->transport)){
+ throw new Exception('transport cannot be null');
+ }
+ }
+}