src/parse.c
author Markus Bröker <mbroeker@largo.dyndns.tv>
Mon, 22 Feb 2010 19:06:15 +0100
changeset 47 a689b6a8e6ed
parent 45 535478a0f482
child 48 34094173351c
permissions -rw-r--r--
fgets may return a NULL pointer... fgets can return NULL and if it returns NULL, the application will be in an undefined state. committer: Markus Bröker <mbroeker@largo.homelinux.org>

/**
 *  $Id: parse.c 153 2008-04-27 07:26:15Z mbroeker $
 * $URL: http://localhost/svn/c/mcbot/trunk/src/parse.c $
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include <mcbot.h>
#include <database.h>
#include "common.h"

#include <locale.h>
#include <libintl.h>

#ifndef DATABASE_FILE
#define DATABASE_FILE "/var/lib/mcbot/data/mcbot.dat"
#endif

#ifndef SOURCE_URL
#define SOURCE_URL "http://largo.homelinux.org/cgi-bin/gitweb.cgi?p=net/mcbot.git"
#endif

enum command_map {
    HELP, JOIN, LEAVE, ADD, REPLACE, DELETE, LIST, SEARCH, INFO, PING, ON, OFF, DEBUG,
    VACCUUM, LOGOUT, WHO, WHOIS, TIME, TELL, OP, DEOP, KICK, BAN, UNBAN, KICKBAN, HELLO,
    TOPIC,
};

const
char *COMMAND_LIST[] = {
    "help      Known Commands: join(1), leave(2), add(3), replace(4), delete(5), list(6), search(7), info(8)\r\n",
    "join      Joins a new channel\r\n",
    "leave     Parts from the current channel\r\n",
    "add       adds an entry\r\n",
    "replace   replaces an entry\r\n",
    "delete    deletes an entry\r\n",
    "list      lists the number of stored values\r\n",
    "search    searches an entry up\r\n",
    "info      Prints the current Bot-Version\r\n",
    "ping      pings an host\r\n",
    "on        enables autolearning mode\r\n",
    "off       disables autolearning\r\n",
    "debug     prints some debug infos\r\n",
    "vaccuum   reorganizes the database\r\n",
    "logout    Protected logout function\r\n",
    "topic     Sets a new topic\r\n",
    NULL,
};

const
char VISIBLE_ITEMS = 14;

const
char *Bot_Commands[] = {
    "!help", "!join", "!leave",
    "!add", "!replace", "!delete",
    "!list", "!search", "!info",
    "!ping", "!on", "!off",
    "!debug", "!vaccuum", "!logout",
    "!who", "!whois", "!time",
    "!tell", "!op", "!deop",
    "!kick", "!ban", "!unban",
    "!kickban", "!hello", "!topic",
    NULL
};

char *parse (MSG * message)
{
    static char msg[DEFAULT_BUF_SIZE];
    int cmd = -1;
    enum command_map map;
    char *token;
    char *parameters;

    time_t t;
    struct tm *timeptr;

    /*
     * make sure that parseable data is available
     * this prevents a possible segmentation fault
     */
    if (message->user == NULL)
        message->user = "error";
    if (message->email == NULL)
        message->email = "server.err";

    /*
     * default message
     */
    snprintf (msg, sizeof (msg), "PRIVMSG %s :%s.\r\n", message->channel, gettext ("Request cannot be performed"));

    /*
     * PRIVATE MESSAGES
     */
    if (!strcmp (message->channel, message->nick))
        message->channel = message->user;

    /*
     * NO BOT Commands
     */
    if (*message->line != '!') {
        return NULL;
    }

    map = 0;
    token = strtok (message->line, " ");
    while (Bot_Commands[map]) {
        if (!strcmp (token, Bot_Commands[map])) {
            switch (map) {
            case HELP:
                if ((token = strtok (NULL, "\r\n")))
                    cmd = atoi (token);
                if ((cmd > 0) && (cmd < VISIBLE_ITEMS))
                    snprintf (msg, sizeof (msg), "PRIVMSG %s :%s\r\n", message->channel, COMMAND_LIST[cmd]);
                else
                    snprintf (msg, sizeof (msg), "PRIVMSG %s :%s\r\n", message->channel, COMMAND_LIST[0]);
                return msg;

            case JOIN:
                if ((token = strtok (NULL, "\r\n")))
                    if (strstr (message->user, db_lookup (DATABASE_FILE, "mcbot.user"))) {
                        if (strstr (message->email, db_lookup (DATABASE_FILE, "mcbot.email")))
                            snprintf (msg, sizeof (msg), "JOIN %s\r\n", token);
                    }
                return msg;

            case LEAVE:
                if (*message->channel != '#')
                    return NULL;
                if (strstr (message->user, db_lookup (DATABASE_FILE, "mcbot.user"))) {
                    if (strstr (message->email, db_lookup (DATABASE_FILE, "mcbot.email")))
                        snprintf (msg, sizeof (msg), "PART %s :Leaving.\r\n", message->channel);
                }
                return msg;

            case ADD:
                if ((token = strtok (NULL, " "))) {
                    if ((parameters = strtok (NULL, "\r\n"))) {
                        snprintf (msg, sizeof (msg), "PRIVMSG %s :%s, %s\r\n",
                                  message->channel, message->user, db_insert (DATABASE_FILE, token, parameters, 0));
                    } else {
                        snprintf (msg, sizeof (msg), "PRIVMSG %s :%s, %s!\r\n", message->channel,
                                  gettext ("I need more parameters to add"), message->user);
                    }
                }
                return msg;

            case REPLACE:
                if ((token = strtok (NULL, " "))) {
                    if ((parameters = strtok (NULL, "\r\n"))) {
                        snprintf (msg, sizeof (msg), "PRIVMSG %s :%s, %s\r\n",
                                  message->channel, message->user, db_insert (DATABASE_FILE, token, parameters, 1));
                    } else {
                        snprintf (msg, sizeof (msg), "PRIVMSG %s :%s, %s!\r\n", message->channel,
                                  gettext ("I need more parameters to replace"), message->user);
                    }
                }
                return msg;

            case DELETE:
                if ((token = strtok (NULL, "\r\n"))) {
                    snprintf (msg, sizeof (msg), "PRIVMSG %s :%s, %s\r\n",
                              message->channel, message->user, db_remove (DATABASE_FILE, token));
                } else {
                    snprintf (msg, sizeof (msg), "PRIVMSG %s :%s, %s!\r\n", message->channel,
                              gettext ("I need a key to delete"), message->user);
                }
                return msg;

            case LIST:
                snprintf (msg, sizeof (msg), "PRIVMSG %s :%s %s\r\n", message->channel, db_elements (DATABASE_FILE),
                          db_lookup (DATABASE_FILE, "mcbot.cgi"));
                return msg;

            case SEARCH:
                if ((token = strtok (NULL, "\r\n"))) {
                    snprintf (msg, sizeof (msg), "PRIVMSG %s :%s, %s\r\n", message->channel, message->user,
                              db_lookup (DATABASE_FILE, token));
                } else {
                    snprintf (msg, sizeof (msg),
                              "PRIVMSG %s :%s, %s!\r\n", message->channel, gettext ("I need a key to lookup"),
                              message->user);
                }
                return msg;

            case INFO:
                snprintf (msg, sizeof (msg),
                          "PRIVMSG %s :I am MCBot-%1.2f Build %s and my source code can be found at %s\r\n",
                          message->channel, BOT_VERSION, BOT_BUILD, SOURCE_URL);
                return msg;

            case PING:
                if ((token = strtok (NULL, "\r\n")))
                    snprintf (msg, sizeof (msg), "PRIVMSG %s :PING 0815\r\n", token);
                return msg;

            case ON:
                snprintf (msg, sizeof (msg), "PRIVMSG %s :%s %s.\r\n", message->user,
                          gettext ("Autolearn enabled for channel"), message->channel);
                return msg;

            case OFF:
                snprintf (msg, sizeof (msg), "PRIVMSG %s :%s %s.\r\n", message->user,
                          gettext ("Autolearn disabled for channel"), message->channel);
                return msg;

            case DEBUG:
                snprintf (msg, sizeof (msg), "PRIVMSG %s :USER: %s EMAIL: %s CHANNEL: %s LINE: %s\r\n",
                          message->channel, message->user, message->email, message->channel, message->line);
                return msg;

            case VACCUUM:
                snprintf (msg, sizeof (msg), "PRIVMSG %s :%s\r\n", message->channel, db_vaccuum (DATABASE_FILE));
                return msg;

            case LOGOUT:
                if (strstr (message->user, db_lookup (DATABASE_FILE, "mcbot.user"))) {
                    if (strstr (message->email, db_lookup (DATABASE_FILE, "mcbot.email"))) {
                        snprintf (msg, sizeof (msg), "PRIVMSG %s :%s!\r\nQUIT\r\n", message->channel,
                                  gettext ("Bye, have a nice day!"));
                    }
                }
                /*
                 * the returned message is either the default one or the generated one
                 */
                return msg;

            case WHO:
                if ((token = strtok (NULL, "\r\n")) != NULL) {
                    snprintf (msg, sizeof (msg), "WHO %s\r\n", token);
                }
                return msg;

            case WHOIS:
                if ((token = strtok (NULL, "\r\n")) != NULL) {
                    snprintf (msg, sizeof (msg), "WHOIS %s\r\n", token);
                }
                return msg;

            case TIME:
                t = time (NULL);
                timeptr = localtime (&t);
                if ((token = malloc (81))) {
                    strftime (token, 80, "%I:%M:%S %p", timeptr);
                    snprintf (msg, sizeof (msg), "PRIVMSG %s :%s %s, %s!\r\n", message->channel, gettext ("It is"),
                              token, message->user);
                    free (token);
                }
                return msg;

            case TELL:
                if ((token = strtok (NULL, " "))) {
                    if ((parameters = strtok (NULL, "\r\n"))) {
                        if (*token == '*')
                            message->channel = ++token;
                        snprintf (msg, sizeof (msg), "PRIVMSG %s :%s, %s\r\n", message->channel, token,
                                  db_lookup (DATABASE_FILE, parameters));
                    }
                }
                return msg;

            case OP:
                if ((token = strtok (NULL, "\r\n")) != NULL) {
                    if (strstr (message->user, db_lookup (DATABASE_FILE, "mcbot.user"))) {
                        if (strstr (message->email, db_lookup (DATABASE_FILE, "mcbot.email")))
                            snprintf (msg, sizeof (msg), "MODE %s +o %s\r\n", message->channel, token);
                    }
                }
                return msg;

            case DEOP:
                if ((token = strtok (NULL, "\r\n")) != NULL) {
                    if (strstr (message->user, db_lookup (DATABASE_FILE, "mcbot.user"))) {
                        if (strstr (message->email, db_lookup (DATABASE_FILE, "mcbot.email")))
                            snprintf (msg, sizeof (msg), "MODE %s -o %s\r\n", message->channel, token);
                    }
                }
                return msg;

            case KICK:
                if ((token = strtok (NULL, "\r\n")) != NULL) {
                    if (strstr (message->user, db_lookup (DATABASE_FILE, "mcbot.user"))) {
                        if (strstr (message->email, db_lookup (DATABASE_FILE, "mcbot.email")))
                            snprintf (msg, sizeof (msg), "KICK %s %s\r\n", message->channel, token);
                    }
                }
                return msg;

            case BAN:
                if ((token = strtok (NULL, "\r\n")) != NULL) {
                    if (strstr (message->user, db_lookup (DATABASE_FILE, "mcbot.user"))) {
                        if (strstr (message->email, db_lookup (DATABASE_FILE, "mcbot.email")))
                            snprintf (msg, sizeof (msg), "MODE %s +b %s\r\n", message->channel, token);
                    }
                }
                return msg;

            case UNBAN:
                if ((token = strtok (NULL, "\r\n")) != NULL) {
                    if (strstr (message->user, db_lookup (DATABASE_FILE, "mcbot.user"))) {
                        if (strstr (message->email, db_lookup (DATABASE_FILE, "mcbot.email")))
                            snprintf (msg, sizeof (msg), "MODE %s -b %s\r\n", message->channel, token);
                    }
                }
                return msg;

            case KICKBAN:
                if ((token = strtok (NULL, "\r\n")) != NULL) {
                    if (strstr (message->user, db_lookup (DATABASE_FILE, "mcbot.user"))) {
                        if (strstr (message->email, db_lookup (DATABASE_FILE, "mcbot.email")))
                            snprintf (msg, sizeof (msg), "MODE %s +b %s\r\nKICK %s %s\r\n", message->channel, token,
                                      message->channel, token);
                    }
                }
                return msg;

            case HELLO:
                snprintf (msg, sizeof (msg), "PRIVMSG %s :%s, %s?\r\n", message->channel, gettext ("What's up"),
                          message->user);
                return msg;

            case TOPIC:
                if ((token = strtok (NULL, "\r\n")) == NULL)
                    return NULL;

                snprintf (msg, sizeof (msg), "TOPIC %s :%s\r\n", message->channel, token);
                return msg;
            }
        }
        map++;
    }

    return NULL;
}