diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/common.vcxproj | 2 | ||||
-rw-r--r-- | src/common/dcc.c | 12 | ||||
-rw-r--r-- | src/common/dcc.h | 1 | ||||
-rw-r--r-- | src/common/hexchat-plugin.h | 50 | ||||
-rw-r--r-- | src/common/make-te.vcxproj | 2 | ||||
-rw-r--r-- | src/common/outbound.c | 18 | ||||
-rw-r--r-- | src/common/plugin.c | 144 | ||||
-rw-r--r-- | src/common/plugin.h | 25 | ||||
-rw-r--r-- | src/common/proto-irc.c | 21 | ||||
-rw-r--r-- | src/common/servlist.c | 9 | ||||
-rw-r--r-- | src/common/text.c | 12 | ||||
-rw-r--r-- | src/common/text.h | 3 | ||||
-rw-r--r-- | src/common/url.c | 243 |
13 files changed, 393 insertions, 149 deletions
diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj index c71d6ced..5568409e 100644 --- a/src/common/common.vcxproj +++ b/src/common/common.vcxproj @@ -119,7 +119,6 @@ <ClCompile> <PrecompiledHeader> </PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions> @@ -137,7 +136,6 @@ <ClCompile> <PrecompiledHeader> </PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> <PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_LIB;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions> diff --git a/src/common/dcc.c b/src/common/dcc.c index c0527510..5f4b1190 100644 --- a/src/common/dcc.c +++ b/src/common/dcc.c @@ -227,6 +227,15 @@ is_dcc (struct DCC *dcc) return FALSE; } +gboolean +is_dcc_completed (struct DCC *dcc) +{ + if (dcc != NULL) + return (dcc->dccstat == STAT_FAILED || dcc->dccstat == STAT_DONE || dcc->dccstat == STAT_ABORTED); + + return FALSE; +} + /* this is called from hexchat.c:hexchat_misc_checks() every 1 second. */ void @@ -548,7 +557,8 @@ dcc_chat_line (struct DCC *dcc, char *line) for (i = 5; i < PDIWORDS; i++) word[i] = "\000"; - ret = plugin_emit_print (sess, word); + ret = plugin_emit_print (sess, word) + + plugin_emit_print_attrs (sess, word, 0); /* did the plugin close it? */ if (!g_slist_find (dcc_list, dcc)) diff --git a/src/common/dcc.h b/src/common/dcc.h index e3163c8a..acb87f34 100644 --- a/src/common/dcc.h +++ b/src/common/dcc.h @@ -117,6 +117,7 @@ struct dccstat_info extern struct dccstat_info dccstat[]; gboolean is_dcc (struct DCC *dcc); +gboolean is_dcc_completed (struct DCC *dcc); void dcc_abort (session *sess, struct DCC *dcc); void dcc_get (struct DCC *dcc); int dcc_resume (struct DCC *dcc); diff --git a/src/common/hexchat-plugin.h b/src/common/hexchat-plugin.h index 36dc544f..61597181 100644 --- a/src/common/hexchat-plugin.h +++ b/src/common/hexchat-plugin.h @@ -49,6 +49,10 @@ typedef struct _hexchat_hook hexchat_hook; #ifndef PLUGIN_C typedef struct _hexchat_context hexchat_context; #endif +typedef struct +{ + time_t server_time_utc; /* 0 if not used */ +} hexchat_event_attrs; #ifndef PLUGIN_C struct _hexchat_plugin @@ -164,6 +168,23 @@ struct _hexchat_plugin const char *var); int (*hexchat_pluginpref_list) (hexchat_plugin *ph, char *dest); + hexchat_hook *(*hexchat_hook_server_attrs) (hexchat_plugin *ph, + const char *name, + int pri, + int (*callback) (char *word[], char *word_eol[], + hexchat_event_attrs *attrs, void *user_data), + void *userdata); + hexchat_hook *(*hexchat_hook_print_attrs) (hexchat_plugin *ph, + const char *name, + int pri, + int (*callback) (char *word[], hexchat_event_attrs *attrs, + void *user_data), + void *userdata); + int (*hexchat_emit_print_attrs) (hexchat_plugin *ph, hexchat_event_attrs *attrs, + const char *event_name, ...); + hexchat_event_attrs *(*hexchat_event_attrs_create) (hexchat_plugin *ph); + void (*hexchat_event_attrs_free) (hexchat_plugin *ph, + hexchat_event_attrs *attrs); }; #endif @@ -176,6 +197,10 @@ hexchat_hook_command (hexchat_plugin *ph, const char *help_text, void *userdata); +hexchat_event_attrs *hexchat_event_attrs_create (hexchat_plugin *ph); + +void hexchat_event_attrs_free (hexchat_plugin *ph, hexchat_event_attrs *attrs); + hexchat_hook * hexchat_hook_server (hexchat_plugin *ph, const char *name, @@ -184,6 +209,14 @@ hexchat_hook_server (hexchat_plugin *ph, void *userdata); hexchat_hook * +hexchat_hook_server_attrs (hexchat_plugin *ph, + const char *name, + int pri, + int (*callback) (char *word[], char *word_eol[], + hexchat_event_attrs *attrs, void *user_data), + void *userdata); + +hexchat_hook * hexchat_hook_print (hexchat_plugin *ph, const char *name, int pri, @@ -191,6 +224,14 @@ hexchat_hook_print (hexchat_plugin *ph, void *userdata); hexchat_hook * +hexchat_hook_print_attrs (hexchat_plugin *ph, + const char *name, + int pri, + int (*callback) (char *word[], hexchat_event_attrs *attrs, + void *user_data), + void *userdata); + +hexchat_hook * hexchat_hook_timer (hexchat_plugin *ph, int timeout, int (*callback) (void *user_data), @@ -297,6 +338,10 @@ int hexchat_emit_print (hexchat_plugin *ph, const char *event_name, ...); +int +hexchat_emit_print_attrs (hexchat_plugin *ph, hexchat_event_attrs *attrs, + const char *event_name, ...); + char * hexchat_gettext (hexchat_plugin *ph, const char *msgid); @@ -350,8 +395,12 @@ hexchat_pluginpref_list (hexchat_plugin *ph, #define HEXCHAT_PLUGIN_HANDLE (ph) #endif #define hexchat_hook_command ((HEXCHAT_PLUGIN_HANDLE)->hexchat_hook_command) +#define hexchat_event_attrs_create ((HEXCHAT_PLUGIN_HANDLE)->hexchat_event_attrs_create) +#define hexchat_event_attrs_free ((HEXCHAT_PLUGIN_HANDLE)->hexchat_event_attrs_free) #define hexchat_hook_server ((HEXCHAT_PLUGIN_HANDLE)->hexchat_hook_server) +#define hexchat_hook_server_attrs ((HEXCHAT_PLUGIN_HANDLE)->hexchat_hook_server_attrs) #define hexchat_hook_print ((HEXCHAT_PLUGIN_HANDLE)->hexchat_hook_print) +#define hexchat_hook_print_attrs ((HEXCHAT_PLUGIN_HANDLE)->hexchat_hook_print_attrs) #define hexchat_hook_timer ((HEXCHAT_PLUGIN_HANDLE)->hexchat_hook_timer) #define hexchat_hook_fd ((HEXCHAT_PLUGIN_HANDLE)->hexchat_hook_fd) #define hexchat_unhook ((HEXCHAT_PLUGIN_HANDLE)->hexchat_unhook) @@ -374,6 +423,7 @@ hexchat_pluginpref_list (hexchat_plugin *ph, #define hexchat_plugingui_add ((HEXCHAT_PLUGIN_HANDLE)->hexchat_plugingui_add) #define hexchat_plugingui_remove ((HEXCHAT_PLUGIN_HANDLE)->hexchat_plugingui_remove) #define hexchat_emit_print ((HEXCHAT_PLUGIN_HANDLE)->hexchat_emit_print) +#define hexchat_emit_print_attrs ((HEXCHAT_PLUGIN_HANDLE)->hexchat_emit_print_attrs) #define hexchat_list_time ((HEXCHAT_PLUGIN_HANDLE)->hexchat_list_time) #define hexchat_gettext ((HEXCHAT_PLUGIN_HANDLE)->hexchat_gettext) #define hexchat_send_modes ((HEXCHAT_PLUGIN_HANDLE)->hexchat_send_modes) diff --git a/src/common/make-te.vcxproj b/src/common/make-te.vcxproj index 07bb5ca4..b9f0f11f 100644 --- a/src/common/make-te.vcxproj +++ b/src/common/make-te.vcxproj @@ -57,7 +57,6 @@ <ClCompile> <PrecompiledHeader> </PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> @@ -77,7 +76,6 @@ <ClCompile> <PrecompiledHeader> </PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> diff --git a/src/common/outbound.c b/src/common/outbound.c index 6beaa2cc..91188a8a 100644 --- a/src/common/outbound.c +++ b/src/common/outbound.c @@ -487,19 +487,19 @@ create_mask (session * sess, char *mask, char *mode, char *typestr, int deop) switch (type) { case 0: - snprintf (buf, sizeof (buf), "%s%s *!*@%s.*", mode, p2, domain); + snprintf (buf, sizeof (buf), "%s %s *!*@%s.*", mode, p2, domain); break; case 1: - snprintf (buf, sizeof (buf), "%s%s *!*@%s", mode, p2, fullhost); + snprintf (buf, sizeof (buf), "%s %s *!*@%s", mode, p2, fullhost); break; case 2: - snprintf (buf, sizeof (buf), "%s%s *!%s@%s.*", mode, p2, username, domain); + snprintf (buf, sizeof (buf), "%s %s *!%s@%s.*", mode, p2, username, domain); break; case 3: - snprintf (buf, sizeof (buf), "%s%s *!%s@%s", mode, p2, username, fullhost); + snprintf (buf, sizeof (buf), "%s %s *!%s@%s", mode, p2, username, fullhost); break; } } else @@ -507,19 +507,19 @@ create_mask (session * sess, char *mask, char *mode, char *typestr, int deop) switch (type) { case 0: - snprintf (buf, sizeof (buf), "%s%s *!*@*%s", mode, p2, domain); + snprintf (buf, sizeof (buf), "%s %s *!*@*%s", mode, p2, domain); break; case 1: - snprintf (buf, sizeof (buf), "%s%s *!*@%s", mode, p2, fullhost); + snprintf (buf, sizeof (buf), "%s %s *!*@%s", mode, p2, fullhost); break; case 2: - snprintf (buf, sizeof (buf), "%s%s *!%s@*%s", mode, p2, username, domain); + snprintf (buf, sizeof (buf), "%s %s *!%s@*%s", mode, p2, username, domain); break; case 3: - snprintf (buf, sizeof (buf), "%s%s *!%s@%s", mode, p2, username, fullhost); + snprintf (buf, sizeof (buf), "%s %s *!%s@%s", mode, p2, username, fullhost); break; } } @@ -3877,7 +3877,7 @@ const struct commands xc_cmds[] = { {"ME", cmd_me, 0, 0, 1, N_("ME <action>, sends the action to the current channel (actions are written in the 3rd person, like /me jumps)")}, {"MENU", cmd_menu, 0, 0, 1, "MENU [-eX] [-i<ICONFILE>] [-k<mod>,<key>] [-m] [-pX] [-r<X,group>] [-tX] {ADD|DEL} <path> [command] [unselect command]\n" - " See http://docs.hexchat.org/en/latest/plugins.html#controlling-the-gui for more details."}, + " See http://hexchat.readthedocs.org/en/latest/plugins.html#controlling-the-gui for more details."}, {"MKICK", cmd_mkick, 1, 1, 1, N_("MKICK, Mass kicks everyone except you in the current channel (needs chanop)")}, {"MODE", cmd_mode, 1, 0, 1, 0}, diff --git a/src/common/plugin.c b/src/common/plugin.c index 5a6a42a6..50157ea1 100644 --- a/src/common/plugin.c +++ b/src/common/plugin.c @@ -86,6 +86,8 @@ struct _hexchat_list typedef int (hexchat_cmd_cb) (char *word[], char *word_eol[], void *user_data); typedef int (hexchat_serv_cb) (char *word[], char *word_eol[], void *user_data); typedef int (hexchat_print_cb) (char *word[], void *user_data); +typedef int (hexchat_serv_attrs_cb) (char *word[], char *word_eol[], hexchat_event_attrs *attrs, void *user_data); +typedef int (hexchat_print_attrs_cb) (char *word[], hexchat_event_attrs *attrs, void *user_data); typedef int (hexchat_fd_cb) (int fd, int flags, void *user_data); typedef int (hexchat_timer_cb) (void *user_data); typedef int (hexchat_init_func) (hexchat_plugin *, char **, char **, char **, char *); @@ -102,12 +104,14 @@ enum enum { - HOOK_COMMAND, /* /command */ - HOOK_SERVER, /* PRIVMSG, NOTICE, numerics */ - HOOK_PRINT, /* All print events */ - HOOK_TIMER, /* timeouts */ - HOOK_FD, /* sockets & fds */ - HOOK_DELETED /* marked for deletion */ + HOOK_COMMAND, /* /command */ + HOOK_SERVER, /* PRIVMSG, NOTICE, numerics */ + HOOK_SERVER_ATTRS, /* same as above, with attributes */ + HOOK_PRINT, /* All print events */ + HOOK_PRINT_ATTRS, /* same as above, with attributes */ + HOOK_TIMER, /* timeouts */ + HOOK_FD, /* sockets & fds */ + HOOK_DELETED /* marked for deletion */ }; GSList *plugin_list = NULL; /* export for plugingui.c */ @@ -289,12 +293,11 @@ plugin_add (session *sess, char *filename, void *handle, void *init_func, pl->hexchat_pluginpref_get_int = hexchat_pluginpref_get_int; pl->hexchat_pluginpref_delete = hexchat_pluginpref_delete; pl->hexchat_pluginpref_list = hexchat_pluginpref_list; - - /* incase new plugins are loaded on older HexChat */ - pl->hexchat_dummy4 = hexchat_dummy; - pl->hexchat_dummy3 = hexchat_dummy; - pl->hexchat_dummy2 = hexchat_dummy; - pl->hexchat_dummy1 = hexchat_dummy; + pl->hexchat_hook_server_attrs = hexchat_hook_server_attrs; + pl->hexchat_hook_print_attrs = hexchat_hook_print_attrs; + pl->hexchat_emit_print_attrs = hexchat_emit_print_attrs; + pl->hexchat_event_attrs_create = hexchat_event_attrs_create; + pl->hexchat_event_attrs_free = hexchat_event_attrs_free; /* run hexchat_plugin_init, if it returns 0, close the plugin */ if (((hexchat_init_func *)init_func) (pl, &pl->name, &pl->desc, &pl->version, arg) == 0) @@ -519,7 +522,7 @@ plugin_hook_find (GSList *list, int type, char *name) while (list) { hook = list->data; - if (hook->type == type) + if (hook && hook->type == type) { if (g_ascii_strcasecmp (hook->name, name) == 0) return list; @@ -539,7 +542,8 @@ plugin_hook_find (GSList *list, int type, char *name) /* check for plugin hooks and run them */ static int -plugin_hook_run (session *sess, char *name, char *word[], char *word_eol[], int type) +plugin_hook_run (session *sess, char *name, char *word[], char *word_eol[], + hexchat_event_attrs *attrs, int type) { GSList *list, *next; hexchat_hook *hook; @@ -562,9 +566,15 @@ plugin_hook_run (session *sess, char *name, char *word[], char *word_eol[], int case HOOK_COMMAND: ret = ((hexchat_cmd_cb *)hook->callback) (word, word_eol, hook->userdata); break; + case HOOK_PRINT_ATTRS: + ret = ((hexchat_print_attrs_cb *)hook->callback) (word, attrs, hook->userdata); + break; case HOOK_SERVER: ret = ((hexchat_serv_cb *)hook->callback) (word, word_eol, hook->userdata); break; + case HOOK_SERVER_ATTRS: + ret = ((hexchat_serv_attrs_cb *)hook->callback) (word, word_eol, attrs, hook->userdata); + break; default: /*case HOOK_PRINT:*/ ret = ((hexchat_print_cb *)hook->callback) (word, hook->userdata); break; @@ -590,7 +600,7 @@ xit: { hook = list->data; next = list->next; - if (hook->type == HOOK_DELETED) + if (!hook || hook->type == HOOK_DELETED) { hook_list = g_slist_remove (hook_list, hook); free (hook); @@ -606,15 +616,43 @@ xit: int plugin_emit_command (session *sess, char *name, char *word[], char *word_eol[]) { - return plugin_hook_run (sess, name, word, word_eol, HOOK_COMMAND); + return plugin_hook_run (sess, name, word, word_eol, NULL, HOOK_COMMAND); } -/* got a server PRIVMSG, NOTICE, numeric etc... */ +hexchat_event_attrs * +hexchat_event_attrs_create (hexchat_plugin *ph) +{ + hexchat_event_attrs *attrs; + + attrs = g_malloc (sizeof (*attrs)); + attrs->server_time_utc = (time_t) 0; + + return attrs; +} + +void +hexchat_event_attrs_free (hexchat_plugin *ph, hexchat_event_attrs *attrs) +{ + g_free (attrs); +} + +/* got a server PRIVMSG, NOTICE, numeric etc... */ int plugin_emit_server (session *sess, char *name, char *word[], char *word_eol[]) { - return plugin_hook_run (sess, name, word, word_eol, HOOK_SERVER); + return plugin_hook_run (sess, name, word, word_eol, NULL, HOOK_SERVER); +} + +int +plugin_emit_server_attrs (session *sess, char *name, char *word[], char *word_eol[], + time_t server_time) +{ + hexchat_event_attrs attrs; + + attrs.server_time_utc = server_time; + + return plugin_hook_run (sess, name, word, word_eol, &attrs, HOOK_SERVER_ATTRS); } /* see if any plugins are interested in this print event */ @@ -622,7 +660,17 @@ plugin_emit_server (session *sess, char *name, char *word[], char *word_eol[]) int plugin_emit_print (session *sess, char *word[]) { - return plugin_hook_run (sess, word[0], word, NULL, HOOK_PRINT); + return plugin_hook_run (sess, word[0], word, NULL, NULL, HOOK_PRINT); +} + +int +plugin_emit_print_attrs (session *sess, char *word[], time_t server_time) +{ + hexchat_event_attrs attrs; + + attrs.server_time_utc = server_time; + + return plugin_hook_run (sess, word[0], word, NULL, &attrs, HOOK_PRINT_ATTRS); } int @@ -635,7 +683,7 @@ plugin_emit_dummy_print (session *sess, char *name) for (i = 1; i < 32; i++) word[i] = "\000"; - return plugin_hook_run (sess, name, word, NULL, HOOK_PRINT); + return plugin_hook_run (sess, name, word, NULL, NULL, HOOK_PRINT); } int @@ -663,7 +711,7 @@ plugin_emit_keypress (session *sess, unsigned int state, unsigned int keyval, for (i = 5; i < PDIWORDS; i++) word[i] = "\000"; - return plugin_hook_run (sess, word[0], word, NULL, HOOK_PRINT); + return plugin_hook_run (sess, word[0], word, NULL, NULL, HOOK_PRINT); } static int @@ -702,7 +750,7 @@ plugin_insert_hook (hexchat_hook *new_hook) while (list) { hook = list->data; - if (hook->type == new_hook->type && hook->pri <= new_hook->pri) + if (hook && hook->type == new_hook->type && hook->pri <= new_hook->pri) { hook_list = g_slist_insert_before (hook_list, list, new_hook); return; @@ -780,7 +828,7 @@ plugin_command_list(GList *tmp_list) while (list) { hook = list->data; - if (hook->type == HOOK_COMMAND) + if (hook && hook->type == HOOK_COMMAND) tmp_list = g_list_prepend(tmp_list, hook->name); list = list->next; } @@ -798,7 +846,7 @@ plugin_command_foreach (session *sess, void *userdata, while (list) { hook = list->data; - if (hook->type == HOOK_COMMAND && hook->name[0]) + if (hook && hook->type == HOOK_COMMAND && hook->name[0]) { cb (sess, userdata, hook->name, hook->help_text); } @@ -869,6 +917,14 @@ hexchat_hook_server (hexchat_plugin *ph, const char *name, int pri, } hexchat_hook * +hexchat_hook_server_attrs (hexchat_plugin *ph, const char *name, int pri, + hexchat_serv_attrs_cb *callb, void *userdata) +{ + return plugin_add_hook (ph, HOOK_SERVER_ATTRS, pri, name, 0, callb, 0, + userdata); +} + +hexchat_hook * hexchat_hook_print (hexchat_plugin *ph, const char *name, int pri, hexchat_print_cb *callb, void *userdata) { @@ -876,6 +932,14 @@ hexchat_hook_print (hexchat_plugin *ph, const char *name, int pri, } hexchat_hook * +hexchat_hook_print_attrs (hexchat_plugin *ph, const char *name, int pri, + hexchat_print_attrs_cb *callb, void *userdata) +{ + return plugin_add_hook (ph, HOOK_PRINT_ATTRS, pri, name, 0, callb, 0, + userdata); +} + +hexchat_hook * hexchat_hook_timer (hexchat_plugin *ph, int timeout, hexchat_timer_cb *callb, void *userdata) { @@ -1598,8 +1662,36 @@ hexchat_emit_print (hexchat_plugin *ph, const char *event_name, ...) break; } - i = text_emit_by_name ((char *)event_name, ph->context, argv[0], argv[1], - argv[2], argv[3]); + i = text_emit_by_name ((char *)event_name, ph->context, (time_t) 0, + argv[0], argv[1], argv[2], argv[3]); + va_end (args); + + return i; +} + +int +hexchat_emit_print_attrs (hexchat_plugin *ph, hexchat_event_attrs *attrs, + const char *event_name, ...) +{ + va_list args; + /* currently only 4 because no events use more than 4. + This can be easily expanded without breaking the API. */ + char *argv[4] = {NULL, NULL, NULL, NULL}; + int i = 0; + + va_start (args, event_name); + while (1) + { + argv[i] = va_arg (args, char *); + if (!argv[i]) + break; + i++; + if (i >= 4) + break; + } + + i = text_emit_by_name ((char *)event_name, ph->context, attrs->server_time_utc, + argv[0], argv[1], argv[2], argv[3]); va_end (args); return i; diff --git a/src/common/plugin.h b/src/common/plugin.h index dd878895..f75639e9 100644 --- a/src/common/plugin.h +++ b/src/common/plugin.h @@ -132,10 +132,24 @@ struct _hexchat_plugin const char *var); int (*hexchat_pluginpref_list) (hexchat_plugin *ph, char *dest); - void *(*hexchat_dummy4) (hexchat_plugin *ph); - void *(*hexchat_dummy3) (hexchat_plugin *ph); - void *(*hexchat_dummy2) (hexchat_plugin *ph); - void *(*hexchat_dummy1) (hexchat_plugin *ph); + hexchat_hook *(*hexchat_hook_server_attrs) (hexchat_plugin *ph, + const char *name, + int pri, + int (*callback) (char *word[], char *word_eol[], + hexchat_event_attrs *attrs, void *user_data), + void *userdata); + hexchat_hook *(*hexchat_hook_print_attrs) (hexchat_plugin *ph, + const char *name, + int pri, + int (*callback) (char *word[], hexchat_event_attrs *attrs, + void *user_data), + void *userdata); + int (*hexchat_emit_print_attrs) (hexchat_plugin *ph, hexchat_event_attrs *attrs, + const char *event_name, ...); + hexchat_event_attrs *(*hexchat_event_attrs_create) (hexchat_plugin *ph); + void (*hexchat_event_attrs_free) (hexchat_plugin *ph, + hexchat_event_attrs *attrs); + /* PRIVATE FIELDS! */ void *handle; /* from dlopen */ char *filename; /* loaded from */ @@ -156,7 +170,10 @@ void plugin_kill_all (void); void plugin_auto_load (session *sess); int plugin_emit_command (session *sess, char *name, char *word[], char *word_eol[]); int plugin_emit_server (session *sess, char *name, char *word[], char *word_eol[]); +int plugin_emit_server_attrs (session *sess, char *name, char *word[], + char *word_eol[], time_t server_time); int plugin_emit_print (session *sess, char *word[]); +int plugin_emit_print_attrs (session *sess, char *word[], time_t server_time); int plugin_emit_dummy_print (session *sess, char *name); int plugin_emit_keypress (session *sess, unsigned int state, unsigned int keyval, int len, char *string); GList* plugin_command_list(GList *tmp_list); diff --git a/src/common/proto-irc.c b/src/common/proto-irc.c index bea9f6f7..128c0c85 100644 --- a/src/common/proto-irc.c +++ b/src/common/proto-irc.c @@ -1493,6 +1493,9 @@ irc_inline (server *serv, char *buf, int len) if (buf[0] == ':') { + int eat1; + int eat2; + /* find a context for this message */ if (is_channel (serv, word[3])) { @@ -1506,15 +1509,29 @@ irc_inline (server *serv, char *buf, int len) word[0] = type; word_eol[1] = buf; /* keep the ":" for plugins */ - if (plugin_emit_server (sess, type, word, word_eol)) + + eat1 = plugin_emit_server (sess, type, word, word_eol); + eat2 = plugin_emit_server_attrs (sess, type, word, word_eol, + tags_data.timestamp); + + if (eat1 || eat2) goto xit; + word[1]++; word_eol[1] = buf + 1; /* but not for HexChat internally */ } else { + int eat1; + int eat2; + word[0] = type = word[1]; - if (plugin_emit_server (sess, type, word, word_eol)) + + eat1 = plugin_emit_server (sess, type, word, word_eol); + eat2 = plugin_emit_server_attrs (sess, type, word, word_eol, + tags_data.timestamp); + + if (eat1 || eat2) goto xit; } diff --git a/src/common/servlist.c b/src/common/servlist.c index 1e06acd4..51094687 100644 --- a/src/common/servlist.c +++ b/src/common/servlist.c @@ -207,7 +207,7 @@ static const struct defaultserver def[] = {"EnterTheGame", 0}, {0, "IRC.EnterTheGame.Com"}, - {"EntropyNet", 0}, + {"EntropyNet", 0, 0, 0, LOGIN_SASL}, #ifdef USE_OPENSSL {0, "irc.entropynet.net/+6697"}, #endif @@ -251,7 +251,7 @@ static const struct defaultserver def[] = {0, "irc.ggn.net"}, {0, "irc.vendetta.com"}, - {"freenode", 0, "#hexchat", 0, LOGIN_SASL}, + {"freenode", 0, 0, 0, LOGIN_SASL}, #ifdef USE_OPENSSL {0, "chat.freenode.net/+6697"}, #endif @@ -510,7 +510,7 @@ static const struct defaultserver def[] = {0, "moo.slashnet.org"}, {0, "radon.slashnet.org"}, - {"Snoonet", 0}, + {"Snoonet", 0, 0, 0, LOGIN_SASL}, #ifdef USE_OPENSSL {0, "irc.snoonet.org/+6697"}, #endif @@ -550,6 +550,9 @@ static const struct defaultserver def[] = {0, "tahoma.starchat.net"}, {0, "neo.starchat.net"}, + {"StaticBox", 0, 0, 0, LOGIN_SASL}, + {0, "irc.staticbox.net"}, + {"Station51", 0}, #ifdef USE_OPENSSL {0, "irc.station51.net/+6697"}, diff --git a/src/common/text.c b/src/common/text.c index a0e860ce..b825faba 100644 --- a/src/common/text.c +++ b/src/common/text.c @@ -2070,6 +2070,8 @@ text_emit (int index, session *sess, char *a, char *b, char *c, char *d, int i; unsigned int stripcolor_args = (chanopt_is_set (prefs.hex_text_stripcolor_msg, sess->text_strip) ? 0xFFFFFFFF : 0); char tbuf[NICKLEN + 4]; + int eat1; + int eat2; if (prefs.hex_text_color_nicks && (index == XP_TE_CHANACTION || index == XP_TE_CHANMSG)) { @@ -2086,7 +2088,10 @@ text_emit (int index, session *sess, char *a, char *b, char *c, char *d, for (i = 5; i < PDIWORDS; i++) word[i] = "\000"; - if (plugin_emit_print (sess, word)) + eat1 = plugin_emit_print (sess, word); + eat2 = plugin_emit_print_attrs (sess, word, timestamp); + + if (eat1 || eat2) return; /* If a plugin's callback executes "/close", 'sess' may be invalid */ @@ -2158,14 +2163,15 @@ text_find_format_string (char *name) } int -text_emit_by_name (char *name, session *sess, char *a, char *b, char *c, char *d) +text_emit_by_name (char *name, session *sess, time_t timestamp, + char *a, char *b, char *c, char *d) { int i = 0; i = pevent_find (name, &i); if (i >= 0) { - text_emit (i, sess, a, b, c, d, 0); + text_emit (i, sess, a, b, c, d, timestamp); return 1; } diff --git a/src/common/text.h b/src/common/text.h index 5a51c894..a9fd9d4e 100644 --- a/src/common/text.h +++ b/src/common/text.h @@ -55,7 +55,8 @@ void pevent_make_pntevts (void); int text_color_of (char *name); void text_emit (int index, session *sess, char *a, char *b, char *c, char *d, time_t timestamp); -int text_emit_by_name (char *name, session *sess, char *a, char *b, char *c, char *d); +int text_emit_by_name (char *name, session *sess, time_t timestamp, + char *a, char *b, char *c, char *d); char *text_validate (char **text, int *len); int get_stamp_str (char *fmt, time_t tim, char **ret); void format_event (session *sess, int index, char **args, char *o, int sizeofo, unsigned int stripcolor_args); diff --git a/src/common/url.c b/src/common/url.c index 10479127..1cdfdce7 100644 --- a/src/common/url.c +++ b/src/common/url.c @@ -32,15 +32,22 @@ void *url_tree = NULL; GTree *url_btree = NULL; -static int do_an_re (const char *word, int *start, int *end, int *type); -static GRegex *re_url (void); -static GRegex *re_host (void); -static GRegex *re_host6 (void); -static GRegex *re_email (void); -static GRegex *re_nick (void); -static GRegex *re_channel (void); -static GRegex *re_path (void); - +static gboolean regex_match (const GRegex *re, const char *word, + int *start, int *end); +static const GRegex *re_url (void); +static const GRegex *re_host (void); +static const GRegex *re_host6 (void); +static const GRegex *re_email (void); +static const GRegex *re_nick (void); +static const GRegex *re_channel (void); +static const GRegex *re_path (void); +static gboolean match_nick (const char *word, int *start, int *end); +static gboolean match_channel (const char *word, int *start, int *end); +static gboolean match_email (const char *word, int *start, int *end); +static gboolean match_url (const char *word, int *start, int *end); +static gboolean match_host (const char *word, int *start, int *end); +static gboolean match_host6 (const char *word, int *start, int *end); +static gboolean match_path (const char *word, int *start, int *end); static int url_free (char *url, void *data) @@ -189,50 +196,111 @@ static int laststart = 0; static int lastend = 0; static int lasttype = 0; -static int -strchrs (char c, char *s) -{ - while (*s) - if (c == *s++) - return TRUE; - return FALSE; -} +#define NICKPRE "~+!@%&" +#define CHANPRE "#&!+" -#define NICKPRE "~+!@%%&" int url_check_word (const char *word) { + struct { + gboolean (*match) (const char *word, int *start, int *end); + int type; + } m[] = { + { match_url, WORD_URL }, + { match_email, WORD_EMAIL }, + { match_nick, WORD_NICK }, + { match_channel, WORD_CHANNEL }, + { match_host6, WORD_HOST6 }, + { match_host, WORD_HOST }, + { match_path, WORD_PATH }, + { NULL, 0} + }; + int i; + laststart = lastend = lasttype = 0; - if (do_an_re (word, &laststart, &lastend, &lasttype)) - { - switch (lasttype) + + for (i = 0; m[i].match; i++) + if (m[i].match (word, &laststart, &lastend)) { - char *str; - - case WORD_NICK: - if (strchrs (word[laststart], NICKPRE)) - laststart++; - str = g_strndup (&word[laststart], lastend - laststart); - if (!userlist_find (current_sess, str)) - lasttype = 0; - g_free (str); - return lasttype; - case WORD_EMAIL: - if (!isalnum (word[laststart])) - laststart++; - /* Fall through */ - case WORD_URL: - case WORD_HOST: - case WORD_HOST6: - case WORD_CHANNEL: - case WORD_PATH: - return lasttype; - default: - return 0; /* Should not occur */ + lasttype = m[i].type; + return lasttype; } + + return 0; +} + +static gboolean +match_nick (const char *word, int *start, int *end) +{ + const server *serv = current_sess->server; + const char *nick_prefixes = serv ? serv->nick_prefixes : NICKPRE; + char *str; + + if (!regex_match (re_nick (), word, start, end)) + return FALSE; + + /* ignore matches with prefixes that the server doesn't use */ + if (strchr (NICKPRE, word[*start]) + && !strchr (nick_prefixes, word[*start])) + return FALSE; + + /* nick prefix is not part of the matched word */ + if (strchr (nick_prefixes, word[*start])) + (*start)++; + + str = g_strndup (&word[*start], *end - *start); + + if (!userlist_find (current_sess, str)) + { + g_free (str); + return FALSE; } - else - return 0; + + g_free (str); + + return TRUE; +} + +static gboolean +match_channel (const char *word, int *start, int *end) +{ + const server *serv = current_sess->server; + const char *chan_prefixes = serv ? serv->chantypes : CHANPRE; + + if (!regex_match (re_channel (), word, start, end)) + return FALSE; + + return strchr (chan_prefixes, word[*start]) != NULL; +} + +static gboolean +match_email (const char *word, int *start, int *end) +{ + return regex_match (re_email (), word, start, end); +} + +static gboolean +match_url (const char *word, int *start, int *end) +{ + return regex_match (re_url (), word, start, end); +} + +static gboolean +match_host (const char *word, int *start, int *end) +{ + return regex_match (re_host (), word, start, end); +} + +static gboolean +match_host6 (const char *word, int *start, int *end) +{ + return regex_match (re_host6 (), word, start, end); +} + +static gboolean +match_path (const char *word, int *start, int *end) +{ + return regex_match (re_path (), word, start, end); } /* List of IRC commands for which contents (and thus possible URLs) @@ -307,51 +375,33 @@ url_last (int *lstart, int *lend) return lasttype; } -static int -do_an_re(const char *word, int *start, int *end, int *type) +static gboolean +regex_match (const GRegex *re, const char *word, int *start, int *end) { - typedef struct func_s { - GRegex *(*fn)(void); - int type; - } func_t; - func_t funcs[] = - { - { re_url, WORD_URL }, - { re_email, WORD_EMAIL }, - { re_channel, WORD_CHANNEL }, - { re_host6, WORD_HOST6 }, - { re_host, WORD_HOST }, - { re_path, WORD_PATH }, - { re_nick, WORD_NICK } - }; - GMatchInfo *gmi; - int k; - for (k = 0; k < sizeof funcs / sizeof (func_t); k++) + g_regex_match (re, word, 0, &gmi); + + if (!g_match_info_matches (gmi)) { - g_regex_match (funcs[k].fn(), word, 0, &gmi); - if (!g_match_info_matches (gmi)) - { - g_match_info_free (gmi); - continue; - } - while (g_match_info_matches (gmi)) - { - g_match_info_fetch_pos (gmi, 0, start, end); - g_match_info_next (gmi, NULL); - } g_match_info_free (gmi); - *type = funcs[k].type; - return TRUE; + return FALSE; } - - return FALSE; + + while (g_match_info_matches (gmi)) + { + g_match_info_fetch_pos (gmi, 0, start, end); + g_match_info_next (gmi, NULL); + } + + g_match_info_free (gmi); + + return TRUE; } /* Miscellaneous description --- */ -#define DOMAIN "[a-z0-9][-a-z0-9]*(\\.[-a-z0-9]+)*\\." -#define TLD "[a-z][-a-z0-9]*[a-z]" +#define DOMAIN "[a-z0-9][-a-z0-9]*(\\.[-a-z0-9]+)*" +#define TLD "\\.[a-z][-a-z0-9]*[a-z]" #define IPADDR "[0-9]{1,3}(\\.[0-9]{1,3}){3}" #define IPV6GROUP "([0-9a-f]{0,4})" #define IPV6ADDR "((" IPV6GROUP "(:" IPV6GROUP "){7})" \ @@ -359,6 +409,7 @@ do_an_re(const char *word, int *start, int *end, int *type) #define HOST "(" DOMAIN TLD "|" IPADDR "|" IPV6ADDR ")" /* In urls the IPv6 must be enclosed in square brackets */ #define HOST_URL "(" DOMAIN TLD "|" IPADDR "|" "\\[" IPV6ADDR "\\]" ")" +#define HOST_URL_OPT_TLD "(" DOMAIN "|" HOST_URL ")" #define PORT "(:[1-9][0-9]{0,4})" #define OPT_PORT "(" PORT ")?" @@ -375,7 +426,7 @@ make_re (char *grist) /* HOST description --- */ /* (see miscellaneous above) */ -static GRegex * +static const GRegex * re_host (void) { static GRegex *host_ret; @@ -383,7 +434,7 @@ re_host (void) if (host_ret) return host_ret; - grist = g_strdup_printf ( + grist = g_strdup ( "(" "(" HOST_URL PORT ")|(" HOST ")" ")" @@ -392,7 +443,7 @@ re_host (void) return host_ret; } -static GRegex * +static const GRegex * re_host6 (void) { static GRegex *host6_ret; @@ -400,7 +451,7 @@ re_host6 (void) if (host6_ret) return host6_ret; - grist = g_strdup_printf ( + grist = g_strdup ( "(" "(" IPV6ADDR ")|(" "\\[" IPV6ADDR "\\]" PORT ")" ")" @@ -488,7 +539,7 @@ struct { NULL, "", 0} }; -static GRegex * +static const GRegex * re_url (void) { static GRegex *url_ret = NULL; @@ -517,7 +568,7 @@ re_url (void) g_string_append (grist_gstr, USERINFO "?"); if (uri[i].flags & URI_AUTHORITY) - g_string_append (grist_gstr, HOST_URL OPT_PORT); + g_string_append (grist_gstr, HOST_URL_OPT_TLD OPT_PORT); if (uri[i].flags & URI_PATH) { @@ -545,7 +596,7 @@ re_url (void) /* EMAIL description --- */ #define EMAIL "[a-z][-_a-z0-9]+@" "(" HOST_URL ")" -static GRegex * +static const GRegex * re_email (void) { static GRegex *email_ret; @@ -553,7 +604,7 @@ re_email (void) if (email_ret) return email_ret; - grist = g_strdup_printf ( + grist = g_strdup ( "(" EMAIL ")" @@ -581,7 +632,7 @@ re_email (void) #define NICK1 "[" NICKHYP NICKLET NICKDIG NICKSPE "]*" #define NICK NICK0 NICK1 -static GRegex * +static const GRegex * re_nick (void) { static GRegex *nick_ret; @@ -589,7 +640,7 @@ re_nick (void) if (nick_ret) return nick_ret; - grist = g_strdup_printf ( + grist = g_strdup ( "(" NICK ")" @@ -599,9 +650,9 @@ re_nick (void) } /* CHANNEL description --- */ -#define CHANNEL "#[^ \t\a,:]+" +#define CHANNEL "[" CHANPRE "][^ \t\a,:]+" -static GRegex * +static const GRegex * re_channel (void) { static GRegex *channel_ret; @@ -609,7 +660,7 @@ re_channel (void) if (channel_ret) return channel_ret; - grist = g_strdup_printf ( + grist = g_strdup ( "(" CHANNEL ")" @@ -627,7 +678,7 @@ re_channel (void) #define FS_PATH "^(/|\\./|\\.\\./).*" #endif -static GRegex * +static const GRegex * re_path (void) { static GRegex *path_ret; @@ -635,7 +686,7 @@ re_path (void) if (path_ret) return path_ret; - grist = g_strdup_printf ( + grist = g_strdup ( "(" FS_PATH ")" |