# This patch file was generated by NetBeans IDE
# Following Index: paths are relative to: /home/lighta/Documents/Myscript/RO/Servs/ramerge
# This patch can be applied using context Tools: Patch action on respective folder.
# It uses platform neutral UTF-8 encoding and \n newlines.
# Above lines and this line are ignored by the patching process.
Index: conf/atcommand_athena.conf
--- conf/atcommand_athena.conf Base (BASE)
+++ conf/atcommand_athena.conf Locally Modified (Based On LOCAL)
Index: conf/channels.conf
--- conf/channels.conf Base (BASE)
+++ conf/channels.conf Locally Modified (Based On LOCAL)
@@ -2,19 +2,19 @@
chsys: (
{
- /* Default channels (available to all players) */
+ /* Default channels (available on boot) */
default_channels: {
/* channel_name : channel_messages_color */
- main: "Orange"
- support: "Blue"
- trade: "Red"
- offtopic: "Cyan"
- /* Add as many channels as you'd like. */
+ main: "Orange" /* available as #main */
+ support: "Blue" /* available as #support */
+ trade: "Red" /* available as #trade */
+ offtopic: "Cyan" /* available as #offtopic */
+ /* Add as many channels as you'd like */
}
/* Colors available */
colors: {
- Default: "0xffffff" /* Custom channels will use the first in the list unless a font is selected through @channel. */
+ Default: "0xffffff" /* Custom channels will use the first in the list unless a font is selected through @channel */
Red: "0xff0000"
Blue: "0x83cfe9"
Orange: "0xe57c00"
@@ -22,22 +22,22 @@
Yellow: "0xffff90"
Green: "0x28bf00"
Normal: "0x00ff00"
- /* Add as many channels as you'd like. */
+ /* Add as many channels as you'd like */
}
/* Allow users to create their own (private) channels through @channels command? */
/* (must also allow players to use @channels in groups.conf) */
allow_user_channel_creation: true
- /* "map_local_channel" is an instanced channel unique to each map. */
+ /* "map_local_channel" is a instanced channel unique to each map */
map_local_channel: true
- map_local_channel_name: "map"
+ map_local_channel_name: "map" /* available as #map */
map_local_channel_color: "Yellow"
- map_local_channel_autojoin: true /* Disable autojoin in specific maps through mapflag 'nomapchannelautojoin'. */
+ map_local_channel_autojoin: true /* can disable autojoin in specific maps through a mapflag or zone */
- /* "ally_channel" is a channel shared by all your guild allies. */
+ /* "ally_channel" is a channel shared by all your guild allies */
ally_channel_enabled: true
- ally_channel_name: "ally"
+ ally_channel_name: "ally" /* available as #ally */
ally_channel_color: "Green"
ally_channel_autojoin: true
}
Index: doc/permissions.txt
--- doc/permissions.txt Base (BASE)
+++ doc/permissions.txt Locally Modified (Based On LOCAL)
Index: src/char/Makefile.in
--- src/char/Makefile.in Base (BASE)
+++ src/char/Makefile.in Locally Modified (Based On LOCAL)
@@ -15,9 +15,9 @@
COMMON_SQL_OBJ = ../common/obj_sql/sql.o
COMMON_H = ../common/sql.h
-CHAR_OBJ = obj_sql/char.o obj_sql/inter.o obj_sql/int_party.o obj_sql/int_guild.o \
+CHAR_OBJ = obj_sql/char.o obj_sql/inter.o obj_sql/int_party.o obj_sql/int_guild.o obj_sql/pincode.o \
obj_sql/int_storage.o obj_sql/int_pet.o obj_sql/int_homun.o obj_sql/int_mail.o obj_sql/int_auction.o obj_sql/int_quest.o obj_sql/int_mercenary.o obj_sql/int_elemental.o
-CHAR_H = char.h inter.h int_party.h int_guild.h int_storage.h int_pet.h int_homun.h int_mail.h int_auction.h int_quest.h int_mercenary.h int_elemental.h
+CHAR_H = char.h inter.h int_party.h int_guild.h pincode.h int_storage.h int_pet.h int_homun.h int_mail.h int_auction.h int_quest.h int_mercenary.h int_elemental.h
HAVE_MYSQL=@HAVE_MYSQL@
ifeq ($(HAVE_MYSQL),yes)
Index: src/char/char.c
--- src/char/char.c Base (BASE)
+++ src/char/char.c Locally Modified (Based On LOCAL)
@@ -21,6 +21,7 @@
#include "int_storage.h"
#include "char.h"
#include "inter.h"
+#include "pincode.h"
#include <sys/types.h>
#include <time.h>
@@ -81,7 +82,7 @@
unsigned short map[MAX_MAP_PER_SERVER];
} server[MAX_MAP_SERVERS];
-int login_fd=-1, char_fd=-1;
+int char_fd=-1;
char userid[24];
char passwd[24];
char server_name[20];
@@ -119,27 +120,6 @@
} subnet[16];
int subnet_count = 0;
-struct char_session_data {
- bool auth; // whether the session is authed or not
- int account_id, login_id1, login_id2, sex;
- int found_char[MAX_CHARS]; // ids of chars on this account
- char email[40]; // e-mail (default: [email protected]) by [Yor]
- time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
- int group_id; // permission
- uint8 char_slots;
- uint32 version;
- uint8 clienttype;
- char new_name[NAME_LENGTH];
- char birthdate[10+1]; // YYYY-MM-DD
- // Pincode system
- char pincode[4+1];
- uint16 pincode_seed;
- time_t pincode_change;
- uint16 pincode_try;
- // Addon system
- unsigned int char_moves[MAX_CHARS]; // character moves left
-};
-
int max_connect_user = -1;
int gm_allow_group = -1;
int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
@@ -148,29 +128,6 @@
int start_armor = 2301;
int guild_exp_rate = 100;
-// Pincode system
-#define PINCODE_OK 0
-#define PINCODE_ASK 1
-#define PINCODE_NOTSET 2
-#define PINCODE_EXPIRED 3
-#define PINCODE_NEW 4
-#define PINCODE_PASSED 7
-#define PINCODE_WRONG 8
-
-bool pincode_enabled = true;
-int pincode_changetime = 0;
-int pincode_maxtry = 3;
-bool pincode_force = true;
-
-void pincode_check( int fd, struct char_session_data* sd );
-void pincode_change( int fd, struct char_session_data* sd );
-void pincode_setnew( int fd, struct char_session_data* sd );
-void pincode_sendstate( int fd, struct char_session_data* sd, uint16 state );
-void pincode_notifyLoginPinUpdate( int account_id, char* pin );
-void pincode_notifyLoginPinError( int account_id );
-void pincode_decrypt( unsigned long userSeed, char* pin );
-int pincode_compare( int fd, struct char_session_data* sd, char* pin );
-
// Addon system
bool char_move_enabled = true;
bool char_movetoused = true;
@@ -222,16 +179,8 @@
// Online User Database
//-----------------------------------------------------
-struct online_char_data {
- int account_id;
- int char_id;
- int fd;
- int waiting_disconnect;
- short server; // -2: unknown server, -1: not connected, 0+: id of server
- bool pincode_success;
-};
-
static DBMap* online_char_db; // int account_id -> struct online_char_data*
+DBMap* char_get_online_char_db(void) { return online_char_db; }
static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data);
int delete_char_sql(int char_id);
@@ -245,6 +194,7 @@
character->account_id = key.i;
character->char_id = -1;
character->server = -1;
+ character->pincode_enable = -1;
character->fd = -1;
character->waiting_disconnect = INVALID_TIMER;
return db_ptr2data(character);
@@ -262,6 +212,8 @@
character->char_id = -1;
character->server = -1;
+ if(character->pincode_enable == -1)
+ character->pincode_enable = pincode_charselect + pincode_enabled;
if(character->waiting_disconnect != INVALID_TIMER) {
delete_timer(character->waiting_disconnect, chardb_waiting_disconnect);
@@ -358,8 +310,7 @@
{
character->char_id = -1;
character->server = -1;
- // needed if player disconnects completely since Skotlex did not want to free the session
- character->pincode_success = false;
+ character->pincode_enable = -1;
}
//FIXME? Why Kevin free'd the online information when the char was effectively in the map-server?
@@ -1044,8 +995,7 @@
char last_map[MAP_NAME_LENGTH_EXT];
stmt = SqlStmt_Malloc(sql_handle);
- if( stmt == NULL )
- {
+ if( stmt == NULL ) {
SqlStmt_ShowDebug(stmt);
return 0;
}
@@ -1109,8 +1059,7 @@
sd->char_moves[i] = 0;
}
- for( i = 0; i < MAX_CHARS && SQL_SUCCESS == SqlStmt_NextRow(stmt); i++ )
- {
+ for( i = 0; i < MAX_CHARS && SQL_SUCCESS == SqlStmt_NextRow(stmt); i++ ) {
p.last_point.map = mapindex_name2id(last_map);
sd->found_char[p.slot] = p.char_id;
j += mmo_char_tobuf(WBUFP(buf, j), &p);
@@ -2209,8 +2158,7 @@
// find the authenticated session with this account id
ARR_FIND( 0, fd_max, i, session[i] && (sd = (struct char_session_data*)session[i]->session_data) && sd->auth && sd->account_id == RFIFOL(fd,2) );
- if( i < fd_max )
- {
+ if( i < fd_max ) {
int server_id;
memcpy(sd->email, RFIFOP(fd,6), 40);
sd->expiration_time = (time_t)RFIFOL(fd,46);
@@ -2237,39 +2185,9 @@
} else {
// send characters to player
mmo_char_send006b(i, sd);
-#if PACKETVER >= 20110309
- if( pincode_enabled ){
- // PIN code system enabled
- if( strlen( sd->pincode ) <= 0 ){
- // No PIN code has been set yet
- if( pincode_force ){
- pincode_sendstate( i, sd, PINCODE_NEW );
- }else{
- pincode_sendstate( i, sd, PINCODE_PASSED );
+ pincode_handle(fd,sd);
}
- }else{
- if( !pincode_changetime || ( sd->pincode_change + pincode_changetime ) > time(NULL) ){
- struct online_char_data* node = (struct online_char_data*)idb_get( online_char_db, sd->account_id );
-
- if( node != NULL && node->pincode_success ){
- // User has already passed the check
- pincode_sendstate( i, sd, PINCODE_PASSED );
- }else{
- // Ask user for his PIN code
- pincode_sendstate( i, sd, PINCODE_ASK );
}
- }else{
- // User hasnt changed his PIN code too long
- pincode_sendstate( i, sd, PINCODE_EXPIRED );
- }
- }
- }else{
- // PIN code system disabled
- pincode_sendstate( i, sd, PINCODE_OK );
- }
-#endif
- }
- }
RFIFOSKIP(fd,72);
break;
@@ -2934,6 +2852,7 @@
WFIFOSET(fd,7);
}else{
struct auth_node* node;
+ struct online_char_data* character;
// create temporary auth entry
CREATE(node, struct auth_node, 1);
@@ -2950,14 +2869,12 @@
//Set char to "@ char select" in online db [Kevin]
set_char_charselect(account_id);
- {
- struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, account_id);
-
+ character = (struct online_char_data*)idb_get(online_char_db, account_id);
if( character != NULL ){
character->pincode_success = true;
}
- }
+
WFIFOHEAD(fd,7);
WFIFOW(fd,0) = 0x2b03;
WFIFOL(fd,2) = account_id;
@@ -3744,14 +3661,12 @@
return 0;
}
- while( RFIFOREST(fd) >= 2 )
- {
+ while( RFIFOREST(fd) >= 2 ) {
//For use in packets that depend on an sd being present [Skotlex]
#define FIFOSD_CHECK(rest) { if(RFIFOREST(fd) < rest) return 0; if (sd==NULL || !sd->auth) { RFIFOSKIP(fd,rest); return 0; } }
cmd = RFIFOW(fd,0);
- switch( cmd )
- {
+ switch( cmd ) {
// request to connect
// 0065 <account id>.L <login id1>.L <login id2>.L <???>.W <sex>.B
@@ -3844,6 +3759,7 @@
int slot = RFIFOB(fd,2);
RFIFOSKIP(fd,3);
+ if(pincode_hack_check(fd,sd)==1) break;
if ( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `char_id` FROM `%s` WHERE `account_id`='%d' AND `char_num`='%d'", char_db, sd->account_id, slot)
|| SQL_SUCCESS != Sql_NextRow(sql_handle)
@@ -4040,6 +3956,8 @@
{
int cid = RFIFOL(fd,2);
+ if(pincode_hack_check(fd,sd)==1) break;
+
ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid);
memcpy(email, RFIFOP(fd,6), 40);
RFIFOSKIP(fd,( cmd == 0x68) ? 46 : 56);
@@ -4274,12 +4192,10 @@
case 0x8b8:
if( RFIFOREST(fd) < 10 )
return 0;
-
- if( RFIFOL(fd,2) != sd->account_id )
+ if(RFIFOL(fd,2) != sd->account_id )
break;
-
+ if( pincode_enabled)
pincode_check( fd, sd );
-
RFIFOSKIP(fd,10);
break;
@@ -4291,11 +4207,13 @@
if( RFIFOL(fd,2) != sd->account_id )
break;
+ if( pincode_enabled){
if( strlen( sd->pincode ) <= 0 ){
pincode_sendstate( fd, sd, PINCODE_NEW );
}else{
pincode_sendstate( fd, sd, PINCODE_ASK );
}
+ }
RFIFOSKIP(fd,6);
break;
@@ -4307,7 +4225,7 @@
if( RFIFOL(fd,2) != sd->account_id )
break;
-
+ if(pincode_enabled)
pincode_change( fd, sd );
RFIFOSKIP(fd,14);
@@ -4321,6 +4239,7 @@
if( RFIFOL(fd,2) != sd->account_id )
break;
+ if( pincode_enabled)
pincode_setnew( fd, sd );
RFIFOSKIP(fd,10);
@@ -4517,120 +4436,6 @@
}
//------------------------------------------------
-//Pincode system
-//------------------------------------------------
-void pincode_check( int fd, struct char_session_data* sd ){
- char pin[5] = "\0\0\0\0";
- strncpy((char*)pin, (char*)RFIFOP(fd, 6), 4+1);
-
- pincode_decrypt(sd->pincode_seed, pin );
-
- if( pincode_compare( fd, sd, pin ) ){
- pincode_sendstate( fd, sd, PINCODE_PASSED );
- }
-}
-
-int pincode_compare( int fd, struct char_session_data* sd, char* pin ){
- if( strcmp( sd->pincode, pin ) == 0 ){
- sd->pincode_try = 0;
- return 1;
- }else{
- pincode_sendstate( fd, sd, PINCODE_WRONG );
-
- if( pincode_maxtry && ++sd->pincode_try >= pincode_maxtry ){
- pincode_notifyLoginPinError( sd->account_id );
- }
-
- return 0;
- }
-}
-
-void pincode_change( int fd, struct char_session_data* sd ){
- char oldpin[5] = "\0\0\0\0";
- char newpin[5] = "\0\0\0\0";
-
- strncpy(oldpin, (char*)RFIFOP(fd,6), 4+1);
- pincode_decrypt(sd->pincode_seed,oldpin);
-
- if( !pincode_compare( fd, sd, oldpin ) )
- return;
-
- strncpy(newpin, (char*)RFIFOP(fd,10), 4+1);
- pincode_decrypt(sd->pincode_seed,newpin);
-
- pincode_notifyLoginPinUpdate( sd->account_id, newpin );
-
- pincode_sendstate( fd, sd, PINCODE_PASSED );
-}
-
-void pincode_setnew( int fd, struct char_session_data* sd ){
- char newpin[5] = "\0\0\0\0";
-
- strncpy( newpin, (char*)RFIFOP(fd,6), 4+1 );
- pincode_decrypt( sd->pincode_seed, newpin );
-
- pincode_notifyLoginPinUpdate( sd->account_id, newpin );
- strncpy( sd->pincode, newpin, strlen( newpin ) );
-
- pincode_sendstate( fd, sd, PINCODE_PASSED );
-}
-
-// 0 = disabled / pin is correct
-// 1 = ask for pin - client sends 0x8b8
-// 2 = create new pin - client sends 0x8ba
-// 3 = pin must be changed - client 0x8be
-// 4 = create new pin - client sends 0x8ba
-// 5 = client shows msgstr(1896)
-// 6 = client shows msgstr(1897) Unable to use your KSSN number
-// 7 = char select window shows a button - client sends 0x8c5
-// 8 = pincode was incorrect
-void pincode_sendstate( int fd, struct char_session_data* sd, uint16 state ){
- WFIFOHEAD(fd, 12);
- WFIFOW(fd, 0) = 0x8b9;
- WFIFOL(fd, 2) = sd->pincode_seed = rand() % 0xFFFF;
- WFIFOL(fd, 6) = sd->account_id;
- WFIFOW(fd,10) = state;
- WFIFOSET(fd,12);
-}
-
-void pincode_notifyLoginPinUpdate( int account_id, char* pin ){
- WFIFOHEAD(login_fd,11);
- WFIFOW(login_fd,0) = 0x2738;
- WFIFOL(login_fd,2) = account_id;
- strncpy( (char*)WFIFOP(login_fd,6), pin, 5 );
- WFIFOSET(login_fd,11);
-}
-
-void pincode_notifyLoginPinError( int account_id ){
- WFIFOHEAD(login_fd,6);
- WFIFOW(login_fd,0) = 0x2739;
- WFIFOL(login_fd,2) = account_id;
- WFIFOSET(login_fd,6);
-}
-
-void pincode_decrypt( unsigned long userSeed, char* pin ){
- int i, pos;
- char tab[10] = {0,1,2,3,4,5,6,7,8,9};
- unsigned long multiplier = 0x3498, baseSeed = 0x881234;
-
- for( i = 1; i < 10; i++ ){
- userSeed = baseSeed + userSeed * multiplier;
- pos = userSeed % (i + 1);
- if( i != pos ){
- tab[i] ^= tab[pos];
- tab[pos] ^= tab[i];
- tab[i] ^= tab[pos];
- }
- }
-
- for( i = 0; i < 4; i++ ){
- pin[i] = tab[pin[i]- '0'];
- }
-
- sprintf(pin, "%d%d%d%d", pin[0], pin[1], pin[2], pin[3]);
-}
-
-//------------------------------------------------
//Add On system
//------------------------------------------------
void moveCharSlot( int fd, struct char_session_data* sd, unsigned short from, unsigned short to ){
@@ -4939,7 +4744,7 @@
} else if (strcmpi(w1, "max_connect_user") == 0) {
max_connect_user = atoi(w2);
if (max_connect_user < -1)
- max_connect_user = -1;
+ max_connect_user = -1; // unlimited online players
} else if(strcmpi(w1, "gm_allow_group") == 0) {
gm_allow_group = atoi(w2);
} else if (strcmpi(w1, "autosave_time") == 0) {
@@ -5018,6 +4823,12 @@
guild_exp_rate = atoi(w2);
} else if (strcmpi(w1, "pincode_enabled") == 0) {
pincode_enabled = config_switch(w2);
+ #if PACKETVER < 20110309
+ if( pincode_enabled ) {
+ ShowWarning("pincode_enabled requires PACKETVER 20110309 or higher. Disabling...\n");
+ pincode_enabled = false;
+ }
+ #endif
} else if (strcmpi(w1, "pincode_changetime") == 0) {
pincode_changetime = atoi(w2)*60*60*24;
} else if (strcmpi(w1, "pincode_maxtry") == 0) {
@@ -5137,8 +4948,7 @@
mmo_char_sql_init();
char_read_fame_list(); //Read fame lists.
- if ((naddr_ != 0) && (!login_ip || !char_ip))
- {
+ if ((naddr_ != 0) && (!login_ip || !char_ip)) {
char ip_str[16];
ip2str(addr_[0], ip_str);
Index: src/char/char.h
--- src/char/char.h Base (BASE)
+++ src/char/char.h Locally Modified (Based On LOCAL)
@@ -7,9 +7,9 @@
#include "../config/core.h"
#include "../common/core.h" // CORE_ST_LAST
#include "../common/msg_conf.h"
+#include "../common/cbasetypes.h"
-enum E_CHARSERVER_ST
-{
+enum E_CHARSERVER_ST {
CHARSERVER_ST_RUNNING = CORE_ST_LAST,
CHARSERVER_ST_SHUTDOWN,
CHARSERVER_ST_LAST
@@ -28,6 +28,46 @@
const char* char_msg_txt(int msg_number);
void char_do_final_msg(void);
+struct char_session_data {
+ bool auth; // whether the session is authed or not
+ int account_id, login_id1, login_id2, sex;
+ int found_char[MAX_CHARS]; // ids of chars on this account
+ char email[40]; // e-mail (default: [email protected]) by [Yor]
+ time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
+ int group_id; // permission
+ uint8 char_slots;
+ uint32 version;
+ uint8 clienttype;
+ char new_name[NAME_LENGTH];
+ char birthdate[10+1]; // YYYY-MM-DD
+ // Pincode system
+ char pincode[PINCODE_LENGTH+1];
+ uint32 pincode_seed;
+ time_t pincode_change;
+ uint16 pincode_try;
+ // Addon system
+ unsigned int char_moves[MAX_CHARS]; // character moves left
+};
+
+struct online_char_data {
+ int account_id;
+ int char_id;
+ int fd;
+ int waiting_disconnect;
+ short server; // -2: unknown server, -1: not connected, 0+: id of server
+ bool pincode_success;
+ int pincode_enable;
+};
+DBMap* char_get_online_char_db(void);
+
+typedef struct char_session_data char_sd;
+typedef struct online_char_data online_cd;
+extern int pincode_charselect;
+extern bool pincode_enabled;
+extern int pincode_changetime;
+extern int pincode_maxtry;
+extern bool pincode_force;
+
enum {
TABLE_INVENTORY,
TABLE_CART,
@@ -47,7 +87,7 @@
int request_accreg2(int account_id, int char_id);
int save_accreg2(unsigned char* buf, int len);
-
+int login_fd;
extern int char_name_option;
extern char char_name_letters[];
extern bool char_gm_read;
Index: src/char/pincode.c
--- src/char/pincode.c No Base Revision
+++ src/char/pincode.c Locally New
@@ -0,0 +1,221 @@
+
+#include "../common/cbasetypes.h"
+#include "../common/mmo.h"
+#include "../common/random.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "pincode.h"
+
+#include <stdio.h>
+
+bool pincode_enabled = true;
+int pincode_changetime = 0;
+int pincode_maxtry = 3;
+bool pincode_force = true;
+int pincode_charselect = 0;
+
+void pincode_handle(int fd, char_sd *sd) {
+#if PACKETVER >= 20110309
+ DBMap* online_char_db = char_get_online_char_db();
+ online_cd *character = (online_cd *)idb_get( online_char_db, sd->account_id );
+
+ if( pincode_enabled ){
+ // PIN code system enabled
+ if( strlen( sd->pincode ) <= 0 ){
+ // No PIN code has been set yet
+ if( pincode_force ){
+ pincode_sendstate( fd, sd, PINCODE_NEW );
+ }else{
+ pincode_sendstate( fd, sd, PINCODE_OK );
+ }
+ }else{
+ if( !pincode_changetime || ( sd->pincode_change + pincode_changetime ) > time(NULL) ){
+ if( character != NULL && character->pincode_success ){
+ // User has already passed the check
+ pincode_sendstate( fd, sd, PINCODE_PASSED );
+ }else{
+ // Ask user for his PIN code
+ pincode_sendstate( fd, sd, PINCODE_ASK );
+ }
+ }else{
+ // User hasnt changed his PIN code too long
+ pincode_sendstate( fd, sd, PINCODE_EXPIRED );
+ }
+ }
+ }else{
+ // PIN code system disabled
+ pincode_sendstate( fd, sd, PINCODE_OK ); //PINCODE_NOTSET
+ }
+
+ if( character )
+ character->pincode_enable = -1;
+#endif
+}
+
+void pincode_handle2 ( int fd, struct char_session_data* sd ) {
+ DBMap* online_char_db = char_get_online_char_db();
+ struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, sd->account_id);
+
+ if( character && character->pincode_enable > pincode_charselect ){
+ character->pincode_enable = pincode_charselect * 2;
+ }else{
+ pincode_sendstate( fd, sd, PINCODE_OK );
+ return;
+ }
+
+ if( strlen(sd->pincode) == 4 ){
+ if( pincode_changetime && time(NULL) > (sd->pincode_change+pincode_changetime) ){ // User hasnt changed his PIN code for a long time
+ pincode_sendstate( fd, sd, PINCODE_EXPIRED );
+ } else { // Ask user for his PIN code
+ pincode_sendstate( fd, sd, PINCODE_ASK );
+ }
+ } else // No PIN code has been set yet
+ pincode_sendstate( fd, sd, PINCODE_NOTSET );
+
+ if( character )
+ character->pincode_enable = -1;
+}
+
+/*
+ * Checking if trying to bypass pincode
+ * return
+ * 1 : yes must close session
+ * 0 : no
+ */
+int pincode_hack_check(int fd, char_sd *sd ) {
+#if PACKETVER >= 20110309
+ DBMap* online_char_db = char_get_online_char_db();
+ if( pincode_enabled ){ // hack check
+ struct online_char_data* character;
+ character = (struct online_char_data*)idb_get(online_char_db, sd->account_id);
+ if( character && character->pincode_enable == -1){
+ WFIFOHEAD(fd,3);
+ WFIFOW(fd,0) = 0x6c;
+ WFIFOB(fd,2) = 0;
+ WFIFOSET(fd,3);
+ return 1;
+ }
+ }
+#endif
+ return 0;
+}
+
+void pincode_check( int fd, char_sd *sd ){
+ char pin[PINCODE_LENGTH+1];
+ DBMap* online_char_db = char_get_online_char_db();
+
+ memset(pin,0,sizeof(pin));
+ strncpy((char*)pin, (char*)RFIFOP(fd, 6), sizeof(pin));
+
+ pincode_decrypt(sd->pincode_seed, pin );
+
+ if( pincode_compare( fd, sd, pin ) ){
+ struct online_char_data* character;
+ if( (character = (struct online_char_data*)idb_get(online_char_db, sd->account_id)) )
+ character->pincode_enable = pincode_charselect * 2;
+ pincode_sendstate( fd, sd, PINCODE_PASSED );
+ }
+}
+
+int pincode_compare( int fd, char_sd *sd, char* pin ){
+ if( strcmp( sd->pincode, pin ) == 0 ){
+ sd->pincode_try = 0;
+ return 1;
+ }else{
+ pincode_sendstate( fd, sd, PINCODE_WRONG );
+
+ if( pincode_maxtry && ++sd->pincode_try >= pincode_maxtry ){
+ pincode_notifyLoginPinError( sd->account_id );
+ }
+
+ return 0;
+ }
+}
+
+void pincode_change( int fd, char_sd *sd ){
+ char oldpin[PINCODE_LENGTH+1];
+ char newpin[PINCODE_LENGTH+1];
+
+ memset(oldpin,0,sizeof(oldpin));
+ memset(newpin,0,sizeof(newpin));
+
+ strncpy(oldpin, (char*)RFIFOP(fd,6), sizeof(oldpin));
+ pincode_decrypt(sd->pincode_seed,oldpin);
+
+ if( !pincode_compare( fd, sd, oldpin ) )
+ return;
+
+ strncpy(newpin, (char*)RFIFOP(fd,10), sizeof(newpin));
+ pincode_decrypt(sd->pincode_seed,newpin);
+
+ pincode_notifyLoginPinUpdate( sd->account_id, newpin );
+ strncpy(sd->pincode, newpin, sizeof(sd->pincode));
+ pincode_sendstate( fd, sd, PINCODE_PASSED );
+}
+
+void pincode_setnew( int fd, char_sd *sd ){
+ char newpin[PINCODE_LENGTH+1];
+
+ memset(newpin,0,sizeof(newpin));
+
+ strncpy( newpin, (char*)RFIFOP(fd,6), sizeof(newpin) );
+ pincode_decrypt( sd->pincode_seed, newpin );
+
+ pincode_notifyLoginPinUpdate( sd->account_id, newpin );
+ strncpy( sd->pincode, newpin, strlen( newpin ) );
+
+ pincode_sendstate( fd, sd, PINCODE_ASK );
+}
+
+// 0 = disabled / pin is correct
+// 1 = ask for pin - client sends 0x8b8
+// 2 = create new pin - client sends 0x8ba
+// 3 = pin must be changed - client 0x8be
+// 4 = create new pin - client sends 0x8ba
+// 5 = client shows msgstr(1896)
+// 6 = client shows msgstr(1897) Unable to use your KSSN number
+// 7 = char select window shows a button - client sends 0x8c5
+// 8 = pincode was incorrect
+void pincode_sendstate( int fd, char_sd * sd, uint16 state ){
+ WFIFOHEAD(fd, 12);
+ WFIFOW(fd, 0) = 0x8b9;
+ WFIFOL(fd, 2) = sd->pincode_seed = rnd() % 0xFFFF;
+ WFIFOL(fd, 6) = sd->account_id;
+ WFIFOW(fd,10) = state;
+ WFIFOSET(fd,12);
+}
+
+void pincode_notifyLoginPinUpdate( int account_id, char* pin ){
+ WFIFOHEAD(login_fd,11);
+ WFIFOW(login_fd,0) = 0x2738;
+ WFIFOL(login_fd,2) = account_id;
+ strncpy( (char*)WFIFOP(login_fd,6), pin, strlen(pin) );
+ WFIFOSET(login_fd,11);
+}
+
+void pincode_notifyLoginPinError( int account_id ){
+ WFIFOHEAD(login_fd,6);
+ WFIFOW(login_fd,0) = 0x2739;
+ WFIFOL(login_fd,2) = account_id;
+ WFIFOSET(login_fd,6);
+}
+
+void pincode_decrypt( uint32 userSeed, char* pin ){
+ int i, pos;
+ char tab[10] = {0,1,2,3,4,5,6,7,8,9};
+// uint32 multiplier = 0x3498, baseSeed = 0x881234;
+
+ for( i = 1; i < 10; i++ ){
+ userSeed = baseSeed + userSeed * multiplier;
+ pos = userSeed % (i + 1);
+ if( i != pos ){
+ tab[i] ^= tab[pos];
+ tab[pos] ^= tab[i];
+ tab[i] ^= tab[pos];
+ }
+ }
+
+ for( i = 0; i < PINCODE_LENGTH; i++ ){
+ sprintf( pin+i, "%d", tab[pin[i]- '0'] );
+ }
+}
Index: src/char/pincode.h
--- src/char/pincode.h No Base Revision
+++ src/char/pincode.h Locally New
@@ -0,0 +1,51 @@
+// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#ifndef PINCODE_H
+#define PINCODE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "char.h"
+
+// Pincode system
+typedef enum pin_state {
+ PINCODE_OK,
+ PINCODE_ASK,
+ PINCODE_NOTSET,
+ PINCODE_EXPIRED,
+ PINCODE_NEW,
+ PINCODE_PASSED,
+ PINCODE_WRONG
+} pin_state;
+
+void pincode_handle(int fd, char_sd *sd);
+int pincode_hack_check(int fd, char_sd *sd );
+void pincode_check( int fd, char_sd *sd );
+int pincode_compare( int fd, char_sd *sd, char* pin );
+void pincode_change( int fd, char_sd *sd );
+void pincode_setnew( int fd, char_sd *sd );
+
+// 0 = disabled / pin is correct
+// 1 = ask for pin - client sends 0x8b8
+// 2 = create new pin - client sends 0x8ba
+// 3 = pin must be changed - client 0x8be
+// 4 = create new pin - client sends 0x8ba
+// 5 = client shows msgstr(1896)
+// 6 = client shows msgstr(1897) Unable to use your KSSN number
+// 7 = char select window shows a button - client sends 0x8c5
+// 8 = pincode was incorrect
+void pincode_sendstate( int fd, struct char_session_data* sd, uint16 state );
+
+void pincode_notifyLoginPinUpdate( int account_id, char* pin );
+void pincode_notifyLoginPinError( int account_id );
+void pincode_decrypt( uint32 userSeed, char* pin );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PINCODE_H */
+
Index: src/common/mmo.h
--- src/common/mmo.h Base (BASE)
+++ src/common/mmo.h Locally Modified (Based On LOCAL)
@@ -122,6 +122,8 @@
//For Map Names, which the client considers to be 16 in length including the .gat extension
#define MAP_NAME_LENGTH (11 + 1)
#define MAP_NAME_LENGTH_EXT (MAP_NAME_LENGTH + 4)
+//Pincode Length
+#define PINCODE_LENGTH 4
#define MAX_FRIENDS 40
#define MAX_MEMOPOINTS 3
Index: src/login/account.h
--- src/login/account.h Base (BASE)
+++ src/login/account.h Locally Modified (Based On LOCAL)
@@ -50,7 +50,7 @@
char lastlogin[24]; // date+time of last successful login
char last_ip[16]; // save of last IP of connection
char birthdate[10+1]; // assigned birth date (format: YYYY-MM-DD, default: 0000-00-00)
- char pincode[4+1]; // pincode system
+ char pincode[PINCODE_LENGTH+1]; // pincode system
time_t pincode_change; // (timestamp): last time of pincode change
int account_reg2_num;
struct global_reg account_reg2[ACCOUNT_REG2_NUM]; // account script variables (stored on login server)
Index: src/login/login.c
--- src/login/login.c Base (BASE)
+++ src/login/login.c Locally Modified (Based On LOCAL)
@@ -552,8 +552,10 @@
uint8 char_slots = 0;
int group_id = 0;
char birthdate[10+1] = "";
- char pincode[4+1] = "";
+ char pincode[PINCODE_LENGTH+1];
+ memset(pincode,0,PINCODE_LENGTH+1);
+
int account_id = RFIFOL(fd,2);
RFIFOSKIP(fd,6);
Index: src/map/map.c
--- src/map/map.c Base (BASE)
+++ src/map/map.c Locally Modified (Based On LOCAL)