about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAlexander Barton <alex@barton.de>2013-01-01 14:57:03 +0100
committerAlexander Barton <alex@barton.de>2013-01-01 14:57:03 +0100
commit289a26e9e43be303a7355ab530ddcaa84aca60b9 (patch)
treea1babd4f3caeee9017b09fe455685326d08ed6fb /src
parentd2a1f6aa4be7e42dd76e5342b309b8331d86bab4 (diff)
downloadngircd-289a26e9e43be303a7355ab530ddcaa84aca60b9.tar.gz
ngircd-289a26e9e43be303a7355ab530ddcaa84aca60b9.zip
Implement Help() function parsing and returning the help text
This function parses the already read in help text and sends the requested
portions to the user. Parsing is done as following when a user user
issues a "HELP <cmd>" command:

 1. Search the file for a line "- <cmd>",
 2. Output all subsequent lines that start with a TAB (ASCII 9) character
    to the client using NOTICE commands, treat lines containing a single "."
    after the TAB as empty lines.
 3. Break at the first line not starting with a TAB character.

This format allows to have information to each command stored in this file
which will not be sent to an IRC user requesting help which enables us to
have additional annotations stored here which further describe the origin,
implementation details, or limits of the specific command.

A special "Intro" block is returned to the user when the HELP command is
used without a command name.
Diffstat (limited to 'src')
-rw-r--r--src/ngircd/irc.c84
1 files changed, 81 insertions, 3 deletions
diff --git a/src/ngircd/irc.c b/src/ngircd/irc.c
index 1a0d725f..f6b9dc59 100644
--- a/src/ngircd/irc.c
+++ b/src/ngircd/irc.c
@@ -44,6 +44,7 @@ static bool Send_Message PARAMS((CLIENT *Client, REQUEST *Req, int ForceType,
 static bool Send_Message_Mask PARAMS((CLIENT *from, char *command,
 				      char *targetMask, char *message,
 				      bool SendErrors));
+static bool Help PARAMS((CLIENT *Client, const char *Topic));
 
 
 /**
@@ -320,10 +321,23 @@ IRC_HELP(CLIENT *Client, REQUEST *Req)
 	assert(Req != NULL);
 
 	/* Bad number of arguments? */
-	if (Req->argc > 0)
+	if (Req->argc > 1)
 		return IRC_WriteStrClient(Client, ERR_NORECIPIENT_MSG,
 					  Client_ID(Client), Req->command);
 
+	IRC_SetPenalty(Client, 2);
+
+	if ((Req->argc == 0 && array_bytes(&Conf_Helptext) > 0)
+	    || (Req->argc >= 1 && strcasecmp(Req->argv[0], "Commands") != 0)) {
+		/* Help text available and requested */
+		if (Req->argc >= 1)
+			return Help(Client, Req->argv[0]);
+
+		if (!Help(Client, "Intro"))
+			return DISCONNECTED;
+		return CONNECTED;
+	}
+
 	cmd = Parse_GetCommandStruct();
 	while(cmd->name) {
 		if (!IRC_WriteStrClient(Client, "NOTICE %s :%s",
@@ -331,12 +345,76 @@ IRC_HELP(CLIENT *Client, REQUEST *Req)
 			return DISCONNECTED;
 		cmd++;
 	}
-
-	IRC_SetPenalty(Client, 2);
 	return CONNECTED;
 } /* IRC_HELP */
 
 
+/**
+ * Send help for a given topic to the client.
+ *
+ * @param Client The client requesting help.
+ * @param Topoc The help topic requested.
+ * @return CONNECTED or DISCONNECTED.
+ */
+static bool
+Help(CLIENT *Client, const char *Topic)
+{
+	char *line;
+	size_t helptext_len, len_str, idx_start, lines = 0;
+	bool in_article = false;
+
+	assert(Client != NULL);
+	assert(Topic != NULL);
+
+	helptext_len = array_bytes(&Conf_Helptext);
+	line = array_start(&Conf_Helptext);
+	while (helptext_len > 0) {
+		len_str = strlen(line) + 1;
+		assert(helptext_len >= len_str);
+		helptext_len -= len_str;
+
+		if (in_article) {
+			/* The first character in each article text line must
+			 * be a TAB (ASCII 9) character which will be stripped
+			 * in the output. If it is not a TAB, the end of the
+			 * article has been reached. */
+			if (line[0] != '\t') {
+				if (lines > 0)
+					return CONNECTED;
+				else
+					break;
+			}
+
+			/* A single '.' character indicates an empty line */
+			if (line[1] == '.' && line[2] == '\0')
+				idx_start = 2;
+			else
+				idx_start = 1;
+
+			if (!IRC_WriteStrClient(Client, "NOTICE %s :%s",
+						Client_ID(Client),
+						&line[idx_start]))
+				return DISCONNECTED;
+			lines++;
+
+		} else {
+			if (line[0] == '-' && line[1] == ' '
+			    && strcasecmp(&line[2], Topic) == 0)
+				in_article = true;
+		}
+
+		line += len_str;
+	}
+
+	/* Help topic not found (or empty)! */
+	if (!IRC_WriteStrClient(Client, "NOTICE %s :No help for \"%s\" found!",
+				Client_ID(Client), Topic))
+		return DISCONNECTED;
+
+	return CONNECTED;
+}
+
+
 static char *
 #ifdef ZLIB
 Option_String(CONN_ID Idx)