Bläddra i källkod

"Beautified" login-server

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@430 54d463be-8e91-2dee-dedb-b68131a5f0ec
wizputer 20 år sedan
förälder
incheckning
b6a5e2df73

+ 3 - 0
Changelog.txt

@@ -1,4 +1,7 @@
 Date	Added
+11/30
+	* "Beautified" sql login-server [Wizputer]
+
 11/28
         * Updated packet_ver_flag's default value, thanks to iscandium
         * Updated Finger Offensive, thanks to orn

+ 9 - 1
Makefile

@@ -1,7 +1,12 @@
 # $Id: Makefile 158 2004-10-01 03:45:15Z PoW $
 
 CC = gcc -pipe
+
+ifdef DEBUG
+PACKETDEF = -DPACKETVER=6 -DNEW_006b -DSO_REUSEPORT -DDEBUG
+else
 PACKETDEF = -DPACKETVER=6 -DNEW_006b -DSO_REUSEPORT
+endif
 #PACKETDEF = -DPACKETVER=5 -DNEW_006b
 #PACKETDEF = -DPACKETVER=4 -DNEW_006b
 #PACKETDEF = -DPACKETVER=3 -DNEW_006b
@@ -92,6 +97,9 @@ sql:
 	$(MAKE) CC="$(CC)" OPT="$(OPT)" SQLFLAG=1 $@
 endif
 
+debug-sql:
+	$(MAKE) CC="$(CC)" OPT="$(OPT)" DEBUG=1 sql
+
 clean: src/common/GNUmakefile src/login/GNUmakefile src/char/GNUmakefile src/map/GNUmakefile src/ladmin/GNUmakefile src/txt-converter/login/GNUmakefile src/txt-converter/char/GNUmakefile
 	cd src ; cd common ; $(MAKE) $(MKDEF) $@ ; cd ..
 	cd src ; cd login ; $(MAKE) $(MKDEF) $@ ; cd ..
@@ -105,7 +113,7 @@ clean: src/common/GNUmakefile src/login/GNUmakefile src/char/GNUmakefile src/map
 
 tools:
 	cd tool && $(MAKE) $(MKDEF) && cd ..
-	$(CC) -o setupwizard setupwizard.c	
+	$(CC) -o setupwizard setupwizard.c
 
 src/common/GNUmakefile: src/common/Makefile
 	sed -e 's/$$>/$$^/' src/common/Makefile > src/common/GNUmakefile

+ 5 - 4
src/login_sql/GNUmakefile

@@ -5,13 +5,14 @@ shared_libs=all
 COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/malloc.o ../common/showmsg.o
 COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/db.h ../common/malloc.h ../common/showmsg.h
 
-login-server_sql: login.o md5calc.o strlib.o $(COMMON_OBJ)
+login-server_sql: login.o char_int.o login_int.o md5calc.o strlib.o $(COMMON_OBJ)
 	$(CC) -o ../../$@ $^ $(LIB_S)
 
-login.o: login.c login.h md5calc.h strlib.h $(COMMON_H)
+login.o: login.c login.h md5calc.h strlib.h char_int.h login_int.h $(COMMON_H)
+char_int.o: char_int.c login.h char_int.h $(COMMON_H)
+login_int.o: login_int.c login.h login_int.h char_int.h $(COMMON_H)
 md5calc.o: md5calc.c md5calc.h
 strlib.o: strlib.c strlib.h
 
 clean:
-	rm -f *.o ../../login-server_sql
-
+	rm -f *.o ../../login-server_sql

+ 5 - 4
src/login_sql/Makefile

@@ -5,13 +5,14 @@ shared_libs=all
 COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/malloc.o ../common/showmsg.o
 COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/db.h ../common/malloc.h ../common/showmsg.h
 
-login-server_sql: login.o md5calc.o strlib.o $(COMMON_OBJ)
+login-server_sql: login.o char_int.o login_int.o md5calc.o strlib.o $(COMMON_OBJ)
 	$(CC) -o ../../$@ $^ $(LIB_S)
 
-login.o: login.c login.h md5calc.h strlib.h $(COMMON_H)
+login.o: login.c login.h md5calc.h strlib.h char_int.h login_int.h $(COMMON_H)
+char_int.o: char_int.c login.h char_int.h $(COMMON_H)
+login_int.o: login_int.c login.h login_int.h char_int.h $(COMMON_H)
 md5calc.o: md5calc.c md5calc.h
 strlib.o: strlib.c strlib.h
 
 clean:
-	rm -f *.o ../../login-server_sql
-
+	rm -f *.o ../../login-server_sql

+ 512 - 0
src/login_sql/char_int.c

@@ -0,0 +1,512 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include "login.h"
+
+//--------------------------------
+// Send to char
+//--------------------------------
+int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len) {
+	int i, c;
+	int fd;
+
+	c = 0;
+	for(i = 0; i < MAX_SERVERS; i++) {
+		if ((fd = server_fd[i]) > 0 && fd != sfd) {
+			memcpy(WFIFOP(fd,0), buf, len);
+			WFIFOSET(fd,len);
+			c++;
+		}
+	}
+
+	return c;
+}
+
+//--------------------------------
+// Char-server anti-freeze system
+//--------------------------------
+int char_anti_freeze_system(int tid, unsigned int tick, int id, int data) {
+	int i;
+
+	for(i = 0; i < MAX_SERVERS; i++) {
+		if (server_fd[i] >= 0) {// if char-server is online
+//			printf("char_anti_freeze_system: server #%d '%s', flag: %d.\n", i, server[i].name, server_freezeflag[i]);
+			if (server_freezeflag[i]-- < 1) {// Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed
+				session[server_fd[i]]->eof = 1;
+			}
+		}
+	}
+
+	return 0;
+}
+
+//-------------------------------------------
+// Request for account reg from char-server [Edit: Wizputer]
+//-------------------------------------------
+void send_account_reg(int fd) {
+    int account_id = RFIFOL(fd,2);
+    int i;
+			
+    for(i=0;i<AUTH_FIFO_SIZE;i++){
+        if (auth_fifo[i].account_id == account_id &&
+		    auth_fifo[i].login_id1 == RFIFOL(fd,6) &&
+#if CMP_AUTHFIFO_LOGIN2 != 0
+		    auth_fifo[i].login_id2 == RFIFOL(fd,10) && // relate to the versions higher than 18 
+#endif
+		    auth_fifo[i].sex == RFIFOB(fd,14) &&
+#if CMP_AUTHFIFO_IP != 0
+		    auth_fifo[i].ip == RFIFOL(fd,15) &&
+#endif
+		    !auth_fifo[i].delflag) {
+				auth_fifo[i].delflag = 1;
+				#ifdef DEBUG
+				printf("Client: [%d] Auth Number: [%d]\n",fd, i);
+				#endif
+				break;
+		}
+	}
+
+	if (i != AUTH_FIFO_SIZE) { // send account_reg
+		int p;
+		time_t connect_until_time = 0;
+		char email[40] = "";
+
+		sprintf(tmpsql, "SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'", login_db, login_db_account_id, account_id);
+		sql_query(tmpsql,"send_account_reg");
+		sql_res = mysql_store_result(&mysql_handle) ;
+		
+        if (sql_res) {
+			sql_row = mysql_fetch_row(sql_res);
+			connect_until_time = atol(sql_row[1]);
+			strcpy(email, sql_row[0]);
+		}
+		mysql_free_result(sql_res);
+		
+		if (account_id > 0) {
+			sprintf(tmpsql, "SELECT `str`,`value` FROM `global_reg_value` WHERE `type`='1' AND `account_id`='%d'",account_id);
+			sql_query(tmpsql,"send_account_reg");
+			sql_res = mysql_store_result(&mysql_handle) ;
+			
+            if (sql_res) {
+				WFIFOW(fd,0) = 0x2729;
+				WFIFOL(fd,4) = account_id;
+				for(p = 8; (sql_row = mysql_fetch_row(sql_res));p+=36){
+					memcpy(WFIFOP(fd,p), sql_row[0], 32);
+					WFIFOL(fd,p+32) = atoi(sql_row[1]);
+				}
+				WFIFOW(fd,2) = p;
+				WFIFOSET(fd,p);
+				#ifdef DEBUG
+				printf("account_reg2 send : login->char (auth fifo)\n");
+				#endif
+				WFIFOW(fd,0) = 0x2713;
+				WFIFOL(fd,2) = account_id;
+				WFIFOB(fd,6) = 0;
+				memcpy(WFIFOP(fd, 7), email, 40);
+				WFIFOL(fd,47) = (unsigned long) connect_until_time;
+				WFIFOSET(fd,51);
+			}
+			mysql_free_result(sql_res);
+		}
+	} else {
+		WFIFOW(fd,0) = 0x2713;
+		WFIFOL(fd,2) = account_id;
+		WFIFOB(fd,6) = 1;
+		WFIFOSET(fd,51);
+	}
+	RFIFOSKIP(fd,19);
+}
+
+//----------------------------------------------------------
+// Number of users in the world (connected char-server(s)) [Edit: Wizputer]
+//----------------------------------------------------------
+void number_world_users(int fd, int id) {
+	#ifdef DEBUG
+    if (server[id].users != RFIFOL(fd,2))
+		printf("set number users %s : %d\n", server[id].name, RFIFOL(fd,2));
+	#endif
+		
+	server[id].users = RFIFOL(fd,2);
+	if(anti_freeze_enable)
+		server_freezeflag[id] = 5; // Char anti-freeze system. Counter. 5 ok, 4...0 freezed
+		
+	sprintf(tmpsql,"UPDATE `sstatus` SET `user` = '%d' WHERE `index` = '%d'", server[id].users, id);
+	sql_query(tmpsql,"number_world_users");
+	
+	RFIFOSKIP(fd,6);
+}
+
+//-----------------------------------------
+// Email and Time request from char-server [Edit: Wizputer]
+//-----------------------------------------
+void email_time_request(int fd, int id) {
+	int account_id=RFIFOL(fd,2);
+	time_t connect_until_time = 0;
+	char email[40] = "";
+	
+	sprintf(tmpsql,"SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'",login_db, login_db_account_id, account_id);
+	sql_query(tmpsql,"email_time_request");
+	
+	sql_res = mysql_store_result(&mysql_handle) ;
+	if (sql_res) {
+		sql_row = mysql_fetch_row(sql_res);
+		connect_until_time = atol(sql_row[1]);
+		strcpy(email, sql_row[0]);
+	}
+	mysql_free_result(sql_res);
+	
+	#ifdef DEBUG
+	printf("parse_fromchar: E-mail/limited time request from '%s' server (concerned account: %d)\n", server[id].name, account_id);
+	#endif
+	
+	WFIFOW(fd,0) = 0x2717;
+	WFIFOL(fd,2) = account_id;
+	memcpy(WFIFOP(fd, 6), email, 40);
+	WFIFOL(fd,46) = (unsigned long) connect_until_time;
+	WFIFOSET(fd,50);
+
+	RFIFOSKIP(fd,6);
+}
+
+//--------------------------------
+// Request to change email [Edit: Wizputer]
+//--------------------------------
+void change_account_email(int fd, int id, char ip[16]) {
+	int acc = RFIFOL(fd,2);
+	char actual_email[40], new_email[40];
+
+	memcpy(actual_email, RFIFOP(fd,6), 40);
+	memcpy(new_email, RFIFOP(fd,46), 40);
+
+	if (e_mail_check(actual_email) == 0) {
+	    #ifdef DEBUG
+		printf("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)" RETCODE,
+		       server[id].name, acc, ip);
+        #endif
+	} else if (e_mail_check(new_email) == 0) {
+	    #ifdef DEBUG
+	    printf("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a invalid new e-mail (account: %d, ip: %s)" RETCODE,
+		       server[id].name, acc, ip);
+        #endif     
+	} else if (strcmpi(new_email, "athena@athena.com") == 0) {
+	    #ifdef DEBUG
+		printf("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)" RETCODE,
+               server[id].name, acc, ip);
+        #endif               
+	} else {
+		sprintf(tmpsql, "SELECT `%s`,`email` FROM `%s` WHERE `%s` = '%d'", login_db_userid, login_db, login_db_account_id, acc);
+		sql_query(tmpsql,"change_account_email");
+
+		sql_res = mysql_store_result(&mysql_handle);
+		if (sql_res) {
+			sql_row = mysql_fetch_row(sql_res);	//row fetching
+
+			if (strcmpi(sql_row[1], actual_email) == 0) {
+				sprintf(tmpsql, "UPDATE `%s` SET `email` = '%s' WHERE `%s` = '%d'", login_db, new_email, login_db_account_id, acc);
+				sql_query(tmpsql,"change_account_email");
+				#ifdef DEBUG
+				printf("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d (%s), new e-mail: %s, ip: %s)." RETCODE,
+ 				       server[id].name, acc, sql_row[0], actual_email, ip);
+                #endif
+			}
+		}
+				
+    }
+    
+    RFIFOSKIP(fd, 86);
+}
+
+//-----------------------------------------------
+// State change request from map server (By Yor) [Edit: Wizputer]
+//-----------------------------------------------
+void status_change_request(int fd) {
+	int acc = RFIFOL(fd,2), status = RFIFOL(fd,6);
+
+	sprintf(tmpsql, "SELECT `state` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, acc);
+	sql_query(tmpsql,"status_change_request");
+	
+	sql_res = mysql_store_result(&mysql_handle);
+	if (sql_res) {
+		sql_row = mysql_fetch_row(sql_res); // row fetching
+
+		if (atoi(sql_row[0]) != status && status != 0) {
+			unsigned char buf[16];
+			WBUFW(buf,0) = 0x2731;
+			WBUFL(buf,2) = acc;
+			WBUFB(buf,6) = 0; // 0: change of statut, 1: ban
+			WBUFL(buf,7) = status; // status or final date of a banishment
+			charif_sendallwos(-1, buf, 11);
+		}
+			
+		sprintf(tmpsql,"UPDATE `%s` SET `state` = '%d' WHERE `%s` = '%d'", login_db, status,login_db_account_id,acc);
+		sql_query(tmpsql,"status_change_request");
+    }    
+	
+    RFIFOSKIP(fd,10);
+}
+//--------------------------------------
+// Ban request from map-server (By Yor) [Edit: Wizputer]
+//--------------------------------------
+void ban_request(int fd) {
+	int acc=RFIFOL(fd,2);
+	struct tm *tmtime;
+	time_t timestamp, tmptime;
+
+	sprintf(tmpsql, "SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc);
+	sql_query(tmpsql,"ban_request");
+	
+	sql_res = mysql_store_result(&mysql_handle);
+	if (sql_res) {
+		sql_row = mysql_fetch_row(sql_res); // row fetching
+
+		tmptime = atol(sql_row[0]);
+
+		if (tmptime == 0 || tmptime < time(NULL))
+			timestamp = time(NULL);
+		else
+			timestamp = tmptime;
+
+		tmtime = localtime(&timestamp);
+		tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,6);
+		tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,8);
+		tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,10);
+		tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,12);
+		tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,14);
+		tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,16);
+
+		timestamp = mktime(tmtime);
+
+		if (timestamp != -1) {
+			if (timestamp <= time(NULL))
+				timestamp = 0;
+			if (tmptime != timestamp) {
+				if (timestamp != 0) {
+					unsigned char buf[16];
+					WBUFW(buf,0) = 0x2731;
+					WBUFL(buf,2) = acc;
+					WBUFB(buf,6) = 1; // 0: change of statut, 1: ban
+					WBUFL(buf,7) = timestamp; // status or final date of a banishment
+					charif_sendallwos(-1, buf, 11);
+				}
+				#ifdef DEBUG
+				printf("Account: [%d] Banned until: [%ld]\n", acc, timestamp); 
+				#endif
+				
+                sprintf(tmpsql, "UPDATE `%s` SET `ban_until` = '%ld', `state`='7' WHERE `%s` = '%d'", login_db, timestamp, login_db_account_id, acc);
+				sql_query(tmpsql,"ban_request");
+			}
+		}
+    }
+    
+	RFIFOSKIP(fd,18);
+}
+
+//-----------------------------
+// Change sex [Edit: Wizputer]
+//-----------------------------
+void change_sex(int fd) {
+	int sex,acc=RFIFOL(fd,4);
+	unsigned char buf[16];
+	
+	sprintf(tmpsql,"SELECT `sex` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc);
+    sql_query(tmpsql,"change_sex");
+        
+    sql_res = mysql_store_result(&mysql_handle) ;
+        
+    if (sql_res) {
+		sql_row = mysql_fetch_row(sql_res);	//row fetching
+	
+        if (strcmpi(sql_row[0], "M") == 0)
+            sex = 1;
+        else
+            sex = 0;
+        
+        sprintf(tmpsql,"UPDATE `%s` SET `sex` = '%c' WHERE `%s` = '%d'", login_db, (sex==0?'M':'F'), login_db_account_id, acc);
+		sql_query(tmpsql,"change_sex");
+		
+		WBUFW(buf,0) = 0x2723;
+		WBUFL(buf,2) = acc;
+		WBUFB(buf,6) = sex;
+		charif_sendallwos(-1, buf, 7);
+    }	
+	
+    RFIFOSKIP(fd,6);
+}
+
+//-------------------------------
+// Save Account Reg [Edit: Wizputer]
+//-------------------------------
+void save_account_reg(int fd){
+	int p,j,value,acc=RFIFOL(fd,4);
+	char str[32];
+	char temp_str[32];
+
+	if (acc>0){
+		unsigned char buf[RFIFOW(fd,2)+1];
+		for(p=8,j=0;p<RFIFOW(fd,2) && j<ACCOUNT_REG2_NUM;p+=36,j++){
+			memcpy(str,RFIFOP(fd,p),32);
+			value=RFIFOL(fd,p+32);
+			
+            sprintf(tmpsql,"DELETE FROM `global_reg_value` WHERE `type`='1' AND `account_id`='%d' AND `str`='%s';",acc,jstrescapecpy(temp_str,str));
+			sql_query(tmpsql,"save_account_reg");
+			
+            sprintf(tmpsql,"INSERT INTO `global_reg_value` (`type`, `account_id`, `str`, `value`) VALUES ( 1 , '%d' , '%s' , '%d');",  acc, jstrescapecpy(temp_str,str), value);
+			sql_query(tmpsql,"save_account_reg");
+		}
+
+		// Send to char
+		memcpy(WBUFP(buf,0),RFIFOP(fd,0),RFIFOW(fd,2));
+		WBUFW(buf,0)=0x2729;
+		charif_sendallwos(fd,buf,WBUFW(buf,2));
+	}
+
+	RFIFOSKIP(fd,RFIFOW(fd,2));
+	
+	#ifdef DEBUG
+	printf("login: save account_reg (from char)\n");
+	#endif
+}
+
+//------------------------------------------------
+// Recieve unban request from map-server (by Yor) [Edit: Wizputer]
+//------------------------------------------------
+void unban_request(int fd) {
+	int acc = RFIFOL(fd,2);
+				
+    sprintf(tmpsql,"SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc);
+    sql_query(tmpsql,"unban_request");
+    
+    sql_res = mysql_store_result(&mysql_handle) ;
+
+    if (sql_res) {
+        sql_row = mysql_fetch_row(sql_res);	//row fetching
+
+        if (atol(sql_row[0]) != 0) {
+            sprintf(tmpsql,"UPDATE `%s` SET `ban_until` = '0', `state`='0' WHERE `%s` = '%d'", login_db,login_db_account_id,acc);
+            sql_query(tmpsql,"unban_request");
+		}
+	}
+
+	RFIFOSKIP(fd,6);
+}
+
+//-----------------------------------------------------
+// char-server packet parse [Edit: Wizputer]
+//-----------------------------------------------------
+int parse_fromchar(int fd){
+	int id;
+
+	unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
+	char ip[16];
+
+	sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+
+	for(id = 0; id < MAX_SERVERS; id++)
+		if (server_fd[id] == fd)
+			break;
+
+	if (id == MAX_SERVERS)
+		session[fd]->eof = 1;
+		
+	if(session[fd]->eof) {
+		if (id < MAX_SERVERS) {
+			printf("Char-server '%s' has disconnected.\n", server[id].name);
+			server_fd[id] = -1;
+			memset(&server[id], 0, sizeof(struct mmo_char_server));
+			// server delete
+			sprintf(tmpsql, "DELETE FROM `sstatus` WHERE `index`='%d'", id);
+    		sql_query(tmpsql,"parse_fromchar");
+		}
+		close(fd);
+		delete_session(fd);
+		return 0;
+	}
+
+	while(RFIFOREST(fd) >= 2) {
+	    #ifdef DEBUG_PACKETS
+		printf("char_parse: %d %d packet case=%x\n", fd, RFIFOREST(fd), RFIFOW(fd, 0));
+		#endif
+		
+		switch (RFIFOW(fd,0)) {
+		case 0x2712:
+			if (RFIFOREST(fd) < 19)
+				return 0;
+			send_account_reg(fd);
+			break;
+
+		case 0x2714:
+			if (RFIFOREST(fd) < 6)
+				return 0;
+			number_world_users(fd,id);
+			break;
+
+		case 0x2716:
+			if (RFIFOREST(fd) < 6)
+				return 0;
+			email_time_request(fd, id);
+			break;
+	
+		case 0x2722:
+			if (RFIFOREST(fd) < 86)
+				return 0;
+			change_account_email(fd, id, ip);
+			break;
+
+		case 0x2724:
+			if (RFIFOREST(fd) < 10)
+				return 0;
+			status_change_request(fd);
+			break;
+
+		case 0x2725:
+			if (RFIFOREST(fd) < 18)
+				return 0;
+			ban_request(fd);
+			break;
+
+		case 0x2727:
+			if (RFIFOREST(fd) < 6)
+				return 0;
+			change_sex(fd);
+			break;
+
+		case 0x2728:
+            if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
+                return 0;
+            save_account_reg(fd);	
+            break;
+
+        case 0x272a:
+			if (RFIFOREST(fd) < 6)
+				return 0;
+			unban_request(fd);
+			return 0;
+			
+        case 0x272b:    // Set account_id to online [Wizputer]
+            if (RFIFOREST(fd) < 6)
+                return 0;
+            add_online_user(RFIFOL(fd,2));
+            RFIFOSKIP(fd,6);
+            break;
+    
+        case 0x272c:   // Set account_id to offline [Wizputer]
+            if (RFIFOREST(fd) < 6)
+                return 0;
+            remove_online_user(RFIFOL(fd,2));
+            RFIFOSKIP(fd,6);
+            break;
+			
+		default:
+		    #ifdef DEBUG
+		    printf("login: unknown packet %x! (from char).\n", RFIFOW(fd,0));
+		    #endif
+		    session[fd]->eof = 1;
+        }
+	}
+
+	return 0;
+}

+ 2 - 0
src/login_sql/char_int.h

@@ -0,0 +1,2 @@
+int char_anti_freeze_system(int, unsigned int, int, int);
+int parse_fromchar(int);

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 254 - 708
src/login_sql/login.c


+ 116 - 0
src/login_sql/login.h

@@ -15,6 +15,111 @@
 #define START_ACCOUNT_NUM	  2000000
 #define END_ACCOUNT_NUM		100000000
 
+//add include for DBMS(mysql)
+#include <mysql.h>
+
+#include "../common/socket.h"
+#include "../common/core.h"
+#include "../common/mmo.h"
+#include "../common/version.h"
+#include "../common/db.h"
+#include "../common/timer.h"
+
+#include "strlib.h"
+
+#ifdef LCCWIN32
+#include <winsock.h>
+#pragma lib <libmysql.lib>
+extern void gettimeofday(struct timeval *t, struct timezone *dummy);
+#else
+#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <winsock2.h>
+#include <time.h>
+void Gettimeofday(struct timeval *timenow)
+{
+	time_t t;
+	t = clock();
+	timenow->tv_usec = t;
+	timenow->tv_sec = t / CLK_TCK;
+	return;
+}
+#define gettimeofday(timenow, dummy) Gettimeofday(timenow)
+#pragma comment(lib,"libmysql.lib")
+#else
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#endif
+#endif
+
+// Auth Data
+#define AUTH_FIFO_SIZE 256
+extern struct auth_fifo {
+	int account_id,login_id1,login_id2;
+	int ip,sex,delflag;
+} auth_fifo[AUTH_FIFO_SIZE];
+
+extern int auth_fifo_pos;
+
+// MySQL Query
+extern char tmpsql[65535], prev_query[65535];
+
+// MySQL Connection Handle
+extern MYSQL mysql_handle;
+extern MYSQL_RES* 	sql_res ;
+extern MYSQL_ROW	sql_row ;
+
+// MySQL custom table and column names 
+extern char login_db[32];
+extern char loginlog_db[32];
+extern char login_db_account_id[32];
+extern char login_db_userid[32];
+extern char login_db_user_pass[32];
+extern char login_db_level[32];
+
+// MD5 Key Data for encrypted login
+extern int md5keylen;
+extern char md5key[20];
+
+// Dynamic IP Ban config
+extern int ipban;
+extern int dynamic_account_ban;
+extern int dynamic_account_ban_class;
+extern int dynamic_pass_failure_ban;
+extern int dynamic_pass_failure_ban_time;
+extern int dynamic_pass_failure_ban_how_many;
+extern int dynamic_pass_failure_ban_how_long;
+
+// Date format for bans
+extern char date_format[32];
+
+// minimum level of player/GM (0: player, 1-99: gm) to connect on the server
+extern int min_level_to_connect; 
+
+// It's to check IP of a player between login-server and char-server (part of anti-hacking system)
+extern int check_ip_flag; 
+
+// Login's FD
+extern int login_fd;
+
+// LAN IP of char-server and subnet mask(Kashy)
+extern char lan_char_ip[16];
+extern int subnetmaski[4];
+
+// Char-server data
+extern struct mmo_char_server server[MAX_SERVERS];
+extern int server_fd[MAX_SERVERS];
+
+// Anti-freeze Data
+extern int server_freezeflag[MAX_SERVERS];
+extern int anti_freeze_enable;
+extern int ANTI_FREEZE_INTERVAL;
+
 struct mmo_account {
 	char* userid;
 	char* passwd;
@@ -26,6 +131,8 @@ struct mmo_account {
 	long char_id;
 	char lastlogin[24];
 	int sex;
+
+	time_t ban_until_time;
 };
 
 struct mmo_char_server {
@@ -37,5 +144,14 @@ struct mmo_char_server {
 	int new;
 };
 
+void sql_query(char*,char*);
+int e_mail_check(unsigned char*);
+void add_online_user(int);
+int is_user_online(int);
+void remove_online_user(int);
+int mmo_auth( struct mmo_account*, int);
+int isGM(int);
+int lan_ip_check(unsigned char *);
+
 
 #endif

+ 418 - 0
src/login_sql/login_int.c

@@ -0,0 +1,418 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include "login.h"
+#include "char_int.h"
+
+//----------------------
+// Client requesting login [Edit: Wizputer]
+//----------------------
+void client_request_login(int fd,unsigned char *p ) {
+    struct mmo_account account;
+   	char t_uid[32];  
+   	int server_num = 0,result,i;
+    
+    #ifdef DEBUG
+    printf("client connection request %s from %d.%d.%d.%d\n", RFIFOP(fd, 6), p[0], p[1], p[2], p[3]);
+    #endif
+
+	account.userid = RFIFOP(fd, 6);
+	account.passwd = RFIFOP(fd, 30);
+#ifdef PASSWORDENC
+	account.passwdenc= (RFIFOW(fd,0)==0x64)?0:PASSWORDENC;
+#else
+	account.passwdenc=0;
+#endif
+	result=mmo_auth(&account, fd);
+
+	jstrescapecpy(t_uid,RFIFOP(fd, 6));
+	if(result==-1){
+	    int gm_level = isGM(account.account_id);
+        if (min_level_to_connect > gm_level) {
+			WFIFOW(fd,0) = 0x81;
+			WFIFOL(fd,2) = 1; // 01 = Server closed
+			WFIFOSET(fd,3);
+	    } else {
+            if (p[0] != 127) {
+                sprintf(tmpsql,"INSERT INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', '%s','100', 'login ok')", loginlog_db, p[0], p[1], p[2], p[3], t_uid);
+                sql_query(tmpsql,"client_request_login");
+            }
+
+            if (gm_level) {
+                #ifdef DEBUG            
+			    printf("Connection of the GM (level:%d) account '%s' accepted.\n", gm_level, account.userid);
+			    #endif
+			} else {
+			    #ifdef DEBUG
+				printf("Connection of the account '%s' accepted.\n", account.userid);
+				#endif
+			}
+   			
+            for(i = 0; i < MAX_SERVERS; i++) {
+				if (server_fd[i] >= 0) {
+					//Lan check added by Kashy
+					if (lan_ip_check(p))
+						WFIFOL(fd,47+server_num*32) = inet_addr(lan_char_ip);
+					else
+                        WFIFOL(fd,47+server_num*32) = server[i].ip;
+
+                    WFIFOW(fd,47+server_num*32+4) = server[i].port;
+                    memcpy(WFIFOP(fd,47+server_num*32+6), server[i].name, 20);
+                    WFIFOW(fd,47+server_num*32+26) = server[i].users;
+                    WFIFOW(fd,47+server_num*32+28) = server[i].maintenance;
+                    WFIFOW(fd,47+server_num*32+30) = server[i].new;
+                    server_num++;
+                }
+            }
+            
+            // if at least 1 char-server
+            if (server_num > 0) {
+                WFIFOW(fd,0)=0x69;
+                WFIFOW(fd,2)=47+32*server_num;
+                WFIFOL(fd,4)=account.login_id1;
+                WFIFOL(fd,8)=account.account_id;
+                WFIFOL(fd,12)=account.login_id2;
+                WFIFOL(fd,16)=0;
+                memcpy(WFIFOP(fd,20),account.lastlogin,24);
+                WFIFOB(fd,46)=account.sex;
+                WFIFOSET(fd,47+32*server_num);
+                
+                if(auth_fifo_pos>=AUTH_FIFO_SIZE)
+                    auth_fifo_pos=0;
+                
+                auth_fifo[auth_fifo_pos].account_id=account.account_id;
+                auth_fifo[auth_fifo_pos].login_id1=account.login_id1;
+                auth_fifo[auth_fifo_pos].login_id2=account.login_id2;
+                auth_fifo[auth_fifo_pos].sex=account.sex;
+                auth_fifo[auth_fifo_pos].delflag=0;
+                auth_fifo[auth_fifo_pos].ip = session[fd]->client_addr.sin_addr.s_addr;
+                auth_fifo_pos++;
+            } else {
+                WFIFOW(fd,0) = 0x81;
+                WFIFOL(fd,2) = 1; // 01 = Server closed
+                WFIFOSET(fd,3);
+            }
+        }
+    } else {
+		char error[64];
+		char tmp_sql[65535];
+		
+        sprintf(tmp_sql,"INSERT INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', '%s', '%d','login failed : %%s')", loginlog_db, p[0], p[1], p[2], p[3], t_uid, result);
+		switch((result)) {
+		
+        case -3:  //-3 = Account Banned
+			sprintf(tmpsql,tmp_sql,"Account banned.");
+			sprintf(error,"Account banned.");
+		break;
+		case -2:  //-2 = Dynamic Ban
+			sprintf(tmpsql,tmp_sql,"dynamic ban (ip and account).");
+			sprintf(error,"dynamic ban (ip and account).");
+		break;
+		case 1:   // 0 = Unregistered ID
+			sprintf(tmpsql,tmp_sql,"Unregisterd ID.");
+			sprintf(error,"Unregisterd ID.");
+		break;
+		case 2:   // 1 = Incorrect Password
+			sprintf(tmpsql,tmp_sql,"Incorrect Password.");
+			sprintf(error,"Incorrect Password.");
+		break;
+		case 3:   // 2 = This ID is expired
+			sprintf(tmpsql,tmp_sql,"Account Expired.");
+			sprintf(error,"Account Expired.");
+		break;
+		case 4:   // 3 = Rejected from Server
+			sprintf(tmpsql,tmp_sql,"Rejected from server.");
+			sprintf(error,"Rejected from server.");
+		break;
+		case 5:   // 4 = You have been blocked by the GM Team
+			sprintf(tmpsql,tmp_sql,"Blocked by GM.");
+			sprintf(error,"Blocked by GM.");
+		break;
+		case 6:   // 5 = Your Game's EXE file is not the latest version
+			sprintf(tmpsql,tmp_sql,"Not latest game EXE.");
+			sprintf(error,"Not latest game EXE.");
+		break;
+		case 7:   // 6 = Your are Prohibited to log in until %s
+			sprintf(tmpsql,tmp_sql,"Banned.");
+			sprintf(error,"Banned.");
+		break;
+		case 8:   // 7 = Server is jammed due to over populated
+			sprintf(tmpsql,tmp_sql,"Server Over-population.");
+			sprintf(error,"Server Over-population.");
+		break;
+		case 9:   // 8 = No MSG (actually, all states after 9 except 99 are No MSG, use only this)
+			sprintf(tmpsql,tmp_sql," ");
+			sprintf(error," ");
+		break;
+		case 100: // 99 = This ID has been totally erased
+			sprintf(tmpsql,tmp_sql,"Account gone.");
+			sprintf(error,"Account gone.");
+		break;
+		default:
+			sprintf(tmpsql,tmp_sql,"Uknown Error.");
+			sprintf(error,"Uknown Error.");
+		break;
+		}
+
+		sql_query(tmpsql,"client_request_login");
+
+		if ((result == 1) && (dynamic_pass_failure_ban != 0)){	// failed password
+			sprintf(tmpsql,"SELECT count(*) FROM `%s` WHERE `ip` = '%d.%d.%d.%d' AND `rcode` = '1' AND `time` > NOW() - INTERVAL %d MINUTE",
+			        loginlog_db, p[0], p[1], p[2], p[3], dynamic_pass_failure_ban_time);	//how many times filed account? in one ip.
+			sql_query(tmpsql,"client_request_login");
+			
+			if ((sql_res = mysql_store_result(&mysql_handle))) {
+                if ((sql_row = mysql_fetch_row(sql_res))) {
+                    if (atoi(sql_row[0]) >= dynamic_pass_failure_ban_how_many ) {
+                        sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() +  INTERVAL %d MINUTE ,'Password error ban: %s')", p[0], p[1], p[2], dynamic_pass_failure_ban_how_long, t_uid);
+                        sql_query(tmpsql,"client_request_login");
+                    }
+                }
+            }        
+
+			
+			mysql_free_result(sql_res);
+			
+		} else if (result == -2) {	//dynamic banned - add ip to ban list.
+			sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() +  INTERVAL 1 MONTH ,'Dynamic banned user id : %s')", p[0], p[1], p[2], t_uid);
+			sql_query(tmpsql,"client_request_login");
+			result = -3;
+		}
+
+		//cannot connect login failed
+		memset(WFIFOP(fd,0),'\0',23);
+		WFIFOW(fd,0)=0x6a;
+		WFIFOB(fd,2)=result-1;
+		if (result == 6) { // 6 = Your are Prohibited to log in until %s
+			char tmpstr[256];
+			strftime(tmpstr, 20, date_format, localtime(&account.ban_until_time));
+			tmpstr[19] = '\0';
+			memcpy(WFIFOP(fd,3), tmpstr, 20);
+		} else { // we send error message
+			memcpy(WFIFOP(fd,3), error, 20);
+		}
+	}
+
+	WFIFOSET(fd,23);
+
+	RFIFOSKIP(fd,(RFIFOW(fd,0)==0x64)?55:47);
+}
+
+//------------------------------------------------------
+// MD5 Key requested for encypted login [Edit: Wizputer
+//------------------------------------------------------
+void md5_key_request(int fd) {
+    #ifdef DEBUG
+    printf("Request Password key -%s\n",md5key);
+    #endif
+    
+	RFIFOSKIP(fd,2);
+	WFIFOW(fd,0)=0x01dc;
+	WFIFOW(fd,2)=4+md5keylen;
+	memcpy(WFIFOP(fd,4),md5key,md5keylen);
+	WFIFOSET(fd,WFIFOW(fd,2));
+}
+
+//----------------------------------------------------
+// Char-server requesting connection [Edit: Wizputer]
+//-----------------------------------------------------
+void char_request_login(int fd, unsigned char *p) {
+    struct mmo_account account;
+	unsigned char* server_name;
+   	char t_uid[32];  
+	int result;
+	
+	sprintf(tmpsql,"INSERT INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', '%s@%s','100', 'charserver - %s@%d.%d.%d.%d:%d')", loginlog_db, p[0], p[1], p[2], p[3], RFIFOP(fd, 2),RFIFOP(fd, 60),RFIFOP(fd, 60), RFIFOB(fd, 54), RFIFOB(fd, 55), RFIFOB(fd, 56), RFIFOB(fd, 57), RFIFOW(fd, 58));
+	sql_query(tmpsql,"char_request_login");
+	
+	#ifdef DEBUG
+	printf("server connection request %s @ %d.%d.%d.%d:%d (%d.%d.%d.%d)\n",
+			RFIFOP(fd, 60), RFIFOB(fd, 54), RFIFOB(fd, 55), RFIFOB(fd, 56), RFIFOB(fd, 57), RFIFOW(fd, 58),
+			p[0], p[1], p[2], p[3]);
+	#endif
+
+	account.userid = RFIFOP(fd, 2);
+	account.passwd = RFIFOP(fd, 26);
+	account.passwdenc = 0;
+	server_name = RFIFOP(fd,60);
+	result = mmo_auth(&account, fd);
+
+	#ifdef DEBUG
+	printf("Result: %d - Sex: %d - Account ID: %d\n",result,account.sex,(int) account.account_id);
+	#endif
+
+	if(result == -1 && account.sex==2 && account.account_id<MAX_SERVERS && server_fd[account.account_id]==-1){
+	    printf("Connection of the char-server '%s' accepted.\n", server_name);
+
+        memset(&server[account.account_id], 0, sizeof(struct mmo_char_server));
+        
+        server[account.account_id].ip=RFIFOL(fd,54);
+		server[account.account_id].port=RFIFOW(fd,58);
+		memcpy(server[account.account_id].name,RFIFOP(fd,60),20);
+		server[account.account_id].users=0;
+		server[account.account_id].maintenance=RFIFOW(fd,82);
+		server[account.account_id].new=RFIFOW(fd,84);
+		server_fd[account.account_id]=fd;
+
+		if(anti_freeze_enable)
+			server_freezeflag[account.account_id] = 5; // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed
+
+		sprintf(tmpsql,"DELETE FROM `sstatus` WHERE `index`='%ld'", account.account_id);
+		sql_query(tmpsql,"char_request_login");
+
+		jstrescapecpy(t_uid,server[account.account_id].name);
+		
+		sprintf(tmpsql,"INSERT DELAYED INTO `sstatus`(`index`,`name`,`user`) VALUES ( '%ld', '%s', '%d')",
+				account.account_id, server[account.account_id].name,0);
+		sql_query(tmpsql,"char_request_login");
+		
+        WFIFOW(fd,0)=0x2711;
+		WFIFOB(fd,2)=0;
+		WFIFOSET(fd,3);
+		session[fd]->func_parse=parse_fromchar;
+		realloc_fifo(fd,FIFOSIZE_SERVERLINK,FIFOSIZE_SERVERLINK);
+	} else {
+		WFIFOW(fd, 0) =0x2711;
+		WFIFOB(fd, 2)=3;
+		WFIFOSET(fd, 3);
+	}
+
+	RFIFOSKIP(fd, 86);
+}
+
+//---------------------------------------------
+// Athena Version Info Request [Edit: Wizputer]
+//---------------------------------------------
+void request_athena_info(int fd) {
+    #ifdef DEBUG
+	printf ("Athena version check...\n");
+	#endif
+	
+	WFIFOW(fd,0)=0x7531;
+	WFIFOB(fd,2)=ATHENA_MAJOR_VERSION;
+	WFIFOB(fd,3)=ATHENA_MINOR_VERSION;
+	WFIFOB(fd,4)=ATHENA_REVISION;
+	WFIFOB(fd,5)=ATHENA_RELEASE_FLAG;
+	WFIFOB(fd,6)=ATHENA_OFFICIAL_FLAG;
+	WFIFOB(fd,7)=ATHENA_SERVER_LOGIN;
+	WFIFOW(fd,8)=ATHENA_MOD_VERSION;
+	WFIFOSET(fd,10);
+	RFIFOSKIP(fd,2);
+}
+
+//----------------------------------------------------------------------------------------
+// Default packet parsing (normal players or administation/char-server connection requests)
+//----------------------------------------------------------------------------------------
+int parse_login(int fd) {
+	char ip[16];
+ 	
+	unsigned char *p = (unsigned char *) &session[fd]->client_addr.sin_addr;
+	sprintf(ip, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+
+	if (ipban > 0) {
+		//ip ban
+		//p[0], p[1], p[2], p[3]
+		//request DB connection
+		//check
+		sprintf(tmpsql, "SELECT count(*) FROM `ipbanlist` WHERE `list` = '%d.*.*.*' OR `list` = '%d.%d.*.*' OR `list` = '%d.%d.%d.*' OR `list` = '%d.%d.%d.%d'",
+		  p[0], p[0], p[1], p[0], p[1], p[2], p[0], p[1], p[2], p[3]);
+		sql_query(tmpsql,"parse_login");
+
+		if((sql_res = mysql_store_result(&mysql_handle))) {
+            if((sql_row = mysql_fetch_row(sql_res))) {//row fetching
+                if (atoi(sql_row[0]) >0) {
+                    // ip ban ok.
+                    printf ("packet from banned ip : %d.%d.%d.%d" RETCODE, p[0], p[1], p[2], p[3]);
+                
+                    sprintf(tmpsql,"INSERT INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%d.%d.%d.%d', 'unknown','-3', 'ip banned')", loginlog_db, p[0], p[1], p[2], p[3]);
+                    sql_query(tmpsql,"parse_login");
+                
+                    #ifdef DEBUG
+                    printf ("close session connection...\n");
+                    #endif
+
+                    // close connection
+                    session[fd]->eof = 1;
+                } else {
+                    #ifdef DEBUG
+                    printf ("packet from ip (ban check ok) : %d.%d.%d.%d" RETCODE, p[0], p[1], p[2], p[3]);
+                    #endif
+                }
+            }    
+        }
+        
+        mysql_free_result(sql_res);
+    }
+    
+	if (session[fd]->eof) {
+	    int i;
+		for(i = 0; i < MAX_SERVERS; i++)
+			if (server_fd[i] == fd)
+				server_fd[i] = -1;
+		close(fd);
+		delete_session(fd);
+		return 0;
+	}
+
+	while(RFIFOREST(fd)>=2){
+	    #ifdef DEBUG_PACKETS
+		printf("parse_login : %d %d packet case=%x\n", fd, RFIFOREST(fd), RFIFOW(fd,0));
+		#endif
+
+		switch(RFIFOW(fd,0)){
+		case 0x200:		// New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive.
+			if (RFIFOREST(fd) < 26)
+				return 0;
+			RFIFOSKIP(fd,26);
+			break;
+
+		case 0x204:		// New alive packet: structure: 0x204 <encrypted.account.userid>.16B. (new ragexe from 22 june 2004)
+			if (RFIFOREST(fd) < 18)
+				return 0;
+			RFIFOSKIP(fd,18);
+			break;
+
+		case 0x64:
+		case 0x01dd:
+			if(RFIFOREST(fd)< ((RFIFOW(fd, 0) ==0x64)?55:47))
+				return 0;
+			client_request_login(fd, p);	
+			break;
+		case 0x01db:
+		    if (session[fd]->session_data) {
+		          #ifdef DEBUG
+		          printf("login: abnormal request of MD5 key (already opened session).\n");
+		          #endif
+		          session[fd]->eof = 1;
+		          return 0;
+            }
+            md5_key_request(fd);
+            break;
+
+        case 0x2710:
+			if(RFIFOREST(fd)<86)
+				return 0;
+			char_request_login(fd,p);
+			break;
+
+		case 0x7530:
+		    request_athena_info(fd);
+			break;
+
+		case 0x7532:
+		default:
+		    #ifdef DEBUG
+			printf ("End of connection (ip: %s)" RETCODE, ip);
+			#endif
+			session[fd]->eof = 1;
+			return 0;
+		}
+	}
+
+	return 0;
+}
+

+ 1 - 0
src/login_sql/login_int.h

@@ -0,0 +1 @@
+int parse_login(int);

Vissa filer visades inte eftersom för många filer har ändrats