/* X-Chat * Copyright (C) 1998 Peter Zelezny. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #define WANTSOCKET #include "inet.h" /* make it first to avoid macro redefinitions */ #define __APPLE_API_STRICT_CONFORMANCE #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #ifdef WIN32 #include #include #include #include /* for find_font() */ #include "../dirent/dirent-win32.h" #include "../../config-win32.h" #else #include #include #include #include #include #include "../../config.h" #endif #include #include #include "hexchat.h" #include "hexchatc.h" #include #include "util.h" #if defined (USING_FREEBSD) || defined (__APPLE__) #include #endif #ifdef SOCKS #include #endif /* SASL mechanisms */ #ifdef USE_OPENSSL #include #include #include #include #ifndef WIN32 #include #endif #endif #ifndef HAVE_SNPRINTF #define snprintf g_snprintf #endif #ifdef USE_DEBUG #undef free #undef malloc #undef realloc #undef strdup int current_mem_usage; struct mem_block { char *file; void *buf; int size; int line; int total; struct mem_block *next; }; struct mem_block *mroot = NULL; void * hexchat_malloc (int size, char *file, int line) { void *ret; struct mem_block *new; current_mem_usage += size; ret = malloc (size); if (!ret) { printf ("Out of memory! (%d)\n", current_mem_usage); exit (255); } new = malloc (sizeof (struct mem_block)); new->buf = ret; new->size = size; new->next = mroot; new->line = line; new->file = strdup (file); mroot = new; printf ("%s:%d Malloc'ed %d bytes, now \033[35m%d\033[m\n", file, line, size, current_mem_usage); return ret; } void * hexchat_realloc (char *old, int len, char *file, int line) { char *ret; ret = hexchat_malloc (len, file, line); if (ret) { strcpy (ret, old); hexchat_dfree (old, file, line); } return ret; } void * hexchat_strdup (char *str, char *file, int line) { void *ret; struct mem_block *new; int size; size = strlen (str) + 1; current_mem_usage += size; ret = malloc (size); if (!ret) { printf ("Out of memory! (%d)\n", current_mem_usage); exit (255); } strcpy (ret, str); new = malloc (sizeof (struct mem_block)); new->buf = ret; new->size = size; new->next = mroot; new->line = line; new->file = strdup (file); mroot = new; printf ("%s:%d strdup (\"%-.40s\") size: %d, total: \033[35m%d\033[m\n", file, line, str, size, current_mem_usage); return ret; } void hexchat_mem_list (void) { struct mem_block *cur, *p; GSList *totals = 0; GSList *list; cur = mroot; while (cur) { list = totals; while (list) { p = list->data; if (p->line == cur->line && strcmp (p->file, cur->file) == 0) { p->total += p->size; break; } list = list->next; } if (!list) { cur->total = cur->size; totals = g_slist_prepend (totals, cur); } cur = cur->next; } fprintf (stderr, "file line size num total\n"); list = totals; while (list) { cur = list->data; fprintf (stderr, "%-15.15s %6d %6d %6d %6d\n", cur->file, cur->line, cur->size, cur->total/cur->size, cur->total); list = list->next; } } void hexchat_dfree (void *buf, char *file, int line) { struct mem_block *cur, *last; if (buf == NULL) { printf ("%s:%d \033[33mTried to free NULL\033[m\n", file, line); return; } last = NULL; cur = mroot; while (cur) { if (buf == cur->buf) break; last = cur; cur = cur->next; } if (cur == NULL) { printf ("%s:%d \033[31mTried to free unknown block %lx!\033[m\n", file, line, (unsigned long) buf); /* abort(); */ free (buf); return; } current_mem_usage -= cur->size; printf ("%s:%d Free'ed %d bytes, usage now \033[35m%d\033[m\n", file, line, cur->size, current_mem_usage); if (last) last->next = cur->next; else mroot = cur->next; free (cur->file); free (cur); } #define malloc(n) hexchat_malloc(n, __FILE__, __LINE__) #define realloc(n, m) hexchat_realloc(n, m, __FILE__, __LINE__) #define free(n) hexchat_dfree(n, __FILE__, __LINE__) #define strdup(n) hexchat_strdup(n, __FILE__, __LINE__) #endif /* MEMORY_DEBUG */ char * file_part (char *file) { char *filepart = file; if (!file) return ""; while (1) { switch (*file) { case 0: return (filepart); case '/': #ifdef WIN32 case '\\': #endif filepart = file + 1; break; } file++; } } void path_part (char *file, char *path, int pathlen) { unsigned char t; char *filepart = file_part (file); t = *filepart; *filepart = 0; safe_strcpy (path, file, pathlen); *filepart = t; } char * /* like strstr(), but nocase */ nocasestrstr (const char *s, const char *wanted) { register const int len = strlen (wanted); if (len == 0) return (char *)s; while (rfc_tolower(*s) != rfc_tolower(*wanted) || g_ascii_strncasecmp (s, wanted, len)) if (*s++ == '\0') return (char *)NULL; return (char *)s; } char * errorstring (int err) { switch (err) { case -1: return ""; case 0: return _("Remote host closed socket"); #ifndef WIN32 } #else case WSAECONNREFUSED: return _("Connection refused"); case WSAENETUNREACH: case WSAEHOSTUNREACH: return _("No route to host"); case WSAETIMEDOUT: return _("Connection timed out"); case WSAEADDRNOTAVAIL: return _("Cannot assign that address"); case WSAECONNRESET: return _("Connection reset by peer"); } /* can't use strerror() on Winsock errors! */ if (err >= WSABASEERR) { static char tbuf[384]; OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); GetVersionEx (&osvi); /* FormatMessage works on WSA*** errors starting from Win2000 */ if (osvi.dwMajorVersion >= 5) { if (FormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, err, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), tbuf, sizeof (tbuf), NULL)) { int len; char *utf; tbuf[sizeof (tbuf) - 1] = 0; len = strlen (tbuf); if (len >= 2) tbuf[len - 2] = 0; /* remove the cr-lf */ /* now convert to utf8 */ utf = g_locale_to_utf8 (tbuf, -1, 0, 0, 0); if (utf) { safe_strcpy (tbuf, utf, sizeof (tbuf)); g_free (utf); return tbuf; } } } /* ! if (osvi.dwMajorVersion >= 5) */ /* fallback to error number */ sprintf (tbuf, "%s %d", _("Error"), err); return tbuf; } /* ! if (err >= WSABASEERR) */ #endif /* ! WIN32 */ return strerror (err); } int waitline (int sok, char *buf, int bufsize, int use_recv) { int i = 0; while (1) { if (use_recv) { if (recv (sok, &buf[i], 1, 0) < 1) return -1; } else { if (read (sok, &buf[i], 1) < 1) return -1; } if (buf[i] == '\n' || bufsize == i + 1) { buf[i] = 0; return i; } i++; } } #ifdef WIN32 /* waitline2 using win32 file descriptor and glib instead of _read. win32 can't _read() sok! */ int waitline2 (GIOChannel *source, char *buf, int bufsize) { int i = 0; gsize len; GError *error = NULL; while (1) { g_io_channel_set_buffered (source, FALSE); g_io_channel_set_encoding (source, NULL, &error); if (g_io_channel_read_chars (source, &buf[i], 1, &len, &error) != G_IO_STATUS_NORMAL) { return -1; } if (buf[i] == '\n' || bufsize == i + 1) { buf[i] = 0; return i; } i++; } } #endif /* checks for "~" in a file and expands */ char * expand_homedir (char *file) { #ifndef WIN32 char *ret, *user; struct passwd *pw; if (*file == '~') { if (file[1] != '\0' && file[1] != '/') { user = strdup(file); if (strchr(user,'/') != NULL) *(strchr(user,'/')) = '\0'; if ((pw = getpwnam(user + 1)) == NULL) { free(user); return strdup(file); } free(user); user = strchr(file, '/') != NULL ? strchr(file,'/') : file; ret = malloc(strlen(user) + strlen(pw->pw_dir) + 1); strcpy(ret, pw->pw_dir); strcat(ret, user); } else { ret = malloc (strlen (file) + strlen (g_get_home_dir ()) + 1); sprintf (ret, "%s%s", g_get_home_dir (), file + 1); } return ret; } #endif return g_strdup (file); } gchar * strip_color (const char *text, int len, int flags) { char *new_str; if (len == -1) len = strlen (text); new_str = g_malloc (len + 2); strip_color2 (text, len, new_str, flags); if (flags & STRIP_ESCMARKUP) { char *esc = g_markup_escape_text (new_str, -1); g_free (new_str); return esc; } return new_str; } /* CL: strip_color2 strips src and writes the output at dst; pass the same pointer in both arguments to strip in place. */ int strip_color2 (const char *src, int len, char *dst, int flags) { int rcol = 0, bgcol = 0; char *start = dst; if (len == -1) len = strlen (src); while (len-- > 0) { if (rcol > 0 && (isdigit ((unsigned char)*src) || (*src == ',' && isdigit ((unsigned char)src[1]) && !bgcol))) { if (src[1] != ',') rcol--; if (*src == ',') { rcol = 2; bgcol = 1; } } else { rcol = bgcol = 0; switch (*src) { case '\003': /*ATTR_COLOR: */ if (!(flags & STRIP_COLOR)) goto pass_char; rcol = 2; break; case HIDDEN_CHAR: /* CL: invisible text (for event formats only) */ /* this takes care of the topic */ if (!(flags & STRIP_HIDDEN)) goto pass_char; break; case '\007': /*ATTR_BEEP: */ case '\017': /*ATTR_RESET: */ case '\026': /*ATTR_REVERSE: */ case '\002': /*ATTR_BOLD: */ case '\037': /*ATTR_UNDERLINE: */ case '\035': /*ATTR_ITALICS: */ if (!(flags & STRIP_ATTRIB)) goto pass_char; break; default: pass_char: *dst++ = *src; } } src++; } *dst = 0; return (int) (dst - start); } int strip_hidden_attribute (char *src, char *dst) { int len = 0; while (*src != '\000') { if (*src != HIDDEN_CHAR) { *dst++ = *src; len++; } src++; } return len; } #if defined (USING_LINUX) || defined (USING_FREEBSD) || defined (__APPLE__) static void get_cpu_info (double *mhz, int *cpus) { #ifdef USING_LINUX char buf[256]; int fh; *mhz = 0; *cpus = 0; fh = open ("/proc/cpuinfo", O_RDONLY); /* linux 2.2+ only */ if (fh == -1) { *cpus = 1; return; } while (1) { if (waitline (fh, buf, sizeof buf, FALSE) < 0) break; if (!strncmp (buf, "cycle frequency [Hz]\t:", 22)) /* alpha */ { *mhz = atoi (buf + 23) / 1000000; } else if (!strncmp (buf, "cpu MHz\t\t:", 10)) /* i386 */ { *mhz = atof (buf + 11) + 0.5; } else if (!strncmp (buf, "clock\t\t:", 8)) /* PPC */ { *mhz = atoi (buf + 9); } else if (!strncmp (buf, "processor\t", 10)) { (*cpus)++; } } close (fh); if (!*cpus) *cpus = 1; #endif #ifdef USING_FREEBSD int mib[2], ncpu; u_long freq; size_t len; freq = 0; *mhz = 0; *cpus = 0; mib[0] = CTL_HW; mib[1] = HW_NCPU; len = sizeof(ncpu); sysctl(mib, 2, &ncpu, &len, NULL, 0); len = sizeof(freq); sysctlbyname("machdep.tsc_freq", &freq, &len, NULL, 0); *cpus = ncpu; *mhz = (freq / 1000000); #endif #ifdef __APPLE__ int mib[2], ncpu; unsigned long long freq; size_t len; freq = 0; *mhz = 0; *cpus = 0; mib[0] = CTL_HW; mib[1] = HW_NCPU; len = sizeof(ncpu); sysctl(mib, 2, &ncpu, &len, NULL, 0); len = sizeof(freq); sysctlbyname("hw.cpufrequency", &freq, &len, NULL, 0); *cpus = ncpu; *mhz = (freq / 1000000); #endif } #endif #ifdef WIN32 static int get_mhz (void) { HKEY hKey; int result, data, dataSize; if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Hardware\\Description\\System\\" "CentralProcessor\\0", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { dataSize = sizeof (data); result = RegQueryValueEx (hKey, "~MHz", 0, 0, (LPBYTE)&data, &dataSize); RegCloseKey (hKey); if (result == ERROR_SUCCESS) return data; } return 0; /* fails on Win9x */ } int get_cpu_arch (void) { SYSTEM_INFO si; GetSystemInfo (&si); if (si.wProcessorArchitecture == 9) { return 64; } else { return 86; } } char * get_sys_str (int with_cpu) { static char verbuf[64]; static char winver[20]; OSVERSIONINFOEX osvi; double mhz; osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX); GetVersionEx ((OSVERSIONINFO*) &osvi); switch (osvi.dwMajorVersion) { case 5: switch (osvi.dwMinorVersion) { case 1: strcpy (winver, "XP"); break; case 2: if (osvi.wProductType == VER_NT_WORKSTATION) { strcpy (winver, "XP x64 Edition"); } else { if (GetSystemMetrics(SM_SERVERR2) == 0) { strcpy (winver, "Server 2003"); } else { strcpy (winver, "Server 2003 R2"); } } break; } break; case 6: switch (osvi.dwMinorVersion) { case 0: if (osvi.wProductType == VER_NT_WORKSTATION) { strcpy (winver, "Vista"); } else { strcpy (winver, "Server 2008"); } break; case 1: if (osvi.wProductType == VER_NT_WORKSTATION) { strcpy (winver, "7"); } else { strcpy (winver, "Server 2008 R2"); } break; case 2: if (osvi.wProductType == VER_NT_WORKSTATION) { strcpy (winver, "8"); } else { strcpy (winver, "Server 2012"); } break; } break; } mhz = get_mhz (); if (mhz && with_cpu) { double cpuspeed = ( mhz > 1000 ) ? mhz / 1000 : mhz; const char *cpuspeedstr = ( mhz > 1000 ) ? "GHz" : "MHz"; sprintf (verbuf, "Windows %s [%.2f%s]", winver, cpuspeed, cpuspeedstr); } else { sprintf (verbuf, "Windows %s", winver); } return verbuf; } #else char * get_sys_str (int with_cpu) { #if defined (USING_LINUX) || defined (USING_FREEBSD) || defined (__APPLE__) double mhz; #endif int cpus = 1; struct utsname un; static char *buf = NULL; if (buf) return buf; buf = malloc (128); uname (&un); #if defined (USING_LINUX) || defined (USING_FREEBSD) || defined (__APPLE__) get_cpu_info (&mhz, &cpus); if (mhz && with_cpu) { double cpuspeed = ( mhz > 1000 ) ? mhz / 1000 : mhz; const char *cpuspeedstr = ( mhz > 1000 ) ? "GHz" : "MHz"; snprintf (buf, 128, (cpus == 1) ? "%s %s [%s/%.2f%s]" : "%s %s [%s/%.2f%s/SMP]", un.sysname, un.release, un.machine, cpuspeed, cpuspeedstr); } else #endif snprintf (buf, 128, "%s %s", un.sysname, un.release); return buf; } #endif int buf_get_line (char *ibuf, char **buf, int *position, int len) { int pos = *position, spos = pos; if (pos == len) return 0; while (ibuf[pos++] != '\n') { if (pos == len) return 0; } pos--; ibuf[pos] = 0; *buf = &ibuf[spos]; pos++; *position = pos; return 1; } int match(const char *mask, const char *string) { register const char *m = mask, *s = string; register char ch; const char *bm, *bs; /* Will be reg anyway on a decent CPU/compiler */ /* Process the "head" of the mask, if any */ while ((ch = *m++) && (ch != '*')) switch (ch) { case '\\': if (*m == '?' || *m == '*') ch = *m++; default: if (rfc_tolower(*s) != rfc_tolower(ch)) return 0; case '?': if (!*s++) return 0; }; if (!ch) return !(*s); /* We got a star: quickly find if/where we match the next char */ got_star: bm = m; /* Next try rollback here */ while ((ch = *m++)) switch (ch) { case '?': if (!*s++) return 0; case '*': bm = m; continue; /* while */ case '\\': if (*m == '?' || *m == '*') ch = *m++; default: goto break_while; /* C is structured ? */ }; break_while: if (!ch) return 1; /* mask ends with '*', we got it */ ch = rfc_tolower(ch); while (rfc_tolower(*s++) != ch) if (!*s) return 0; bs = s; /* Next try start from here */ /* Check the rest of the "chunk" */ while ((ch = *m++)) { switch (ch) { case '*': goto got_star; case '\\': if (*m == '?' || *m == '*') ch = *m++; default: if (rfc_tolower(*s) != rfc_tolower(ch)) { if (!*s) return 0; m = bm; s = bs; goto got_star; }; case '?': if (!*s++) return 0; }; }; if (*s) { m = bm; s = bs; goto got_star; }; return 1; } void for_files (char *dirname, char *mask, void callback (char *file)) { DIR *dir; struct dirent *ent; char *buf; dir = opendir (dirname); if (dir) { while ((ent = readdir (dir))) { if (strcmp (ent->d_name, ".") && strcmp (ent->d_name, "..")) { if (match (mask, ent->d_name)) { buf = malloc (strlen (dirname) + strlen (ent->d_name) + 2); sprintf (buf, "%s" G_DIR_SEPARATOR_S "%s", dirname, ent->d_name); callback (buf); free (buf); } } } closedir (dir); } } /*void tolowerStr (char *str) { while (*str) { *str = rfc_tolower (*str); str++; } }*/ typedef struct { char *code, *country; } domain_t; static int country_compare (const void *a, const void *b) { return g_ascii_strcasecmp (a, ((domain_t *)b)->code); } static const domain_t domain[] = { {"AC", N_("Ascension Island") }, {"AD", N_("Andorra") }, {"AE", N_("United Arab Emirates") }, {"AERO", N_("Aviation-Related Fields") }, {"AF", N_("Afghanistan") }, {"AG", N_("Antigua and Barbuda") }, {"AI", N_("Anguilla") }, {"AL", N_("Albania") }, {"AM", N_("Armenia") }, {"AN", N_("Netherlands Antilles") }, {"AO", N_("Angola") }, {"AQ", N_("Antarctica") }, {"AR", N_("Argentina") }, {"ARPA", N_("Reverse DNS") }, {"AS", N_("American Samoa") }, {"ASIA", N_("Asia-Pacific Region") }, {"AT", N_("Austria") }, {"ATO", N_("Nato Fiel") }, {"AU", N_("Australia") }, {"AW", N_("Aruba") }, {"AX", N_("Aland Islands") }, {"AZ", N_("Azerbaijan") }, {"BA", N_("Bosnia and Herzegovina") }, {"BB", N_("Barbados") }, {"BD", N_("Bangladesh") }, {"BE", N_("Belgium") }, {"BF", N_("Burkina Faso") }, {"BG", N_("Bulgaria") }, {"BH", N_("Bahrain") }, {"BI", N_("Burundi") }, {"BIZ", N_("Businesses"), }, {"BJ", N_("Benin") }, {"BM", N_("Bermuda") }, {"BN", N_("Brunei Darussalam") }, {"BO", N_("Bolivia") }, {"BR", N_("Brazil") }, {"BS", N_("Bahamas") }, {"BT", N_("Bhutan") }, {"BV", N_("Bouvet Island") }, {"BW", N_("Botswana") }, {"BY", N_("Belarus") }, {"BZ", N_("Belize") }, {"CA", N_("Canada") }, {"CAT", N_("Catalan") }, {"CC", N_("Cocos Islands") }, {"CD", N_("Democratic Republic of Congo") }, {"CF", N_("Central African Republic") }, {"CG", N_("Congo") }, {"CH", N_("Switzerland") }, {"CI", N_("Cote d'Ivoire") }, {"CK", N_("Cook Islands") }, {"CL", N_("Chile") }, {"CM", N_("Cameroon") }, {"CN", N_("China") }, {"CO", N_("Colombia") }, {"COM", N_("Internic Commercial") }, {"COOP", N_("Cooperatives") }, {"CR", N_("Costa Rica") }, {"CS", N_("Serbia and Montenegro") }, {"CU", N_("Cuba") }, {"CV", N_("Cape Verde") }, {"CX", N_("Christmas Island") }, {"CY", N_("Cyprus") }, {"CZ", N_("Czech Republic") }, {"DD", N_("East Germany") }, {"DE", N_("Germany") }, {"DJ", N_("Djibouti") }, {"DK", N_("Denmark") }, {"DM", N_("Dominica") }, {"DO", N_("Dominican Republic") }, {"DZ", N_("Algeria") }, {"EC", N_("Ecuador") }, {"EDU", N_("Educational Institution") }, {"EE", N_("Estonia") }, {"EG", N_("Egypt") }, {"EH", N_("Western Sahara") }, {"ER", N_("Eritrea") }, {"ES", N_("Spain") }, {"ET", N_("Ethiopia") }, {"EU", N_("European Union") }, {"FI", N_("Finland") }, {"FJ", N_("Fiji") }, {"FK", N_("Falkland Islands") }, {"FM", N_("Micronesia") }, {"FO", N_("Faroe Islands") }, {"FR", N_("France") }, {"GA", N_("Gabon") }, {"GB", N_("Great Britain") }, {"GD", N_("Grenada") }, {"GE", N_("Georgia") }, {"GF", N_("French Guiana") }, {"GG", N_("British Channel Isles") }, {"GH", N_("Ghana") }, {"GI", N_("Gibraltar") }, {"GL", N_("Greenland") }, {"GM", N_("Gambia") }, {"GN", N_("Guinea") }, {"GOV", N_("Government") }, {"GP", N_("Guadeloupe") }, {"GQ", N_("Equatorial Guinea") }, {"GR", N_("Greece") }, {"GS", N_("S. Georgia and S. Sandwich Isles") }, {"GT", N_("Guatemala") }, {"GU", N_("Guam") }, {"GW", N_("Guinea-Bissau") }, {"GY", N_("Guyana") }, {"HK", N_("Hong Kong") }, {"HM", N_("Heard and McDonald Islands") }, {"HN", N_("Honduras") }, {"HR", N_("Croatia") }, {"HT", N_("Haiti") }, {"HU", N_("Hungary") }, {"ID", N_("Indonesia") }, {"IE", N_("Ireland") }, {"IL", N_("Israel") }, {"IM", N_("Isle of Man") }, {"IN", N_("India") }, {"INFO", N_("Informational") }, {"INT", N_("International") }, {"IO", N_("British Indian Ocean Territory") }, {"IQ", N_("Iraq") }, {"IR", N_("Iran") }, {"IS", N_("Iceland") }, {"IT", N_("Italy") }, {"JE", N_("Jersey") }, {"JM", N_("Jamaica") }, {"JO", N_("Jordan") }, {"JOBS", N_("Company Jobs") }, {"JP", N_("Japan") }, {"KE", N_("Kenya") }, {"KG", N_("Kyrgyzstan") }, {"KH", N_("Cambodia") }, {"KI", N_("Kiribati") }, {"KM", N_("Comoros") }, {"KN", N_("St. Kitts and Nevis") }, {"KP", N_("North Korea") }, {"KR", N_("South Korea") }, {"KW", N_("Kuwait") }, {"KY", N_("Cayman Islands") }, {"KZ", N_("Kazakhstan") }, {"LA", N_("Laos") }, {"LB", N_("Lebanon") }, {"LC", N_("Saint Lucia") }, {"LI", N_("Liechtenstein") }, {"LK", N_("Sri Lanka") }, {"LR", N_("Liberia") }, {"LS", N_("Lesotho") }, {"LT", N_("Lithuania") }, {"LU", N_("Luxembourg") }, {"LV", N_("Latvia") }, {"LY", N_("Libya") }, {"MA", N_("Morocco") }, {"MC", N_
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Debug|x64">
      <Configuration>Debug</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|x64">
      <Configuration>Release</Configuration>
      <Platform>x64</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{1B4E62F7-3437-48D5-AAB2-CBBE3DE513ED}</ProjectGuid>
    <RootNamespace>fc-case</RootNamespace>
    <Keyword>Win32Proj</Keyword>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <ConfigurationType>Application</ConfigurationType>
    <CharacterSet>MultiByte</CharacterSet>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
    <Import Project="fontconfig.props" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
    <Import Project="fontconfig.props" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
    <Import Project="fontconfig.props" />
  </ImportGroup>
  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
    <Import Project="fontconfig.props" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup>
    <_ProjectFileVersion>11.0.50727.1</_ProjectFileVersion>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <OutDir>Debug\</OutDir>
    <IntDir>Debug\</IntDir>
    <LinkIncremental>true</LinkIncremental>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <LinkIncremental>true</LinkIncremental>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <OutDir>Release\</OutDir>
    <IntDir>Release\</IntDir>
    <LinkIncremental>false</LinkIncremental>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <LinkIncremental>false</LinkIncremental>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <PreBuildEvent>
      <Command>
      </Command>
    </PreBuildEvent>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>.\;.\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_DEBUG;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <MinimalRebuild>true</MinimalRebuild>
      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
      <PrecompiledHeader />
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
      <DisableSpecificWarnings>4244;4819;%(DisableSpecificWarnings)</DisableSpecificWarnings>
    </ClCompile>
    <Link>
      <OutputFile>.\fc-case\fc-case.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)fc-case.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention />
      <TargetMachine>MachineX86</TargetMachine>
    </Link>
    <PostBuildEvent>
      <Command>if exist .\fc-case\fccase.h goto END
cd fc-case
fc-case.exe ../fc-case/CaseFolding.txt &lt; ../fc-case/fccase.tmpl.h &gt; fccase.h
cd ..
:END
</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <PreBuildEvent>
      <Command>
      </Command>
    </PreBuildEvent>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>.\;.\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_DEBUG;HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <DisableSpecificWarnings>4244;4819;%(DisableSpecificWarnings)</DisableSpecificWarnings>
    </ClCompile>
    <Link>
      <OutputFile>.\fc-case\fc-case.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)fc-case.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
    </Link>
    <PostBuildEvent>
      <Command>if exist .\fc-case\fccase.h goto END
cd fc-case
fc-case.exe ../fc-case/CaseFolding.txt &lt; ../fc-case/fccase.tmpl.h &gt; fccase.h
cd ..
:END
</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <PreBuildEvent>
      <Command>
      </Command>
    </PreBuildEvent>
    <ClCompile>
      <AdditionalIncludeDirectories>.\;.\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <PrecompiledHeader />
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <DisableSpecificWarnings>4244;4819;%(DisableSpecificWarnings)</DisableSpecificWarnings>
    </ClCompile>
    <Link>
      <OutputFile>.\fc-case\fc-case.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention />
      <TargetMachine>MachineX86</TargetMachine>
    </Link>
    <PostBuildEvent>
      <Command>if exist .\fc-case\fccase.h goto END
cd fc-case
fc-case.exe ../fc-case/CaseFolding.txt &lt; ../fc-case/fccase.tmpl.h &gt; fccase.h
cd ..
:END
</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <PreBuildEvent>
      <Command>
      </Command>
    </PreBuildEvent>
    <ClCompile>
      <AdditionalIncludeDirectories>.\;.\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>HAVE_CONFIG_H;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <WarningLevel>Level3</WarningLevel>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
      <DisableSpecificWarnings>4244;4819;%(DisableSpecificWarnings)</DisableSpecificWarnings>
    </ClCompile>
    <Link>
      <OutputFile>.\fc-case\fc-case.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <SubSystem>Console</SubSystem>
      <OptimizeReferences>true</OptimizeReferences>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
    </Link>
    <PostBuildEvent>
      <Command>if exist .\fc-case\fccase.h goto END
cd fc-case
fc-case.exe ../fc-case/CaseFolding.txt &lt; ../fc-case/fccase.tmpl.h &gt; fccase.h
cd ..
:END
</Command>
    </PostBuildEvent>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="fc-case\fc-case.c" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>
rectly on buffer thanks to the atrocious \0 characters it requires */ authlen = strlen (user) * 2 + 2 + strlen (pass); buffer = g_strdup_printf ("%s%c%s%c%s", user, '\0', user, '\0', pass); encoded = g_base64_encode ((unsigned char*) buffer, authlen); g_free (buffer); return encoded; } #ifdef USE_OPENSSL /* Adapted from ZNC's SASL module */ static int parse_dh (char *str, DH **dh_out, unsigned char **secret_out, int *keysize_out) { DH *dh; guchar *data, *decoded_data; guchar *secret; gsize data_len; guint size; guint16 size16; BIGNUM *pubkey; gint key_size; dh = DH_new(); data = decoded_data = g_base64_decode (str, &data_len); if (data_len < 2) goto fail; /* prime number */ memcpy (&size16, data, sizeof(size16)); size = ntohs (size16); data += 2; data_len -= 2; if (size > data_len) goto fail; dh->p = BN_bin2bn (data, size, NULL); data += size; /* Generator */ if (data_len < 2) goto fail; memcpy (&size16, data, sizeof(size16)); size = ntohs (size16); data += 2; data_len -= 2; if (size > data_len) goto fail; dh->g = BN_bin2bn (data, size, NULL); data += size; /* pub key */ if (data_len < 2) goto fail; memcpy (&size16, data, sizeof(size16)); size = ntohs(size16); data += 2; data_len -= 2; pubkey = BN_bin2bn (data, size, NULL); if (!(DH_generate_key (dh))) goto fail; secret = (unsigned char*)malloc (DH_size(dh)); key_size = DH_compute_key (secret, pubkey, dh); if (key_size == -1) goto fail; g_free (decoded_data); *dh_out = dh; *secret_out = secret; *keysize_out = key_size; return 1; fail: if (decoded_data) g_free (decoded_data); return 0; } char * encode_sasl_pass_blowfish (char *user, char *pass, char *data) { DH *dh; char *response, *ret; unsigned char *secret; unsigned char *encrypted_pass; char *plain_pass; BF_KEY key; int key_size, length; int pass_len = strlen (pass) + (8 - (strlen (pass) % 8)); int user_len = strlen (user); guint16 size16; char *in_ptr, *out_ptr; if (!parse_dh (data, &dh, &secret, &key_size)) return NULL; BF_set_key (&key, key_size, secret); encrypted_pass = (guchar*)malloc (pass_len); memset (encrypted_pass, 0, pass_len); plain_pass = (char*)malloc (pass_len); memset (plain_pass, 0, pass_len); memcpy (plain_pass, pass, pass_len); out_ptr = (char*)encrypted_pass; in_ptr = (char*)plain_pass; for (length = pass_len; length; length -= 8, in_ptr += 8, out_ptr += 8) BF_ecb_encrypt ((unsigned char*)in_ptr, (unsigned char*)out_ptr, &key, BF_ENCRYPT); /* Create response */ length = 2 + BN_num_bytes (dh->pub_key) + pass_len + user_len + 1; response = (char*)malloc (length); out_ptr = response; /* our key */ size16 = htons ((guint16)BN_num_bytes (dh->pub_key)); memcpy (out_ptr, &size16, sizeof(size16)); out_ptr += 2; BN_bn2bin (dh->pub_key, (guchar*)out_ptr); out_ptr += BN_num_bytes (dh->pub_key); /* username */ memcpy (out_ptr, user, user_len + 1); out_ptr += user_len + 1; /* pass */ memcpy (out_ptr, encrypted_pass, pass_len); ret = g_base64_encode ((const guchar*)response, length); DH_free (dh); free (plain_pass); free (encrypted_pass); free (secret); free (response); return ret; } char * encode_sasl_pass_aes (char *user, char *pass, char *data) { DH *dh; AES_KEY key; char *response = NULL; char *out_ptr, *ret = NULL; unsigned char *secret, *ptr; unsigned char *encrypted_userpass, *plain_userpass; int key_size, length; guint16 size16; unsigned char iv[16], iv_copy[16]; int user_len = strlen (user) + 1; int pass_len = strlen (pass) + 1; int len = user_len + pass_len; int padlen = 16 - (len % 16); int userpass_len = len + padlen; if (!parse_dh (data, &dh, &secret, &key_size)) return NULL; encrypted_userpass = (guchar*)malloc (userpass_len); memset (encrypted_userpass, 0, userpass_len); plain_userpass = (guchar*)malloc (userpass_len); memset (plain_userpass, 0, userpass_len); /* create message */ /* format of: \0\0 */ ptr = plain_userpass; memcpy (ptr, user, user_len); ptr += user_len; memcpy (ptr, pass, pass_len); ptr += pass_len; if (padlen) { /* Padding */ unsigned char randbytes[16]; if (!RAND_bytes (randbytes, padlen)) goto end; memcpy (ptr, randbytes, padlen); } if (!RAND_bytes (iv, sizeof (iv))) goto end; memcpy (iv_copy, iv, sizeof(iv)); /* Encrypt */ AES_set_encrypt_key (secret, key_size * 8, &key); AES_cbc_encrypt(plain_userpass, encrypted_userpass, userpass_len, &key, iv_copy, AES_ENCRYPT); /* Create response */ /* format of: */ length = 2 + key_size + sizeof(iv) + userpass_len; response = (char*)malloc (length); out_ptr = response; /* our key */ size16 = htons ((guint16)key_size); memcpy (out_ptr, &size16, sizeof(size16)); out_ptr += 2; BN_bn2bin (dh->pub_key, (guchar*)out_ptr); out_ptr += key_size; /* iv */ memcpy (out_ptr, iv, sizeof(iv)); out_ptr += sizeof(iv); /* userpass */ memcpy (out_ptr, encrypted_userpass, userpass_len); ret = g_base64_encode ((const guchar*)response, length); end: DH_free (dh); free (plain_userpass); free (encrypted_userpass); free (secret); if (response) free (response); return ret; } #endif #ifdef WIN32 int find_font (const char *fontname) { int i; int n_families; const char *family_name; PangoFontMap *fontmap; PangoFontFamily *family; PangoFontFamily **families; fontmap = pango_cairo_font_map_get_default (); pango_font_map_list_families (fontmap, &families, &n_families); for (i = 0; i < n_families; i++) { family = families[i]; family_name = pango_font_family_get_name (family); if (!g_ascii_strcasecmp (family_name, fontname)) { g_free (families); return 1; } } g_free (families); return 0; } #endif #ifdef USE_OPENSSL static char * str_sha256hash (char *string) { int i; unsigned char hash[SHA256_DIGEST_LENGTH]; char buf[SHA256_DIGEST_LENGTH * 2 + 1]; /* 64 digit hash + '\0' */ SHA256_CTX sha256; SHA256_Init (&sha256); SHA256_Update (&sha256, string, strlen (string)); SHA256_Final (hash, &sha256); for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { sprintf (buf + (i * 2), "%02x", hash[i]); } buf[SHA256_DIGEST_LENGTH * 2] = 0; return g_strdup (buf); } /** * \brief Generate CHALLENGEAUTH response for QuakeNet login. * * \param username QuakeNet user name * \param password password for the user * \param challenge the CHALLENGE response we got from Q * * After a successful connection to QuakeNet a CHALLENGE is requested from Q. * Generate the CHALLENGEAUTH response from this CHALLENGE and our user * credentials as per the * CHALLENGEAUTH * docs. As for using OpenSSL HMAC, see * example 1, * example 2. */ char * challengeauth_response (char *username, char *password, char *challenge) { int i; char *user; char *pass; char *passhash; char *key; char *keyhash; unsigned char *digest; GString *buf = g_string_new_len (NULL, SHA256_DIGEST_LENGTH * 2); user = g_strdup (username); *user = rfc_tolower (*username); /* convert username to lowercase as per the RFC */ pass = g_strndup (password, 10); /* truncate to 10 characters */ passhash = str_sha256hash (pass); g_free (pass); key = g_strdup_printf ("%s:%s", user, passhash); g_free (user); g_free (passhash); keyhash = str_sha256hash (key); g_free (key); digest = HMAC (EVP_sha256 (), keyhash, strlen (keyhash), (unsigned char *) challenge, strlen (challenge), NULL, NULL); g_free (keyhash); for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { g_string_append_printf (buf, "%02x", (unsigned int) digest[i]); } digest = (unsigned char *) g_string_free (buf, FALSE); return (char *) digest; } #endif