summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2020-02-25 18:06:41 -0500
committerJune McEnroe <june@causal.agency>2020-02-25 18:11:11 -0500
commitdde937cec56b3f6563322d37121308d3f5f5ac39 (patch)
tree2aa278588e31c07b23796f352dc5d6fb08c37c04
parentBump buffer sizes to allow for tags (diff)
downloadpounce-dde937cec56b3f6563322d37121308d3f5f5ac39.tar.gz
pounce-dde937cec56b3f6563322d37121308d3f5f5ac39.zip
Request server-time from the server and filter tags for clients
This doesn't yet, but it will break the "robustness principle" according
to which a server "SHOULD NOT" assume that a client capable of parsing
one tag is capable of parsing all tags. In future, TagCaps will have all
other caps that use tags ORed into it, and only if the client supports
none of them will tags be filtered out.
-rw-r--r--bounce.h3
-rw-r--r--client.c21
-rw-r--r--pounce.13
-rw-r--r--state.c2
4 files changed, 24 insertions, 5 deletions
diff --git a/bounce.h b/bounce.h
index f95bdc8..da52592 100644
--- a/bounce.h
+++ b/bounce.h
@@ -43,6 +43,7 @@ enum { MessageCap = 8191 + 512 };
 
 enum { ParamCap = 15 };
 struct Message {
+	char *tags;
 	char *origin;
 	char *cmd;
 	char *params[ParamCap];
@@ -50,6 +51,7 @@ struct Message {
 
 static inline struct Message parse(char *line) {
 	struct Message msg = {0};
+	if (line[0] == '@') msg.tags = 1 + strsep(&line, " ");
 	if (line[0] == ':') msg.origin = 1 + strsep(&line, " ");
 	msg.cmd = strsep(&line, " ");
 	for (size_t i = 0; line && i < ParamCap; ++i) {
@@ -79,6 +81,7 @@ enum Cap {
 #define X(name, id) BIT(id),
 	ENUM_CAP
 #undef X
+	TagCaps = CapServerTime,
 };
 
 static const char *CapNames[] = {
diff --git a/client.c b/client.c
index 93b1716..8a4e86f 100644
--- a/client.c
+++ b/client.c
@@ -315,6 +315,10 @@ size_t clientDiff(const struct Client *client) {
 }
 
 static int wordcmp(const char *line, size_t i, const char *word) {
+	if (line[0] == '@') {
+		line += strcspn(line, " ");
+		if (*line) line++;
+	}
 	while (i--) {
 		line += strcspn(line, " ");
 		if (*line) line++;
@@ -421,6 +425,12 @@ static const char *filterUserhostInNames(const char *line) {
 	);
 }
 
+static const char *filterTags(const char *line) {
+	if (line[0] != '@') return line;
+	const char *sp = strchr(line, ' ');
+	return (sp ? sp + 1 : NULL);
+}
+
 static Filter *Filters[] = {
 	[CapAccountNotifyBit] = filterAccountNotify,
 	[CapAwayNotifyBit] = filterAwayNotify,
@@ -441,18 +451,23 @@ void clientConsume(struct Client *client) {
 		if (!Filters[i]) continue;
 		if (diff & (1 << i)) line = Filters[i](line);
 	}
+	if (stateCaps & TagCaps && !(client->caps & TagCaps)) {
+		if (line) line = filterTags(line);
+	}
 	if (!line) {
 		ringConsume(NULL, client->consumer);
 		return;
 	}
 
-	if (client->caps & CapServerTime) {
+	if (client->caps & CapServerTime && !(stateCaps & CapServerTime)) {
 		char ts[sizeof("YYYY-MM-DDThh:mm:ss")];
 		struct tm *tm = gmtime(&time.tv_sec);
 		strftime(ts, sizeof(ts), "%FT%T", tm);
 		clientFormat(
-			client, "@time=%s.%03dZ %s\r\n",
-			ts, (int)(time.tv_usec / 1000), line
+			client, "@time=%s.%03dZ%c%s\r\n",
+			ts, (int)(time.tv_usec / 1000),
+			(line[0] == '@' ? ';' : ' '),
+			(line[0] == '@' ? &line[1] : line)
 		);
 	} else {
 		clientFormat(client, "%s\r\n", line);
diff --git a/pounce.1 b/pounce.1
index c55310b..7ed431f 100644
--- a/pounce.1
+++ b/pounce.1
@@ -1,4 +1,4 @@
-.Dd February 18, 2020
+.Dd February 25, 2020
 .Dt POUNCE 1
 .Os
 .
@@ -343,6 +343,7 @@ is supported:
 .Sy extended-join ,
 .Sy invite-notify ,
 .Sy multi-prefix ,
+.Sy server-time ,
 .Sy userhost-in-names .
 .
 .Pp
diff --git a/state.c b/state.c
index a661ce7..c714628 100644
--- a/state.c
+++ b/state.c
@@ -75,7 +75,7 @@ static void handleCap(struct Message *msg) {
 	enum Cap caps = capParse(msg->params[2]);
 
 	if (!strcmp(msg->params[1], "LS")) {
-		caps &= ~(CapSASL | CapServerTime | CapUnsupported);
+		caps &= ~(CapSASL | CapUnsupported);
 		serverFormat("CAP REQ :%s\r\n", capList(caps));
 
 	} else if (!strcmp(msg->params[1], "ACK")) {
8:23:04 -0500'>2020-02-11Rename query ID on nick changeJune McEnroe 2020-02-11Call completeClear when closing a windowJune McEnroe 2020-02-11Don't insert color codes for non-mentionsJune McEnroe 2020-02-11Take first two words in colorMentionsJune McEnroe This lets phrases like "hi june" get colored, but still doesn't get carried away. 2020-02-11Use time_t for save signatureJune McEnroe It's actually more likely to be 64-bit than size_t anyway, and it eliminates some helper functions. Also don't error when reading an empty save file. 2020-02-11Set self.nick to * initiallyJune McEnroe Allows removing a bunch of checks that self.nick is set, and it's what the server usually calls you before registration. Never highlight notices as mentions. 2020-02-11Define ColorCap instead of hardcoding 100June McEnroe 2020-02-11Move hash to top of chat.hJune McEnroe 2020-02-11Move base64 out of chat.hJune McEnroe 2020-02-11Move XDG_SUBDIR out of chat.hJune McEnroe 2020-02-11Fix whois idle unit calculationJune McEnroe Rookie mistake. 2020-02-11Cast towupper to wchar_tJune McEnroe For some reason it takes and returns wint_t... 2020-02-11Cast set but unused variables to voidJune McEnroe 2020-02-11Declare strlcatJune McEnroe 2020-02-11Check if VDSUSP existsJune McEnroe 2020-02-11Fix completeReplace iterationJune McEnroe 2020-02-11Use pkg(8) to configure on FreeBSDJune McEnroe 2020-02-11Remove legacy codeJune McEnroe 2020-02-11Add INSTALLING section to READMEJune McEnroe