diff --git a/dlls/geoip/AMBuilder b/dlls/geoip/AMBuilder index 715a32f2..3bc50513 100644 --- a/dlls/geoip/AMBuilder +++ b/dlls/geoip/AMBuilder @@ -10,7 +10,9 @@ binary.compiler.defines += [ binary.sources = [ 'sdk/amxxmodule.cpp', 'GeoIP2/maxminddb.cpp', - 'geoip_amxx.cpp', + 'geoip_main.cpp', + 'geoip_natives.cpp', + 'geoip_util.cpp', ] if builder.target_platform == 'windows': diff --git a/dlls/geoip/GeoIP2/maxminddb_config.h b/dlls/geoip/GeoIP2/maxminddb_config.h index 4c9f70eb..1a54c0e1 100644 --- a/dlls/geoip/GeoIP2/maxminddb_config.h +++ b/dlls/geoip/GeoIP2/maxminddb_config.h @@ -1,7 +1,7 @@ #ifndef MAXMINDDB_CONFIG_H #define MAXMINDDB_CONFIG_H -#define PACKAGE_VERSION "0.5.6" +#define PACKAGE_VERSION "0.5.6" // Arkshine: added manually. #ifndef MMDB_UINT128_USING_MODE /* Define as 1 if we we use unsigned int __atribute__ ((__mode__(TI))) for uint128 values */ diff --git a/dlls/geoip/Makefile b/dlls/geoip/Makefile index fce54680..01b27512 100755 --- a/dlls/geoip/Makefile +++ b/dlls/geoip/Makefile @@ -14,7 +14,7 @@ MM_ROOT = ../../../metamod/metamod PROJECT = geoip -OBJECTS = sdk/amxxmodule.cpp GeoIP.c geoip_amxx.cpp +OBJECTS = sdk/amxxmodule.cpp GeoIP2/maxminddb.cpp geoip_main.cpp geoip_natives.cpp geoip_util.cpp ############################################## ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### diff --git a/dlls/geoip/geoip_main.cpp b/dlls/geoip/geoip_main.cpp new file mode 100644 index 00000000..1477d350 --- /dev/null +++ b/dlls/geoip/geoip_main.cpp @@ -0,0 +1,108 @@ +/* Geoip + * Copyright 2007-2014 + * By the AMX Mod X Development Team + * + * Geoip 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. + * + * Geoip 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 Geoip; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of Ham Sandwich with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + */ +#include "geoip_main.h" +#include "geoip_natives.h" + +MMDB_s HandleDB; +ke::Vector LangList; + +void OnAmxxAttach() +{ + if (loadDatabase()) + { + MF_AddNatives(GeoipNatives); + } +} + +void OnAmxxDetach() +{ + MMDB_close(&HandleDB); + + LangList.clear(); +} + +bool loadDatabase() +{ + if (HandleDB.filename) // Already loaded. + { + return true; + } + + const char *databases[] = + { + "City", + "Country" // Is the default shipped database with AMXX. + }; + + const char *modName = MF_GetModname(); + const char *dataDir = MF_GetLocalInfo("amxx_datadir", "addons/amxmodx/data"); + + char file[255]; + int status = -1; + + for (size_t i = 0; i < ARRAYSIZE(databases); ++i) + { + snprintf(file, sizeof(file)-1, "%s/%s/GeoLite2-%s.mmdb", modName, dataDir, databases[i]); // MF_BuildPathname not used because backslash + // makes CreateFileMapping failing under windows. + status = MMDB_open(file, MMDB_MODE_MMAP, &HandleDB); + + if (status == MMDB_SUCCESS) + { + break; + } + else if (status != MMDB_FILE_OPEN_ERROR) + { + MF_Log("Could not open %s - %s", file, MMDB_strerror(status)); + + if (status == MMDB_IO_ERROR) + { + MF_Log(" IO error: %s", strerror(errno)); + } + } + } + + if (status != MMDB_SUCCESS) + { + MF_Log("Could not find GeoIP2 databases. Disabled natives."); + return false; + } + + MF_Log("Database info: %s %i.%i", + HandleDB.metadata.description.descriptions[0]->description, + HandleDB.metadata.binary_format_major_version, + HandleDB.metadata.binary_format_minor_version); + + // Retrieve supported languages. + for (size_t i = 0; i < HandleDB.metadata.languages.count; i++) + { + LangList.append(ke::AString(HandleDB.metadata.languages.names[i])); + } + + return true; +} diff --git a/dlls/geoip/geoip_main.h b/dlls/geoip/geoip_main.h new file mode 100644 index 00000000..e9da1f07 --- /dev/null +++ b/dlls/geoip/geoip_main.h @@ -0,0 +1,37 @@ +/* Geoip + * Copyright 2007-2014 + * By the AMX Mod X Development Team + * + * Geoip 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. + * + * Geoip 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 Geoip; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of Ham Sandwich with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + */ +#ifndef _INCLUDE_GEOIPMAIN_H +#define _INCLUDE_GEOIPMAIN_H + +#include "GeoIP2/maxminddb.h" +#include "amxxmodule.h" + +bool loadDatabase(); + +#endif // _INCLUDE_GEOIPMAIN_H \ No newline at end of file diff --git a/dlls/geoip/geoip_amxx.cpp b/dlls/geoip/geoip_natives.cpp similarity index 70% rename from dlls/geoip/geoip_amxx.cpp rename to dlls/geoip/geoip_natives.cpp index cda14490..7a6bea6d 100755 --- a/dlls/geoip/geoip_amxx.cpp +++ b/dlls/geoip/geoip_natives.cpp @@ -1,5 +1,3 @@ -<<<<<<< HEAD -<<<<<<< HEAD // vim: set ts=4 sw=4 tw=99 noet: // // AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). @@ -13,189 +11,13 @@ // GeoIP Module // -#include "geoip_amxx.h" +#include "geoip_main.h" +#include "geoip_natives.h" +#include "geoip_util.h" + #include #include -MMDB_s HandleDB; -ke::Vector LangList; - -char *stripPort(char *ip) -{ - char *tmp = strchr(ip, ':'); - - if (tmp) - { - *tmp = '\0'; - } - - return ip; -} - -const char* stristr(const char* str, const char* substr) -{ - register char *needle = (char *)substr; - register char *prevloc = (char *)str; - register char *haystack = (char *)str; - - while (*haystack) - { - if (tolower(*haystack) == tolower(*needle)) - { - haystack++; - - if (!*++needle) - { - return prevloc; - } - } - else - { - haystack = ++prevloc; - needle = (char *)substr; - } - } - - return NULL; -} - -bool lookupByIp(const char *ip, const char **path, MMDB_entry_data_s *result) -{ - int gai_error = 0, mmdb_error = 0; - MMDB_lookup_result_s lookup = MMDB_lookup_string(&HandleDB, ip, &gai_error, &mmdb_error); - - if (gai_error != 0 || MMDB_SUCCESS != mmdb_error || !lookup.found_entry) - { - return false; - } - - MMDB_entry_data_s entry_data; - MMDB_aget_value(&lookup.entry, &entry_data, path); - - if (!entry_data.has_data) - { - return false; - } - - *result = entry_data; - - return true; -} - -const char *lookupString(const char *ip, const char **path, int *length = NULL) -{ - static char buffer[256]; // This should be large enough for long name in UTF-8. - MMDB_entry_data_s result; - - if (!lookupByIp(ip, path, &result)) - { - return NULL; - } - - // Let's avoid a crash in case we go over the buffer size. - size_t maxLength = ke::Min(result.data_size, sizeof(buffer)); - - // Strings from database are not null terminated. - memcpy(buffer, result.utf8_string, maxLength); - buffer[result.data_size] = '\0'; - - if (length) - { - *length = maxLength; - } - - return buffer; -} - -double lookupDouble(const char *ip, const char **path) -{ - MMDB_entry_data_s result; - - if (!lookupByIp(ip, path, &result)) - { - return NULL; - } - - return result.double_value; -} - -int getContinentId(const char *code) -{ - #define CONTINENT_UNKNOWN 0 - #define CONTINENT_AFRICA 1 - #define CONTINENT_ASIA 2 - #define CONTINENT_EUROPE 3 - #define CONTINENT_NORTH_AMERICA 4 - #define CONTINENT_OCEANIA 5 - #define CONTINENT_SOUTH_AMERICA 6 - - int index = CONTINENT_UNKNOWN; - - if (code) - { - switch (code[0]) - { - case 'A': - { - switch (code[1]) - { - case 'F': index = CONTINENT_AFRICA; break; - case 'S': index = CONTINENT_ASIA; break; - } - } - case 'E': index = CONTINENT_EUROPE; break; - case 'O': index = CONTINENT_OCEANIA; break; - case 'N': index = CONTINENT_NORTH_AMERICA; break; - case 'S': index = CONTINENT_SOUTH_AMERICA; break; - } - } - - return index; -} - -const char *getLang(int playerIndex) -{ - static cvar_t *amxmodx_language = NULL; - static cvar_t *amxmodx_cl_langs = NULL; - - if (!amxmodx_language) - amxmodx_language = CVAR_GET_POINTER("amx_language"); - - if (!amxmodx_cl_langs) - amxmodx_cl_langs = CVAR_GET_POINTER("amx_client_languages"); - - if (playerIndex >= 0 && amxmodx_cl_langs && amxmodx_language) - { - const char *value; - const char *lang; - - if (playerIndex == 0 || amxmodx_cl_langs->value <= 0 || !MF_IsPlayerIngame(playerIndex)) - { - value = amxmodx_language->string; - } - else - { - value = ENTITY_KEYVALUE(MF_GetPlayerEdict(playerIndex), "lang"); - } - - if (value && *value) - { - for (size_t i = 0; i < LangList.length(); ++i) - { - lang = LangList.at(i).chars(); - - if (stristr(lang, value) != NULL) - { - return lang; - } - } - } - } - - return "en"; -} - - // native geoip_code2(const ip[], ccode[3]); // Deprecated. static cell AMX_NATIVE_CALL amx_geoip_code2(AMX *amx, cell *params) @@ -429,70 +251,7 @@ static cell AMX_NATIVE_CALL amx_geoip_continent_name(AMX *amx, cell *params) } -void OnAmxxAttach() -{ - const char *databases[] = - { - "City", - "Country" // is the default shipped database with AMXX. - }; - - const char *modName = MF_GetModname(); - const char *dataDir = MF_GetLocalInfo("amxx_datadir", "addons/amxmodx/data"); - - char file[255]; - int status = -1; - - for (size_t i = 0; i < ARRAYSIZE(databases); ++i) - { - sprintf(file, "%s/%s/GeoLite2-%s.mmdb", modName, dataDir, databases[i]); // MF_BuildPathname not used because backslash - // makes CreateFileMapping failing under windows. - status = MMDB_open(file, MMDB_MODE_MMAP, &HandleDB); - - if (status == MMDB_SUCCESS) - { - break; - } - else if (status != MMDB_FILE_OPEN_ERROR) - { - MF_Log("Could not open %s - %s", file, MMDB_strerror(status)); - - if (status == MMDB_IO_ERROR) - { - MF_Log(" IO error: %s", strerror(errno)); - } - } - } - - if (status != MMDB_SUCCESS) - { - MF_Log("Could not find GeoIP2 databases. Disabled natives."); - return; - } - - MF_Log("Database info: %s %i.%i", - HandleDB.metadata.description.descriptions[0]->description, - HandleDB.metadata.binary_format_major_version, - HandleDB.metadata.binary_format_minor_version); - - // Retrieve supported languages. - for (size_t i = 0; i < HandleDB.metadata.languages.count; i++) - { - LangList.append(ke::AString(HandleDB.metadata.languages.names[i])); - } - - MF_AddNatives(geoip_natives); -} - -void OnAmxxDetach() -{ - MMDB_close(&HandleDB); - - LangList.clear(); -} - - -AMX_NATIVE_INFO geoip_natives[] = +AMX_NATIVE_INFO GeoipNatives[] = { { "geoip_code2", amx_geoip_code2 }, { "geoip_code3", amx_geoip_code3 }, diff --git a/dlls/geoip/geoip_natives.h b/dlls/geoip/geoip_natives.h new file mode 100644 index 00000000..4f31be0f --- /dev/null +++ b/dlls/geoip/geoip_natives.h @@ -0,0 +1,39 @@ +/* Geoip + * Copyright 2007-2014 + * By the AMX Mod X Development Team + * + * Geoip 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. + * + * Geoip 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 Geoip; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of Ham Sandwich with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + */ +#ifndef _INCLUDE_GEOIPNATIVES_H +#define _INCLUDE_GEOIPNATIVES_H + +#include +#include + +extern MMDB_s HandleDB; +extern ke::Vector LangList; +extern AMX_NATIVE_INFO GeoipNatives[]; + +#endif // _INCLUDE_GEOIPNATIVES_H diff --git a/dlls/geoip/geoip_util.cpp b/dlls/geoip/geoip_util.cpp new file mode 100644 index 00000000..41a8de4a --- /dev/null +++ b/dlls/geoip/geoip_util.cpp @@ -0,0 +1,205 @@ +/* Geoip + * Copyright 2007-2014 + * By the AMX Mod X Development Team + * + * Geoip 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. + * + * Geoip 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 Geoip; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of Ham Sandwich with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + */ +#include "geoip_util.h" +#include "geoip_natives.h" + +char *stripPort(char *ip) +{ + char *tmp = strchr(ip, ':'); + + if (tmp) + { + *tmp = '\0'; + } + + return ip; +} + +const char* stristr(const char* str, const char* substr) +{ + register char *needle = (char *)substr; + register char *prevloc = (char *)str; + register char *haystack = (char *)str; + + while (*haystack) + { + if (tolower(*haystack) == tolower(*needle)) + { + haystack++; + + if (!*++needle) + { + return prevloc; + } + } + else + { + haystack = ++prevloc; + needle = (char *)substr; + } + } + + return NULL; +} + +bool lookupByIp(const char *ip, const char **path, MMDB_entry_data_s *result) +{ + int gai_error = 0, mmdb_error = 0; + MMDB_lookup_result_s lookup = MMDB_lookup_string(&HandleDB, ip, &gai_error, &mmdb_error); + + if (gai_error != 0 || MMDB_SUCCESS != mmdb_error || !lookup.found_entry) + { + return false; + } + + MMDB_entry_data_s entry_data; + MMDB_aget_value(&lookup.entry, &entry_data, path); + + if (!entry_data.has_data) + { + return false; + } + + *result = entry_data; + + return true; +} + +const char *lookupString(const char *ip, const char **path, int *length) +{ + static char buffer[256]; // This should be large enough for long name in UTF-8. + MMDB_entry_data_s result; + + if (!lookupByIp(ip, path, &result)) + { + return NULL; + } + + // Let's avoid a crash in case we go over the buffer size. + size_t maxLength = ke::Min((size_t)result.data_size, sizeof(buffer)); + + // Strings from database are not null terminated. + memcpy(buffer, result.utf8_string, maxLength); + buffer[result.data_size] = '\0'; + + if (length) + { + *length = maxLength; + } + + return buffer; +} + +double lookupDouble(const char *ip, const char **path) +{ + MMDB_entry_data_s result; + + if (!lookupByIp(ip, path, &result)) + { + return 0; + } + + return result.double_value; +} + +int getContinentId(const char *code) +{ + #define CONTINENT_UNKNOWN 0 + #define CONTINENT_AFRICA 1 + #define CONTINENT_ASIA 2 + #define CONTINENT_EUROPE 3 + #define CONTINENT_NORTH_AMERICA 4 + #define CONTINENT_OCEANIA 5 + #define CONTINENT_SOUTH_AMERICA 6 + + int index = CONTINENT_UNKNOWN; + + if (code) + { + switch (code[0]) + { + case 'A': + { + switch (code[1]) + { + case 'F': index = CONTINENT_AFRICA; break; + case 'S': index = CONTINENT_ASIA; break; + } + } + case 'E': index = CONTINENT_EUROPE; break; + case 'O': index = CONTINENT_OCEANIA; break; + case 'N': index = CONTINENT_NORTH_AMERICA; break; + case 'S': index = CONTINENT_SOUTH_AMERICA; break; + } + } + + return index; +} + +const char *getLang(int playerIndex) +{ + static cvar_t *amxmodx_language = NULL; + static cvar_t *amxmodx_cl_langs = NULL; + + if (!amxmodx_language) + amxmodx_language = CVAR_GET_POINTER("amx_language"); + + if (!amxmodx_cl_langs) + amxmodx_cl_langs = CVAR_GET_POINTER("amx_client_languages"); + + if (playerIndex >= 0 && amxmodx_cl_langs && amxmodx_language) + { + const char *value; + const char *lang; + + if (playerIndex == 0 || amxmodx_cl_langs->value <= 0 || !MF_IsPlayerIngame(playerIndex)) + { + value = amxmodx_language->string; + } + else + { + value = ENTITY_KEYVALUE(MF_GetPlayerEdict(playerIndex), "lang"); + } + + if (value && *value) + { + for (size_t i = 0; i < LangList.length(); ++i) + { + lang = LangList.at(i).chars(); + + if (stristr(lang, value) != NULL) + { + return lang; + } + } + } + } + + return "en"; +} diff --git a/dlls/geoip/geoip_util.h b/dlls/geoip/geoip_util.h new file mode 100644 index 00000000..54ee61d7 --- /dev/null +++ b/dlls/geoip/geoip_util.h @@ -0,0 +1,49 @@ +/* Geoip + * Copyright 2007-2014 + * By the AMX Mod X Development Team + * + * Geoip 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. + * + * Geoip 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 Geoip; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * In addition, as a special exception, the author gives permission to + * link the code of Ham Sandwich with the Half-Life Game Engine ("HL + * Engine") and Modified Game Libraries ("MODs") developed by Valve, + * L.L.C ("Valve"). You must obey the GNU General Public License in all + * respects for all of the code used other than the HL Engine and MODs + * from Valve. If you modify this file, you may extend this exception + * to your version of the file, but you are not obligated to do so. If + * you do not wish to do so, delete this exception statement from your + * version. + */ +#ifndef _INCLUDE_GEOIPUTIL_H +#define _INCLUDE_GEOIPUTIL_H + +#include "geoip_main.h" + +#if defined(WIN32) + #define snprintf _snprintf +#endif + +char *stripPort(char *ip); + +bool lookupByIp(const char *ip, const char **path, MMDB_entry_data_s *result); +double lookupDouble(const char *ip, const char **path); +const char *lookupString(const char *ip, const char **path, int *length = NULL); + +int getContinentId(const char *code); +const char *getLang(int playerIndex); + +const char* stristr(const char* str, const char* substr); + +#endif // _INCLUDE_GEOIPUTIL_H