summaryrefslogblamecommitdiffstats
path: root/jacs/recv.c
blob: 63b1b91939ce501768333c211ba12a6533887688 (plain) (tree)



































































































































































































































































































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