1
0
Fork 0
mirror of git://git.psyced.org/git/psyced synced 2024-08-15 03:25:10 +00:00

things that happened in 2008

This commit is contained in:
psyc://psyced.org/~lynX 2009-01-26 21:12:53 +01:00
parent 8f98522570
commit 94530cc322
136 changed files with 3222 additions and 2873 deletions

View file

@ -1,13 +1,10 @@
// $Id: active.c,v 1.395 2008/04/01 09:38:26 lynx Exp $ // vim:syntax=lpc:ts=8
#include <net.h>
#include <sys/time.h>
#include <url.h>
// $Id: active.c,v 1.404 2008/10/26 17:24:57 lynx Exp $ // vim:syntax=lpc:ts=8
// a jabber thing which actively connects something
#define NO_INHERIT
#include "jabber.h"
#undef NO_INHERIT
#include <url.h>
#ifdef ERQ_WITHOUT_SRV
# define hostname host // hostname contains the name before SRV resolution
@ -39,9 +36,9 @@ volatile int dialback_outgoing;
tls_logon(); // prototype
#ifdef NOT_EXPERIMENTAL // not strictly necessary, but more spec conformant
// not strictly necessary, but more spec conformant
quit() {
emit("</stream:stream>");
emitraw("</stream:stream>");
#ifdef _flag_log_sockets_XMPP
D0( log_file("RAW_XMPP", "\n%O: shutting down, quit called\n", ME); )
#endif
@ -49,7 +46,6 @@ quit() {
// matter on an outgoing-only socket
//destruct(ME);
}
#endif
sGateway(gw, ho, id) {
// TODO: ho is obsolete
@ -68,7 +64,7 @@ removeGateway(gw, id) {
start_dialback() {
string source_host, key;
source_host = NAMEPREP(JABBER_HOST);
source_host = NAMEPREP(_host_XMPP);
key = DIALBACK_KEY(streamid, hostname, source_host);
P3(("%O: starting dialback from %O to %O\n", ME, source_host, hostname))
@ -137,7 +133,7 @@ handle_stream_features(XMLNode node) {
// && !config(XMPP + hostname, "_tls_invalid")
){
// may use tls unless we already do so
emit("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
emitraw("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
nodeHandler = #'handle_starttls;
return;
}
@ -177,11 +173,11 @@ handle_stream_features(XMLNode node) {
#ifndef _flag_disable_authentication_external_XMPP
if (mechs["EXTERNAL"]) {
// TODO we should check that the name in our
// certificate is equal to JABBER_HOST
// certificate is equal to _host_XMPP
// but so should the other side!
emit("<auth mechanism='EXTERNAL' "
"xmlns='" NS_XMPP "xmpp-sasl'>" +
encode_base64(JABBER_HOST)
encode_base64(_host_XMPP)
+ "</auth>");
return;
} else
@ -191,7 +187,7 @@ handle_stream_features(XMLNode node) {
PT(("jabber/active requesting to do digest md5\n"))
emit("<auth mechanism='DIGEST-MD5' "
"xmlns='" NS_XMPP "xmpp-sasl>" +
encode_base64(JABBER_HOST) +
encode_base64(_host_XMPP) +
"</auth>");
return;
@ -201,7 +197,7 @@ handle_stream_features(XMLNode node) {
#ifdef SWITCH2PSYC
else if (node["/switch"]) { // should check scheme
PT(("upgrading %O from XMPP to PSYC.\n", ME))
emit("<switching xmlns='http://switch.psyced.org'>"
emitraw("<switching xmlns='http://switch.psyced.org'>"
"<scheme>psyc</scheme>"
"</switching>");
return;
@ -235,6 +231,11 @@ disconnected(remainder) {
// nothing else happening here? no reconnect?
// TODO: what about the dialback Q if any?
::disconnected(remainder);
// let's call this a special case of good will:
// hopefully a sending side socket close operation
if (remainder == "</stream:stream>") return 1;
// we could forward remainder to feed(), but we haven't seen any other
// cases of content than the one above.
return flags & TCP_PENDING_DISCONNECT;
}
@ -259,18 +260,20 @@ static int logon(int failure) {
emit("<stream:stream xmlns:stream='http://etherx.jabber.org/streams' "
"xmlns='jabber:server' xmlns:db='jabber:server:dialback' "
"to='" + hostname + "' "
"from='" + NAMEPREP(JABBER_HOST) + "' "
"from='" + NAMEPREP(_host_XMPP) + "' "
"xml:lang='en' "
"version='1.0'>");
#ifdef NOT_EXPERIMENTAL // not strictly necessary, but more spec conformant
#if 1 // not strictly necessary, but more spec conformant
} else if (!qSize(me)) { // no retry for dialback-only
P0(("notify gateways %O of failure\n", gateways))
if (sizeof(dialback_queue) > 1) {
P0(("tell fippo that sizeof(dialback queue) was > 1\n"))
}
foreach(string id, mixed gw : gateways) {
if (objectp(gw)) {
gw->remote_connection_failed();
if (sizeof(gateways)) {
P0(("%O notifies gateways %O of failure\n", ME, gateways))
foreach(string id, mixed gw : gateways) {
if (objectp(gw)) {
gw->remote_connection_failed();
}
}
}
dialback_queue = 0;
@ -286,7 +289,8 @@ static int logon(int failure) {
#ifdef WANT_S2S_TLS
tls_logon(result) {
if (result < 0) {
PT(("%O tls_logon %d\n", ME, result))
P1(("%O tls_logon %d: %O\n", ME, result, tls_error(result) ))
// would be nice to insert the tls_error() message here.. TODO
connect_failure("_encrypt", "Problems setting up an encrypted circuit");
} else if (result == 0) {
// we need to check the certificate
@ -304,12 +308,12 @@ tls_logon(result) {
"contains %O/%O",
hostname, cert["2.5.4.3"],
cert["2.5.29.17:1.3.6.1.5.5.7.8.5"]));
#else
P1(("TLS: %s presented a certificate with unexpected identity.\n", hostname))
P2(("%O\n", cert))
#endif
#ifdef _flag_log_bogus_certificates
log_file("CERTS", S("%O %O %O id?\n", ME, hostname, cert));
#else
P1(("TLS: %s presented a certificate with unexpected identity.\n", hostname))
P2(("%O\n", cert))
#endif
#if 0 //def _flag_reject_bogus_certificates
QUIT
@ -321,12 +325,12 @@ tls_logon(result) {
monitor_report("_error_untrusted_certificate",
sprintf("%O certificate could not be verified",
hostname));
#else
P1(("TLS: %s presented untrusted certificate.\n", hostname))
P2(("%O\n", cert))
#endif
#ifdef _flag_log_bogus_certificates
log_file("CERTS", S("%O %O %O\n", ME, hostname, cert));
#else
P1(("TLS: %s presented untrusted certificate.\n", hostname))
P2(("%O\n", cert))
#endif
#if 0 //def _flag_reject_bogus_certificates
// QUIT is wrong...
@ -375,7 +379,7 @@ jabberMsg(XMLNode node) {
* Server MUST terminate both the XML stream and the
* underlying TCP connection.
*/
emit("</stream:stream>");
emitraw("</stream:stream>");
remove_interactive(ME);
connect_failure("_dialback", "dialback gone wrong");
}
@ -390,7 +394,7 @@ jabberMsg(XMLNode node) {
node["@type"]);
// probably we can delete this...
m_delete(gateways, t);
#ifdef NOT_EXPERIMENTAL // not strictly necessary, but more spec conformant
#if 1 // not strictly necessary, but more spec conformant
} else if (member(gateways, t)) {
P0(("%O found gateway for %O, but it is not an object: %O\n",
ME, t, o))
@ -413,7 +417,7 @@ jabberMsg(XMLNode node) {
emit("<stream:stream xmlns:stream='http://etherx.jabber.org/streams' "
"xmlns='jabber:server' xmlns:db='jabber:server:dialback' "
"to='" + hostname + "' "
"from='" + NAMEPREP(JABBER_HOST) + "' "
"from='" + NAMEPREP(_host_XMPP) + "' "
"xml:lang='en' "
"version='1.0'>");
authenticated = 1;
@ -435,7 +439,7 @@ jabberMsg(XMLNode node) {
data = sasl_parse(t);
PT(("extracted %O\n", data))
data["username"] = JABBER_HOST;
data["username"] = _host_XMPP;
secret = config(XMPP + hostname, "_secret_shared");
unless(secret) {
// mh... this is a problem!
@ -444,13 +448,13 @@ jabberMsg(XMLNode node) {
}
data["cnonce"] = RANDHEXSTRING;
data["nc"] = "00000001";
data["digest-uri"] = "xmpp/" JABBER_HOST;
data["digest-uri"] = "xmpp/" _host_XMPP;
response = sasl_calculate_digestMD5(data, secret, 0);
// ok, the username is our hostname
// note: qop must not be quoted, as we are 'client'
t = "username=\"" JABBER_HOST "\","
t = "username=\"" _host_XMPP "\","
"realm=\"" + data["realm"] + "\","
"nonce=\"" + data["nonce"] + "\","
"cnonce=\"" + data["cnonce"] + "\","
@ -584,7 +588,7 @@ int msg(string source, string mc, string data,
if (interactive() && ready && dialback_outgoing == 0) {
start_dialback();
}
#if JABBER_HOST == SERVER_HOST
#if _host_XMPP == SERVER_HOST
// we can only do this if mkjid patches the psyc host into jabber host
// but that is terrifically complicated and requires parsing of things
// we already knew.. so let's simply enqueue with object id and reject
@ -596,7 +600,7 @@ int msg(string source, string mc, string data,
#else
// is this a bad idea? not sure.. we'll see..
// if i don't have this here, a "tell lynX where it happened" will
// be triggered from here -- best to never use JABBER_HOST really ;)
// be triggered from here -- best to never use _host_XMPP really ;)
vars["_source"] = source;
// behaviour has changed.. so maybe we don't need this any longer TODO
#endif

View file

@ -1,9 +1,9 @@
// $Id: common.c,v 1.270 2008/04/11 10:27:24 fippo Exp $ // vim:syntax=lpc:ts=8
// $Id: common.c,v 1.276 2008/12/01 11:31:33 lynx Exp $ // vim:syntax=lpc:ts=8
#define NO_INHERIT
#include "jabber.h"
#undef NO_INHERIT
#include <net.h>
#include <net.h>
#include <text.h>
//virtual inherit NET_PATH "output";
#include <url.h>
@ -22,7 +22,7 @@ jabberMsg();
inherit NET_PATH "xml/common";
volatile string buffer = "";
closure jid_has_node_cl = (: int t, t2;
volatile closure jid_has_node_cl = (: int t, t2;
t = index($1, '@');
if (t == -1) return 0;
t2 = index($1, '/');
@ -72,6 +72,15 @@ int emit(string message) {
return ::emit(message);
}
// don't check message, use this only where you are 100% sure
// to be sending safe data
int emitraw(string message) {
#ifdef _flag_log_sockets_XMPP
D0( log_file("RAW_XMPP", "\n« %O\t%s", ME, message); )
#endif
return ::emit(message);
}
// this assumes the old ldmuddish charmode+combine-charset
// if we ever get a input_bytes it needs to be rewrittn
feed(a) {
@ -131,7 +140,7 @@ varargs string mkjid(mixed who, mixed vars, mixed ignore_context, string target
*/
string t, *u;
if (!who || who == "") return "";
unless (jabberhost) jabberhost = JABBER_HOST;
unless (jabberhost) jabberhost = _host_XMPP;
P3(("%O mkjid(%O, %O, %O, %O, %O)\n", ME, who, vars, ignore_context, target, jabberhost))
if (!ignore_context && vars && vars["_nick_place"]
&& vars["_context"]) {
@ -274,7 +283,14 @@ render(string mc, string data, mapping vars, mixed source) {
+"' from='"+ vars["_INTERNAL_source_jabber"] +"' type='"
+ (ISPLACEMSG(vars["_INTERNAL_source_jabber"]) && vars["_nick"] ?
"groupchat" : "chat")
+"'><body>"+ chomp(xmlquote(output)) +"</body></message>";
+"'><body>"+
#ifdef NEW_LINE
xmlquote(output)
#else
// was: chomp after xmlquote.. but why?
xmlquote(chomp(output))
#endif
+"</body></message>";
#if DEBUG > 1
// most of these message we are happy with, so we don't need this log
log_file("XMPP_TODO", "%O %s %s\n", ME, mc, output);
@ -384,7 +400,6 @@ certificate_check_jabbername(name, cert) {
foreach(string cn : t) {
if (NAMEPREP(cn) == name) return 1;
}
return 0;
}
else if (name == NAMEPREP(t))
return 1;

View file

@ -1,4 +1,4 @@
// $Id: component.c,v 1.68 2008/03/11 15:13:58 lynx Exp $ // vim:syntax=lpc
// $Id: component.c,v 1.72 2008/10/01 10:59:24 lynx Exp $ // vim:syntax=lpc
//
// this implements a passive listener component
#define NO_INHERIT
@ -40,7 +40,7 @@ reboot(reason, restart, pass) {
// close the stream according to XEP 0190
if (interactive(ME)) {
flags |= TCP_PENDING_DISCONNECT;
emit("</stream:stream>");
emitraw("</stream:stream>");
}
}
@ -96,7 +96,7 @@ waitfor_handshake(XMLNode node) {
PT(("%O component auth succeded as %O\n", ME, componentname))
nodeHandler = #'jabberMsg;
authenticated = 1;
emit("<handshake/>");
emitraw("<handshake/>");
onHandshake();
} else {
monitor_report("_error_invalid_password",
@ -122,7 +122,7 @@ int msg(string source, string mc, string data,
#ifdef PREFIXES
if (abbrev("_prefix", mc)) return 1;
#endif
#ifndef EXPERIMENTAL // TODO: decide if this is good or bad
#ifndef GAMMA // TODO: decide if this is good or bad
else if (abbrev("_status_person_absent", mc)) {
PT(("Intercepted absent from %O to %O\n", mc, source, ME))
return 1;
@ -172,7 +172,7 @@ open_stream(node) {
if (node["@to"]) {
packet += "from='" + node["@to"] + "' ";
} else {
packet += "from='" JABBER_HOST "' ";
packet += "from='" _host_XMPP "' ";
}
if (!config) {
/* reply with a stream error */

View file

@ -1,4 +1,4 @@
// $Id: disco.c,v 1.41 2008/01/05 13:44:38 lynx Exp $ // vim:syntax=lpc
// $Id: disco.c,v 1.43 2008/09/12 15:54:38 lynx Exp $ // vim:syntax=lpc
//
// this gets included by user.c and gateway.c. you can distinguish this
// by ifdeffing USER_PROGRAM. it may be renamed into disco.i one day.
@ -19,7 +19,9 @@ disco_info_root(vars) {
string featurelist;
featurelist = "<feature var='http://jabber.org/protocol/muc'/>"
#ifndef REGISTERED_USERS_ONLY
# ifndef _flag_disable_registration_XMPP
"<feature var='jabber:iq:register'/>"
# endif
#endif
#ifndef VOLATILE
"<feature var='msgoffline'/>"
@ -95,8 +97,8 @@ disco_items_root(vars) {
#ifdef PUBLIC_PLACES
// see also: library advertised_places()
#endif
// TODO: is it safe to use JABBER_HOST here?
vars["_list_item"] = "<item name='Chatrooms' jid='" JABBER_HOST "'/>";
// is it safe to use _host_XMPP here?
vars["_list_item"] = "<item name='Chatrooms' jid='" _host_XMPP "'/>";
}
disco_items_place(name, vars) {

View file

@ -1,4 +1,4 @@
// $Id: gateway.c,v 1.451 2008/03/29 16:07:30 fippo Exp $ // vim:syntax=lpc
// $Id: gateway.c,v 1.461 2008/10/22 16:35:59 fippo Exp $ // vim:syntax=lpc
/*
* jabber/gateway
* listens on jabber interserver port for incoming connections
@ -56,6 +56,12 @@ quit() {
disconnected(remainder) {
// TODO: handle remainder
P2(( "gateway %O disconnected\n", ME ))
#ifdef GAMMA
// sometimes we get complete presence packets in the socket close
// remainder. probably broken xmpp implementations, let's try and
// do the best we can with it by forwarding stuff to feed().
if (remainder && strlen(remainder)) feed(remainder);
#endif
if (objectp(active)) active -> removeGateway(streamid);
#ifdef _flag_log_sockets_XMPP
D0( log_file("RAW_XMPP", "\n%O disc\t%O", ME, ctime()); )
@ -85,13 +91,18 @@ void create() {
}
#ifdef WANT_S2S_TLS
// similar code in other files
tls_logon(result) {
P2(("%O tls_logon(%d)\n", ME, result))
if (result < 0) {
QUIT
}
else if (result == 0) {
if (result == 0) {
certinfo = tls_certificate(ME, 0);
P3(("%O tls_logon fetching certificate: %O\n", ME, certinfo))
# ifdef ERR_TLS_NOT_DETECTED
} else if (result == ERR_TLS_NOT_DETECTED) {
// just go on without encryption
# endif
} else if (result < 0) {
P1(("%O TLS error %d: %O\n", ME, result, tls_error(result)))
QUIT
} else {
P0(("tls_logon with result > 0?!?!\n"))
// should not happen
@ -121,7 +132,7 @@ verify_connection(string to, string from, string type) {
emit(sprintf("<db:result from='%s' to='%s' type='%s'/>",
to, from, type));
if (type != "valid") {
emit("</stream:stream>");
emitraw("</stream:stream>");
P2(("quitting invalid stream\n"))
QUIT
} else {
@ -217,7 +228,7 @@ jabberMsg(XMLNode node) {
// <?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:server' to='localhost' xmlns:db='jabber:server:dialback' version='1.0'><switching xmlns='http://switch.psyced.org'><scheme>psyc</scheme></switching>
emit("<switched xmlns='http://switch.psyced.org'/>");
emitraw("<switched xmlns='http://switch.psyced.org'/>");
PT(("received 'switching'. authhosts %O\n", authhosts))
o = ("S:psyc:" + host) -> load();
P1(("%O switching to %O for %O\n", ME, o, host))
@ -237,8 +248,8 @@ jabberMsg(XMLNode node) {
* a request for verification of a key
*/
// if we dont know the host, complain
// put NAMEPREP(JABBER_HOST) into the localhost mapping pleeeease
//if (target != NAMEPREP(JABBER_HOST)) {
// put NAMEPREP(_host_XMPP) into the localhost mapping pleeeease
//if (target != NAMEPREP(_host_XMPP)) {
unless (is_localhost(lower_case(target))) {
monitor_report("_error_unknown_host",
sprintf("%O sent us a dialback packet believing we would be %O",
@ -250,7 +261,7 @@ jabberMsg(XMLNode node) {
sendmsg(origin,
"_dialback_request_verify", 0,
([ "_INTERNAL_target_jabber" : source,
"_INTERNAL_source_jabber" : NAMEPREP(JABBER_HOST),
"_INTERNAL_source_jabber" : NAMEPREP(_host_XMPP),
"_dialback_key" : node[Cdata],
"_tag" : streamid
])
@ -296,7 +307,7 @@ jabberMsg(XMLNode node) {
/* we were calling this server, this packet is step 8
* and we are doing step 9
*/
/* if we dont recognize target (currently: == JABBER_HOST)
/* if we dont recognize target (currently: == _host_XMPP)
* then croak with a host-unknown and commit suicide
*/
// same as above...
@ -317,12 +328,15 @@ jabberMsg(XMLNode node) {
case "starttls":
#ifdef WANT_S2S_TLS
if (tls_available()) {
emit("<proceed xmlns='" NS_XMPP "xmpp-tls'/>");
emitraw("<proceed xmlns='" NS_XMPP "xmpp-tls'/>");
# if __EFUN_DEFINED__(tls_want_peer_certificate)
tls_want_peer_certificate(ME);
# endif
tls_init_connection(ME, #'tls_logon);
return;
}
#endif
emit("<failure xmlns='" NS_XMPP "xmpp-tls'/>");
emitraw("<failure xmlns='" NS_XMPP "xmpp-tls'/>");
return;
case "stream:error":
if (node["/connection-timeout"]) {
@ -351,7 +365,7 @@ jabberMsg(XMLNode node) {
success = certificate_check_jabbername(t, certinfo);
if (success) {
emit("<success xmlns='" NS_XMPP "xmpp-sasl'/>");
emitraw("<success xmlns='" NS_XMPP "xmpp-sasl'/>");
P2(("successful sasl external authentication with "
"%O\n", t))
sAuthenticated(t);
@ -377,7 +391,7 @@ jabberMsg(XMLNode node) {
encode_base64(sprintf("realm=\"%s\",nonce=\"%s\","
"qop=\"auth\",charset=utf-8,"
"algorithm=md5-sess",
JABBER_HOST, RANDHEXSTRING)
_host_XMPP, RANDHEXSTRING)
) + "</challenge>");
} else {
// kind of 'unknown username'
@ -469,7 +483,10 @@ open_stream(XMLNode node) {
if (node["@to"]) {
packet += "from='" + node["@to"] + "' ";
} else {
packet += "from='" JABBER_HOST "' ";
packet += "from='" _host_XMPP "' ";
}
if (node["@from"]) {
packet += "to='" + node["@from"] + "' ";
}
if (node["@to"] && !(is_localhost(lower_case(node["@to"])))) {
emit(packet + ">");
@ -505,7 +522,7 @@ open_stream(XMLNode node) {
// let the other side decide if it knows a shared secret
// with us
// if it it has, it will use it with digest-md5
# if __VERSION_MINOR__ > 3 || __VERSION_MICRO__ > 610
# ifndef _flag_disable_authentication_digest_MD5
if (node["@from"]
&& config(XMPP + node["@from"],
"_secret_shared")) {
@ -517,7 +534,7 @@ open_stream(XMLNode node) {
// and we have verified it as X509_V_OK (0)
// we offer SASL external (authentication via name
// presented in x509 certificate
P3(("gateway::certinfo %O\n", certinfo))
P0(("gateway::certinfo %O\n", certinfo))
if (mappingp(certinfo) && certinfo[0] == 0) {
// if from attribute is present we only offer
// sasl external if we know that it will succeed
@ -554,6 +571,6 @@ w(string mc, string data, mapping vars, mixed source) {
P2(("%O using w() for %O, unimplemented... mc %O, source %O\n",
ME, origin, mc, source))
unless (vars) vars = ([ ]);
vars["_INTERNAL_source_jabber"] = objectp(source) ? mkjid(source) : JABBER_HOST;
vars["_INTERNAL_source_jabber"] = objectp(source) ? mkjid(source) : _host_XMPP;
sendmsg(origin, mc, data, vars);
}

View file

@ -1,4 +1,4 @@
// $Id: interserver.c,v 1.12 2008/03/11 15:13:58 lynx Exp $ vim:syntax=lpc
// $Id: interserver.c,v 1.13 2008/10/01 10:59:24 lynx Exp $ vim:syntax=lpc
//
// common things for interserver jabber.. included or maybe later inherited by
// active.c and gateway.c. i am sure fippo will find some more nice things to
@ -35,7 +35,7 @@ int clean_up(int refcount) {
// and is therefore the correct way to timeout a connection.
PT(("%O cleaning up: closing stream\n", ME))
// close the stream according to XEP 0190
emit("</stream:stream>");
emitraw("</stream:stream>");
// flag says the stream is in closing phase and nothing may be
// delivered on it. but we aren't enforcing this. TODO!
flags |= TCP_PENDING_DISCONNECT;

View file

@ -1,4 +1,4 @@
// $Id: jabber.h,v 1.74 2008/03/30 10:27:49 lynx Exp $ // vim:syntax=lpc
// $Id: jabber.h,v 1.75 2008/09/12 15:54:39 lynx Exp $ // vim:syntax=lpc
//
// REMINDER:
// there are plenty of calls to lower_case in the code, that is because
@ -74,12 +74,12 @@ virtual inherit JABBER_PATH "common";
# endif
#endif
#ifndef JABBER_HOST
# define JABBER_HOST SERVER_HOST
#ifndef _host_XMPP
# define _host_XMPP SERVER_HOST
#endif
// this is not ready for is_localhost
#define is_localhost(a) (a) == JABBER_HOST
#define is_localhost(a) (a) == _host_XMPP
#define JABSOURCE "_INTERNAL_source_jabber"

View file

@ -1,5 +1,5 @@
#include <net.h> // vim:set syntax=lpc
#include "jabber.h"
#include <net.h> // vim:set syntax=lpc
#include <url.h>
#include "presence.h"
#include <time.h>
@ -48,7 +48,6 @@ jabberMsg(XMLNode node, mixed origin, mixed *su, array(mixed) tu) {
// #define MYORIGIN XMPP + su[UUserAtHost]
unless(su) su = parse_uniform(origin);
#if 1 //def NOT_EXPERIMENTAL
origin = XMPP;
if (su[UUser]) {
origin += NODEPREP(su[UUser]) + "@";
@ -59,7 +58,6 @@ jabberMsg(XMLNode node, mixed origin, mixed *su, array(mixed) tu) {
origin += "/" + RESOURCEPREP(su[UResource]);
}
su = parse_uniform(origin);
#endif
if (node["/nick"] &&
node["/nick"]["@xmlns"] == "http://jabber.org/protocol/nick" &&
node["/nick"][Cdata]) {
@ -133,7 +131,14 @@ jabberMsg(XMLNode node, mixed origin, mixed *su, array(mixed) tu) {
data = "Talking to [_nick_target] is not possible: [_text_XMPP]";
} else {
mc = "_failure_unavailable_service_talk";
data = "Talking to [_nick_target] is not possible. You may have to establish friendship first.";
// data = "Talking to [_nick_target] is not possible. You may have to establish friendship first.";
// google talk sends this quite frequently:
// * when a friendship exchange hasn't been done
// * when a friend has gone offline
// and you never know if a message has been delivered to the
// recipient just the same! so here's a more accurate error message,
// effectively giving you less information, since that's what we have here.
data = "Message to [_nick_target] may not have reached its recipient.";
}
} else if (1) { // TODO: what was that error?
PT(("gateway TODO <error> in <message>: %O\n",
@ -293,7 +298,7 @@ jabberMsg(XMLNode node, mixed origin, mixed *su, array(mixed) tu) {
} else {
// no relaying allowed, so we ignore hostname
o = summon_person(tu[UUser]);
#ifdef EXPERIMENTAL
#ifdef GAMMA
// xep 0085 typing notices - we even split active into a separate message
// for now. could be sent as a flag
if ((node[t="/composing"] || node[t="/active"] ||
@ -379,7 +384,7 @@ jabberMsg(XMLNode node, mixed origin, mixed *su, array(mixed) tu) {
// so there wont be circular error messages
if (tu[UUser]) {
o = summon_person(tu[UUser]);
#ifndef EXPERIMENTAL
#ifndef GAMMA
if (o && o->execute_callback(node["@id"], ({ vars["_INTERNAL_identification"], vars, node }))) return 1;
#else
// the following should catch errors - in theory, requires testing
@ -540,26 +545,20 @@ jabberMsg(XMLNode node, mixed origin, mixed *su, array(mixed) tu) {
sendmsg(o, "_notice_place_leave_unicast", 0, vars, origin);
#endif
} else {
#ifdef AVAILABILITY_OFFLINE
o = summon_person(tu[UUser]);
// http://www.psyc.eu/presence
vars["_degree_availability"] = AVAILABILITY_OFFLINE;
#ifdef CACHE_PRESENCE
# ifdef CACHE_PRESENCE
persistent_presence(XMPP + su[UUserAtHost],
AVAILABILITY_OFFLINE);
#endif
# endif
vars["_description_presence"] =
(node["/status"] && node["/status"][Cdata]) ?
node["/status"][Cdata] : ""; // "Get psyced!";
vars["_INTERNAL_mood_jabber"] = "neutral";
sendmsg(o, "_notice_presence_absent", 0,
vars, origin);
#if 0 // packen wir das doch wieder zusammen...
} else {
// one more famous fippoesque else case.. let's fill it ;)
P0(("%O Surprise! Encountered absence with resource: %O\n",
ME, node))
// interessant... wir werden das wohl noch oefter sehen
// ich bin nicht sicher, ob das ein bug der gegenseite ist
#endif
}
break;
@ -637,11 +636,11 @@ jabberMsg(XMLNode node, mixed origin, mixed *su, array(mixed) tu) {
// }
P4(("_request_enter from %O to %O: %O\n", ME, o, vars))
// dont send me a memberlist if i am a member already
#ifndef HISTORY_AMOUNT
# define HISTORY_AMOUNT 5
#ifndef _limit_amount_history_place_default
# define _limit_amount_history_place_default 5
#endif
unless(vars["_amount_history"])
vars["_amount_history"] = HISTORY_AMOUNT;
vars["_amount_history"] = _limit_amount_history_place_default;
sendmsg(o,
#ifdef SPEC
"_request_context_enter"

View file

@ -1,6 +1,6 @@
#include "jabber.h"
#include <net.h>
#include <url.h>
#include "jabber.h"
// just renderMembers
#include NET_PATH "members.i"
@ -37,9 +37,9 @@ int msg(string source, string mc, string data,
// ignore these
return 1;
break;
case "_request_description": // wir sollten uns da auf eins einigen :)
case "_request_examine": // needs a tag also... probably all _request's do
mc = "_request_examine_vCard";
case "_request_examine": // don't use this, please remove in 2009
case "_request_description": // this is the one.
mc = "_request_description_vCard"; // pending rename.. TODO
unless (vars["_tag"]) vars["_tag"] = RANDHEXSTRING;
source->chain_callback(vars["_tag"], (:
if ($3["@type"] == "result") {
@ -245,6 +245,7 @@ int msg(string source, string mc, string data,
$2 });
:));
break;
#ifndef _flag_disable_module_authentication
case "_request_authentication":
// TODO: XEP 0070 says we should use <message/> when the recipient is a bare jid
// but I prefer the iq method
@ -255,6 +256,8 @@ int msg(string source, string mc, string data,
return ({ $1, "_error_invalid_authentication", 0, $2 });
:));
break;
#endif
#ifndef _flag_disable_query_server
case "_notice_list_feature":
case "_notice_list_feature_person":
case "_notice_list_feature_place":
@ -266,6 +269,7 @@ int msg(string source, string mc, string data,
vars["_list_feature"] = implode(map(vars["_list_feature"],
(: return "<feature var='" + feat2jabber[$1] + "'/>"; :)), "");
break;
#endif
case "_notice_list_item":
t = "";
// same stuff in user.c (what happened to code sharing?)
@ -513,6 +517,10 @@ int msg(string source, string mc, string data,
#endif
if ($3["@type"] == "error") {
// FIXME: could remove context
//
// also, we should implement the full choice of errors and
// map them to appropriate psyc errors.. instead we just
// have this silly lazy coder's message:
return ({ t, "_failure_place_enter_XMPP",
"[_nick_place] could not be entered for jabberish reasons.",
$2 });
@ -557,6 +565,9 @@ int msg(string source, string mc, string data,
else if (abbrev("_failure_redirect", mc)) {
if (vars["_tag_reply"]) { // wild guess that it is an iq then
mc = "_jabber_iq_error";
// <lynX> was spricht dagegen _failure_redirect als <redirect/> auszugeben?
// <fippo> ich denke nicht, dass es irgendwer vernünftig implementiert...
// außerdem musst du die jid des raumes in dem konkreten fall rausfinden
vars["_jabber_XML"] = "<error type='modify'><gone xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/><text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' xml:lang='en'>" + psyctext(data, vars) + "</text></error>";
}
}

View file

@ -1,6 +1,6 @@
#include <net.h>
/* a cache for the remote muc
/* a slave for the remote muc
* yes, this is for a SINGLE person
* yes, that's horrible
*
@ -8,13 +8,6 @@
* even /history if we'd like to have that.. ;)
*/
// FIXME: should set "owner nick" and tag so
// we can detect when the remote room does not
// support tagging or when we are kicked
// and this could even do echo detection
// NOTE: this should work when using the
// isecho check
object owner;
mapping membercache = ([ ]);
@ -49,6 +42,8 @@ castmsg(source, method, data, mapping vars) {
case "_notice_place_leave":
if (isecho) {
// got kicked or room does not support tagging
// this works already for kick, but it might be nice to do that
// as a KICK for irc
P0(("%O left via _notice_place_leave, this is strange\n", vars["_context"]))
}
m_delete(membercache, source);
@ -63,6 +58,5 @@ castmsg(source, method, data, mapping vars) {
}
mapping qMembers() {
P4(("membercache is %O\n", membercache))
return m_indices(membercache);
}

View file

@ -1,11 +1,12 @@
// $Id: server.c,v 1.148 2008/03/11 15:13:58 lynx Exp $ // vim:syntax=lpc:ts=8
// $Id: server.c,v 1.159 2008/10/01 10:59:24 lynx Exp $ // vim:syntax=lpc:ts=8
#include "jabber.h"
#include "server.h" // inherits net/server
#include "person.h" // find_person
#include "url.h"
#include <sys/tls.h>
volatile string tag;
volatile string authtag;
volatile string resource;
volatile string streamid;
volatile string pass;
@ -16,12 +17,11 @@ volatile string sasluser;
volatile string saslchallenge;
#ifdef __TLS__
volatile mixed cert;
volatile mixed certinfo;
#endif
qScheme() { return "jabber"; }
// qName() { } // we need that in common.c - probably no more
qTag() { return tag; }
void create() {
unless (clonep()) return;
@ -30,13 +30,24 @@ void create() {
}
#ifdef __TLS__
tls_logon(result) {
PT(("%O tls_logon(%d)\n", ME, result))
PT(("%O tls? %O\n", ME, tls_query_connection_state(ME)))
// we may write again
# ifdef WANT_S2S_SASL
cert = tls_certificate(ME, 0);
// similar code in other files
tls_logon(result) {
if (result == 0) {
# ifdef WANT_S2S_SASL /* hey wait.. this is not S2S here!? */
certinfo = tls_certificate(ME, 0);
# endif
P3(("%O tls_logon fetching certificate: %O\n", ME, certinfo))
# ifdef ERR_TLS_NOT_DETECTED
} else if (result == ERR_TLS_NOT_DETECTED) {
// no encryption. no problem.
# endif
} else if (result < 0) {
P1(("%O TLS error %d: %O\n", ME, result, tls_error(result)))
QUIT // don't fall back to plaintext instead
} else {
P0(("tls_logon with result > 0?!?!\n"))
// should not happen
}
}
#endif
@ -57,14 +68,13 @@ string *splitsasl(string data) {
return result;
}
promptForPassword(user) {
P2(("promptForPassword with %O\n", user))
if (reprompt == 1 || pass) {
w("_error_invalid_password", "Invalid password.\n",
([ "_tag_reply" : qTag(), "_nick" : nick,
([ "_tag_reply" : authtag || "", "_nick" : nick,
"_resource" : resource ]) );
write("</stream:stream>");
emitraw("</stream:stream>");
QUIT
return; // ?
}
@ -72,9 +82,9 @@ promptForPassword(user) {
unless (pass) {
reprompt = 1;
w("_query_password", 0, //"Please provide your password.",
([ "_nick": nick, "_tag_reply" : qTag() ]) );
}
return 1;
([ "_nick": nick, "_tag_reply" : authtag || "" ]) );
}
return 1;
}
logon(a) {
@ -100,17 +110,17 @@ createUser(nick) {
userLogon() {
user->sTag(tag);
user->sTag(authtag);
user->sResource(resource);
return ::userLogon();
}
#ifdef EXPERIMENTAL
#ifdef GAMMA
authChecked(result, varargs array(mixed) args) {
// a point where we could be sending our jabber:iq:auth reply
// instead of letting _notice_login do that
PT(("%O got authChecked %O, %O\n", ME, result, args))
return ::authChecked(result, args);
return ::authChecked(result, args...);
}
#endif
@ -119,12 +129,12 @@ jabberMsg(XMLNode node) {
string id;
mixed t;
id = node["@id"]; // tag?
id = node["@id"] || ""; // tag?
switch (node[Tag]) {
case "iq":
if (node["/bind"]) {
// suppresses the jabber:iq:auth reply in the SASL case
tag = -1;
authtag = -1;
unless (sasluser) {
// not-allowed stanza error?
return 0;
@ -137,31 +147,28 @@ jabberMsg(XMLNode node) {
if (!stringp(resource) || resource == "")
resource = "PSYC";
nick = sasluser;
sasluser = "";
sasluser = ""; // why an empty string? explanation needed
emit(sprintf("<iq type='result' id='%s'>"
"<bind xmlns='" NS_XMPP "xmpp-bind'>"
"<jid>%s</jid>"
"</bind></iq>",
id, nick + "@" SERVER_HOST "/" + resource));
emit("<iq type='result' id='"+ id +"'>"
"<bind xmlns='" NS_XMPP "xmpp-bind'><jid>"+
nick +"@" SERVER_HOST "/"+ resource +"</jid>"
"</bind></iq>");
return 0;
} else if (node["/session"]) {
unless(user) return 0; // what then?
if (!stringp(id))
id = "";
emit(sprintf("<iq type='result' id='%s' from='%s'/>",
id, SERVER_HOST));
emit("<iq type='result' id='"+ id +"' from='"
SERVER_HOST "'/>");
user -> vSet("language", language);
return morph();
}
switch (node["/query"]["@xmlns"]) {
// old-school style.. for clients that don't like SASL, like kopete
// old-school style.. for clients that don't like SASL, like kopete, jabbin
case "jabber:iq:auth":
tag = id;
authtag = id;
if (node["@type"] == "get"){
// hello(nick) ?
w("_query_password", 0,
([ "_nick": nick, "_tag_reply": tag ]), "");
([ "_nick": nick, "_tag_reply": authtag || "" ]), "");
} else if (node["@type"] == "set") {
helper = node["/query"];
resource = helper["/resource"][Cdata];
@ -182,10 +189,11 @@ jabberMsg(XMLNode node) {
case "jabber:iq:register":
if (node["@type"] == "get"){
string packet;
#ifdef REGISTERED_USERS_ONLY
#if defined(REGISTERED_USERS_ONLY) || defined(_flag_disable_registration_XMPP)
// super dirty.. this should all be in textdb
packet = sprintf("<iq type='result' id='%s'>"
"<query xmlns='jabber:iq:register'/>"
"<error code='501>No way!</error>" IQ_OFF,
"<error code='501>Registration by XMPP not permitted.</error>" IQ_OFF,
id);
#else
packet = sprintf("<iq type='result' id='%s'>"
@ -228,6 +236,9 @@ jabberMsg(XMLNode node) {
emit(packet);
QUIT
} else {
#if defined(REGISTERED_USERS_ONLY) || defined(_flag_disable_registration_XMPP)
// TODO: generate some error as above
#else
user -> vSet("password", t[Cdata]);
if (t = helper["/email"]) {
user -> vSet("email", helper["/email"]);
@ -235,6 +246,7 @@ jabberMsg(XMLNode node) {
// maybe immediate save is not really a good idea
// user -> save();
emit(sprintf("<iq type='result' id='%s'/>", id));
#endif
}
user = 0;
}
@ -243,15 +255,14 @@ jabberMsg(XMLNode node) {
case "starttls":
#if __EFUN_DEFINED__(tls_available)
if (tls_available()) {
emit("<proceed xmlns='" NS_XMPP "xmpp-tls'/>");
emitraw("<proceed xmlns='" NS_XMPP "xmpp-tls'/>");
// we may not write until tls_logon is called!
tls_init_connection(ME, #'tls_logon);
} else {
P1(("%O received a 'starttls' but TLS isn't available.\n", ME))
}
#else
emit("<failure xmlns='" NS_XMPP "xmpp-tls'/>");
emit("</stream:stream>");
emitraw("<failure xmlns='" NS_XMPP "xmpp-tls'/></stream:stream>");
destruct(ME);
#endif
break;
@ -282,7 +293,7 @@ jabberMsg(XMLNode node) {
{
if (result) {
sasluser = creds[1];
emit("<success xmlns='" NS_XMPP "xmpp-sasl'/>");
emitraw("<success xmlns='" NS_XMPP "xmpp-sasl'/>");
} else {
sasluser = 0;
SASL_ERROR("temporary-auth-failure")
@ -294,7 +305,7 @@ jabberMsg(XMLNode node) {
#else
&& user -> checkPassword(creds[2], "plain")) {
sasluser = creds[1];
emit("<success xmlns='" NS_XMPP "xmpp-sasl'/>");
emitraw("<success xmlns='" NS_XMPP "xmpp-sasl'/>");
#endif
} else {
SASL_ERROR("invalid-mechanism")
@ -312,8 +323,8 @@ jabberMsg(XMLNode node) {
unless (node[Cdata]) {
SASL_ERROR("incorrect-encoding")
QUIT
} else unless (mappingp(cert) && cert[0] == 0
&& cert["1.2.840.113549.1.9.1"]) {
} else unless (mappingp(certinfo) && certinfo[0] == 0
&& certinfo["1.2.840.113549.1.9.1"]) {
SASL_ERROR("invalid-mechanism")
QUIT
} else {
@ -322,7 +333,7 @@ jabberMsg(XMLNode node) {
// incorrect-encoding sasl error
deco = to_string(decode_base64(node[Cdata]));
// TODO: the right thingie could be a list!
unless (deco == cert["1.2.840.113549.1.9.1"]) {
unless (deco == certinfo["1.2.840.113549.1.9.1"]) {
// TODO: not sure about this one
SASL_ERROR("invalid-mechanism")
QUIT
@ -340,7 +351,7 @@ jabberMsg(XMLNode node) {
} else {
user = find_person(u) || createUser(u);
sasluser = u;
emit("<success xmlns='" NS_XMPP "xmpp-sasl'/>");
emitraw("<success xmlns='" NS_XMPP "xmpp-sasl'/>");
}
}
# else
@ -377,7 +388,7 @@ jabberMsg(XMLNode node) {
QUIT
}
sasluser = u;
emit("<success xmlns='" NS_XMPP "xmpp-sasl'/>");
emitraw("<success xmlns='" NS_XMPP "xmpp-sasl'/>");
}
break;
#endif
@ -402,11 +413,12 @@ jabberMsg(XMLNode node) {
+ encode_base64("rspauth=" + result) +
"</success>");
} else {
PT(("digest md5 failure\n"))
P0(("digest md5 failure: %O\n", creds))
sasluser = 0;
SASL_ERROR("invalid-authzid")
SASL_ERROR("invalid-authzid") // why do we get here?
QUIT
}
return 0; // ignored, but avoids a warning
});
user = find_person(creds["username"]) || createUser(creds["username"]);
@ -422,7 +434,7 @@ jabberMsg(XMLNode node) {
* wie auch immer haetten wir sonst mittlerweile net/queue fuer
* diesen job
*/
P2(("jabber/server:jabberMsg default case\n"))
P0(("jabber/server:jabberMsg default case\n"))
}
// return ::jabberMsg(from, cmd, args, data, all);
return 0;
@ -467,7 +479,7 @@ open_stream(XMLNode node) {
} else {
features += "<mechanisms xmlns='" NS_XMPP "xmpp-sasl'>"
#if __VERSION_MINOR__ > 3 || __VERSION_MICRO__ > 610
#ifndef _flag_disable_authentication_digest_MD5
"<mechanism>DIGEST-MD5</mechanism>"
#endif
"<mechanism>PLAIN</mechanism>";
@ -477,8 +489,8 @@ open_stream(XMLNode node) {
#endif
#if __EFUN_DEFINED__(tls_available)
if (tls_available() && tls_query_connection_state(ME) > 0
&& mappingp(cert) && cert[0] == 0
&& certificate_check_jabbername(0, cert)) {
&& mappingp(certinfo) && certinfo[0] == 0
&& certificate_check_jabbername(0, certinfo)) {
features += "<mechanism>EXTERNAL</mechanism>";
}
#endif
@ -496,7 +508,7 @@ open_stream(XMLNode node) {
// overrides certificate_check_jabbername from common.c with a function
// that is approproate for authenticating users
certificate_check_jabbername(name, cert) {
certificate_check_jabbername(name, certinfo) {
// plan: prefer subjectAltName:id-on-xmppAddr,
// but allow email (1.2.840.113549.1.9.1)
// and subjectAltName:rfc822Name

View file

@ -1,4 +1,4 @@
// $Id: user.c,v 1.293 2008/04/15 19:18:12 lynx Exp $ // vim:syntax=lpc:ts=8
// $Id: user.c,v 1.303 2008/09/12 15:54:39 lynx Exp $ // vim:syntax=lpc:ts=8
#include "jabber.h"
#include "user.h"
#include "person.h"
@ -6,9 +6,9 @@
#include <peers.h>
// important to #include user.h first
// then we also repatch JABBER_HOST so disco.c does the right thing for us
#undef JABBER_HOST
#define JABBER_HOST SERVER_HOST
// then we also repatch _host_XMPP so disco.c does the right thing for us
#undef _host_XMPP
#define _host_XMPP SERVER_HOST
volatile string prefix; // used anywhere?
volatile string tag;
@ -42,6 +42,7 @@ msg(source, mc, data, mapping vars, showingLog) {
int ret;
string jid, buddy;
string packet;
mixed t;
P2(("%s beim jabber:user:msg\n", mc))
// net/group/master says we should copy vars if we need to
@ -124,11 +125,25 @@ msg(source, mc, data, mapping vars, showingLog) {
mc = "_notice_place_leave";
}
switch (mc) {
#ifndef EXPERIMENTAL
case "_status_person_present":
case "_status_person_present_implied":
case "_status_person_absent":
case "_status_person_absent_recorded":
return;
#endif
PT(("%O got %O\n", ME, mc))
// actually.. we never send _time_idle with this
if (member(vars, "_time_idle")) {
t = vars["_time_idle"];
if (stringp(t)) {
t = to_int(t);
PT(("_time_idle %O == %O, right?\n", vars["_time_idle"], t))
}
t = gmtime(time() - t);
vars["_INTERNAL_time_jabber"] = JABBERTIME(t);
} else {
vars["_INTERNAL_time_jabber"] = JABBERTIME(gmtime(time()));
}
break;
case "_notice_friendship_established":
// TODO:
// it should be checked that this request is valid
@ -270,7 +285,7 @@ presence(XMLNode node) {
if (!isplacemsg && getchild(node, "x", "http://jabber.org/protocol/muc#user")) {
isplacemsg = 2;
}
/* directed presence */
#ifndef _flag_disable_presence_directed_XMPP
if (node["@to"]) {
target = jid2unl(node["@to"]);
if (isplacemsg) {
@ -279,54 +294,56 @@ presence(XMLNode node) {
if (node["@type"] == "unavailable") {
P2(("requesting to leave %O\n", target))
placeRequest(target,
#ifdef SPEC
# ifdef SPEC
"_request_context_leave"
#else
# else
"_request_leave"
#endif
# endif
, 1);
place = 0; // should we do it when we receive the notice?
// anyway, w/out this we show up as still being
// in that room in /p
} else {
#ifdef ENTER_MEMBERS
# ifdef ENTER_MEMBERS
// TODO: this might be needed and should work for remote rooms
// doing it in local rooms is a bad idea
if (is_formal(target))
placeRequest(target,
# ifdef SPEC
# ifdef SPEC
"_request_context_enter"
# else
# else
"_request_enter"
# endif
# endif
"_again", 0, 1, ([
"_nick" : MYNICK,
"_nick_local" : u[UResource]
]));
else
placeRequest(target,
# ifdef SPEC
# ifdef SPEC
"_request_context_enter"
# else
# else
"_request_enter"
# endif
# endif
"_again", 0, 1);
#else
# else
P2(("teleporting to %O\n", target))
teleport(target, "_join", 0, 1);
#endif
# endif
}
# ifndef _flag_disable_module_friendship
} else if (node["@type"] == "subscribe") {
// was: friend(({ jid2unl(node["@to"]) }), 0);
friend(0, jid2unl(node["@to"]));
} else if (node["@type"] == "unsubscribe") {
friend(1, jid2unl(node["@to"]));
# endif // _flag_disable_module_friendship
} else if (abbrev(XMPP, target)) {
// if the person is not on our buddylist,
// this is usually a muc join
// but i am not sure if there are other uses of
// presence in jabber
#ifdef JABBER_TRANSPARENCY
# ifdef JABBER_TRANSPARENCY
mapping vars = ([ "_nick" : MYNICK ]);
mixed *u = parse_uniform(XMPP + node["@to"]);
P3(("jtranz presence to %O\n", target))
@ -339,7 +356,7 @@ presence(XMLNode node) {
// unless(mappingp(presence_out)) presence_out = ([ ]);
vars["_jabber_XML"] = innerxml;
// TODO: wir fliegen wir mit JABBER_HOST auf die
// TODO: wir fliegen wir mit _host_XMPP auf die
// NASE.
// wir muessen die resource in die vars stecken...
vars["_INTERNAL_source_jabber"] = myjidresource;
@ -356,14 +373,15 @@ presence(XMLNode node) {
"[_nick] is sending you a jabber presence.",
vars);
}
#endif
# endif
} else {
// TODO: what can we do in this case?
// we can look at our buddylist, if target is a member
// then this is a directed presence
}
} /* end of directed presence handling */
#endif // _flag_disable_presence_directed_XMPP
#ifdef AVAILABILITY_AWAY
else if (node["/show"]) {
// else this is one of the so-called "presence broadcasts"
// we will never support stupid broadcasts although we could
@ -393,6 +411,7 @@ presence(XMLNode node) {
// TODO: quiet?
announce(AVAILABILITY_HERE);
}
#endif // AVAILABILITY_AWAY
}
@ -592,6 +611,7 @@ iq(XMLNode node) {
break;
}
break;
#if !defined(REGISTERED_USERS_ONLY) && !defined(_flag_disable_registration_XMPP)
case "jabber:iq:register":
switch(node["@type"]) {
case "get":
@ -632,6 +652,7 @@ iq(XMLNode node) {
case "error":
break;
}
#endif // jabber:iq:register
case "jabber:iq:roster":
switch(node["@type"]) {
case "get":
@ -716,8 +737,10 @@ iq(XMLNode node) {
helper = helper["/item"];
if (helper && helper["@subscription"] == "remove") {
string buddy = jid2unl(helper["@jid"]);
#ifndef _flag_disable_module_friendship
P2(("remove %O from roster\n", helper["@jid"]))
friend(1, buddy);
#endif
m_delete(xbuddylist, buddy);
emit(sprintf("<iq type='result' id='%s'/>", tag));
} else {
@ -806,11 +829,14 @@ iq(XMLNode node) {
}
break;
case "http://jabber.org/protocol/disco#items":
// send a list of rooms to the client
switch(node["@type"]) {
case "get":
if (!node["@to"])
// "my" places - let person.c handle this
sendmsg(ME, "_request_list_item", 0, vars);
else if (is_localhost(lower_case(node["@to"])))
// server's places - let root.c handle this
sendmsg("/", "_request_list_item", 0, vars);
/* else... TODO */
break;
@ -833,6 +859,9 @@ iq(XMLNode node) {
"<query xmlns='jabber:iq:private'>"
"<storage xmlns='storage:bookmarks'>",
tag);
// hey wait.. we are sending the list of places here..
// why is it i have never seen a jabber client actually
// executing autojoins? FIXME
if (v("subscriptions"))
foreach (string s in v("subscriptions")) {
string jid;
@ -1078,7 +1107,7 @@ string jid2unl(string jid) {
return node;
}
# if 1
else if (ISPLACEMSG(node)) {
else if (strlen(node) && ISPLACEMSG(node)) {
return "psyc://" + host + "/@" + PREFIXFREE(node);
}
# endif
@ -1199,12 +1228,17 @@ w(string mc, string data, mapping vars, mixed source) {
case "_notice_list_feature_place":
case "_notice_list_feature_server":
case "_notice_list_feature_newsfeed":
#ifndef _flag_disable_query_server
mixed id2jabber = shared_memory("disco_identity");
mixed feat2jabber = shared_memory("disco_features");
unless (mappingp(id2jabber)) return 1;
vars["_identity"] = id2jabber[vars["_identity"]] || vars["_identity"];
vars["_list_feature"] = implode(map(vars["_list_feature"],
(: return "<feature var='" + feat2jabber[$1] + "'/>"; :)), "");
(: return "<feature var='" + feat2jabber[$1] + "'/>"; :)), "");
break;
#else
return 1;
#endif
case "_notice_list_item":
t = "";
// same stuff in user.c (what happened to code sharing?)