extern int d2char_delete(char const * account, char const * charname) { char * file; ASSERT(account,-1); ASSERT(charname,-1); if (d2char_check_charname(charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name \"%s\"",charname); return -1; } if (d2char_check_acctname(account)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account name \"%s\"",account); return -1; } /* charsave file */ file=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1); d2char_get_infofile_name(file,account,charname); if (remove(file)<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to delete charinfo file \"%s\" (remove: %s)",file,pstrerror(errno)); xfree(file); return -1; } xfree(file); /* charinfo file */ file=xmalloc(strlen(prefs_get_charsave_dir())+1+strlen(charname)+1); d2char_get_savefile_name(file,charname); if (remove(file)<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to delete charsave file \"%s\" (remove: %s)",file,pstrerror(errno)); } xfree(file); /* bak charsave file */ file=xmalloc(strlen(prefs_get_bak_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1); d2char_get_bak_infofile_name(file,account,charname); if (access(file, F_OK) == 0) { if (remove(file)<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to delete bak charinfo file \"%s\" (remove: %s)",file,pstrerror(errno)); } } xfree(file); /* bak charinfo file */ file=xmalloc(strlen(prefs_get_bak_charsave_dir())+1+strlen(charname)+1); d2char_get_bak_savefile_name(file,charname); if (access(file, F_OK) == 0) { if (remove(file)<0) { eventlog(eventlog_level_error,__FUNCTION__,"failed to delete bak charsave file \"%s\" (remove: %s)",file,pstrerror(errno)); } } xfree(file); eventlog(eventlog_level_info,__FUNCTION__,"character %s(*%s) deleted",charname,account); return 0; }
static int on_client_loginreq(t_connection * c, t_packet * packet) { t_packet * bnpacket; char const * account; t_sq * sq; unsigned int sessionnum; if (!(account=packet_get_str_const(packet,sizeof(t_client_d2cs_loginreq),MAX_CHARNAME_LEN))) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account name"); return -1; } if (d2char_check_acctname(account)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account name"); return -1; } if (!bnetd_conn()) { eventlog(eventlog_level_warn,__FUNCTION__,"d2cs is offline with bnetd, login request will be rejected"); return -1; } sessionnum=bn_int_get(packet->u.client_d2cs_loginreq.sessionnum); conn_set_bnetd_sessionnum(c,sessionnum); eventlog(eventlog_level_info,__FUNCTION__,"got client (*%s) login request sessionnum=0x%X",account,sessionnum); if ((bnpacket=packet_create(packet_class_d2cs_bnetd))) { if ((sq=sq_create(d2cs_conn_get_sessionnum(c),packet,0))) { packet_set_size(bnpacket,sizeof(t_d2cs_bnetd_accountloginreq)); packet_set_type(bnpacket,D2CS_BNETD_ACCOUNTLOGINREQ); bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.h.seqno,sq_get_seqno(sq)); bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.seqno, bn_int_get(packet->u.client_d2cs_loginreq.seqno)); bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.sessionkey, bn_int_get(packet->u.client_d2cs_loginreq.sessionkey)); bn_int_set(&bnpacket->u.d2cs_bnetd_accountloginreq.sessionnum,sessionnum); memcpy(bnpacket->u.d2cs_bnetd_accountloginreq.secret_hash, packet->u.client_d2cs_loginreq.secret_hash, sizeof(bnpacket->u.d2cs_bnetd_accountloginreq.secret_hash)); packet_append_string(bnpacket,account); conn_push_outqueue(bnetd_conn(),bnpacket); } packet_del_ref(bnpacket); } return 0; }
extern int d2charinfo_load(char const * account, char const * charname, t_d2charinfo_file * data) { char * file; int size, ladder_time; if (d2char_check_charname(charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name \"%s\"",charname); return -1; } if (d2char_check_acctname(account)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account name \"%s\"",account); return -1; } file=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1); d2char_get_infofile_name(file,account,charname); size=sizeof(t_d2charinfo_file); if (file_read(file,data,&size)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error loading character file %s",file); xfree(file); return -1; } if (size!=sizeof(t_d2charinfo_file)) { eventlog(eventlog_level_error,__FUNCTION__,"got bad charinfo file %s (length %d)",charname,size); xfree(file); return -1; } d2char_portrait_init(&data->portrait); if (d2charinfo_check(data) < 0) { xfree(file); return -1; } if (!(charstatus_get_ladder(bn_int_get(data->summary.charstatus)))) { bn_byte_set(&data->portrait.ladder, D2CHARINFO_PORTRAIT_PADBYTE); xfree(file); return 0; } ladder_time = prefs_get_ladder_start_time(); if ((ladder_time > 0) && bn_int_get(data->header.create_time) < ladder_time) { char buffer[MAX_SAVEFILE_SIZE]; unsigned int status_offset; unsigned char status; unsigned int charstatus; unsigned int size; unsigned int version; unsigned int checksum; FILE * fp; eventlog(eventlog_level_info,__FUNCTION__,"%s(*%s) was created in old ladder season, set to non-ladder", charname, account); if (!(fp=fopen(file,"wb"))) { eventlog(eventlog_level_error,__FUNCTION__,"charinfo file \"%s\" does not exist for account \"%s\"",file,account); xfree(file); return 0; } xfree(file); charstatus = bn_int_get(data->summary.charstatus); charstatus_set_ladder(charstatus, 0); bn_int_set(&data->summary.charstatus, charstatus); status=bn_byte_get(data->portrait.status); charstatus_set_ladder(status,0); bn_byte_set(&data->portrait.status,status); bn_byte_set(&data->portrait.ladder, D2CHARINFO_PORTRAIT_PADBYTE); if (fwrite(data,1,sizeof(*data),fp)!=sizeof(*data)) { eventlog(eventlog_level_error,__FUNCTION__,"error writing charinfo file for character \"%s\" (fwrite: %s)",charname,pstrerror(errno)); fclose(fp); return 0; } fclose(fp); file=xmalloc(strlen(prefs_get_charsave_dir())+1+strlen(charname)+1); d2char_get_savefile_name(file,charname); if (!(fp=fopen(file,"rb+"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open charsave file \"%s\" for reading and writing (fopen: %s)",file,pstrerror(errno)); xfree(file); return 0; } xfree(file); size=fread(buffer,1,sizeof(buffer),fp); if (!feof(fp)) { eventlog(eventlog_level_error,__FUNCTION__,"error reading charsave file for character \"%s\" (fread: %s)",charname,pstrerror(errno)); fclose(fp); return 0; } version=bn_int_get(buffer+D2CHARSAVE_VERSION_OFFSET); if (version>=0x5C) { status_offset=D2CHARSAVE_STATUS_OFFSET_109; } else { status_offset=D2CHARSAVE_STATUS_OFFSET; } status=bn_byte_get(buffer+status_offset); charstatus_set_ladder(status,0); /* FIXME: shouldn't abuse bn_*_set()... what's the best way to do this? */ bn_byte_set((bn_byte *)(buffer+status_offset),status); if (version>=0x5C) { checksum=d2charsave_checksum(buffer,size,D2CHARSAVE_CHECKSUM_OFFSET); bn_int_set((bn_int *)(buffer+D2CHARSAVE_CHECKSUM_OFFSET),checksum); } fseek(fp,0,SEEK_SET); if (fwrite(buffer,1,size,fp)!=size) { eventlog(eventlog_level_error,__FUNCTION__,"error writing charsave file for character %s (fwrite: %s)",charname,pstrerror(errno)); fclose(fp); return 0; } fclose(fp); } else { bn_byte_set(&data->portrait.ladder, 1); xfree(file); } return 0; }
extern int d2char_convert(char const * account, char const * charname) { FILE * fp; char * file; unsigned char buffer[MAX_SAVEFILE_SIZE]; unsigned int status_offset; unsigned char status; unsigned int charstatus; t_d2charinfo_file charinfo; unsigned int size; unsigned int version; unsigned int checksum; ASSERT(account,-1); ASSERT(charname,-1); /* Playing with a expanstion char on a classic realm will cause the game server to crash, therefore I recommed setting allow_convert = 0 in the d2cs.conf We need to do this to prevent creating classic char and converting to expantion on a classic realm. LOD Char must be created on LOD realm */ if (!prefs_get_allow_convert()) { eventlog(eventlog_level_info,__FUNCTION__,"Convert char has been disabled"); return -1; } /* Procedure is stopped here and returned if allow_convet = 0 in d2cs.conf */ if (d2char_check_charname(charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name \"%s\"",charname); return -1; } if (d2char_check_acctname(account)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account name \"%s\"",account); return -1; } file=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1); d2char_get_infofile_name(file,account,charname); if (!(fp=fopen(file,"rb+"))) { eventlog(eventlog_level_error,__FUNCTION__,"unable to open charinfo file \"%s\" for reading and writing (fopen: %s)",file,pstrerror(errno)); xfree(file); return -1; } xfree(file); if (fread(&charinfo,1,sizeof(charinfo),fp)!=sizeof(charinfo)) { eventlog(eventlog_level_error,__FUNCTION__,"error reading charinfo file for character \"%s\" (fread: %s)",charname,pstrerror(errno)); fclose(fp); return -1; } charstatus=bn_int_get(charinfo.summary.charstatus); charstatus_set_expansion(charstatus,1); bn_int_set(&charinfo.summary.charstatus,charstatus); status=bn_byte_get(charinfo.portrait.status); charstatus_set_expansion(status,1); bn_byte_set(&charinfo.portrait.status,status); fseek(fp,0,SEEK_SET); /* FIXME: check return */ if (fwrite(&charinfo,1,sizeof(charinfo),fp)!=sizeof(charinfo)) { eventlog(eventlog_level_error,__FUNCTION__,"error writing charinfo file for character \"%s\" (fwrite: %s)",charname,pstrerror(errno)); fclose(fp); return -1; } if (fclose(fp)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not close charinfo file for character \"%s\" after writing (fclose: %s)",charname,pstrerror(errno)); return -1; } file=xmalloc(strlen(prefs_get_charsave_dir())+1+strlen(charname)+1); d2char_get_savefile_name(file,charname); if (!(fp=fopen(file,"rb+"))) { eventlog(eventlog_level_error,__FUNCTION__,"could not open charsave file \"%s\" for reading and writing (fopen: %s)",file,pstrerror(errno)); xfree(file); return -1; } xfree(file); size=fread(buffer,1,sizeof(buffer),fp); if (!feof(fp)) { eventlog(eventlog_level_error,__FUNCTION__,"error reading charsave file for character \"%s\" (fread: %s)",charname,pstrerror(errno)); fclose(fp); return -1; } version=bn_int_get(buffer+D2CHARSAVE_VERSION_OFFSET); if (version>=0x0000005C) { status_offset=D2CHARSAVE_STATUS_OFFSET_109; } else { status_offset=D2CHARSAVE_STATUS_OFFSET; } status=bn_byte_get(buffer+status_offset); charstatus_set_expansion(status,1); bn_byte_set((bn_byte *)(buffer+status_offset),status); /* FIXME: shouldn't abuse bn_*_set()... what's the best way to do this? */ if (version>=0x0000005C) { checksum=d2charsave_checksum(buffer,size,D2CHARSAVE_CHECKSUM_OFFSET); bn_int_set((bn_int *)(buffer+D2CHARSAVE_CHECKSUM_OFFSET),checksum); /* FIXME: shouldn't abuse bn_*_set()... what's the best way to do this? */ } fseek(fp,0,SEEK_SET); /* FIXME: check return */ if (fwrite(buffer,1,size,fp)!=size) { eventlog(eventlog_level_error,__FUNCTION__,"error writing charsave file for character %s (fwrite: %s)",charname,pstrerror(errno)); fclose(fp); return -1; } if (fclose(fp)<0) { eventlog(eventlog_level_error,__FUNCTION__,"could not close charsave file for character \"%s\" after writing (fclose: %s)",charname,pstrerror(errno)); return -1; } eventlog(eventlog_level_info,__FUNCTION__,"character %s(*%s) converted to expansion",charname,account); return 0; }
extern int d2char_create(char const * account, char const * charname, unsigned char classs, unsigned short status) { t_d2charinfo_file chardata; char * savefile, * infofile; char buffer[1024]; unsigned int size; int ladder_time, now; FILE * fp; ASSERT(account,-1); ASSERT(charname,-1); if (classs>D2CHAR_MAX_CLASS) classs=0; status &= D2CHARINFO_STATUS_FLAG_INIT_MASK; charstatus_set_init(status,1); /* We need to make sure we are creating the correct character (Classic or Expansion) for the type of game server we are running. If lod_realm = 1 then only Expansion characters can be created and if set to 0 then only Classic character can be created */ if (!(prefs_get_lod_realm() == 2)) { if (prefs_get_lod_realm() && ((status & 0x20) != 0x20)) { eventlog(eventlog_level_warn,__FUNCTION__,"This Realm is for LOD Characters Only"); return -1; } if (!prefs_get_lod_realm() && ((status & 0x20) != 0x0)) { eventlog(eventlog_level_warn,__FUNCTION__,"This Realm is for Classic Characters Only"); return -1; } } /* Once correct type of character is varified then continue with creation of character */ if (!prefs_allow_newchar()) { eventlog(eventlog_level_warn,__FUNCTION__,"creation of new_ character is disabled"); return -1; } if (d2char_check_charname(charname)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad character name \"%s\"",charname); return -1; } if (d2char_check_acctname(account)<0) { eventlog(eventlog_level_error,__FUNCTION__,"got bad account name \"%s\"",account); return -1; } size=sizeof(buffer); if (file_read(prefs_get_charsave_newbie(), buffer, &size)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error loading newbie save file"); return -1; } if (size>=sizeof(buffer)) { eventlog(eventlog_level_error,__FUNCTION__,"newbie save file \"%s\" is corrupt (length %lu, expected <%lu)",prefs_get_charsave_newbie(),(unsigned long)size,(unsigned long)sizeof(buffer)); return -1; } savefile=xmalloc(strlen(prefs_get_charsave_dir())+1+strlen(charname)+1); d2char_get_savefile_name(savefile,charname); if ((fp=fopen(savefile,"rb"))) { eventlog(eventlog_level_warn,__FUNCTION__,"character save file \"%s\" for \"%s\" already exist",savefile,charname); fclose(fp); xfree(savefile); return -1; } infofile=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1); d2char_get_infofile_name(infofile,account,charname); now = time(NULL); ladder_time = prefs_get_ladder_start_time(); if ((ladder_time > 0) && (now < ladder_time)) charstatus_set_ladder(status, 0); d2charsave_init(buffer,charname,classs,status); d2charinfo_init(&chardata,account,charname,classs,status); if (file_write(infofile,&chardata,sizeof(chardata))<0) { eventlog(eventlog_level_error,__FUNCTION__,"error writing info file \"%s\"",infofile); remove(infofile); xfree(infofile); xfree(savefile); return -1; } if (file_write(savefile,buffer,size)<0) { eventlog(eventlog_level_error,__FUNCTION__,"error writing save file \"%s\"",savefile); remove(infofile); remove(savefile); xfree(savefile); xfree(infofile); return -1; } xfree(savefile); xfree(infofile); eventlog(eventlog_level_info,__FUNCTION__,"character %s(*%s) classs %d status 0x%X created",charname,account,classs,status); return 0; }