Geoip: Add an optional parameter in some natves to get a result in player's language.
This is new with Geoip2 database where some entries, like country, city, etc, are translated in several languages. So far: de, en, es, fr, ru, pt-BR, zh-CN.
This commit is contained in:
		@@ -1,4 +1,5 @@
 | 
				
			|||||||
<<<<<<< HEAD
 | 
					<<<<<<< HEAD
 | 
				
			||||||
 | 
					<<<<<<< HEAD
 | 
				
			||||||
// vim: set ts=4 sw=4 tw=99 noet:
 | 
					// vim: set ts=4 sw=4 tw=99 noet:
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
 | 
					// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO").
 | 
				
			||||||
@@ -12,9 +13,12 @@
 | 
				
			|||||||
// GeoIP Module
 | 
					// GeoIP Module
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "geoip_amxx.h"
 | 
					#include "geoip_amxx.h"
 | 
				
			||||||
 | 
					#include <am-string.h>
 | 
				
			||||||
 | 
					#include <am-vector.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MMDB_s HandleDB;
 | 
					MMDB_s HandleDB;
 | 
				
			||||||
 | 
					ke::Vector<ke::AString> LangList;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char *stripPort(char *ip)
 | 
					char *stripPort(char *ip)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -28,6 +32,33 @@ char *stripPort(char *ip)
 | 
				
			|||||||
	return ip;
 | 
						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)
 | 
					bool lookupByIp(const char *ip, const char **path, MMDB_entry_data_s *result)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int gai_error = 0, mmdb_error = 0;
 | 
						int gai_error = 0, mmdb_error = 0;
 | 
				
			||||||
@@ -118,6 +149,49 @@ int getContinentId(const char *code)
 | 
				
			|||||||
	return index;
 | 
						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]);
 | 
					// native geoip_code2(const ip[], ccode[3]);
 | 
				
			||||||
// Deprecated.
 | 
					// Deprecated.
 | 
				
			||||||
static cell AMX_NATIVE_CALL amx_geoip_code2(AMX *amx, cell *params)
 | 
					static cell AMX_NATIVE_CALL amx_geoip_code2(AMX *amx, cell *params)
 | 
				
			||||||
@@ -200,13 +274,13 @@ static cell AMX_NATIVE_CALL amx_geoip_code3_ex(AMX *amx, cell *params)
 | 
				
			|||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// native geoip_country(const ip[], result[], len);
 | 
					// native geoip_country(const ip[], result[], len, id = -1);
 | 
				
			||||||
static cell AMX_NATIVE_CALL amx_geoip_country(AMX *amx, cell *params)
 | 
					static cell AMX_NATIVE_CALL amx_geoip_country(AMX *amx, cell *params)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int length;
 | 
						int length;
 | 
				
			||||||
	char *ip = stripPort(MF_GetAmxString(amx, params[1], 0, &length));
 | 
						char *ip = stripPort(MF_GetAmxString(amx, params[1], 0, &length));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const char *path[] = { "country", "names", "en", NULL };
 | 
						const char *path[] = { "country", "names", getLang(params[4]), NULL };
 | 
				
			||||||
	const char *country = lookupString(ip, path, &length);
 | 
						const char *country = lookupString(ip, path, &length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!country)
 | 
						if (!country)
 | 
				
			||||||
@@ -217,13 +291,13 @@ static cell AMX_NATIVE_CALL amx_geoip_country(AMX *amx, cell *params)
 | 
				
			|||||||
	return MF_SetAmxString(amx, params[2], country, length >= params[3] ? params[3] : length); // TODO: make this utf8 safe.
 | 
						return MF_SetAmxString(amx, params[2], country, length >= params[3] ? params[3] : length); // TODO: make this utf8 safe.
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// native geoip_city(const ip[], result[], len);
 | 
					// native geoip_city(const ip[], result[], len, id = -1);
 | 
				
			||||||
static cell AMX_NATIVE_CALL amx_geoip_city(AMX *amx, cell *params)
 | 
					static cell AMX_NATIVE_CALL amx_geoip_city(AMX *amx, cell *params)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int length;
 | 
						int length;
 | 
				
			||||||
	char *ip = stripPort(MF_GetAmxString(amx, params[1], 0, &length));
 | 
						char *ip = stripPort(MF_GetAmxString(amx, params[1], 0, &length));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const char *path[] = { "city", "names", "en", NULL };
 | 
						const char *path[] = { "city", "names", getLang(params[4]), NULL };
 | 
				
			||||||
	const char *city = lookupString(ip, path, &length);
 | 
						const char *city = lookupString(ip, path, &length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return MF_SetAmxString(amx, params[2], city ? city : "", length >= params[3] ? params[3] : length); // TODO: make this utf8 safe.
 | 
						return MF_SetAmxString(amx, params[2], city ? city : "", length >= params[3] ? params[3] : length); // TODO: make this utf8 safe.
 | 
				
			||||||
@@ -263,13 +337,13 @@ static cell AMX_NATIVE_CALL amx_geoip_region_code(AMX *amx, cell *params)
 | 
				
			|||||||
	return MF_SetAmxString(amx, params[2], finalLength ? code : "", finalLength >= params[3] ? params[3] : finalLength);
 | 
						return MF_SetAmxString(amx, params[2], finalLength ? code : "", finalLength >= params[3] ? params[3] : finalLength);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// native geoip_region_name(const ip[], result[], len);
 | 
					// native geoip_region_name(const ip[], result[], len, id = -1);
 | 
				
			||||||
static cell AMX_NATIVE_CALL amx_geoip_region_name(AMX *amx, cell *params)
 | 
					static cell AMX_NATIVE_CALL amx_geoip_region_name(AMX *amx, cell *params)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int length;
 | 
						int length;
 | 
				
			||||||
	char *ip = stripPort(MF_GetAmxString(amx, params[1], 0, &length));
 | 
						char *ip = stripPort(MF_GetAmxString(amx, params[1], 0, &length));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const char *path[] = { "subdivisions", "0", "names", "en", NULL }; // First result.
 | 
						const char *path[] = { "subdivisions", "0", "names", getLang(params[4]), NULL }; // First result.
 | 
				
			||||||
	const char *region = lookupString(ip, path, &length);
 | 
						const char *region = lookupString(ip, path, &length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return MF_SetAmxString(amx, params[2], region ? region : "", length >= params[3] ? params[3] : length); // TODO: make this utf8 safe.
 | 
						return MF_SetAmxString(amx, params[2], region ? region : "", length >= params[3] ? params[3] : length); // TODO: make this utf8 safe.
 | 
				
			||||||
@@ -338,13 +412,13 @@ static cell AMX_NATIVE_CALL amx_geoip_continent_code(AMX *amx, cell *params)
 | 
				
			|||||||
	return getContinentId(code);
 | 
						return getContinentId(code);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// native geoip_continent_name(const ip[], result[], len);
 | 
					// native geoip_continent_name(const ip[], result[], len, id = -1);
 | 
				
			||||||
static cell AMX_NATIVE_CALL amx_geoip_continent_name(AMX *amx, cell *params)
 | 
					static cell AMX_NATIVE_CALL amx_geoip_continent_name(AMX *amx, cell *params)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int length;
 | 
						int length;
 | 
				
			||||||
	char *ip = stripPort(MF_GetAmxString(amx, params[1], 0, &length));
 | 
						char *ip = stripPort(MF_GetAmxString(amx, params[1], 0, &length));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const char *path[] = { "continent", "names", "en", NULL };
 | 
						const char *path[] = { "continent", "names", getLang(params[4]), NULL };
 | 
				
			||||||
	const char *continent = lookupString(ip, path, &length);
 | 
						const char *continent = lookupString(ip, path, &length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return MF_SetAmxString(amx, params[2], continent ? continent : "", length >= params[3] ? params[3] : length); // TODO: make this utf8 safe.
 | 
						return MF_SetAmxString(amx, params[2], continent ? continent : "", length >= params[3] ? params[3] : length); // TODO: make this utf8 safe.
 | 
				
			||||||
@@ -397,12 +471,20 @@ void OnAmxxAttach()
 | 
				
			|||||||
		HandleDB.metadata.binary_format_major_version,
 | 
							HandleDB.metadata.binary_format_major_version,
 | 
				
			||||||
		HandleDB.metadata.binary_format_minor_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);
 | 
						MF_AddNatives(geoip_natives);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void OnAmxxDetach()
 | 
					void OnAmxxDetach()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	MMDB_close(&HandleDB);
 | 
						MMDB_close(&HandleDB);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LangList.clear();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -78,8 +78,13 @@ native geoip_code3(const ip[], result[4]);
 | 
				
			|||||||
 * @param ip		The IP address to lookup.
 | 
					 * @param ip		The IP address to lookup.
 | 
				
			||||||
 * @param result	The result of the geoip lookup.
 | 
					 * @param result	The result of the geoip lookup.
 | 
				
			||||||
 * @param len		The maximum length of the result buffer.
 | 
					 * @param len		The maximum length of the result buffer.
 | 
				
			||||||
 | 
					 * @param id		An optional player's index in order to return the result 
 | 
				
			||||||
 | 
					 *                  in the player's language, if supported.
 | 
				
			||||||
 | 
					 *                  -1: the default language, which is english.
 | 
				
			||||||
 | 
					 *                   0: the server language. You can use LANG_SERVER define.
 | 
				
			||||||
 | 
					 *                 >=1: the player's language. 
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
native geoip_country(const ip[], result[], len=45);
 | 
					native geoip_country(const ip[], result[], len, id = -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -94,10 +99,15 @@ native geoip_country(const ip[], result[], len=45);
 | 
				
			|||||||
 * @param ip		The IP address to look up. 
 | 
					 * @param ip		The IP address to look up. 
 | 
				
			||||||
 * @param result	The result of the geoip look up. 
 | 
					 * @param result	The result of the geoip look up. 
 | 
				
			||||||
 * @param len		The maximum length of the result buffer.
 | 
					 * @param len		The maximum length of the result buffer.
 | 
				
			||||||
 | 
					 * @param id		An optional player's index in order to return the result 
 | 
				
			||||||
 | 
					 *                  in the player's language, if supported.
 | 
				
			||||||
 | 
					 *                  -1: the default language, which is english.
 | 
				
			||||||
 | 
					 *                   0: the server language. You can use LANG_SERVER define.
 | 
				
			||||||
 | 
					 *                 >=1: the player's language. 
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @return          The result length on successful lookup, 0 otherwise.
 | 
					 * @return          The result length on successful lookup, 0 otherwise.
 | 
				
			||||||
 */ 
 | 
					 */ 
 | 
				
			||||||
native geoip_city(const ip[], result[], len); 
 | 
					native geoip_city(const ip[], result[], len, id = -1); 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Look up the region/state code for the given IP address.
 | 
					 * Look up the region/state code for the given IP address.
 | 
				
			||||||
@@ -117,10 +127,15 @@ native geoip_region_code(const ip[], result[], len);
 | 
				
			|||||||
 * @param ip		The IP address to look up.
 | 
					 * @param ip		The IP address to look up.
 | 
				
			||||||
 * @param result	The result of the geoip look up.
 | 
					 * @param result	The result of the geoip look up.
 | 
				
			||||||
 * @param len		The maximum length of the result buffer.
 | 
					 * @param len		The maximum length of the result buffer.
 | 
				
			||||||
 | 
					 * @param id		An optional player's index in order to return the result 
 | 
				
			||||||
 | 
					 *                  in the player's language, if supported.
 | 
				
			||||||
 | 
					 *                  -1: the default language, which is english.
 | 
				
			||||||
 | 
					 *                   0: the server language. You can use LANG_SERVER define.
 | 
				
			||||||
 | 
					 *                 >=1: the player's language. 
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @return			The result length on successful lookup, 0 otherwise.
 | 
					 * @return			The result length on successful lookup, 0 otherwise.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
native geoip_region_name(const ip[], result[], len);
 | 
					native geoip_region_name(const ip[], result[], len, id = -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Look up the full time zone for the given IP address.
 | 
					 * Look up the full time zone for the given IP address.
 | 
				
			||||||
@@ -198,7 +213,12 @@ native Continent:geoip_continent_code(const ip[], result[3]);
 | 
				
			|||||||
 * @param ip		The IP address to look up.
 | 
					 * @param ip		The IP address to look up.
 | 
				
			||||||
 * @param result	The result of the geoip look up.
 | 
					 * @param result	The result of the geoip look up.
 | 
				
			||||||
 * @param len		The maximum length of the result buffer.
 | 
					 * @param len		The maximum length of the result buffer.
 | 
				
			||||||
 | 
					 * @param id		An optional player's index in order to return the result 
 | 
				
			||||||
 | 
					 *                  in the player's language, if supported.
 | 
				
			||||||
 | 
					 *                  -1: the default language, which is english.
 | 
				
			||||||
 | 
					 *                   0: the server language. You can use LANG_SERVER define.
 | 
				
			||||||
 | 
					 *                 >=1: the player's language. 
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @return			The result length on successful lookup, 0 otherwise.
 | 
					 * @return			The result length on successful lookup, 0 otherwise.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
native geoip_continent_name(const ip[], result[], len);
 | 
					native geoip_continent_name(const ip[], result[], len, id = -1);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user