summaryrefslogtreecommitdiffstats
path: root/jacc-paste.c
diff options
context:
space:
mode:
Diffstat (limited to 'jacc-paste.c')
-rw-r--r--jacc-paste.c757
1 files changed, 757 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;
+}