diff options
Diffstat (limited to 'jacs/recv.c')
-rw-r--r-- | jacs/recv.c | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/jacs/recv.c b/jacs/recv.c new file mode 100644 index 0000000..63b1b91 --- /dev/null +++ b/jacs/recv.c @@ -0,0 +1,292 @@ +/* + * Copy me if you can. + * by 20h + */ + +#include <u.h> +#include <libc.h> +#include "xmlpull.h" +#include "jacs.h" +#include "dat.h" +#include "roster.h" + +char * +getline(void) +{ + char *ret; + int l; + + l = -1; + ret = reallocj(nil, 1025, 2); + + while(read(0, &ret[++l], 1) && l < 1024) + if(ret[l] == '\n') + break; + ret[l] = '\0'; + + return ret; +} + +void +askanswers(ilist *i, char *tmstmp) +{ + ilist *ac; + char *val; + + ac = i; + while(ac != nil){ + print("%s%s[%s] = ", tmstmp, ac->name, (ac->val != nil) ? ac->val : ""); + val = getline(); + if(ac->val == nil) + ac->val = val; + else { + if(*val != '\0'){ + free(ac->val); + ac->val = val; + } else + free(val); + } + ac = ac->n; + } + + return; +} + +int +recvjacc(int sock, jabberc *me, char *pass) +{ + xmlpull *x, *b; + char *id, *to, *from, *tmstmp, st, *type; + ilist *ac; + + type = nil; + id = nil; + from = nil; + to = nil; + st = NONE; + ac = nil; + + if(xmljacc(sock) < 0) + return -1; + if(loginjacc(sock, me->serv) < 0) + return -1; + + x = openxmlpull(sock); + while((b = nextxmlpull(x)) != nil && st != END){ + tmstmp = mktmstmp('(', ')'); + switch(b->ev){ + case START_DOCUMENT: + if(me->debug) + print("Start.\n"); + st = NONE; + break; + case START_TAG: + if(me->debug) + print("Tag: %s\n", x->na); + if(!strcmp(x->na, "stream:stream")){ + st = STREAM; + break; + } + if(!strcmp(x->na, "stream:error")){ + st = ERROR; + break; + } + if(st == ERROR){ + if(strcmp(x->na, "text")) + fprint(2, "%serror: %s\n", tmstmp, x->na); + break; + } + if(!strcmp(x->na, "iq")){ + st = IQ; + break; + } + if(!strcmp(x->na, "error") && st == IQ){ + st = IQ_ERROR; + break; + } + if(st == IQ_ERROR){ + print("IQ-Error: %s\n", x->na); + break; + } + if(!strcmp(x->na, "query") && st == IQ){ + st = IQ_INNER; + break; + } + if(!strcmp(x->na, "instructions") && st == IQ_REGISTER){ + st = IQ_REGISTER_INST; + break; + } + if(!strcmp(x->na, "query") && st == IQ_REGISTER) + break; + if(st == IQ_REGISTER){ + st = IQ_REGISTER_INNE; + me->list = addilist(me->list, x->na, nil); + ac = lastilist(me->list); + break; + } + break; + case START_END_TAG: + if(me->debug) + print("Startend: %s\n", x->na); + if(st == IQ_REGISTER){ + if(!strcmp(x->na, "registered")){ + print("%sAlready registerd.\n", tmstmp); + break; + } + if(strcmp(x->na, "remove")) + me->list = addilist(me->list, x->na, nil); + break; + } + if(st == ERROR){ + fprint(2, "%serror: %s\n", tmstmp, x->na); + break; + } + break; + case TEXT: + if(me->debug) + print("Text: %s\n", x->na); + switch(st){ + case IQ_REGISTER_INST: + print("%s %s\n", tmstmp, x->na); + break; + case IQ_REGISTER_INNE: + ac->val = strdup(x->na); + break; + default: + break; + } + break; + case ATTR: + if(me->debug) + print("Attr: %s = %s\n", x->na, x->va); + switch(st){ + case STREAM: + if(!strcmp(x->na, "id")){ + st = NONE; + if(userjacc(sock, me->name, pass, me->reso) < 0) { + memset(pass, 0, strlen(pass)); + st = AUTH; + break; + } + } + break; + case IQ: + if(!strcmp(x->na, "id")){ + if(!strcmp(x->va, "auth_1")) { + presencejacc(sock, me->stat, me->show, me->jid, nil); + if(me->unreg) + xmlnsnegjacc(sock, me->dest, "jabber:iq:register", "service_1"); + else + xmlnsjacc(sock, me->dest, "jabber:iq:register", "service_0"); + } + if(!strcmp(x->va, "service_0")) + st = IQ_REGISTER; + id = strdup(x->va); + } + if(!strcmp(x->na, "from")) + from = strdup(x->va); + if(!strcmp(x->na, "to")) + to = strdup(x->va); + if(!strcmp(x->na, "type")) + type = strdup(x->va); + break; + case IQ_INNER: + if(!strcmp(x->na, "xmlns")){ + if(!strcmp(x->va, "jabber:iq:version")) { + if(!strcmp(to, me->jid)){ + print("%s%s:\n", tmstmp, from); + break; + } else + versionjacc(sock, me->jid, from, id); + break; + } + if(!strcmp(x->va, "http://jabber.org/protocol/disco#info")) + if(!strcmp(me->jid, to)) + featuresjacc(sock, to, from, id); + + } + break; + default: + break; + } + break; + case END_TAG: + if(me->debug) + print("Endtag: %s\n", x->na); + if(!strcmp(x->na, "stream:stream")){ + st = END; + break; + } + if(!strcmp(x->na, "stream:error") && st == ERROR){ + st = NONE; + break; + } + if(st == ERROR) + break; + if(!strcmp(x->na, "iq") && (st == IQ || st == IQ_REGISTER)){ + st = NONE; + if(type != nil){ + if(!strcmp(type, "result") && !strcmp(id, "service_1")){ + print("%sSuccess.\n", tmstmp); + st = END; + } + free(type); + } + if(from != nil) + free(from); + if(to != nil) + free(to); + if(id != nil) + free(id); + from = nil; + to = nil; + id = nil; + type = nil; + break; + } + if(!strcmp(x->na, "error") && st == IQ_ERROR){ + st = IQ; + break; + } + if(!strcmp(x->na, "query") && st == IQ_INNER){ + st = IQ; + break; + } + if(!strcmp(x->na, "query") && st == IQ_REGISTER){ + st = IQ; + if(me->list != nil){ + askanswers(me->list, tmstmp); + answersjacc(sock, me->dest, "jabber:iq:register", "service_1", me->list); + freeilist(me->list); + me->list = nil; + } + break; + } + if(!strcmp(x->na, "instructions") && st == IQ_REGISTER_INST){ + st = IQ_REGISTER; + break; + } + if(st == IQ_REGISTER_INNE){ + st = IQ_REGISTER; + break; + } + break; + case END_DOCUMENT: + if(me->debug) + print("Documentend.\n"); + st = END; + break; + default: + print("Please contact the xmlpull author about this. %x\n", b->ev); + st = END; + break; + } + free(tmstmp); + } + + if(id != nil) + free(id); + freexmlpull(x); + + return 0; +} |