first raw version of the xchat rxpd plugin
authorChristian Thaeter <ct@pipapo.org>
Sat, 3 Nov 2007 06:59:18 +0000 (07:59 +0100)
committerChristian Thaeter <ct@pipapo.org>
Sat, 3 Nov 2007 06:59:18 +0000 (07:59 +0100)
contrib/irc/xchat/rx.c [new file with mode: 0644]

diff --git a/contrib/irc/xchat/rx.c b/contrib/irc/xchat/rx.c
new file mode 100644 (file)
index 0000000..b600eba
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+    rx.c - rxpd plugin for xchat
+
+  Copyright (C)
+    2007,               Christian Thaeter <ct@pipapo.org>
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+//#include <sys/resource.h>
+#include <netinet/in.h>
+//#include <arpa/inet.h>
+//#include <fcntl.h>
+//#include <time.h>
+#include <netdb.h>
+#include <sys/uio.h>
+
+#include "xchat-plugin.h"
+
+#define PNAME "RxpdPlugin"
+#define PDESC "Uses rxpd to act on content";
+#define PVERSION "0.1"
+
+#define PREFIXCMP(str, pfx) (!strncmp (str, (pfx), sizeof (pfx)-1))
+
+static xchat_plugin *ph;   /* plugin handle */
+
+static struct rx_plugin_data
+{
+  int debug;
+  const char* server;
+  const char* port;
+  const char* prefix;
+  const char* list;
+  int fd;               /* the fd used for CHECK:list */
+  char* eol;
+  char* eob;
+  char buffer[4096];
+} rx_private;
+
+
+static char*
+buffer_readline (struct rx_plugin_data* self)
+{
+  ssize_t r;
+
+  if (self->eol < self->eob)
+    {
+      //there was a line pending, shift buffer left
+      memmove (self->buffer, self->eol+1, self->eob - self->eol - 1);
+      self->eob = (char*)(self->eob - (self->eol - self->buffer + 1));
+      self->eol = self->buffer;
+      // TODO handle \r's
+    }
+
+  do {
+    // find next newline, terminate string there
+    char* i;
+    for (i = self->buffer; i < self->eob; ++i)
+      {
+        if (*i == '\n')
+          {
+            *i = '\0';
+            self->eol = i;
+            // have line, return it
+            return (self->eob == self->buffer) ? NULL : self->buffer;
+          }
+      }
+
+    r = 0;
+    do
+      {
+        r = read (self->fd, self->eob, 4095 - (self->eob - self->buffer));
+      }
+    while (r == -1 && errno == EINTR);
+
+    if (r != -1)
+      self->eob += r;
+
+  } while (r != -1);
+
+  return NULL;
+}
+
+
+
+void
+xchat_plugin_get_info (char **name,
+                       char **desc,
+                       char **version,
+                       void **reserved)
+{
+   *name = PNAME;
+   *desc = PDESC;
+   *version = PVERSION;
+}
+
+static int
+rxstart_cb (char *word[], char *word_eol[], void *userdata)
+{
+  //  server port list; enables and connects to rxpd", &rx_private);
+  struct rx_plugin_data* rx = (struct rx_plugin_data*)userdata;
+
+  rx->server = strdup (word[2]);
+  rx->port = strdup (word[3]);
+  rx->list = strdup (word[4]);
+
+  struct addrinfo* addrs = NULL;
+  int aierr;
+
+  /* resolve peer */
+  aierr = getaddrinfo (rx->server, rx->port, NULL, &addrs);
+  if (aierr)
+    {
+      xchat_printf (ph, "could not resolve %s:%s, %s\n", rx->server, rx->port, gai_strerror (aierr));
+      return XCHAT_EAT_ALL;
+    }
+
+  rx->fd = socket (addrs->ai_family, addrs->ai_socktype, addrs->ai_protocol);
+  if (rx->fd == -1 || connect (rx->fd, addrs->ai_addr, addrs->ai_addrlen))
+    {
+      freeaddrinfo (addrs);
+      xchat_printf (ph, "error connecting %s:%s, %s\n", rx->server, rx->port, strerror (errno));
+      return XCHAT_EAT_ALL;
+    }
+  freeaddrinfo (addrs);
+
+  struct iovec cmd[3] =
+    {
+      {"CHECK:", sizeof("CHECK:")-1},
+      {(void*)rx->list, strlen (rx->list)},
+      {"\n", 1}
+    };
+
+  ssize_t written = writev (rx->fd, cmd, 3);
+  if (written < cmd[0].iov_len + cmd[1].iov_len + cmd[2].iov_len)
+    {
+      xchat_printf (ph, "error writing check commmand\n");
+      close (rx->fd);
+      rx->fd = -1;
+      return XCHAT_EAT_ALL;
+    }
+
+  if (rx->debug)
+    xchat_printf (ph, "established rxpd connection to %s:%s\n", rx->server, rx->port);
+
+  return XCHAT_EAT_ALL;
+}
+
+static int
+rxstop_cb (char *word[], char *word_eol[], void *userdata)
+{
+  struct rx_plugin_data* rx = (struct rx_plugin_data*)userdata;
+
+  if (rx->fd != -1)
+    {
+      close (rx->fd);
+      rx->fd = -1;
+      if (rx->debug)
+        xchat_printf (ph, "closed rxpd connection to %s:%s\n", rx->server, rx->port);
+    }
+  else
+    if (rx->debug)
+      xchat_printf (ph, "no rxpd connection established\n");
+
+  return XCHAT_EAT_ALL;
+}
+
+static int
+rxadd_cb (char *word[], char *word_eol[], void *userdata)
+{
+  //struct rx_plugin_data* rx = (struct rx_plugin_data*)userdata;
+  return XCHAT_EAT_ALL;   /* eat this command so xchat and other plugins can't process it */
+}
+
+static int
+rxdel_cb (char *word[], char *word_eol[], void *userdata)
+{
+  //struct rx_plugin_data* rx = (struct rx_plugin_data*)userdata;
+  return XCHAT_EAT_ALL;   /* eat this command so xchat and other plugins can't process it */
+}
+
+static int
+rxlist_cb (char *word[], char *word_eol[], void *userdata)
+{
+  //struct rx_plugin_data* rx = (struct rx_plugin_data*)userdata;
+  return XCHAT_EAT_ALL;   /* eat this command so xchat and other plugins can't process it */
+}
+
+static int
+rxraw_cb (char *word[], char *word_eol[], void *userdata)
+{
+  //struct rx_plugin_data* rx = (struct rx_plugin_data*)userdata;
+  return XCHAT_EAT_ALL;   /* eat this command so xchat and other plugins can't process it */
+}
+
+static int
+rxdebug_cb (char *word[], char *word_eol[], void *userdata)
+{
+  struct rx_plugin_data* rx = (struct rx_plugin_data*)userdata;
+  rx->debug ^= 1;
+  xchat_printf (ph, "Turned rxpd debugging %s\n", rx->debug?"on":"off");  
+  return XCHAT_EAT_ALL;
+}
+
+static int
+rxhook_cb (char *word[], char *word_eol[], void *userdata)
+{
+  struct rx_plugin_data* rx = (struct rx_plugin_data*)userdata;
+
+  if (rx->fd != -1)
+    {
+      /* ok do the checking*/
+
+      struct iovec check[2] =
+        {
+          {(void*)word_eol[1], strlen (word_eol[1])},
+          {"\n", 1}
+        };
+
+      ssize_t written = writev (rx->fd, check, 2);
+      if (written < check[0].iov_len + 1)
+        {
+          xchat_printf (ph, "RXPD: error writing\n");
+          close (rx->fd);
+          rx->fd = -1;
+          return XCHAT_EAT_NONE;
+        }
+
+      char* line = buffer_readline (rx);
+
+      if (rx->debug && !PREFIXCMP(line, "ok:"))
+        xchat_printf (ph, "RXPD: '%s'\n", line);
+
+      if (PREFIXCMP(line, "ignore:"))
+        return XCHAT_EAT_XCHAT;
+
+      //else if (PREFIXCMP(line, "kick:"))
+      //else if (PREFIXCMP(line, "kickban:"))
+      //else if (PREFIXCMP(line, "ban:"))
+      //else if (PREFIXCMP(line, "op:"))
+
+    }
+
+  return XCHAT_EAT_NONE;
+}
+
+int
+xchat_plugin_init(xchat_plugin *plugin_handle,
+                  char **plugin_name,
+                  char **plugin_desc,
+                  char **plugin_version,
+                  char *arg)
+{
+  /* we need to save this for use with any xchat_* functions */
+  ph = plugin_handle;
+
+  /* tell xchat our info */
+  *plugin_name = PNAME;
+  *plugin_desc = PDESC;
+  *plugin_version = PVERSION;
+
+  rx_private.debug = 0;
+  rx_private.server = NULL;
+  rx_private.port = NULL;
+  rx_private.list = NULL;
+  rx_private.fd = -1;
+  rx_private.eol = rx_private.eob = rx_private.buffer;
+  rx_private.buffer [4095] = '\0';
+
+  xchat_hook_command (ph, "RXSTART", XCHAT_PRI_NORM, rxstart_cb,
+                      "Usage: RXSTART server port list; enables and connects to rxpd", &rx_private);
+
+  xchat_hook_command (ph, "RXSTOP", XCHAT_PRI_NORM, rxstop_cb,
+                      "Usage: RXSTOP; disconnects and stops rxpd plugin", &rx_private);
+
+  xchat_hook_command (ph, "RXADD", XCHAT_PRI_NORM, rxadd_cb,
+                      "Usage: RXADD listname rule; adds rule to list", &rx_private);
+
+  xchat_hook_command (ph, "RXDEL", XCHAT_PRI_NORM, rxdel_cb,
+                      "Usage: RXDEL list rule; removes rule from list", &rx_private);
+
+  xchat_hook_command (ph, "RXLIST", XCHAT_PRI_NORM, rxlist_cb,
+                      "Usage: RXLIST [list]; shows list", &rx_private);
+
+  xchat_hook_command (ph, "RXRAW", XCHAT_PRI_NORM, rxraw_cb,
+                      "Usage: RXRAW ...; sends a raw command to the rxpd", &rx_private);
+
+  xchat_hook_command (ph, "RXDEBUG", XCHAT_PRI_NORM, rxdebug_cb,
+                      "Usage: RXDEBUG; toggle rxpd plugin debugging", &rx_private);
+
+  xchat_hook_server (ph, "RAW LINE", XCHAT_PRI_NORM, rxhook_cb, &rx_private);
+
+  xchat_print (ph, "Rxpd plugin loaded successfully!\n");
+
+  return 1;
+}