From: Enlightenment S. <no-...@en...> - 2010-08-31 03:07:42
|
Log: I can't even begin to explain every change, but in summary I've done the following: - Improved IRC message parsing (what a pita!) - Included support (or better support) for a few commands. Namely PRIVMSG, JOIN, and PART. - Cleaned up a segv on shutdown - Some other misc tweaks/fixes I wouldn't recommend it for daily use yet, but it's coming along. Author: mekius Date: 2010-08-30 20:07:34 -0700 (Mon, 30 Aug 2010) New Revision: 51769 Modified: trunk/PROTO/emote/src/bin/em_gui.c trunk/PROTO/emote/src/bin/em_gui.h trunk/PROTO/emote/src/bin/main.c trunk/PROTO/emote/src/lib/Emote.h trunk/PROTO/emote/src/lib/emote_event.c trunk/PROTO/emote/src/lib/emote_protocol.c trunk/PROTO/emote/src/lib/emote_types.h trunk/PROTO/emote/src/lib/protocols/irc/irc.c trunk/PROTO/emote/src/lib/protocols/irc/irc.h trunk/PROTO/emote/src/lib/protocols/irc/irc_parse.c Modified: trunk/PROTO/emote/src/bin/em_gui.c =================================================================== --- trunk/PROTO/emote/src/bin/em_gui.c 2010-08-31 01:13:45 UTC (rev 51768) +++ trunk/PROTO/emote/src/bin/em_gui.c 2010-08-31 03:07:34 UTC (rev 51769) @@ -112,14 +112,28 @@ EM_INTERN void em_gui_channel_add(const char *server, const char *channel, Emote_Protocol *p) { + // FIXME: Need to stash this item somewhere so we can delete it later. elm_hoversel_item_add(gui->o_chansel, channel, NULL, ELM_ICON_NONE, _em_gui_hoversel_cb_item_clicked, server); } EM_INTERN void -em_gui_message_add(const char *server, const char *channel, const char *text) +em_gui_channel_del(const char *server, const char *channel, Emote_Protocol *p) { - elm_scrolled_entry_entry_insert(gui->o_chantxt, text); + // FIXME: See em_gui_channel_add, need pointer to delete it. +} + +EM_INTERN void +em_gui_message_add(const char *server, const char *channel, const char *user, const char *text) +{ + char buf[4096]; + + if (user) + snprintf(buf, sizeof(buf), "%s: %s<br>", user, text); + else + snprintf(buf, sizeof(buf), "*: %s<br>", text); + + elm_scrolled_entry_entry_insert(gui->o_chantxt, buf); elm_scrolled_entry_cursor_end_set(gui->o_chantxt); } @@ -165,26 +179,36 @@ _em_gui_entry_cb_enter(void *data __UNUSED__, Evas_Object *obj, void *event __UNUSED__) { const char *text; - char msg[5012]; + //char msg[5012]; Emote_Event *d; text = elm_scrolled_entry_entry_get(obj); - snprintf(msg, sizeof(msg), "%s", text); + //snprintf(msg, sizeof(msg), "%s", text); d = emote_event_new( eina_hash_find(em_protocols, "irc"), - EMOTE_EVENT_CHAT_CHANNEL_MESSAGE_SEND, + EMOTE_EVENT_CHAT_MESSAGE_SEND, "irc.freenode.net", "#emote", "emote", - msg + text ); emote_event_send(d); - elm_scrolled_entry_cursor_end_set(gui->o_chantxt); - elm_scrolled_entry_entry_insert(gui->o_chantxt, text); - elm_scrolled_entry_cursor_end_set(gui->o_chantxt); - elm_scrolled_entry_entry_insert(gui->o_chantxt, "<br>"); - elm_scrolled_entry_cursor_end_set(gui->o_chantxt); + // Single /, don't print to textblock + if (!((text[0] == '/') && (text[1] != '/'))) + { + // We have // at beginning of string + if (text[0] == '/') text++; + + // Add message to textblock + elm_scrolled_entry_cursor_end_set(gui->o_chantxt); + elm_scrolled_entry_entry_insert(gui->o_chantxt, text); + elm_scrolled_entry_cursor_end_set(gui->o_chantxt); + elm_scrolled_entry_entry_insert(gui->o_chantxt, "<br>"); + elm_scrolled_entry_cursor_end_set(gui->o_chantxt); + } + + // Clear entry elm_scrolled_entry_entry_set(obj, NULL); } Modified: trunk/PROTO/emote/src/bin/em_gui.h =================================================================== --- trunk/PROTO/emote/src/bin/em_gui.h 2010-08-31 01:13:45 UTC (rev 51768) +++ trunk/PROTO/emote/src/bin/em_gui.h 2010-08-31 03:07:34 UTC (rev 51769) @@ -6,7 +6,7 @@ # ifndef EM_GUI_H # define EM_GUI_H -struct _Em_Gui +struct _Em_Gui { Em_Object em_obj_inherit; @@ -21,7 +21,8 @@ EM_INTERN int em_gui_init(void); EM_INTERN void em_gui_server_add(const char *server, Emote_Protocol *p); EM_INTERN void em_gui_channel_add(const char *server, const char *channel, Emote_Protocol *p); -EM_INTERN void em_gui_message_add(const char *server, const char *channel, const char *text); +EM_INTERN void em_gui_channel_del(const char *server, const char *channel, Emote_Protocol *p); +EM_INTERN void em_gui_message_add(const char *server, const char *channel, const char *user, const char *text); EM_INTERN int em_gui_shutdown(void); # endif Modified: trunk/PROTO/emote/src/bin/main.c =================================================================== --- trunk/PROTO/emote/src/bin/main.c 2010-08-31 01:13:45 UTC (rev 51768) +++ trunk/PROTO/emote/src/bin/main.c 2010-08-31 03:07:34 UTC (rev 51769) @@ -52,11 +52,13 @@ _em_main_chat_events_handler, NULL); emote_event_handler_add(EMOTE_EVENT_SERVER_DISCONNECTED, _em_main_chat_events_handler, NULL); - emote_event_handler_add(EMOTE_EVENT_CHAT_CHANNEL_JOINED, + emote_event_handler_add(EMOTE_EVENT_CHAT_JOINED, _em_main_chat_events_handler, NULL); + emote_event_handler_add(EMOTE_EVENT_CHAT_PARTED, + _em_main_chat_events_handler, NULL); emote_event_handler_add(EMOTE_EVENT_SERVER_MESSAGE_RECEIVED, _em_main_chat_events_handler, NULL); - emote_event_handler_add(EMOTE_EVENT_CHAT_CHANNEL_MESSAGE_RECEIVED, + emote_event_handler_add(EMOTE_EVENT_CHAT_MESSAGE_RECEIVED, _em_main_chat_events_handler, NULL); em_protocols = eina_hash_string_superfast_new(NULL); @@ -149,9 +151,10 @@ c = emote_event_new ( EMOTE_EVENT_T(d)->protocol, - EMOTE_EVENT_CHAT_CHANNEL_JOIN, + EMOTE_EVENT_CHAT_JOIN, d->server, - "#emote" + "#emote", + "emote" ); emote_event_send(c); break; @@ -165,29 +168,62 @@ d->server, EMOTE_EVENT_T(d)->protocol->api->label); break; } - case EMOTE_EVENT_CHAT_CHANNEL_JOINED: + case EMOTE_EVENT_CHAT_JOINED: { - Emote_Event_Chat_Channel *d; + Emote_Event_Chat *d; + char buf[8192]; d = event; - em_gui_channel_add(EMOTE_EVENT_SERVER_T(d)->server, d->channel, EMOTE_EVENT_T(d)->protocol); + // FIXME: Make this check the actual username based on the server + if (!strcmp(d->user, "emote")) + { + snprintf(buf, sizeof(buf), "You have joined %s", d->channel); + em_gui_message_add(EMOTE_EVENT_SERVER_T(d)->server, NULL, NULL, buf); + em_gui_channel_add(EMOTE_EVENT_SERVER_T(d)->server, d->channel, EMOTE_EVENT_T(d)->protocol); + } + else + { + snprintf(buf, sizeof(buf), "%s has joined %s", d->user, d->channel); + em_gui_message_add(EMOTE_EVENT_SERVER_T(d)->server, NULL, NULL, buf); + } break; } + case EMOTE_EVENT_CHAT_PARTED: + { + Emote_Event_Chat *d; + char buf[8192]; + + d = event; + // FIXME: Make this check the actual username based on the server + if (!strcmp(d->user, "emote")) + { + snprintf(buf, sizeof(buf), "You have left %s", d->channel); + em_gui_message_add(EMOTE_EVENT_SERVER_T(d)->server, NULL, NULL, buf); + em_gui_channel_del(EMOTE_EVENT_SERVER_T(d)->server, d->channel, EMOTE_EVENT_T(d)->protocol); + } + else + { + + snprintf(buf, sizeof(buf), "%s has left %s", d->user, d->channel); + em_gui_message_add(EMOTE_EVENT_SERVER_T(d)->server, NULL, NULL, buf); + } + break; + } case EMOTE_EVENT_SERVER_MESSAGE_RECEIVED: { Emote_Event_Server_Message *d; d = event; - em_gui_message_add(EMOTE_EVENT_SERVER_T(d)->server, NULL, d->message); + em_gui_message_add(EMOTE_EVENT_SERVER_T(d)->server, NULL, NULL, d->message); break; } - case EMOTE_EVENT_CHAT_CHANNEL_MESSAGE_RECEIVED: + case EMOTE_EVENT_CHAT_MESSAGE_RECEIVED: { - Emote_Event_Chat_Channel_Message *d; + Emote_Event_Chat_Message *d; d = event; - em_gui_message_add(EMOTE_EVENT_SERVER_T(d)->server, EMOTE_EVENT_CHAT_CHANNEL_T(d)->channel, d->message); + em_gui_message_add(EMOTE_EVENT_SERVER_T(d)->server, EMOTE_EVENT_CHAT_T(d)->channel, EMOTE_EVENT_CHAT_T(d)->user, d->message); break; } default: Modified: trunk/PROTO/emote/src/lib/Emote.h =================================================================== --- trunk/PROTO/emote/src/lib/Emote.h 2010-08-31 01:13:45 UTC (rev 51768) +++ trunk/PROTO/emote/src/lib/Emote.h 2010-08-31 03:07:34 UTC (rev 51769) @@ -44,8 +44,8 @@ typedef struct _Emote_Event_Server Emote_Event_Server; typedef struct _Emote_Event_Server_Connect Emote_Event_Server_Connect; typedef struct _Emote_Event_Server_Message Emote_Event_Server_Message; -typedef struct _Emote_Event_Chat_Channel Emote_Event_Chat_Channel; -typedef struct _Emote_Event_Chat_Channel_Message Emote_Event_Chat_Channel_Message; +typedef struct _Emote_Event_Chat Emote_Event_Chat; +typedef struct _Emote_Event_Chat_Message Emote_Event_Chat_Message; enum _Emote_Event_Type { @@ -55,11 +55,13 @@ EMOTE_EVENT_SERVER_DISCONNECTED=3, EMOTE_EVENT_SERVER_MESSAGE_SEND=4, EMOTE_EVENT_SERVER_MESSAGE_RECEIVED=5, - EMOTE_EVENT_CHAT_CHANNEL_JOIN=6, - EMOTE_EVENT_CHAT_CHANNEL_JOINED=7, - EMOTE_EVENT_CHAT_CHANNEL_MESSAGE_SEND=8, - EMOTE_EVENT_CHAT_CHANNEL_MESSAGE_RECEIVED=9, - EMOTE_EVENT_COUNT=10 + EMOTE_EVENT_CHAT_JOIN=6, + EMOTE_EVENT_CHAT_JOINED=7, + EMOTE_EVENT_CHAT_PART=8, + EMOTE_EVENT_CHAT_PARTED=9, + EMOTE_EVENT_CHAT_MESSAGE_SEND=10, + EMOTE_EVENT_CHAT_MESSAGE_RECEIVED=11, + EMOTE_EVENT_COUNT=12 }; struct _Emote_Object @@ -80,6 +82,8 @@ struct _Emote_Protocol { + Emote_Object em_object_inherit; + Emote_Protocol_Api *api; void *handle; @@ -94,8 +98,8 @@ #define EMOTE_EVENT_SERVER_T(x) ((Emote_Event_Server*)x) #define EMOTE_EVENT_SERVER_CONNECT_T(x) ((Emote_Event_Server_Connect*)x) #define EMOTE_EVENT_SERVER_MESSAGE_T(x) ((Emote_Event_Server_Message*)x) -#define EMOTE_EVENT_CHAT_CHANNEL_T(x) ((Emote_Event_Chat_Channel*)x) -#define EMOTE_EVENT_CHAT_CHANNEL_MESSAGE_T(x) ((Emote_Event_Chat_Channel_Message*)x) +#define EMOTE_EVENT_CHAT_T(x) ((Emote_Event_Chat*)x) +#define EMOTE_EVENT_CHAT_MESSAGE_T(x) ((Emote_Event_Chat_Message*)x) struct _Emote_Event { @@ -125,16 +129,16 @@ const char *message; }; -struct _Emote_Event_Chat_Channel +struct _Emote_Event_Chat { Emote_Event_Server s; const char *channel; + const char *user; }; -struct _Emote_Event_Chat_Channel_Message +struct _Emote_Event_Chat_Message { - Emote_Event_Chat_Channel c; - const char *user; + Emote_Event_Chat c; const char *message; }; Modified: trunk/PROTO/emote/src/lib/emote_event.c =================================================================== --- trunk/PROTO/emote/src/lib/emote_event.c 2010-08-31 01:13:45 UTC (rev 51768) +++ trunk/PROTO/emote/src/lib/emote_event.c 2010-08-31 03:07:34 UTC (rev 51769) @@ -14,8 +14,8 @@ static void _emote_event_server_free(void *e); static void _emote_event_server_connect_free(void *e); static void _emote_event_server_message_free(void *e); -static void _emote_event_chat_channel_free(void *e); -static void _emote_event_chat_channel_message_free(void *e); +static void _emote_event_chat_free(void *e); +static void _emote_event_chat_message_free(void *e); EM_INTERN int emote_event_init() @@ -90,36 +90,40 @@ EMOTE_EVENT_ALLOC_STRING(Emote_Event_Server_Message, ev, message, s); break; - // Emote_Event_Chat_Channel - case EMOTE_EVENT_CHAT_CHANNEL_JOIN: - case EMOTE_EVENT_CHAT_CHANNEL_JOINED: - ev = (Emote_Event*)EMOTE_OBJECT_ALLOC(Emote_Event_Chat_Channel, - EMOTE_EVENT_CHAT_CHANNEL_TYPE, - _emote_event_chat_channel_free + // Emote_Event_Chat + case EMOTE_EVENT_CHAT_JOIN: + case EMOTE_EVENT_CHAT_JOINED: + case EMOTE_EVENT_CHAT_PART: + case EMOTE_EVENT_CHAT_PARTED: + ev = (Emote_Event*)EMOTE_OBJECT_ALLOC(Emote_Event_Chat, + EMOTE_EVENT_CHAT_TYPE, + _emote_event_chat_free ); s = va_arg(args, char*); EMOTE_EVENT_ALLOC_STRING(Emote_Event_Server, ev, server, s); s = va_arg(args, char*); - EMOTE_EVENT_ALLOC_STRING(Emote_Event_Chat_Channel, ev, channel, s); + EMOTE_EVENT_ALLOC_STRING(Emote_Event_Chat, ev, channel, s); + s = va_arg(args, char*); + EMOTE_EVENT_ALLOC_STRING(Emote_Event_Chat, ev, user, s); break; - // Emote_Event_Chat_Channel Message - case EMOTE_EVENT_CHAT_CHANNEL_MESSAGE_SEND: - case EMOTE_EVENT_CHAT_CHANNEL_MESSAGE_RECEIVED: - ev = (Emote_Event*)EMOTE_OBJECT_ALLOC(Emote_Event_Chat_Channel_Message, - EMOTE_EVENT_CHAT_CHANNEL_MESSAGE_TYPE, - _emote_event_chat_channel_message_free + // Emote_Event_Chat Message + case EMOTE_EVENT_CHAT_MESSAGE_SEND: + case EMOTE_EVENT_CHAT_MESSAGE_RECEIVED: + ev = (Emote_Event*)EMOTE_OBJECT_ALLOC(Emote_Event_Chat_Message, + EMOTE_EVENT_CHAT_MESSAGE_TYPE, + _emote_event_chat_message_free ); s = va_arg(args, char*); EMOTE_EVENT_ALLOC_STRING(Emote_Event_Server, ev, server, s); s = va_arg(args, char*); - EMOTE_EVENT_ALLOC_STRING(Emote_Event_Chat_Channel, ev, channel, s); + EMOTE_EVENT_ALLOC_STRING(Emote_Event_Chat, ev, channel, s); s = va_arg(args, char*); - EMOTE_EVENT_ALLOC_STRING(Emote_Event_Chat_Channel_Message, ev, user, s); + EMOTE_EVENT_ALLOC_STRING(Emote_Event_Chat, ev, user, s); s = va_arg(args, char*); - EMOTE_EVENT_ALLOC_STRING(Emote_Event_Chat_Channel_Message, ev, message, s); + EMOTE_EVENT_ALLOC_STRING(Emote_Event_Chat_Message, ev, message, s); break; // Unknown Event @@ -202,30 +206,30 @@ } static void -_emote_event_chat_channel_free(void *e) +_emote_event_chat_free(void *e) { - Emote_Event_Chat_Channel *ee; + Emote_Event_Chat *ee; ee = e; if (ee->channel) eina_stringshare_del(ee->channel); + if (ee->user) + eina_stringshare_del(ee->user); + _emote_event_server_free(e); } static void -_emote_event_chat_channel_message_free(void *e) +_emote_event_chat_message_free(void *e) { - Emote_Event_Chat_Channel_Message *ee; + Emote_Event_Chat_Message *ee; ee = e; - if (ee->user) - eina_stringshare_del(ee->user); - if (ee->message) eina_stringshare_del(ee->message); - _emote_event_chat_channel_free(e); + _emote_event_chat_free(e); } Modified: trunk/PROTO/emote/src/lib/emote_protocol.c =================================================================== --- trunk/PROTO/emote/src/lib/emote_protocol.c 2010-08-31 01:13:45 UTC (rev 51768) +++ trunk/PROTO/emote/src/lib/emote_protocol.c 2010-08-31 03:07:34 UTC (rev 51769) @@ -25,6 +25,7 @@ { eina_hash_foreach(_emote_protocols, _emote_protocol_hash_cb_free, NULL); eina_hash_free(_emote_protocols); + _emote_protocols = NULL; } return 1; @@ -198,6 +199,7 @@ Emote_Protocol *p; if (!(p = data)) return EINA_TRUE; + emote_object_del(EMOTE_OBJECT(p)); return EINA_TRUE; } Modified: trunk/PROTO/emote/src/lib/emote_types.h =================================================================== --- trunk/PROTO/emote/src/lib/emote_types.h 2010-08-31 01:13:45 UTC (rev 51768) +++ trunk/PROTO/emote/src/lib/emote_types.h 2010-08-31 03:07:34 UTC (rev 51769) @@ -7,6 +7,6 @@ #define EMOTE_EVENT_SERVER_TYPE 0xE0e02001 #define EMOTE_EVENT_SERVER_CONNECT_TYPE 0xE0e02002 #define EMOTE_EVENT_SERVER_MESSAGE_TYPE 0xE0e02003 -#define EMOTE_EVENT_CHAT_CHANNEL_TYPE 0xE0e02004 -#define EMOTE_EVENT_CHAT_CHANNEL_MESSAGE_TYPE 0xE0e02005 +#define EMOTE_EVENT_CHAT_TYPE 0xE0e02004 +#define EMOTE_EVENT_CHAT_MESSAGE_TYPE 0xE0e02005 Modified: trunk/PROTO/emote/src/lib/protocols/irc/irc.c =================================================================== --- trunk/PROTO/emote/src/lib/protocols/irc/irc.c 2010-08-31 01:13:45 UTC (rev 51768) +++ trunk/PROTO/emote/src/lib/protocols/irc/irc.c 2010-08-31 03:07:34 UTC (rev 51769) @@ -27,8 +27,8 @@ _irc_servers = eina_hash_string_superfast_new(NULL); emote_event_handler_add(EMOTE_EVENT_SERVER_CONNECT, _irc_event_handler, NULL); emote_event_handler_add(EMOTE_EVENT_SERVER_DISCONNECT, _irc_event_handler, NULL); - emote_event_handler_add(EMOTE_EVENT_CHAT_CHANNEL_JOIN, _irc_event_handler, NULL); - emote_event_handler_add(EMOTE_EVENT_CHAT_CHANNEL_MESSAGE_SEND, _irc_event_handler, NULL); + emote_event_handler_add(EMOTE_EVENT_CHAT_JOIN, _irc_event_handler, NULL); + emote_event_handler_add(EMOTE_EVENT_CHAT_MESSAGE_SEND, _irc_event_handler, NULL); return 1; } @@ -142,25 +142,29 @@ int len = 0; if ((!server) || (!chan)) return 0; + if (!(serv = eina_hash_find(_irc_servers, server))) return 0; + if (!ecore_con_server_connected_get(serv)) return 0; + len = snprintf(buf, sizeof(buf), "JOIN %s\r\n", chan); + ecore_con_server_send(serv, buf, len); - printf("Joining %s on %s\n", chan, server); + return 1; +} +int +protocol_irc_command(const char *server, const char *chan, const char *message) +{ + Ecore_Con_Server *serv = NULL; + char buf[512]; + int len = 0; + + if ((!server) || (!chan) || (!message)) return 0; if (!(serv = eina_hash_find(_irc_servers, server))) return 0; - - printf("Joining %s on %s\n", chan, server); - if (!ecore_con_server_connected_get(serv)) return 0; - printf("Joining %s on %s\n", chan, server); + printf("Parsing Command %s\n", message); - len = snprintf(buf, sizeof(buf), "JOIN %s\r\n", chan); - - printf("Buffer: %s\n", buf); - + len = snprintf(buf, sizeof(buf), "%s\r\n", message); ecore_con_server_send(serv, buf, len); - - printf("Success!\n"); - return 1; } @@ -531,10 +535,9 @@ ev = event; if(!ev->server) return EINA_FALSE; - msg = strndup(ev->data, ev->size); - + msg = calloc((ev->size + 1), sizeof(char)); + strncpy(msg, ev->data, ev->size); irc_parse_input(msg, ecore_con_server_name_get(ev->server), m); - free(msg); return EINA_FALSE; @@ -571,22 +574,31 @@ protocol_irc_disconnect(d->server); break; } - case EMOTE_EVENT_CHAT_CHANNEL_JOIN: + case EMOTE_EVENT_CHAT_JOIN: { - Emote_Event_Chat_Channel *d; + Emote_Event_Chat *d; d = event; protocol_irc_join(EMOTE_EVENT_SERVER_T(d)->server, d->channel); break; } - case EMOTE_EVENT_CHAT_CHANNEL_MESSAGE_SEND: + case EMOTE_EVENT_CHAT_MESSAGE_SEND: { - Emote_Event_Chat_Channel_Message *d; + Emote_Event_Chat_Message *d; d = event; - protocol_irc_message(EMOTE_EVENT_SERVER_T(d)->server, - EMOTE_EVENT_CHAT_CHANNEL_T(d)->channel, - d->message); + if ((d->message[0] == '/') && (d->message[1] != '/')) + { + protocol_irc_command(EMOTE_EVENT_SERVER_T(d)->server, + EMOTE_EVENT_CHAT_T(d)->channel, + &(d->message[1])); + } + else + { + protocol_irc_message(EMOTE_EVENT_SERVER_T(d)->server, + EMOTE_EVENT_CHAT_T(d)->channel, + ((d->message[0] == '/') ? &(d->message[1]) : d->message)); + } break; } default: Modified: trunk/PROTO/emote/src/lib/protocols/irc/irc.h =================================================================== --- trunk/PROTO/emote/src/lib/protocols/irc/irc.h 2010-08-31 01:13:45 UTC (rev 51768) +++ trunk/PROTO/emote/src/lib/protocols/irc/irc.h 2010-08-31 03:07:34 UTC (rev 51769) @@ -4,6 +4,8 @@ #include "Emote.h" #include "irc_parse.h" +#define IRC_LINE_TYPE 0xE0E03000 + EMAPI extern Emote_Protocol_Api protocol_api; EMAPI int protocol_init(Emote_Protocol *p); Modified: trunk/PROTO/emote/src/lib/protocols/irc/irc_parse.c =================================================================== --- trunk/PROTO/emote/src/lib/protocols/irc/irc_parse.c 2010-08-31 01:13:45 UTC (rev 51768) +++ trunk/PROTO/emote/src/lib/protocols/irc/irc_parse.c 2010-08-31 03:07:34 UTC (rev 51769) @@ -5,319 +5,375 @@ #include <Evas.h> #include <unistd.h> +typedef struct _IRC_Line IRC_Line; + +struct _IRC_Line +{ + const char *prefix; + const char *source; + const char *user; + const char *host; + const char *cmd; + Eina_List *params; +}; + +typedef enum _PARSE_STATE PARSE_STATE; +typedef enum _IRC_COMMANDS IRC_COMMANDS; + +enum _PARSE_STATE +{ + PARSE_PREFIX=0, + PARSE_SOURCE=1, + PARSE_USER=2, + PARSE_HOST=3, + PARSE_CMD=4, + PARSE_MIDDLE=5, + PARSE_TRAILING=6, + PARSE_END=7 +}; + +enum _IRC_COMMANDS +{ + RPL_TOPIC=332, + RPL_TOPICUSER=333, + RPL_NAMREPLY=353, + RPL_ENDOFNAMES=366 +}; + /* local function prototypes */ static Eina_List *_irc_parse_split_input(const char *input); -static int _irc_parse_split_prefix(const char *input, int start, Eina_Strbuf **prefix); -static int _irc_parse_split_command(const char *input, int start, Eina_Strbuf **cmd); -static int _irc_parse_split_params(const char *input, int start, Eina_Strbuf **params); -static int _irc_parse_remove_username(const char *input, int start, Eina_Strbuf **params); +static void _irc_cleanup_irc_line(IRC_Line *line); static char *_irc_parse_utf8_to_markup(const char *text); static char *_irc_str_append(char *str, const char *txt, int *len, int *alloc); +static int _irc_parse_line(const char *line, IRC_Line *out); void irc_parse_input(char *input, const char *server, Emote_Protocol *m) { - Eina_Strbuf *buff; - Eina_Strbuf *prefix, *cmd, *params; - Eina_List *lines, *l; - char *line; + static char buf[8192]; + static int length = 0; + IRC_Line ln; + Eina_List *lines, *l, *p; + char *line, *param; + int size; - printf("Parse Input: %s\n", input); + if ((length == 1) && (buf[0] == 0)) + length = 0; + strncpy(&(buf[length]), input, sizeof(buf)-length); + length += strlen(input); + /* NB: Any parsing of messages after this split will need to append - * a new line if printing to the screen as this split strips them out. - * - * This is currently handled in the individual _parse_ functions */ - lines = _irc_parse_split_input(input); - - buff = eina_strbuf_new(); - prefix = eina_strbuf_new(); - cmd = eina_strbuf_new(); - params = eina_strbuf_new(); - + * a new line if printing to the screen as this split strips them out + */ + lines = _irc_parse_split_input(buf); EINA_LIST_FOREACH(lines, l, line) { - const char *str; - int pos; + printf("Parse Line: %s\n", line); - pos = _irc_parse_split_prefix(line, 0, &prefix); + size = strlen(line); + length -= size+2; + memmove(buf, &(buf[size+2]), length); + buf[length] = 0; - if (strstr(line, "PING")) + if(!_irc_parse_line(line, &ln)) continue; + +/* printf("\tPrefix = %s\n\tSource = %s\n\tUser = %s\n\tHost = %s\n\tCmd: %s\n", + ln.prefix, ln.source, ln.user, ln.host, ln.cmd);*/ + /*EINA_LIST_FOREACH(ln.params, p, param) { - protocol_irc_pong(server, eina_strbuf_string_get(prefix)); - goto reset; + printf("\tParam: %s\n", param); + }*/ + + if (!strcmp(ln.cmd, "PING")) + { + protocol_irc_pong(server, ln.prefix); } + else if (!strcmp(ln.cmd, "NOTICE")) + { + Emote_Event *d; - pos = _irc_parse_split_command(line, pos, &cmd); - printf("Command: %s\n", eina_strbuf_string_get(cmd)); + d = emote_event_new( + m, + EMOTE_EVENT_SERVER_MESSAGE_RECEIVED, + server, + _irc_parse_utf8_to_markup(eina_list_nth(ln.params,1)) + ); + emote_event_send(d); + } + else if (!strcmp(ln.cmd, "PRIVMSG")) + { + Emote_Event *d; - pos = _irc_parse_split_params(line, pos, ¶ms); - printf("Params: %s\n", eina_strbuf_string_get(params)); + d = emote_event_new + ( + m, + EMOTE_EVENT_CHAT_MESSAGE_RECEIVED, + server, + _irc_parse_utf8_to_markup(eina_list_nth(ln.params,0)), + _irc_parse_utf8_to_markup(ln.source), + _irc_parse_utf8_to_markup(eina_list_nth(ln.params,1)) + ); + emote_event_send(d); + } + else if (!strcmp(ln.cmd, "JOIN")) + { + Emote_Event *d; - /* NB: Based on the command, pass off to parsing functions. - * The 'params' may need special parsing based on command */ - if ((str = eina_strbuf_string_get(cmd))) + d = emote_event_new + ( + m, + EMOTE_EVENT_CHAT_JOINED, + server, + _irc_parse_utf8_to_markup(eina_list_nth(ln.params,0)), + _irc_parse_utf8_to_markup(ln.source) + ); + emote_event_send(d); + } + else if (!strcmp(ln.cmd, "PART")) { - const char *p; - char *msg = NULL; + Emote_Event *d; - /* Don't print Server Info */ - if (!strcmp(str, "004")) goto reset; - /* Don't print current channels user list to the tb */ - if (!strcmp(str, "353")) goto reset; + printf("Received PART: %s, %s, %s\n", server, _irc_parse_utf8_to_markup(eina_list_nth(ln.params,0)), _irc_parse_utf8_to_markup(ln.source)); - p = eina_strbuf_string_get(params); - /* Append tail to username if it is in use */ - if (!strcmp(str, "433")) - { - /* TODO Reconnect with different username */ - } - if (!strcmp(str, "NOTICE")) - { - if ((msg = _irc_parse_utf8_to_markup(p))) - { - char fmt[5012]; - Emote_Event *d; + d = emote_event_new + ( + m, + EMOTE_EVENT_CHAT_PARTED, + server, + _irc_parse_utf8_to_markup(eina_list_nth(ln.params,0)), + _irc_parse_utf8_to_markup(ln.source) + ); + emote_event_send(d); + } + else if (atoi(ln.cmd) == RPL_NAMREPLY) + { + // TODO: Add command for sending channel list + } + else if (atoi(ln.cmd) == RPL_TOPICUSER) + { + // Don't really need to show this. + } + else if (atoi(ln.cmd) != 0) + { + Emote_Event *d; + Eina_List *l; + char *p; + char buf[8192]; - snprintf(fmt, sizeof(fmt), " <color=#ff0000>%s</> ", msg); - d = emote_event_new( - m, - EMOTE_EVENT_SERVER_MESSAGE_RECEIVED, - server, - msg - ); - emote_event_send(d); - } - goto reset; - } - else if (!strcmp(str, "JOIN")) + buf[0] = 0; + EINA_LIST_FOREACH(ln.params->next, l, p) { - char *channel, chan[5012]; - Emote_Event *d; - - channel = strrchr(p, ':'); - channel++; - snprintf(chan, sizeof(chan), "%s", channel); - d = emote_event_new - ( - m, - EMOTE_EVENT_CHAT_CHANNEL_JOINED, - server, - chan - ); - emote_event_send(d); + strncat(buf, p, sizeof(buf)); + strncat(buf, " ", sizeof(buf)); } - else if ( - ((atoi(str) >= 001) && (atoi(str) <= 003)) || - (atoi(str) == 251) || (atoi(str) == 255) || - (atoi(str) == 250) || - ((atoi(str) >= 372) && (atoi(str) <= 376)) - ) - { - /* I DON'T LIKE THIS AT ALL :( - * NOT HAPPY WITH THE WAY THIS IS GETTING DONE */ - Eina_Strbuf *tmp; - const char *txt; - int pos2; - Emote_Event *d; + d = emote_event_new( + m, + EMOTE_EVENT_SERVER_MESSAGE_RECEIVED, + server, + _irc_parse_utf8_to_markup(buf) + ); + emote_event_send(d); + } - /* NB: For these messages, we need to strip the username :*/ - tmp = eina_strbuf_new(); - txt = eina_strbuf_string_get(params); - pos2 = _irc_parse_remove_username(txt, 0, &tmp); - p = eina_strbuf_string_get(tmp); - msg = _irc_parse_utf8_to_markup(p); - d = emote_event_new - ( - m, - EMOTE_EVENT_SERVER_MESSAGE_RECEIVED, - server, - msg - ); - emote_event_send(d); - eina_strbuf_free(tmp); - } - else if (!(strcmp(str, "PRIVMSG"))) - { - Emote_Event *d; + _irc_cleanup_irc_line(&ln); + } - msg = _irc_parse_utf8_to_markup(p); - d = emote_event_new - ( - m, - EMOTE_EVENT_CHAT_CHANNEL_MESSAGE_RECEIVED, - server, - NULL, - NULL, - msg - ); - emote_event_send(d); - } - else - { - Emote_Event *d; + EINA_LIST_FREE(l, line) + free(line); +} - msg = _irc_parse_utf8_to_markup(p); - d = emote_event_new - ( - m, - EMOTE_EVENT_CHAT_CHANNEL_MESSAGE_RECEIVED, - server, - NULL, - NULL, - msg - ); - emote_event_send(d); - } - } -reset: - eina_strbuf_reset(buff); - eina_strbuf_reset(prefix); - eina_strbuf_reset(cmd); - eina_strbuf_reset(params); - } +/* local functions */ +static int +_irc_find_token_pos(const char *buf, int pos, int end, const char token, const char token2) +{ + int pos2; - /* clenaup */ - eina_strbuf_free(buff); - eina_strbuf_free(prefix); - eina_strbuf_free(cmd); - eina_strbuf_free(params); + pos2 = pos; + while ((pos2 < end) && (buf[++pos2] != token) && (buf[pos2] != token2)); - EINA_LIST_FREE(l, line) - free(line); + return pos2; } -/* local functions */ static Eina_List * _irc_parse_split_input(const char *input) { + char buf[8192]; Eina_List *l = NULL; - char *tok = NULL, *str; + char *tok = NULL, *str, *str2; + int length, pos, pos2; + int i = 0; - str = strdup(input); + str2 = str = strdup(input); while ((tok = strsep(&str, "\r\n"))) { + if (!str) break; if ((*tok == '\0') || (*tok == '\n')) continue; l = eina_list_append(l, strdup(tok)); } - free(str); + free(str2); return l; } -static int -_irc_parse_split_prefix(const char *input, int start, Eina_Strbuf **prefix) +static void +_irc_cleanup_irc_line(IRC_Line *line) { - int chr, pos = 0; + char *param; - if (!input) return 0; + if (!line) return; - pos = start; - while ((pos = evas_string_char_next_get((char *)input, pos, &chr))) + if (line->prefix) + eina_stringshare_del(line->prefix); + if (line->source) + eina_stringshare_del(line->source); + if (line->user) + eina_stringshare_del(line->user); + if (line->host) + eina_stringshare_del(line->host); + if (line->cmd) + eina_stringshare_del(line->cmd); + if (line->params) { - if ((chr <= 0) || (pos <= 0)) break; - if (chr == ':') - { - int chr2, pos2 = 0; - - pos2 = pos; -// eina_strbuf_append_char(*prefix, chr); - while ((pos2 = evas_string_char_next_get((char *)input, pos2, &chr2))) - { - if ((chr2 <= 0) || (pos2 <= 0)) break; - if (chr2 != ' ') - eina_strbuf_append_char(*prefix, chr2); - else - return pos2; - } - pos = pos2; - } + EINA_LIST_FREE(line->params, param) + eina_stringshare_del(param); } - return pos; } static int -_irc_parse_split_command(const char *input, int start, Eina_Strbuf **cmd) +_irc_parse_line(const char *line, IRC_Line *out) { - int chr, pos = 0; + char buf[8192]; + PARSE_STATE state; + int pos, pos2; + int length; - if (!input) return 0; + // Check for null or blank line + if (!line || !line[0]) return 0; - pos = start - 1; - while ((pos = evas_string_char_next_get((char *)input, pos, &chr))) + strncpy(buf, line, sizeof(buf)); + length = strlen(buf); + + memset(out, 0, sizeof(IRC_Line)); + + state = PARSE_PREFIX; + pos = pos2 = 0; + while(state < PARSE_END) { - if ((chr <= 0) || (pos <= 0)) break; - if (chr != ' ') + switch(state) { - int chr2, pos2 = 0; + case PARSE_PREFIX: + if (buf[0] != ':') + state = PARSE_CMD; - pos2 = pos; - eina_strbuf_append_char(*cmd, chr); - while ((pos2 = evas_string_char_next_get((char *)input, pos2, &chr2))) - { - if ((chr2 <= 0) || (pos2 <= 0)) break; - if (chr2 != ' ') - eina_strbuf_append_char(*cmd, chr2); - else - return pos2; - } - pos = pos2; - } - } - return pos; -} + pos = 0; + pos2 = _irc_find_token_pos(buf, pos, sizeof(buf), 0, ' '); -static int -_irc_parse_split_params(const char *input, int start, Eina_Strbuf **params) -{ - int chr, pos = 0; + state = PARSE_SOURCE; - if (!input) return 0; + buf[pos2] = 0; + out->prefix = eina_stringshare_add(&(buf[pos])); + buf[pos2] = ' '; + break; + case PARSE_SOURCE: + // Check if there is a prefix or not + if (buf[0] != ':') + state = PARSE_CMD; - pos = start; - while ((pos = evas_string_char_next_get((char *)input, pos, &chr))) - { - if ((chr <= 0) || (pos <= 0)) break; - if (chr == '\r') - eina_strbuf_append_char(*params, '\n'); - else if (!iscntrl(chr)) - eina_strbuf_append_char(*params, chr); - } - eina_strbuf_append_char(*params, '\n'); - return pos; -} + pos = 1; + pos2 = _irc_find_token_pos(buf, pos, sizeof(buf), '!', ' '); -static int -_irc_parse_remove_username(const char *input, int start, Eina_Strbuf **params) -{ - int chr, pos = 0; + if (buf[pos2] == '!') + state = PARSE_USER; + else + state = PARSE_CMD; - if (!input) return 0; + buf[pos2] = 0; + out->source = eina_stringshare_add(&(buf[pos])); - pos = start; - while ((pos = evas_string_char_next_get((char *)input, pos, &chr))) - { - int chr2, pos2 = 0; + pos2++; + break; - if ((chr <= 0) || (pos < 0)) break; + case PARSE_USER: + pos = pos2; + pos2 = _irc_find_token_pos(buf, pos, sizeof(buf), '@', ' '); - /* skip until we hit the : */ - if (chr != ':') continue; + if (buf[pos2] == '@') + state = PARSE_HOST; + else + state = PARSE_CMD; - pos2 = pos; - eina_strbuf_append_char(*params, chr); - while ((pos2 = evas_string_char_next_get((char *)input, pos2, &chr2))) - { - if ((chr2 <= 0) || (pos2 <= 0)) break; - if (chr2 == '\r') - eina_strbuf_append_char(*params, '\n'); - else if (!iscntrl(chr2)) - eina_strbuf_append_char(*params, chr2); - } - pos = pos2; + buf[pos2] = 0; + out->user = eina_stringshare_add(&(buf[pos])); + + pos2++; + break; + + case PARSE_HOST: + pos = pos2; + pos2 = _irc_find_token_pos(buf, pos, sizeof(buf), 0, ' '); + + state = PARSE_CMD; + + buf[pos2] = 0; + out->host = eina_stringshare_add(&(buf[pos])); + + pos2++; + break; + + case PARSE_CMD: + pos = pos2; + pos2 = _irc_find_token_pos(buf, pos, sizeof(buf), 0, ' '); + buf[pos2] = 0; + out->cmd = eina_stringshare_add(&(buf[pos])); + + pos2++; + if (buf[pos2] == ':') + { + pos2++; + state = PARSE_TRAILING; + } + else + state = PARSE_MIDDLE; + break; + + case PARSE_MIDDLE: + state = PARSE_END; + while (pos2 < length) + { + pos = pos2; + pos2 = _irc_find_token_pos(buf, pos, sizeof(buf), ' ', 0); + buf[pos2] = 0; + out->params = eina_list_append(out->params, eina_stringshare_add(&(buf[pos]))); + + pos2++; + if (buf[pos2] == ':') + { + pos2++; + state = PARSE_TRAILING; + break; + } + } + break; + + case PARSE_TRAILING: + while (pos2 < length) + { + pos = pos2; + pos2 = _irc_find_token_pos(buf, pos, sizeof(buf), ':', 0); + buf[pos2] = 0; + out->params = eina_list_append(out->params, eina_stringshare_add(&(buf[pos]))); + } + state = PARSE_END; + break; + + case PARSE_END: + default: + break; + } } - eina_strbuf_append_char(*params, '\n'); - return pos; + + return 1; } static char * @@ -330,27 +386,27 @@ if (!text) return NULL; for (;;) { - pos = pos2; + pos = pos2; pos2 = evas_string_char_next_get((char *)(text), pos2, &ch); if ((ch <= 0) || (pos2 <= 0)) break; - if (ch == '\n') - str = _irc_str_append(str, "<br>", &str_len, &str_alloc); - else if (ch == '\t') - str = _irc_str_append(str, "<\t>", &str_len, &str_alloc); - else if (ch == '<') - str = _irc_str_append(str, "<", &str_len, &str_alloc); - else if (ch == '>') - str = _irc_str_append(str, ">", &str_len, &str_alloc); - else if (ch == '&') - str = _irc_str_append(str, "&", &str_len, &str_alloc); - else - { - char tstr[16]; + if (ch == '\n') + str = _irc_str_append(str, "<br>", &str_len, &str_alloc); + else if (ch == '\t') + str = _irc_str_append(str, "<\t>", &str_len, &str_alloc); + else if (ch == '<') + str = _irc_str_append(str, "<", &str_len, &str_alloc); + else if (ch == '>') + str = _irc_str_append(str, ">", &str_len, &str_alloc); + else if (ch == '&') + str = _irc_str_append(str, "&", &str_len, &str_alloc); + else + { + char tstr[16]; - strncpy(tstr, text + pos, pos2 - pos); - tstr[pos2 - pos] = 0; - str = _irc_str_append(str, tstr, &str_len, &str_alloc); - } + strncpy(tstr, text + pos, pos2 - pos); + tstr[pos2 - pos] = 0; + str = _irc_str_append(str, tstr, &str_len, &str_alloc); + } } return str; } @@ -363,14 +419,14 @@ if (txt_len <= 0) return str; if ((*len + txt_len) >= *alloc) { - char *str2; - int alloc2; + char *str2; + int alloc2; - alloc2 = *alloc + txt_len + 128; - str2 = realloc(str, alloc2); - if (!str2) return str; - *alloc = alloc2; - str = str2; + alloc2 = *alloc + txt_len + 128; + str2 = realloc(str, alloc2); + if (!str2) return str; + *alloc = alloc2; + str = str2; } strcpy(str + *len, txt); *len += txt_len; |