323 changes: 162 additions & 161 deletions po/fi.po

Large diffs are not rendered by default.

174 changes: 87 additions & 87 deletions po/fr.po

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions po/it.po
Expand Up @@ -6,13 +6,14 @@
# Claudio Arseni <claudio.arseni@gmail.com>, 2013-2014
# Eros Palberti - Fabio Viola : How-Tux Team <admin@how-tux.com>, 2006
# Random_R, 2013
# Random_R, 2013
msgid ""
msgstr ""
"Project-Id-Version: HexChat\n"
"Report-Msgid-Bugs-To: www.hexchat.org\n"
"POT-Creation-Date: 2014-05-14 13:20-0400\n"
"PO-Revision-Date: 2014-05-30 13:32+0000\n"
"Last-Translator: Claudio Arseni <claudio.arseni@gmail.com>\n"
"PO-Revision-Date: 2014-09-03 19:07+0000\n"
"Last-Translator: Teodoro Santoni <asbrasbra@gmail.com>\n"
"Language-Team: Italian (http://www.transifex.com/projects/p/hexchat/language/it/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
Expand Down
12 changes: 6 additions & 6 deletions po/ja_JP.po
Expand Up @@ -4,14 +4,14 @@
#
# Translators:
# k725, 2014
# Emmanuel Chanel <emmanuelchanel@gmail.com>, 2013
# Emmanuel Chanel <emmanuelchanel@gmail.com>, 2013-2014
msgid ""
msgstr ""
"Project-Id-Version: HexChat\n"
"Report-Msgid-Bugs-To: www.hexchat.org\n"
"POT-Creation-Date: 2014-05-14 13:20-0400\n"
"PO-Revision-Date: 2014-06-07 16:20+0000\n"
"Last-Translator: k725\n"
"PO-Revision-Date: 2014-11-07 04:47+0000\n"
"Last-Translator: Emmanuel Chanel <emmanuelchanel@gmail.com>\n"
"Language-Team: Japanese (Japan) (http://www.transifex.com/projects/p/hexchat/language/ja_JP/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
Expand Down Expand Up @@ -254,7 +254,7 @@ msgstr "Ping"
#, c-format
msgid ""
"You do not have write access to %s. Nothing from this session can be saved."
msgstr ""
msgstr "%s へのに書き込み許可がありません。このセッションの何も保存されません。"

#: ../src/common/hexchat.c:1139
msgid ""
Expand Down Expand Up @@ -350,7 +350,7 @@ msgstr "不明な引数 '%s' を無視します。"

#: ../src/common/outbound.c:3093 ../src/common/outbound.c:3123
msgid "Quiet is not supported by this server."
msgstr ""
msgstr "Quiet 機能はこのサーバーではサポートしていません。"

#. error
#: ../src/common/outbound.c:3585 ../src/common/outbound.c:3619
Expand Down Expand Up @@ -3207,7 +3207,7 @@ msgstr "ダウンロードリスト(_D)"

#: ../src/fe-gtk/chanlist.c:806
msgid "Save _List..."
msgstr "サーバーリスト(_L)"
msgstr "リストを保存(_L)"

#. =============================================================
#: ../src/fe-gtk/chanlist.c:819
Expand Down
769 changes: 385 additions & 384 deletions po/lt.po

Large diffs are not rendered by default.

308 changes: 154 additions & 154 deletions po/pt.po

Large diffs are not rendered by default.

2,515 changes: 1,258 additions & 1,257 deletions po/pt_BR.po

Large diffs are not rendered by default.

64 changes: 33 additions & 31 deletions po/sv.po
Expand Up @@ -3,14 +3,16 @@
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
# Jakob <jakob@knugen.nu>, 2014
# Jakob <jakob@knugen.nu>, 2012
# Martin Jernberg <bittin@cafe8bitar.se>, 2014
msgid ""
msgstr ""
"Project-Id-Version: HexChat\n"
"Report-Msgid-Bugs-To: www.hexchat.org\n"
"POT-Creation-Date: 2014-05-14 13:20-0400\n"
"PO-Revision-Date: 2014-05-14 17:20+0000\n"
"Last-Translator: TingPing <tingping@tingping.se>\n"
"PO-Revision-Date: 2014-08-22 13:24+0000\n"
"Last-Translator: Martin Jernberg <bittin@cafe8bitar.se>\n"
"Language-Team: Swedish (http://www.transifex.com/projects/p/hexchat/language/sv/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
Expand All @@ -23,7 +25,7 @@ msgid ""
"HexChat is an easy to use yet extensible IRC Client. It allows you to "
"securely join multiple networks and talk to users privately or in channels "
"using a customizable interface. You can even transfer files."
msgstr ""
msgstr "HexChat är en lättanvänd men även utbyggbar IRC klient. Den låter dig säkert ansluta till flera nätverk och prata med användare privat eller i kanaler med ett anpassningsbart utseende. Du kan även överföra filer."

#: ../data/misc/hexchat.appdata.xml.in.h:2
msgid ""
Expand All @@ -33,27 +35,27 @@ msgstr ""

#: ../data/misc/hexchat.desktop.in.h:1
msgid "HexChat"
msgstr ""
msgstr "HexChat"

#: ../data/misc/hexchat.desktop.in.h:2
msgid "IRC Client"
msgstr ""
msgstr "IRC klient"

#: ../data/misc/hexchat.desktop.in.h:3
msgid "Chat with other people online"
msgstr ""
msgstr "Chatta med andra människor online"

#: ../data/misc/hexchat.desktop.in.h:4
msgid "IM;Chat;"
msgstr ""

#: ../data/misc/hexchat.desktop.in.h:5
msgid "Open Safe Mode"
msgstr ""
msgstr "Öppna säkert läge"

#: ../data/misc/htm.desktop.in.h:1
msgid "HexChat Theme Manager"
msgstr ""
msgstr "HexChat temahanterare "

#. 0 means unlimited
#. STRINGS
Expand Down Expand Up @@ -128,15 +130,15 @@ msgstr "_Skicka en fil"

#: ../src/common/hexchat.c:869
msgid "_User Info (WhoIs)"
msgstr "An_vändarinfo (Whois)"
msgstr "_Användarinfo (Whois)"

#: ../src/common/hexchat.c:870
msgid "_Add to Friends List"
msgstr "_Lägg till i vännerlista"
msgstr "_Lägg till i vänlista"

#: ../src/common/hexchat.c:871
msgid "_Ignore"
msgstr ""
msgstr "_Ignorera"

#: ../src/common/hexchat.c:872
msgid "O_perator Actions"
Expand Down Expand Up @@ -212,7 +214,7 @@ msgstr "Ta bort op"

#: ../src/common/hexchat.c:918
msgid "bye"
msgstr "hejdå"
msgstr "hej då"

#: ../src/common/hexchat.c:919
#, c-format
Expand Down Expand Up @@ -253,7 +255,7 @@ msgstr "Ping"
#, c-format
msgid ""
"You do not have write access to %s. Nothing from this session can be saved."
msgstr ""
msgstr "Du har inte skrivrättigheter till %s. Ingenting från den här sessionen kan bli sparat"

#: ../src/common/hexchat.c:1139
msgid ""
Expand Down Expand Up @@ -2444,7 +2446,7 @@ msgstr "Jordanien"

#: ../src/common/util.c:1112
msgid "Company Jobs"
msgstr ""
msgstr "Företags jobb"

#: ../src/common/util.c:1113
msgid "Japan"
Expand Down Expand Up @@ -2552,7 +2554,7 @@ msgstr "Moldavien"

#: ../src/common/util.c:1139
msgid "Montenegro"
msgstr ""
msgstr "Montenegro"

#: ../src/common/util.c:1140
msgid "United States Medical"
Expand Down Expand Up @@ -2620,7 +2622,7 @@ msgstr "Mauritius"

#: ../src/common/util.c:1156
msgid "Museums"
msgstr ""
msgstr "Museum"

#: ../src/common/util.c:1157
msgid "Maldives"
Expand Down Expand Up @@ -2784,7 +2786,7 @@ msgstr "Gammaldags ARPAnet"

#: ../src/common/util.c:1197
msgid "Serbia"
msgstr ""
msgstr "Serbien"

#: ../src/common/util.c:1198
msgid "Russian Federation"
Expand Down Expand Up @@ -2856,7 +2858,7 @@ msgstr "Surinam"

#: ../src/common/util.c:1215
msgid "South Sudan"
msgstr ""
msgstr "Syd Sudan"

#: ../src/common/util.c:1216
msgid "Sao Tome and Principe"
Expand Down Expand Up @@ -3086,7 +3088,7 @@ msgstr ""

#: ../src/fe-gtk/banlist.c:67
msgid "Invites"
msgstr ""
msgstr "Inbjudningar"

#: ../src/fe-gtk/banlist.c:68 ../src/fe-gtk/ignoregui.c:164
msgid "Invite"
Expand Down Expand Up @@ -3721,7 +3723,7 @@ msgstr "<u>Understruken</u>"

#: ../src/fe-gtk/maingui.c:1475
msgid "<i>Italic</i>"
msgstr ""
msgstr "<i>kursiv</i>"

#: ../src/fe-gtk/maingui.c:1476
msgid "Normal"
Expand Down Expand Up @@ -3835,7 +3837,7 @@ msgstr "Ange nytt smeknamn:"

#: ../src/fe-gtk/maingui.c:2832
msgid "No results found."
msgstr ""
msgstr "Inga resultat funna."

#: ../src/fe-gtk/maingui.c:2928
msgid "Search hit end or not found."
Expand Down Expand Up @@ -3893,7 +3895,7 @@ msgstr "Användare:"

#: ../src/fe-gtk/menu.c:637
msgid "Account:"
msgstr ""
msgstr "Konto:"

#: ../src/fe-gtk/menu.c:647
msgid "Country:"
Expand Down Expand Up @@ -4114,7 +4116,7 @@ msgstr "XChat: CTCP-svar"

#: ../src/fe-gtk/menu.c:1743
msgid "He_xChat"
msgstr ""
msgstr "He_xChat"

#: ../src/fe-gtk/menu.c:1744
msgid "Network Li_st..."
Expand Down Expand Up @@ -4199,7 +4201,7 @@ msgstr "Diagram"

#: ../src/fe-gtk/menu.c:1785
msgid "_Fullscreen"
msgstr ""
msgstr "_Fullskärm"

#: ../src/fe-gtk/menu.c:1787
msgid "_Server"
Expand Down Expand Up @@ -5957,7 +5959,7 @@ msgstr "Gränssnitt"

#: ../src/fe-gtk/setup.c:1807
msgid "Appearance"
msgstr ""
msgstr "Utseende "

#: ../src/fe-gtk/setup.c:1808
msgid "Input box"
Expand All @@ -5981,7 +5983,7 @@ msgstr "Chattande"

#: ../src/fe-gtk/setup.c:1816
msgid "Sounds"
msgstr ""
msgstr "Ljud"

#: ../src/fe-gtk/setup.c:1818
msgid "Advanced"
Expand Down Expand Up @@ -6023,15 +6025,15 @@ msgstr "*VARNING*\nAtt automatiskt acceptera DCC till din\nhemkatalog kan vara f

#: ../src/fe-gtk/setup.c:2198
msgid ": Preferences"
msgstr "XChat: Inställningar"
msgstr ": Inställningar"

#: ../src/fe-gtk/sexy-spell-entry.c:545
msgid "<i>(no suggestions)</i>"
msgstr ""

#: ../src/fe-gtk/sexy-spell-entry.c:559
msgid "More..."
msgstr ""
msgstr "Mer..."

#. + Add to Dictionary
#: ../src/fe-gtk/sexy-spell-entry.c:631
Expand All @@ -6042,11 +6044,11 @@ msgstr ""
#. - Ignore All
#: ../src/fe-gtk/sexy-spell-entry.c:676
msgid "Ignore All"
msgstr ""
msgstr "Ignorera alla"

#: ../src/fe-gtk/sexy-spell-entry.c:711
msgid "Spelling Suggestions"
msgstr ""
msgstr "Stavningsförslag"

#: ../src/fe-gtk/sexy-spell-entry.c:1272
#, c-format
Expand Down Expand Up @@ -6084,7 +6086,7 @@ msgstr "Testa allt"

#: ../src/fe-gtk/textgui.c:485
msgid "OK"
msgstr ""
msgstr "OK"

#: ../src/fe-gtk/urlgrab.c:198
msgid ": URL Grabber"
Expand Down
80 changes: 40 additions & 40 deletions po/tr.po
Expand Up @@ -14,8 +14,8 @@ msgstr ""
"Project-Id-Version: HexChat\n"
"Report-Msgid-Bugs-To: www.hexchat.org\n"
"POT-Creation-Date: 2014-05-14 13:20-0400\n"
"PO-Revision-Date: 2014-07-14 10:59+0000\n"
"Last-Translator: Atilla Öntaş <tarakbumba@gmail.com>\n"
"PO-Revision-Date: 2014-10-06 16:54+0000\n"
"Last-Translator: Demiray Muhterem <mdemiray@msn.com>\n"
"Language-Team: Turkish (http://www.transifex.com/projects/p/hexchat/language/tr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
Expand All @@ -38,27 +38,27 @@ msgstr ""

#: ../data/misc/hexchat.desktop.in.h:1
msgid "HexChat"
msgstr ""
msgstr "HexChat"

#: ../data/misc/hexchat.desktop.in.h:2
msgid "IRC Client"
msgstr ""
msgstr "IRC Client"

#: ../data/misc/hexchat.desktop.in.h:3
msgid "Chat with other people online"
msgstr ""
msgstr "İnsanlar ile çevrimiçi sohbet"

#: ../data/misc/hexchat.desktop.in.h:4
msgid "IM;Chat;"
msgstr ""
msgstr "IM;Chat;"

#: ../data/misc/hexchat.desktop.in.h:5
msgid "Open Safe Mode"
msgstr ""
msgstr "Güvenli Modda Aç"

#: ../data/misc/htm.desktop.in.h:1
msgid "HexChat Theme Manager"
msgstr ""
msgstr "Hexchat Tema Yöneticisi"

#. 0 means unlimited
#. STRINGS
Expand Down Expand Up @@ -1407,7 +1407,7 @@ msgstr "Katılan kişinin adı"

#: ../src/common/text.c:1033
msgid "The channel being joined"
msgstr ""
msgstr "Kanala girildi."

#: ../src/common/text.c:1034 ../src/common/text.c:1097
#: ../src/common/text.c:1148
Expand All @@ -1416,7 +1416,7 @@ msgstr "Kişinin bilgisayarı"

#: ../src/common/text.c:1035
msgid "The account of the person"
msgstr ""
msgstr "Kişinin hesabı"

#: ../src/common/text.c:1039 ../src/common/text.c:1046
#: ../src/common/text.c:1053 ../src/common/text.c:1265
Expand Down Expand Up @@ -1470,7 +1470,7 @@ msgstr "Sunucu Adı"

#: ../src/common/text.c:1060
msgid "Acknowledged Capabilities"
msgstr ""
msgstr "Sunucu Özellikleri"

#: ../src/common/text.c:1065
msgid "Server Capabilities"
Expand Down Expand Up @@ -1578,99 +1578,99 @@ msgstr ""

#: ../src/common/text.c:1171
msgid "The nick of the person who set the key"
msgstr ""
msgstr "Kilidi ayarlayan kişinin rumuzu"

#: ../src/common/text.c:1172
msgid "The key"
msgstr "Anahtar"

#: ../src/common/text.c:1176
msgid "The nick of the person who set the limit"
msgstr ""
msgstr "Limiti ayarlayan kişinin rumuzu"

#: ../src/common/text.c:1177
msgid "The limit"
msgstr "Sınır"

#: ../src/common/text.c:1181
msgid "The nick of the person who did the op'ing"
msgstr ""
msgstr "Op veren kişinin rumuzu"

#: ../src/common/text.c:1182
msgid "The nick of the person who has been op'ed"
msgstr ""
msgstr "Op olan kişinin rumuzu"

#: ../src/common/text.c:1186
msgid "The nick of the person who has been halfop'ed"
msgstr ""
msgstr "Yarım Op olan kişinin rumuzu"

#: ../src/common/text.c:1187
msgid "The nick of the person who did the halfop'ing"
msgstr ""
msgstr "Yarım Op veren kişinin rumuzu"

#: ../src/common/text.c:1191
msgid "The nick of the person who did the voice'ing"
msgstr ""
msgstr "Konuşma izni veren kişinin rumuzu"

#: ../src/common/text.c:1192
msgid "The nick of the person who has been voice'ed"
msgstr ""
msgstr "Konuşma izni alan kişinin rumuzu"

#: ../src/common/text.c:1196
msgid "The nick of the person who did the banning"
msgstr ""
msgstr "Banlayan kişinin rumuzu"

#: ../src/common/text.c:1197 ../src/common/text.c:1229
msgid "The ban mask"
msgstr "Yasak maskesi"

#: ../src/common/text.c:1201
msgid "The nick of the person who did the quieting"
msgstr ""
msgstr "Konuşma iznini alan kişinin rumuzu"

#: ../src/common/text.c:1202 ../src/common/text.c:1234
msgid "The quiet mask"
msgstr "Sessiz maske"

#: ../src/common/text.c:1206
msgid "The nick who removed the key"
msgstr ""
msgstr "Kilidi kaldıranın rumuzu"

#: ../src/common/text.c:1210
msgid "The nick who removed the limit"
msgstr ""
msgstr "Limiti kaldıranın rumuzu"

#: ../src/common/text.c:1214
msgid "The nick of the person of did the deop'ing"
msgstr ""
msgstr "Op alan kişinin rumuzu"

#: ../src/common/text.c:1215
msgid "The nick of the person who has been deop'ed"
msgstr ""
msgstr "Op'u alınan kişinin rumuzu"

#: ../src/common/text.c:1218
msgid "The nick of the person of did the dehalfop'ing"
msgstr ""
msgstr "Yarım Op'u alan kişinin rumuzu"

#: ../src/common/text.c:1219
msgid "The nick of the person who has been dehalfop'ed"
msgstr ""
msgstr "Yarım Op'u elinden alınan kişinin rumuzu"

#: ../src/common/text.c:1223
msgid "The nick of the person of did the devoice'ing"
msgstr ""
msgstr "Konuşma iznini alan kişini rumuzu"

#: ../src/common/text.c:1224
msgid "The nick of the person who has been devoice'ed"
msgstr ""
msgstr "Konuşma izni alınan kişinin rumuzu"

#: ../src/common/text.c:1228
msgid "The nick of the person of did the unban'ing"
msgstr ""
msgstr "Yasağı kaldıran kişinin rumuzu"

#: ../src/common/text.c:1233
msgid "The nick of the person of did the unquiet'ing"
msgstr ""
msgstr "Konuşma yasağını kaldıran kişinin rumuzu"

#: ../src/common/text.c:1238
msgid "The nick of the person who did the exempt"
Expand All @@ -1686,31 +1686,31 @@ msgstr "Kişinin kullanıcı adı serbest bırakıldı."

#: ../src/common/text.c:1248
msgid "The nick of the person who did the invite"
msgstr ""
msgstr "Davet eden kişinin rumuzu"

#: ../src/common/text.c:1249 ../src/common/text.c:1254
msgid "The invite mask"
msgstr "Davet maskesi"

#: ../src/common/text.c:1253
msgid "The nick of the person removed the invite"
msgstr ""
msgstr "Daveti kaldıran kişinin rumuzu"

#: ../src/common/text.c:1258
msgid "The nick of the person setting the mode"
msgstr ""
msgstr "Mod ayarlarını yapan kişinin rumuzu"

#: ../src/common/text.c:1259
msgid "The mode's sign (+/-)"
msgstr ""
msgstr "Mod'lar imza (+/-)"

#: ../src/common/text.c:1260
msgid "The mode letter"
msgstr "Mektup Modu"

#: ../src/common/text.c:1261
msgid "The channel it's being set on"
msgstr ""
msgstr "Bu şu anda kanal ayarlanıyor"

#: ../src/common/text.c:1268
msgid "Full name"
Expand Down Expand Up @@ -2893,7 +2893,7 @@ msgstr "Chad"

#: ../src/common/util.c:1223
msgid "Internet Communication Services"
msgstr ""
msgstr "İnternet İletişim Hizmetleri"

#: ../src/common/util.c:1224
msgid "French Southern Territories"
Expand Down Expand Up @@ -2937,7 +2937,7 @@ msgstr "Türkiye"

#: ../src/common/util.c:1235
msgid "Travel and Tourism"
msgstr ""
msgstr "Seyahat ve Turizm"

#: ../src/common/util.c:1236
msgid "Trinidad and Tobago"
Expand Down Expand Up @@ -3017,7 +3017,7 @@ msgstr "Samoa"

#: ../src/common/util.c:1255
msgid "Adult Entertainment"
msgstr ""
msgstr "Yetişkin Eğlence"

#: ../src/common/util.c:1256
msgid "Yemen"
Expand Down Expand Up @@ -3053,7 +3053,7 @@ msgstr ""

#: ../src/common/dbus/dbus-client.c:114 ../src/common/dbus/dbus-client.c:128
msgid "Failed to complete Command"
msgstr ""
msgstr "Komut başarısız"

#: ../src/common/dbus/dbus-plugin.c:30
msgid "remote access"
Expand Down
12 changes: 6 additions & 6 deletions po/zh_CN.po
Expand Up @@ -22,8 +22,8 @@ msgstr ""
"Project-Id-Version: HexChat\n"
"Report-Msgid-Bugs-To: www.hexchat.org\n"
"POT-Creation-Date: 2014-05-14 13:20-0400\n"
"PO-Revision-Date: 2014-07-16 13:16+0000\n"
"Last-Translator: bababababanana1\n"
"PO-Revision-Date: 2014-11-02 15:21+0000\n"
"Last-Translator: Michael Jay Tong <michaeljayt@gmail.com>\n"
"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/hexchat/language/zh_CN/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
Expand Down Expand Up @@ -296,7 +296,7 @@ msgstr "您正受到来自 %s 的洗屏攻击,忽略 %s\n"
#: ../src/common/ignore.c:410
#, c-format
msgid "You are being MSG flooded from %s, setting gui_autoopen_dialog OFF.\n"
msgstr "您正受到来自 %s 的 MSG 洪水攻击,自动打开图形化对话框参数gui_autoopen_dialog 将设置为关闭。\n"
msgstr "您正受到来自 %s 的 MSG 洪水攻击,设置图形化自动对话框为关闭。\n"

#: ../src/common/notify.c:558
#, c-format
Expand Down Expand Up @@ -987,7 +987,7 @@ msgstr "%C22*%O$t%C26$1%O 给了 %C18$2%O 发言权"

#: ../src/common/textevents.h:114
msgid "%C23*%O$tConnected. Now logging in."
msgstr "%C23*%O$tC 已连接。正在登录..."
msgstr "%C23*%O$t 已连接。正在登录..."

#: ../src/common/textevents.h:117
msgid "%C23*%O$tConnecting to %C29$1%C (%C23$2:$3%O)"
Expand Down Expand Up @@ -4335,7 +4335,7 @@ msgstr "重置标记线"

#: ../src/fe-gtk/menu.c:1823
msgid "Move to Marker Line"
msgstr "移动至标记线."
msgstr "移动至标记线"

#: ../src/fe-gtk/menu.c:1824
msgid "_Copy Selection"
Expand Down Expand Up @@ -4737,7 +4737,7 @@ msgstr "按字母顺序排练网络列表。使用SHIFT+上下方向键来移动

#: ../src/fe-gtk/servlistgui.c:2168
msgid "_Favor"
msgstr "收藏 (_F)"
msgstr "收藏(_F)"

#: ../src/fe-gtk/servlistgui.c:2169
msgid "Mark or unmark this network as a favorite."
Expand Down
9 changes: 3 additions & 6 deletions src/common/cfgfiles.c
Expand Up @@ -313,13 +313,10 @@ get_xdir (void)
if (portable_mode () || SHGetKnownFolderPath (&FOLDERID_RoamingAppData, 0, NULL, &roaming_path_wide) != S_OK)
{
char *path;
char file[MAX_PATH];
HMODULE hModule;

hModule = GetModuleHandle (NULL);
if (GetModuleFileName (hModule, file, sizeof(file)))

path = g_win32_get_package_installation_directory_of_module (NULL);
if (path)
{
path = g_path_get_dirname (file);
xdir = g_build_filename (path, "config", NULL);
g_free (path);
}
Expand Down
18 changes: 0 additions & 18 deletions src/common/hexchat.c
Expand Up @@ -55,11 +55,6 @@
#include <glib-object.h> /* for g_type_init() */
#endif

#ifdef USE_OPENSSL
#include <openssl/ssl.h> /* SSL_() */
#include "ssl.h"
#endif

#ifdef USE_MSPROXY
#include "msproxy.h"
#endif
Expand Down Expand Up @@ -118,10 +113,6 @@ struct session *current_tab;
struct session *current_sess = 0;
struct hexchatprefs prefs;

#ifdef USE_OPENSSL
SSL_CTX *ctx = NULL;
#endif

#ifdef USE_LIBPROXY
pxProxyFactory *libproxy_factory;
#endif
Expand Down Expand Up @@ -1149,15 +1140,6 @@ main (int argc, char *argv[])
px_proxy_factory_free(libproxy_factory);
#endif

#ifdef USE_OPENSSL
if (ctx)
_SSL_context_free (ctx);
#endif

#ifdef USE_DEBUG
hexchat_mem_list ();
#endif

#ifdef WIN32
WSACleanup ();
#endif
Expand Down
1 change: 1 addition & 0 deletions src/common/hexchat.h
Expand Up @@ -532,6 +532,7 @@ typedef struct server
struct msproxy_state_t msp_state;
int id; /* unique ID number (for plugin API) */
#ifdef USE_OPENSSL
SSL_CTX *ctx;
SSL *ssl;
int ssl_do_connect_tag;
#else
Expand Down
28 changes: 8 additions & 20 deletions src/common/notify.c
Expand Up @@ -293,26 +293,20 @@ notify_set_offline_list (server * serv, char *users, int quiet,
struct notify_per_server *servnot;
char nick[NICKLEN];
char *token, *chr;
int pos;

token = strtok (users, ",");
while (token != NULL)
{
chr = strchr (token, '!');
if (!chr)
goto end;
if (chr != NULL)
*chr = '\0';

pos = chr - token;
if (pos + 1 >= sizeof(nick))
goto end;

memset (nick, 0, sizeof(nick));
strncpy (nick, token, pos);
g_strlcpy (nick, token, sizeof(nick));

servnot = notify_find (serv, nick);
if (servnot)
notify_announce_offline (serv, servnot, nick, quiet, tags_data);
end:

token = strtok (NULL, ",");
}
}
Expand All @@ -324,26 +318,20 @@ notify_set_online_list (server * serv, char *users,
struct notify_per_server *servnot;
char nick[NICKLEN];
char *token, *chr;
int pos;

token = strtok (users, ",");
while (token != NULL)
{
chr = strchr (token, '!');
if (!chr)
goto end;
if (chr != NULL)
*chr = '\0';

pos = chr - token;
if (pos + 1 >= sizeof(nick))
goto end;

memset (nick, 0, sizeof(nick));
strncpy (nick, token, pos);
g_strlcpy (nick, token, sizeof(nick));

servnot = notify_find (serv, nick);
if (servnot)
notify_announce_online (serv, servnot, nick, tags_data);
end:

token = strtok (NULL, ",");
}
}
Expand Down
37 changes: 27 additions & 10 deletions src/common/server.c
Expand Up @@ -76,7 +76,6 @@
#endif

#ifdef USE_OPENSSL
extern SSL_CTX *ctx; /* hexchat.c */
/* local variables */
static struct session *g_sess = NULL;
#endif
Expand Down Expand Up @@ -724,9 +723,22 @@ ssl_do_connect (server * serv)
switch (verify_error)
{
case X509_V_OK:
{
X509 *cert = SSL_get_peer_certificate (serv->ssl);
int hostname_err;
if ((hostname_err = _SSL_check_hostname(cert, serv->hostname)) != 0)
{
snprintf (buf, sizeof (buf), "* Verify E: Failed to validate hostname? (%d)%s",
hostname_err, serv->accept_invalid_cert ? " -- Ignored" : "");
if (serv->accept_invalid_cert)
EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0);
else
goto conn_fail;
}
break;
}
/* snprintf (buf, sizeof (buf), "* Verify OK (?)"); */
/* EMIT_SIGNAL (XP_TE_SSLMESSAGE, serv->server_session, buf, NULL, NULL, NULL, 0); */
break;
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
Expand All @@ -745,6 +757,7 @@ ssl_do_connect (server * serv)
snprintf (buf, sizeof (buf), "%s.? (%d)",
X509_verify_cert_error_string (verify_error),
verify_error);
conn_fail:
EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, buf, NULL, NULL,
NULL, 0);

Expand Down Expand Up @@ -861,8 +874,8 @@ server_connect_success (server *serv)

/* it'll be a memory leak, if connection isn't terminated by
server_cleanup() */
serv->ssl = _SSL_socket (ctx, serv->sok);
if ((err = _SSL_set_verify (ctx, ssl_cb_verify, NULL)))
serv->ssl = _SSL_socket (serv->ctx, serv->sok);
if ((err = _SSL_set_verify (serv->ctx, ssl_cb_verify, NULL)))
{
EMIT_SIGNAL (XP_TE_CONNFAIL, serv->server_session, err, NULL,
NULL, NULL, 0);
Expand Down Expand Up @@ -1666,9 +1679,9 @@ server_connect (server *serv, char *hostname, int port, int no_login)
session *sess = serv->server_session;

#ifdef USE_OPENSSL
if (!ctx && serv->use_ssl)
if (!serv->ctx && serv->use_ssl)
{
if (!(ctx = _SSL_context_init (ssl_cb_info, FALSE)))
if (!(serv->ctx = _SSL_context_init (ssl_cb_info, FALSE)))
{
fprintf (stderr, "_SSL_context_init failed\n");
exit (1);
Expand Down Expand Up @@ -1711,18 +1724,18 @@ server_connect (server *serv, char *hostname, int port, int no_login)
/* first try network specific cert/key */
cert_file = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "certs" G_DIR_SEPARATOR_S "%s.pem",
get_xdir (), server_get_network (serv, TRUE));
if (SSL_CTX_use_certificate_file (ctx, cert_file, SSL_FILETYPE_PEM) == 1)
if (SSL_CTX_use_certificate_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
{
if (SSL_CTX_use_PrivateKey_file (ctx, cert_file, SSL_FILETYPE_PEM) == 1)
if (SSL_CTX_use_PrivateKey_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
serv->have_cert = TRUE;
}
else
{
/* if that doesn't exist, try <config>/certs/client.pem */
cert_file = g_build_filename (get_xdir (), "certs", "client.pem", NULL);
if (SSL_CTX_use_certificate_file (ctx, cert_file, SSL_FILETYPE_PEM) == 1)
if (SSL_CTX_use_certificate_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
{
if (SSL_CTX_use_PrivateKey_file (ctx, cert_file, SSL_FILETYPE_PEM) == 1)
if (SSL_CTX_use_PrivateKey_file (serv->ctx, cert_file, SSL_FILETYPE_PEM) == 1)
serv->have_cert = TRUE;
}
}
Expand Down Expand Up @@ -2047,6 +2060,10 @@ server_free (server *serv)
free (serv->encoding);
if (serv->favlist)
g_slist_free_full (serv->favlist, (GDestroyNotify) servlist_favchan_free);
#ifdef USE_OPENSSL
if (serv->ctx)
_SSL_context_free (serv->ctx);
#endif

fe_server_callback (serv);

Expand Down
233 changes: 222 additions & 11 deletions src/common/ssl.c
Expand Up @@ -25,6 +25,7 @@
#include "inet.h" /* make it first to avoid macro redefinitions */
#include <openssl/ssl.h> /* SSL_() */
#include <openssl/err.h> /* ERR_() */
#include <openssl/x509v3.h>
#ifdef WIN32
#include <openssl/rand.h> /* RAND_seed() */
#include "../../config-win32.h" /* HAVE_SNPRINTF */
Expand All @@ -35,10 +36,14 @@
#include <string.h> /* strncpy() */
#include "ssl.h" /* struct cert_info */

#ifndef HAVE_SNPRINTF
#include <glib.h>
#include <glib/gprintf.h>
#define snprintf g_snprintf
#include <gio/gio.h>
#include "util.h"

/* If openssl was built without ec */
#ifndef SSL_OP_SINGLE_ECDH_USE
#define SSL_OP_SINGLE_ECDH_USE 0
#endif

/* globals */
Expand All @@ -57,7 +62,7 @@ __SSL_fill_err_buf (char *funcname)

err = ERR_get_error ();
ERR_error_string (err, buf);
snprintf (err_buf, sizeof (err_buf), "%s: %s (%d)\n", funcname, buf, err);
g_snprintf (err_buf, sizeof (err_buf), "%s: %s (%d)\n", funcname, buf, err);
}


Expand Down Expand Up @@ -86,6 +91,11 @@ _SSL_context_init (void (*info_cb_func), int server)

SSL_CTX_set_session_cache_mode (ctx, SSL_SESS_CACHE_BOTH);
SSL_CTX_set_timeout (ctx, 300);
SSL_CTX_set_options (ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3
|SSL_OP_NO_COMPRESSION
|SSL_OP_SINGLE_DH_USE|SSL_OP_SINGLE_ECDH_USE
|SSL_OP_NO_TICKET
|SSL_OP_CIPHER_SERVER_PREFERENCE);

/* used in SSL_connect(), SSL_accept() */
SSL_CTX_set_info_callback (ctx, info_cb_func);
Expand Down Expand Up @@ -113,8 +123,8 @@ ASN1_TIME_snprintf (char *buf, int buf_len, ASN1_TIME * tm)
buf[0] = 0;
if (expires != NULL)
{
memset (buf, 0, buf_len);
strncpy (buf, expires, 24);
/* expires is not \0 terminated */
safe_strcpy (buf, expires, MIN(24, buf_len));
}
BIO_free (inMem);
}
Expand Down Expand Up @@ -176,17 +186,17 @@ _SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl)

peer_pkey = X509_get_pubkey (peer_cert);

strncpy (cert_info->algorithm,
safe_strcpy (cert_info->algorithm,
(alg == NID_undef) ? "Unknown" : OBJ_nid2ln (alg),
sizeof (cert_info->algorithm));
cert_info->algorithm_bits = EVP_PKEY_bits (peer_pkey);
strncpy (cert_info->sign_algorithm,
safe_strcpy (cert_info->sign_algorithm,
(sign_alg == NID_undef) ? "Unknown" : OBJ_nid2ln (sign_alg),
sizeof (cert_info->sign_algorithm));
/* EVP_PKEY_bits(ca_pkey)); */
cert_info->sign_algorithm_bits = 0;
strncpy (cert_info->notbefore, notBefore, sizeof (cert_info->notbefore));
strncpy (cert_info->notafter, notAfter, sizeof (cert_info->notafter));
safe_strcpy (cert_info->notbefore, notBefore, sizeof (cert_info->notbefore));
safe_strcpy (cert_info->notafter, notAfter, sizeof (cert_info->notafter));

EVP_PKEY_free (peer_pkey);

Expand Down Expand Up @@ -215,9 +225,9 @@ _SSL_get_cipher_info (SSL * ssl)


c = SSL_get_current_cipher (ssl);
strncpy (chiper_info.version, SSL_CIPHER_get_version (c),
safe_strcpy (chiper_info.version, SSL_CIPHER_get_version (c),
sizeof (chiper_info.version));
strncpy (chiper_info.chiper, SSL_CIPHER_get_name (c),
safe_strcpy (chiper_info.chiper, SSL_CIPHER_get_name (c),
sizeof (chiper_info.chiper));
SSL_CIPHER_get_bits (c, &chiper_info.chiper_bits);

Expand Down Expand Up @@ -333,3 +343,204 @@ _SSL_close (SSL * ssl)
SSL_free (ssl);
ERR_remove_state (0); /* free state buffer */
}

/* Hostname validation code based on OpenBSD's libtls. */

static int
_SSL_match_hostname (const char *cert_hostname, const char *hostname)
{
const char *cert_domain, *domain, *next_dot;

if (g_ascii_strcasecmp (cert_hostname, hostname) == 0)
return 0;

/* Wildcard match? */
if (cert_hostname[0] == '*')
{
/*
* Valid wildcards:
* - "*.domain.tld"
* - "*.sub.domain.tld"
* - etc.
* Reject "*.tld".
* No attempt to prevent the use of eg. "*.co.uk".
*/
cert_domain = &cert_hostname[1];
/* Disallow "*" */
if (cert_domain[0] == '\0')
return -1;
/* Disallow "*foo" */
if (cert_domain[0] != '.')
return -1;
/* Disallow "*.." */
if (cert_domain[1] == '.')
return -1;
next_dot = strchr (&cert_domain[1], '.');
/* Disallow "*.bar" */
if (next_dot == NULL)
return -1;
/* Disallow "*.bar.." */
if (next_dot[1] == '.')
return -1;

domain = strchr (hostname, '.');

/* No wildcard match against a hostname with no domain part. */
if (domain == NULL || strlen(domain) == 1)
return -1;

if (g_ascii_strcasecmp (cert_domain, domain) == 0)
return 0;
}

return -1;
}

static int
_SSL_check_subject_altname (X509 *cert, const char *host)
{
STACK_OF(GENERAL_NAME) *altname_stack = NULL;
GInetAddress *addr;
GSocketFamily family;
int type = GEN_DNS;
int count, i;
int rv = -1;

altname_stack = X509_get_ext_d2i (cert, NID_subject_alt_name, NULL, NULL);
if (altname_stack == NULL)
return -1;

addr = g_inet_address_new_from_string (host);
if (addr != NULL)
{
family = g_inet_address_get_family (addr);
if (family == G_SOCKET_FAMILY_IPV4 || family == G_SOCKET_FAMILY_IPV6)
type = GEN_IPADD;
}

count = sk_GENERAL_NAME_num(altname_stack);
for (i = 0; i < count; i++)
{
GENERAL_NAME *altname;

altname = sk_GENERAL_NAME_value (altname_stack, i);

if (altname->type != type)
continue;

if (type == GEN_DNS)
{
unsigned char *data;
int format;

format = ASN1_STRING_type (altname->d.dNSName);
if (format == V_ASN1_IA5STRING)
{
data = ASN1_STRING_data (altname->d.dNSName);

if (ASN1_STRING_length (altname->d.dNSName) != (int)strlen(data))
{
g_warning("NUL byte in subjectAltName, probably a malicious certificate.\n");
rv = -2;
break;
}

if (_SSL_match_hostname (data, host) == 0)
{
rv = 0;
break;
}
}
else
g_warning ("unhandled subjectAltName dNSName encoding (%d)\n", format);

}
else if (type == GEN_IPADD)
{
unsigned char *data;
const guint8 *addr_bytes;
int datalen, addr_len;

datalen = ASN1_STRING_length (altname->d.iPAddress);
data = ASN1_STRING_data (altname->d.iPAddress);

addr_bytes = g_inet_address_to_bytes (addr);
addr_len = (int)g_inet_address_get_native_size (addr);

if (datalen == addr_len && memcmp (data, addr_bytes, addr_len) == 0)
{
rv = 0;
break;
}
}
}

if (addr != NULL)
g_object_unref (addr);
sk_GENERAL_NAME_free (altname_stack);
return rv;
}

static int
_SSL_check_common_name (X509 *cert, const char *host)
{
X509_NAME *name;
char *common_name = NULL;
int common_name_len;
int rv = -1;
GInetAddress *addr;

name = X509_get_subject_name (cert);
if (name == NULL)
return -1;

common_name_len = X509_NAME_get_text_by_NID (name, NID_commonName, NULL, 0);
if (common_name_len < 0)
return -1;

common_name = calloc (common_name_len + 1, 1);
if (common_name == NULL)
return -1;

X509_NAME_get_text_by_NID (name, NID_commonName, common_name, common_name_len + 1);

/* NUL bytes in CN? */
if (common_name_len != (int)strlen(common_name))
{
g_warning ("NUL byte in Common Name field, probably a malicious certificate.\n");
rv = -2;
goto out;
}

if ((addr = g_inet_address_new_from_string (host)) != NULL)
{
/*
* We don't want to attempt wildcard matching against IP
* addresses, so perform a simple comparison here.
*/
if (g_strcmp0 (common_name, host) == 0)
rv = 0;
else
rv = -1;

g_object_unref (addr);
}
else if (_SSL_match_hostname (common_name, host) == 0)
rv = 0;

out:
free(common_name);
return rv;
}

int
_SSL_check_hostname (X509 *cert, const char *host)
{
int rv;

rv = _SSL_check_subject_altname (cert, host);
if (rv == 0 || rv == -2)
return rv;

return _SSL_check_common_name (cert, host);
}
4 changes: 2 additions & 2 deletions src/common/ssl.h
Expand Up @@ -37,7 +37,7 @@ struct cert_info {

struct chiper_info {
char version[16];
char chiper[24];
char chiper[48];
int chiper_bits;
};

Expand All @@ -52,7 +52,7 @@ char *_SSL_set_verify (SSL_CTX *ctx, void *(verify_callback), char *cacert);
int SSL_get_fd(SSL *);
*/
void _SSL_close (SSL * ssl);

int _SSL_check_hostname(X509 *cert, const char *host);
int _SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl);
struct chiper_info *_SSL_get_cipher_info (SSL * ssl);

Expand Down
9 changes: 8 additions & 1 deletion src/common/text.c
Expand Up @@ -2300,7 +2300,14 @@ sound_play (const char *file, gboolean quiet)
if (g_access (wavfile, R_OK) == 0)
{
#ifdef WIN32
PlaySound (wavfile, NULL, SND_NODEFAULT|SND_FILENAME|SND_ASYNC);
gunichar2 *wavfile_utf16 = g_utf8_to_utf16 (wavfile, -1, NULL, NULL, NULL);

if (wavfile_utf16 != NULL)
{
PlaySoundW (wavfile_utf16, NULL, SND_NODEFAULT | SND_FILENAME | SND_ASYNC);

g_free (wavfile_utf16);
}
#else
#ifdef USE_LIBCANBERRA
if (ca_con == NULL)
Expand Down
6 changes: 3 additions & 3 deletions src/common/url.c
Expand Up @@ -415,8 +415,8 @@ regex_match (const GRegex *re, const char *word, int *start, int *end)
}

/* Miscellaneous description --- */
#define DOMAIN "[a-z0-9][-a-z0-9]*(\\.[-a-z0-9]+)*"
#define TLD "\\.[a-z][-a-z0-9]*[a-z]"
#define DOMAIN "[_\\pL\\pN][-_\\pL\\pN]*(\\.[-_\\pL\\pN]+)*"
#define TLD "\\.[\\pL][-\\pL\\pN]*[\\pL]"
#define IPADDR "[0-9]{1,3}(\\.[0-9]{1,3}){3}"
#define IPV6GROUP "([0-9a-f]{0,4})"
#define IPV6ADDR "((" IPV6GROUP "(:" IPV6GROUP "){7})" \
Expand Down Expand Up @@ -610,7 +610,7 @@ re_url (void)
}

/* EMAIL description --- */
#define EMAIL "[a-z][-_a-z0-9]+@" "(" HOST_URL ")"
#define EMAIL "[a-z][._%+-a-z0-9]+@" "(" HOST_URL ")"

static const GRegex *
re_email (void)
Expand Down
4 changes: 2 additions & 2 deletions src/common/util.c
Expand Up @@ -433,7 +433,7 @@ char *
expand_homedir (char *file)
{
#ifndef WIN32
char *ret, *user;
char *user;
struct passwd *pw;

if (file[0] == '~')
Expand Down Expand Up @@ -2017,7 +2017,7 @@ encode_sasl_pass_blowfish (char *user, char *pass, char *data)
memset (encrypted_pass, 0, pass_len);
plain_pass = (char*)malloc (pass_len);
memset (plain_pass, 0, pass_len);
memcpy (plain_pass, pass, pass_len);
memcpy (plain_pass, pass, strlen(pass));
out_ptr = (char*)encrypted_pass;
in_ptr = (char*)plain_pass;

Expand Down
105 changes: 73 additions & 32 deletions src/fe-gtk/fe-gtk.c
Expand Up @@ -656,10 +656,11 @@ void
fe_beep (session *sess)
{
#ifdef WIN32
if (!PlaySound ("Notification.IM", NULL, SND_ALIAS|SND_ASYNC))
/* Play the "Instant Message Notification" system sound
*/
if (!PlaySoundW (L"Notification.IM", NULL, SND_ALIAS | SND_ASYNC))
{
/* This is really just a fallback attempt, may or may not work on new Windows releases, especially on x64.
* You should set up the "Instant Message Notification" system sound instead, supported on Vista and up.
/* The user does not have the "Instant Message Notification" sound set. Fall back to system beep.
*/
Beep (1000, 50);
}
Expand Down Expand Up @@ -983,23 +984,84 @@ fe_set_inputbox_contents (session *sess, char *text)
}
}

#ifdef __APPLE__
static char *
url_escape_hostname (const char *url)
{
char *host_start, *host_end, *ret, *hostname;

host_start = strstr (url, "://");
if (host_start != NULL)
{
*host_start = '\0';
host_start += 3;
host_end = strchr (host_start, '/');

if (host_end != NULL)
{
*host_end = '\0';
host_end++;
}

hostname = g_hostname_to_ascii (host_start);
if (host_end != NULL)
ret = g_strdup_printf ("%s://%s/%s", url, hostname, host_end);
else
ret = g_strdup_printf ("%s://%s", url, hostname);

g_free (hostname);
return ret;
}

return g_strdup (url);
}

static void
osx_show_uri (const char *url)
{
char *escaped_url, *encoded_url, *open, *cmd;

escaped_url = url_escape_hostname (url);
encoded_url = g_filename_from_utf8 (escaped_url, -1, NULL, NULL, NULL);
if (encoded_url)
{
open = g_find_program_in_path ("open");
cmd = g_strjoin (" ", open, encoded_url, NULL);

hexchat_exec (cmd);

g_free (encoded_url);
g_free (cmd);
}

g_free (escaped_url);
}

#endif

static void
fe_open_url_inner (const char *url)
{
#ifdef WIN32
ShellExecute (0, "open", url, NULL, NULL, SW_SHOWNORMAL);
#elif defined __APPLE__
/* on Mac you can just 'open http://foo.bar/' */
gchar open[512];
g_snprintf (open, sizeof(open), "%s %s", g_find_program_in_path ("open"), url, NULL);
hexchat_exec (open);
gunichar2 *url_utf16 = g_utf8_to_utf16 (url, -1, NULL, NULL, NULL);

if (url_utf16 == NULL)
{
return;
}

ShellExecuteW (0, L"open", url_utf16, NULL, NULL, SW_SHOWNORMAL);

g_free (url_utf16);
#elif defined(__APPLE__)
osx_show_uri (url);
#else
gtk_show_uri (NULL, url, GDK_CURRENT_TIME, NULL);
#endif
}

static void
fe_open_url_locale (const char *url)
void
fe_open_url (const char *url)
{
int url_type = url_check_word (url);
char *uri;
Expand Down Expand Up @@ -1041,27 +1103,6 @@ fe_open_url_locale (const char *url)
}
}

void
fe_open_url (const char *url)
{
char *loc;

if (prefs.utf8_locale)
{
fe_open_url_locale (url);
return;
}

/* the OS expects it in "locale" encoding. This makes it work on
unix systems that use ISO-8859-x and Win32. */
loc = g_locale_from_utf8 (url, -1, 0, 0, 0);
if (loc)
{
fe_open_url_locale (loc);
g_free (loc);
}
}

void
fe_server_event (server *serv, int type, int arg)
{
Expand Down
72 changes: 51 additions & 21 deletions src/fe-gtk/gtkutil.c
Expand Up @@ -66,48 +66,69 @@ gtkutil_file_req_destroy (GtkWidget * wid, struct file_req *freq)
}

static void
gtkutil_check_file (char *file, struct file_req *freq)
gtkutil_check_file (char *filename, struct file_req *freq)
{
struct stat st;
int axs = FALSE;
char temp[256];

path_part (file, temp, sizeof (temp));
GFile *file = g_file_new_for_path (filename);

/* check if the file is readable or writable */
if (freq->flags & FRF_WRITE)
{
if (access (temp, W_OK) == 0)
axs = TRUE;
} else
GFile *parent = g_file_get_parent (file);

GFileInfo *fi = g_file_query_info (parent, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, G_FILE_QUERY_INFO_NONE, NULL, NULL);
if (fi != NULL)
{
if (g_file_info_get_attribute_boolean (fi, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
{
axs = TRUE;
}

g_object_unref (fi);
}

g_object_unref (parent);
}
else
{
if (stat (file, &st) != -1)
GFileInfo *fi = g_file_query_info (file, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, G_FILE_QUERY_INFO_NONE, NULL, NULL);

if (fi != NULL)
{
if (!S_ISDIR (st.st_mode) || (freq->flags & FRF_CHOOSEFOLDER))
if (g_file_info_get_file_type (fi) != G_FILE_TYPE_DIRECTORY || (freq->flags & FRF_CHOOSEFOLDER))
{
axs = TRUE;
}

g_object_unref (fi);
}
}

g_object_unref (file);

if (axs)
{
char *utf8_file;
/* convert to UTF8. It might be converted back to locale by
server.c's g_convert */
utf8_file = hexchat_filename_to_utf8 (file, -1, NULL, NULL, NULL);
if (utf8_file)
char *filename_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
if (filename_utf8 != NULL)
{
freq->callback (freq->userdata, utf8_file);
g_free (utf8_file);
} else
freq->callback (freq->userdata, filename_utf8);
g_free (filename_utf8);
}
else
{
fe_message ("Filename encoding is corrupt.", FE_MSG_ERROR);
}
} else
}
else
{
if (freq->flags & FRF_WRITE)
{
fe_message (_("Cannot write to that file."), FE_MSG_ERROR);
}
else
{
fe_message (_("Cannot read that file."), FE_MSG_ERROR);
}
}
}

Expand All @@ -128,12 +149,21 @@ gtkutil_file_req_done (GtkWidget * wid, struct file_req *freq)
}
if (files)
g_slist_free (files);
} else
}
else
{
if (freq->flags & FRF_CHOOSEFOLDER)
gtkutil_check_file (gtk_file_chooser_get_current_folder (fs), freq);
{
gchar *filename = gtk_file_chooser_get_current_folder (fs);
gtkutil_check_file (filename, freq);
g_free (filename);
}
else
{
gchar *filename = gtk_file_chooser_get_filename (fs);
gtkutil_check_file (gtk_file_chooser_get_filename (fs), freq);
g_free (filename);
}
}

/* this should call the "destroy" cb, where we free(freq) */
Expand Down
3 changes: 2 additions & 1 deletion src/fe-gtk/maingui.c
Expand Up @@ -441,7 +441,8 @@ mg_windowstate_cb (GtkWindow *wid, GdkEventWindowState *event, gpointer userdata
{
if ((event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) &&
(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) &&
prefs.hex_gui_tray_minimize && !unity_mode ())
prefs.hex_gui_tray_minimize && prefs.hex_gui_tray &&
!unity_mode ())
{
tray_toggle_visibility (TRUE);
gtk_window_deiconify (wid);
Expand Down
15 changes: 8 additions & 7 deletions src/fe-gtk/servlistgui.c
Expand Up @@ -1526,13 +1526,14 @@ servlist_logintypecombo_cb (GtkComboBox *cb, gpointer *userdata)

index = gtk_combo_box_get_active (cb); /* starts at 0, returns -1 for invalid selections */

if (index != -1)
{
/* The selection is valid. It can be 0, which is the default type, but we need to allow
* that so that you can revert from other types. servlist_save() will dump 0 anyway.
*/
selected_net->logintype = login_types_conf[index];
}
if (index == -1)
return; /* Invalid */

/* The selection is valid. It can be 0, which is the default type, but we need to allow
* that so that you can revert from other types. servlist_save() will dump 0 anyway.
*/
selected_net->logintype = login_types_conf[index];

if (login_types_conf[index] == LOGIN_CUSTOM)
{
gtk_notebook_set_current_page (GTK_NOTEBOOK (userdata), 2); /* FIXME avoid hardcoding? */
Expand Down
3 changes: 3 additions & 0 deletions src/fe-gtk/xtext.c
Expand Up @@ -488,7 +488,10 @@ gtk_xtext_adjustment_set (xtext_buffer *buf, int fire_signal)
adj->page_increment = adj->page_size;

if (adj->value > adj->upper - adj->page_size)
{
buf->scrollbar_down = TRUE;
adj->value = adj->upper - adj->page_size;
}

if (adj->value < 0)
adj->value = 0;
Expand Down