570 lines · 11.2 KB · C
RawDownload
#include <u.h>#include <libc.h>#include "xml.h"#include "xmpp.h" typedef struct Bookmark Bookmark;struct Bookmark{	char *jid;}; char *affs[] = {	[Anone]    "none",	[Aowner]   "owner",	[Aadmin]   "admin",	[Amember]  "member",	[Aoutcast] "outcast",}; static char *roles[] = {	[Rnone]  "none",	[Rmoder] "moderator",	[Rpart]  "participant",	[Rvisit] "visitor",}; static Bookmark *bookmarks;static int numbookmarks, mucwidth; static intaddnick(Target *room, char *nick, char *jid, char *show, Target **ent){	Target *t;	int i, width; 	for(i = 0; i < numtargets; i++){		int r;		t = targets[i];		if(t->type != Emucent || t->mucent.room != room)			continue;		r = strcmp(t->name, nick);		if(r == 0){			*ent = t;			return 0;		}		if(r > 0)			break;	}	t = addtarget(Emucent, nick);	t->jid = smprint("%s/%s", room->jid, nick);	t->mucent.jid = (jid == nil) ? nil : strdup(jid);	t->mucent.show = (show == nil) ? nil : strdup(show);	t->mucent.room = room;	if((width = utflen(nick)) > room->muc.width)		room->muc.width = width;	*ent = t;	room->muc.numents++;	return 1;} static intrmnick(Target *room, char *nick){	Target *t;	int i, width, removed; 	removed = 0;	room->muc.width = 0;	for(i = 0; i < numtargets; i++){		t = targets[i];		if(t->type != Emucent || t->mucent.room != room)			continue;		if(strcmp(t->name, nick) == 0){			rmtarget(t);			removed = 1;		}else if((width = utflen(t->name)) > room->muc.width)			room->muc.width = width;	}	if(removed)		room->muc.numents--;	return removed;} static intsetaffrole(Target *t, Xelem *item){	Xattr *aff, *role;	int changed, n, i; 	if(item == nil)		return 0;	changed = 0;	role = xmlgetattr(item->a, "role");	aff = xmlgetattr(item->a, "affiliation");	if(role != nil){		n = Rnone;		for(i = 0; i < nelem(roles); i++){			if(strcmp(roles[i], role->v) == 0){				n = i;				break;			}		}		changed |= (t->mucent.role != n);		t->mucent.role = n;	}	if(aff != nil){		n = Anone;		for(i = 0; i < nelem(affs); i++){			if(strcmp(affs[i], aff->v) == 0){				n = i;				break;			}		}		changed |= (t->mucent.aff != n);		t->mucent.aff = n;	} 	return changed;} static intaddbookmark(char *jid){	Bookmark *b;	int i; 	for(i = 0; i < numbookmarks; i++)		if(strcmp(bookmarks[i].jid, jid) == 0)			return 0; 	numbookmarks++;	bookmarks = realloc(bookmarks, sizeof(*b)*numbookmarks);	b = &bookmarks[numbookmarks-1];	b->jid = strdup(jid);	return 1;} static intrmbookmark(char *jid){	int i; 	for(i = 0; i < numbookmarks; i++){		if(strcmp(bookmarks[i].jid, jid) == 0){			numbookmarks--;			memcpy(&bookmarks[i], &bookmarks[i+1], sizeof(bookmarks[0])*(numbookmarks-i));			return 1;		}	}	return 0;} voidmucpresence(Xelem *xml, Target *room, Xattr *from){	char *s, didwhat[32];	Xattr *type;	Xelem *msg, *item, *x, *ch, *show;	int changed; 	if((s = strchr(from->v, '/')) == nil)		return;	s++; 	type = xmlgetattr(xml->a, "type");	msg = xmlget(xml->ch, "status");	x = item = nil;	show = xmlget(xml->ch, "show");	for(ch = xml->ch; ch != nil; ch = ch->next){		if(item == nil && (x = xmlget(ch, "x")) != nil)			item = xmlget(x->ch, "item");	}	if(x == nil)		return; 	if(type != nil && strcmp(type->v, "unavailable") == 0){		Xelem *xstatus;		Xattr *code; 		strcpy(didwhat, "left");		changed = rmnick(room, s);		xstatus = xmlget(x->ch, "status");		code = (xstatus != nil) ? xmlgetattr(xstatus->a, "code") : nil;		if(code != nil && strcmp(code->v, "303") == 0){			Xattr *nick;			nick = xmlgetattr(item->a, "nick");			if(nick != nil){				print("[%s] (%s) %s changed nick to %s\n",					strtime(), room->name, s, nick->v);			}			return;		}	}else{		Target *t;		Xattr *jid;		char *j, *sh; 		jid = xmlgetattr(item->a, "jid");		j = (jid != nil && jid->v != nil) ? jid->v : nil;		sh = (show != nil && show->v != nil) ? show->v : nil; 		strcpy(didwhat, "joined");		changed = addnick(room, s, j, sh, &t);		if(setaffrole(t, item) && !changed)			snprint(didwhat, sizeof(didwhat), "role=%s affiliation=%s",				affs[t->mucent.aff], roles[t->mucent.role]);	}	if(!changed || nopresence)		return;	print("[%s] (%s) %s %s", strtime(), room->name, s, didwhat);	if(msg != nil)		print(" (%s)", msg->v);	print("\n");} intmucbookmarks(Xelem *e, int fd){	Xelem *x; 	for(x = e->ch; x != nil; x = x->next){		char *argv[2];		Xattr *a; 		if(strcmp(x->n, "conference") != 0)			continue;		if((a = xmlgetattr(x->a, "autojoin")) == nil)			continue;		if(strcmp(a->v, "1") != 0 && strcmp(a->v, "true") != 0)			continue;		argv[0] = "j";		a = xmlgetattr(x->a, "jid");		argv[1] = a->v;		if(cmdjoin(fd, 2, argv) < 0)			return -1;		addbookmark(a->v);	} 	return 0;} intcmdaff(int fd, int argc, char **argv){	Target *t, *room;	char *targ, *aff, *slash, *jid;	int i, nlen, res; 	room = nil;	res = 0;	if(argc < 3){		if(argc < 2 && curr >= 0 && targets[curr]->type == Emuc)			room = targets[curr];		else{			targ = argv[1];			nlen = strlen(targ);			for(i = 0; i < numtargets; i++){				t = targets[i];				if(t->type == Emuc && targmatches(t, targ, nlen)){					room = t;					break;				}			}		}		for(i = Anone+1; room != nil && i < nelem(affs) && res >= 0; i++){			res = fprint(fd,				"<iq to='%Ӽ' type='get' id='afflist'>"				"<query xmlns='http://jabber.org/protocol/muc#admin'>"				"<item affiliation='%Ӽ'/>"				"</query></iq>",				room->jid,				affs[i]);		}		return res;	} 	targ = argv[1];	aff = argv[2];	slash = strchr(targ, '/');	jid = nil; 	if(curr >= 0 && targets[curr]->type == Emuc && slash == nil){		room = targets[curr];		if(strchr(targ, '@') != nil)			jid = targ;		else{			nlen = strlen(targ);			for(i = 0; i < numtargets; i++){				t = targets[i];				if(t->type == Emucent && t->mucent.room == room && targmatches(t, targ, nlen)){					jid = t->mucent.jid;					break;				}			}		}	}else if(slash != nil){		int rlen;		rlen = slash - targ;		slash++;		nlen = strlen(slash);		jid = (strchr(slash, '@') != nil) ? slash : nil;		for(i = 0; i < numtargets; i++){			t = targets[i];			if(t->type == Emucent && targmatches(t->mucent.room, targ, rlen) && targmatches(t, slash, nlen)){				room = t->mucent.room;				jid = t->mucent.jid;				break;			}			if(t->type == Emuc && targmatches(t, targ, rlen) && jid != nil){				room = t;				break;			}		}	} 	if(room != nil && jid != nil){		res = fprint(fd,			"<iq to='%Ӽ' type='set'>"			"<query xmlns='http://jabber.org/protocol/muc#admin'>"			"<item affiliation='%Ӽ' jid='%Ӽ'/>"			"</query></iq>",			room->jid,			aff,			jid);	}else		print("no such target: %q\n", targ); 	return res;} intcmdbookmark(int fd, int /*argc*/, char **argv){	int (*f)(char *jid);	int i, res; 	if(argv[0][1] == 0){		int i;		for(i = 0; i < numbookmarks; i++)			print("  %s\n", bookmarks[i].jid);		print("%d bookmark(s)\n", numbookmarks);		return 0;	} 	if(argv[0][1] == '+')		f = addbookmark;	else if(argv[0][1] == '-')		f = rmbookmark;	else		return 0;	if(targets[curr]->type != Emuc || !f(targets[curr]->jid))		return 0; 	res = fprint(fd,		"<iq type='set' id='takethat'>"		"<query xmlns='jabber:iq:private'>"		"<storage xmlns='storage:bookmarks'>");	for(i = 0; i < numbookmarks && res >= 0; i++)		res = fprint(fd, "<conference autojoin='1' jid='%Ӽ'/>", bookmarks[i].jid);	return res < 0 ? res : fprint(fd, "</storage></query></iq>");} intcmdjoin(int fd, int argc, char **argv){	Target *t;	char *room, *rnick, *s;	int i, width, num; 	if(argc < 2){		for(i = num = 0; i < numtargets; i++){			t = targets[i];			if(t->type == Emuc){				print("  %*s  %d\n", -mucwidth, t->jid, t->muc.numents);				num++;			}		}		print("%d muc(s)\n", num);		return 0;	} 	room = argv[1];	if(rnick = strchr(room, '/'))		*rnick++ = 0;	else		rnick = mynick; 	if(fprint(fd,		"<presence to='%Ӽ/%Ӽ'>"		"<x xmlns='http://jabber.org/protocol/muc'>",		room, rnick) < 0)		return -1;	if(argc > 2 && fprint(fd, "<password>%Ӽ</password>", argv[2]) < 0)		return -1;	if(nohistory && fprint(fd, "<history maxchars='0'/>") < 0)		return -1;	if(fprint(fd, "</x></presence>") < 0)		return -1; 	for(i = 0; i < numtargets; i++)		if(strcmp(targets[i]->name, room) == 0)			return 0; 	t = addtarget(Emuc, room);	t->jid = strdup(room);	if(s = strchr(t->name, '@'))		*s = 0;	mucwidth = 0;	for(i = 0; i < numtargets; i++){		t = targets[i];		if(t->type == Emuc && (width = utflen(t->jid)) > mucwidth)			mucwidth = width;	}	return 0;} static Target *findmuc(char *name){	int tlen, i;	Target *t; 	t = nil;	tlen = strlen(name);	for(i = 0; i < numtargets; i++, t = nil){		t = targets[i];		if(t->type == Emuc && targmatches(t, name, tlen))			break;	}	if(t == nil)		print("no such muc: %q\n", name);	return t;} intcmdpart(int fd, int argc, char **argv){	Target *t;	int i, width; 	t = nil;	if(argc >= 2)		t = findmuc(argv[1]);	else if(curr >= 0 && targets[curr]->type == Emuc)		t = targets[curr];	if(t == nil)		return 0; 	/* free private chats */	if(fprint(fd,		"<presence from='%Ӽ' to='%Ӽ' type='unavailable'></presence>",		myjid, t->jid) < 0)		return -1; 	mucwidth = 0;	for(i = 0; i < numtargets; i++){		if(targets[i]->type == Emucent && targets[i]->mucent.room == t)			rmtarget(targets[i]);		if(t->type == Emuc && (width = utflen(t->jid)) > mucwidth)			mucwidth = width;	} 	print("left %s\n", t->name);	rmtarget(t);	return 0;} intcmdsubj(int fd, int argc, char **argv){	Target *t;	char *subj;	int res; 	t = nil;	if(argc >= 2)		t = findmuc(argv[1]);	else if(curr >= 0 && targets[curr]->type == Emuc)		t = targets[curr];	if(t == nil)		return 0; 	if(argv[0][0] == 's'){		print("subject for %s:\n%s\n", t->name, (t->muc.subj == nil) ? "" : t->muc.subj);		return 0;	} 	subj = readlines();	res = fprint(fd,		"<message to='%Ӽ' type='%Ӽ'><subject>%Ӽ</subject></message>",		t->jid,		enttypes[t->type],		subj);	free(subj);	return res;} intcmdwho(int, int argc, char **argv){

Lines 1–500 of 570.

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