3,447 changes: 1,735 additions & 1,712 deletions po/sr.po

Large diffs are not rendered by default.

6,114 changes: 6,114 additions & 0 deletions po/sr@latin.po

Large diffs are not rendered by default.

3,365 changes: 1,694 additions & 1,671 deletions po/sv.po

Large diffs are not rendered by default.

3,365 changes: 1,694 additions & 1,671 deletions po/th.po

Large diffs are not rendered by default.

6,116 changes: 6,116 additions & 0 deletions po/tr.po

Large diffs are not rendered by default.

3,365 changes: 1,694 additions & 1,671 deletions po/uk.po

Large diffs are not rendered by default.

3,365 changes: 1,694 additions & 1,671 deletions po/vi.po

Large diffs are not rendered by default.

3,339 changes: 1,681 additions & 1,658 deletions po/wa.po

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion po/zh_CN.po
Expand Up @@ -17,7 +17,7 @@ msgstr ""
"Project-Id-Version: HexChat\n"
"Report-Msgid-Bugs-To: www.hexchat.org\n"
"POT-Creation-Date: 2013-09-08 01:16-0400\n"
"PO-Revision-Date: 2013-09-08 05:21+0000\n"
"PO-Revision-Date: 2013-11-20 09:21+0000\n"
"Last-Translator: TingPing <tingping@tingping.se>\n"
"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/hexchat/language/zh_CN/)\n"
"MIME-Version: 1.0\n"
Expand Down
3,359 changes: 1,691 additions & 1,668 deletions po/zh_TW.po

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions readme.md
@@ -0,0 +1,25 @@
# HexChat [![Build Status](https://travis-ci.org/hexchat/hexchat.png)](https://travis-ci.org/hexchat/hexchat) [![Build Status](http://nekomimi.cloudapp.net:8080/job/hexchat/badge/icon)](http://nekomimi.cloudapp.net:8080/job/hexchat/) [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/hexchat/hexchat/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

HexChat is an IRC client for Windows and UNIX-like operating systems.
See [IRCHelp.org](http://irchelp.org) for information about IRC in general.
For more information on HexChat please read our [documentation](https://hexchat.readthedocs.org/en/latest/index.html):
- [Downloads](http://hexchat.github.io/downloads.html)
- [FAQ](https://hexchat.readthedocs.org/en/latest/faq.html)
- [Changelog](https://hexchat.readthedocs.org/en/latest/changelog.html)
- [Python API](https://hexchat.readthedocs.org/en/latest/script_python.html)
- [Perl API](https://hexchat.readthedocs.org/en/latest/script_perl.html)

---

<sub>
X-Chat ("xchat") Copyright (c) 1998-2010 By Peter Zelezny.
HexChat ("hexchat") Copyright (c) 2009-2014 By Berke Viktor.
</sub>

<sub>
This program is released under the GPL v2 with the additional exemption
that compiling, linking, and/or using OpenSSL is allowed. You may
provide binary packages linked to the OpenSSL libraries, provided that
all other requirements of the GPL are met.
See file COPYING for details.
</sub>
2,191 changes: 0 additions & 2,191 deletions share/doc/changelog-xchat.md

This file was deleted.

33 changes: 0 additions & 33 deletions share/doc/fishlim.md

This file was deleted.

36 changes: 0 additions & 36 deletions share/doc/hacking.md

This file was deleted.

3 changes: 0 additions & 3 deletions share/doc/hexchat-text.md

This file was deleted.

89 changes: 0 additions & 89 deletions share/doc/readme.md

This file was deleted.

Binary file removed share/icons/hexchat.ico
Binary file not shown.
12 changes: 0 additions & 12 deletions share/misc/hexchat.appdata.xml

This file was deleted.

31 changes: 0 additions & 31 deletions share/misc/hexchat.desktop

This file was deleted.

5 changes: 2 additions & 3 deletions src/Makefile.am
@@ -1,7 +1,6 @@
## Process this file with automake to produce Makefile.in

EXTRA_DIST = fe-text/fe-text.c \
fe-text/README fe-text/fe-text.h version-script
EXTRA_DIST = version-script

if DO_TEXT
text_fe = fe-text
Expand All @@ -11,7 +10,7 @@ if DO_GTK
gtk_fe = fe-gtk
endif

SUBDIRS = pixmaps common $(gtk_fe) $(text_fe)
SUBDIRS = common $(gtk_fe) $(text_fe)

if WITH_TM
SUBDIRS += htm
Expand Down
21 changes: 18 additions & 3 deletions src/common/Makefile.am
Expand Up @@ -44,6 +44,10 @@ if USE_OPENSSL
ssl_c = ssl.c
endif

if USE_MSPROXY
msproxy_c = msproxy.c
endif

if USE_DBUS
dbusdir = dbus
libhexchatcommon_a_LIBADD = \
Expand All @@ -55,15 +59,26 @@ if DO_PLUGIN
include_HEADERS = hexchat-plugin.h
endif

noinst_PROGRAMS = make-te

libhexchatcommon_a_SOURCES = cfgfiles.c chanopt.c ctcp.c dcc.c hexchat.c \
history.c ignore.c inbound.c modes.c msproxy.c network.c notify.c \
history.c ignore.c inbound.c marshal.c modes.c $(msproxy_c) network.c notify.c \
outbound.c plugin.c plugin-timer.c proto-irc.c server.c servlist.c \
$(ssl_c) text.c tree.c url.c userlist.c util.c
libhexchatcommon_a_CFLAGS = $(LIBPROXY_CFLAGS)

textenums.h: textevents.h

textevents.h: textevents.in make-te
./make-te < textevents.in > textevents.h 2> textenums.h
$(AM_V_GEN) ./make-te < textevents.in > textevents.h 2> textenums.h

marshal.h: marshalers.list
$(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=_hexchat_marshal --header $(srcdir)/marshalers.list > $@

marshal.c: marshalers.list
$(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=_hexchat_marshal --body $(srcdir)/marshalers.list > $@


BUILT_SOURCES = textenums.h textevents.h marshal.c marshal.h

BUILT_SOURCES = textenums.h textevents.h
CLEANFILES = $(BUILT_SOURCES)
220 changes: 138 additions & 82 deletions src/common/cfgfiles.c

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/common/cfgfiles.h
Expand Up @@ -24,10 +24,10 @@

#include "hexchat.h"

#define LANGUAGES_LENGTH 52
#define LANGUAGES_LENGTH 53

extern char *xdir;
extern const char const *languages[LANGUAGES_LENGTH];
extern const char * const languages[LANGUAGES_LENGTH];

char *cfg_get_str (char *cfg, const char *var, char *dest, int dest_len);
int cfg_get_bool (char *var);
Expand Down
27 changes: 22 additions & 5 deletions src/common/common.vcxproj
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Configuration">
<PlatformToolset>v110</PlatformToolset>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|Win32">
Expand All @@ -14,7 +14,6 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\config-win32.h" />
<ClInclude Include="cfgfiles.h" />
<ClInclude Include="chanopt.h" />
<ClInclude Include="ctcp.h" />
Expand All @@ -25,6 +24,7 @@
<ClInclude Include="ignore.h" />
<ClInclude Include="inbound.h" />
<ClInclude Include="inet.h" />
<ClInclude Include="marshal.h" />
<ClInclude Include="modes.h" />
<ClInclude Include="msproxy.h" />
<ClInclude Include="network.h" />
Expand All @@ -39,7 +39,6 @@
<ClInclude Include="text.h" />
<ClInclude Include="textenums.h" />
<ClInclude Include="textevents.h" />
<ClInclude Include="thread.h" />
<ClInclude Include="tree.h" />
<ClInclude Include="typedef.h" />
<ClInclude Include="url.h" />
Expand All @@ -58,6 +57,7 @@
<ClCompile Include="identd.c" />
<ClCompile Include="ignore.c" />
<ClCompile Include="inbound.c" />
<ClCompile Include="marshal.c" />
<ClCompile Include="modes.c" />
<ClCompile Include="msproxy.c" />
<ClCompile Include="network.c" />
Expand All @@ -70,13 +70,16 @@
<ClCompile Include="servlist.c" />
<ClCompile Include="ssl.c" />
<ClCompile Include="text.c" />
<ClCompile Include="thread.c" />
<ClCompile Include="tree.c" />
<ClCompile Include="url.c" />
<ClCompile Include="userlist.c" />
<ClCompile Include="util.c" />
<ClCompile Include="hexchat.c" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\config-win32.h.tt" />
<ClInclude Include="..\..\config-win32.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{87554B59-006C-4D94-9714-897B27067BA3}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
Expand Down Expand Up @@ -153,4 +156,18 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<ItemDefinitionGroup>
<PreBuildEvent>
<Command><![CDATA[
SET SOLUTIONDIR=$(SolutionDir)..\
powershell -File "$(SolutionDir)..\version-template.ps1" "$(SolutionDir)..\config-win32.h.tt" "$(SolutionDir)..\config-win32.h"
powershell -File "$(SolutionDir)..\version-template.ps1" "$(SolutionDir)..\win32\version.txt.tt" "$(SolutionDir)..\win32\version.txt.tmp"
REM version.txt must be in UTF-8 without trailing newline
powershell "[string] $content = Get-Content '$(SolutionDir)..\win32\version.txt.tmp' -Encoding UTF8; [System.IO.File]::WriteAllText('$(SolutionDir)..\win32\version.txt', $content); Remove-Item '$(SolutionDir)..\win32\version.txt.tmp';"
"$(DepsRoot)\bin\glib-genmarshal.exe" --prefix=_hexchat_marshal --header "$(ProjectDir)marshalers.list" > "$(ProjectDir)marshal.h"
"$(DepsRoot)\bin\glib-genmarshal.exe" --prefix=_hexchat_marshal --body "$(ProjectDir)marshalers.list" > "$(ProjectDir)marshal.c"
]]></Command>
</PreBuildEvent>
</ItemDefinitionGroup>
</Project>
15 changes: 9 additions & 6 deletions src/common/common.vcxproj.filters
Expand Up @@ -83,9 +83,6 @@
<ClInclude Include="textevents.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="thread.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="tree.h">
<Filter>Header Files</Filter>
</ClInclude>
Expand Down Expand Up @@ -113,6 +110,9 @@
<ClInclude Include="typedef.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="marshal.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="cfgfiles.c">
Expand Down Expand Up @@ -175,9 +175,6 @@
<ClCompile Include="text.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="thread.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="tree.c">
<Filter>Source Files</Filter>
</ClCompile>
Expand All @@ -193,5 +190,11 @@
<ClCompile Include="hexchat.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="marshal.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\config-win32.h.tt" />
</ItemGroup>
</Project>
27 changes: 3 additions & 24 deletions src/common/dbus/Makefile.am
Expand Up @@ -7,29 +7,22 @@ libhexchatdbus_a_SOURCES = \

EXTRA_DIST = \
remote-object.xml \
apps_hexchat_url_handler.schemas \
marshallers.list \
example.py \
org.hexchat.service.service.in \
README
org.hexchat.service.service.in

BUILT_SOURCES = \
marshallers.h \
remote-object-glue.h

CLEANFILES = $(BUILT_SOURCES)

AM_CPPFLAGS = $(COMMON_CFLAGS) $(DBUS_CFLAGS)

noinst_PROGRAMS = example
example_SOURCES = example.c
example_SOURCES = example.c
example_LDADD = $(DBUS_LIBS) $(GLIB_LIBS)

remote-object-glue.h: remote-object.xml
$(LIBTOOL) --mode=execute $(DBUS_BINDING_TOOL) --prefix=remote_object --mode=glib-server --output=$@ $<

marshallers.h: marshallers.list
$(LIBTOOL) --mode=execute $(GLIB_GENMARSHAL) --header --body $< > $@
$(AM_V_GEN) $(LIBTOOL) --mode=execute $(DBUS_BINDING_TOOL) --prefix=remote_object --mode=glib-server --output=$@ $<

# Dbus service file
servicedir = $(DBUS_SERVICES_DIR)
Expand All @@ -40,17 +33,3 @@ service_DATA = $(service_in_files:.service.in=.service)
$(service_DATA): $(service_in_files) Makefile
@sed -e "s|\@bindir\@|$(bindir)|" $< > $@

#if DO_GCONF
#GCONF_SCHEMA_CONFIG_SOURCE = `$(GCONFTOOL) --get-default-source`
#GCONF_SCHEMA_FILE_DIR = $(sysconfdir)/gconf/schemas
#schemadir = $(GCONF_SCHEMA_FILE_DIR)
#schema_DATA = apps_hexchat_url_handler.schemas
#install-data-local:
# if test -z "$(DESTDIR)" ; then \
# for p in $(schema_DATA) ; do \
# GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(srcdir)/$$p; \
# done \
# fi
#else
install-data-local:
#endif
37 changes: 0 additions & 37 deletions src/common/dbus/apps_hexchat_url_handler.schemas

This file was deleted.

8 changes: 4 additions & 4 deletions src/common/dbus/dbus-plugin.c
Expand Up @@ -241,7 +241,7 @@ static gboolean remote_object_send_modes (RemoteObject *obj,
GError **error);

#include "remote-object-glue.h"
#include "marshallers.h"
#include "../marshal.h"

/* Useful functions */

Expand Down Expand Up @@ -317,7 +317,7 @@ remote_object_class_init (RemoteObjectClass *klass)
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_user_marshal_VOID__POINTER_POINTER_UINT_UINT,
_hexchat_marshal_VOID__POINTER_POINTER_UINT_UINT,
G_TYPE_NONE,
4, G_TYPE_STRV, G_TYPE_STRV, G_TYPE_UINT, G_TYPE_UINT);

Expand All @@ -327,7 +327,7 @@ remote_object_class_init (RemoteObjectClass *klass)
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_user_marshal_VOID__POINTER_POINTER_UINT_UINT,
_hexchat_marshal_VOID__POINTER_POINTER_UINT_UINT,
G_TYPE_NONE,
4, G_TYPE_STRV, G_TYPE_STRV, G_TYPE_UINT, G_TYPE_UINT);

Expand All @@ -337,7 +337,7 @@ remote_object_class_init (RemoteObjectClass *klass)
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_user_marshal_VOID__POINTER_POINTER_UINT_UINT,
_hexchat_marshal_VOID__POINTER_POINTER_UINT_UINT,
G_TYPE_NONE,
3, G_TYPE_STRV, G_TYPE_UINT, G_TYPE_UINT);

Expand Down
4 changes: 2 additions & 2 deletions src/common/dbus/example.c
Expand Up @@ -22,7 +22,7 @@
#include <config.h>
#include <dbus/dbus-glib.h>
#include <stdlib.h>
#include "marshallers.h"
#include "../marshal.c"

#define DBUS_SERVICE "org.hexchat.service"
#define DBUS_REMOTE "/org/hexchat/Remote"
Expand Down Expand Up @@ -159,7 +159,7 @@ main (int argc, char **argv)
g_print ("Server hook id=%d\n", server_id);

dbus_g_object_register_marshaller (
g_cclosure_user_marshal_VOID__POINTER_POINTER_UINT_UINT,
_hexchat_marshal_VOID__POINTER_POINTER_UINT_UINT,
G_TYPE_NONE,
G_TYPE_STRV, G_TYPE_STRV, G_TYPE_UINT, G_TYPE_UINT,
G_TYPE_INVALID);
Expand Down
1 change: 0 additions & 1 deletion src/common/dbus/marshallers.list

This file was deleted.

8 changes: 5 additions & 3 deletions src/common/dcc.c
Expand Up @@ -394,7 +394,7 @@ dcc_close (struct DCC *dcc, int dccstat, int destroy)

if(dccstat == STAT_DONE)
{
/* if we just completed a dcc recieve, move the */
/* if we just completed a dcc receive, move the */
/* completed file to the completed directory */
if(dcc->type == TYPE_RECV)
{
Expand Down Expand Up @@ -557,8 +557,7 @@ dcc_chat_line (struct DCC *dcc, char *line)
for (i = 5; i < PDIWORDS; i++)
word[i] = "\000";

ret = plugin_emit_print (sess, word)
+ plugin_emit_print_attrs (sess, word, 0);
ret = plugin_emit_print (sess, word, 0);

/* did the plugin close it? */
if (!g_slist_find (dcc_list, dcc))
Expand Down Expand Up @@ -1806,7 +1805,10 @@ dcc_send (struct session *sess, char *to, char *file, int maxcps, int passive)

dcc = new_dcc ();
if (!dcc)
{
free (file);
return;
}
dcc->file = file;
dcc->maxcps = maxcps;

Expand Down
2 changes: 1 addition & 1 deletion src/common/dcc.h
Expand Up @@ -87,7 +87,7 @@ struct DCC
unsigned char dccstat; /* 0 = QUEUED 1 = ACTIVE 2 = FAILED 3 = DONE */
unsigned int resume_sent:1; /* resume request sent */
unsigned int fastsend:1;
unsigned int ackoffset:1; /* is reciever sending acks as an offset from */
unsigned int ackoffset:1; /* is receiver sending acks as an offset from */
/* the resume point? */
unsigned int throttled:2; /* 0x1 = per send/get throttle
0x2 = global throttle */
Expand Down
8 changes: 6 additions & 2 deletions src/common/fe.h
Expand Up @@ -86,7 +86,8 @@ void fe_text_clear (struct session *sess, int lines);
void fe_close_window (struct session *sess);
void fe_progressbar_start (struct session *sess);
void fe_progressbar_end (struct server *serv);
void fe_print_text (struct session *sess, char *text, time_t stamp);
void fe_print_text (struct session *sess, char *text, time_t stamp,
gboolean no_activity);
void fe_userlist_insert (struct session *sess, struct User *newuser, int row, int sel);
int fe_userlist_remove (struct session *sess, struct User *user);
void fe_userlist_rehash (struct session *sess, struct User *user);
Expand Down Expand Up @@ -117,10 +118,11 @@ void fe_set_nick (struct server *serv, char *newnick);
void fe_ignore_update (int level);
void fe_beep (session *sess);
void fe_lastlog (session *sess, session *lastlog_sess, char *sstr, gtk_xtext_search_flags flags);
void fe_set_lag (server *serv, int lag);
void fe_set_lag (server *serv, long lag);
void fe_set_throttle (server *serv);
void fe_set_away (server *serv);
void fe_serverlist_open (session *sess);
void fe_get_bool (char *title, char *prompt, void *callback, void *userdata);
void fe_get_str (char *prompt, char *def, void *callback, void *ud);
void fe_get_int (char *prompt, int def, void *callback, void *ud);
#define FRF_WRITE 1 /* save file */
Expand Down Expand Up @@ -178,5 +180,7 @@ typedef enum
void fe_tray_set_icon (feicon icon);
void fe_tray_set_tooltip (const char *text);
void fe_tray_set_balloon (const char *title, const char *text);
void fe_open_chan_list (server *serv, char *filter, int do_refresh);
const char *fe_get_default_font ();

#endif
31 changes: 25 additions & 6 deletions src/common/hexchat.c
Expand Up @@ -232,7 +232,7 @@ find_channel (server *serv, char *chan)
while (list)
{
sess = list->data;
if ((!serv || serv == sess->server) && sess->type != SESS_DIALOG)
if ((!serv || serv == sess->server) && sess->type == SESS_CHANNEL)
{
if (!serv->p_cmp (chan, sess->channel))
return sess;
Expand Down Expand Up @@ -286,12 +286,16 @@ lag_check (void)
NULL, NULL, 0);
if (prefs.hex_net_auto_reconnect)
serv->auto_reconnect (serv, FALSE, -1);
} else if (!serv->lag_sent)
} else
{
snprintf (tbuf, sizeof (tbuf), "LAG%lu", tim);
serv->p_ping (serv, "", tbuf);
serv->lag_sent = tim;
fe_set_lag (serv, -1);

if (!serv->lag_sent)
{
serv->lag_sent = tim;
fe_set_lag (serv, -1);
}
}
}
list = list->next;
Expand Down Expand Up @@ -447,6 +451,7 @@ irc_init (session *sess)

if (arg_command != NULL)
{
handle_command (sess, arg_command, FALSE);
g_free (arg_command);
}

Expand Down Expand Up @@ -523,6 +528,8 @@ new_ircwindow (server *serv, char *name, int type, int focus)
irc_init (sess);
chanopt_load (sess);
scrollback_load (sess);
if (sess->scrollwritten && sess->scrollback_replay_marklast)
sess->scrollback_replay_marklast (sess);
plugin_emit_dummy_print (sess, "Open Context");

return sess;
Expand Down Expand Up @@ -735,7 +742,7 @@ static char defaultconf_commands[] =
"NAME WII\n" "CMD quote WHOIS %2 %2\n\n";

static char defaultconf_urlhandlers[] =
"NAME Open Link in Private Firefox Window\n" "CMD !firefox -private %s\n\n";
"NAME Open Link in a new Firefox Window\n" "CMD !firefox -new-window %s\n\n";

#ifdef USE_SIGACTION
/* Close and open log files on SIGUSR1. Usefull for log rotating */
Expand Down Expand Up @@ -1088,7 +1095,7 @@ main (int argc, char *argv[])
{
/* this is probably the first run */
load_default_config ();
make_config_dirs (); /* FIXME: if this fail display an error (?) */
make_config_dirs ();
make_dcc_dirs ();
}

Expand All @@ -1113,6 +1120,18 @@ main (int argc, char *argv[])

fe_init ();

/* This is done here because cfgfiles.c is too early in
* the startup process to use gtk functions. */
if (g_access (get_xdir (), W_OK) != 0)
{
char buf[2048];

g_snprintf (buf, sizeof(buf),
_("You do not have write access to %s. Nothing from this session can be saved."),
get_xdir ());
fe_message (buf, FE_MSG_ERROR);
}

#ifndef WIN32
#ifndef __EMX__
/* OS/2 uses UID 0 all the time */
Expand Down
24 changes: 18 additions & 6 deletions src/common/hexchat.h
Expand Up @@ -31,6 +31,13 @@
#ifndef HEXCHAT_H
#define HEXCHAT_H

#ifdef USE_OPENSSL
#ifdef __APPLE__
#define __AVAILABILITYMACROS__
#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
#endif
#endif

#include "history.h"

#ifndef HAVE_SNPRINTF
Expand Down Expand Up @@ -149,8 +156,10 @@ struct hexchatprefs
unsigned int hex_gui_autoopen_recv;
unsigned int hex_gui_autoopen_send;
unsigned int hex_gui_compact;
unsigned int hex_gui_filesize_iec;
unsigned int hex_gui_focus_omitalerts;
unsigned int hex_gui_hide_menu;
unsigned int hex_gui_input_attr;
unsigned int hex_gui_input_icon;
unsigned int hex_gui_input_nick;
unsigned int hex_gui_input_spell;
Expand All @@ -165,6 +174,7 @@ struct hexchatprefs
unsigned int hex_gui_tab_dialogs;
unsigned int hex_gui_tab_dots;
unsigned int hex_gui_tab_icons;
unsigned int hex_gui_tab_scrollchans;
unsigned int hex_gui_tab_server;
unsigned int hex_gui_tab_sort;
unsigned int hex_gui_tab_utils;
Expand Down Expand Up @@ -206,6 +216,8 @@ struct hexchatprefs
unsigned int hex_input_tray_priv;
unsigned int hex_irc_auto_rejoin;
unsigned int hex_irc_conf_mode;
unsigned int hex_irc_hidehost;
unsigned int hex_irc_hide_nickchange;
unsigned int hex_irc_hide_version;
unsigned int hex_irc_invisible;
unsigned int hex_irc_logging;
Expand All @@ -231,7 +243,6 @@ struct hexchatprefs
unsigned int hex_text_indent;
unsigned int hex_text_replay;
unsigned int hex_text_search_case_match;
unsigned int hex_text_search_backward;
unsigned int hex_text_search_highlight_all;
unsigned int hex_text_search_follow;
unsigned int hex_text_search_regexp;
Expand Down Expand Up @@ -278,17 +289,20 @@ struct hexchatprefs
int hex_gui_pane_left_size;
int hex_gui_pane_right_size;
int hex_gui_pane_right_size_min;
int hex_gui_search_pos;
int hex_gui_slist_select;
int hex_gui_tab_layout;
int hex_gui_tab_newtofront;
int hex_gui_tab_pos;
int hex_gui_tab_small;
int hex_gui_tab_trunc;
int hex_gui_transparency;
int hex_gui_throttlemeter;
int hex_gui_ulist_pos;
int hex_gui_ulist_sort;
int hex_gui_url_mod;
int hex_gui_win_height;
int hex_gui_win_fullscreen;
int hex_gui_win_left;
int hex_gui_win_state;
int hex_gui_win_top;
Expand All @@ -305,9 +319,6 @@ struct hexchatprefs
int hex_notify_timeout;
int hex_text_max_indent;
int hex_text_max_lines;
int hex_text_tint_blue;
int hex_text_tint_green;
int hex_text_tint_red;
int hex_url_grabber_limit;

/* STRINGS */
Expand All @@ -316,7 +327,6 @@ struct hexchatprefs
char hex_dcc_completed_dir[PATHLEN + 1];
char hex_dcc_dir[PATHLEN + 1];
char hex_dcc_ip[DOMAINLEN + 1];
char hex_dnsprogram[72];
char hex_gui_ulist_doubleclick[256];
char hex_input_command_char[4];
char hex_irc_extra_hilight[300];
Expand Down Expand Up @@ -451,6 +461,7 @@ typedef struct session
int doing_who:1; /* /who sent on this channel */
int done_away_check:1; /* done checking for away status changes */
gtk_xtext_search_flags lastlog_flags;
void (*scrollback_replay_marklast) (struct session *sess);
} session;

struct msproxy_state_t
Expand Down Expand Up @@ -569,7 +580,7 @@ typedef struct server
time_t msg_last_time;

/*time_t connect_time;*/ /* when did it connect? */
time_t lag_sent;
unsigned long lag_sent; /* we are still waiting for this ping response*/
time_t ping_recv; /* when we last got a ping reply */
time_t away_time; /* when we were marked away */

Expand All @@ -584,6 +595,7 @@ typedef struct server
unsigned int skip_next_whois:1; /* hide whois output */
unsigned int inside_whois:1;
unsigned int doing_dns:1; /* /dns has been done */
unsigned int retry_sasl:1; /* retrying another sasl mech */
unsigned int end_of_motd:1; /* end of motd reached (logged in) */
unsigned int sent_quit:1; /* sent a QUIT already? */
unsigned int use_listargs:1; /* undernet and dalnet need /list >0,<10000 */
Expand Down
19 changes: 9 additions & 10 deletions src/common/ignore.c
Expand Up @@ -77,7 +77,7 @@ ignore_exists (char *mask)
*/

int
ignore_add (char *mask, int type)
ignore_add (char *mask, int type, gboolean overwrite)
{
struct ignore *ig = 0;
int change_only = FALSE;
Expand All @@ -94,7 +94,11 @@ ignore_add (char *mask, int type)
return 0;

ig->mask = strdup (mask);
ig->type = type;

if (!overwrite && change_only)
ig->type |= type;
else
ig->type = type;

if (!change_only)
ignore_list = g_slist_prepend (ignore_list, ig);
Expand Down Expand Up @@ -322,7 +326,7 @@ ignore_save ()
ig = (struct ignore *) temp->data;
if (!(ig->type & IG_NOSAVE))
{
snprintf (buf, sizeof (buf), "mask = %s\ntype = %d\n\n",
snprintf (buf, sizeof (buf), "mask = %s\ntype = %u\n\n",
ig->mask, ig->type);
write (fh, buf, strlen (buf));
}
Expand Down Expand Up @@ -376,16 +380,14 @@ flood_check (char *nick, char *ip, server *serv, session *sess, int what) /*0=ct
if (ip[i] == '@')
break;
snprintf (real_ip, sizeof (real_ip), "*!*%s", &ip[i]);
/*ignore_add (char *mask, int priv, int noti, int chan,
int ctcp, int invi, int unignore, int no_save) */

snprintf (buf, sizeof (buf),
_("You are being CTCP flooded from %s, ignoring %s\n"),
nick, real_ip);
PrintText (sess, buf);

/*FIXME: only ignore ctcp or all?, its ignoring ctcps for now */
ignore_add (real_ip, IG_CTCP);
/* ignore CTCP */
ignore_add (real_ip, IG_CTCP, FALSE);
return 0;
}
}
Expand All @@ -410,12 +412,9 @@ flood_check (char *nick, char *ip, server *serv, session *sess, int what) /*0=ct
PrintText (sess, buf);
serv->msg_last_time = current_time; /*we got the flood, restore all the vars for next one */
serv->msg_counter = 0;
/*ignore_add (char *mask, int priv, int noti, int chan,
int ctcp, int invi, int unignore, int no_save) */

if (prefs.hex_gui_autoopen_dialog)
{
/*FIXME: only ignore ctcp or all?, its ignoring ctcps for now */
prefs.hex_gui_autoopen_dialog = 0;
/* turn it back on in 30 secs */
fe_timeout_add (30000, flood_autodialog_timeout, NULL);
Expand Down
2 changes: 1 addition & 1 deletion src/common/ignore.h
Expand Up @@ -44,7 +44,7 @@ struct ignore
};

struct ignore *ignore_exists (char *mask);
int ignore_add (char *mask, int type);
int ignore_add (char *mask, int type, gboolean overwrite);
void ignore_showlist (session *sess);
int ignore_del (char *mask, struct ignore *ig);
int ignore_check (char *mask, int type);
Expand Down
222 changes: 174 additions & 48 deletions src/common/inbound.c
Expand Up @@ -33,6 +33,8 @@
#define WANTDNS
#include "inet.h"

#include <gio/gio.h>

#include "hexchat.h"
#include "util.h"
#include "ignore.h"
Expand All @@ -46,6 +48,7 @@
#include "text.h"
#include "ctcp.h"
#include "hexchatc.h"
#include "chanopt.h"


void
Expand Down Expand Up @@ -467,7 +470,7 @@ inbound_chanmsg (server *serv, session *sess, char *chan, char *from,

if (fromme)
{
if (prefs.hex_away_auto_unmark && serv->is_away)
if (prefs.hex_away_auto_unmark && serv->is_away && !tags_data->timestamp)
sess->server->p_set_back (sess->server);
EMIT_SIGNAL_TIMESTAMP (XP_TE_UCHANMSG, sess, from, text, nickchar, NULL,
0, tags_data->timestamp);
Expand Down Expand Up @@ -581,6 +584,7 @@ inbound_ujoin (server *serv, char *chan, char *nick, char *ip,
const message_tags_data *tags_data)
{
session *sess;
int found_unused = FALSE;

/* already joined? probably a bnc */
sess = find_channel (serv, chan);
Expand All @@ -592,13 +596,21 @@ inbound_ujoin (server *serv, char *chan, char *nick, char *ip,
{
/* find a "<none>" tab and use that */
sess = find_unused_session (serv);
found_unused = sess != NULL;
if (!sess)
/* last resort, open a new tab/window */
sess = new_ircwindow (serv, chan, SESS_CHANNEL, 1);
}
}

safe_strcpy (sess->channel, chan, CHANLEN);
if (found_unused)
{
chanopt_load (sess);
scrollback_load (sess);
if (sess->scrollwritten && sess->scrollback_replay_marklast)
sess->scrollback_replay_marklast (sess);
}

fe_set_channel (sess);
fe_set_title (sess);
Expand Down Expand Up @@ -667,8 +679,10 @@ inbound_nameslist (server *serv, char *chan, char *names,
const message_tags_data *tags_data)
{
session *sess;
char **name_list;
char *host, *nopre_name;
char name[NICKLEN];
int pos = 0;
int i, offset;

sess = find_channel (serv, chan);
if (!sess)
Expand All @@ -687,27 +701,37 @@ inbound_nameslist (server *serv, char *chan, char *names,
userlist_clear (sess);
}

while (1)
name_list = g_strsplit (names, " ", -1);
for (i = 0; name_list[i]; i++)
{
switch (*names)
host = NULL;
offset = sizeof(name);

if (name_list[i][0] == 0)
continue;

if (serv->have_uhnames)
{
case 0:
name[pos] = 0;
if (pos != 0)
userlist_add (sess, name, 0, NULL, NULL, tags_data);
return;
case ' ':
name[pos] = 0;
pos = 0;
userlist_add (sess, name, 0, NULL, NULL, tags_data);
break;
default:
name[pos] = *names;
if (pos < (NICKLEN-1))
pos++;
offset = 0;
nopre_name = name_list[i];

/* Ignore prefixes so '!' won't cause issues */
while (strchr (serv->nick_prefixes, *nopre_name) != NULL)
{
nopre_name++;
offset++;
}

offset += strcspn (nopre_name, "!");
if (offset++ < strlen (name_list[i]))
host = name_list[i] + offset;
}
names++;

g_strlcpy (name, name_list[i], MIN(offset, sizeof(name)));

userlist_add (sess, name, host, NULL, NULL, tags_data);
}
g_strfreev (name_list);
}

void
Expand Down Expand Up @@ -754,7 +778,7 @@ inbound_join (server *serv, char *chan, char *user, char *ip, char *account,
session *sess = find_channel (serv, chan);
if (sess)
{
EMIT_SIGNAL_TIMESTAMP (XP_TE_JOIN, sess, user, chan, ip, NULL, 0,
EMIT_SIGNAL_TIMESTAMP (XP_TE_JOIN, sess, user, chan, ip, account, 0,
tags_data->timestamp);
userlist_add (sess, user, ip, account, realname, tags_data);
}
Expand Down Expand Up @@ -878,8 +902,8 @@ inbound_ping_reply (session *sess, char *timestring, char *from,
if (lag)
{
sess->server->lag_sent = 0;
sess->server->lag = dif / 1000;
fe_set_lag (sess->server, dif / 100000);
sess->server->lag = dif;
fe_set_lag (sess->server, dif);
return;
}

Expand All @@ -892,7 +916,7 @@ inbound_ping_reply (session *sess, char *timestring, char *from,
tags_data->timestamp);
} else
{
snprintf (outbuf, sizeof (outbuf), "%ld.%ld%ld", dif / 1000000, (dif / 100000) % 10, dif % 10);
snprintf (outbuf, sizeof (outbuf), "%ld.%03ld", dif / 1000, dif % 1000);
EMIT_SIGNAL_TIMESTAMP (XP_TE_PINGREP, sess, from, outbuf, NULL, NULL, 0,
tags_data->timestamp);
}
Expand Down Expand Up @@ -924,19 +948,8 @@ inbound_notice (server *serv, char *to, char *nick, char *msg, char *ip, int id,
if (is_channel (serv, ptr))
sess = find_channel (serv, ptr);

if (!sess && ptr[0] == '@')
{
ptr++;
sess = find_channel (serv, ptr);
}

if (!sess && ptr[0] == '%')
{
ptr++;
sess = find_channel (serv, ptr);
}

if (!sess && ptr[0] == '+')
/* /notice [mode-prefix]#channel should end up in that channel */
if (!sess && strchr(serv->nick_prefixes, ptr[0]) != NULL)
{
ptr++;
sess = find_channel (serv, ptr);
Expand Down Expand Up @@ -1258,20 +1271,74 @@ inbound_next_nick (session *sess, char *nick, int error,
}
}


static void
dns_addr_callback (GObject *obj, GAsyncResult *result, gpointer user_data)
{
GResolver *resolver = G_RESOLVER(obj);
session *sess = (session*)user_data;
gchar *addr;

g_return_if_fail (is_session(sess));

addr = g_resolver_lookup_by_address_finish (resolver, result, NULL);
if (addr)
PrintTextf (sess, _("Resolved to %s"), addr);
else
PrintText (sess, _("Not found"));
}

static void
dns_name_callback (GObject *obj, GAsyncResult *result, gpointer user_data)
{
GResolver *resolver = G_RESOLVER(obj);
session *sess = (session*)user_data;
GList* addrs;
gchar* addr;
GList* list;

g_return_if_fail (is_session (sess));

addrs = g_resolver_lookup_by_name_finish (resolver, result, NULL);
if (addrs)
{
PrintText (sess, _("Resolved to:"));

for (list = g_list_first (addrs); list; list = g_list_next (list))
{
addr = g_inet_address_to_string (list->data);
PrintTextf (sess, " %s", addr);
}

g_resolver_free_addresses (addrs);
}
else
PrintText (sess, _("Not found"));
}

void
do_dns (session *sess, char *nick, char *host,
const message_tags_data *tags_data)
const message_tags_data *tags_data)
{
GResolver *res = g_resolver_get_default ();
GInetAddress *addr;
char *po;
char tbuf[1024];

po = strrchr (host, '@');
if (po)
host = po + 1;
EMIT_SIGNAL_TIMESTAMP (XP_TE_RESOLVINGUSER, sess, nick, host, NULL, NULL, 0,
tags_data->timestamp);
snprintf (tbuf, sizeof (tbuf), "exec -d %s %s", prefs.hex_dnsprogram, host);
handle_command (sess, tbuf, FALSE);

if (nick)
EMIT_SIGNAL_TIMESTAMP (XP_TE_RESOLVINGUSER, sess, nick, host, NULL, NULL, 0,
tags_data->timestamp);

PrintTextf (sess, _("Looking up %s..."), host);

addr = g_inet_address_new_from_string (host);
if (addr)
g_resolver_lookup_by_address_async (res, addr, NULL, dns_addr_callback, sess);
else
g_resolver_lookup_by_name_async (res, host, NULL, dns_name_callback, sess);
}

static void
Expand All @@ -1288,6 +1355,8 @@ set_default_modes (server *serv)
strcat (modes, "s");
if (prefs.hex_irc_invisible)
strcat (modes, "i");
if (prefs.hex_irc_hidehost)
strcat (modes, "x");

if (modes[1] != '\0')
{
Expand Down Expand Up @@ -1425,10 +1494,15 @@ inbound_banlist (session *sess, time_t stamp, char *chan, char *mask,
server *serv = sess->server;
char *nl;

if ((nl = strchr (time_str, '\n')))
*nl = 0;
if (stamp == 0)
if (stamp <= 0)
{
time_str = "";
}
else
{
if ((nl = strchr (time_str, '\n')))
*nl = 0;
}

sess = find_channel (serv, chan);
if (!sess)
Expand Down Expand Up @@ -1594,6 +1668,11 @@ inbound_cap_ack (server *serv, char *nick, char *extensions,
serv->have_extjoin = TRUE;
}

if (strstr (extensions, "userhost-in-names") != NULL)
{
serv->have_uhnames = TRUE;
}

if (strstr (extensions, "server-time") != NULL)
{
serv->have_server_time = TRUE;
Expand Down Expand Up @@ -1671,22 +1750,30 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str,
strcat (buffer, "extended-join ");
want_cap = 1;
}
if (!strcmp (extension, "userhost-in-names"))
{
strcat (buffer, "userhost-in-names ");
want_cap = 1;
}

/* bouncers can prefix a name space to the extension so we should use.
* znc <= 1.0 uses "znc.in/server-time" and newer use "znc.in/server-time-iso".
*/
if (!strcmp (extension, "znc.in/server-time-iso"))
{
strcat (buffer, "znc.in/server-time-iso ");
want_cap = 1;
}
if (!strcmp (extension, "znc.in/server-time"))
{
strcat (buffer, "znc.in/server-time ");
want_cap = 1;
}
if (prefs.hex_irc_cap_server_time
&& !strcmp (extension, "server-time"))
{
strcat (buffer, "server-time ");
want_cap = 1;
}

/* if the SASL password is set AND auth mode is set to SASL, request SASL auth */
Expand All @@ -1708,7 +1795,7 @@ inbound_cap_ls (server *serv, char *nick, char *extensions_str,
EMIT_SIGNAL_TIMESTAMP (XP_TE_CAPREQ, serv->server_session,
buffer + 9, NULL, NULL, NULL, 0,
tags_data->timestamp);
tcp_sendf (serv, "%s\r\n", buffer);
tcp_sendf (serv, "%s\r\n", g_strchomp (buffer));
}
if (!want_sasl)
{
Expand Down Expand Up @@ -1741,14 +1828,50 @@ static const char *sasl_mechanisms[] =
"EXTERNAL"
};

void
inbound_sasl_supportedmechs (server *serv, char *list)
{
int i;

if (serv->sasl_mech != MECH_EXTERNAL)
{
/* Use most secure one supported */
for (i = MECH_AES; i >= MECH_PLAIN; i--)
{
if (strstr (list, sasl_mechanisms[i]) != NULL)
{
serv->sasl_mech = i;
serv->retry_sasl = TRUE;
tcp_sendf (serv, "AUTHENTICATE %s\r\n", sasl_mechanisms[i]);
return;
}
}
}

/* Abort, none supported */
serv->sent_saslauth = TRUE;
tcp_sendf (serv, "AUTHENTICATE *\r\n");
return;
}

void
inbound_sasl_authenticate (server *serv, char *data)
{
ircnet *net = (ircnet*)serv->network;
char *user, *pass = NULL;
const char *mech = sasl_mechanisms[serv->sasl_mech];

user = (((ircnet*)serv->network)->user)
? (((ircnet*)serv->network)->user) : prefs.hex_irc_user_name;
/* Got a list of supported mechanisms from inspircd */
if (strchr (data, ',') != NULL)
{
inbound_sasl_supportedmechs (serv, data);
return;
}

if (net->user && !(net->flags & FLAG_USE_GLOBAL))
user = net->user;
else
user = prefs.hex_irc_user_name;

switch (serv->sasl_mech)
{
Expand Down Expand Up @@ -1788,6 +1911,9 @@ inbound_sasl_authenticate (server *serv, char *data)
int
inbound_sasl_error (server *serv)
{
if (serv->retry_sasl && !serv->sent_saslauth)
return 1;

/* If server sent 904 before we sent password,
* mech not support so fallback to next mech */
if (!serv->sent_saslauth && serv->sasl_mech != MECH_EXTERNAL && serv->sasl_mech != MECH_PLAIN)
Expand Down
1 change: 1 addition & 0 deletions src/common/inbound.h
Expand Up @@ -97,6 +97,7 @@ void inbound_cap_list (server *serv, char *nick, char *extensions,
const message_tags_data *tags_data);
void inbound_sasl_authenticate (server *serv, char *data);
int inbound_sasl_error (server *serv);
void inbound_sasl_supportedmechs (server *serv, char *list);
void do_dns (session *sess, char *nick, char *host,
const message_tags_data *tags_data);
gboolean alert_match_word (char *word, char *masks);
Expand Down
4 changes: 4 additions & 0 deletions src/common/inet.h
Expand Up @@ -34,6 +34,10 @@
#endif
#ifdef WANTDNS
#include <netdb.h>
/* OpenBSD's netdb.h does not define AI_ADDRCONFIG */
#ifndef AI_ADDRCONFIG
#define AI_ADDRCONFIG 0
#endif
#endif
#define closesocket close
#define set_blocking(sok) fcntl(sok, F_SETFL, 0)
Expand Down
4 changes: 2 additions & 2 deletions src/common/make-te.vcxproj
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Configuration">
<PlatformToolset>v110</PlatformToolset>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|Win32">
Expand Down
8 changes: 8 additions & 0 deletions src/common/marshalers.list
@@ -0,0 +1,8 @@
# xtext
VOID:OBJECT,OBJECT
VOID:POINTER,POINTER
# sexy-entry
BOOLEAN:STRING
OBJECT:OBJECT,OBJECT
# dbus-plugin & dbus-example
VOID:POINTER,POINTER,UINT,UINT
4 changes: 2 additions & 2 deletions src/common/msproxy.c
Expand Up @@ -72,7 +72,7 @@ send_msprequest(s, state, request, end)

if ((w = send(s, request, l, 0)) != l) {
#ifdef DEBUG_MSPROXY
printf ("send_msprequest(): send() failed (%d bytes sent instead of %d\n", w, l);
printf ("send_msprequest(): send() failed (%ld bytes sent instead of %Iu\n", w, l);
perror ("Error is");
#endif
return -1;
Expand All @@ -93,7 +93,7 @@ recv_mspresponse(s, state, response)
do {
if ((r = recv (s, response, sizeof (*response), 0)) < MSPROXY_MINLENGTH) {
#ifdef DEBUG_MSPROXY
printf ("recv_mspresponse(): expected to read atleast %d, read %d\n", MSPROXY_MINLENGTH, r);
printf ("recv_mspresponse(): expected to read atleast %d, read %ld\n", MSPROXY_MINLENGTH, r);
#endif
return -1;
}
Expand Down
7 changes: 5 additions & 2 deletions src/common/notify.c
Expand Up @@ -394,8 +394,11 @@ notify_flush_watches (server * serv, GSList *from, GSList *end)
while (list != end)
{
notify = list->data;
serv->supports_monitor ? strcat (tbuf, ",") : strcat (tbuf, " +");
strcat (tbuf, notify->name);
if (serv->supports_monitor)
g_strlcat (tbuf, ",", sizeof(tbuf));
else
g_strlcat (tbuf, " +", sizeof(tbuf));
g_strlcat (tbuf, notify->name, sizeof(tbuf));
list = list->next;
}
serv->p_raw (serv, tbuf);
Expand Down
194 changes: 161 additions & 33 deletions src/common/outbound.c

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion src/common/outbound.h
Expand Up @@ -20,6 +20,8 @@
#ifndef HEXCHAT_OUTBOUND_H
#define HEXCHAT_OUTBOUND_H

#include "hexchat.h"

extern const struct commands xc_cmds[];
extern GSList *menu_list;

Expand All @@ -34,7 +36,7 @@ void notc_msg (session *sess);
void server_sendpart (server * serv, char *channel, char *reason);
void server_sendquit (session * sess);
int menu_streq (const char *s1, const char *s2, int def);
void open_query (server *serv, char *nick, gboolean focus_existing);
session *open_query (server *serv, char *nick, gboolean focus_existing);
gboolean load_perform_file (session *sess, char *file);

#endif
137 changes: 86 additions & 51 deletions src/common/plugin.c
Expand Up @@ -102,16 +102,21 @@ enum
LIST_USERS
};

/* We use binary flags here because it makes it possible for plugin_hook_find()
* to match several types of hooks. This is used so that plugin_hook_run()
* match both HOOK_SERVER and HOOK_SERVER_ATTRS hooks when plugin_emit_server()
* is called.
*/
enum
{
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 */
HOOK_COMMAND = 1 << 0, /* /command */
HOOK_SERVER = 1 << 1, /* PRIVMSG, NOTICE, numerics */
HOOK_SERVER_ATTRS = 1 << 2, /* same as above, with attributes */
HOOK_PRINT = 1 << 3, /* All print events */
HOOK_PRINT_ATTRS = 1 << 4, /* same as above, with attributes */
HOOK_TIMER = 1 << 5, /* timeouts */
HOOK_FD = 1 << 6, /* sockets & fds */
HOOK_DELETED = 1 << 7 /* marked for deletion */
};

GSList *plugin_list = NULL; /* export for plugingui.c */
Expand Down Expand Up @@ -474,37 +479,50 @@ plugin_auto_load_cb (char *filename)
}
}

static char *
plugin_get_libdir ()
{
const char *libdir;

libdir = g_getenv ("HEXCHAT_LIBDIR");
if (libdir && *libdir)
return (char*)libdir;
else
return HEXCHATLIBDIR;
}

void
plugin_auto_load (session *sess)
{
char *lib_dir;
char *sub_dir;
ps = sess;

lib_dir = plugin_get_libdir ();
sub_dir = g_build_filename (get_xdir (), "addons", NULL);

#ifdef WIN32
/* a long list of bundled plugins that should be loaded automatically,
* user plugins should go to <config>, leave Program Files alone! */
for_files (HEXCHATLIBDIR, "hcchecksum.dll", plugin_auto_load_cb);
for_files (HEXCHATLIBDIR, "hcdns.dll", plugin_auto_load_cb);
for_files (HEXCHATLIBDIR, "hcdoat.dll", plugin_auto_load_cb);
for_files (HEXCHATLIBDIR, "hcexec.dll", plugin_auto_load_cb);
for_files (HEXCHATLIBDIR, "hcfishlim.dll", plugin_auto_load_cb);
for_files (HEXCHATLIBDIR, "hcmpcinfo.dll", plugin_auto_load_cb);
for_files (HEXCHATLIBDIR, "hcperl.dll", plugin_auto_load_cb);
for_files (HEXCHATLIBDIR, "hcpython2.dll", plugin_auto_load_cb);
for_files (HEXCHATLIBDIR, "hcpython3.dll", plugin_auto_load_cb);
for_files (HEXCHATLIBDIR, "hcupd.dll", plugin_auto_load_cb);
for_files (HEXCHATLIBDIR, "hcwinamp.dll", plugin_auto_load_cb);
for_files (HEXCHATLIBDIR, "hcsysinfo.dll", plugin_auto_load_cb);
for_files (lib_dir, "hcchecksum.dll", plugin_auto_load_cb);
for_files (lib_dir, "hcdoat.dll", plugin_auto_load_cb);
for_files (lib_dir, "hcexec.dll", plugin_auto_load_cb);
for_files (lib_dir, "hcfishlim.dll", plugin_auto_load_cb);
for_files (lib_dir, "hcmpcinfo.dll", plugin_auto_load_cb);
for_files (lib_dir, "hcperl.dll", plugin_auto_load_cb);
for_files (lib_dir, "hcpython2.dll", plugin_auto_load_cb);
for_files (lib_dir, "hcpython3.dll", plugin_auto_load_cb);
for_files (lib_dir, "hcupd.dll", plugin_auto_load_cb);
for_files (lib_dir, "hcwinamp.dll", plugin_auto_load_cb);
for_files (lib_dir, "hcsysinfo.dll", plugin_auto_load_cb);

for_files (sub_dir, "*.dll", plugin_auto_load_cb);
#else
#if defined(__hpux)
for_files (HEXCHATLIBDIR, "*.sl", plugin_auto_load_cb);
for_files (lib_dir, "*.sl", plugin_auto_load_cb);
for_files (sub_dir, "*.sl", plugin_auto_load_cb);
#else
for_files (HEXCHATLIBDIR, "*.so", plugin_auto_load_cb);
for_files (lib_dir, "*.so", plugin_auto_load_cb);
for_files (sub_dir, "*.so", plugin_auto_load_cb);
#endif
#endif
Expand Down Expand Up @@ -560,16 +578,14 @@ plugin_hook_find (GSList *list, int type, char *name)
while (list)
{
hook = list->data;
if (hook && hook->type == type)
if (hook && (hook->type & type))
{
if (g_ascii_strcasecmp (hook->name, name) == 0)
return list;

if (type == HOOK_SERVER)
{
if (g_ascii_strcasecmp (hook->name, "RAW LINE") == 0)
if ((type & HOOK_SERVER)
&& g_ascii_strcasecmp (hook->name, "RAW LINE") == 0)
return list;
}
}
list = list->next;
}
Expand Down Expand Up @@ -599,7 +615,7 @@ plugin_hook_run (session *sess, char *name, char *word[], char *word_eol[],
hook->pl->context = sess;

/* run the plugin's callback function */
switch (type)
switch (hook->type)
{
case HOOK_COMMAND:
ret = ((hexchat_cmd_cb *)hook->callback) (word, word_eol, hook->userdata);
Expand Down Expand Up @@ -676,39 +692,30 @@ hexchat_event_attrs_free (hexchat_plugin *ph, hexchat_event_attrs *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, NULL, HOOK_SERVER);
}

int
plugin_emit_server_attrs (session *sess, char *name, char *word[], char *word_eol[],
time_t server_time)
plugin_emit_server (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);
return plugin_hook_run (sess, name, word, word_eol, &attrs,
HOOK_SERVER | HOOK_SERVER_ATTRS);
}

/* see if any plugins are interested in this print event */

int
plugin_emit_print (session *sess, char *word[])
{
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)
plugin_emit_print (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);
return plugin_hook_run (sess, word[0], word, NULL, &attrs,
HOOK_PRINT | HOOK_PRINT_ATTRS);
}

int
Expand Down Expand Up @@ -783,12 +790,27 @@ plugin_insert_hook (hexchat_hook *new_hook)
{
GSList *list;
hexchat_hook *hook;
int new_hook_type;

switch (new_hook->type)
{
case HOOK_PRINT:
case HOOK_PRINT_ATTRS:
new_hook_type = HOOK_PRINT | HOOK_PRINT_ATTRS;
break;
case HOOK_SERVER:
case HOOK_SERVER_ATTRS:
new_hook_type = HOOK_SERVER | HOOK_PRINT_ATTRS;
break;
default:
new_hook_type = new_hook->type;
}

list = hook_list;
while (list)
{
hook = list->data;
if (hook && 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;
Expand Down Expand Up @@ -1158,7 +1180,7 @@ hexchat_get_info (hexchat_plugin *ph, const char *id)
switch (hash)
{
case 0x325acab5: /* libdirfs */
return HEXCHATLIBDIR;
return plugin_get_libdir ();

case 0x14f51cd8: /* version */
return PACKAGE_VERSION;
Expand Down Expand Up @@ -1548,7 +1570,8 @@ hexchat_list_int (hexchat_plugin *ph, hexchat_list *xlist, const char *name)
{
guint32 hash = str_hash (name);
gpointer data = ph->context;
int tmp, type = LIST_CHANNELS;
int tmp = 0;
int type = LIST_CHANNELS;

/* a NULL xlist is a shortcut to current "channels" context */
if (xlist)
Expand Down Expand Up @@ -1601,13 +1624,25 @@ hexchat_list_int (hexchat_plugin *ph, hexchat_list *xlist, const char *name)
case 0xd1b: /* id */
return ((struct session *)data)->server->id;
case 0x5cfee87: /* flags */
tmp = ((struct session *)data)->alert_taskbar; /* bit 10 */
/* used if text_strip is unset */ /* 16 */
tmp <<= 1;
tmp = ((struct session *)data)->text_strip; /* 15 */
tmp <<= 1;
/* used if text_scrollback is unset */ /* 14 */
tmp <<= 1;
tmp |= ((struct session *)data)->text_scrollback; /* 13 */
tmp <<= 1;
/* used if text_logging is unset */ /* 12 */
tmp <<= 1;
tmp |= ((struct session *)data)->text_logging; /* 11 */
tmp <<= 1;
tmp |= ((struct session *)data)->alert_taskbar; /* 10 */
tmp <<= 1;
tmp |= ((struct session *)data)->alert_tray; /* 9 */
tmp <<= 1;
tmp |= ((struct session *)data)->alert_beep; /* 8 */
tmp <<= 1;
/*tmp |= ((struct session *)data)->color_paste;*/ /* 7 */
/* used if text_hidejoinpart is unset */ /* 7 */
tmp <<= 1;
tmp |= ((struct session *)data)->text_hidejoinpart; /* 6 */
tmp <<= 1;
Expand Down Expand Up @@ -2015,8 +2050,8 @@ hexchat_pluginpref_list (hexchat_plugin *pl, char* dest)
while (fscanf (fpIn, " %[^\n]", bufp) != EOF) /* read whole lines including whitespaces */
{
token = strtok (buffer, "=");
strncat (dest, token, strlen (token) - 1);
strcat (dest, ",");
g_strlcat (dest, g_strchomp (token), 4096); /* Dest must not be smaller than this */
g_strlcat (dest, ",", 4096);
}

fclose (fpIn);
Expand Down
8 changes: 3 additions & 5 deletions src/common/plugin.h
Expand Up @@ -170,11 +170,9 @@ int plugin_kill (char *name, int by_filename);
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_server (session *sess, char *name, char *word[], char *word_eol[],
time_t server_time);
int plugin_emit_print (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);
Expand Down
46 changes: 24 additions & 22 deletions src/common/proto-irc.c
Expand Up @@ -665,11 +665,11 @@ process_numeric (session * sess, int n,
else
EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANMODES, sess, word[4], word_eol[5],
NULL, NULL, 0, tags_data->timestamp);
fe_update_mode_buttons (sess, 'c', '-');
fe_update_mode_buttons (sess, 'r', '-');
fe_update_mode_buttons (sess, 't', '-');
fe_update_mode_buttons (sess, 'n', '-');
fe_update_mode_buttons (sess, 's', '-');
fe_update_mode_buttons (sess, 'i', '-');
fe_update_mode_buttons (sess, 'p', '-');
fe_update_mode_buttons (sess, 'm', '-');
fe_update_mode_buttons (sess, 'l', '-');
fe_update_mode_buttons (sess, 'k', '-');
Expand Down Expand Up @@ -968,6 +968,9 @@ process_numeric (session * sess, int n,
tcp_send_len (serv, "CAP END\r\n", 9);
}
break;
case 908: /* Supported SASL Mechs */
inbound_sasl_supportedmechs (serv, word[4]);
break;

default:

Expand Down Expand Up @@ -1039,8 +1042,12 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[],
{
char *chan = word[3];
char *account = word[4];
char *realname = word_eol[5] + 1;
char *realname = word_eol[5];

if (account && strcmp (account, "*") == 0)
account = NULL;
if (realname && *realname == ':')
realname++;
if (*chan == ':')
chan++;
if (!serv->p_cmp (nick, serv->nick))
Expand Down Expand Up @@ -1068,8 +1075,14 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[],
return;

case WORDL('K','I','L','L'):
EMIT_SIGNAL_TIMESTAMP (XP_TE_KILL, sess, nick, word_eol[5], NULL, NULL,
0, tags_data->timestamp);
{
char *reason = word_eol[4];
if (*reason == ':')
reason++;

EMIT_SIGNAL_TIMESTAMP (XP_TE_KILL, sess, nick, reason, NULL, NULL,
0, tags_data->timestamp);
}
return;

case WORDL('M','O','D','E'):
Expand Down Expand Up @@ -1197,7 +1210,8 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[],
if (*to)
{
/* Handle limited channel messages, for now no special event */
if (strchr (serv->nick_prefixes, to[0]) != NULL)
if (strchr (serv->chantypes, to[0]) == NULL
&& strchr (serv->nick_prefixes, to[0]) != NULL)
to++;

text = word_eol[4];
Expand Down Expand Up @@ -1502,9 +1516,6 @@ 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]))
{
Expand All @@ -1519,28 +1530,19 @@ irc_inline (server *serv, char *buf, int len)
word[0] = type;
word_eol[1] = buf; /* keep the ":" for plugins */

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)
if (plugin_emit_server (sess, type, word, word_eol,
tags_data.timestamp))
goto xit;

word[1]++;
word_eol[1] = buf + 1; /* but not for HexChat internally */

} else
{
int eat1;
int eat2;

word[0] = type = word[1];

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)
if (plugin_emit_server (sess, type, word, word_eol,
tags_data.timestamp))
goto xit;
}

Expand Down
217 changes: 70 additions & 147 deletions src/common/servlist.c

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions src/common/ssl.c
Expand Up @@ -17,6 +17,11 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/

#ifdef __APPLE__
#define __AVAILABILITYMACROS__
#define DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
#endif

#include "inet.h" /* make it first to avoid macro redefinitions */
#include <openssl/ssl.h> /* SSL_() */
#include <openssl/err.h> /* ERR_() */
Expand Down
85 changes: 57 additions & 28 deletions src/common/text.c
Expand Up @@ -79,7 +79,10 @@ scrollback_get_filename (session *sess)
g_free (buf);

chan = log_create_filename (sess->channel);
buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "scrollback" G_DIR_SEPARATOR_S "%s" G_DIR_SEPARATOR_S "%s.txt", get_xdir (), net, chan);
if (chan[0])
buf = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "scrollback" G_DIR_SEPARATOR_S "%s" G_DIR_SEPARATOR_S "%s.txt", get_xdir (), net, chan);
else
buf = NULL;
free (chan);

return buf;
Expand Down Expand Up @@ -207,7 +210,7 @@ scrollback_save (session *sess, char *text)
time_t stamp;
int len;

if (sess->type == SESS_SERVER)
if (sess->type == SESS_SERVER && prefs.hex_gui_tab_server == 1)
return;

if (sess->text_scrollback == SET_DEFAULT)
Expand Down Expand Up @@ -295,34 +298,58 @@ scrollback_load (session *sess)
{
char *buf_tmp;

/* If nothing but funny trailing matter e.g. 0x0d or 0x0d0a, toss it */
if (n_bytes >= 1 && buf[0] == 0x0d)
{
g_free (buf);
continue;
}

n_bytes--;
buf_tmp = buf;
buf = g_strndup (buf_tmp, n_bytes);
g_free (buf_tmp);

/*
* Some scrollback lines have three blanks after the timestamp and a newline
* Some have only one blank and a newline
* Some don't even have a timestamp
* Some don't have any text at all
*/
if (buf[0] == 'T')
{
if (sizeof (time_t) == 4)
stamp = strtoul (buf + 2, NULL, 10);
else
stamp = strtoull (buf + 2, NULL, 10); /* in case time_t is 64 bits */
text = strchr (buf + 3, ' ');
if (text)
if (text && text[1])
{
if (prefs.hex_text_stripcolor_replay)
{
text = strip_color (text + 1, -1, STRIP_COLOR);
}

fe_print_text (sess, text, stamp);
fe_print_text (sess, text, stamp, TRUE);

if (prefs.hex_text_stripcolor_replay)
{
g_free (text);
}
}
lines++;
else
{
fe_print_text (sess, " ", stamp, TRUE);
}
}
else
{
if (strlen (buf))
fe_print_text (sess, buf, 0, TRUE);
else
fe_print_text (sess, " ", 0, TRUE);
}
lines++;

g_free (buf);
}
Expand All @@ -340,7 +367,7 @@ scrollback_load (session *sess)
text = ctime (&stamp);
text[24] = 0; /* get rid of the \n */
buf = g_strdup_printf ("\n*\t%s %s\n\n", _("Loaded log from"), text);
fe_print_text (sess, buf, 0);
fe_print_text (sess, buf, 0, TRUE);
g_free (buf);
/*EMIT_SIGNAL (XP_TE_GENMSG, sess, "*", buf, NULL, NULL, NULL, 0);*/
}
Expand Down Expand Up @@ -513,12 +540,15 @@ log_create_pathname (char *servname, char *channame, char *netname)
{
char fname[384];
char fnametime[384];
struct tm *tm;
time_t now;

if (!netname)
{
netname = "NETWORK";
netname = strdup ("NETWORK");
}
else
{
netname = log_create_filename (netname);
}

/* first, everything is in UTF-8 */
Expand All @@ -533,11 +563,11 @@ log_create_pathname (char *servname, char *channame, char *netname)

log_insert_vars (fname, sizeof (fname), prefs.hex_irc_logmask, channame, netname, servname);
free (channame);
free (netname);

/* insert time/date */
now = time (NULL);
tm = localtime (&now);
strftime (fnametime, sizeof (fnametime), fname, tm);
strftime_utf8 (fnametime, sizeof (fnametime), fname, now);

/* create final path/filename */
if (logmask_is_fullpath ())
Expand Down Expand Up @@ -644,14 +674,7 @@ get_stamp_str (char *fmt, time_t tim, char **ret)
fmt = loc;
}

len = strftime (dest, sizeof (dest), fmt, localtime (&tim));
#ifdef WIN32
if (!len)
{
/* use failsafe format until a correct one is specified */
len = strftime (dest, sizeof (dest), "[%H:%M:%S]", localtime (&tim));
}
#endif
len = strftime_validated (dest, sizeof (dest), fmt, localtime (&tim));
if (len)
{
if (prefs.utf8_locale)
Expand All @@ -667,7 +690,7 @@ get_stamp_str (char *fmt, time_t tim, char **ret)
}

static void
log_write (session *sess, char *text)
log_write (session *sess, char *text, time_t ts)
{
char *temp;
char *stamp;
Expand Down Expand Up @@ -704,7 +727,8 @@ log_write (session *sess, char *text)

if (prefs.hex_stamp_log)
{
len = get_stamp_str (prefs.hex_stamp_log_format, time (0), &stamp);
if (!ts) ts = time(0);
len = get_stamp_str (prefs.hex_stamp_log_format, ts, &stamp);
if (len)
{
write (sess->logfd, stamp, len);
Expand Down Expand Up @@ -888,9 +912,9 @@ PrintTextTimeStamp (session *sess, char *text, time_t timestamp)
conv = text_validate ((char **)&text, &len);
}

log_write (sess, text);
log_write (sess, text, timestamp);
scrollback_save (sess, text);
fe_print_text (sess, text, timestamp);
fe_print_text (sess, text, timestamp, FALSE);

if (conv)
g_free (conv);
Expand Down Expand Up @@ -1008,6 +1032,7 @@ static char * const pevt_join_help[] = {
N_("The nick of the joining person"),
N_("The channel being joined"),
N_("The host of the person"),
N_("The account of the person"),
};

static char * const pevt_chanaction_help[] = {
Expand Down Expand Up @@ -1661,7 +1686,10 @@ pevent_load (char *filename)
if (fd == -1)
return 1;
if (fstat (fd, &st) != 0)
{
close (fd);
return 1;
}
ibuf = malloc (st.st_size);
read (fd, ibuf, st.st_size);
close (fd);
Expand Down Expand Up @@ -2076,8 +2104,6 @@ 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))
{
Expand All @@ -2094,10 +2120,7 @@ text_emit (int index, session *sess, char *a, char *b, char *c, char *d,
for (i = 5; i < PDIWORDS; i++)
word[i] = "\000";

eat1 = plugin_emit_print (sess, word);
eat2 = plugin_emit_print_attrs (sess, word, timestamp);

if (eat1 || eat2)
if (plugin_emit_print (sess, word, timestamp))
return;

/* If a plugin's callback executes "/close", 'sess' may be invalid */
Expand Down Expand Up @@ -2150,6 +2173,12 @@ text_emit (int index, session *sess, char *a, char *b, char *c, char *d,
if (sess->alert_tray == SET_ON)
fe_tray_set_icon (FE_ICON_MESSAGE);
break;

/* ===Nick change message=== */
case XP_TE_CHANGENICK:
if (prefs.hex_irc_hide_nickchange)
return;
break;
}

sound_play_event (index);
Expand Down
2 changes: 1 addition & 1 deletion src/common/textevents.in
Expand Up @@ -494,7 +494,7 @@ Join
XP_TE_JOIN
pevt_join_help
%C23*$t$1 ($3%C23) has joined
3
4

Keyword
XP_TE_KEYWORD
Expand Down
54 changes: 0 additions & 54 deletions src/common/thread.c

This file was deleted.

36 changes: 0 additions & 36 deletions src/common/thread.h

This file was deleted.

104 changes: 50 additions & 54 deletions src/common/url.c
Expand Up @@ -35,6 +35,7 @@ GTree *url_btree = NULL;
static gboolean regex_match (const GRegex *re, const char *word,
int *start, int *end);
static const GRegex *re_url (void);
static const GRegex *re_url_no_scheme (void);
static const GRegex *re_host (void);
static const GRegex *re_host6 (void);
static const GRegex *re_email (void);
Expand Down Expand Up @@ -208,11 +209,11 @@ url_check_word (const char *word)
} 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 },
{ match_nick, WORD_NICK },
{ NULL, 0}
};
int i;
Expand Down Expand Up @@ -266,11 +267,23 @@ match_channel (const char *word, int *start, int *end)
{
const server *serv = current_sess->server;
const char *chan_prefixes = serv ? serv->chantypes : CHANPRE;
const char *nick_prefixes = serv ? serv->nick_prefixes : NICKPRE;

if (!regex_match (re_channel (), word, start, end))
return FALSE;

return strchr (chan_prefixes, word[*start]) != NULL;
/* Check for +#channel (for example whois output) */
if (strchr (nick_prefixes, word[*start]) != NULL
&& strchr (chan_prefixes, word[*start + 1]) != NULL)
{
(*start)++;
return TRUE;
}
/* Or just #channel */
else if (strchr (chan_prefixes, word[*start]) != NULL)
return TRUE;

return FALSE;
}

static gboolean
Expand All @@ -282,7 +295,10 @@ match_email (const char *word, int *start, int *end)
static gboolean
match_url (const char *word, int *start, int *end)
{
return regex_match (re_url (), word, start, end);
if (regex_match (re_url (), word, start, end))
return TRUE;

return regex_match (re_url_no_scheme (), word, start, end);
}

static gboolean
Expand Down Expand Up @@ -360,8 +376,7 @@ url_check_line (char *buf, int len)
g_match_info_fetch_pos(gmi, 0, &start, &end);
while (end > start && (po[end - 1] == '\r' || po[end - 1] == '\n'))
end--;
if (g_strstr_len (po + start, end - start, "://"))
url_add(po + start, end - start);
url_add(po + start, end - start);
g_match_info_next(gmi, NULL);
}
g_match_info_free(gmi);
Expand Down Expand Up @@ -413,14 +428,14 @@ regex_match (const GRegex *re, const char *word, int *start, int *end)
#define PORT "(:[1-9][0-9]{0,4})"
#define OPT_PORT "(" PORT ")?"

GRegex *
static GRegex *
make_re (char *grist)
{
GRegex *ret;
GError *err = NULL;

ret = g_regex_new (grist, G_REGEX_CASELESS | G_REGEX_OPTIMIZE, 0, &err);
g_free (grist);

return ret;
}

Expand All @@ -430,34 +445,22 @@ static const GRegex *
re_host (void)
{
static GRegex *host_ret;
char *grist;

if (host_ret) return host_ret;

grist = g_strdup (
"("
"(" HOST_URL PORT ")|(" HOST ")"
")"
);
host_ret = make_re (grist);
host_ret = make_re ("(" "(" HOST_URL PORT ")|(" HOST ")" ")");

return host_ret;
}

static const GRegex *
re_host6 (void)
{
static GRegex *host6_ret;
char *grist;

if (host6_ret) return host6_ret;

grist = g_strdup (
"("
"(" IPV6ADDR ")|(" "\\[" IPV6ADDR "\\]" PORT ")"
")"
);

host6_ret = make_re (grist);
host6_ret = make_re ("(" "(" IPV6ADDR ")|(" "\\[" IPV6ADDR "\\]" PORT ")" ")");

return host6_ret;
}
Expand Down Expand Up @@ -539,6 +542,18 @@ struct
{ NULL, "", 0}
};

static const GRegex *
re_url_no_scheme (void)
{
static GRegex *url_ret = NULL;

if (url_ret) return url_ret;

url_ret = make_re ("(" HOST_URL OPT_PORT "/" "(" PATH ")?" ")");

return url_ret;
}

static const GRegex *
re_url (void)
{
Expand All @@ -551,12 +566,12 @@ re_url (void)

grist_gstr = g_string_new (NULL);

/* Add regex "host/path", representing a "schemeless" url */
g_string_append (grist_gstr, "(" HOST_URL OPT_PORT "/" "(" PATH ")?" ")");

for (i = 0; uri[i].scheme; i++)
{
g_string_append (grist_gstr, "|(");
if (i)
g_string_append (grist_gstr, "|");

g_string_append (grist_gstr, "(");
g_string_append_printf (grist_gstr, "%s:", uri[i].scheme);

if (uri[i].flags & URI_AUTHORITY)
Expand Down Expand Up @@ -589,6 +604,7 @@ re_url (void)
grist = g_string_free (grist_gstr, FALSE);

url_ret = make_re (grist);
g_free (grist);

return url_ret;
}
Expand All @@ -600,16 +616,11 @@ static const GRegex *
re_email (void)
{
static GRegex *email_ret;
char *grist;

if (email_ret) return email_ret;

grist = g_strdup (
"("
EMAIL
")"
);
email_ret = make_re (grist);
email_ret = make_re ("(" EMAIL ")");

return email_ret;
}

Expand All @@ -636,16 +647,11 @@ static const GRegex *
re_nick (void)
{
static GRegex *nick_ret;
char *grist;

if (nick_ret) return nick_ret;

grist = g_strdup (
"("
NICK
")"
);
nick_ret = make_re (grist);
nick_ret = make_re ("(" NICK ")");

return nick_ret;
}

Expand All @@ -656,16 +662,11 @@ static const GRegex *
re_channel (void)
{
static GRegex *channel_ret;
char *grist;

if (channel_ret) return channel_ret;

grist = g_strdup (
"("
CHANNEL
")"
);
channel_ret = make_re (grist);
channel_ret = make_re ("(" CHANNEL ")");

return channel_ret;
}

Expand All @@ -682,15 +683,10 @@ static const GRegex *
re_path (void)
{
static GRegex *path_ret;
char *grist;

if (path_ret) return path_ret;

grist = g_strdup (
"("
FS_PATH
")"
);
path_ret = make_re (grist);
path_ret = make_re ("(" FS_PATH ")");

return path_ret;
}
10 changes: 5 additions & 5 deletions src/common/url.h
Expand Up @@ -23,11 +23,11 @@
extern void *url_tree;

#define WORD_URL 1
#define WORD_NICK 2
#define WORD_CHANNEL 3
#define WORD_HOST 4
#define WORD_HOST6 5
#define WORD_EMAIL 6
#define WORD_CHANNEL 2
#define WORD_HOST 3
#define WORD_HOST6 4
#define WORD_EMAIL 5
#define WORD_NICK 6
/* anything >0 will be displayed as a link by gtk_xtext_motion_notify() */
#define WORD_DIALOG -1
#define WORD_PATH -2
Expand Down
21 changes: 12 additions & 9 deletions src/common/userlist.c
Expand Up @@ -139,30 +139,33 @@ userlist_add_hostname (struct session *sess, char *nick, char *hostname,
char *realname, char *servername, char *account, unsigned int away)
{
struct User *user;
gboolean do_rehash = FALSE;

user = userlist_find (sess, nick);
if (user)
{
if (!user->hostname && hostname)
{
if (prefs.hex_gui_ulist_show_hosts)
do_rehash = TRUE;
user->hostname = strdup (hostname);
if (!user->realname && realname)
}
if (!user->realname && realname && *realname)
user->realname = strdup (realname);
if (!user->servername && servername)
user->servername = strdup (servername);
if (!user->account && account && strcmp (account, "0") != 0)
user->account = strdup (account);

if (away != 0xff)
{
if (prefs.hex_gui_ulist_show_hosts || user->away != away)
{
user->away = away;
fe_userlist_rehash (sess, user);
}
if (user->away != away)
do_rehash = TRUE;
user->away = away;
}

fe_userlist_update (sess, user);
if (do_rehash)
fe_userlist_rehash (sess, user);

return 1;
}
Expand Down Expand Up @@ -413,9 +416,9 @@ userlist_add (struct session *sess, char *name, char *hostname,
/* extended join info */
if (sess->server->have_extjoin)
{
if (account && strcmp (account, "*") != 0)
if (account && *account)
user->account = strdup (account);
if (realname)
if (realname && *realname)
user->realname = strdup (realname);
}

Expand Down
338 changes: 180 additions & 158 deletions src/common/util.c

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions src/common/util.h
Expand Up @@ -65,7 +65,6 @@ int waitline (int sok, char *buf, int bufsize, int);
#ifdef WIN32
int waitline2 (GIOChannel *source, char *buf, int bufsize);
int get_cpu_arch (void);
int find_font (const char *fontname);
#else
#define waitline2(source,buf,size) waitline(serv->childread,buf,size,0)
#endif
Expand All @@ -78,10 +77,10 @@ void safe_strcpy (char *dest, const char *src, int bytes_left);
void canonalize_key (char *key);
int portable_mode ();
int unity_mode ();
GSList *get_subdirs (const char *path);
char *encode_sasl_pass_plain (char *user, char *pass);
char *encode_sasl_pass_blowfish (char *user, char *pass, char *data);
char *encode_sasl_pass_aes (char *user, char *pass, char *data);
char *challengeauth_response (char *username, char *password, char *challenge);

size_t strftime_validated (char *dest, size_t destsize, const char *format, const struct tm *time);
size_t strftime_utf8 (char *dest, size_t destsize, const char *format, time_t time);
#endif
27 changes: 15 additions & 12 deletions src/fe-gtk/Makefile.am
Expand Up @@ -9,25 +9,28 @@ hexchat_LDADD = ../common/libhexchatcommon.a $(GUI_LIBS)
EXTRA_DIST = \
ascii.h banlist.h chanlist.h chanview.h chanview-tabs.c \
chanview-tree.c custom-list.h editlist.h fe-gtk.h fkeys.h gtkutil.h joind.h \
maingui.h menu.h mmx_cmod.S mmx_cmod.h notifygui.h palette.h pixmaps.h \
plugin-tray.h plugingui.c plugingui.h rawlog.h search.h sexy-iso-codes.h \
sexy-spell-entry.h sexy-marshal.h textgui.h urlgrab.h userlistgui.h xtext.h
maingui.h menu.h notifygui.h palette.h pixmaps.h \
plugin-tray.h plugingui.c plugingui.h rawlog.h sexy-iso-codes.h \
sexy-spell-entry.h textgui.h urlgrab.h userlistgui.h xtext.h \
../../data/hexchat.gresource.xml

if USE_MMX
mmx_cmod_S = mmx_cmod.S
endif
BUILT_SOURCES = resources.c

CLEANFILES = $(BUILT_SOURCES)

if DO_PLUGIN
plugingui_c = plugingui.c
endif

if USE_LIBSEXY
sexy_spell = \
sexy-iso-codes.c sexy-marshal.c sexy-spell-entry.c
if HAVE_ISO_CODES
iso_codes_c = sexy-iso-codes.c
endif

hexchat_SOURCES = ascii.c banlist.c chanlist.c chanview.c custom-list.c \
dccgui.c editlist.c fe-gtk.c fkeys.c gtkutil.c ignoregui.c joind.c menu.c \
maingui.c $(mmx_cmod_S) notifygui.c palette.c pixmaps.c plugin-tray.c $(plugingui_c) \
rawlog.c search.c servlistgui.c setup.c $(sexy_spell) textgui.c \
urlgrab.c userlistgui.c xtext.c
maingui.c notifygui.c palette.c pixmaps.c plugin-tray.c $(plugingui_c) \
rawlog.c resources.c servlistgui.c setup.c $(iso_codes_c) \
sexy-spell-entry.c textgui.c urlgrab.c userlistgui.c xtext.c

resources.c: ../../data/hexchat.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=../../data --generate-dependencies ../../data/hexchat.gresource.xml)
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=../../data --generate-source $<
13 changes: 9 additions & 4 deletions src/fe-gtk/banlist.c
Expand Up @@ -237,9 +237,14 @@ static void
banlist_sensitize (banlist_info *banl)
{
int checkable, i;
gboolean is_op = FALSE;

/* FIXME: More access levels than these can unban */
if (banl->sess->me->op || banl->sess->me->hop)
is_op = TRUE;

/* CHECKBOXES -- */
checkable = banl->sess->me->op? banl->writeable: banl->readable;
checkable = is_op? banl->writeable: banl->readable;
for (i = 0; i < MODE_CT; i++)
{
if (banl->checkboxes[i] == NULL)
Expand All @@ -258,7 +263,7 @@ banlist_sensitize (banlist_info *banl)
}

/* BUTTONS --- */
if (banl->sess->me->op == 0 || banl->line_ct == 0)
if (!is_op || banl->line_ct == 0)
{
/* If user is not op or list is empty, buttons should be all greyed */
gtk_widget_set_sensitive (banl->but_clear, FALSE);
Expand Down Expand Up @@ -632,7 +637,7 @@ banlist_toggle (GtkWidget *item, gpointer data)
if (bit) /* Should be gassert() */
{
banl->checked &= ~bit;
banl->checked |= (GTK_TOGGLE_BUTTON (item)->active)? bit: 0;
banl->checked |= (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (item)))? bit: 0;
banlist_do_refresh (banl);
}
}
Expand Down Expand Up @@ -775,7 +780,7 @@ banlist_opengui (struct session *sess)
GtkWidget *table, *vbox, *bbox;
char tbuf[256];

if (sess->type != SESS_CHANNEL)
if (sess->type != SESS_CHANNEL || sess->channel[0] == 0)
{
fe_message (_("You can only open the Ban List window while in a channel tab."), FE_MSG_ERROR);
return;
Expand Down
75 changes: 38 additions & 37 deletions src/fe-gtk/chanlist.c
Expand Up @@ -75,16 +75,14 @@ chanlist_match (server *serv, const char *str)
switch (serv->gui->chanlist_search_type)
{
case 1:
return match (GTK_ENTRY (serv->gui->chanlist_wild)->text, str);
#ifndef WIN32
return match (gtk_entry_get_text (GTK_ENTRY (serv->gui->chanlist_wild)), str);
case 2:
if (!serv->gui->have_regex)
return 0;
/* regex returns 0 if it's a match: */
return !regexec (&serv->gui->chanlist_match_regex, str, 1, NULL, REG_NOTBOL);
#endif

return g_regex_match (serv->gui->chanlist_match_regex, str, 0, NULL);
default: /* case 0: */
return nocasestrstr (str, GTK_ENTRY (serv->gui->chanlist_wild)->text) ? 1 : 0;
return nocasestrstr (str, gtk_entry_get_text (GTK_ENTRY (serv->gui->chanlist_wild))) ? 1 : 0;
}
}

Expand Down Expand Up @@ -227,7 +225,7 @@ chanlist_place_row_in_gui (server *serv, chanlistrow *next_row, gboolean force)
return;
}

if (GTK_ENTRY (serv->gui->chanlist_wild)->text[0])
if (gtk_entry_get_text (GTK_ENTRY (serv->gui->chanlist_wild))[0])
{
/* Check what the user wants to match. If both buttons or _neither_
* button is checked, look for match in both by default.
Expand Down Expand Up @@ -406,30 +404,32 @@ chanlist_search_pressed (GtkButton * button, server *serv)
static void
chanlist_find_cb (GtkWidget * wid, server *serv)
{
#ifndef WIN32
const char *pattern = gtk_entry_get_text (GTK_ENTRY (wid));

/* recompile the regular expression. */
if (serv->gui->have_regex)
{
serv->gui->have_regex = 0;
regfree (&serv->gui->chanlist_match_regex);
g_regex_unref (serv->gui->chanlist_match_regex);
}

if (regcomp (&serv->gui->chanlist_match_regex, GTK_ENTRY (wid)->text,
REG_ICASE | REG_EXTENDED | REG_NOSUB) == 0)
serv->gui->chanlist_match_regex = g_regex_new (pattern, G_REGEX_CASELESS | G_REGEX_EXTENDED,
G_REGEX_MATCH_NOTBOL, NULL);

if (serv->gui->chanlist_match_regex)
serv->gui->have_regex = 1;
#endif
}

static void
chanlist_match_channel_button_toggled (GtkWidget * wid, server *serv)
{
serv->gui->chanlist_match_wants_channel = GTK_TOGGLE_BUTTON (wid)->active;
serv->gui->chanlist_match_wants_channel = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (wid));
}

static void
chanlist_match_topic_button_toggled (GtkWidget * wid, server *serv)
{
serv->gui->chanlist_match_wants_topic = GTK_TOGGLE_BUTTON (wid)->active;
serv->gui->chanlist_match_wants_topic = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (wid));
}

static char *
Expand Down Expand Up @@ -519,7 +519,7 @@ chanlist_save (GtkWidget * wid, server *serv)
static gboolean
chanlist_flash (server *serv)
{
if (serv->gui->chanlist_refresh->state != GTK_STATE_ACTIVE)
if (gtk_widget_get_state (serv->gui->chanlist_refresh) != GTK_STATE_ACTIVE)
gtk_widget_set_state (serv->gui->chanlist_refresh, GTK_STATE_ACTIVE);
else
gtk_widget_set_state (serv->gui->chanlist_refresh, GTK_STATE_PRELIGHT);
Expand Down Expand Up @@ -615,7 +615,7 @@ chanlist_button_cb (GtkTreeView *tree, GdkEventButton *event, server *serv)

menu = gtk_menu_new ();
if (event->window)
gtk_menu_set_screen (GTK_MENU (menu), gdk_drawable_get_screen (event->window));
gtk_menu_set_screen (GTK_MENU (menu), gdk_window_get_screen (event->window));
g_object_ref (menu);
g_object_ref_sink (menu);
g_object_unref (menu);
Expand Down Expand Up @@ -655,13 +655,11 @@ chanlist_destroy_widget (GtkWidget *wid, server *serv)
serv->gui->chanlist_tag = 0;
}

#ifndef WIN32
if (serv->gui->have_regex)
{
regfree (&serv->gui->chanlist_match_regex);
g_regex_unref (serv->gui->chanlist_match_regex);
serv->gui->have_regex = 0;
}
#endif
}

static void
Expand All @@ -688,11 +686,16 @@ chanlist_add_column (GtkWidget *tree, int textcol, int size, char *title, gboole
col = gtk_tree_view_get_column (GTK_TREE_VIEW (tree), textcol);
gtk_tree_view_column_set_sort_column_id (col, textcol);
gtk_tree_view_column_set_resizable (col, TRUE);
if (textcol != COL_TOPIC)
if (textcol == COL_CHANNEL)
{
gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_FIXED);
gtk_tree_view_column_set_fixed_width (col, size);
}
else if (textcol == COL_USERS)
{
gtk_tree_view_column_set_sizing (col, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
gtk_tree_view_column_set_resizable (col, FALSE);
}
}

static void
Expand Down Expand Up @@ -762,7 +765,7 @@ chanlist_opengui (server *serv, int do_refresh)

store = (GtkListStore *) custom_list_new();
view = gtkutil_treeview_new (vbox, GTK_TREE_MODEL (store), NULL, -1);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (view->parent),
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (gtk_widget_get_parent (view)),
GTK_SHADOW_IN);
serv->gui->chanlist_list = view;

Expand Down Expand Up @@ -870,16 +873,15 @@ chanlist_opengui (server *serv, int do_refresh)

wid = gtk_check_button_new_with_label (_("Channel name"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wid), TRUE);
gtk_signal_connect (GTK_OBJECT (wid), "toggled",
GTK_SIGNAL_FUNC
(chanlist_match_channel_button_toggled), serv);
g_signal_connect (G_OBJECT (wid), "toggled",
G_CALLBACK(chanlist_match_channel_button_toggled), serv);
gtk_box_pack_start (GTK_BOX (hbox), wid, 0, 0, 0);
gtk_widget_show (wid);

wid = gtk_check_button_new_with_label (_("Topic"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wid), TRUE);
gtk_signal_connect (GTK_OBJECT (wid), "toggled",
GTK_SIGNAL_FUNC (chanlist_match_topic_button_toggled),
g_signal_connect (G_OBJECT (wid), "toggled",
G_CALLBACK (chanlist_match_topic_button_toggled),
serv);
gtk_box_pack_start (GTK_BOX (hbox), wid, 0, 0, 0);
gtk_widget_show (wid);
Expand All @@ -895,12 +897,10 @@ chanlist_opengui (server *serv, int do_refresh)
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (wid);

wid = gtk_combo_box_new_text ();
gtk_combo_box_append_text (GTK_COMBO_BOX (wid), _("Simple Search"));
gtk_combo_box_append_text (GTK_COMBO_BOX (wid), _("Pattern Match (Wildcards)"));
#ifndef WIN32
gtk_combo_box_append_text (GTK_COMBO_BOX (wid), _("Regular Expression"));
#endif
wid = gtk_combo_box_text_new ();
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (wid), _("Simple Search"));
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (wid), _("Pattern Match (Wildcards)"));
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (wid), _("Regular Expression"));
gtk_combo_box_set_active (GTK_COMBO_BOX (wid), serv->gui->chanlist_search_type);
gtk_table_attach (GTK_TABLE (table), wid, 1, 2, 1, 2,
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
Expand All @@ -916,11 +916,12 @@ chanlist_opengui (server *serv, int do_refresh)
GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (wid);

wid = gtk_entry_new_with_max_length (255);
gtk_signal_connect (GTK_OBJECT (wid), "changed",
GTK_SIGNAL_FUNC (chanlist_find_cb), serv);
gtk_signal_connect (GTK_OBJECT (wid), "activate",
GTK_SIGNAL_FUNC (chanlist_search_pressed),
wid = gtk_entry_new ();
gtk_entry_set_max_length (GTK_ENTRY(wid), 255);
g_signal_connect (G_OBJECT (wid), "changed",
G_CALLBACK (chanlist_find_cb), serv);
g_signal_connect (G_OBJECT (wid), "activate",
G_CALLBACK (chanlist_search_pressed),
(gpointer) serv);
gtk_table_attach (GTK_TABLE (table), wid, 1, 2, 0, 1,
GTK_EXPAND | GTK_FILL, 0, 0, 0);
Expand Down