[ekg2-commit] r3787 - trunk/plugins/polchat: +trunk/plugins/polchat/polchat_handlers.c trunk/plugins/polchat/Makefile.am trunk/plugins/polchat/polchat.c
SVN commit
svn w toxygen.net
Pią, 15 Lut 2008, 18:31:20 CET
Author: darkjames
Date: 2008-02-15 18:31:19 +0100 (Fri, 15 Feb 2008)
New Revision: 3787
Added:
trunk/plugins/polchat/polchat_handlers.c
Modified:
trunk/plugins/polchat/Makefile.am
trunk/plugins/polchat/polchat.c
Log:
polchat v. 0.02
Modified: trunk/plugins/polchat/Makefile.am
===================================================================
--- trunk/plugins/polchat/Makefile.am 2008-02-15 16:19:31 UTC (rev 3786)
+++ trunk/plugins/polchat/Makefile.am 2008-02-15 17:31:19 UTC (rev 3787)
@@ -1,6 +1,9 @@
+EXTRA_DIST = polchat_handlers.c
+
lib_LTLIBRARIES = polchat.la
polchat_la_SOURCES = polchat.c
polchat_la_LDFLAGS = -module -avoid-version
+polchat_la_CPPFLAGS = $(C_FVISIBILITY)
libdir = $(plugindir)
Modified: trunk/plugins/polchat/polchat.c
===================================================================
--- trunk/plugins/polchat/polchat.c 2008-02-15 16:19:31 UTC (rev 3786)
+++ trunk/plugins/polchat/polchat.c 2008-02-15 17:31:19 UTC (rev 3787)
@@ -1,6 +1,6 @@
/*
* (C) Copyright 2006 Jakub 'ABUKAJ' Kowalski
- * Jakub 'darkjames' Zawadzki <darkjames w darkjames.ath.cx>
+ * (C) Copyright 2006, 2008 Jakub 'darkjames' Zawadzki <darkjames w darkjames.ath.cx>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License Version 2 as
@@ -16,6 +16,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
@@ -47,6 +48,8 @@
#include <ekg/xmalloc.h>
#include <ekg/userlist.h>
+#include <ekg/queries.h>
+
#define DEFQUITMSG "EKG2 - It's better than sex!"
#define SGQUITMSG(x) session_get(x, "QUIT_MSG")
#define QUITMSG(x) (SGQUITMSG(x)?SGQUITMSG(x):DEFQUITMSG)
@@ -54,14 +57,21 @@
typedef struct {
int fd;
int connecting;
+
+ char *nick;
+ char *room;
+ char *newroom;
+
+ string_t recvbuf;
} polchat_private_t;
-PLUGIN_DEFINE(polchat, PLUGIN_PROTOCOL, NULL);
+static int polchat_theme_init();
-#define POLCHAT_DEFAULT_HOST "polczat.pl"
-#define POLCHAT_DEFAULT_PORT 14003
-#define POLCHAT_DEFAULT_PORT_STR "14003"
+PLUGIN_DEFINE(polchat, PLUGIN_PROTOCOL, polchat_theme_init);
+#define POLCHAT_DEFAULT_HOST "s1.polchat.pl"
+#define POLCHAT_DEFAULT_PORT "14003"
+
/* HELPERS */
static inline char *dword_str(int dword) { /* 4 bajty BE */
static unsigned char buf[4];
@@ -69,33 +79,38 @@
buf[1] = (dword & 0x00ff0000) >> 16;
buf[2] = (dword & 0x0000ff00) >> 8;
buf[3] = (dword & 0x000000ff);
- return &buf[0];
+
+ return (char *) buf;
}
static inline char *word_str(short word) { /* 2 bajty BE */
static unsigned char buf[2];
buf[0] = (word & 0xff00) >> 8;
buf[1] = (word & 0x00ff);
- return &buf[0];
+
+ return (char *) buf;
}
/* w data rozmiar danych do wyslania */
static WATCHER_LINE(polchat_handle_write) {
static time_t t = 0; /* last time_t execute of this function */
- watch_t *next_watch = NULL;
- list_t l;
+
size_t fulllen = (size_t) data;
- int len = 0;
+ int len;
if (type)
return 0;
- if (t == time(NULL)) return 0; /* flood-protection */
+ if (t == time(NULL))
+ return 0; /* flood-protection [XXX] */
len = write(fd, watch, fulllen);
if (len == fulllen) { /* we sent all data, ok.. */
+ watch_t *next_watch = NULL;
+ list_t l;
+
/* turn on next watch */
for (l = watches; l; l = l->next) { /* watche sa od najnowszego po najstarszy.. dlatego musimy znalezc ostatni... */
@@ -109,21 +124,24 @@
next_watch->type = WATCH_WRITE; /* turn on watch */
t = time(NULL);
errno = 0;
+
} else if (len > 0) {
+ list_t l;
+
for (l = watches; l; l = l->next) {
watch_t *w = l->data;
if (w && w->fd == fd && w->type == WATCH_WRITE_LINE && w->data == data) { /* this watch */
w->data = (void *) fulllen - len;
+ break;
}
}
- }
+ }
return (fulllen == len) ? -1 : len;
}
-
-static watch_t *sendpkt(session_t *s, short headercode, ...) {
+static watch_t *polchat_sendpkt(session_t *s, short headercode, ...) {
va_list ap;
watch_t *w;
@@ -137,26 +155,36 @@
/* XXX, headercode brzydko */
if (!s || !(j = s->priv)) {
- debug("Invalid params\n");
+ debug_error("polchat_sendpkt() Invalid params\n");
return NULL;
}
+
fd = j->fd;
if (watch_find(&polchat_plugin, fd, WATCH_WRITE_LINE)) {
w = watch_add_line(&polchat_plugin, fd, WATCH_WRITE_LINE, polchat_handle_write, NULL);
w->type = WATCH_NONE;
- } else w = watch_add_line(&polchat_plugin, fd, WATCH_WRITE_LINE, polchat_handle_write, NULL);
+ } else
+ w = watch_add_line(&polchat_plugin, fd, WATCH_WRITE_LINE, polchat_handle_write, NULL);
- size = 8;
+ size = 8; /* size [4 bytes] + headers [4 bytes] */
- if (headercode) size += (2 * 1);
+ if (headercode)
+ size += (2 * 1);
va_start(ap, headercode);
while ((tmp = va_arg(ap, char *))) {
- /* XXX przekoduj na utf-8 */
- array_add(&arr, xstrdup(tmp));
- size += strlen(tmp) + 3;
+ char *r;
+
+ /* XXX, use cache */
+ if ((r = ekg_convert_string(tmp, NULL, "UTF-8"))) {
+ array_add(&arr, r);
+ size += strlen(r) + 3;
+ } else {
+ array_add(&arr, xstrdup(tmp));
+ size += strlen(tmp) + 3;
+ }
}
va_end(ap);
@@ -182,7 +210,22 @@
return w;
}
+static watch_t *polchat_sendmsg(session_t *s, const char *message, ...) {
+ va_list ap;
+ char *msg;
+ watch_t *res;
+
+ va_start(ap, message);
+ msg = vsaprintf(message, ap);
+ va_end(ap);
+
+ res = polchat_sendpkt(s, 0x019a, msg, NULL);
+
+ xfree(msg);
+ return res;
+}
+
static QUERY(polchat_validate_uid) {
char *uid = *(va_arg(ap, char **));
int *valid = va_arg(ap, int *);
@@ -190,7 +233,7 @@
if (!uid)
return 0;
- if (!xstrncmp(uid, "polchat:", 8) && *(uid+8) != '\0') {
+ if (!xstrncmp(uid, "polchat:", 8) && uid[8]) {
(*valid)++;
return -1;
}
@@ -199,532 +242,257 @@
}
static QUERY(polchat_print_version) {
- print("generic", "polchat plugin, proto code based on AmiX v0.2 (http://213.199.197.135/~kowalskijan/amix/) (c ABUKAJ), ekg2 <==> plugin code based on irc & jabber plugin");
+ print("generic",
+ "polchat plugin, proto code based on AmiX v0.2 (http://213.199.197.135/~kowalskijan/amix/) (c ABUKAJ) "
+ "and on http://eter.sytes.net/polchatproto/ v0.3");
return 0;
-}
+}
-static void polchat_private_init(session_t *s) {
+static QUERY(polchat_session_init) {
+ char *session = *(va_arg(ap, char**));
+ session_t *s = session_find(session);
polchat_private_t *j;
- if (!session_check(s, 0, "polchat"))
- return;
+ if (!s || s->priv || s->plugin != &polchat_plugin)
+ return 1;
- if (s->priv) return;
-
- userlist_free(s);
-
j = xmalloc(sizeof(polchat_private_t));
j->fd = -1;
+ j->recvbuf = string_init(NULL);
- session_connected_set(s, 0);
-
s->priv = j;
+
+ return 0;
}
-static void polchat_private_destroy(session_t *s) {
- polchat_private_t *j = s->priv;
+static QUERY(polchat_session_deinit) {
+ char *session = *(va_arg(ap, char**));
+ session_t *s = session_find(session);
+ polchat_private_t *j;
- if (!session_check(s, 1, "polchat"))
- return;
+ if (!s || !(j = s->priv) || s->plugin != &polchat_plugin)
+ return 1;
- xfree(j);
s->priv = NULL;
-}
-static QUERY(polchat_session) {
- char *session = *(va_arg(ap, char**));
- session_t *s = session_find(session);
+ string_free(j->recvbuf, 1);
- if (!s)
- return 0;
+ xfree(j->newroom);
+ xfree(j->room);
+ xfree(j->nick);
+ xfree(j);
- if (data)
- polchat_private_init(s);
- else
- polchat_private_destroy(s);
-
return 0;
}
static void polchat_handle_disconnect(session_t *s, const char *reason, int type) {
- polchat_private_t *j = s->priv;
- char *__session, *__reason;
- list_t l;
+ polchat_private_t *j;
+ if (!s || !(j = s->priv))
+ return;
+
+ if (!s->connected && !j->connecting)
+ return;
+
+ j->connecting = 0;
+ userlist_free(s);
+ {
+ char *__session = xstrdup(session_uid_get(s));
+ char *__reason = xstrdup(reason);
+
+ query_emit_id(NULL, PROTOCOL_DISCONNECTED, &__session, &__reason, &type);
+
+ xfree(__session);
+ xfree(__reason);
+ }
+
if (j->fd != -1) {
+ list_t l;
+
for (l = watches; l; l = l->next) {
watch_t *w = l->data;
if (!w || w->fd != j->fd) continue;
- if (w->type == WATCH_NONE || w->type == WATCH_WRITE_LINE)
+ if (1 /* || w->type == WATCH_NONE || w->type == WATCH_WRITE_LINE */)
watch_free(w);
}
close(j->fd);
j->fd = -1;
}
- s->connected = 0;
- j->connecting = 0;
+}
- userlist_free(s);
+#include "polchat_handlers.c"
+/* extern void polchat_processpkt(session_t *s, unsigned short nheaders, unsigned short nstrings, unsigned char *data, size_t len); */
-/* notify */
- __session = xstrdup(session_uid_get(s));
- __reason = xstrdup(reason);
- query_emit(NULL, ("protocol-disconnected"), &__session, &__reason, &type);
- xfree(__session);
- xfree(__reason);
-}
+static WATCHER_SESSION(polchat_handle_stream) {
+ polchat_private_t *j;
+ char buf[1024];
+ int len;
-static WATCHER(polchat_handle_resolver) {
if (type) {
-
+ polchat_handle_disconnect(s, NULL, EKG_DISCONNECT_NETWORK);
+ return 0;
}
- return 0;
-}
+ if (!s || !(j = s->priv))
+ return -1;
-static int polchat_mode_to_ekg_mode(unsigned short status) {
- if (status & 0x0002) return EKG_STATUS_AVAIL; /* OP */
- if (status & 0x0001) return EKG_STATUS_AWAY; /* moderator ? */
- return EKG_STATUS_XA; /* normal */
-}
+ if ((len = read(fd, buf, sizeof(buf))) > 0) {
+ unsigned char *buffer;
+
+ debug("polchat_handle_stream() read %d bytes from fd\n", len);
-static int hex_to_dec(unsigned char ch1, unsigned char ch2) {
- int res = 0;
+ string_append_raw(j->recvbuf, buf, len);
- if (xisdigit(ch1)) res = (ch1 - '0') << 4;
- else res = ((tolower(ch1)-'a')+10) << 4;
+ buffer = (unsigned char *) j->recvbuf->str;
- if (xisdigit(ch2)) res |= ch2 - '0';
- else res |= ((tolower(ch2)-'a')+10);
+ while (j->recvbuf->len >= 8) {
+ unsigned int rlen = (buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]);
- return res;
-}
+ debug("polchat_handle_stream() rlen: %u buflen: %d\n", rlen, j->recvbuf->len);
-static unsigned char *html_to_ekg2(unsigned char *tekst) {
- string_t str = string_init(NULL);
- int bold = 0;
- int underline = 0;
- char color = '\0';
-
- while (*tekst) {
- if (*tekst == '<') {
- int reset = 0;
-
- unsigned char *btekst = tekst;
- while (*tekst != '>' && *tekst != '\0')
- tekst++;
-
- if (*tekst == '\0') break;
- tekst++;
-
- if (btekst[1] == '/') {
- if (!xstrncmp("</u>", btekst, tekst-btekst)) underline = 0;
- if (!xstrncmp("</b>", btekst, tekst-btekst)) bold = 0;
- if (!xstrncmp("</font>", btekst, tekst-btekst)) color = 0;
-
- string_append(str, "%n"); reset = 1;
+ if (rlen < 8) { /* bad packet */
+ debug_error("polchat_handle_stream() RECV BAD PACKET rlen < 8\n");
+ return -1;
}
- if ((reset && underline) || (!underline && !xstrncmp("<u>", btekst, tekst-btekst))) {
- underline = 1;
- string_append(str, "%U");
+ if (rlen > 1024 * 1024) {
+ debug_error("polchat_handle_stream() RECV BAD PACKET rlen > 1MiB\n");
+ return -1;
}
- if (!reset && !xstrncmp("<font ", btekst, 6)) {
-#define ishex(x) ((x >= '0' && x <= '9') || (x >= 'A' && x <= 'F') || (x >= 'a' && x <= 'f'))
- unsigned char *fnt_color = xstrstr(btekst, " color=#");
- char new_color = color;
+ if (j->recvbuf->len >= rlen) {
+ short headerlen = buffer[4] << 8 | buffer[5];
+ short nstrings = buffer[6] << 8 | buffer[7];
- if (fnt_color && fnt_color < tekst) {
- if (ishex(fnt_color[8]) && ishex(fnt_color[9]) && ishex(fnt_color[10]) && ishex(fnt_color[11]) && ishex(fnt_color[12]) && ishex(fnt_color[13]))
- new_color = color_map(
- hex_to_dec(fnt_color[8], fnt_color[9]),
- hex_to_dec(fnt_color[10], fnt_color[11]),
- hex_to_dec(fnt_color[12], fnt_color[13]));
- if (new_color != color) {
- string_append_c(str, '%');
- string_append_c(str, bold ? toupper(new_color) : new_color);
- color = new_color;
- }
+ if (!headerlen && !nstrings) {
+ debug_error("polchat_handle_stream() <blink> CONNECTION LOST :-( </blink>");
+ return -1;
}
-#undef ishex
- } else if (reset && color) {
- string_append_c(str, '%');
- string_append_c(str, bold ? toupper(color) : color);
- continue;
- }
- if ((reset && bold) || (!bold && !xstrncmp("<b>", btekst, tekst-btekst))) {
- bold = 1;
- if (!color) string_append(str, "%T");
- else {
- string_append_c(str, '%');
- string_append_c(str, toupper(color));
- }
- }
- continue;
+ polchat_processpkt(s, headerlen, nstrings, &buffer[8], rlen-8);
- } else if (*tekst == '&') { /* eskejpniete */
- unsigned char *btekst = tekst;
- while (*tekst != ';' && *tekst != '\0')
- tekst++;
-
- if (*tekst == '\0') break;
- tekst++;
-
- if (!xstrncmp("&", btekst, tekst-btekst)) string_append_c(str, '&');
- if (!xstrncmp("<", btekst, tekst-btekst)) string_append_c(str, '<');
- if (!xstrncmp(">", btekst, tekst-btekst)) string_append_c(str, '>');
- if (!xstrncmp(""", btekst, tekst-btekst)) string_append_c(str, '\"');
- /* ... */
- continue;
+ string_remove(j->recvbuf, rlen);
+ } else
+ break;
}
-
- if (*tekst == '%' || *tekst == '\\')
- string_append_c(str, '\\');
-
- string_append_c(str, *tekst);
- tekst++;
+ return 0;
}
- return string_free(str, 0);
+
+ debug("polchat_handle_stream() Connection closed/ error XXX\n");
+ return -1;
}
-static void processpkt(session_t *s, unsigned short nheaders, unsigned short nstrings, unsigned char *data, size_t len) {
- polchat_private_t *j = s->priv;
+static WATCHER_SESSION(polchat_handle_connect) {
+ polchat_private_t *j;
+ const char *tmp;
- unsigned short *headers;
- unsigned char **strings;
- int unk = 0;
- int pok = 0;
- int i;
+ int res = 0;
+ socklen_t res_size = sizeof(res);
- debug("processpkt() pkt->headerlen: %d nstrings: %d len: %d\n", nheaders, nstrings, len);
- if (!len) return;
+ if (type)
+ return 0;
- headers = xcalloc(nheaders, sizeof(short));
- strings = xcalloc(nstrings+1, sizeof(char *));
-
-/* x naglowkow po 2 bajty kazdy (short) BE */
- for (i = 0; i < nheaders; i++) {
- if (len < 2) goto invalid_packet; len -= 2;
-
- headers[i] = data[0] << 8 | data[1];
- data += 2;
+ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res) {
+ polchat_handle_disconnect(s, strerror(res), EKG_DISCONNECT_FAILURE);
+ return -1;
}
-/* x stringow w &data[2] data[0..1] -> rozmiar, stringi NUL terminated */
- for (i = 0; i < nstrings; i++) {
- unsigned short strlen;
-
- if (len < 2) goto invalid_packet; len -= 2;
-
- strlen = (data[0] << 8 | data[1]);
+ if (!s || !(j = s->priv))
+ return -1;
- if (len < strlen+1) goto invalid_packet; len -= (strlen+1);
+ /* here we shouldn't have any WATCH_WRITE watch */
-/* XXX, przekonwertowac z utf-8 na locale */
- strings[i] = xstrndup(&data[2], strlen);
- data += (strlen + 3);
- }
+ j->connecting = 2;
- if (len)
- debug("processpkt() headers && string parsed but len left: %d\n", len);
+ polchat_sendpkt(s, 0x0578,
+ j->nick, /* nickname */
+ ((tmp = session_get(s, "password")) ? tmp : ""), /* password */
+ "", /* XXX cookie, always NUL? */
+ j->newroom + 8, /* pokoj */
+ /* XXX: */
+ "http://www.polchat.pl/chat/room.phtml/?room=AmiX", /* referer */
+ "polchat.pl", /* adres serwera */
+ "nlst=1&nnum=1&jlmsg=true&ignprv=false", /* konfiguracja */
+ "ekg2-CVS-polchat", /* klient */
+ NULL);
- pok = 1;
-
- if (nheaders) {
-#define HEADER0_ECHOREQUEST 0x0001
-#define HEADER0_MSG 0x0262
-#define HEADER0_PRIVMSG 0x0263
-#define HEADER0_CLIENTCONFIG 0x0266
-#define HEADER0_JOIN 0x0267
-#define HEADER0_PART 0x0268
-#define HEADER0_ROOMINFO 0x0271
-#define HEADER0_ROOMCONFIG 0x0272
-#define HEADER0_WELCOMEMSG 0x0276
-#define HEADER0_GOODBYEMSG 0x0277
-#define HEADER0_NICKLIST 0x026b
-#define HEADER0_ERRORMSG 0xffff
- /* move to another .c file or create callbacks... ( IF IT'LL BE MORE THAN 500 LINES... )*/
-
- switch (headers[0] & 0xffff) { /* '&' what for? */
- case HEADER0_ECHOREQUEST:
- if (nheaders == 1 && !nstrings) {
- sendpkt(s, 0x00, NULL);
-
- debug_function("processpkt() HEADER0_ECHOREQUEST\n");
- } else unk = 1;
- break;
-
- case HEADER0_MSG:
- if (nheaders == 1 && nstrings == 1) {
- char *tmp = html_to_ekg2(strings[0]);
- char *tmp2= format_string(tmp);
- xfree(tmp);
-
- print("none", tmp2);
- xfree(tmp2);
-
- debug_function("processpkt() HEADER0_MSG: %s\n", strings[0]);
- } else unk = 1;
- break;
-
- case HEADER0_CLIENTCONFIG:
- if (nheaders == 1 && nstrings == 1)
- debug("HEADER0_CLIENTCONFIG: %s\n", strings[0]);
- else unk = 1;
- break;
-
- case HEADER0_ROOMINFO:
- if (nheaders == 2 && nstrings == 2) {
- debug_function("processpkt() HEADER0_ROOMINFO: NAME: %s DESC: %s\n", strings[0], strings[1]);
- /* XXX, update j-> & use in ncurses header like irc-topic */
-#if 0
- xfree(roomname);
- roomname = xstrdup(strings[0]);
- xfree(roomdesc);
- roomdesc = xstrdup(strings[1]);
-#endif
- } else unk = 1;
- break;
-
- case HEADER0_JOIN:
- if (nheaders == 2 && nstrings == 1) {
- userlist_t *u;
- char *uid = saprintf("polchat:%s", strings[0]);
- char *tmp;
-
- u = userlist_add(s, uid, strings[0]);
-
- u->status = polchat_mode_to_ekg_mode(headers[1]);
-
- xfree(uid);
-
- if ((headers[1] & 0x00ff8c) != 0x0000)
- debug_error("Unknown status of: %s data: %.4x\n", strings[0], headers[1]);
-
- } else unk = 1;
- break;
-
- case HEADER0_PART:
- if (nheaders == 1 && nstrings == 1) {
- debug_function("processpkt() HEADER0_PART: %s\n", strings[0]);
- userlist_remove(s, userlist_find(s, strings[0]));
- } else unk = 1;
- break;
-
- case HEADER0_NICKLIST:
- if (nheaders >= 5 &&
- headers[1] == 0x0001 &&
- headers[2] == 0x0001 &&
- headers[3] == 0x0000 &&
- headers[4] == 0x0000) {
-
- for (i = 0; i < nstrings; i++) {
- debug_function("processpkt() HEADER0_NICKLIST: %s\n", strings[i]);
-#if 0
- addnick(ppart->strings[i], ppart->header[2 * i + 5], ppart->header[2 * i + 6]);
- if (((ppart->header[2 * i + 5] & 0x00ff8c) != 0x0000 || ppart->header[2 * i + 6] != 0x0000) && debug)
- debug_error("Unknown status of: %s data1: %.4x data2: %.4x\n", strings[i], headers[2 * i + 5], headers[2 * i + 6]);
-#endif
- }
- } else unk = 1;
- break;
-
- case HEADER0_ROOMCONFIG:
- if (nheaders == 1 && nstrings == 2) {
- debug_function("HEADER0_ROOMCONFIG: %s\n", strings[0]);
-#if 0
- if (NULL != (ptr = strstr(ppart->strings[0], "color_user=")))
- {
- ptr += 11;
- sscanf(ptr, "#%x", &tmp);
- colourt[0] = transformrgb((tmp >> 16) & 0x00FF, (tmp >> 8) & 0x00FF, tmp & 0x00FF);
- }
- if (NULL != (ptr = strstr(ppart->strings[0], "color_op=")))
- {
- ptr += 9;
- sscanf(ptr, "#%x", &tmp);
- colourop = transformrgb((tmp >> 16) & 0x00FF, (tmp >> 8) & 0x00FF, tmp & 0x00FF);
- }
- if (NULL != (ptr = strstr(ppart->strings[0], "color_guest=")))
- {
- ptr += 12;
- tmp = sscanf(ptr, "#%x #%x #%x #%x #%x #%x #%x", &tempt[0],
- &tempt[1], &tempt[2], &tempt[3], &tempt[4], &tempt[5],
- &tempt[6]);
- for (i = 0; i <tmp; i++)
- {
- colourt[i + 1] = transformrgb((tempt[i] >> 16) & 0x00FF, (tempt[i] >> 8) & 0x00FF, tempt[i] & 0x00FF);
- }
-#endif
- } else unk = 1;
- break;
-
- case HEADER0_WELCOMEMSG:
- if (nheaders == 1 && nstrings == 1) {
- /* new-status */
- s->status = EKG_STATUS_AVAIL;
- /* connected */
- j->connecting = 0;
- s->connected = 1;
- /* notify */
- char *__session = xstrdup(s->uid);
- query_emit(NULL, "protocol-connected", &__session);
- xfree(__session);
-
- debug_function("processpkt() HEADER0_WELCOMEMSG: %s\n", strings[0]);
- } else unk = 1;
- break;
-
- case HEADER0_GOODBYEMSG:
- if (nheaders == 1 && nstrings == 1) {
- userlist_free(s);
-
- debug_function("HEADER0_GOODBYEMSG: %s\n", strings[0]);
- } else unk = 1;
- break;
-
- case HEADER0_PRIVMSG:
- if (nheaders == 1 && nstrings == 2) {
- debug("processpkt() HEADER0_PRIVMSG INC(?) : NICK: %s MSG: %s\n", strings[1], strings[0]);
- } else if (nheaders == 1 && nstrings == 3) {
- debug("processpkt() HEADER0_PRIVMSG OUT(?) : UNK[0]: %s\nUNK[1]: %s\nMSG: %s\n", strings[0], strings[1], strings[2]);
- } else unk = 1;
- break;
-#if 0
- case 0x0269:/*NICK update*/
- if (nheaders == 2 && nstrings == 1) {
- /* addnick(ppart->strings[0], ppart->header[1], 0x0000); */
-
- if ((headers[1] & 0x00ff8c) != 0x0000) {
- debug_error("Unknown status of: %s data: %.4x\n", strings[0], headers[1]);
- } else unk = 1;
- break;
-
- case 0x026a:/*I have absolutly no idea - chyba ze wlazlem jako ja???*/
- if (nheaders == 2 && nstrings == 1) {
- if (headers[1] != 0x0004)
- debug_error("0x0004 != %.4x NICK: %s\n", headers[1], strings[0]);
- } else unk = 1;
- break;
-#endif
-
- case HEADER0_ERRORMSG:
- if (nheaders == 1 && nstrings == 1) {
- /* XXX, utf -> locale */
- polchat_handle_disconnect(s, strings[0], EKG_DISCONNECT_FAILURE);
- } else unk = 1;
- break;
-
- case 0x0000:
- default:
- unk = 1;
- }
- } else debug_error("processpkt() XXX nheaders == 0 !!!\n");
-
- if (unk) {
- int i;
- debug_error("processpkt() XXX nheaders: %d nstrings: %d\n\t", nheaders, nstrings);
- for (i = 0; i < nheaders; i++)
- debug_error("headers[%d]: %.4x ", i, headers[i]);
-
- debug_error("\n");
- for (i = 0; i < nstrings; i++)
- debug_error("\tstrings[%d]: %s\n", i, strings[i]);
-
- debug_error("\n");
- }
-
-invalid_packet:
- if (!pok)
- debug_error("invalid len packet!! exploit warning?\n");
-
- xfree(headers);
- array_free((char **) strings);
+ watch_add_session(s, fd, WATCH_READ, polchat_handle_stream);
+ return -1;
}
-static WATCHER(polchat_handle_stream) {
- session_t *s = session_find(data);
- polchat_private_t *j;
+static WATCHER(polchat_handle_resolver) {
+ session_t *s = session_find((char *) data);
+ polchat_private_t *j;
- unsigned char buffer[4];
- unsigned char *result = NULL;
- int len;
+ struct sockaddr_in sin;
+ struct in_addr a;
- if (type) {
- if (s && session_connected_get(s))
- polchat_handle_disconnect(s, NULL, EKG_DISCONNECT_NETWORK);
+ int one = 1;
+ int port;
+ int res;
+
+ if (type) {
xfree(data);
- return 0;
+ close(fd);
+ return 0;
}
if (!s || !(j = s->priv))
return -1;
- /* XXX tutaj fragmentacja... sprawdzic czy mamy j->buffer .. jesli mamy j->buffer to dodajemy do bufora i sprawdzamy czy dl. == j->bufferlen */
+ res = read(fd, &a, sizeof(a));
- if ((len = read(fd, buffer, 4)) == 4) {
- unsigned int rlen = (buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3])-4;
- debug("STEP1: Read 4 bytes from fd, ok rlen: %d (%d)\n", rlen);
+ if ((res != sizeof(a)) || (res && a.s_addr == INADDR_NONE /* INADDR_NONE kiedy NXDOMAIN */)) {
+ if (res == -1)
+ debug_error("[polchat] unable to read data from resolver: %s\n", strerror(errno));
+ else
+ debug_error("[polchat] read %d bytes from resolver. not good\n", res);
- result = xmalloc(rlen);
+ /* no point in reconnecting by polchat_handle_disconnect() */
- if ((len = read(fd, result, rlen)) < rlen) {
- debug("STEP2: Err Read %d bytes from fd, fragmented packed?\n", len);
- xfree(result);
- return -1;
- } else {
- struct {
- short headerlen __attribute__((__packed__));
- short nstrings __attribute__((__packed__));
- unsigned char data[] __attribute__((__packed__));
- } *pkt = (void *) result;
+ print("conn_failed", format_find("conn_failed_resolving"), session_name(s));
+ j->connecting = 0;
+ return -1;
+ }
- if (!pkt->headerlen && !pkt->nstrings) {
- debug("<blink> CONNECTION LOST :-( </blink>");
- xfree(result);
- return -1;
- }
+ debug_function("[polchat] resolved to %s\n", inet_ntoa(a));
- processpkt(s, ntohs(pkt->headerlen), ntohs(pkt->nstrings), pkt->data, len-4);
- }
- xfree(result);
- } else if (len > 0) {
- debug("Read %d bytes from fd: %d not good, fragmented packed?\n", len, fd);
- return -1; /* XXX */
- } else {
- debug("Connection closed/ error XXX\n");
+ port = session_int_get(s, "port");
+ if (port < 0 || port > 65535)
+ port = atoi(POLCHAT_DEFAULT_PORT);
+
+ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+ debug("[polchat] socket() failed: %s\n", strerror(errno));
+ polchat_handle_disconnect(s, strerror(errno), EKG_DISCONNECT_FAILURE);
return -1;
}
- return 0;
-}
-static WATCHER(polchat_handle_connect) {
- session_t *s = session_find(data);
- polchat_private_t *j;
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(port);
+ sin.sin_addr.s_addr = a.s_addr;
- if (type) {
- xfree(data);
- return 0;
- }
+ if (ioctl(fd, FIONBIO, &one) == -1)
+ debug_error("[polchat] ioctl() FIONBIO failed: %s\n", strerror(errno));
+ if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one)) == -1)
+ debug_error("[polchat] setsockopt() SO_KEEPALIVE failed: %s\n", strerror(errno));
- if (!s || !(j = s->priv)) {
- debug("session: %s deleted\n", data);
+ res = connect(fd, (struct sockaddr *) &sin, sizeof(struct sockaddr_in));
+
+ if (res == -1 && errno != EINPROGRESS) {
+ int err = errno;
+
+ debug_error("[polchat] connect() failed: %s (errno=%d)\n", strerror(err), err);
+ polchat_handle_disconnect(s, strerror(err), EKG_DISCONNECT_FAILURE);
return -1;
}
- j->connecting = 2;
-/* XXX, oproznij watche? */
- sendpkt(s, 0x0578,
- "darkjames", "", "", "aaaaaszcxzczxcz",
- /* XXX j->nick, j->pass, j->roompass, j->room, */
- "http://www.polchat.pl/chat/room.phtml/?room=AmiX", "polchat.pl", "nlst=1&nnum=1&jlmsg=true&ignprv=false", "ekg2-CVS-polchat", NULL);
+ j->fd = fd;
- watch_add(&polchat_plugin, fd, WATCH_READ, polchat_handle_stream, xstrdup(data));
+ watch_add_session(s, fd, WATCH_WRITE, polchat_handle_connect);
+
return -1;
}
@@ -732,13 +500,8 @@
polchat_private_t *j = session->priv;
const char *server;
const char *nick;
+ const char *room;
- int fd;
- int port;
- struct sockaddr_in sin;
- int one = 1;
- int res;
-
if (j->connecting) {
printq("during_connect", session_name(session));
return -1;
@@ -759,46 +522,45 @@
return -1;
}
- port = session_int_get(session, "port");
- if (port < 0 || port > 65535)
- port = POLCHAT_DEFAULT_PORT;
+ if (!(room = session_get(session, "room"))) {
+ room = session->uid + 8;
+ }
-
- if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
- debug("[polchat] socket() failed: %s\n", strerror(errno));
- polchat_handle_disconnect(session, strerror(errno), EKG_DISCONNECT_FAILURE);
+ if (!(*room)) {
+ printq("generic_error", "gdzie lecimy ziom ?! [/session room]");
return -1;
}
- j->connecting = 1;
+ xfree(j->room);
+ j->room = NULL;
- sin.sin_family = AF_INET;
- sin.sin_port = htons(port);
- sin.sin_addr.s_addr = inet_addr("64.34.174.225");
+ xfree(j->nick);
+ j->nick = xstrdup(nick);
- if (ioctl(fd, FIONBIO, &one) == -1) debug("[polchat] ioctl() FIONBIO failed: %s\n", strerror(errno));
- if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one)) == -1) debug("[polchat] setsockopt() SO_KEEPALIVE failed: %s\n", strerror(errno));
+ xfree(j->newroom);
+ j->newroom = saprintf("polchat:%s", room);
- res = connect(fd, (struct sockaddr *) &sin, sizeof(struct sockaddr_in));
+ string_clear(j->recvbuf);
- if (res == -1 && errno != EINPROGRESS) {
- debug("[polchat] connect() failed: %s (errno=%d)\n", strerror(errno), errno);
- polchat_handle_disconnect(session, strerror(errno), EKG_DISCONNECT_FAILURE);
+ j->connecting = 1;
+
+ if (ekg_resolver2(&polchat_plugin, server, polchat_handle_resolver, xstrdup(session->uid)) == NULL) {
+ print("generic_error", strerror(errno));
+ j->connecting = 0;
return -1;
}
- j->fd = fd;
+ printq("connecting", session_name(session));
- watch_add(&polchat_plugin, fd, WATCH_WRITE, polchat_handle_connect, xstrdup(session->uid));
return 0;
}
static COMMAND(polchat_command_disconnect) {
- polchat_private_t *j = session->priv;
- const char *reason = params[0]?params[0]:QUITMSG(session);
+ polchat_private_t *j = session->priv;
+ const char *reason = params[0]?params[0]:QUITMSG(session);
- if (timer_remove(&polchat_plugin, "reconnect") == 0) { /* XXX here, coz we can remove wrong reconnect timer for more than one polchat session */
+ if (timer_remove_session(session, "reconnect") == 0) {
printq("auto_reconnect_removed", session_name(session));
return 0;
}
@@ -809,9 +571,7 @@
}
if (reason && session_connected_get(session)) {
- char *quitmsg = saprintf("/quit %s", reason);
- sendpkt(session, 0x019a, quitmsg, NULL);
- xfree(quitmsg);
+ polchat_sendmsg(session, "/quit %s", reason);
}
if (j->connecting)
@@ -822,48 +582,99 @@
return 0;
}
-
static COMMAND(polchat_command_reconnect) {
polchat_private_t *j = session->priv;
if (j->connecting || session_connected_get(session))
polchat_command_disconnect(name, params, session, target, quiet);
+
return polchat_command_connect(name, params, session, target, quiet);
}
static COMMAND(polchat_command_msg) {
/* w target -> target */
- /* XXX, params[1] MUST BE in utf-8 otherwise it'll disconnect session, likes some jabberd do. */
- sendpkt(session, 0x019a, params[1], NULL);
-/* NOTE: sending `/quit` msg disconnect session */ /* XXX, escape? */
+ /* NOTE: sending `/quit` msg disconnect session */ /* XXX, escape? */
+/* polchat_sendpkt(session, 0x019a, params[1], NULL); */
+ polchat_sendmsg(session, "%s", params[1]);
+
return 0;
}
static COMMAND(polchat_command_inline_msg) {
const char *p[2] = { NULL, params[0] };
+
+ if (!session->connected)
+ return -1;
+
if (!target || !params[0])
return -1;
+
return polchat_command_msg(("msg"), p, session, target, quiet);
}
+static COMMAND(polchat_command_part) {
+ polchat_private_t *j = session->priv;
+
+ if (!j->room) {
+ printq("invalid_params", name);
+ return 0;
+ }
+
+ polchat_sendmsg(session, "/part");
+
+ return 0;
+}
+
+static COMMAND(polchat_command_join) {
+ polchat_private_t *j = session->priv;
+
+ if (j->newroom) {
+ debug_error("/join but j->newroom: %s\n", j->newroom);
+
+ printq("generic_error", "Too fast, or please look at debug.");
+ return 0;
+ }
+
+ polchat_sendmsg(session, "/join %s", params[0]);
+
+ j->newroom = saprintf("polchat:%s", params[0]);
+
+ return 0;
+}
+
+static int polchat_theme_init() {
+#ifndef NO_DEFAULT_THEME
+/*
+ format_add("polchat_joined", _("%> %Y%2%n has joined %3"), 1);
+ format_add("polchat_joined_you", _("%> %RYou%n have joined %3"), 1);
+ */
+#endif
+ return 0;
+}
+
static plugins_params_t polchat_plugin_vars[] = {
- PLUGIN_VAR_ADD("alias", VAR_STR, 0, 0, NULL),
+ PLUGIN_VAR_ADD("alias", VAR_STR, NULL, 0, NULL),
PLUGIN_VAR_ADD("auto_connect", VAR_BOOL, "0", 0, NULL),
PLUGIN_VAR_ADD("log_formats", VAR_STR, "irssi", 0, NULL),
PLUGIN_VAR_ADD("nickname", VAR_STR, NULL, 0, NULL),
- PLUGIN_VAR_ADD("port", VAR_INT, POLCHAT_DEFAULT_PORT_STR, 0, NULL),
+ PLUGIN_VAR_ADD("password", VAR_STR, NULL, 1, NULL),
+ PLUGIN_VAR_ADD("port", VAR_INT, POLCHAT_DEFAULT_PORT, 0, NULL),
+ PLUGIN_VAR_ADD("room", VAR_STR, NULL, 0, NULL),
PLUGIN_VAR_ADD("server", VAR_STR, POLCHAT_DEFAULT_HOST, 0, NULL),
PLUGIN_VAR_END()
};
-int polchat_plugin_init(int prio) {
+EXPORT int polchat_plugin_init(int prio) {
polchat_plugin.params = polchat_plugin_vars;
+
plugin_register(&polchat_plugin, prio);
- query_connect(&polchat_plugin, "protocol-validate-uid", polchat_validate_uid, NULL);
- query_connect(&polchat_plugin, "session-added", polchat_session, (void*) 1);
- query_connect(&polchat_plugin, "session-removed", polchat_session, (void*) 0);
- query_connect(&polchat_plugin, "plugin-print-version", polchat_print_version, NULL);
+
+ query_connect_id(&polchat_plugin, PROTOCOL_VALIDATE_UID, polchat_validate_uid, NULL);
+ query_connect_id(&polchat_plugin, SESSION_ADDED, polchat_session_init, NULL);
+ query_connect_id(&polchat_plugin, SESSION_REMOVED, polchat_session_deinit, NULL);
+ query_connect_id(&polchat_plugin, PLUGIN_PRINT_VERSION, polchat_print_version, NULL);
+
#if 0
query_connect(&irc_plugin, ("ui-window-kill"), irc_window_kill, NULL);
query_connect(&irc_plugin, ("irc-topic"), irc_topic_header, NULL);
@@ -874,20 +685,20 @@
#define POLCHAT_FLAGS POLCHAT_ONLY | SESSION_MUSTBECONNECTED
#define POLCHAT_FLAGS_TARGET POLCHAT_FLAGS | COMMAND_ENABLEREQPARAMS | COMMAND_PARAMASTARGET
- command_add(&polchat_plugin, "polchat:", "?", polchat_command_inline_msg, POLCHAT_FLAGS, NULL);
+ command_add(&polchat_plugin, "polchat:", "?", polchat_command_inline_msg, POLCHAT_ONLY, NULL);
command_add(&polchat_plugin, "polchat:msg", "!uUw !", polchat_command_msg, POLCHAT_FLAGS_TARGET, NULL);
command_add(&polchat_plugin, "polchat:connect", NULL, polchat_command_connect, POLCHAT_ONLY, NULL);
command_add(&polchat_plugin, "polchat:disconnect", "r ?",polchat_command_disconnect,POLCHAT_ONLY, NULL);
command_add(&polchat_plugin, "polchat:reconnect", "r ?", polchat_command_reconnect, POLCHAT_ONLY, NULL);
+ command_add(&polchat_plugin, "polchat:part", "r", polchat_command_part, POLCHAT_ONLY, NULL);
+ command_add(&polchat_plugin, "polchat:join", "!uUw", polchat_command_join, POLCHAT_FLAGS_TARGET, NULL);
+
return 0;
}
static int polchat_plugin_destroy() {
- list_t l;
- for (l = sessions; l; l = l->next)
- polchat_private_destroy((session_t*) l->data);
-
plugin_unregister(&polchat_plugin);
return 0;
}
+
Added: trunk/plugins/polchat/polchat_handlers.c
===================================================================
--- trunk/plugins/polchat/polchat_handlers.c (rev 0)
+++ trunk/plugins/polchat/polchat_handlers.c 2008-02-15 17:31:19 UTC (rev 3787)
@@ -0,0 +1,572 @@
+#if 0
+
+#include <ekg/debug.h>
+#include <ekg/dynstuff.h>
+#include <ekg/userlist.h>
+#include <ekg/xmalloc.h>
+
+#include <ekg/themes.h> /* ? */
+
+#include <ekg/queries.h>
+
+#endif
+
+/* TODO:
+ * - uzywac konwerterow.
+ * - uzywac uint16_t, uint32_t
+ */
+
+static int polchat_mode_to_ekg_mode(unsigned short status) {
+#if 0
+ int kolorek = (status >> 4);
+#endif
+
+ if (status & 0x0002) return EKG_STATUS_AVAIL; /* OP */
+ if (status & 0x0001) return EKG_STATUS_AWAY; /* priv? */
+ return EKG_STATUS_XA; /* normal */
+
+
+/*
+ if ((status & 0x00ff8c) != 0x0000)
+ debug_error("Unknown status data: %.4x\n", status);
+ */
+}
+
+static int hex_to_dec(unsigned char ch1, unsigned char ch2) {
+ int res = 0;
+
+ if (xisdigit(ch1)) res = (ch1 - '0') << 4;
+ else res = ((tolower(ch1)-'a')+10) << 4;
+
+ if (xisdigit(ch2)) res |= ch2 - '0';
+ else res |= ((tolower(ch2)-'a')+10);
+
+ return res;
+}
+
+static char *html_to_ekg2(char *tekst) {
+ string_t str;
+
+ int bold = 0;
+ int underline = 0;
+ char color = '\0';
+
+ debug_white("html_to_ekg2() %s\n", tekst);
+
+ str = string_init(NULL);
+
+ while (*tekst) {
+ if (*tekst == '<') {
+ int reset = 0;
+ char *btekst = tekst;
+
+ while (*tekst && *tekst != '>')
+ tekst++;
+
+ if (*tekst == '\0')
+ break;
+
+ tekst++;
+
+ if (btekst[1] == '/') {
+ if (!xstrncmp("</u>", btekst, tekst-btekst)) underline = 0;
+ if (!xstrncmp("</b>", btekst, tekst-btekst)) bold = 0;
+ if (!xstrncmp("</font>", btekst, tekst-btekst)) color = 0;
+
+ string_append(str, "%n"); reset = 1;
+ }
+
+ if ((reset && underline) || (!underline && !xstrncmp("<u>", btekst, tekst-btekst))) {
+ underline = 1;
+ string_append(str, "%U");
+ }
+
+ if (!reset && !xstrncmp("<font ", btekst, 6)) {
+#define ishex(x) ((x >= '0' && x <= '9') || (x >= 'A' && x <= 'F') || (x >= 'a' && x <= 'f'))
+ char *fnt_color = xstrstr(btekst, " color=");
+ char new_color = color;
+
+ if (fnt_color && fnt_color < tekst) {
+ if (fnt_color[7] == '#' &&
+ ishex(fnt_color[8]) && ishex(fnt_color[9]) &&
+ ishex(fnt_color[10]) && ishex(fnt_color[11]) &&
+ ishex(fnt_color[12]) && ishex(fnt_color[13]))
+ {
+ new_color = color_map(
+ hex_to_dec(fnt_color[8], fnt_color[9]),
+ hex_to_dec(fnt_color[10], fnt_color[11]),
+ hex_to_dec(fnt_color[12], fnt_color[13]));
+ } else {
+ if (!xstrncasecmp(&(fnt_color[7]), "red", 3)) new_color = 'r';
+ else
+ debug_error("NOT IMPLEMENTED COLOR=\n");
+
+
+ }
+
+
+ if (new_color != color) {
+ string_append_c(str, '%');
+ string_append_c(str, bold ? toupper(new_color) : new_color);
+ color = new_color;
+ }
+ }
+#undef ishex
+ } else if (reset && color) {
+ string_append_c(str, '%');
+ string_append_c(str, bold ? toupper(color) : color);
+ continue;
+ }
+
+ if ((reset && bold) || (!bold && !xstrncmp("<b>", btekst, tekst-btekst))) {
+ bold = 1;
+ if (!color) string_append(str, "%T");
+ else {
+ string_append_c(str, '%');
+ string_append_c(str, toupper(color));
+ }
+ }
+ continue;
+
+ } else if (*tekst == '&') { /* eskejpniete */
+ char *btekst = tekst;
+
+ /* here we do trick:
+ * We go forward until ';' or NUL is found
+ * When we found ';'
+ *
+ * We match strings with ';' so we convert only valid html-escaped tags
+ */
+
+ while (*tekst && *tekst != ';')
+ tekst++;
+
+ if (*tekst)
+ tekst++;
+
+ if (0);
+ else if (!xstrncmp("&", btekst, tekst-btekst)) string_append_c(str, '&');
+ else if (!xstrncmp("<", btekst, tekst-btekst)) string_append_c(str, '<');
+ else if (!xstrncmp(">", btekst, tekst-btekst)) string_append_c(str, '>');
+ else if (!xstrncmp(""", btekst, tekst-btekst)) string_append_c(str, '\"');
+ /* ... */
+ else {
+ char *tmp = xstrndup(btekst, tekst - btekst);
+
+ debug_error("html_to_ekg2() invalid/unknown escaped-tag [%s]\n", tmp);
+ string_append(str, tmp);
+
+ xfree(tmp);
+ }
+
+ continue;
+ }
+
+ if (*tekst == '%' || *tekst == '\\')
+ string_append_c(str, '\\');
+
+ string_append_c(str, *tekst);
+ tekst++;
+ }
+ return string_free(str, 0);
+}
+
+#define POLCHAT_HANDLER(x) static int x(session_t *s, int nheaders, int nstrings, unsigned short *headers, char **strings)
+
+POLCHAT_HANDLER(polchat_echo_request) {
+ if (nheaders == 1 && !nstrings) {
+ polchat_sendpkt(s, 0x00, NULL);
+ return 0;
+ }
+
+ return 1;
+}
+
+POLCHAT_HANDLER(polchat_msg) {
+ polchat_private_t *j = s->priv;
+
+ if (nheaders == 1 && nstrings == 1) {
+ char *tmp = html_to_ekg2(strings[0]);
+ char *tmp2= format_string(tmp);
+
+ print_window(j->room, s, 1, "none", tmp2);
+
+ xfree(tmp2);
+ xfree(tmp);
+
+ return 0;
+ }
+ return 1;
+}
+
+POLCHAT_HANDLER(polchat_privmsg) {
+ if (nheaders == 1 && nstrings == 2) {
+ debug("polchat_processpkt() HEADER0_PRIVMSG INC(?) : NICK: %s MSG: %s\n", strings[1], strings[0]);
+ return 0;
+ } else if (nheaders == 1 && nstrings == 3) {
+ debug("polchat_processpkt() HEADER0_PRIVMSG OUT(?) : UNK[0]: %s\nUNK[1]: %s\nMSG: %s\n", strings[0], strings[1], strings[2]);
+ return 0;
+ }
+
+ return 1;
+}
+
+POLCHAT_HANDLER(polchat_roomconfig) {
+ if (nheaders == 1 && nstrings == 2) {
+#if 0
+ if ((ptr = strstr(ppart->strings[0], "color_user=")))
+ {
+ ptr += 11;
+ sscanf(ptr, "#%x", &tmp);
+ colourt[0] = transformrgb((tmp >> 16) & 0x00FF, (tmp >> 8) & 0x00FF, tmp & 0x00FF);
+ }
+ if ((ptr = strstr(ppart->strings[0], "color_op=")))
+ {
+ ptr += 9;
+ sscanf(ptr, "#%x", &tmp);
+ colourop = transformrgb((tmp >> 16) & 0x00FF, (tmp >> 8) & 0x00FF, tmp & 0x00FF);
+ }
+ if ((ptr = strstr(ppart->strings[0], "color_guest=")))
+ {
+ ptr += 12;
+ tmp = sscanf(ptr, "#%x #%x #%x #%x #%x #%x #%x", &tempt[0],
+ &tempt[1], &tempt[2], &tempt[3], &tempt[4], &tempt[5],
+ &tempt[6]);
+ for (i = 0; i <tmp; i++)
+ {
+ colourt[i + 1] = transformrgb((tempt[i] >> 16) & 0x00FF, (tempt[i] >> 8) & 0x00FF, tempt[i] & 0x00FF);
+ }
+ }
+#endif
+ return 0;
+ }
+ return 1;
+}
+
+POLCHAT_HANDLER(polchat_clientconfig) {
+ if (nheaders == 1 && nstrings == 1)
+ return 0;
+ return 1;
+}
+
+POLCHAT_HANDLER(polchat_join) {
+ if (nheaders == 2 && nstrings == 1) {
+ userlist_t *u;
+ char *uid;
+
+ uid = saprintf("polchat:%s", strings[0]);
+
+ /* XXX, userlist_find() */
+
+ if ((u = userlist_add(s, uid, strings[0]))) {
+ u->status = polchat_mode_to_ekg_mode(headers[1]);
+
+ query_emit_id(NULL, USERLIST_REFRESH);
+ }
+
+ xfree(uid);
+
+ return 0;
+ }
+ return 1;
+}
+
+POLCHAT_HANDLER(polchat_part) {
+ if (nheaders == 1 && nstrings == 1) {
+ userlist_remove(s, userlist_find(s, strings[0]));
+
+ query_emit_id(NULL, USERLIST_REFRESH);
+
+ return 0;
+ }
+ return 1;
+}
+
+POLCHAT_HANDLER(polchat_roominfo) {
+ if (nheaders == 2 && nstrings == 2) {
+ debug_function("polchat_roominfo() HEADER0_ROOMINFO: NAME: %s DESC: %s\n", strings[0], strings[1]);
+ /* XXX, update j-> & use in ncurses header like irc-topic */
+#if 0
+ xfree(roomname);
+ roomname = xstrdup(strings[0]);
+ xfree(roomdesc);
+ roomdesc = xstrdup(strings[1]);
+#endif
+ return 0;
+ }
+ return 1;
+}
+
+POLCHAT_HANDLER(polchat_welcomemsg) {
+ polchat_private_t *j = s->priv;
+
+ if (nheaders == 1 && nstrings == 1) {
+ window_t *w;
+
+ if (j->connecting) {
+ /* new-status */
+ s->status = EKG_STATUS_AVAIL;
+ /* connected */
+ j->connecting = 0;
+
+ {
+ char *__session = xstrdup(s->uid);
+ query_emit_id(NULL, PROTOCOL_CONNECTED, &__session);
+ xfree(__session);
+ }
+
+ }
+
+ if (j->room) {
+ debug_error("polchat_welcomemsg() but j->room: %s [newone: %s]\n", j->room, __(j->newroom));
+ xfree(j->room);
+ }
+
+ j->room = j->newroom;
+ j->newroom = NULL;
+
+ if (!(w = window_find_s(s, j->room)))
+ w = window_new(j->room, s, 0);
+
+
+ {
+ char *tmp = html_to_ekg2(strings[0]);
+ char *tmp2= format_string(tmp);
+
+ print_window_w(w, 1, "none", tmp2);
+
+ xfree(tmp2);
+ xfree(tmp);
+ }
+
+ return 0;
+ }
+
+ return 1;
+}
+
+POLCHAT_HANDLER(polchat_goodbyemsg) {
+ polchat_private_t *j = s->priv;
+
+ if (nheaders == 1 && nstrings == 1) {
+ userlist_free(s);
+
+ {
+ char *tmp = html_to_ekg2(strings[0]);
+ char *tmp2= format_string(tmp);
+
+ print_window(j->room, s, 1, "none", tmp2);
+
+ xfree(tmp2);
+ xfree(tmp);
+ }
+
+ if (!j->room)
+ debug_error("polchat_goodbyemsg() but j->room == NULL\n");
+
+ xfree(j->room);
+ j->room = NULL;
+
+ return 0;
+ }
+
+ return 1;
+}
+
+POLCHAT_HANDLER(polchat_nicklist) {
+ if (nheaders >= 5 && headers[1] == 0x0001 && headers[2] == 0x0001 && headers[3] == 0x0000 && headers[4] == 0x0000) {
+ int i;
+
+ for (i = 0; i < nstrings; i++) {
+ userlist_t *u;
+ char *uid;
+
+ debug_function("polchat_processpkt() HEADER0_NICKLIST: %s\n", strings[i]);
+
+ uid = saprintf("polchat:%s", strings[i]);
+
+ /* XXX, userlist_find() */
+
+ if ((u = userlist_add(s, uid, strings[i]))) {
+
+ if (nheaders >= 1 + (5 + 2 * i)) {
+ u->status = polchat_mode_to_ekg_mode(headers[5 + 2 * i]);
+ } else {
+ debug_error("polchat_nicklist() ERROR: %d vs %d\n", 5 + 2 * i, nheaders);
+ u->status = EKG_STATUS_ERROR;
+ }
+
+ /* XXX, atrybuty lokalne w headers[5 + 2 * i + 1] */
+ }
+
+ xfree(uid);
+ }
+
+ query_emit_id(NULL, USERLIST_REFRESH);
+ return 0;
+ }
+ return 1;
+}
+
+POLCHAT_HANDLER(polchat_errormsg) {
+ if (nheaders == 1 && nstrings == 1) {
+ polchat_handle_disconnect(s, strings[0], EKG_DISCONNECT_FAILURE);
+ return 0;
+ }
+ return 1;
+}
+
+POLCHAT_HANDLER(polchat_wejoin) {
+ polchat_private_t *j = s->priv;
+
+ if (nheaders == 2 && nstrings == 1) {
+ if (headers[1] != 0x0004) return 1;
+
+ if (xstrcmp(j->nick, strings[0])) {
+ if (j->nick[0] == '~') return 1;
+
+ /* fix nick, if we've got at beg '~' <-- anonymous */
+
+ if (strings[0][0] != '~' || xstrcmp(j->nick, &(strings[0][1]))) {
+ debug_error("polchat_wejoin() j->nick [%s] vs str0 [%s]\n", j->nick, strings[0]);
+ return 1;
+ }
+
+ xfree(j->nick);
+ j->nick = xstrdup(strings[0]);
+ }
+
+/* print_window(j->room, s, 1, "polchat_joined_you", session_name(s), j->nick, j->room + 8); */
+
+ return 0;
+ }
+ return 1;
+}
+
+POLCHAT_HANDLER(polchat_nick_update) {
+ if (nheaders == 2 && nstrings == 1) {
+ userlist_t *u;
+
+ if (!(u = userlist_find(s, strings[0]))) {
+ debug_error("polchat_nick_update() UNKNOWN NICK\n");
+ return 1;
+ }
+
+ u->status = polchat_mode_to_ekg_mode(headers[1]);
+ query_emit_id(NULL, USERLIST_REFRESH);
+
+ return 0;
+ }
+ return 1;
+}
+
+struct {
+ char *name;
+ unsigned short id;
+ int (*handler)(session_t *, int nheaders, int nstrings, unsigned short *headers, char **strings);
+
+} polchat_handlers[] = {
+ { "HEADER0_ECHOREQUEST", 0x0001, polchat_echo_request },
+ { "HEADER0_MSG", 0x0262, polchat_msg },
+ { "HEADER0_PRIVMSG", 0x0263, polchat_privmsg },
+ { "HEADER0_CLIENTCONFIG", 0x0266, polchat_clientconfig },
+ { "HEADER0_JOIN", 0x0267, polchat_join },
+ { "HEADER0_PART", 0x0268, polchat_part },
+ { "HEADER0_ROOMINFO", 0x0271, polchat_roominfo },
+ { "HEADER0_ROOMCONFIG", 0x0272, polchat_roomconfig },
+ { "HEADER0_WELCOMEMSG", 0x0276, polchat_welcomemsg },
+ { "HEADER0_GOODBYEMSG", 0x0277, polchat_goodbyemsg },
+ { "HEADER0_NICKLIST", 0x026b, polchat_nicklist },
+ { "HEADER0_ERRORMSG", 0xffff, polchat_errormsg },
+
+ { "HEADER0_WEJOIN", 0x026a, polchat_wejoin },
+ { "HEADER0_NICKUPDATE", 0x0269, polchat_nick_update },
+ { NULL, 0, NULL }
+};
+
+void polchat_processpkt(session_t *s, unsigned short nheaders, unsigned short nstrings, unsigned char *data, size_t len) {
+ unsigned short *headers = NULL;
+ char **strings = NULL;
+ int unk;
+ int pok = 0;
+ int i;
+
+ debug("polchat_processpkt() nheaders: %d nstrings: %d len: %d\n", nheaders, nstrings, len);
+
+ if (!len)
+ return;
+
+ headers = xcalloc(nheaders, sizeof(unsigned short));
+ strings = xcalloc(nstrings+1, sizeof(char *));
+
+/* x naglowkow po 2 bajty kazdy (short) BE */
+ for (i = 0; i < nheaders; i++) {
+ if (len < 2) goto invalid_packet; len -= 2;
+
+ headers[i] = data[0] << 8 | data[1];
+ data += 2;
+ }
+
+/* x stringow w &data[2] data[0..1] -> rozmiar, stringi NUL terminated */
+ for (i = 0; i < nstrings; i++) {
+ unsigned short strlen;
+
+ if (len < 2) goto invalid_packet; len -= 2;
+
+ strlen = (data[0] << 8 | data[1]);
+
+ if (len < strlen+1) goto invalid_packet; len -= (strlen+1);
+
+ /* rekoduj, uzywaj cache (?) */
+ {
+ char *tmp = xstrndup(&data[2], strlen);
+
+ if ((strings[i] = ekg_convert_string(tmp, "UTF-8", NULL)))
+ xfree(tmp);
+ else
+ strings[i] = tmp;
+ }
+
+ data += (2 + strlen + 1);
+ }
+
+ if (len)
+ debug_error("polchat_processpkt() headers && string parsed but len left: %d\n", len);
+
+ pok = 1;
+ unk = 1;
+
+ if (nheaders) {
+ int i;
+
+ for (i = 0; polchat_handlers[i].name; i++) {
+ if (polchat_handlers[i].id == headers[0]) {
+ debug("polchat_processpkt() %s [0x%.4x, %d] \n", polchat_handlers[i].name, polchat_handlers[i].id, polchat_handlers[i].id);
+
+ unk = polchat_handlers[i].handler(s, nheaders, nstrings, headers, strings);
+ break;
+ }
+ }
+ }
+
+ if (unk) {
+ int i;
+ debug_error("polchat_processpkt() XXX nheaders: %d nstrings: %d\n\t", nheaders, nstrings);
+ for (i = 0; i < nheaders; i++)
+ debug_error("headers[%d]: %.4x [%d]\n", i, headers[i], headers[i]);
+
+ debug_error("\n");
+ for (i = 0; i < nstrings; i++)
+ debug_error("\tstrings[%d]: %s\n", i, strings[i]);
+
+ debug_error("\n");
+ }
+
+invalid_packet:
+ if (!pok)
+ debug_error("polchat_processpkt() invalid len packet!! exploit warning?\n");
+
+ xfree(headers);
+ array_free(strings);
+}
+
Więcej informacji o liście dyskusyjnej ekg2-commit