<?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>/usr/web/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="/plan9/">Plan 9 from Bell Labs</a>’s /usr/web/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="/plan9/license.html">Lucent Public License version 1.02</a>. <br /> <a href="/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"></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>