]> arthur.barton.de Git - ngircd-alex.git/commitdiff
Merge branch 'bug145-ProvideHelp'
authorAlexander Barton <alex@barton.de>
Wed, 2 Jan 2013 22:41:46 +0000 (23:41 +0100)
committerAlexander Barton <alex@barton.de>
Wed, 2 Jan 2013 22:41:46 +0000 (23:41 +0100)
* bug145-ProvideHelp:
  Use "${docdir}/Commands.txt" as help text file
  Add a note that "help file" is updated on startup and REHASH only
  Add doc/Commands.txt which should document all commands
  Implement Help() function parsing and returning the help text
  Document "HelpFile" in sample-ngircd.conf and ngircd.conf.5
  Implement new configuration option "HelpFile"
  IRC_HELP(): Code cleanup
  Refactor Read_Motd() into Read_TextFile()

1  2 
src/ngircd/irc.c

diff --combined src/ngircd/irc.c
index a678f9048e68d0c27b43d55533e333621d730543,f6b9dc59b6086c060aa2dc5c1c5f7a1c521ebe1d..e76abcb8a4af00250d819d00d332ca4a5cdc0f65
@@@ -44,6 -44,7 +44,7 @@@ static bool Send_Message PARAMS((CLIEN
  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));
  
  
  /**
@@@ -81,17 -82,6 +82,17 @@@ IRC_ERROR( CLIENT *Client, REQUEST *Re
        assert( Client != NULL );
        assert( Req != NULL );
  
 +      if (Client_Type(Client) != CLIENT_GOTPASS
 +          && Client_Type(Client) != CLIENT_GOTPASS_2813
 +          && Client_Type(Client) != CLIENT_UNKNOWNSERVER
 +          && Client_Type(Client) != CLIENT_SERVER
 +          && Client_Type(Client) != CLIENT_SERVICE) {
 +              LogDebug("Ignored ERROR command from \"%s\" ...",
 +                       Client_Mask(Client));
 +              IRC_SetPenalty(Client, 2);
 +              return CONNECTED;
 +      }
 +
        if (Req->argc < 1)
                Log(LOG_NOTICE, "Got ERROR from \"%s\"!",
                    Client_Mask(Client));
@@@ -315,29 -305,116 +316,116 @@@ IRC_TRACE( CLIENT *Client, REQUEST *Re
  } /* IRC_TRACE */
  
  
+ /**
+  * Handler for the IRC "HELP" command.
+  *
+  * @param Client The client from which this command has been received.
+  * @param Req Request structure with prefix and all parameters.
+  * @return CONNECTED or DISCONNECTED.
+  */
  GLOBAL bool
- IRC_HELP( CLIENT *Client, REQUEST *Req )
+ IRC_HELP(CLIENT *Client, REQUEST *Req)
  {
        COMMAND *cmd;
  
-       assert( Client != NULL );
-       assert( Req != NULL );
+       assert(Client != NULL);
+       assert(Req != NULL);
  
        /* Bad number of arguments? */
-       if( Req->argc > 0 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command );
+       if (Req->argc > 1)
+               return IRC_WriteStrClient(Client, ERR_NORECIPIENT_MSG,
+                                         Client_ID(Client), Req->command);
  
-       cmd = Parse_GetCommandStruct( );
-       while( cmd->name )
-       {
-               if( ! IRC_WriteStrClient( Client, "NOTICE %s :%s", Client_ID( Client ), cmd->name )) return DISCONNECTED;
+       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",
+                                       Client_ID(Client), cmd->name))
+                       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)