/[LeafOK_CVS]/pvpgn-1.7.4/src/d2cs/d2charfile.c
ViewVC logotype

Contents of /pvpgn-1.7.4/src/d2cs/d2charfile.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (show annotations) (vendor branch)
Tue Jun 6 03:41:38 2006 UTC (19 years, 9 months ago) by sysadm
Branch: GNU, MAIN
CVS Tags: pvpgn_1-7-4-0_MIL, arelease, HEAD
Changes since 1.1: +0 -0 lines
Content type: text/x-csrc
Error occurred while calculating annotation data.
no message

1 /*
2 * Copyright (C) 2000,2001 Onlyer (onlyer@263.net)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18 #include "common/setup_before.h"
19 #include "setup.h"
20
21 #ifdef HAVE_STDDEF_H
22 # include <stddef.h>
23 #else
24 # ifndef NULL
25 # define NULL ((void *)0)
26 # endif
27 #endif
28 #include <stdio.h>
29 #include <ctype.h>
30 #ifdef HAVE_STRING_H
31 # include <string.h>
32 #else
33 # ifdef HAVE_STRINGS_H
34 # include <strings.h>
35 # endif
36 # ifdef HAVE_MEMORY_H
37 # include <memory.h>
38 # endif
39 #endif
40 #ifdef STDC_HEADERS
41 # include <stdlib.h>
42 #else
43 # ifdef HAVE_MALLOC_H
44 # include <malloc.h>
45 # endif
46 #endif
47 #include "compat/memset.h"
48 #include "compat/memcpy.h"
49 #include <errno.h>
50 #include "compat/strerror.h"
51 #ifdef HAVE_UNISTD_H
52 # include <unistd.h>
53 #endif
54 #include "compat/access.h"
55 #ifdef TIME_WITH_SYS_TIME
56 # include <time.h>
57 # include <sys/time.h>
58 #else
59 # ifdef HAVE_SYS_TIME_H
60 # include <sys/time.h>
61 # else
62 # include <time.h>
63 # endif
64 #endif
65 #ifdef HAVE_SYS_STAT_H
66 # include <sys/stat.h>
67 #endif
68
69 #include "d2charfile.h"
70 #include "prefs.h"
71 #include "xstring.h"
72 #include "common/bn_type.h"
73 #include "common/eventlog.h"
74 #include "common/d2char_checksum.h"
75 #include "common/xalloc.h"
76 #include "common/setup_after.h"
77
78 static int d2charsave_init(void * buffer,char const * charname,unsigned char class,unsigned short status);
79 static int d2charinfo_init(t_d2charinfo_file * chardata, char const * account, char const * charname,
80 unsigned char class, unsigned short status);
81
82 static int d2charsave_init(void * buffer,char const * charname,unsigned char class,unsigned short status)
83 {
84 ASSERT(buffer,-1);
85 ASSERT(charname,-1);
86 bn_byte_set((bn_byte *)((char *)buffer+D2CHARSAVE_CLASS_OFFSET), class);
87 bn_short_set((bn_short *)((char *)buffer+D2CHARSAVE_STATUS_OFFSET),status);
88 strncpy((char *)buffer+D2CHARSAVE_CHARNAME_OFFSET,charname,MAX_CHARNAME_LEN);
89 return 0;
90 }
91
92
93 static int d2charinfo_init(t_d2charinfo_file * chardata, char const * account, char const * charname,
94 unsigned char class, unsigned short status)
95 {
96 unsigned int i;
97 time_t now;
98
99 now=time(NULL);
100 bn_int_set(&chardata->header.magicword,D2CHARINFO_MAGICWORD);
101 bn_int_set(&chardata->header.version,D2CHARINFO_VERSION);
102 bn_int_set(&chardata->header.create_time,now);
103 bn_int_set(&chardata->header.last_time,now);
104 bn_int_set(&chardata->header.total_play_time,0);
105
106 memset(chardata->header.charname, 0,MAX_CHARNAME_LEN);
107 strncpy(chardata->header.charname,charname,MAX_CHARNAME_LEN);
108 memset(chardata->header.account, 0,MAX_ACCTNAME_LEN);
109 strncpy(chardata->header.account,account,MAX_ACCTNAME_LEN);
110 memset(chardata->header.realmname, 0,MAX_REALMNAME_LEN);
111 strncpy(chardata->header.realmname,prefs_get_realmname(),MAX_REALMNAME_LEN);
112 bn_int_set(&chardata->header.checksum,0);
113 for (i=0; i<NELEMS(chardata->header.reserved); i++) {
114 bn_int_set(&chardata->header.reserved[i],0);
115 }
116 bn_int_set(&chardata->summary.charlevel,1);
117 bn_int_set(&chardata->summary.experience,0);
118 bn_int_set(&chardata->summary.charclass,class);
119 bn_int_set(&chardata->summary.charstatus,status);
120
121 memset(chardata->portrait.gfx,D2CHARINFO_PORTRAIT_PADBYTE,sizeof(chardata->portrait.gfx));
122 memset(chardata->portrait.color,D2CHARINFO_PORTRAIT_PADBYTE,sizeof(chardata->portrait.color));
123 memset(chardata->portrait.u2,D2CHARINFO_PORTRAIT_PADBYTE,sizeof(chardata->portrait.u2));
124 memset(chardata->portrait.u1,D2CHARINFO_PORTRAIT_MASK,sizeof(chardata->portrait.u1));
125 memset(chardata->pad,0,sizeof(chardata->pad));
126
127 bn_short_set(&chardata->portrait.header,D2CHARINFO_PORTRAIT_HEADER);
128 bn_byte_set(&chardata->portrait.status,status|D2CHARINFO_PORTRAIT_MASK);
129 bn_byte_set(&chardata->portrait.class,class+1);
130 bn_byte_set(&chardata->portrait.level,1);
131 if (charstatus_get_ladder(status))
132 bn_byte_set(&chardata->portrait.ladder, 1);
133 else
134 bn_byte_set(&chardata->portrait.ladder, D2CHARINFO_PORTRAIT_PADBYTE);
135 bn_byte_set(&chardata->portrait.end,'\0');
136
137 memset(chardata->pad,0,sizeof(chardata->pad));
138
139 return 0;
140 }
141
142
143 extern int d2char_create(char const * account, char const * charname, unsigned char class, unsigned short status)
144 {
145 t_d2charinfo_file chardata;
146 char * savefile, * infofile;
147 char buffer[1024];
148 unsigned int size;
149 int ladder_time, now;
150 FILE * fp;
151
152
153 ASSERT(account,-1);
154 ASSERT(charname,-1);
155 if (class>D2CHAR_MAX_CLASS) class=0;
156 status &= D2CHARINFO_STATUS_FLAG_INIT_MASK;
157 charstatus_set_init(status,1);
158
159 /* We need to make sure we are creating the correct character (Classic or Expansion)
160 for the type of game server we are running. If lod_realm = 1 then only Expansion
161 characters can be created and if set to 0 then only Classic character can
162 be created */
163
164 if (!(prefs_get_lod_realm() == 2)) {
165 if (prefs_get_lod_realm() && ((status & 0x20) != 0x20)) {
166 eventlog(eventlog_level_warn,__FUNCTION__,"This Realm is for LOD Characters Only");
167 return -1;
168 }
169 if (!prefs_get_lod_realm() && ((status & 0x20) != 0x0)) {
170 eventlog(eventlog_level_warn,__FUNCTION__,"This Realm is for Classic Characters Only");
171 return -1;
172 }
173 }
174
175 /* Once correct type of character is varified then continue with creation of character */
176
177 if (!prefs_allow_newchar()) {
178 eventlog(eventlog_level_warn,__FUNCTION__,"creation of new character is disabled");
179 return -1;
180 }
181 if (d2char_check_charname(charname)<0) {
182 eventlog(eventlog_level_error,__FUNCTION__,"got bad character name \"%s\"",charname);
183 return -1;
184 }
185 if (d2char_check_acctname(account)<0) {
186 eventlog(eventlog_level_error,__FUNCTION__,"got bad account name \"%s\"",account);
187 return -1;
188 }
189 size=sizeof(buffer);
190 if (file_read(prefs_get_charsave_newbie(), buffer, &size)<0) {
191 eventlog(eventlog_level_error,__FUNCTION__,"error loading newbie save file");
192 return -1;
193 }
194 if (size>=sizeof(buffer)) {
195 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));
196 return -1;
197 }
198
199 savefile=xmalloc(strlen(prefs_get_charsave_dir())+1+strlen(charname)+1);
200 d2char_get_savefile_name(savefile,charname);
201 if ((fp=fopen(savefile,"rb"))) {
202 eventlog(eventlog_level_warn,__FUNCTION__,"character save file \"%s\" for \"%s\" already exist",savefile,charname);
203 fclose(fp);
204 xfree(savefile);
205 return -1;
206 }
207
208 infofile=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1);
209 d2char_get_infofile_name(infofile,account,charname);
210
211 now = time(NULL);
212 ladder_time = prefs_get_ladder_start_time();
213 if ((ladder_time > 0) && (now < ladder_time))
214 charstatus_set_ladder(status, 0);
215
216 d2charsave_init(buffer,charname,class,status);
217 d2charinfo_init(&chardata,account,charname,class,status);
218
219 if (file_write(infofile,&chardata,sizeof(chardata))<0) {
220 eventlog(eventlog_level_error,__FUNCTION__,"error writing info file \"%s\"",infofile);
221 remove(infofile);
222 xfree(infofile);
223 xfree(savefile);
224 return -1;
225 }
226
227 if (file_write(savefile,buffer,size)<0) {
228 eventlog(eventlog_level_error,__FUNCTION__,"error writing save file \"%s\"",savefile);
229 remove(infofile);
230 remove(savefile);
231 xfree(savefile);
232 xfree(infofile);
233 return -1;
234 }
235 xfree(savefile);
236 xfree(infofile);
237 eventlog(eventlog_level_info,__FUNCTION__,"character %s(*%s) class %d status 0x%X created",charname,account,class,status);
238 return 0;
239 }
240
241
242 extern int d2char_find(char const * account, char const * charname)
243 {
244 char * file;
245 FILE * fp;
246
247 ASSERT(account,-1);
248 ASSERT(charname,-1);
249 file=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1);
250 d2char_get_infofile_name(file,account,charname);
251 fp=fopen(file,"rb");
252 xfree(file);
253 if (fp) {
254 fclose(fp);
255 return 0;
256 }
257 return -1;
258 }
259
260
261 extern int d2char_convert(char const * account, char const * charname)
262 {
263 FILE * fp;
264 char * file;
265 unsigned char buffer[MAX_SAVEFILE_SIZE];
266 unsigned int status_offset;
267 unsigned char status;
268 unsigned int charstatus;
269 t_d2charinfo_file charinfo;
270 unsigned int size;
271 unsigned int version;
272 unsigned int checksum;
273
274 ASSERT(account,-1);
275 ASSERT(charname,-1);
276
277 /* Playing with a expanstion char on a classic realm
278 will cause the game server to crash, therefore
279 I recommed setting allow_convert = 0 in the d2cs.conf
280 We need to do this to prevent creating classic char
281 and converting to expantion on a classic realm.
282 LOD Char must be created on LOD realm */
283
284 if (!prefs_get_allow_convert()) {
285 eventlog(eventlog_level_info,__FUNCTION__,"Convert char has been disabled");
286 return -1;
287 }
288
289 /* Procedure is stopped here and returned if
290 allow_convet = 0 in d2cs.conf */
291
292 if (d2char_check_charname(charname)<0) {
293 eventlog(eventlog_level_error,__FUNCTION__,"got bad character name \"%s\"",charname);
294 return -1;
295 }
296 if (d2char_check_acctname(account)<0) {
297 eventlog(eventlog_level_error,__FUNCTION__,"got bad account name \"%s\"",account);
298 return -1;
299 }
300 file=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1);
301 d2char_get_infofile_name(file,account,charname);
302 if (!(fp=fopen(file,"rb+"))) {
303 eventlog(eventlog_level_error,__FUNCTION__,"unable to open charinfo file \"%s\" for reading and writing (fopen: %s)",file,pstrerror(errno));
304 xfree(file);
305 return -1;
306 }
307 xfree(file);
308 if (fread(&charinfo,1,sizeof(charinfo),fp)!=sizeof(charinfo)) {
309 eventlog(eventlog_level_error,__FUNCTION__,"error reading charinfo file for character \"%s\" (fread: %s)",charname,pstrerror(errno));
310 fclose(fp);
311 return -1;
312 }
313 charstatus=bn_int_get(charinfo.summary.charstatus);
314 charstatus_set_expansion(charstatus,1);
315 bn_int_set(&charinfo.summary.charstatus,charstatus);
316
317 status=bn_byte_get(charinfo.portrait.status);
318 charstatus_set_expansion(status,1);
319 bn_byte_set(&charinfo.portrait.status,status);
320
321 fseek(fp,0,SEEK_SET); /* FIXME: check return */
322 if (fwrite(&charinfo,1,sizeof(charinfo),fp)!=sizeof(charinfo)) {
323 eventlog(eventlog_level_error,__FUNCTION__,"error writing charinfo file for character \"%s\" (fwrite: %s)",charname,pstrerror(errno));
324 fclose(fp);
325 return -1;
326 }
327 if (fclose(fp)<0) {
328 eventlog(eventlog_level_error,__FUNCTION__,"could not close charinfo file for character \"%s\" after writing (fclose: %s)",charname,pstrerror(errno));
329 return -1;
330 }
331
332 file=xmalloc(strlen(prefs_get_charsave_dir())+1+strlen(charname)+1);
333 d2char_get_savefile_name(file,charname);
334 if (!(fp=fopen(file,"rb+"))) {
335 eventlog(eventlog_level_error,__FUNCTION__,"could not open charsave file \"%s\" for reading and writing (fopen: %s)",file,pstrerror(errno));
336 xfree(file);
337 return -1;
338 }
339 xfree(file);
340 size=fread(buffer,1,sizeof(buffer),fp);
341 if (!feof(fp)) {
342 eventlog(eventlog_level_error,__FUNCTION__,"error reading charsave file for character \"%s\" (fread: %s)",charname,pstrerror(errno));
343 fclose(fp);
344 return -1;
345 }
346 version=bn_int_get(buffer+D2CHARSAVE_VERSION_OFFSET);
347 if (version>=0x0000005C) {
348 status_offset=D2CHARSAVE_STATUS_OFFSET_109;
349 } else {
350 status_offset=D2CHARSAVE_STATUS_OFFSET;
351 }
352 status=bn_byte_get(buffer+status_offset);
353 charstatus_set_expansion(status,1);
354 bn_byte_set((bn_byte *)(buffer+status_offset),status); /* FIXME: shouldn't abuse bn_*_set()... what's the best way to do this? */
355 if (version>=0x0000005C) {
356 checksum=d2charsave_checksum(buffer,size,D2CHARSAVE_CHECKSUM_OFFSET);
357 bn_int_set((bn_int *)(buffer+D2CHARSAVE_CHECKSUM_OFFSET),checksum); /* FIXME: shouldn't abuse bn_*_set()... what's the best way to do this? */
358 }
359 fseek(fp,0,SEEK_SET); /* FIXME: check return */
360 if (fwrite(buffer,1,size,fp)!=size) {
361 eventlog(eventlog_level_error,__FUNCTION__,"error writing charsave file for character %s (fwrite: %s)",charname,pstrerror(errno));
362 fclose(fp);
363 return -1;
364 }
365 if (fclose(fp)<0) {
366 eventlog(eventlog_level_error,__FUNCTION__,"could not close charsave file for character \"%s\" after writing (fclose: %s)",charname,pstrerror(errno));
367 return -1;
368 }
369 eventlog(eventlog_level_info,__FUNCTION__,"character %s(*%s) converted to expansion",charname,account);
370 return 0;
371 }
372
373
374 extern int d2char_delete(char const * account, char const * charname)
375 {
376 char * file;
377
378 ASSERT(account,-1);
379 ASSERT(charname,-1);
380 if (d2char_check_charname(charname)<0) {
381 eventlog(eventlog_level_error,__FUNCTION__,"got bad character name \"%s\"",charname);
382 return -1;
383 }
384 if (d2char_check_acctname(account)<0) {
385 eventlog(eventlog_level_error,__FUNCTION__,"got bad account name \"%s\"",account);
386 return -1;
387 }
388
389 /* charsave file */
390 file=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1);
391 d2char_get_infofile_name(file,account,charname);
392 if (remove(file)<0) {
393 eventlog(eventlog_level_error,__FUNCTION__,"failed to delete charinfo file \"%s\" (remove: %s)",file,pstrerror(errno));
394 xfree(file);
395 return -1;
396 }
397 xfree(file);
398
399 /* charinfo file */
400 file=xmalloc(strlen(prefs_get_charsave_dir())+1+strlen(charname)+1);
401 d2char_get_savefile_name(file,charname);
402 if (remove(file)<0) {
403 eventlog(eventlog_level_error,__FUNCTION__,"failed to delete charsave file \"%s\" (remove: %s)",file,pstrerror(errno));
404 }
405 xfree(file);
406
407 /* bak charsave file */
408 file=xmalloc(strlen(prefs_get_bak_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1);
409 d2char_get_bak_infofile_name(file,account,charname);
410 if (access(file, F_OK) == 0) {
411 if (remove(file)<0) {
412 eventlog(eventlog_level_error,__FUNCTION__,"failed to delete bak charinfo file \"%s\" (remove: %s)",file,pstrerror(errno));
413 }
414 }
415 xfree(file);
416
417 /* bak charinfo file */
418 file=xmalloc(strlen(prefs_get_bak_charsave_dir())+1+strlen(charname)+1);
419 d2char_get_bak_savefile_name(file,charname);
420 if (access(file, F_OK) == 0) {
421 if (remove(file)<0) {
422 eventlog(eventlog_level_error,__FUNCTION__,"failed to delete bak charsave file \"%s\" (remove: %s)",file,pstrerror(errno));
423 }
424 }
425 xfree(file);
426
427 eventlog(eventlog_level_info,__FUNCTION__,"character %s(*%s) deleted",charname,account);
428 return 0;
429 }
430
431
432 extern int d2char_get_summary(char const * account, char const * charname,t_d2charinfo_summary * charinfo)
433 {
434 t_d2charinfo_file data;
435
436 ASSERT(account,-1);
437 ASSERT(charname,-1);
438 ASSERT(charinfo,-1);
439 if (d2charinfo_load(account, charname, &data)<0) {
440 eventlog(eventlog_level_error,__FUNCTION__,"error loading character %s(*%s)",charname,account);
441 return -1;
442 }
443 memcpy(charinfo,&data.summary,sizeof(data.summary));
444 eventlog(eventlog_level_info,__FUNCTION__,"character %s difficulty %d expansion %d hardcore %d dead %d loaded",charname,
445 d2charinfo_get_difficulty(charinfo), d2charinfo_get_expansion(charinfo),
446 d2charinfo_get_hardcore(charinfo),d2charinfo_get_dead(charinfo));
447 return 0;
448 }
449
450
451 extern int d2charinfo_load(char const * account, char const * charname, t_d2charinfo_file * data)
452 {
453 char * file;
454 int size, ladder_time;
455
456 if (d2char_check_charname(charname)<0) {
457 eventlog(eventlog_level_error,__FUNCTION__,"got bad character name \"%s\"",charname);
458 return -1;
459 }
460 if (d2char_check_acctname(account)<0) {
461 eventlog(eventlog_level_error,__FUNCTION__,"got bad account name \"%s\"",account);
462 return -1;
463 }
464 file=xmalloc(strlen(prefs_get_charinfo_dir())+1+strlen(account)+1+strlen(charname)+1);
465 d2char_get_infofile_name(file,account,charname);
466 size=sizeof(t_d2charinfo_file);
467 if (file_read(file,data,&size)<0) {
468 eventlog(eventlog_level_error,__FUNCTION__,"error loading character file %s",file);
469 xfree(file);
470 return -1;
471 }
472 if (size!=sizeof(t_d2charinfo_file)) {
473 eventlog(eventlog_level_error,__FUNCTION__,"got bad charinfo file %s (length %d)",charname,size);
474 xfree(file);
475 return -1;
476 }
477 d2char_portrait_init(&data->portrait);
478 if (d2charinfo_check(data) < 0) {
479 xfree(file);
480 return -1;
481 }
482 if (!(charstatus_get_ladder(bn_int_get(data->summary.charstatus)))) {
483 bn_byte_set(&data->portrait.ladder, D2CHARINFO_PORTRAIT_PADBYTE);
484 xfree(file);
485 return 0;
486 }
487 ladder_time = prefs_get_ladder_start_time();
488 if ((ladder_time > 0) && bn_int_get(data->header.create_time) < ladder_time) {
489 char buffer[MAX_SAVEFILE_SIZE];
490 unsigned int status_offset;
491 unsigned char status;
492 unsigned int charstatus;
493 unsigned int size;
494 unsigned int version;
495 unsigned int checksum;
496 FILE * fp;
497
498 eventlog(eventlog_level_info,__FUNCTION__,"%s(*%s) was created in old ladder season, set to non-ladder", charname, account);
499 if (!(fp=fopen(file,"wb"))) {
500 eventlog(eventlog_level_error,__FUNCTION__,"charinfo file \"%s\" does not exist for account \"%s\"",file,account);
501 xfree(file);
502 return 0;
503 }
504 xfree(file);
505 charstatus = bn_int_get(data->summary.charstatus);
506 charstatus_set_ladder(charstatus, 0);
507 bn_int_set(&data->summary.charstatus, charstatus);
508
509 status=bn_byte_get(data->portrait.status);
510 charstatus_set_ladder(status,0);
511 bn_byte_set(&data->portrait.status,status);
512 bn_byte_set(&data->portrait.ladder, D2CHARINFO_PORTRAIT_PADBYTE);
513
514 if (fwrite(data,1,sizeof(*data),fp)!=sizeof(*data)) {
515 eventlog(eventlog_level_error,__FUNCTION__,"error writing charinfo file for character \"%s\" (fwrite: %s)",charname,pstrerror(errno));
516 fclose(fp);
517 return 0;
518 }
519 fclose(fp);
520
521 file=xmalloc(strlen(prefs_get_charsave_dir())+1+strlen(charname)+1);
522 d2char_get_savefile_name(file,charname);
523
524 if (!(fp=fopen(file,"rb+"))) {
525 eventlog(eventlog_level_error,__FUNCTION__,"could not open charsave file \"%s\" for reading and writing (fopen: %s)",file,pstrerror(errno));
526 xfree(file);
527 return 0;
528 }
529 xfree(file);
530 size=fread(buffer,1,sizeof(buffer),fp);
531 if (!feof(fp)) {
532 eventlog(eventlog_level_error,__FUNCTION__,"error reading charsave file for character \"%s\" (fread: %s)",charname,pstrerror(errno));
533 fclose(fp);
534 return 0;
535 }
536 version=bn_int_get(buffer+D2CHARSAVE_VERSION_OFFSET);
537 if (version>=0x5C) {
538 status_offset=D2CHARSAVE_STATUS_OFFSET_109;
539 } else {
540 status_offset=D2CHARSAVE_STATUS_OFFSET;
541 }
542 status=bn_byte_get(buffer+status_offset);
543 charstatus_set_ladder(status,0);
544 /* FIXME: shouldn't abuse bn_*_set()... what's the best way to do this? */
545 bn_byte_set((bn_byte *)(buffer+status_offset),status);
546 if (version>=0x5C) {
547 checksum=d2charsave_checksum(buffer,size,D2CHARSAVE_CHECKSUM_OFFSET);
548 bn_int_set((bn_int *)(buffer+D2CHARSAVE_CHECKSUM_OFFSET),checksum);
549 }
550 fseek(fp,0,SEEK_SET);
551 if (fwrite(buffer,1,size,fp)!=size) {
552 eventlog(eventlog_level_error,__FUNCTION__,"error writing charsave file for character %s (fwrite: %s)",charname,pstrerror(errno));
553 fclose(fp);
554 return 0;
555 }
556 fclose(fp);
557 } else {
558 bn_byte_set(&data->portrait.ladder, 1);
559 xfree(file);
560 }
561 return 0;
562 }
563
564 extern int d2charinfo_check(t_d2charinfo_file * data)
565 {
566 ASSERT(data,-1);
567 if (bn_int_get(data->header.magicword) != D2CHARINFO_MAGICWORD) {
568 eventlog(eventlog_level_error,__FUNCTION__,"info data check failed (header 0x%08X)",bn_int_get(data->header.magicword));
569 return -1;
570 }
571 if (bn_int_get(data->header.version) != D2CHARINFO_VERSION) {
572 eventlog(eventlog_level_error,__FUNCTION__,"info data check failed (version 0x%08X)",bn_int_get(data->header.version));
573 return -1;
574 }
575 return 0;
576 }
577
578
579 extern int d2char_portrait_init(t_d2charinfo_portrait * portrait)
580 {
581 unsigned int i;
582 unsigned char * p;
583
584 p=(unsigned char *)portrait;
585 for (i=0; i<sizeof(t_d2charinfo_portrait); i++) {
586 if (!p[i]) p[i]=D2CHARINFO_PORTRAIT_PADBYTE;
587 }
588 p[i-1]='\0';
589 return 0;
590 }
591
592
593 extern int d2char_get_portrait(char const * account,char const * charname, t_d2charinfo_portrait * portrait)
594 {
595 t_d2charinfo_file data;
596
597 ASSERT(charname,-1);
598 ASSERT(account,-1);
599 ASSERT(portrait,-1);
600 if (d2charinfo_load(account, charname, &data)<0) {
601 eventlog(eventlog_level_error,__FUNCTION__,"error loading character %s(*%s)",charname,account);
602 return -1;
603 }
604 strcpy((char *)portrait,(char *)&data.portrait);
605 return 0;
606 }
607
608
609 extern int d2char_check_charname(char const * name)
610 {
611 unsigned int i;
612 unsigned char ch;
613
614 if (!name) return -1;
615 if (!isalpha((int)name[0])) return -1;
616
617 for (i=1; i<=MAX_CHARNAME_LEN; i++) {
618 ch=name[i];
619 if (ch=='\0') break;
620 if (isalpha(ch)) continue;
621 if (ch=='-') continue;
622 if (ch=='_') continue;
623 if (ch=='.') continue;
624 return -1;
625 }
626 if (i >= MIN_NAME_LEN || i<= MAX_CHARNAME_LEN) return 0;
627 return -1;
628 }
629
630
631 extern int d2char_check_acctname(char const * name)
632 {
633 unsigned int i;
634 unsigned char ch;
635
636 if (!name) return -1;
637 if (!isalnum((int)name[0])) return -1;
638
639 for (i=1; i<=MAX_CHARNAME_LEN; i++) {
640 ch=name[i];
641 if (ch=='\0') break;
642 if (isalnum(ch)) continue;
643 if (strchr(prefs_get_d2cs_account_allowed_symbols(),ch)) continue;
644 return -1;
645 }
646 if (i >= MIN_NAME_LEN || i<= MAX_ACCTNAME_LEN) return 0;
647 return -1;
648 }
649
650
651 extern int d2char_get_savefile_name(char * filename, char const * charname)
652 {
653 char tmpchar[MAX_CHARNAME_LEN];
654
655 ASSERT(filename,-1);
656 ASSERT(charname,-1);
657 strncpy(tmpchar,charname,sizeof(tmpchar));
658 tmpchar[sizeof(tmpchar)-1]='\0';
659 strtolower(tmpchar);
660 sprintf(filename,"%s/%s",prefs_get_charsave_dir(),tmpchar);
661 return 0;
662 }
663
664
665 extern int d2char_get_bak_savefile_name(char * filename, char const * charname)
666 {
667 char tmpchar[MAX_CHARNAME_LEN];
668
669 ASSERT(filename,-1);
670 ASSERT(charname,-1);
671 strncpy(tmpchar,charname,sizeof(tmpchar));
672 tmpchar[sizeof(tmpchar)-1]='\0';
673 strtolower(tmpchar);
674 sprintf(filename,"%s/%s",prefs_get_bak_charsave_dir(),tmpchar);
675 return 0;
676 }
677
678
679 extern int d2char_get_infodir_name(char * filename, char const * account)
680 {
681 char tmpacct[MAX_ACCTNAME_LEN];
682
683 ASSERT(filename,-1);
684 ASSERT(account,-1);
685
686 strncpy(tmpacct,account,sizeof(tmpacct));
687 tmpacct[sizeof(tmpacct)-1]='\0';
688 strtolower(tmpacct);
689 sprintf(filename,"%s/%s",prefs_get_charinfo_dir(),tmpacct);
690 return 0;
691 }
692
693
694 extern int d2char_get_infofile_name(char * filename, char const * account, char const * charname)
695 {
696 char tmpchar[MAX_CHARNAME_LEN];
697 char tmpacct[MAX_ACCTNAME_LEN];
698
699 ASSERT(filename,-1);
700 ASSERT(account,-1);
701 ASSERT(charname,-1);
702 strncpy(tmpchar,charname,sizeof(tmpchar));
703 tmpchar[sizeof(tmpchar)-1]='\0';
704 strtolower(tmpchar);
705
706 strncpy(tmpacct,account,sizeof(tmpacct));
707 tmpchar[sizeof(tmpacct)-1]='\0';
708 strtolower(tmpacct);
709 sprintf(filename,"%s/%s/%s",prefs_get_charinfo_dir(),tmpacct,tmpchar);
710 return 0;
711 }
712
713
714 extern int d2char_get_bak_infofile_name(char * filename, char const * account, char const * charname)
715 {
716 char tmpchar[MAX_CHARNAME_LEN];
717 char tmpacct[MAX_ACCTNAME_LEN];
718
719 ASSERT(filename,-1);
720 ASSERT(account,-1);
721 ASSERT(charname,-1);
722 strncpy(tmpchar,charname,sizeof(tmpchar));
723 tmpchar[sizeof(tmpchar)-1]='\0';
724 strtolower(tmpchar);
725
726 strncpy(tmpacct,account,sizeof(tmpacct));
727 tmpchar[sizeof(tmpacct)-1]='\0';
728 strtolower(tmpacct);
729 sprintf(filename,"%s/%s/%s",prefs_get_bak_charinfo_dir(),tmpacct,tmpchar);
730 return 0;
731 }
732
733
734 extern unsigned int d2charinfo_get_ladder(t_d2charinfo_summary const * charinfo)
735 {
736 ASSERT(charinfo,0);
737 return charstatus_get_ladder(bn_int_get(charinfo->charstatus));
738 }
739
740 extern unsigned int d2charinfo_get_expansion(t_d2charinfo_summary const * charinfo)
741 {
742 ASSERT(charinfo,0);
743 return charstatus_get_expansion(bn_int_get(charinfo->charstatus));
744 }
745
746
747 extern unsigned int d2charinfo_get_level(t_d2charinfo_summary const * charinfo)
748 {
749 ASSERT(charinfo,0);
750 return bn_int_get(charinfo->charlevel);
751 }
752
753
754 extern unsigned int d2charinfo_get_class(t_d2charinfo_summary const * charinfo)
755 {
756 ASSERT(charinfo,0);
757 return bn_int_get(charinfo->charclass);
758 }
759
760
761 extern unsigned int d2charinfo_get_hardcore(t_d2charinfo_summary const * charinfo)
762 {
763 ASSERT(charinfo,0);
764 return charstatus_get_hardcore(bn_int_get(charinfo->charstatus));
765 }
766
767
768 extern unsigned int d2charinfo_get_dead(t_d2charinfo_summary const * charinfo)
769 {
770 ASSERT(charinfo,0);
771 return charstatus_get_dead(bn_int_get(charinfo->charstatus));
772 }
773
774
775 extern unsigned int d2charinfo_get_difficulty(t_d2charinfo_summary const * charinfo)
776 {
777 unsigned int difficulty;
778
779 ASSERT(charinfo,0);
780 if (d2charinfo_get_expansion(charinfo)) {
781 difficulty=charstatus_get_difficulty_expansion(bn_int_get(charinfo->charstatus));
782 } else {
783 difficulty=charstatus_get_difficulty(bn_int_get(charinfo->charstatus));
784 }
785 if (difficulty>2) difficulty=2;
786 return difficulty;
787 }
788
789 /* those functions should move to util.c */
790 extern int file_read(char const * filename, void * data, unsigned int * size)
791 {
792 FILE * fp;
793 unsigned int n;
794
795 ASSERT(filename,-1);
796 ASSERT(data,-1);
797 ASSERT(size,-1);
798 if (!(fp=fopen(filename,"rb"))) {
799 eventlog(eventlog_level_error,__FUNCTION__,"could not open file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno));
800 return -1;
801 }
802
803 fseek(fp,0,SEEK_END); /* FIXME: check return value */
804 n=ftell(fp);
805 n=min(*size,n);
806 rewind(fp); /* FIXME: check return value */
807
808 if (fread(data,1,n,fp)!=n) {
809 eventlog(eventlog_level_error,__FUNCTION__,"error reading file \"%s\" (fread: %s)",filename,pstrerror(errno));
810 fclose(fp);
811 return -1;
812 }
813 if (fclose(fp)<0) {
814 eventlog(eventlog_level_error,__FUNCTION__,"could not close file \"%s\" after reading (fclose: %s)",filename,pstrerror(errno));
815 return -1;
816 }
817 *size=n;
818 return 0;
819 }
820
821
822 extern int file_write(char const * filename, void * data, unsigned int size)
823 {
824 FILE * fp;
825
826 ASSERT(filename,-1);
827 ASSERT(data,-1);
828 ASSERT(size,-1);
829 if (!(fp=fopen(filename,"wb"))) {
830 eventlog(eventlog_level_error,__FUNCTION__,"could not open file \"%s\" for writing (fopen: %s)",filename,pstrerror(errno));
831 return -1;
832 }
833 if (fwrite(data,1,size,fp)!=size) {
834 eventlog(eventlog_level_error,__FUNCTION__,"error writing file \"%s\" (fwrite: %s)",filename,pstrerror(errno));
835 fclose(fp);
836 return -1;
837 }
838 if (fclose(fp)<0) {
839 eventlog(eventlog_level_error,__FUNCTION__,"could not close file \"%s\" after writing (fclose: %s)",filename,pstrerror(errno));
840 return -1;
841 }
842 return 0;
843 }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1