diff options
-rw-r--r-- | src/common/inbound.c | 17 | ||||
-rw-r--r-- | src/common/inbound.h | 5 | ||||
-rw-r--r-- | src/common/outbound.c | 12 | ||||
-rw-r--r-- | src/common/proto-irc.c | 83 | ||||
-rw-r--r-- | src/common/proto-irc.h | 17 | ||||
-rw-r--r-- | src/common/text.c | 24 | ||||
-rw-r--r-- | src/common/text.h | 10 |
7 files changed, 136 insertions, 32 deletions
diff --git a/src/common/inbound.c b/src/common/inbound.c index b1b739e5..55a4005c 100644 --- a/src/common/inbound.c +++ b/src/common/inbound.c @@ -158,6 +158,8 @@ inbound_privmsg (server *serv, char *from, char *ip, char *text, int id) struct User *user; char idtext[64]; gboolean nodiag = FALSE; + message_tags_data tags_data_ = MESSAGE_TAGS_DATA_INIT; /* TODO: this will be an argument */ + const message_tags_data const *tags_data = &tags_data_; sess = find_dialog (serv, from); @@ -186,7 +188,7 @@ inbound_privmsg (server *serv, char *from, char *ip, char *text, int id) } set_topic (sess, ip, ip); } - inbound_chanmsg (serv, NULL, NULL, from, text, FALSE, id); + inbound_chanmsg (serv, NULL, NULL, from, text, FALSE, id, tags_data); return; } @@ -410,7 +412,9 @@ inbound_action (session *sess, char *chan, char *from, char *ip, char *text, int } void -inbound_chanmsg (server *serv, session *sess, char *chan, char *from, char *text, char fromme, int id) +inbound_chanmsg (server *serv, session *sess, char *chan, char *from, + char *text, char fromme, int id, + const message_tags_data const *tags_data) { struct User *user; int hilight = FALSE; @@ -462,11 +466,14 @@ inbound_chanmsg (server *serv, session *sess, char *chan, char *from, char *text hilight = TRUE; if (sess->type == SESS_DIALOG) - EMIT_SIGNAL (XP_TE_DPRIVMSG, sess, from, text, idtext, NULL, 0); + EMIT_SIGNAL_TIMESTAMP (XP_TE_DPRIVMSG, sess, from, text, + idtext, NULL, 0, tags_data->timestamp); else if (hilight) - EMIT_SIGNAL (XP_TE_HCHANMSG, sess, from, text, nickchar, idtext, 0); + EMIT_SIGNAL_TIMESTAMP (XP_TE_HCHANMSG, sess, from, text, + nickchar, idtext, 0, tags_data->timestamp); else - EMIT_SIGNAL (XP_TE_CHANMSG, sess, from, text, nickchar, idtext, 0); + EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANMSG, sess, from, text, + nickchar, idtext, 0, tags_data->timestamp); } void diff --git a/src/common/inbound.h b/src/common/inbound.h index 32368cc1..41a927a2 100644 --- a/src/common/inbound.h +++ b/src/common/inbound.h @@ -17,6 +17,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include "proto-irc.h" + #ifndef HEXCHAT_INBOUND_H #define HEXCHAT_INBOUND_H @@ -46,7 +48,8 @@ void inbound_away (server *serv, char *nick, char *msg); void inbound_away_notify (server *serv, char *nick, char *reason); void inbound_login_start (session *sess, char *nick, char *servname); void inbound_login_end (session *sess, char *text); -void inbound_chanmsg (server *serv, session *sess, char *chan, char *from, char *text, char fromme, int id); +void inbound_chanmsg (server *serv, session *sess, char *chan, char *from, char *text, char fromme, int id, + const message_tags_data const *tags_data); void clear_channel (session *sess); void set_topic (session *sess, char *topic, char *stripped_topic); void inbound_privmsg (server *serv, char *from, char *ip, char *text, int id); diff --git a/src/common/outbound.c b/src/common/outbound.c index 120bb241..d02c88a5 100644 --- a/src/common/outbound.c +++ b/src/common/outbound.c @@ -2755,7 +2755,7 @@ cmd_msg (struct session *sess, char *tbuf, char *word[], char *word_eol[]) while ((split_text = split_up_text (sess, msg + offset, cmd_length, split_text))) { inbound_chanmsg (newsess->server, NULL, newsess->channel, - newsess->server->nick, split_text, TRUE, FALSE); + newsess->server->nick, split_text, TRUE, FALSE, 0); if (*split_text) offset += strlen(split_text); @@ -2763,7 +2763,7 @@ cmd_msg (struct session *sess, char *tbuf, char *word[], char *word_eol[]) g_free(split_text); } inbound_chanmsg (newsess->server, NULL, newsess->channel, - newsess->server->nick, msg + offset, TRUE, FALSE); + newsess->server->nick, msg + offset, TRUE, FALSE, 0); } else { @@ -3700,7 +3700,7 @@ cmd_wallchan (struct session *sess, char *tbuf, char *word[], if (sess->type == SESS_CHANNEL) { inbound_chanmsg (sess->server, NULL, sess->channel, - sess->server->nick, word_eol[2], TRUE, FALSE); + sess->server->nick, word_eol[2], TRUE, FALSE, 0); sess->server->p_message (sess->server, sess->channel, word_eol[2]); } list = list->next; @@ -4396,7 +4396,7 @@ handle_say (session *sess, char *text, int check_spch) if (dcc) { inbound_chanmsg (sess->server, NULL, sess->channel, - sess->server->nick, text, TRUE, FALSE); + sess->server->nick, text, TRUE, FALSE, 0); set_topic (sess, net_ip (dcc->addr), net_ip (dcc->addr)); goto xit; } @@ -4411,7 +4411,7 @@ handle_say (session *sess, char *text, int check_spch) while ((split_text = split_up_text (sess, text + offset, cmd_length, split_text))) { inbound_chanmsg (sess->server, sess, sess->channel, sess->server->nick, - split_text, TRUE, FALSE); + split_text, TRUE, FALSE, 0); sess->server->p_message (sess->server, sess->channel, split_text); if (*split_text) @@ -4421,7 +4421,7 @@ handle_say (session *sess, char *text, int check_spch) } inbound_chanmsg (sess->server, sess, sess->channel, sess->server->nick, - text + offset, TRUE, FALSE); + text + offset, TRUE, FALSE, 0); sess->server->p_message (sess->server, sess->channel, text + offset); } else { diff --git a/src/common/proto-irc.c b/src/common/proto-irc.c index ec4a36a3..1061b42c 100644 --- a/src/common/proto-irc.c +++ b/src/common/proto-irc.c @@ -29,6 +29,7 @@ #endif #include "hexchat.h" +#include "proto-irc.h" #include "ctcp.h" #include "fe.h" #include "ignore.h" @@ -959,7 +960,8 @@ process_numeric (session * sess, int n, /* handle named messages that starts with a ':' */ static void -process_named_msg (session *sess, char *type, char *word[], char *word_eol[]) +process_named_msg (session *sess, char *type, char *word[], char *word_eol[], + const message_tags_data const *tags_data) { server *serv = sess->server; char ip[128], nick[NICKLEN]; @@ -1173,7 +1175,7 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[]) { if (ignore_check (word[1], IG_CHAN)) return; - inbound_chanmsg (serv, NULL, to, nick, text, FALSE, id); + inbound_chanmsg (serv, NULL, to, nick, text, FALSE, id, tags_data); } else { if (ignore_check (word[1], IG_PRIV)) @@ -1368,8 +1370,55 @@ process_named_servermsg (session *sess, char *buf, char *rawname, char *word_eol EMIT_SIGNAL (XP_TE_SERVTEXT, sess, buf, sess->server->servername, rawname, NULL, 0); } -/* irc_inline() - 1 single line received from serv */ +/* Handle time-server tags. + * + * Sets timestamp to the correct time. This needs to take into account that + * time is in UTC, so we should convert it to our local time. + * + * See http://ircv3.atheme.org/extensions/server-time-3.2 + */ +static void +handle_message_tag_time (const char const *time, message_tags_data *tags_data) +{ + /* TODO, obviously :P */ + tags_data->timestamp = 44332211; +} + +/* Handle message tags. + * + * See http://ircv3.atheme.org/specification/message-tags-3.2 + */ +/* FIXME: we should ignore capabilities not enabled! */ +static void +handle_message_tags (const char const *tags_str, message_tags_data *tags_data) +{ + char **tags; + int i; + + /* FIXME We might want to avoid the allocation overhead here since + * this might be called for every message from the server. + */ + tags = g_strsplit (tags_str, ";", 0); + + for (i=0; tags[i]; i++) + { + char *key = tags[i]; + char *value = strchr (tags[i], '='); + + if (!value) + continue; + + *value = '\0'; + value++; + + if (!strcmp (key, "time")) + handle_message_tag_time (value, tags_data); + } + + g_strfreev (tags); +} +/* irc_inline() - 1 single line received from serv */ static void irc_inline (server *serv, char *buf, int len) { @@ -1379,8 +1428,7 @@ irc_inline (server *serv, char *buf, int len) char *word_eol[PDIWORDS+1]; char pdibuf_static[522]; /* 1 line can potentially be 512*6 in utf8 */ char *pdibuf = pdibuf_static; - - url_check_line (buf, len); + message_tags_data tags_data = MESSAGE_TAGS_DATA_INIT; /* need more than 522? fall back to malloc */ if (len >= sizeof (pdibuf_static)) @@ -1392,11 +1440,27 @@ irc_inline (server *serv, char *buf, int len) word[PDIWORDS] = NULL; word_eol[PDIWORDS] = NULL; - if (buf[0] == ':') + if (*buf == '@') { - /* split line into words and words_to_end_of_line */ - process_data_init (pdibuf, buf, word, word_eol, FALSE, FALSE); + char *tags = buf + 1; /* skip the '@' */ + char *sep = strchr (buf, ' '); + if (!sep) + goto xit; + + *sep = '\0'; + buf = sep + 1; + + handle_message_tags(tags, &tags_data); + } + + url_check_line (buf, len); + + /* split line into words and words_to_end_of_line */ + process_data_init (pdibuf, buf, word, word_eol, FALSE, FALSE); + + if (buf[0] == ':') + { /* find a context for this message */ if (is_channel (serv, word[3])) { @@ -1417,7 +1481,6 @@ irc_inline (server *serv, char *buf, int len) } else { - process_data_init (pdibuf, buf, word, word_eol, FALSE, FALSE); word[0] = type = word[1]; if (plugin_emit_server (sess, type, word, word_eol)) goto xit; @@ -1439,7 +1502,7 @@ irc_inline (server *serv, char *buf, int len) process_numeric (sess, atoi (word[2]), word, word_eol, text); } else { - process_named_msg (sess, type, word, word_eol); + process_named_msg (sess, type, word, word_eol, &tags_data); } xit: diff --git a/src/common/proto-irc.h b/src/common/proto-irc.h index 2de9815c..7c8a483f 100644 --- a/src/common/proto-irc.h +++ b/src/common/proto-irc.h @@ -17,9 +17,26 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include <time.h> +#include "hexchat.h" + #ifndef HEXCHAT_PROTO_H #define HEXCHAT_PROTO_H +#define MESSAGE_TAGS_DATA_INIT \ + { \ + .timestamp=(time_t)0, \ + } + +/* Message tag information that might be passed along with a server message + * + * See http://ircv3.atheme.org/specification/capability-negotiation-3.1 + */ +typedef struct +{ + time_t timestamp; +} message_tags_data; + void proto_fill_her_up (server *serv); #endif diff --git a/src/common/text.c b/src/common/text.c index f0a1dfb1..dc81feeb 100644 --- a/src/common/text.c +++ b/src/common/text.c @@ -865,8 +865,8 @@ text_validate (char **text, int *len) return utf; } -void -PrintText (session *sess, char *text) +static void +PrintTextTimeStamp (session *sess, char *text, time_t timestamp) { char *conv; @@ -890,13 +890,19 @@ PrintText (session *sess, char *text) log_write (sess, text); scrollback_save (sess, text); - fe_print_text (sess, text, 0); + fe_print_text (sess, text, timestamp); if (conv) g_free (conv); } void +PrintText (session *sess, char *text) +{ + PrintTextTimeStamp (sess, text, 0); +} + +void PrintTextf (session *sess, char *format, ...) { va_list args; @@ -1836,12 +1842,13 @@ format_event (session *sess, int index, char **args, char *o, int sizeofo, unsig } static void -display_event (session *sess, int event, char **args, unsigned int stripcolor_args) +display_event (session *sess, int event, char **args, + unsigned int stripcolor_args, time_t timestamp) { char o[4096]; format_event (sess, event, args, o, sizeof (o), stripcolor_args); if (o[0]) - PrintText (sess, o); + PrintTextTimeStamp (sess, o, timestamp); } int @@ -2042,7 +2049,8 @@ text_color_of (char *name) /* called by EMIT_SIGNAL macro */ void -text_emit (int index, session *sess, char *a, char *b, char *c, char *d) +text_emit (int index, session *sess, char *a, char *b, char *c, char *d, + time_t timestamp) { char *word[PDIWORDS]; int i; @@ -2120,7 +2128,7 @@ text_emit (int index, session *sess, char *a, char *b, char *c, char *d) } sound_play_event (index); - display_event (sess, index, word, stripcolor_args); + display_event (sess, index, word, stripcolor_args, timestamp); } char * @@ -2143,7 +2151,7 @@ text_emit_by_name (char *name, session *sess, char *a, char *b, char *c, char *d i = pevent_find (name, &i); if (i >= 0) { - text_emit (i, sess, a, b, c, d); + text_emit (i, sess, a, b, c, d, 0); return 1; } diff --git a/src/common/text.h b/src/common/text.h index 52cc8ea9..dc5e5f72 100644 --- a/src/common/text.h +++ b/src/common/text.h @@ -17,12 +17,17 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include <time.h> #include "textenums.h" #ifndef HEXCHAT_TEXT_H #define HEXCHAT_TEXT_H -#define EMIT_SIGNAL(i, sess, a, b, c, d, e) text_emit(i, sess, a, b, c, d) +/* timestamp is non-zero if we are using server-time */ +#define EMIT_SIGNAL_TIMESTAMP(i, sess, a, b, c, d, e, timestamp) \ + text_emit(i, sess, a, b, c, d, timestamp) +#define EMIT_SIGNAL(i, sess, a, b, c, d, e) \ + text_emit(i, sess, a, b, c, d, 0) struct text_event { @@ -46,7 +51,8 @@ int pevt_build_string (const char *input, char **output, int *max_arg); int pevent_load (char *filename); 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); +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); char *text_validate (char **text, int *len); int get_stamp_str (char *fmt, time_t tim, char **ret); |