jacc

Jabber/XMPP client for Plan 9
git clone git://r-36.net/jacc
Log | Files | Refs | LICENSE

recv.c (5680B)


      1 /*
      2  * Copy me if you can.
      3  * by 20h
      4  */
      5 
      6 #include <u.h>
      7 #include <libc.h>
      8 #include "xmlpull.h"
      9 #include "jacs.h"
     10 #include "dat.h"
     11 #include "roster.h"
     12 
     13 char *
     14 getline(void)
     15 {
     16 	char *ret;
     17 	int l;
     18 
     19 	l = -1;
     20 	ret = reallocj(nil, 1025, 2);
     21 
     22 	while(read(0, &ret[++l], 1) && l < 1024)
     23 		if(ret[l] == '\n')
     24 			break;
     25 	ret[l] = '\0';
     26 
     27 	return ret;
     28 }
     29 
     30 void
     31 askanswers(ilist *i, char *tmstmp)
     32 {
     33 	ilist *ac;
     34 	char *val;
     35 
     36 	ac = i;
     37 	while(ac != nil){
     38 		print("%s%s[%s] = ", tmstmp, ac->name, (ac->val != nil) ? ac->val : "");
     39 		val = getline();
     40 		if(ac->val == nil)
     41 			ac->val = val;
     42 		else {
     43 			if(*val != '\0'){
     44 				free(ac->val);
     45 				ac->val = val;
     46 			} else
     47 				free(val);
     48 		}
     49 		ac = ac->n;
     50 	}
     51 
     52 	return;
     53 }
     54 
     55 int
     56 recvjacc(int sock, jabberc *me, char *pass)
     57 {
     58 	xmlpull *x, *b;
     59 	char *id, *to, *from, *tmstmp, st, *type;
     60 	ilist *ac;
     61 
     62 	type = nil;
     63 	id = nil;
     64 	from = nil;
     65 	to = nil;
     66 	st = NONE;
     67 	ac = nil;
     68 
     69 	if(xmljacc(sock) < 0)
     70 		return -1;
     71 	if(loginjacc(sock, me->serv) < 0)
     72 		return -1;
     73 
     74 	x = openxmlpull(sock);
     75 	while((b = nextxmlpull(x)) != nil && st != END){
     76 		tmstmp = mktmstmp('(', ')');
     77 		switch(b->ev){
     78 		case START_DOCUMENT:
     79 			if(me->debug)
     80 				print("Start.\n");
     81 			st = NONE;
     82 			break;
     83 		case START_TAG:
     84 			if(me->debug)
     85 				print("Tag: %s\n", x->na);
     86 			if(!strcmp(x->na, "stream:stream")){
     87 				st = STREAM;
     88 				break;
     89 			}
     90 			if(!strcmp(x->na, "stream:error")){
     91 				st = ERROR;
     92 				break;
     93 			}
     94 			if(st == ERROR){
     95 				if(strcmp(x->na, "text"))
     96 					fprint(2, "%serror: %s\n", tmstmp, x->na);
     97 				break;
     98 			}
     99 			if(!strcmp(x->na, "iq")){
    100 				st = IQ;
    101 				break;
    102 			}
    103 			if(!strcmp(x->na, "error") && st == IQ){
    104 				st = IQ_ERROR;
    105 				break;
    106 			}
    107 			if(st == IQ_ERROR){
    108 				print("IQ-Error: %s\n", x->na);
    109 				break;
    110 			}
    111 			if(!strcmp(x->na, "query") && st == IQ){
    112 				st = IQ_INNER;
    113 				break;
    114 			}
    115 			if(!strcmp(x->na, "instructions") && st == IQ_REGISTER){
    116 				st = IQ_REGISTER_INST;
    117 				break;
    118 			}
    119 			if(!strcmp(x->na, "query") && st == IQ_REGISTER)
    120 				break;
    121 			if(st == IQ_REGISTER){
    122 				st = IQ_REGISTER_INNE;
    123 				me->list = addilist(me->list, x->na, nil);
    124 				ac = lastilist(me->list);
    125 				break;
    126 			}
    127 			break;
    128 		case START_END_TAG:
    129 			if(me->debug)
    130 				print("Startend: %s\n", x->na);
    131 			if(st == IQ_REGISTER){
    132 				if(!strcmp(x->na, "registered")){
    133 					print("%sAlready registerd.\n", tmstmp);
    134 					break;
    135 				}
    136 				if(strcmp(x->na, "remove"))
    137 					me->list = addilist(me->list, x->na, nil);
    138 				break;
    139 			}
    140 			if(st == ERROR){
    141 				fprint(2, "%serror: %s\n", tmstmp, x->na);
    142 				break;
    143 			}	
    144 			break;
    145 		case TEXT:
    146 			if(me->debug)
    147 				print("Text: %s\n", x->na);
    148 			switch(st){
    149 			case IQ_REGISTER_INST:
    150 				print("%s %s\n", tmstmp, x->na);
    151 				break;
    152 			case IQ_REGISTER_INNE:
    153 				ac->val = strdup(x->na);
    154 				break;
    155 			default:
    156 				break;
    157 			}
    158 			break;
    159 		case ATTR:
    160 			if(me->debug)
    161 				print("Attr: %s = %s\n", x->na, x->va);
    162 			switch(st){
    163 			case STREAM:
    164 				if(!strcmp(x->na, "id")){
    165 					st = NONE;
    166 					if(userjacc(sock, me->name, pass, me->reso) < 0) {
    167 						memset(pass, 0, strlen(pass));
    168 						st = AUTH;
    169 						break;
    170 					}
    171 				}
    172 				break;
    173 			case IQ:
    174 				if(!strcmp(x->na, "id")){
    175 					if(!strcmp(x->va, "auth_1")) {
    176 						presencejacc(sock, me->stat, me->show, me->jid, nil);
    177 						if(me->unreg)
    178 							xmlnsnegjacc(sock, me->dest, "jabber:iq:register", "service_1");
    179 						else
    180 							xmlnsjacc(sock, me->dest, "jabber:iq:register", "service_0");
    181 					}
    182 					if(!strcmp(x->va, "service_0"))
    183 						st = IQ_REGISTER;
    184 					id = strdup(x->va);
    185 				}
    186 				if(!strcmp(x->na, "from"))
    187 					from = strdup(x->va);
    188 				if(!strcmp(x->na, "to"))
    189 					to = strdup(x->va);
    190 				if(!strcmp(x->na, "type"))
    191 					type = strdup(x->va);
    192 				break;
    193 			case IQ_INNER:
    194 				if(!strcmp(x->na, "xmlns")){
    195 					if(!strcmp(x->va, "jabber:iq:version")) {
    196 						if(!strcmp(to, me->jid)){
    197 							print("%s%s:\n", tmstmp, from);
    198 							break;
    199 						} else
    200 							versionjacc(sock, me->jid, from, id);
    201 						break;
    202 					}
    203 					if(!strcmp(x->va, "http://jabber.org/protocol/disco#info"))
    204 						if(!strcmp(me->jid, to))
    205 							featuresjacc(sock, to, from, id);
    206 
    207 				}
    208 				break;
    209 			default:
    210 				break;
    211 			}
    212 			break;
    213 		case END_TAG:
    214 			if(me->debug)
    215 				print("Endtag: %s\n", x->na);
    216 			if(!strcmp(x->na, "stream:stream")){
    217 				st = END;
    218 				break;
    219 			}
    220 			if(!strcmp(x->na, "stream:error") && st == ERROR){
    221 				st = NONE;
    222 				break;
    223 			}
    224 			if(st == ERROR)
    225 				break;
    226 			if(!strcmp(x->na, "iq") && (st == IQ || st == IQ_REGISTER)){
    227 				st = NONE;
    228 				if(type != nil){
    229 					if(!strcmp(type, "result") && !strcmp(id, "service_1")){
    230 						print("%sSuccess.\n", tmstmp);
    231 						st = END;
    232 					}
    233 					free(type);
    234 				}
    235 				if(from != nil)
    236 					free(from);
    237 				if(to != nil)
    238 					free(to);
    239 				if(id != nil)
    240 					free(id);
    241 				from = nil;
    242 				to = nil;
    243 				id = nil;
    244 				type = nil;
    245 				break;
    246 			}
    247 			if(!strcmp(x->na, "error") && st == IQ_ERROR){
    248 				st = IQ;
    249 				break;
    250 			}
    251 			if(!strcmp(x->na, "query") && st == IQ_INNER){
    252 				st = IQ;
    253 				break;
    254 			}
    255 			if(!strcmp(x->na, "query") && st == IQ_REGISTER){
    256 				st = IQ;
    257 				if(me->list != nil){
    258 					askanswers(me->list, tmstmp);
    259 					answersjacc(sock, me->dest, "jabber:iq:register", "service_1", me->list);
    260 					freeilist(me->list);
    261 					me->list = nil;
    262 				}
    263 				break;
    264 			}
    265 			if(!strcmp(x->na, "instructions") && st == IQ_REGISTER_INST){
    266 				st = IQ_REGISTER;
    267 				break;
    268 			}
    269 			if(st == IQ_REGISTER_INNE){
    270 				st = IQ_REGISTER;
    271 				break;
    272 			}
    273 			break;
    274 		case END_DOCUMENT:
    275 			if(me->debug)
    276 				print("Documentend.\n");
    277 			st = END;
    278 			break;
    279 		default:
    280 			print("Please contact the xmlpull author about this. %x\n", b->ev);
    281 			st = END;
    282 			break;
    283 		}
    284 		free(tmstmp);
    285 	}
    286 
    287 	if(id != nil)
    288 		free(id);
    289 	freexmlpull(x);
    290 
    291 	return 0;
    292 }