diff options
-rw-r--r-- | jacc-paste.c | 757 | ||||
-rw-r--r-- | jacc.c | 820 | ||||
-rw-r--r-- | jacc.tar | bin | 0 -> 102400 bytes |
3 files changed, 1577 insertions, 0 deletions
diff --git a/jacc-paste.c b/jacc-paste.c new file mode 100644 index 0000000..6874b93 --- /dev/null +++ b/jacc-paste.c @@ -0,0 +1,757 @@ +/* + * Copy me if you can. + * by 20h + */ + +#include <u.h> +#include <libc.h> +#include <auth.h> +#include <mp.h> +#include <libsec.h> +#include "xmlpull.h" +#include "jacc.h" +#include "dat.h" +#include "roster.h" +#include "recv.h" + +#define NAME "jacc - Jabber Client for Plan9" +#define VERSION "3rd ed" +#define OS "Plan 9 4th ed" + +extern int doignore; + +int +xmljacc(int sock) +{ + return fprint(sock, "<?xml version=\"1.0\"?>\n"); +} + +int +loginjacc(int sock, char *serv) +{ + return fprint(sock, "<stream:stream xmlns:stream=\"http://etherx.jabber.org/streams\"" + " xmlns=\"jabber:client\" to=\"%s\">\n", serv); +} + +int +userjacc(int sock, char *user, char *pass, char *res) +{ + return fprint(sock, "<iq type=\"set\" id=\"auth_1\">\n" + "<query xmlns=\"jabber:iq:auth\">\n" + "<username>%s</username>\n" + "<password>%s</password>\n" + "<resource>%s</resource>\n" + "</query>\n" + "</iq>\n", user, pass, res); +} + +int +versionjacc(int sock, char *from, char *to, char *id) +{ + return fprint(sock, "<iq from=\"%s\" type=\"result\" id=\"%s\" to=\"%s\">\n" + "<query xmlns=\"jabber:iq:version\">\n" + "<name>" NAME "</name>\n" + "<version>" VERSION "</version>\n" + "<os>" OS "</os>\n" + "</query>\n" + "</iq>\n", from, (id == nil) ? "" : id, to); +} + +int +featuresjacc(int sock, char *from, char *to, char *id) +{ + return fprint(sock, "<iq from=\"%s\" type=\"result\" to=\"%s\" id=\"%s\">\n" + "<query xmlns=\"http://jabber.org/protocol/disco#info\">\n" + "<identity category=\"client\" type=\"pc\"/>\n" + "<feature var=\"jabber:iq:time\"/>\n" + "<feature var=\"jabber:iq:version\"/>\n" + "<feature var=\"http://jabber.org/protocol/muc\"/>\n" + "</query>\n" + "</iq>\n", from, to, (id == nil) ? "" : id); +} + +int +timejacc(int sock, char *from, char *to, char *id) +{ + Tm *lo, *gm; + + lo = localtime(time(0)); + gm = gmtime(time(0)); + + return fprint(sock, "<iq from=\"%s\" type=\"result\" to=\"%s\" id=\"%s\">\n" + "<query xmlns=\"jabber:iq:time\">\n" + "<utc>%.4d%.2d%.2dT%.2d:%.2d:%.2d</utc>\n" + "<display>%s %s %.2d %.2d:%.2d:%.2d %.4d</display>\n" + "<tz>%s</tz>\n" + "</query>\n" + "</iq>\n", from, to, (id == nil) ? "" : id, gm->year + 1900, + gm->mon + 1, gm->mday, gm->hour, gm->min, + gm->sec, getday(lo->wday), getmonth(lo->mon), + lo->mday, lo->hour, lo->min, lo->sec, + lo->year + 1900, lo->zone); +} + +int +lastjacc(int sock, char *from, char *to, char *id, int d) +{ + return fprint(sock, "<iq from=\"%s\" type=\"result\" to=\"%s\" id=\"%s\">\n" + "<query xmlns=\"jabber:iq:last\" seconds=\"%d\"/>\n" + "</iq>\n", from, to, (id == nil) ? "" : id, d); +} + +int +registerjacc(int sock, char *serv, char *user, char *pass) +{ + return fprint(sock, "<iq type=\"set\" id=\"req\" to=\"%s\">\n" + "<query xmlns=\"jabber:iq:register\">\n" + "<username>%s</username>\n" + "<password>%s</password>\n" + "</query>\n" + "</iq>\n", serv, user, pass); +} + +int +vcardgetjacc(int sock, char *from, char *type) +{ + return fprint(sock, "<iq %s=\"%s\" type=\"get\" id=\"v1\">\n" + "<vCard xmlns=\"vcard-temp\"/>\n" + "</iq>\n", type, from); +} + +int +vcardsetjacc(int sock, char *from, int fd) +{ + fprint(sock, "<iq from=\"%s\" type=\"set\" id=\"v2\">\n" + "<vCard xmlns=\"vcard-temp\">\n", from); + readwrite(sock, fd); + + return fprint(sock, "</vCard>\n" + "</iq>\n"); +} + +int +presencejacc(int sock, char *stat, char *show, char *from, char *to) +{ + return fprint(sock, "<presence%s%s%s%s%s%s>\n" + "<show>%s</show>\n" + "<status>%s</status>\n" + "<priority>9</priority>\n" + "</presence>\n", (from != nil) ? " from=\"" : "", + (from != nil) ? from : "", + (from != nil) ? "\"" : "", + (to != nil) ? " to=\"" : "", + (to != nil) ? to : "", + (to != nil) ? "\"" : "", + (show != nil) ? show : "", + (stat != nil) ? stat : ""); +} + +int +presencetypejacc(int sock, char *from, char *to, char *type) +{ + return fprint(sock, "<presence type=\"%s\" from=\"%s\" to=\"%s\"/>\n", + type, from, to); +} + +int +rosterjacc(int sock) +{ + return fprint(sock, "<iq type=\"get\" id=\"auth_2\">\n" + "<query xmlns=\"jabber:iq:roster\"/>\n" + "</iq>\n"); +} + +int +messagejacc(int sock, char *from, char *to, char *msg, char *type) +{ + return fprint(sock, "<message from=\"%s\" to=\"%s\" type=\"%s\">\n" + "<body>%s</body>\n" + "</message>\n", from, to, type, msg); +} + +int +addbuddyjacc(int sock, char *jid, char *na, char *group) +{ + if(na == nil){ + na = jid; + jid = strchr(na, '@'); + + if(jid == nil) + return -1; + *jid++ = '\0'; + + return fprint(sock, "<iq type=\"set\">\n" + "<query xmlns=\"jabber:iq:roster\">\n" + "<item jid=\"%s@%s\" name=\"%s\"/>\n" + "%s%s%s" + "</query>\n" + "</iq>\n", na, jid, na, + (group != nil) ? "<group>" : "", + (group != nil) ? group : "", + (group != nil) ? "</group>\n" : ""); + } + + return fprint(sock, "<iq type=\"set\">\n" + "<query xmlns=\"jabber:iq:roster\">\n" + "<item jid=\"%s\" name=\"%s\"/>\n" + "%s%s%s" + "</query>\n" + "</iq>\n", jid, na, + (group != nil) ? "<group>" : "", + (group != nil) ? group : "", + (group != nil) ? "</group>\n" : ""); +} + +int +delbuddyjacc(int sock, char *jid) +{ + return fprint(sock, "<iq type=\"set\">\n" + "<query xmlns=\"jabber:iq:roster\">\n" + "<item jid=\"%s\" subscription=\"remove\"/>\n" + "</query>\n" + "</iq>\n", jid); +} + +int +xmlnsjacc(int sock, char *who, char *t, char *id) +{ + return fprint(sock, "<iq type=\"get\" to=\"%s\" id=\"%s\">\n" + "<query xmlns=\"%s\"/>\n" + "</iq>\n", who, id, t); +} + +void +printrostern(rostern *r, char *w) +{ + char *tmstmp; + + tmstmp = mktmstmp('(', ')'); + while(r != nil){ + if(w != nil){ + if(r->status != nil) + if(!strcmp(r->status, w)) + goto got_one; + if(r->name != nil) + if(!strcmp(r->name, w)) + goto got_one; + if(r->jid != nil) + if(!strcmp(r->jid, w)) + goto got_one; + if(r->show != nil) + if(!strcmp(r->show, w)) + goto got_one; + if(r->group != nil) + if(!strcmp(r->group, w)) + goto got_one; + } else { +got_one: + print("%s%s/%s on %s -> %s/%s\n", tmstmp, r->name, r->jid, r->group, r->show, r->status); + } + + r = r->n; + } + + return; +} + +void +usage(void) +{ + print("usage: [-dgit] [-r res] [-s tosrv] [net!]server[!port]\n"); + exits(0); +} + +void admin (int sock, char *id, char *room, char *item) +{ + fprint(sock, "<iq id=\"%s\" to=\"%s\" type=\"set\"><query xmlns=\"http://jabber.org/protocol/muc#admin\"><item %s /></query></iq>", id, room, item); +} + + + +int +main(int argc, char *argv[]) +{ + char *server, *user, *lbl, *b, *tmstmp, *buf, *toserver, *role, *tmp; + int sock, ts, reg, debug, tls; + UserPasswd *i; + TLSconn conn; + jabberc *me; + + tls = 0; + b = nil; + reg = 0; + debug = 0; + toserver = nil; + + ARGBEGIN { + case 't': + tls = 1; + break; + case 'r': + b = EARGF(usage()); + break; + case 'g': + reg = 1; + break; + case 'd': + debug = 1; + break; + case 'i': + doignore = 1; + break; + case 's': + toserver = EARGF(usage()); + break; + default: + usage(); + } ARGEND; + + if(argc < 1) + usage(); + server = strdup(argv[0]); + + lbl = getwindowlbl(); + user = reallocj(nil, strlen(server) + 9, 2); + snprint(user, strlen(server) + 8, "jacc - %s", server); + setwindowlbl(user); + free(user); + + i = auth_getuserpasswd(auth_getkey, "proto=pass server=%s service=jabber", server); + if(i == nil) + sysfatal("auth_getuserpasswd: %r"); + + sock = dial(netmkaddr(server, "tcp", tls ? "5223" : "5222"), 0, 0, 0); + if(sock < 0) + sysfatal("dial: %r"); + + if(tls){ + ts = tlsClient(sock, &conn); + if(ts < 0) + sysfatal("tlsClient: %r"); + sock = ts; + + if(conn.cert != nil) + free(conn.cert); + } + + buf = strchr(server, '!'); + if(buf != nil) { + *buf++ = '\0'; + user = strchr(buf, '!'); + if(user != nil) + *user = '\0'; + user = strdup(buf); + free(server); + server = user; + } + + if(toserver == nil) + toserver = server; + + me = mkjabberc(); + me->show = strdup("Online"); + me->stat = strdup("Online"); + me->name = strdup(i->user); + me->serv = strdup(toserver); + + if(b != nil) + me->reso = strdup(b); + else + me->reso = strdup("Plan9"); + me->jid = printjid(me->name, me->serv, me->reso); + me->debug = debug; + me->reg = reg; + me->last = time(0); + + free(server); + + ts = getpid(); + +#ifdef PLAN9PORT + switch(fork()) { +#endif +#ifndef PLAN9PORT + switch(rfork(RFPROC|RFFDG|RFMEM)) { +#endif + case -1: + sysfatal("fork: %r"); + case 0: + if(recvjacc(sock, me, i->passwd) < 0) + perror("recvjacc"); + + if(lbl != nil){ + setwindowlbl(lbl); + lbl = nil; + free(lbl); + } + killproc(ts); + exits(0); + default: + user = reallocj(nil, 1025, 2); + buf = nil; + while(sock > 0 && user != nil){ + ts = -1; + memset(user, 0, 1025); + + while(read(0, &user[++ts], 1) && ts < 1024 && sock > 0) + if(user[ts] == '\n') + break; + user[ts] = '\0'; + me->last = time(0); + + tmstmp = mktmstmp('(', ')'); + if(user[0] != '/'){ + if(buf != nil){ + b = filterhin(user, 0); + messagejacc(sock, me->jid, buf, b, "chat"); + print("%s\n", tmstmp); + free(b); + } + free(tmstmp); + continue; + } + if (user[1] == 'x'){ + b = getarg(user, 1, 0); + if(b != nil){ + if (strcmp(b, "join") == 0){ + free(b); + + server = getarg(user, 2, 0); + + if(server != nil){ + b = getarg(user, 3, 0); + if(b == nil) + b = strdup(me->name); + + fprint(sock, "<presence to=\"%s/%s\"/>", server, b); + free (server); + free(b); + } + } + else + if (strcmp(b, "leave") == 0){ + free(b); + server = getarg(user, 2, 0); + if(server != nil) { + fprint(sock, + "<presence to='%s' type='unavailable'/>", server); + free (server); + } + + } + else + if (strcmp(b, "say") == 0){ + free(b); + server = getarg(user, 2, 0); + if(server != nil){ + b = getarg(user, 3, 2); + if(b != nil){ + messagejacc(sock, + me->jid, server, b, "groupchat"); + free(b); + } + free(server); + } + } + else + if (strcmp(b, "priv") == 0){ + free(b); + server = getarg(user, 2, 0); + if(server != nil){ + role = getarg(user, 3, 0); + if(role != nil){ + b = getarg(user, 4, 2); + if(b != nil){ + tmp = server; + server = smprint("%s/%s", server, role); + free(tmp); + + messagejacc(sock, + me->jid, server, b, "chat"); + free(b); + } + free(role); + } + free(server); + } + } + else + if (strcmp(b, "role") == 0){ + free(b); + server = getarg(user, 2, 0); + if(server != nil){ + role = getarg(user, 3, 0); + if(role != nil){ + b = getarg(user, 4, 2); + if(b != nil){ + tmp = b; + b = smprint("nick='%s' role='%s'", b, role); + free(tmp); + + admin(sock, role, server, b); + free(b); + } + free(role); + } + free(server); + } + } + else + if (strcmp(b, "affil") == 0){ + free(b); + server = getarg(user, 2, 0); + if(server != nil){ + role = getarg(user, 3, 0); + if(role != nil){ + b = getarg(user, 4, 2); + if(b != nil){ + tmp = b; + b = smprint("jid='%s' affiliation='%s'", b, role); + free(tmp); + + admin(sock, role, server, b); + free(b); + } + free(role); + } + free(server); + } + } + else + free(b); + } + } + else + switch(user[1]){ + case 'h': + case 'H': + print("%sHelp for jacc:\n", tmstmp); + print("%s /a [+|-|*]jid - authenticate jid\n", tmstmp); + print("%s /b - turn debugging on or off\n", tmstmp); + print("%s /c file - set vcard on server\n", tmstmp); + print("%s /d jid [feat] - do a discovery request\n", tmstmp); + print("%s /e jid - get time from jid\n", tmstmp); + print("%s /g jid - get agents information from jid\n", tmstmp); + print("%s /h - print out this help\n", tmstmp); + print("%s /i jid - get version of jid\n", tmstmp); + print("%s /l [status|jid|user] - list the roster\n", tmstmp); + print("%s /m jid - send a message to jid\n", tmstmp); + print("%s /p [show] [status] - set status and show\n", tmstmp); + print("%s /q - quit jacc\n", tmstmp); + print("%s /s [jid] - set active jid\n", tmstmp); + print("%s /t jid - get idle time of jid\n",tmstmp); + print("%s /u [+|-]jid [alias] - manage roster\n", tmstmp); + print("%s /v [jid] - get vcard from jid\n", tmstmp); + + print("%s /x command - operate with groupchat\n", tmstmp); + print("%s commands:\n", tmstmp); + print("%s groupchat - leave groupchat\n", tmstmp); + print("%s join groupchat [nick] - join to the groupchat\n", tmstmp); +// print("%s names groupchat - occupants' list\n", tmstmp); + print("%s say groupchat - send a message to groupchat\n", tmstmp); + print("%s priv groupchat nick - send a private message to occupant\n", tmstmp); + print("%s leave groupchat - leave groupchat\n", tmstmp); + print("%s affil groupchat affilation jid - set affilation\n", tmstmp); + print("%s role groupchat role nick - set role\n", tmstmp); + break; + + case 'q': + case 'Q': + fprint(sock, "<presence from=\"%s\" type=\"unavailable\"/>", + me->jid); + fprint(sock, "</stream:stream>"); + free(user); + user = nil; + break; + case 's': + case 'S': + server = getarg(user, 1, 0); + if(server == nil){ + print("%s%s\n", tmstmp, (buf != nil) ? buf : "<nil>"); + break; + } + + buf = setchan(buf, namerostern(me->rost, nil, server)); + free(server); + break; + case 'l': + case 'L': + server = getarg(user, 1, 0); + + printrostern(me->rost, server); + + if(server != nil) + free(server); + break; + case 'm': + case 'M': + server = getarg(user, 1, 0); + if(server != nil){ + + b = getarg(user, 2, 2); + if(b != nil){ + messagejacc(sock, me->jid, namerostern(me->rost, nil, server), b, "normal"); + free(b); + } + + free(server); + } + break; + case 'p': + case 'P': + server = getarg(user, 1, 0); + if(server == nil){ + print("%s%s\n", tmstmp, me->stat); + break; + } + + b = getarg(user, 2, 2); + if(b != nil){ + presencejacc(sock, b, server, nil, nil); + free(me->stat); + me->stat = strdup(b); + } else + presencejacc(sock, nil, server, nil, nil); + free(me->show); + me->show = strdup(server); + statusrostern(me->rost, me->jid, me->jid, server, b); + free(server); + break; + case 'c': + case 'C': + server = getarg(user, 1, 0); + if(server != nil){ + ts = open(server, OREAD); + if(ts >= 0){ + vcardsetjacc(sock, me->jid, ts); + close(ts); + } + free(server); + } + break; + case 'v': + case 'V': + server = getarg(user, 1, 0); + if(server == nil){ + vcardgetjacc(sock, me->jid, "from"); + break; + } + + vcardgetjacc(sock, namerostern(me->rost, nil, server), "to"); + print("Vcard of: %s\n", namerostern(me->rost, nil, server)); + free(server); + break; + case 'u': + case 'U': + server = getarg(user, 1, 0); + if(server != nil){ + if(server[0] == '-') + delbuddyjacc(sock, namerostern(me->rost, server + 1, server + 1)); + else { + b = getarg(user, 2, 0); + if(server[0] == '+') + addbuddyjacc(sock, server + 1, b, nil); + else + addbuddyjacc(sock, server, b, nil); + } + free(server); + } + break; + case 'a': + case 'A': + server = getarg(user, 1, 0); + if(server != nil){ + switch(server[0]){ + case '+': + presencetypejacc(sock, me->jid, namerostern(me->rost, nil, server + 1), "subscribed"); + break; + case '-': + presencetypejacc(sock, me->jid, namerostern(me->rost, nil, server + 1), "unsubscribe"); + break; + case '*': + presencetypejacc(sock, me->jid, namerostern(me->rost, nil, server + 1), "subscribe"); + break; + default: + presencetypejacc(sock, me->jid, namerostern(me->rost, nil, server), "subscribed"); + break; + } + free(server); + } + break; + case 'd': + case 'D': + server = getarg(user, 1, 0); + if(server != nil){ + b = getarg(user, 2, 2); + if(b == nil) + b = strdup("info"); + + free(tmstmp); + tmstmp = reallocj(nil, 35 + strlen(b), 2); + sprint(tmstmp, "http://jabber.org/protocol/disco#%s", b); + + xmlnsjacc(sock, server, tmstmp, "disco0"); + free(b); + free(server); + } + break; + case 'b': + case 'B': + if(me->debug == 0) + me->debug = 1; + else + me->debug = 0; + print("%sDebug: %c\n", tmstmp, me->debug); + break; + case 't': + case 'T': + server = getarg(user, 1, 0); + if(server != nil){ + xmlnsjacc(sock, namerostern(me->rost, nil, server), "jabber:iq:last", "last0"); + free(server); + } + break; + case 'i': + case 'I': + server = getarg(user, 1, 0); + if(server != nil){ + xmlnsjacc(sock, namerostern(me->rost, nil, server), "jabber:iq:version", "version0"); + free(server); + } + break; + case 'e': + case 'E': + server = getarg(user, 1, 0); + if(server != nil){ + xmlnsjacc(sock, namerostern(me->rost, nil, server), "jabber:iq:time", "time0"); + free(server); + } + break; + case 'g': + case 'G': + server = getarg(user, 1, 0); + if(server != nil){ + xmlnsjacc(sock, namerostern(me->rost, nil, server), "jabber:iq:agents", "agents0"); + free(server); + } + break; + + default: + break; + } + free(tmstmp); + } + + wait(); + if(lbl != nil){ + setwindowlbl(lbl); + lbl = nil; + free(lbl); + } + break; + } + + freejabberc(me); + exits(0); + return 0; +} @@ -0,0 +1,820 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" +"http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> +<meta http-equiv=Content-Type content="text/html; charset=utf8"> +<title>/n/sources/contrib/stassats/jacc.c - Plan 9 from Bell Labs</title> +<!-- THIS FILE IS AUTOMATICALLY GENERATED. --> +<!-- EDIT sources.tr INSTEAD. --> +</meta> +</head> +<body> +<p style="margin-top: 0; margin-bottom: 0.17in"></p> +<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;"> +<span style="font-size: 10pt"><a href="http://plan9.bell-labs.com/plan9/">Plan 9 from Bell Labs</a>’s /n/sources/contrib/stassats/jacc.c</span></p> +<p style="margin-top: 0; margin-bottom: 0.17in"></p> +<p style="margin-top: 0; margin-bottom: 0.17in"></p> +<center><font size=-1> +Copyright © 2009 Alcatel-Lucent.<br /> +Distributed under the +<a href="http://plan9.bell-labs.com/plan9/license.html">Lucent Public License version 1.02</a>. +<br /> +<a href="http://plan9.bell-labs.com/plan9/download.html">Download the Plan 9 distribution.</a> +</font> +</center> +<p style="margin-top: 0; margin-bottom: 0.17in"></p> +<table width="100%" cellspacing=0 border=0><tr><td align="center"> +<table cellspacing=0 cellpadding=5 bgcolor="#eeeeff"><tr><td align="left"> +<pre> +<!-- END HEADER --> +/* + * Copy me if you can. + * by 20h + */ + +#include <u.h> +#include <libc.h> +#include <auth.h> +#include <mp.h> +#include <libsec.h> +#include "xmlpull.h" +#include "jacc.h" +#include "dat.h" +#include "roster.h" +#include "recv.h" + +#define NAME "jacc - Jabber Client for Plan9" +#define VERSION "3rd ed" +#define OS "Plan 9 4th ed" + +extern int doignore; + +int +xmljacc(int sock) +{ + return fprint(sock, "<?xml version=\"1.0\"?>\n"); +} + +int +loginjacc(int sock, char *serv) +{ + return fprint(sock, "<stream:stream xmlns:stream=\"http://etherx.jabber.org/streams\"" + " xmlns=\"jabber:client\" to=\"%s\">\n", serv); +} + +int +userjacc(int sock, char *user, char *pass, char *res) +{ + return fprint(sock, "<iq type=\"set\" id=\"auth_1\">\n" + "<query xmlns=\"jabber:iq:auth\">\n" + "<username>%s</username>\n" + "<password>%s</password>\n" + "<resource>%s</resource>\n" + "</query>\n" + "</iq>\n", user, pass, res); +} + +int +versionjacc(int sock, char *from, char *to, char *id) +{ + return fprint(sock, "<iq from=\"%s\" type=\"result\" id=\"%s\" to=\"%s\">\n" + "<query xmlns=\"jabber:iq:version\">\n" + "<name>" NAME "</name>\n" + "<version>" VERSION "</version>\n" + "<os>" OS "</os>\n" + "</query>\n" + "</iq>\n", from, (id == nil) ? "" : id, to); +} + +int +featuresjacc(int sock, char *from, char *to, char *id) +{ + return fprint(sock, "<iq from=\"%s\" type=\"result\" to=\"%s\" id=\"%s\">\n" + "<query xmlns=\"http://jabber.org/protocol/disco#info\">\n" + "<identity category=\"client\" type=\"pc\"/>\n" + "<feature var=\"jabber:iq:time\"/>\n" + "<feature var=\"jabber:iq:version\"/>\n" + "<feature var=\"http://jabber.org/protocol/muc\"/>\n" + "</query>\n" + "</iq>\n", from, to, (id == nil) ? "" : id); +} + +int +timejacc(int sock, char *from, char *to, char *id) +{ + Tm *lo, *gm; + + lo = localtime(time(0)); + gm = gmtime(time(0)); + + return fprint(sock, "<iq from=\"%s\" type=\"result\" to=\"%s\" id=\"%s\">\n" + "<query xmlns=\"jabber:iq:time\">\n" + "<utc>%.4d%.2d%.2dT%.2d:%.2d:%.2d</utc>\n" + "<display>%s %s %.2d %.2d:%.2d:%.2d %.4d</display>\n" + "<tz>%s</tz>\n" + "</query>\n" + "</iq>\n", from, to, (id == nil) ? "" : id, gm->year + 1900, + gm->mon + 1, gm->mday, gm->hour, gm->min, + gm->sec, getday(lo->wday), getmonth(lo->mon), + lo->mday, lo->hour, lo->min, lo->sec, + lo->year + 1900, lo->zone); +} + +int +lastjacc(int sock, char *from, char *to, char *id, int d) +{ + return fprint(sock, "<iq from=\"%s\" type=\"result\" to=\"%s\" id=\"%s\">\n" + "<query xmlns=\"jabber:iq:last\" seconds=\"%d\"/>\n" + "</iq>\n", from, to, (id == nil) ? "" : id, d); +} + +int +registerjacc(int sock, char *serv, char *user, char *pass) +{ + return fprint(sock, "<iq type=\"set\" id=\"req\" to=\"%s\">\n" + "<query xmlns=\"jabber:iq:register\">\n" + "<username>%s</username>\n" + "<password>%s</password>\n" + "</query>\n" + "</iq>\n", serv, user, pass); +} + +int +vcardgetjacc(int sock, char *from, char *type) +{ + return fprint(sock, "<iq %s=\"%s\" type=\"get\" id=\"v1\">\n" + "<vCard xmlns=\"vcard-temp\"/>\n" + "</iq>\n", type, from); +} + +int +vcardsetjacc(int sock, char *from, int fd) +{ + fprint(sock, "<iq from=\"%s\" type=\"set\" id=\"v2\">\n" + "<vCard xmlns=\"vcard-temp\">\n", from); + readwrite(sock, fd); + + return fprint(sock, "</vCard>\n" + "</iq>\n"); +} + +int +presencejacc(int sock, char *stat, char *show, char *from, char *to) +{ + return fprint(sock, "<presence%s%s%s%s%s%s>\n" + "<show>%s</show>\n" + "<status>%s</status>\n" + "<priority>9</priority>\n" + "</presence>\n", (from != nil) ? " from=\"" : "", + (from != nil) ? from : "", + (from != nil) ? "\"" : "", + (to != nil) ? " to=\"" : "", + (to != nil) ? to : "", + (to != nil) ? "\"" : "", + (show != nil) ? show : "", + (stat != nil) ? stat : ""); +} + +int +presencetypejacc(int sock, char *from, char *to, char *type) +{ + return fprint(sock, "<presence type=\"%s\" from=\"%s\" to=\"%s\"/>\n", + type, from, to); +} + +int +rosterjacc(int sock) +{ + return fprint(sock, "<iq type=\"get\" id=\"auth_2\">\n" + "<query xmlns=\"jabber:iq:roster\"/>\n" + "</iq>\n"); +} + +int +messagejacc(int sock, char *from, char *to, char *msg, char *type) +{ + return fprint(sock, "<message from=\"%s\" to=\"%s\" type=\"%s\">\n" + "<body>%s</body>\n" + "</message>\n", from, to, type, msg); +} + +int +addbuddyjacc(int sock, char *jid, char *na, char *group) +{ + if(na == nil){ + na = jid; + jid = strchr(na, '@'); + + if(jid == nil) + return -1; + *jid++ = '\0'; + + return fprint(sock, "<iq type=\"set\">\n" + "<query xmlns=\"jabber:iq:roster\">\n" + "<item jid=\"%s@%s\" name=\"%s\"/>\n" + "%s%s%s" + "</query>\n" + "</iq>\n", na, jid, na, + (group != nil) ? "<group>" : "", + (group != nil) ? group : "", + (group != nil) ? "</group>\n" : ""); + } + + return fprint(sock, "<iq type=\"set\">\n" + "<query xmlns=\"jabber:iq:roster\">\n" + "<item jid=\"%s\" name=\"%s\"/>\n" + "%s%s%s" + "</query>\n" + "</iq>\n", jid, na, + (group != nil) ? "<group>" : "", + (group != nil) ? group : "", + (group != nil) ? "</group>\n" : ""); +} + +int +delbuddyjacc(int sock, char *jid) +{ + return fprint(sock, "<iq type=\"set\">\n" + "<query xmlns=\"jabber:iq:roster\">\n" + "<item jid=\"%s\" subscription=\"remove\"/>\n" + "</query>\n" + "</iq>\n", jid); +} + +int +xmlnsjacc(int sock, char *who, char *t, char *id) +{ + return fprint(sock, "<iq type=\"get\" to=\"%s\" id=\"%s\">\n" + "<query xmlns=\"%s\"/>\n" + "</iq>\n", who, id, t); +} + +void +printrostern(rostern *r, char *w) +{ + char *tmstmp; + + tmstmp = mktmstmp('(', ')'); + while(r != nil){ + if(w != nil){ + if(r->status != nil) + if(!strcmp(r->status, w)) + goto got_one; + if(r->name != nil) + if(!strcmp(r->name, w)) + goto got_one; + if(r->jid != nil) + if(!strcmp(r->jid, w)) + goto got_one; + if(r->show != nil) + if(!strcmp(r->show, w)) + goto got_one; + if(r->group != nil) + if(!strcmp(r->group, w)) + goto got_one; + } else { +got_one: + print("%s%s/%s on %s -> %s/%s\n", tmstmp, r->name, r->jid, r->group, r->show, r->status); + } + + r = r->n; + } + + return; +} + +void +usage(void) +{ + print("usage: [-dgit] [-r res] [-s tosrv] [net!]server[!port]\n"); + exits(0); +} + +void admin (int sock, char *id, char *room, char *item) +{ + fprint(sock, "<iq id=\"%s\" to=\"%s\" type=\"set\"><query xmlns=\"http://jabber.org/protocol/muc#admin\"><item %s /></query></iq>", id, room, item); +} + + + +int +main(int argc, char *argv[]) +{ + char *server, *user, *lbl, *b, *tmstmp, *buf, *toserver, *role, *tmp; + int sock, ts, reg, debug, tls; + UserPasswd *i; + TLSconn conn; + jabberc *me; + + tls = 0; + b = nil; + reg = 0; + debug = 0; + toserver = nil; + + ARGBEGIN { + case 't': + tls = 1; + break; + case 'r': + b = EARGF(usage()); + break; + case 'g': + reg = 1; + break; + case 'd': + debug = 1; + break; + case 'i': + doignore = 1; + break; + case 's': + toserver = EARGF(usage()); + break; + default: + usage(); + } ARGEND; + + if(argc < 1) + usage(); + server = strdup(argv[0]); + + lbl = getwindowlbl(); + user = reallocj(nil, strlen(server) + 9, 2); + snprint(user, strlen(server) + 8, "jacc - %s", server); + setwindowlbl(user); + free(user); + + i = auth_getuserpasswd(auth_getkey, "proto=pass server=%s service=jabber", server); + if(i == nil) + sysfatal("auth_getuserpasswd: %r"); + + sock = dial(netmkaddr(server, "tcp", tls ? "5223" : "5222"), 0, 0, 0); + if(sock < 0) + sysfatal("dial: %r"); + + if(tls){ + ts = tlsClient(sock, &conn); + if(ts < 0) + sysfatal("tlsClient: %r"); + sock = ts; + + if(conn.cert != nil) + free(conn.cert); + } + + buf = strchr(server, '!'); + if(buf != nil) { + *buf++ = '\0'; + user = strchr(buf, '!'); + if(user != nil) + *user = '\0'; + user = strdup(buf); + free(server); + server = user; + } + + if(toserver == nil) + toserver = server; + + me = mkjabberc(); + me->show = strdup("Online"); + me->stat = strdup("Online"); + me->name = strdup(i->user); + me->serv = strdup(toserver); + + if(b != nil) + me->reso = strdup(b); + else + me->reso = strdup("Plan9"); + me->jid = printjid(me->name, me->serv, me->reso); + me->debug = debug; + me->reg = reg; + me->last = time(0); + + free(server); + + ts = getpid(); + +#ifdef PLAN9PORT + switch(fork()) { +#endif +#ifndef PLAN9PORT + switch(rfork(RFPROC|RFFDG|RFMEM)) { +#endif + case -1: + sysfatal("fork: %r"); + case 0: + if(recvjacc(sock, me, i->passwd) < 0) + perror("recvjacc"); + + if(lbl != nil){ + setwindowlbl(lbl); + lbl = nil; + free(lbl); + } + killproc(ts); + exits(0); + default: + user = reallocj(nil, 1025, 2); + buf = nil; + while(sock > 0 && user != nil){ + ts = -1; + memset(user, 0, 1025); + + while(read(0, &user[++ts], 1) && ts < 1024 && sock > 0) + if(user[ts] == '\n') + break; + user[ts] = '\0'; + me->last = time(0); + + tmstmp = mktmstmp('(', ')'); + if(user[0] != '/'){ + if(buf != nil){ + b = filterhin(user, 0); + messagejacc(sock, me->jid, buf, b, "chat"); + print("%s\n", tmstmp); + free(b); + } + free(tmstmp); + continue; + } + if (user[1] == 'x'){ + b = getarg(user, 1, 0); + if(b != nil){ + if (strcmp(b, "join") == 0){ + free(b); + + server = getarg(user, 2, 0); + + if(server != nil){ + b = getarg(user, 3, 0); + if(b == nil) + b = strdup(me->name); + + fprint(sock, "<presence to=\"%s/%s\"/>", server, b); + free (server); + free(b); + } + } + else + if (strcmp(b, "leave") == 0){ + free(b); + server = getarg(user, 2, 0); + if(server != nil) { + fprint(sock, + "<presence to='%s' type='unavailable'/>", server); + free (server); + } + + } + else + if (strcmp(b, "say") == 0){ + free(b); + server = getarg(user, 2, 0); + if(server != nil){ + b = getarg(user, 3, 2); + if(b != nil){ + messagejacc(sock, + me->jid, server, b, "groupchat"); + free(b); + } + free(server); + } + } + else + if (strcmp(b, "priv") == 0){ + free(b); + server = getarg(user, 2, 0); + if(server != nil){ + role = getarg(user, 3, 0); + if(role != nil){ + b = getarg(user, 4, 2); + if(b != nil){ + tmp = server; + server = smprint("%s/%s", server, role); + free(tmp); + + messagejacc(sock, + me->jid, server, b, "chat"); + free(b); + } + free(role); + } + free(server); + } + } + else + if (strcmp(b, "role") == 0){ + free(b); + server = getarg(user, 2, 0); + if(server != nil){ + role = getarg(user, 3, 0); + if(role != nil){ + b = getarg(user, 4, 2); + if(b != nil){ + tmp = b; + b = smprint("nick='%s' role='%s'", b, role); + free(tmp); + + admin(sock, role, server, b); + free(b); + } + free(role); + } + free(server); + } + } + else + if (strcmp(b, "affil") == 0){ + free(b); + server = getarg(user, 2, 0); + if(server != nil){ + role = getarg(user, 3, 0); + if(role != nil){ + b = getarg(user, 4, 2); + if(b != nil){ + tmp = b; + b = smprint("jid='%s' affiliation='%s'", b, role); + free(tmp); + + admin(sock, role, server, b); + free(b); + } + free(role); + } + free(server); + } + } + else + free(b); + } + } + else + switch(user[1]){ + case 'h': + case 'H': + print("%sHelp for jacc:\n", tmstmp); + print("%s /a [+|-|*]jid - authenticate jid\n", tmstmp); + print("%s /b - turn debugging on or off\n", tmstmp); + print("%s /c file - set vcard on server\n", tmstmp); + print("%s /d jid [feat] - do a discovery request\n", tmstmp); + print("%s /e jid - get time from jid\n", tmstmp); + print("%s /g jid - get agents information from jid\n", tmstmp); + print("%s /h - print out this help\n", tmstmp); + print("%s /i jid - get version of jid\n", tmstmp); + print("%s /l [status|jid|user] - list the roster\n", tmstmp); + print("%s /m jid - send a message to jid\n", tmstmp); + print("%s /p [show] [status] - set status and show\n", tmstmp); + print("%s /q - quit jacc\n", tmstmp); + print("%s /s [jid] - set active jid\n", tmstmp); + print("%s /t jid - get idle time of jid\n",tmstmp); + print("%s /u [+|-]jid [alias] - manage roster\n", tmstmp); + print("%s /v [jid] - get vcard from jid\n", tmstmp); + + print("%s /x command - operate with groupchat\n", tmstmp); + print("%s commands:\n", tmstmp); + print("%s groupchat - leave groupchat\n", tmstmp); + print("%s join groupchat [nick] - join to the groupchat\n", tmstmp); +// print("%s names groupchat - occupants' list\n", tmstmp); + print("%s say groupchat - send a message to groupchat\n", tmstmp); + print("%s priv groupchat nick - send a private message to occupant\n", tmstmp); + print("%s leave groupchat - leave groupchat\n", tmstmp); + print("%s affil groupchat affilation jid - set affilation\n", tmstmp); + print("%s role groupchat role nick - set role\n", tmstmp); + break; + + case 'q': + case 'Q': + fprint(sock, "<presence from=\"%s\" type=\"unavailable\"/>", + me->jid); + fprint(sock, "</stream:stream>"); + free(user); + user = nil; + break; + case 's': + case 'S': + server = getarg(user, 1, 0); + if(server == nil){ + print("%s%s\n", tmstmp, (buf != nil) ? buf : "<nil>"); + break; + } + + buf = setchan(buf, namerostern(me->rost, nil, server)); + free(server); + break; + case 'l': + case 'L': + server = getarg(user, 1, 0); + + printrostern(me->rost, server); + + if(server != nil) + free(server); + break; + case 'm': + case 'M': + server = getarg(user, 1, 0); + if(server != nil){ + + b = getarg(user, 2, 2); + if(b != nil){ + messagejacc(sock, me->jid, namerostern(me->rost, nil, server), b, "normal"); + free(b); + } + + free(server); + } + break; + case 'p': + case 'P': + server = getarg(user, 1, 0); + if(server == nil){ + print("%s%s\n", tmstmp, me->stat); + break; + } + + b = getarg(user, 2, 2); + if(b != nil){ + presencejacc(sock, b, server, nil, nil); + free(me->stat); + me->stat = strdup(b); + } else + presencejacc(sock, nil, server, nil, nil); + free(me->show); + me->show = strdup(server); + statusrostern(me->rost, me->jid, me->jid, server, b); + free(server); + break; + case 'c': + case 'C': + server = getarg(user, 1, 0); + if(server != nil){ + ts = open(server, OREAD); + if(ts >= 0){ + vcardsetjacc(sock, me->jid, ts); + close(ts); + } + free(server); + } + break; + case 'v': + case 'V': + server = getarg(user, 1, 0); + if(server == nil){ + vcardgetjacc(sock, me->jid, "from"); + break; + } + + vcardgetjacc(sock, namerostern(me->rost, nil, server), "to"); + print("Vcard of: %s\n", namerostern(me->rost, nil, server)); + free(server); + break; + case 'u': + case 'U': + server = getarg(user, 1, 0); + if(server != nil){ + if(server[0] == '-') + delbuddyjacc(sock, namerostern(me->rost, server + 1, server + 1)); + else { + b = getarg(user, 2, 0); + if(server[0] == '+') + addbuddyjacc(sock, server + 1, b, nil); + else + addbuddyjacc(sock, server, b, nil); + } + free(server); + } + break; + case 'a': + case 'A': + server = getarg(user, 1, 0); + if(server != nil){ + switch(server[0]){ + case '+': + presencetypejacc(sock, me->jid, namerostern(me->rost, nil, server + 1), "subscribed"); + break; + case '-': + presencetypejacc(sock, me->jid, namerostern(me->rost, nil, server + 1), "unsubscribe"); + break; + case '*': + presencetypejacc(sock, me->jid, namerostern(me->rost, nil, server + 1), "subscribe"); + break; + default: + presencetypejacc(sock, me->jid, namerostern(me->rost, nil, server), "subscribed"); + break; + } + free(server); + } + break; + case 'd': + case 'D': + server = getarg(user, 1, 0); + if(server != nil){ + b = getarg(user, 2, 2); + if(b == nil) + b = strdup("info"); + + free(tmstmp); + tmstmp = reallocj(nil, 35 + strlen(b), 2); + sprint(tmstmp, "http://jabber.org/protocol/disco#%s", b); + + xmlnsjacc(sock, server, tmstmp, "disco0"); + free(b); + free(server); + } + break; + case 'b': + case 'B': + if(me->debug == 0) + me->debug = 1; + else + me->debug = 0; + print("%sDebug: %c\n", tmstmp, me->debug); + break; + case 't': + case 'T': + server = getarg(user, 1, 0); + if(server != nil){ + xmlnsjacc(sock, namerostern(me->rost, nil, server), "jabber:iq:last", "last0"); + free(server); + } + break; + case 'i': + case 'I': + server = getarg(user, 1, 0); + if(server != nil){ + xmlnsjacc(sock, namerostern(me->rost, nil, server), "jabber:iq:version", "version0"); + free(server); + } + break; + case 'e': + case 'E': + server = getarg(user, 1, 0); + if(server != nil){ + xmlnsjacc(sock, namerostern(me->rost, nil, server), "jabber:iq:time", "time0"); + free(server); + } + break; + case 'g': + case 'G': + server = getarg(user, 1, 0); + if(server != nil){ + xmlnsjacc(sock, namerostern(me->rost, nil, server), "jabber:iq:agents", "agents0"); + free(server); + } + break; + + default: + break; + } + free(tmstmp); + } + + wait(); + if(lbl != nil){ + setwindowlbl(lbl); + lbl = nil; + free(lbl); + } + break; + } + + freejabberc(me); + exits(0); + return 0; +} +<!-- BEGIN TAIL --> +</pre> +</td></tr></table> +</td></tr></table> +<p style="margin-top: 0; margin-bottom: 0.17in"></p> +<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;"> +<span style="font-size: 10pt">(This is a user-contributed directory and <br> should not be interpreted as statement by Lucent.)</span></p> +<p style="margin-top: 0; margin-bottom: 0.50in"></p> +<p style="margin-top: 0; margin-bottom: 0.33in"></p> +<center><table border="0"><tr> +<td valign="middle"><a href="http://www.alcatel-lucent.com/"><img border="0" src="/plan9/img/logo_ft.gif" alt="Bell Labs" /> +</a></td> +<td valign="middle"><a href="http://www.opensource.org"><img border="0" alt="OSI certified" src="/plan9/img/osi-certified-60x50.gif" /> +</a></td> +<td><img style="padding-right: 45px;" alt="Powered by Plan 9" src="/plan9/img/power36.gif" /> +</td> +</tr></table></center> +<p style="margin-top: 0; margin-bottom: 0.17in"></p> +<center> +<span style="font-size: 10pt">(<a href="/plan9/">Return to Plan 9 Home Page</a>)</span> +</center> +<p style="margin-top: 0; margin-bottom: 0.17in"></p> +<center><font size=-1> +<span style="font-size: 10pt"><a href="http://www.lucent.com/copyright.html">Copyright</a></span> +<span style="font-size: 10pt">© 2009 Alcatel-Lucent.</span> +<span style="font-size: 10pt">All Rights Reserved.</span> +<br /> +<span style="font-size: 10pt">Comments to</span> +<span style="font-size: 10pt"><a href="mailto:webmaster@plan9.bell-labs.com">webmaster@plan9.bell-labs.com</a>.</span> +</font></center> +</body> +</html> + diff --git a/jacc.tar b/jacc.tar Binary files differnew file mode 100644 index 0000000..a037c8d --- /dev/null +++ b/jacc.tar |