summaryrefslogtreecommitdiff
path: root/src/char
diff options
context:
space:
mode:
authorpanikon <panikon@zoho.com>2014-05-06 21:14:46 -0300
committerpanikon <panikon@zoho.com>2014-05-06 21:14:46 -0300
commit9a425c11b61fb6f4e299013c7d8d9841129b8f45 (patch)
treeb8e8bc56c6e51679c23fe2de0e268f49b29f7288 /src/char
parent9cf6b362a0d5e2f52c017d747c0fa8f69a1a273f (diff)
downloadhercules-9a425c11b61fb6f4e299013c7d8d9841129b8f45.tar.gz
hercules-9a425c11b61fb6f4e299013c7d8d9841129b8f45.tar.bz2
hercules-9a425c11b61fb6f4e299013c7d8d9841129b8f45.tar.xz
hercules-9a425c11b61fb6f4e299013c7d8d9841129b8f45.zip
Bug fixes and other changes
#Fixed issue where a corrupted map cache would lead to a crash *Moved Big-endian compatibility functions to common/utils.h #Fixed issue 8162 *http://hercules.ws/board/tracker/issue-8162-loadnpc-doesnt-trigger-oninit-of-duplicate-npcs/ *Added options to npc_parse_duplicate #Fixed issue 8169 *http://hercules.ws/board/tracker/issue-8169-script-command-guildskill-skill-idlevel-not-working-as-intended/ *Changed *guildskill behavior, now it behaves exactly as depicted in the documentation *Updated *guildskill documentation #Added missing GBI types to mapif_parse_GuildBasicInfoChange now it's possible to change guild exp, lv, skill point and skill information #GeoIP revamp *GeoIP module was partially rewritten *Added several data checks to prevent corruption and crashes *Updated GeoIP database *See https://github.com/maxmind/geoip-api-c/blob/master/libGeoIP/GeoIP.c for more information #Added packetver checks regarding NST_MARKET *Now *tradertype warns if user is trying to use this feature with older clients
Diffstat (limited to 'src/char')
-rw-r--r--src/char/int_guild.c50
-rw-r--r--src/char/inter.c119
2 files changed, 144 insertions, 25 deletions
diff --git a/src/char/int_guild.c b/src/char/int_guild.c
index 28b803027..d8556f023 100644
--- a/src/char/int_guild.c
+++ b/src/char/int_guild.c
@@ -1421,29 +1421,61 @@ int mapif_parse_GuildMessage(int fd,int guild_id,int account_id,char *mes,int le
return mapif_guild_message(guild_id,account_id,mes,len, fd);
}
-// Modification of the guild
+/**
+ * Changes basic guild information
+ * The types are available in mmo.h::guild_basic_info
+ **/
int mapif_parse_GuildBasicInfoChange(int fd, int guild_id, int type, const void *data, int len) {
struct guild *g;
- short value = *((const int16 *)data);
+ struct guild_skill gd_skill;
+ short value;
g = inter_guild_fromsql(guild_id);
- if(g==NULL)
+
+ if( g == NULL )
return 0;
switch(type) {
+ case GBI_EXP:
+ value = *((const int16 *)data);
+ if( g->exp+value < 0 )
+ return 0;
+ g->exp += value;
+ guild_calcinfo(g);
+ break;
+
case GBI_GUILDLV:
+ value = *((const int16 *)data);
if (value > 0 && g->guild_lv + value <= MAX_GUILDLEVEL) {
g->guild_lv += value;
g->skill_point += value;
} else if (value < 0 && g->guild_lv + value >= 1)
g->guild_lv += value;
- mapif_guild_info(-1,g);
- g->save_flag |= GS_LEVEL;
- return 0;
- default:
- ShowError("int_guild: GuildBasicInfoChange: Unknown type %d\n",type);
break;
+
+ case GBI_SKILLPOINT:
+ value = *((const int16 *)data);
+ if( g->skill_point+value < 0 )
+ return 0;
+ g->skill_point += value;
+ break;
+
+ case GBI_SKILLLV:
+ gd_skill = *((const struct guild_skill*)data);
+ memcpy(&(g->skill[(gd_skill.id - GD_SKILLBASE)]), &gd_skill, sizeof(gd_skill));
+ if( !guild_calcinfo(g) )
+ mapif_guild_info(-1,g);
+ g->save_flag |= GS_SKILL;
+ mapif_guild_skillupack(g->guild_id, gd_skill.id, 0);
+ break;
+
+ default:
+ ShowError("int_guild: GuildBasicInfoChange: Unknown type %d, see mmo.h::guild_basic_info for more information\n",type);
+ return 0;
}
- mapif_guild_basicinfochanged(guild_id,type,data,len);
+ mapif_guild_info(-1,g);
+ g->save_flag |= GS_LEVEL;
+ // Information is already sent in mapif_guild_info
+ //mapif_guild_basicinfochanged(guild_id,type,data,len);
return 0;
}
diff --git a/src/char/inter.c b/src/char/inter.c
index 6a8412b25..a2ff556d9 100644
--- a/src/char/inter.c
+++ b/src/char/inter.c
@@ -370,7 +370,11 @@ const char* job_name(int class_) {
}
/* [Dekamaster/Nightroad] */
-const char * geoip_countryname[253] = {"Unknown","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Netherlands Antilles",
+#define GEOIP_MAX_COUNTRIES 255
+#define GEOIP_STRUCTURE_INFO_MAX_SIZE 20
+#define GEOIP_COUNTRY_BEGIN 16776960
+
+const char * geoip_countryname[GEOIP_MAX_COUNTRIES] = {"Unknown","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Netherlands Antilles",
"Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados",
"Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia",
"Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the",
@@ -395,17 +399,15 @@ const char * geoip_countryname[253] = {"Unknown","Asia/Pacific Region","Europe",
"Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines","Venezuela",
"Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa",
"Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey",
- "Saint Barthelemy","Saint Martin"};
-unsigned char *geoip_cache;
-void geoip_readdb(void){
- struct stat bufa;
- FILE *db=fopen("./db/GeoIP.dat","rb");
- fstat(fileno(db), &bufa);
- geoip_cache = (unsigned char *) malloc(sizeof(unsigned char) * bufa.st_size);
- if(fread(geoip_cache, sizeof(unsigned char), bufa.st_size, db) != bufa.st_size) { ShowError("geoip_cache reading didn't read all elements \n"); }
- fclose(db);
- ShowStatus("Finished Reading "CL_GREEN"GeoIP"CL_RESET" Database.\n");
-}
+ "Saint Barthelemy", "Saint Martin", "Bonaire, Saint Eustatius and Saba", "South Sudan"};
+/**
+ * GeoIP information
+ **/
+struct s_geoip {
+ unsigned char *cache; // GeoIP.dat information see geoip_init()
+ bool active;
+} geoip;
+
/* [Dekamaster/Nightroad] */
/* WHY NOT A DBMAP: There are millions of entries in GeoIP and it has its own algorithm to go quickly through them, a DBMap wouldn't be efficient */
const char* geoip_getcountry(uint32 ipnum){
@@ -414,8 +416,11 @@ const char* geoip_getcountry(uint32 ipnum){
const unsigned char *buf;
unsigned int offset = 0;
+ if( geoip.active == false )
+ return geoip_countryname[0];
+
for (depth = 31; depth >= 0; depth--) {
- buf = geoip_cache + (long)6 *offset;
+ buf = geoip.cache + (long)6 *offset;
if (ipnum & (1 << depth)) {
/* Take the right-hand branch */
x = (buf[3*1 + 0] << (0*8))
@@ -427,16 +432,97 @@ const char* geoip_getcountry(uint32 ipnum){
+ (buf[3*0 + 1] << (1*8))
+ (buf[3*0 + 2] << (2*8));
}
- if (x >= 16776960) {
- x=x-16776960;
+ if (x >= GEOIP_COUNTRY_BEGIN) {
+ x = x-GEOIP_COUNTRY_BEGIN;
+
+ if( x > GEOIP_MAX_COUNTRIES )
+ return geoip_countryname[0];
+
return geoip_countryname[x];
}
offset = x;
}
+ ShowError("geoip_getcountry(): Error traversing database for ipnum %d\n", ipnum);
+ ShowWarning("geoip_getcountry(): Possible database corruption!\n");
+
return geoip_countryname[0];
}
/**
+ * Disables GeoIP
+ * frees geoip.cache
+ **/
+void geoip_final( void ) {
+ if( geoip.cache )
+ aFree(geoip.cache);
+
+ if( geoip.active ) {
+ ShowStatus("GeoIP "CL_RED"disabled"CL_RESET".\n");
+ geoip.active = false;
+ }
+}
+
+/**
+ * Reads GeoIP database and stores it into memory
+ * geoip.cache should be freed after use!
+ * http://dev.maxmind.com/geoip/legacy/geolite/
+ **/
+void geoip_init(void) {
+ int i, fno;
+ char db_type = 1;
+ unsigned char delim[3];
+ struct stat bufa;
+ FILE *db;
+
+ geoip.active = true;
+
+ db = fopen("./db/GeoIP.dat","rb");
+ if( db == NULL ) {
+ ShowError("geoip_readdb: Error reading GeoIP.dat!\n");
+ geoip_final();
+ return;
+ }
+ fno = fileno(db);
+ if( fstat(fno, &bufa) < 0 ) {
+ ShowError("geoip_readdb: Error stating GeoIP.dat! Error %d\n", errno);
+ geoip_final();
+ return;
+ }
+ geoip.cache = aMalloc( (sizeof(geoip.cache) * bufa.st_size) );
+ if( fread(geoip.cache, sizeof(unsigned char), bufa.st_size, db) != bufa.st_size ) {
+ ShowError("geoip_cache: Couldn't read all elements!\n");
+ fclose(db);
+ geoip_final();
+ return;
+ }
+
+ // Search database type
+ lseek(fno, -3l, SEEK_END);
+ for( i = 0; i < GEOIP_STRUCTURE_INFO_MAX_SIZE; i++ ) {
+ read(fno, delim, 3);
+ if( delim[0] == 255 && delim[1] == 255 && delim[2] == 255 ) {
+ read(fno, &db_type, 1);
+ break;
+ } else {
+ lseek(fno, -4l, SEEK_CUR);
+ }
+ }
+
+ fclose(db);
+
+ if( db_type != 1 ) {
+ if( db_type )
+ ShowError("geoip_init(): Database type is not supported %d!\n", db_type);
+ else
+ ShowError("geoip_init(): GeoIP is corrupted!\n");
+
+ geoip_final();
+ return;
+ }
+ ShowStatus("Finished Reading "CL_GREEN"GeoIP"CL_RESET" Database.\n");
+}
+
+/**
* Argument-list version of inter_msg_to_fd
* @see inter_msg_to_fd
*/
@@ -934,7 +1020,7 @@ int inter_init_sql(const char *file)
inter_mail_sql_init();
inter_auction_sql_init();
- geoip_readdb();
+ geoip_init();
msg_config_read("conf/messages.conf", false);
return 0;
}
@@ -954,6 +1040,7 @@ void inter_final(void)
inter_mail_sql_final();
inter_auction_sql_final();
+ geoip_final();
do_final_msg();
return;
}