/*
* 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;
}