287 lines · 5.7 KB · C
RawDownload
#include <u.h>#include <libc.h>#include "xml.h"#include "xmpp.h" enum{	Snone = 0,	Sto,	Sfrom,	Sboth,}; char *subscr2str[] ={	[Snone] "none",	[Sto]   "to",	[Sfrom] "from",	[Sboth] "both",}; char *subscr2fmt[] ={	[Snone] "[  ]",	[Sto]   "[← ]",	[Sfrom] "[ →]",	[Sboth] "[←→]",}; static char **asked;static int numasked, rostwidth; introstupdate(Xelem *x, int fd){	Xattr *n, *s, *j;	Target *t;	int i, width; 	if(fprint(fd, "<presence/>") < 0)		return -1; 	for(x = x->ch->ch; x != nil; x = x->next){		n = xmlgetattr(x->a, "name");		s = xmlgetattr(x->a, "subscription");		j = xmlgetattr(x->a, "jid");		if(j == nil || s == nil)			continue;		if(n == nil)			n = j; 		for(i = 0, t = nil; i < numtargets; i++, t = nil){			t = targets[i];			if(t->type == Erost && strcmp(t->jid, j->v) == 0)				break;		}		if(t == nil){			t = addtarget(Erost, n->v);			t->jid = strdup(j->v);		}else{			if(strcmp(s->v, "remove") == 0){				print("%t removed from roster\n", t);				rmtarget(t);				continue;			}			free(t->name);			t->name = strdup(n->v);		}		if((width = utflen(t->name)) > rostwidth)			rostwidth = width;		for(i = 0; i < nelem(subscr2str); i++){			if(strcmp(s->v, subscr2str[i]) == 0){				t->rost.subscr = i;				break;			}		}	} 	return 0;} introstsubscr(char *from, char *type, int fd){	Target *t;	int i; 	if(strcmp(type, "subscribe") == 0){		for(i = 0; i < numtargets; i++){			t = targets[i];			if(t->type == Erost && (t->rost.flags & Fasked) && strncmp(t->jid, from, strlen(t->jid)) == 0){				fprint(fd, "<presence to='%Ӽ' type='subscribed'/>", from);				return 1;			}		}		for(i = 0; i < numasked; i++)			if(strcmp(asked[i], from) == 0)				return 1;		print("%s asks for a subscription\n", from);		numasked++;		asked = realloc(asked, numasked*sizeof(asked[0]));		asked[numasked-1] = strdup(from);		return 1;	}else if(strcmp(type, "subscribed") == 0){		for(i = 0; i < numtargets; i++){			t = targets[i];			if(t->type == Erost && strncmp(t->jid, from, strlen(t->jid)) == 0){				t->rost.flags |= Fasked;				print("%s has approved subscription\n", from);				fprint(fd, "<presence to='%Ӽ' type='subscribe'/>", from); /* ack */				return 1;			}		}	} 	return 0;} voidrostpresence(Xelem *x, Target *t){	Xelem *show;	Xattr *type;	char *didwhat, *s;	int online; 	didwhat = nil;	type = xmlgetattr(x->a, "type");	show = xmlget(x->ch, "show");	online = 1;	if(type != nil){		if(strcmp(type->v, "unavailable") == 0)			online = 0;		else{			if(strcmp(type->v, "unsubscribed") == 0)				print("%t cancelled subscription\n", t);			else if(strcmp(type->v, "unsubscribe") == 0)				print("%t unsubscribed\n", t);			return;		}	} 	if(!online && (t->rost.flags & Fonline)){		didwhat = "went offline";		t->rost.flags &= ~Fonline;	}else if(online && (t->rost.flags & Fonline) == 0){		didwhat = "is online";		t->rost.flags |= Fonline;	} 	if(show == nil)		s = "";	else		s = show->v;	if(t->rost.show != nil && strcmp(s, t->rost.show) == 0)		s = nil;	else{		free(t->rost.show);		t->rost.show = strdup(s);	} 	if(nopresence || didwhat == nil)		return;	print("[%s] %s %s", strtime(), t->name, didwhat);	if(s != nil && s[0] != 0)		print(" (%s)", s);	print("\n");} static intcmdrostadd(int fd, char *jid, char *name){	int i; 	for(i = 0; i < numasked; i++){		if(strncmp(asked[i], jid, strlen(jid)) == 0){			if(fprint(fd, "<presence to='%Ӽ' type='subscribed'/>", asked[i]) < 0)				return -1;			jid = asked[i];			break;		}	} 	if(fprint(fd, "<iq type='set'><query xmlns='jabber:iq:roster'><item jid='%Ӽ'", jid) < 0)		return -1;	if(name != nil && fprint(fd, " name='%Ӽ'", name) < 0)		return -1;	if(fprint(fd, "/></query></iq><presence to='%Ӽ' type='subscribe'/>", jid) < 0)		return -1;	print("asking %s for a subscription\n", jid); 	if(i < numasked){		free(asked[i]);		numasked--;		memcpy(&asked[i], &asked[i+1], sizeof(asked[0])*(numasked-i));	}	return 0;} static intcmdrostrm(int fd, char *jid){	Target *t;	char *a, *b;	int i, alen, blen, res; 	for(i = 0; i < numasked; i++){		if(strncmp(asked[i], jid, strlen(jid)) == 0){			if(fprint(fd, "<presence to='%Ӽ' type='unsubscribed'/>", asked[i]) < 0)				return -1;			free(asked[i]);			numasked--;			memcpy(&asked[i], &asked[i+1], sizeof(asked[0])*(numasked-i));			break;		}	} 	a = jid;	b = strchr(a, '/');	if(b == nil){		blen = 0;		alen = strlen(a);	}else{		b++;		blen = strlen(b);		alen = b-1 - a;	} 	res = 0;	for(i = 0; i < numtargets; i++){		t = targets[i];		if(t->type == Erost && targmatches(t, a, alen) && (b == nil || strncmp(t->jid, b, blen) == 0)){			res = fprint(fd,				"<iq type='set'>"				"<query xmlns='jabber:iq:roster'>"				"<item jid='%Ӽ' subscription='remove'/>"				"</query></iq>",				t->jid);			if(res > 0)				res = fprint(fd, "<presence to='%Ӽ' type='unsubscribe'/>", t->jid);			break;		}	}	return res;} static intcmdrostshow(int extra){	int i, num; 	for(i = num = 0; i < numtargets; i++){		Target *t;		t = targets[i];		if(t->type != Erost)			continue;		if((t->rost.flags & Fonline) == 0 && !extra)			continue;		print("  %s %*s", subscr2fmt[t->rost.subscr], -rostwidth, t->name);		if(t->rost.show != nil && t->rost.show[0] != 0)			print("  [%s]", t->rost.show);		else		if((t->rost.flags & Fonline) == 0)			print("  [offline]");		print("\n");		if(extra && strcmp(t->name, t->jid) != 0)			print("    %s\n", t->jid);		num++;	}	print("%d user(s) online\n", num);	return 0;} intcmdroster(int fd, int argc, char **argv){	int op; 	op = argv[0][1];	if(op == 0)		return cmdrostshow(argv[0][0] == 'R');	else if(op == '+' && argc > 1)		return cmdrostadd(fd, argv[1], (argc > 2 ? argv[2] : nil));	else if(op == '-' && argc > 1)		return cmdrostrm(fd, argv[1]);	return 0;}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t