function nextUrl() { if ($this->j < count($this->notices)) { $n = $this->notices[$this->j]; $this->j++; return array(common_local_url('shownotice', array('notice' => $n[0])), common_date_w3dtf($n[1]), 'never', null); } else { return null; } }
function handle_notice($notice) { $profile = Profile::staticGet($notice->profile_id); $this->log(LOG_INFO, "Posting Notice " . $notice->id . " from " . $profile->nickname); if (!$notice->is_local) { $this->log(LOG_INFO, "Skipping remote notice"); return "skipped"; } # # Build an Atom message from the notice # $noticeurl = common_local_url('shownotice', array('notice' => $notice->id)); $msg = $profile->nickname . ': ' . $notice->content; $atom = "<entry xmlns='http://www.w3.org/2005/Atom'>\n"; $atom .= "<apisource>" . common_config('enjit', 'source') . "</apisource>\n"; $atom .= "<source>\n"; $atom .= "<title>" . $profile->nickname . " - " . common_config('site', 'name') . "</title>\n"; $atom .= "<link href='" . $profile->profileurl . "'/>\n"; $atom .= "<link rel='self' type='application/rss+xml' href='" . common_local_url('userrss', array('nickname' => $profile->nickname)) . "'/>\n"; $atom .= "<author><name>" . $profile->nickname . "</name></author>\n"; $atom .= "<icon>" . $profile->avatarUrl(AVATAR_PROFILE_SIZE) . "</icon>\n"; $atom .= "</source>\n"; $atom .= "<title>" . htmlspecialchars($msg) . "</title>\n"; $atom .= "<summary>" . htmlspecialchars($msg) . "</summary>\n"; $atom .= "<link rel='alternate' href='" . $noticeurl . "' />\n"; $atom .= "<id>" . $notice->uri . "</id>\n"; $atom .= "<published>" . common_date_w3dtf($notice->created) . "</published>\n"; $atom .= "<updated>" . common_date_w3dtf($notice->modified) . "</updated>\n"; $atom .= "</entry>\n"; $url = common_config('enjit', 'apiurl') . "/submit/" . common_config('enjit', 'apikey'); $data = "msg={$atom}"; # # POST the message to $config['enjit']['apiurl'] # $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); # SSL and Debugging options # # curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); # curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); # curl_setopt($ch, CURLOPT_VERBOSE, 1); $result = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); $this->log(LOG_INFO, "Response Code: {$code}"); curl_close($ch); return $code; }
function handle($notice) { $profile = Profile::staticGet($notice->profile_id); $this->log(LOG_INFO, "Posting Notice " . $notice->id . " from " . $profile->nickname); if (!$notice->is_local) { $this->log(LOG_INFO, "Skipping remote notice"); return "skipped"; } # # Build an Atom message from the notice # $noticeurl = common_local_url('shownotice', array('notice' => $notice->id)); $msg = $profile->nickname . ': ' . $notice->content; $atom = "<entry xmlns='http://www.w3.org/2005/Atom'>\n"; $atom .= "<apisource>" . common_config('enjit', 'source') . "</apisource>\n"; $atom .= "<source>\n"; $atom .= "<title>" . $profile->nickname . " - " . common_config('site', 'name') . "</title>\n"; $atom .= "<link href='" . $profile->profileurl . "'/>\n"; $atom .= "<link rel='self' type='application/rss+xml' href='" . common_local_url('userrss', array('nickname' => $profile->nickname)) . "'/>\n"; $atom .= "<author><name>" . $profile->nickname . "</name></author>\n"; $atom .= "<icon>" . $profile->avatarUrl(AVATAR_PROFILE_SIZE) . "</icon>\n"; $atom .= "</source>\n"; $atom .= "<title>" . htmlspecialchars($msg) . "</title>\n"; $atom .= "<summary>" . htmlspecialchars($msg) . "</summary>\n"; $atom .= "<link rel='alternate' href='" . $noticeurl . "' />\n"; $atom .= "<id>" . $notice->uri . "</id>\n"; $atom .= "<published>" . common_date_w3dtf($notice->created) . "</published>\n"; $atom .= "<updated>" . common_date_w3dtf($notice->modified) . "</updated>\n"; $atom .= "</entry>\n"; $url = common_config('enjit', 'apiurl') . "/submit/" . common_config('enjit', 'apikey'); $data = array('msg' => $atom); # # POST the message to $config['enjit']['apiurl'] # $request = HTTPClient::start(); $response = $request->post($url, null, $data); return $response->isOk(); }
function notices_map() { global $output_paths; $notices = DB_DataObject::factory('notice'); $notices->query('SELECT id, uri, url, modified FROM notice where is_local = 1'); $notice_count = 0; $map_count = 1; while ($notices->fetch()) { // Maximum 50,000 URLs per sitemap file. if ($notice_count == 50000) { $notice_count = 0; $map_count++; } // remote notices have an URL if (!$notices->url && $notices->uri) { $notice = array('url' => $notices->uri ? $notices->uri : common_local_url('shownotice', array('notice' => $notices->id)), 'lastmod' => common_date_w3dtf($notices->modified), 'changefreq' => 'never', 'priority' => '1'); $notice_list[$map_count] .= url($notice); $notice_count++; } } // Make full sitemaps from the lists and save them. array_to_map($notice_list, 'notice'); }
/** * Build an Atom entry similar to search.twitter.com's based on * a given notice * * @param Notice $notice the notice to use * * @return void */ function showEntry($notice) { $server = common_config('site', 'server'); $profile = $notice->getProfile(); $nurl = common_local_url('shownotice', array('notice' => $notice->id)); $this->elementStart('entry'); $taguribase = TagURI::base(); $this->element('id', null, "tag:{$taguribase}:{$notice->id}"); $this->element('published', null, common_date_w3dtf($notice->created)); $this->element('link', array('type' => 'text/html', 'rel' => 'alternate', 'href' => $nurl)); $this->element('title', null, common_xml_safe_str(trim($notice->content))); $this->element('content', array('type' => 'html'), $notice->getRendered()); $this->element('updated', null, common_date_w3dtf($notice->created)); $this->element('link', array('type' => 'image/png', 'rel' => 'related', 'href' => $profile->avatarUrl())); // @todo: Here is where we'd put in a link to an atom feed for threads $source = null; $ns = $notice->getSource(); if ($ns instanceof Notice_source) { if (!empty($ns->name) && !empty($ns->url)) { $source = '<a href="' . htmlspecialchars($ns->url) . '" rel="nofollow">' . htmlspecialchars($ns->name) . '</a>'; } else { $source = $ns->code; } } $this->element("twitter:source", null, $source); $this->elementStart('author'); $name = $profile->nickname; if ($profile->fullname) { // @todo Needs proper i18n? $name .= ' (' . $profile->fullname . ')'; } $this->element('name', null, $name); $this->element('uri', null, common_profile_uri($profile)); $this->elementEnd('author'); $this->elementEnd('entry'); }
function showItem($notice) { $profile = Profile::staticGet($notice->profile_id); $nurl = common_local_url('shownotice', array('notice' => $notice->id)); $creator_uri = common_profile_uri($profile); $this->elementStart('item', array('rdf:about' => $notice->uri, 'rdf:type' => 'http://rdfs.org/sioc/types#MicroblogPost')); $title = $profile->nickname . ': ' . common_xml_safe_str(trim($notice->content)); $this->element('title', null, $title); $this->element('link', null, $nurl); $this->element('description', null, $profile->nickname . "'s status on " . common_exact_date($notice->created)); if ($notice->rendered) { $this->element('content:encoded', null, common_xml_safe_str($notice->rendered)); } $this->element('dc:date', null, common_date_w3dtf($notice->created)); $this->element('dc:creator', null, $profile->fullname ? $profile->fullname : $profile->nickname); $this->element('foaf:maker', array('rdf:resource' => $creator_uri)); $this->element('sioc:has_creator', array('rdf:resource' => $creator_uri . '#acct')); $location = $notice->getLocation(); if ($location && isset($location->lat) && isset($location->lon)) { $location_uri = $location->getRdfURL(); $attrs = array('geo:lat' => $location->lat, 'geo:long' => $location->lon); if (strlen($location_uri)) { $attrs['rdf:resource'] = $location_uri; } $this->element('statusnet:origin', $attrs); } $this->element('statusnet:postIcon', array('rdf:resource' => $profile->avatarUrl())); $this->element('cc:licence', array('rdf:resource' => common_config('license', 'url'))); if ($notice->reply_to) { $replyurl = common_local_url('shownotice', array('notice' => $notice->reply_to)); $this->element('sioc:reply_of', array('rdf:resource' => $replyurl)); } if (!empty($notice->conversation)) { $conversationurl = common_local_url('conversation', array('id' => $notice->conversation)); $this->element('sioc:has_discussion', array('rdf:resource' => $conversationurl)); } $attachments = $notice->attachments(); if ($attachments) { foreach ($attachments as $attachment) { $enclosure = $attachment->getEnclosure(); if ($enclosure) { $attribs = array('rdf:resource' => $enclosure->url); if ($enclosure->title) { $attribs['dc:title'] = $enclosure->title; } if ($enclosure->modified) { $attribs['dc:date'] = common_date_w3dtf($enclosure->modified); } if ($enclosure->size) { $attribs['enc:length'] = $enclosure->size; } if ($enclosure->mimetype) { $attribs['enc:type'] = $enclosure->mimetype; } $this->element('enc:enclosure', $attribs); } $this->element('sioc:links_to', array('rdf:resource' => $attachment->url)); } } $tag = new Notice_tag(); $tag->notice_id = $notice->id; if ($tag->find()) { $entry['tags'] = array(); while ($tag->fetch()) { $tagpage = common_local_url('tag', array('tag' => $tag->tag)); if (in_array($tag, $this->tags_already_output)) { $this->element('ctag:tagged', array('rdf:resource' => $tagpage . '#concept')); continue; } $tagrss = common_local_url('tagrss', array('tag' => $tag->tag)); $this->elementStart('ctag:tagged'); $this->elementStart('ctag:Tag', array('rdf:about' => $tagpage . '#concept', 'ctag:label' => $tag->tag)); $this->element('foaf:page', array('rdf:resource' => $tagpage)); $this->element('rdfs:seeAlso', array('rdf:resource' => $tagrss)); $this->elementEnd('ctag:Tag'); $this->elementEnd('ctag:tagged'); $this->tags_already_output[] = $tag->tag; } } $this->elementEnd('item'); $this->creators[$creator_uri] = $profile; }
function asAtomEntry($namespace = false, $source = false) { $xs = new XMLStringer(true); if ($namespace) { $attrs = array('xmlns' => 'http://www.w3.org/2005/Atom', 'xmlns:thr' => 'http://purl.org/syndication/thread/1.0'); } else { $attrs = array(); } $xs->elementStart('entry', $attrs); if ($source) { $xs->elementStart('source'); $xs->element('id', null, $this->permalink()); $xs->element('title', null, $profile->nickname . " - " . common_config('site', 'name')); $xs->element('link', array('href' => $this->permalink())); $xs->element('updated', null, $this->modified); $xs->elementEnd('source'); } $xs->element('title', null, $this->nickname); $xs->element('summary', null, common_xml_safe_str($this->description)); $xs->element('link', array('rel' => 'alternate', 'href' => $this->permalink())); $xs->element('id', null, $this->permalink()); $xs->element('published', null, common_date_w3dtf($this->created)); $xs->element('updated', null, common_date_w3dtf($this->modified)); $xs->element('content', array('type' => 'html'), common_xml_safe_str($this->description)); $xs->elementEnd('entry'); return $xs->getString(); }
/** * Send an Activity Streams notification to the remote Salmon endpoint, * if so configured. * * @param Profile $actor Actor who did the activity * @param string $verb Activity::SUBSCRIBE or Activity::JOIN * @param Object $object object of the action; must define asActivityNoun($tag) */ public function notify(Profile $actor, $verb, $object = null, $target = null) { if ($object == null) { $object = $this; } if (empty($this->salmonuri)) { return false; } $text = 'update'; $id = TagURI::mint('%s:%s:%s', $verb, $actor->getURI(), common_date_iso8601(time())); // @todo FIXME: Consolidate all these NS settings somewhere. $attributes = array('xmlns' => Activity::ATOM, 'xmlns:activity' => 'http://activitystrea.ms/spec/1.0/', 'xmlns:thr' => 'http://purl.org/syndication/thread/1.0', 'xmlns:georss' => 'http://www.georss.org/georss', 'xmlns:ostatus' => 'http://ostatus.org/schema/1.0', 'xmlns:poco' => 'http://portablecontacts.net/spec/1.0', 'xmlns:media' => 'http://purl.org/syndication/atommedia'); $entry = new XMLStringer(); $entry->elementStart('entry', $attributes); $entry->element('id', null, $id); $entry->element('title', null, $text); $entry->element('summary', null, $text); $entry->element('published', null, common_date_w3dtf(common_sql_now())); $entry->element('activity:verb', null, $verb); $entry->raw($actor->asAtomAuthor()); $entry->raw($actor->asActivityActor()); $entry->raw($object->asActivityNoun('object')); if ($target != null) { $entry->raw($target->asActivityNoun('target')); } $entry->elementEnd('entry'); $xml = $entry->getString(); common_log(LOG_INFO, "Posting to Salmon endpoint {$this->salmonuri}: {$xml}"); Salmon::post($this->salmonuri, $xml, $actor); }
function showUpdated() { if (!empty($this->peopletag->modified)) { $this->out->element('abbr', array('title' => common_date_w3dtf($this->peopletag->modified), 'class' => 'updated'), common_date_string($this->peopletag->modified)); } }
/** * Send an Activity Streams notification to the remote Salmon endpoint, * if so configured. * * @param Profile $actor Actor who did the activity * @param string $verb Activity::SUBSCRIBE or Activity::JOIN * @param Object $object object of the action; must define asActivityNoun($tag) */ public function notify($actor, $verb, $object = null, $target = null) { if (!$actor instanceof Profile) { $type = gettype($actor); if ($type == 'object') { $type = get_class($actor); } // TRANS: Server exception. // TRANS: %1$s is the method name the exception occured in, %2$s is the actor type. throw new ServerException(sprintf(_m('Invalid actor passed to %1$s: %2$s.'), __METHOD__, $type)); } if ($object == null) { $object = $this; } if ($this->salmonuri) { $text = 'update'; $id = TagURI::mint('%s:%s:%s', $verb, $actor->getURI(), common_date_iso8601(time())); // @todo FIXME: Consolidate all these NS settings somewhere. $attributes = array('xmlns' => Activity::ATOM, 'xmlns:activity' => 'http://activitystrea.ms/spec/1.0/', 'xmlns:thr' => 'http://purl.org/syndication/thread/1.0', 'xmlns:georss' => 'http://www.georss.org/georss', 'xmlns:ostatus' => 'http://ostatus.org/schema/1.0', 'xmlns:poco' => 'http://portablecontacts.net/spec/1.0', 'xmlns:media' => 'http://purl.org/syndication/atommedia'); $entry = new XMLStringer(); $entry->elementStart('entry', $attributes); $entry->element('id', null, $id); $entry->element('title', null, $text); $entry->element('summary', null, $text); $entry->element('published', null, common_date_w3dtf(common_sql_now())); $entry->element('activity:verb', null, $verb); $entry->raw($actor->asAtomAuthor()); $entry->raw($actor->asActivityActor()); $entry->raw($object->asActivityNoun('object')); if ($target != null) { $entry->raw($target->asActivityNoun('target')); } $entry->elementEnd('entry'); $xml = $entry->getString(); common_log(LOG_INFO, "Posting to Salmon endpoint {$this->salmonuri}: {$xml}"); $salmon = new Salmon(); // ? return $salmon->post($this->salmonuri, $xml, $actor); } return false; }
/** * Build an Atom entry similar to search.twitter.com's based on * a given notice * * @param Notice $notice the notice to use * * @return void */ function showEntry($notice) { $server = common_config('site', 'server'); $profile = $notice->getProfile(); $nurl = common_local_url('shownotice', array('notice' => $notice->id)); $this->elementStart('entry'); $taguribase = TagURI::base(); $this->element('id', null, "tag:{$taguribase}:{$notice->id}"); $this->element('published', null, common_date_w3dtf($notice->created)); $this->element('link', array('type' => 'text/html', 'rel' => 'alternate', 'href' => $nurl)); $this->element('title', null, common_xml_safe_str(trim($notice->content))); $this->element('content', array('type' => 'html'), $notice->rendered); $this->element('updated', null, common_date_w3dtf($notice->created)); $this->element('link', array('type' => 'image/png', 'rel' => 'related', 'href' => $profile->avatarUrl())); // TODO: Here is where we'd put in a link to an atom feed for threads $this->element("twitter:source", null, htmlentities($this->sourceLink($notice->source))); $this->elementStart('author'); $name = $profile->nickname; if ($profile->fullname) { $name .= ' (' . $profile->fullname . ')'; } $this->element('name', null, $name); $this->element('uri', null, common_profile_uri($profile)); $this->elementEnd('author'); $this->elementEnd('entry'); }
function asAtomEntry($namespace = false, $source = false, $author = true) { $profile = $this->getProfile(); $xs = new XMLStringer(true); if ($namespace) { $attrs = array('xmlns' => 'http://www.w3.org/2005/Atom', 'xmlns:thr' => 'http://purl.org/syndication/thread/1.0', 'xmlns:georss' => 'http://www.georss.org/georss', 'xmlns:activity' => 'http://activitystrea.ms/spec/1.0/', 'xmlns:media' => 'http://purl.org/syndication/atommedia', 'xmlns:poco' => 'http://portablecontacts.net/spec/1.0', 'xmlns:ostatus' => 'http://ostatus.org/schema/1.0'); } else { $attrs = array(); } $xs->elementStart('entry', $attrs); if ($source) { $xs->elementStart('source'); $xs->element('id', null, $profile->profileurl); $xs->element('title', null, $profile->nickname . " - " . common_config('site', 'name')); $xs->element('link', array('href' => $profile->profileurl)); $user = User::staticGet('id', $profile->id); if (!empty($user)) { $atom_feed = common_local_url('ApiTimelineUser', array('format' => 'atom', 'id' => $profile->nickname)); $xs->element('link', array('rel' => 'self', 'type' => 'application/atom+xml', 'href' => $profile->profileurl)); $xs->element('link', array('rel' => 'license', 'href' => common_config('license', 'url'))); } $xs->element('icon', null, $profile->avatarUrl(AVATAR_PROFILE_SIZE)); $xs->element('updated', null, common_date_w3dtf($this->created)); } if ($source) { $xs->elementEnd('source'); } $xs->element('title', null, common_xml_safe_str($this->content)); if ($author) { $xs->raw($profile->asAtomAuthor()); $xs->raw($profile->asActivityActor()); } $xs->element('link', array('rel' => 'alternate', 'type' => 'text/html', 'href' => $this->bestUrl())); $xs->element('id', null, $this->uri); $xs->element('published', null, common_date_w3dtf($this->created)); $xs->element('updated', null, common_date_w3dtf($this->created)); if ($this->reply_to) { $reply_notice = Notice::staticGet('id', $this->reply_to); if (!empty($reply_notice)) { $xs->element('link', array('rel' => 'related', 'href' => $reply_notice->bestUrl())); $xs->element('thr:in-reply-to', array('ref' => $reply_notice->uri, 'href' => $reply_notice->bestUrl())); } } if (!empty($this->conversation)) { $conv = Conversation::staticGet('id', $this->conversation); if (!empty($conv)) { $xs->element('link', array('rel' => 'ostatus:conversation', 'href' => $conv->uri)); } } $reply_ids = $this->getReplies(); foreach ($reply_ids as $id) { $profile = Profile::staticGet('id', $id); if (!empty($profile)) { $xs->element('link', array('rel' => 'ostatus:attention', 'href' => $profile->getUri())); } } $groups = $this->getGroups(); foreach ($groups as $group) { $xs->element('link', array('rel' => 'ostatus:attention', 'href' => $group->permalink())); } if (!empty($this->repeat_of)) { $repeat = Notice::staticGet('id', $this->repeat_of); if (!empty($repeat)) { $xs->element('ostatus:forward', array('ref' => $repeat->uri, 'href' => $repeat->bestUrl())); } } $xs->element('content', array('type' => 'html'), common_xml_safe_str($this->rendered)); $tag = new Notice_tag(); $tag->notice_id = $this->id; if ($tag->find()) { while ($tag->fetch()) { $xs->element('category', array('term' => $tag->tag)); } } $tag->free(); # Enclosures $attachments = $this->attachments(); if ($attachments) { foreach ($attachments as $attachment) { $enclosure = $attachment->getEnclosure(); if ($enclosure) { $attributes = array('rel' => 'enclosure', 'href' => $enclosure->url, 'type' => $enclosure->mimetype, 'length' => $enclosure->size); if ($enclosure->title) { $attributes['title'] = $enclosure->title; } $xs->element('link', $attributes, null); } } } if (!empty($this->lat) && !empty($this->lon)) { $xs->element('georss:point', null, $this->lat . ' ' . $this->lon); } $xs->elementEnd('entry'); return $xs->getString(); }
function showItem($notice) { $profile = Profile::staticGet($notice->profile_id); $nurl = common_local_url('shownotice', array('notice' => $notice->id)); $creator_uri = common_profile_uri($profile); $this->elementStart('item', array('rdf:about' => $notice->uri)); $title = $profile->nickname . ': ' . common_xml_safe_str(trim($notice->content)); $this->element('title', null, $title); $this->element('link', null, $nurl); $this->element('description', null, $profile->nickname . "'s status on " . common_exact_date($notice->created)); $this->element('dc:date', null, common_date_w3dtf($notice->created)); $this->element('dc:creator', null, $profile->fullname ? $profile->fullname : $profile->nickname); $this->element('sioc:has_creator', array('rdf:resource' => $creator_uri)); $this->element('laconica:postIcon', array('rdf:resource' => $profile->avatarUrl())); $this->element('cc:licence', array('rdf:resource' => common_config('license', 'url'))); $this->elementEnd('item'); $this->creators[$creator_uri] = $profile; }
/** * extra information for XMPP messages, as defined by Twitter * * @param Profile $profile Profile of the sending user * @param Notice $notice Notice being sent * * @return string Extra information (Atom, HTML, addresses) in string format */ function jabber_format_entry($profile, $notice) { // FIXME: notice url might be remote $noticeurl = common_local_url('shownotice', array('notice' => $notice->id)); $msg = jabber_format_notice($profile, $notice); $self_url = common_local_url('userrss', array('nickname' => $profile->nickname)); $entry = "\n<entry xmlns='http://www.w3.org/2005/Atom'>\n"; $entry .= "<source>\n"; $entry .= "<title>" . $profile->nickname . " - " . common_config('site', 'name') . "</title>\n"; $entry .= "<link href='" . htmlspecialchars($profile->profileurl) . "'/>\n"; $entry .= "<link rel='self' type='application/rss+xml' href='" . $self_url . "'/>\n"; $entry .= "<author><name>" . $profile->nickname . "</name></author>\n"; $entry .= "<icon>" . $profile->avatarUrl(AVATAR_PROFILE_SIZE) . "</icon>\n"; $entry .= "</source>\n"; $entry .= "<title>" . htmlspecialchars($msg) . "</title>\n"; $entry .= "<summary>" . htmlspecialchars($msg) . "</summary>\n"; $entry .= "<link rel='alternate' href='" . $noticeurl . "' />\n"; $entry .= "<id>" . $notice->uri . "</id>\n"; $entry .= "<published>" . common_date_w3dtf($notice->created) . "</published>\n"; $entry .= "<updated>" . common_date_w3dtf($notice->modified) . "</updated>\n"; if ($notice->reply_to) { $replyurl = common_local_url('shownotice', array('notice' => $notice->reply_to)); $entry .= "<link rel='related' href='" . $replyurl . "'/>\n"; } $entry .= "</entry>\n"; $html = "\n<html xmlns='http://jabber.org/protocol/xhtml-im'>\n"; $html .= "<body xmlns='http://www.w3.org/1999/xhtml'>\n"; $html .= "<a href='" . htmlspecialchars($profile->profileurl) . "'>" . $profile->nickname . "</a>: "; $html .= $notice->rendered ? $notice->rendered : common_render_content($notice->content, $notice); $html .= "\n</body>\n"; $html .= "\n</html>\n"; $address = "<addresses xmlns='http://jabber.org/protocol/address'>\n"; $address .= "<address type='replyto' jid='" . jabber_daemon_address() . "' />\n"; $address .= "</addresses>\n"; // FIXME: include a pubsub event, too. return $html . $entry . $address; }