3 * StatusNet - the distributed open-source microblogging tool
4 * Copyright (C) 2009, StatusNet, Inc.
6 * Send and receive notices using the XMPP network
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU Affero General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Affero General Public License for more details.
20 * You should have received a copy of the GNU Affero General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 * @author Evan Prodromou <evan@status.net>
26 * @copyright 2009 StatusNet, Inc.
27 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
28 * @link http://status.net/
31 if (!defined('STATUSNET')) {
32 // This check helps protect against security problems;
33 // your code file can't be executed directly from the web.
37 set_include_path(get_include_path() . PATH_SEPARATOR . INSTALLDIR . '/extlib/XMPPHP');
44 * @author Evan Prodromou <evan@status.net>
45 * @copyright 2009 StatusNet, Inc.
46 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
47 * @link http://status.net/
50 class XmppPlugin extends ImPlugin
52 public $server = null;
54 public $user = 'update';
55 public $resource = null;
56 public $encryption = true;
57 public $password = null;
58 public $host = null; // only set if != server
59 public $debug = false; // print extra debug info
61 public $transport = 'xmpp';
65 function getDisplayName(){
66 return _m('XMPP/Jabber/GTalk');
69 function normalize($screenname)
71 if (preg_match("/(?:([^\@]+)\@)?([^\/]+)(?:\/(.*))?$/", $screenname, $matches)) {
73 $server = $matches[2];
74 return strtolower($node.'@'.$server);
80 function daemon_screenname()
82 $ret = $this->user . '@' . $this->server;
85 return $ret . '/' . $this->resource;
91 function validate($screenname)
93 // Cheap but effective
94 return Validate::email($screenname);
98 * Load related modules when needed
100 * @param string $cls Name of the class to be loaded
102 * @return boolean hook value; true means continue processing, false means stop.
105 function onAutoload($cls)
107 $dir = dirname(__FILE__);
112 require_once 'XMPP.php';
116 require_once $dir . '/'.$cls.'.php';
119 require_once $dir . '/'.strtolower($cls).'.php';
126 function onStartImDaemonIoManagers(&$classes)
128 parent::onStartImDaemonIoManagers(&$classes);
129 $classes[] = new XmppManager($this); // handles pings/reconnects
133 function microiduri($screenname)
135 return 'xmpp:' . $screenname;
138 function send_message($screenname, $body)
140 $this->fake_xmpp->message($screenname, $body, 'chat');
141 $this->enqueue_outgoing_raw($this->fake_xmpp->would_be_sent);
145 function send_notice($screenname, $notice)
147 $msg = $this->format_notice($notice);
148 $entry = $this->format_entry($notice);
150 $this->fake_xmpp->message($screenname, $msg, 'chat', null, $entry);
151 $this->enqueue_outgoing_raw($this->fake_xmpp->would_be_sent);
156 * extra information for XMPP messages, as defined by Twitter
158 * @param Profile $profile Profile of the sending user
159 * @param Notice $notice Notice being sent
161 * @return string Extra information (Atom, HTML, addresses) in string format
164 function format_entry($notice)
166 $profile = $notice->getProfile();
168 $entry = $notice->asAtomEntry(true, true);
170 $xs = new XMLStringer();
171 $xs->elementStart('html', array('xmlns' => 'http://jabber.org/protocol/xhtml-im'));
172 $xs->elementStart('body', array('xmlns' => 'http://www.w3.org/1999/xhtml'));
173 $xs->element('a', array('href' => $profile->profileurl),
176 if (!empty($notice->rendered)) {
177 $xs->raw($notice->rendered);
179 $xs->raw(common_render_content($notice->content, $notice));
182 $xs->element('a', array(
183 'href'=>common_local_url('conversation',
184 array('id' => $notice->conversation)).'#notice-'.$notice->id
185 ),sprintf(_('[%s]'),$notice->id));
186 $xs->elementEnd('body');
187 $xs->elementEnd('html');
189 $html = $xs->getString();
191 return $html . ' ' . $entry;
194 function receive_raw_message($pl)
196 $from = $this->normalize($pl['from']);
198 if ($pl['type'] != 'chat') {
199 common_log(LOG_WARNING, "Ignoring message of type ".$pl['type']." from $from.");
203 if (mb_strlen($pl['body']) == 0) {
204 common_log(LOG_WARNING, "Ignoring message with empty body from $from.");
208 return $this->handle_incoming($from, $pl['body']);
211 function initialize(){
212 if(!isset($this->server)){
213 throw new Exception("must specify a server");
215 if(!isset($this->port)){
216 throw new Exception("must specify a port");
218 if(!isset($this->user)){
219 throw new Exception("must specify a user");
221 if(!isset($this->password)){
222 throw new Exception("must specify a password");
225 $this->fake_xmpp = new Fake_XMPP($this->host ?
236 XMPPHP_Log::LEVEL_VERBOSE : null
241 function onPluginVersion(&$versions)
243 $versions[] = array('name' => 'XMPP',
244 'version' => STATUSNET_VERSION,
245 'author' => 'Craig Andrews, Evan Prodromou',
246 'homepage' => 'http://status.net/wiki/Plugin:XMPP',
248 _m('The XMPP plugin allows users to send and receive notices over the XMPP/Jabber network.'));